blob: c8410815f141964e8893c416b0ba31dfc203c676 [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
Wale Ogunwale65ebd952018-04-25 15:41:44 -070019import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED;
20import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
21import static android.app.ActivityTaskManager.INVALID_STACK_ID;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070022import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
23import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070024import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
25import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
26import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
27import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Wale Ogunwale44f036f2017-09-29 05:09:09 -070028import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Jorim Jaggi0a932142016-02-01 17:42:25 -080029import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Wale Ogunwale66e16852017-10-19 13:35:52 -070030import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Jorim Jaggi0a932142016-02-01 17:42:25 -080031import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
Wale Ogunwale66e16852017-10-19 13:35:52 -070032import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale3eadad72016-10-13 09:16:59 -070033import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
Jorim Jaggi0a932142016-02-01 17:42:25 -080034import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
35import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
36import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
37import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080038import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
39import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
40import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Wale Ogunwaled829d362016-02-10 19:24:49 -080041import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070042import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -080043import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070044import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080045import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
Suprabh Shukla7745c142016-03-07 18:21:10 -080046import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
Andrii Kulian036e3ad2017-04-19 10:55:10 -070047import static android.view.Display.DEFAULT_DISPLAY;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070048
Jorim Jaggi0a932142016-02-01 17:42:25 -080049import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
50import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
51import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
52import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
53import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
54import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
55import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
56import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
57import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
58import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwale3b232392016-05-13 15:37:13 -070059import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -080060import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
Wale Ogunwale56d8d162017-05-30 11:12:20 -070061import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
Wale Ogunwaleab5de372017-10-18 06:46:31 -070062import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
Winson Chung6954fc92017-03-24 16:22:12 -070063import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080064import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070065import static com.android.server.am.TaskRecordProto.ACTIVITIES;
66import static com.android.server.am.TaskRecordProto.BOUNDS;
67import static com.android.server.am.TaskRecordProto.CONFIGURATION_CONTAINER;
68import static com.android.server.am.TaskRecordProto.FULLSCREEN;
69import static com.android.server.am.TaskRecordProto.ID;
70import static com.android.server.am.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
71import static com.android.server.am.TaskRecordProto.MIN_HEIGHT;
72import static com.android.server.am.TaskRecordProto.MIN_WIDTH;
73import static com.android.server.am.TaskRecordProto.ORIG_ACTIVITY;
74import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
75import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
76import static com.android.server.am.TaskRecordProto.STACK_ID;
77import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070078
Winson Chung74666102017-02-22 17:49:24 -080079import static java.lang.Integer.MAX_VALUE;
80
Jorim Jaggie7d2b852017-08-28 17:55:15 +020081import android.annotation.IntDef;
82import android.annotation.Nullable;
83import android.app.Activity;
84import android.app.ActivityManager;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020085import android.app.ActivityManager.TaskDescription;
86import android.app.ActivityManager.TaskSnapshot;
87import android.app.ActivityOptions;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070088import android.app.ActivityTaskManager;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020089import android.app.AppGlobals;
90import android.app.IActivityManager;
91import android.content.ComponentName;
92import android.content.Intent;
93import android.content.pm.ActivityInfo;
94import android.content.pm.ApplicationInfo;
95import android.content.pm.IPackageManager;
96import android.content.pm.PackageManager;
97import android.content.res.Configuration;
98import android.graphics.Rect;
99import android.os.Debug;
100import android.os.RemoteException;
Winson Chungfb44d212017-10-04 11:39:10 -0700101import android.os.SystemClock;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200102import android.os.Trace;
103import android.os.UserHandle;
104import android.provider.Settings;
105import android.service.voice.IVoiceInteractionSession;
106import android.util.DisplayMetrics;
107import android.util.Slog;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700108import android.util.proto.ProtoOutputStream;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200109
110import com.android.internal.annotations.VisibleForTesting;
111import com.android.internal.app.IVoiceInteractor;
112import com.android.internal.util.XmlUtils;
Winson Chung61c9e5a2017-10-11 10:39:32 -0700113import com.android.server.am.ActivityStack.ActivityState;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200114import com.android.server.wm.AppWindowContainerController;
115import com.android.server.wm.ConfigurationContainer;
116import com.android.server.wm.StackWindowController;
117import com.android.server.wm.TaskWindowContainerController;
118import com.android.server.wm.TaskWindowContainerListener;
119import com.android.server.wm.WindowManagerService;
120
121import org.xmlpull.v1.XmlPullParser;
122import org.xmlpull.v1.XmlPullParserException;
123import org.xmlpull.v1.XmlSerializer;
124
125import java.io.IOException;
126import java.io.PrintWriter;
127import java.lang.annotation.Retention;
128import java.lang.annotation.RetentionPolicy;
129import java.util.ArrayList;
130import java.util.Objects;
131
Benjamin Franza83859f2017-07-03 16:34:14 +0100132class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800133 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700134 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700135 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
Craig Mautnere0570202015-05-13 13:06:11 -0700136 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700137 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800138
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700139 private static final String ATTR_TASKID = "task_id";
Craig Mautner21d24a22014-04-23 11:45:37 -0700140 private static final String TAG_INTENT = "intent";
141 private static final String TAG_AFFINITYINTENT = "affinity_intent";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700142 private static final String ATTR_REALACTIVITY = "real_activity";
143 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
Craig Mautner21d24a22014-04-23 11:45:37 -0700144 private static final String ATTR_ORIGACTIVITY = "orig_activity";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700145 private static final String TAG_ACTIVITY = "activity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700146 private static final String ATTR_AFFINITY = "affinity";
Dianne Hackborn79228822014-09-16 11:11:23 -0700147 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700148 private static final String ATTR_ROOTHASRESET = "root_has_reset";
Dianne Hackborn13420f22014-07-18 15:43:56 -0700149 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
Craig Mautner21d24a22014-04-23 11:45:37 -0700150 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
151 private static final String ATTR_USERID = "user_id";
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800152 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700153 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700154 @Deprecated
Craig Mautner21d24a22014-04-23 11:45:37 -0700155 private static final String ATTR_TASKTYPE = "task_type";
Craig Mautner21d24a22014-04-23 11:45:37 -0700156 private static final String ATTR_LASTDESCRIPTION = "last_description";
157 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700158 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700159 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
Craig Mautnera228ae92014-07-09 05:44:55 -0700160 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
161 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
Winson Chungec396d62014-08-06 17:08:00 -0700162 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700163 private static final String ATTR_CALLING_UID = "calling_uid";
164 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Winson Chungd3395382016-12-13 11:49:09 -0800165 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800166 private static final String ATTR_RESIZE_MODE = "resize_mode";
Wale Ogunwale706ed792015-08-02 10:29:44 -0700167 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700168 private static final String ATTR_MIN_WIDTH = "min_width";
169 private static final String ATTR_MIN_HEIGHT = "min_height";
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700170 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Andrii Kulian18d75122016-03-27 20:20:28 -0700171
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700172 // Current version of the task record we persist. Used to check if we need to run any upgrade
173 // code.
174 private static final int PERSIST_TASK_VERSION = 1;
Craig Mautner21d24a22014-04-23 11:45:37 -0700175
Wale Ogunwale18795a22014-12-03 11:38:33 -0800176 static final int INVALID_TASK_ID = -1;
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700177 private static final int INVALID_MIN_SIZE = -1;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800178
Winson Chung74666102017-02-22 17:49:24 -0800179 /**
180 * The modes to control how the stack is moved to the front when calling
181 * {@link TaskRecord#reparent}.
182 */
183 @Retention(RetentionPolicy.SOURCE)
184 @IntDef({
185 REPARENT_MOVE_STACK_TO_FRONT,
186 REPARENT_KEEP_STACK_AT_FRONT,
187 REPARENT_LEAVE_STACK_IN_PLACE
188 })
Wale Ogunwale66e16852017-10-19 13:35:52 -0700189 @interface ReparentMoveStackMode {}
Winson Chung74666102017-02-22 17:49:24 -0800190 // Moves the stack to the front if it was not at the front
Wale Ogunwale66e16852017-10-19 13:35:52 -0700191 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
Winson Chung74666102017-02-22 17:49:24 -0800192 // Only moves the stack to the front if it was focused or front most already
Wale Ogunwale66e16852017-10-19 13:35:52 -0700193 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
Winson Chung74666102017-02-22 17:49:24 -0800194 // Do not move the stack as a part of reparenting
Wale Ogunwale66e16852017-10-19 13:35:52 -0700195 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
Winson Chung74666102017-02-22 17:49:24 -0800196
Garfield Tan9b1efea2017-12-05 16:43:46 -0800197 /**
198 * The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}.
199 */
200 private static TaskRecordFactory sTaskRecordFactory;
201
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 final int taskId; // Unique identifier for this task.
Dianne Hackborn79228822014-09-16 11:11:23 -0700203 String affinity; // The affinity name for this task, or null; may change identity.
204 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Dianne Hackborn91097de2014-04-04 18:02:06 -0700205 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
206 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Bryce Lee1a990e52018-04-23 10:54:11 -0700207 Intent intent; // The original intent that started the task. Note that this value can
208 // be null.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700210 int effectiveUid; // The current effective uid of the identity of this task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 ComponentName origActivity; // The non-alias activity component of the intent.
212 ComponentName realActivity; // The actual activity component that started the task.
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +0000213 boolean realActivitySuspended; // True if the actual activity component that started the
214 // task is suspended.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700215 boolean inRecents; // Actually in the recents list?
Winson Chungfb44d212017-10-04 11:39:10 -0700216 long lastActiveTime; // Last time this task was active in the current device session,
217 // including sleep. This time is initialized to the elapsed time when
218 // restored from disk.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700219 boolean isAvailable; // Is the activity available to be launched?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 boolean rootWasReset; // True if the intent at the root of the task had
221 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700222 boolean autoRemoveRecents; // If true, we should automatically remove the task from
223 // recents when activity finishes
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700224 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700225 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 -0800226
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700227 String stringName; // caching of toString() result.
Dianne Hackborn9da2d402012-03-15 13:43:08 -0700228 int userId; // user for which this task was created
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800229 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
230 // was changed.
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800231
232 int numFullscreen; // Number of fullscreen activities.
233
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800234 int mResizeMode; // The resize mode of this task and its activities.
235 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800236 private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
237 // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
238 // of the root activity.
Craig Mautner15df08a2015-04-01 12:17:18 -0700239 /** Can't be put in lockTask mode. */
240 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
Benjamin Franz469dd582015-06-09 14:24:36 +0100241 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700242 final static int LOCK_TASK_AUTH_PINNABLE = 1;
243 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
244 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
Benjamin Franz469dd582015-06-09 14:24:36 +0100245 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700246 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
Benjamin Franz469dd582015-06-09 14:24:36 +0100247 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
248 * lockTask task. */
249 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
Craig Mautner15df08a2015-04-01 12:17:18 -0700250 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
251
252 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800253
Winson Chung03a9bae2014-05-02 09:56:12 -0700254 // This represents the last resolved activity values for this task
255 // NOTE: This value needs to be persisted with each task
Craig Mautner648f69b2014-09-18 14:16:26 -0700256 TaskDescription lastTaskDescription = new TaskDescription();
Winson Chung03a9bae2014-05-02 09:56:12 -0700257
Craig Mautnerd2328952013-03-05 12:46:26 -0800258 /** List of all activities in the task arranged in history order */
Craig Mautner21d24a22014-04-23 11:45:37 -0700259 final ArrayList<ActivityRecord> mActivities;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800260
Andrii Kulian02b7a832016-10-06 23:11:56 -0700261 /** Current stack. Setter must always be used to update the value. */
262 private ActivityStack mStack;
Craig Mautnerd2328952013-03-05 12:46:26 -0800263
Dianne Hackborn68a06332017-11-15 17:54:18 -0800264 /** The process that had previously hosted the root activity of this task.
265 * Used to know that we should try harder to keep this process around, in case the
266 * user wants to return to it. */
267 private ProcessRecord mRootProcess;
268
Craig Mautner21d24a22014-04-23 11:45:37 -0700269 /** Takes on same value as first root activity */
270 boolean isPersistable = false;
Craig Mautnerffcfcaa2014-06-05 09:54:38 -0700271 int maxRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700272
273 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
274 * determining the order when restoring. Sign indicates whether last task movement was to front
275 * (positive) or back (negative). Absolute value indicates time. */
276 long mLastTimeMoved = System.currentTimeMillis();
277
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 CharSequence lastDescription; // Last description captured for this item.
286
Craig Mautnera228ae92014-07-09 05:44:55 -0700287 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Winson Chungec396d62014-08-06 17:08:00 -0700288 int mAffiliatedTaskColor; // color of the parent task affiliation.
Craig Mautnera228ae92014-07-09 05:44:55 -0700289 TaskRecord mPrevAffiliate; // previous task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800290 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700291 TaskRecord mNextAffiliate; // next task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800292 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700293
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700294 // For relaunching the task from recents as though it was launched by the original launcher.
295 int mCallingUid;
296 String mCallingPackage;
297
Craig Mautner21d24a22014-04-23 11:45:37 -0700298 final ActivityManagerService mService;
299
Jorim Jaggi82c9dc92016-02-05 15:10:33 -0800300 private final Rect mTmpStableBounds = new Rect();
301 private final Rect mTmpNonDecorBounds = new Rect();
Wale Ogunwale9a08f822016-02-17 19:03:58 -0800302 private final Rect mTmpRect = new Rect();
Jorim Jaggi0a932142016-02-01 17:42:25 -0800303
Wale Ogunwale706ed792015-08-02 10:29:44 -0700304 // Last non-fullscreen bounds the task was launched in or resized to.
305 // The information is persisted and used to determine the appropriate stack to launch the
306 // task into on restore.
307 Rect mLastNonFullscreenBounds = null;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700308 // Minimal width and height of this task when it's resizeable. -1 means it should use the
309 // default minimal width/height.
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700310 int mMinWidth;
311 int mMinHeight;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700312
Chong Zhangfdcc4d42015-10-14 16:50:12 -0700313 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
314 // This number will be assigned when we evaluate OOM scores for all visible tasks.
315 int mLayerRank = -1;
316
Andrii Kulian1779e612016-10-12 21:58:25 -0700317 /** Helper object used for updating override configuration. */
318 private Configuration mTmpConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700319
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800320 private TaskWindowContainerController mWindowContainerController;
321
Garfield Tan9b1efea2017-12-05 16:43:46 -0800322 /**
323 * Don't use constructor directly. Use {@link #create(ActivityManagerService, int, ActivityInfo,
324 * Intent, TaskDescription)} instead.
325 */
Craig Mautner21d24a22014-04-23 11:45:37 -0700326 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700327 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700328 mService = service;
Suprabh Shukla23593142015-11-03 17:31:15 -0800329 userId = UserHandle.getUserId(info.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 taskId = _taskId;
Winson Chungfb44d212017-10-04 11:39:10 -0700331 lastActiveTime = SystemClock.elapsedRealtime();
Craig Mautnera228ae92014-07-09 05:44:55 -0700332 mAffiliatedTaskId = _taskId;
Dianne Hackborn91097de2014-04-04 18:02:06 -0700333 voiceSession = _voiceSession;
334 voiceInteractor = _voiceInteractor;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700335 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800336 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700337 mCallingUid = info.applicationInfo.uid;
338 mCallingPackage = info.packageName;
Martijn Coenend4a69702014-06-30 11:12:17 -0700339 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700340 setMinDimensions(info);
Winson730bf062016-03-31 18:04:56 -0700341 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700342 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Craig Mautner21d24a22014-04-23 11:45:37 -0700343 }
344
Garfield Tan9b1efea2017-12-05 16:43:46 -0800345 /**
346 * Don't use constructor directly. Use {@link #create(ActivityManagerService, int, ActivityInfo,
347 * Intent, IVoiceInteractionSession, IVoiceInteractor)} instead.
348 */
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700349 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200350 TaskDescription _taskDescription) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700351 mService = service;
Suprabh Shukla23593142015-11-03 17:31:15 -0800352 userId = UserHandle.getUserId(info.applicationInfo.uid);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700353 taskId = _taskId;
Winson Chungfb44d212017-10-04 11:39:10 -0700354 lastActiveTime = SystemClock.elapsedRealtime();
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700355 mAffiliatedTaskId = _taskId;
356 voiceSession = null;
357 voiceInteractor = null;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700358 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800359 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700360 mCallingUid = info.applicationInfo.uid;
361 mCallingPackage = info.packageName;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700362 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700363 setMinDimensions(info);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700364
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700365 isPersistable = true;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700366 // Clamp to [1, max].
367 maxRecents = Math.min(Math.max(info.maxRecents, 1),
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700368 ActivityTaskManager.getMaxAppRecentsLimitStatic());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700369
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700370 lastTaskDescription = _taskDescription;
Winson730bf062016-03-31 18:04:56 -0700371 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700372 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700373 }
374
Garfield Tan9b1efea2017-12-05 16:43:46 -0800375 /**
376 * Don't use constructor directly. This is only used by XML parser.
377 */
378 TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800379 Intent _affinityIntent, String _affinity, String _rootAffinity,
380 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700381 boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800382 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
Winson Chungfb44d212017-10-04 11:39:10 -0700383 long lastTimeMoved, boolean neverRelinquishIdentity,
384 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
385 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Charles He2bf28322017-10-12 22:24:49 +0100386 int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
387 boolean userSetupComplete, int minWidth, int minHeight) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700388 mService = service;
389 taskId = _taskId;
390 intent = _intent;
391 affinityIntent = _affinityIntent;
392 affinity = _affinity;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800393 rootAffinity = _rootAffinity;
Craig Mautner21d24a22014-04-23 11:45:37 -0700394 voiceSession = null;
395 voiceInteractor = null;
396 realActivity = _realActivity;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800397 realActivitySuspended = _realActivitySuspended;
Craig Mautner21d24a22014-04-23 11:45:37 -0700398 origActivity = _origActivity;
399 rootWasReset = _rootWasReset;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700400 isAvailable = true;
Dianne Hackborn13420f22014-07-18 15:43:56 -0700401 autoRemoveRecents = _autoRemoveRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700402 askedCompatMode = _askedCompatMode;
Craig Mautner21d24a22014-04-23 11:45:37 -0700403 userId = _userId;
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800404 mUserSetupComplete = userSetupComplete;
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700405 effectiveUid = _effectiveUid;
Winson Chungfb44d212017-10-04 11:39:10 -0700406 lastActiveTime = SystemClock.elapsedRealtime();
Craig Mautner21d24a22014-04-23 11:45:37 -0700407 lastDescription = _lastDescription;
408 mActivities = activities;
409 mLastTimeMoved = lastTimeMoved;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700410 mNeverRelinquishIdentity = neverRelinquishIdentity;
Winson Chung2cb86c72014-06-25 12:03:30 -0700411 lastTaskDescription = _lastTaskDescription;
Craig Mautnera228ae92014-07-09 05:44:55 -0700412 mAffiliatedTaskId = taskAffiliation;
Winson Chungec396d62014-08-06 17:08:00 -0700413 mAffiliatedTaskColor = taskAffiliationColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700414 mPrevAffiliateTaskId = prevTaskId;
415 mNextAffiliateTaskId = nextTaskId;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700416 mCallingUid = callingUid;
417 mCallingPackage = callingPackage;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800418 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800419 mSupportsPictureInPicture = supportsPictureInPicture;
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700420 mMinWidth = minWidth;
421 mMinHeight = minHeight;
Yorke Leebd54c2a2016-10-25 13:49:23 -0700422 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 }
424
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800425 TaskWindowContainerController getWindowContainerController() {
426 return mWindowContainerController;
427 }
428
429 void createWindowContainer(boolean onTop, boolean showForAllUsers) {
430 if (mWindowContainerController != null) {
431 throw new IllegalArgumentException("Window container=" + mWindowContainerController
432 + " already created for task=" + this);
433 }
434
435 final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
Bryce Lee04ab3462017-04-10 15:06:33 -0700436 setWindowContainerController(new TaskWindowContainerController(taskId, this,
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700437 getStack().getWindowContainerController(), userId, bounds,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700438 mResizeMode, mSupportsPictureInPicture, onTop,
439 showForAllUsers, lastTaskDescription));
Bryce Lee04ab3462017-04-10 15:06:33 -0700440 }
441
442 /**
443 * Should only be invoked from {@link #createWindowContainer(boolean, boolean)}.
444 */
445 @VisibleForTesting
446 protected void setWindowContainerController(TaskWindowContainerController controller) {
447 if (mWindowContainerController != null) {
448 throw new IllegalArgumentException("Window container=" + mWindowContainerController
449 + " already created for task=" + this);
450 }
451
452 mWindowContainerController = controller;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800453 }
454
455 void removeWindowContainer() {
Bryce Lee2b8e0372018-04-05 17:01:37 -0700456 mService.getLockTaskController().clearLockedTask(this);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800457 mWindowContainerController.removeContainer();
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700458 if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800459 // Reset current bounds for task whose bounds shouldn't be persisted so it uses
460 // default configuration the next time it launches.
461 updateOverrideConfiguration(null);
462 }
463 mService.mTaskChangeNotificationController.notifyTaskRemoved(taskId);
464 mWindowContainerController = null;
465 }
466
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100467 @Override
468 public void onSnapshotChanged(TaskSnapshot snapshot) {
469 mService.mTaskChangeNotificationController.notifyTaskSnapshotChanged(taskId, snapshot);
470 }
471
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800472 void setResizeMode(int resizeMode) {
473 if (mResizeMode == resizeMode) {
474 return;
475 }
476 mResizeMode = resizeMode;
477 mWindowContainerController.setResizeable(resizeMode);
478 mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
479 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
480 }
481
482 void setTaskDockedResizing(boolean resizing) {
483 mWindowContainerController.setTaskDockedResizing(resizing);
484 }
485
Wale Ogunwale1666e312016-12-16 11:27:18 -0800486 // TODO: Consolidate this with the resize() method below.
487 @Override
488 public void requestResize(Rect bounds, int resizeMode) {
489 mService.resizeTask(taskId, bounds, resizeMode);
490 }
491
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800492 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800493 mService.mWindowManager.deferSurfaceLayout();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800494
Bryce Leef3c6a472017-11-14 14:53:06 -0800495 try {
496 if (!isResizeable()) {
497 Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
498 return true;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800499 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800500
Bryce Leef3c6a472017-11-14 14:53:06 -0800501 // If this is a forced resize, let it go through even if the bounds is not changing,
502 // as we might need a relayout due to surface size change (to/from fullscreen).
503 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
504 if (equivalentOverrideBounds(bounds) && !forced) {
505 // Nothing to do here...
506 return true;
507 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800508
Bryce Leef3c6a472017-11-14 14:53:06 -0800509 if (mWindowContainerController == null) {
510 // Task doesn't exist in window manager yet (e.g. was restored from recents).
511 // All we can do for now is update the bounds so it can be used when the task is
512 // added to window manager.
513 updateOverrideConfiguration(bounds);
514 if (!inFreeformWindowingMode()) {
515 // re-restore the task so it can have the proper stack association.
516 mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
517 }
518 return true;
519 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800520
Bryce Leef3c6a472017-11-14 14:53:06 -0800521 if (!canResizeToBounds(bounds)) {
522 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
523 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
524 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800525
Bryce Leef3c6a472017-11-14 14:53:06 -0800526 // Do not move the task to another stack here.
527 // This method assumes that the task is already placed in the right stack.
528 // we do not mess with that decision and we only do the resize!
529
530 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId);
531
532 final boolean updatedConfig = updateOverrideConfiguration(bounds);
533 // This variable holds information whether the configuration didn't change in a significant
534
535 // way and the activity was kept the way it was. If it's false, it means the activity
536 // had
537 // to be relaunched due to configuration change.
538 boolean kept = true;
539 if (updatedConfig) {
540 final ActivityRecord r = topRunningActivityLocked();
541 if (r != null && !deferResume) {
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800542 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
Bryce Leef3c6a472017-11-14 14:53:06 -0800543 preserveWindow);
544 mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0,
545 !PRESERVE_WINDOWS);
546 if (!kept) {
547 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
548 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800549 }
550 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800551 mWindowContainerController.resize(kept, forced);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800552
Bryce Leef3c6a472017-11-14 14:53:06 -0800553 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
554 return kept;
555 } finally {
556 mService.mWindowManager.continueSurfaceLayout();
557 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800558 }
559
560 // TODO: Investigate combining with the resize() method above.
561 void resizeWindowContainer() {
Bryce Leef3c6a472017-11-14 14:53:06 -0800562 mWindowContainerController.resize(false /* relayout */, false /* forced */);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800563 }
564
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800565 void getWindowContainerBounds(Rect bounds) {
566 mWindowContainerController.getBounds(bounds);
567 }
568
Winson Chung74666102017-02-22 17:49:24 -0800569 /**
570 * Convenience method to reparent a task to the top or bottom position of the stack.
571 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700572 boolean reparent(ActivityStack preferredStack, boolean toTop,
573 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
574 String reason) {
575 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
576 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung5af42fc2017-03-24 17:11:33 -0700577 }
578
579 /**
580 * Convenience method to reparent a task to the top or bottom position of the stack, with
581 * an option to skip scheduling the picture-in-picture mode change.
582 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700583 boolean reparent(ActivityStack preferredStack, boolean toTop,
584 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
585 boolean schedulePictureInPictureModeChange, String reason) {
586 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
Winson Chung5af42fc2017-03-24 17:11:33 -0700587 deferResume, schedulePictureInPictureModeChange, reason);
588 }
589
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700590 /** Convenience method to reparent a task to a specific position of the stack. */
591 boolean reparent(ActivityStack preferredStack, int position,
592 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
593 String reason) {
594 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
Winson Chung5af42fc2017-03-24 17:11:33 -0700595 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800596 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800597
Winson Chung74666102017-02-22 17:49:24 -0800598 /**
599 * Reparents the task into a preferred stack, creating it if necessary.
600 *
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700601 * @param preferredStack the target stack to move this task
Winson Chung74666102017-02-22 17:49:24 -0800602 * @param position the position to place this task in the new stack
603 * @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 -0700604 * reparenting to be drawn and animated in
Winson Chung74666102017-02-22 17:49:24 -0800605 * @param moveStackMode whether or not to move the stack to the front always, only if it was
Winson Chung5af42fc2017-03-24 17:11:33 -0700606 * previously focused & in front, or never
Winson Chung74666102017-02-22 17:49:24 -0800607 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
Winson Chung5af42fc2017-03-24 17:11:33 -0700608 * have changed as a result of this reparenting
609 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
610 * change. Callers may set this to false if they are explicitly scheduling PiP mode
611 * changes themselves, like during the PiP animation
Winson Chung74666102017-02-22 17:49:24 -0800612 * @param reason the caller of this reparenting
Winson Chung5af42fc2017-03-24 17:11:33 -0700613 * @return whether the task was reparented
Winson Chung74666102017-02-22 17:49:24 -0800614 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700615 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700616 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700617 boolean reparent(ActivityStack preferredStack, int position,
618 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
619 boolean schedulePictureInPictureModeChange, String reason) {
Winson Chung74666102017-02-22 17:49:24 -0800620 final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
621 final WindowManagerService windowManager = mService.mWindowManager;
622 final ActivityStack sourceStack = getStack();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700623 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
Winson Chung74666102017-02-22 17:49:24 -0800624 position == MAX_VALUE);
625 if (toStack == sourceStack) {
626 return false;
627 }
Andrii Kulianb850ea52017-12-12 23:49:10 -0800628 if (!canBeLaunchedOnDisplay(toStack.mDisplayId)) {
629 return false;
630 }
Winson Chung74666102017-02-22 17:49:24 -0800631
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700632 final int toStackWindowingMode = toStack.getWindowingMode();
Winson Chung74666102017-02-22 17:49:24 -0800633 final ActivityRecord topActivity = getTopActivity();
634
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800635 final boolean mightReplaceWindow = topActivity != null
636 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
Winson Chung74666102017-02-22 17:49:24 -0800637 if (mightReplaceWindow) {
638 // We are about to relaunch the activity because its configuration changed due to
639 // being maximized, i.e. size change. The activity will first remove the old window
640 // and then add a new one. This call will tell window manager about this, so it can
641 // preserve the old window until the new one is drawn. This prevents having a gap
642 // between the removal and addition, in which no window is visible. We also want the
643 // entrance of the new window to be properly animated.
644 // Note here we always set the replacing window first, as the flags might be needed
645 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
646 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
647 }
648
649 windowManager.deferSurfaceLayout();
650 boolean kept = true;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800651 try {
Winson Chung74666102017-02-22 17:49:24 -0800652 final ActivityRecord r = topRunningActivityLocked();
Winson Chung95f8f0e2017-03-24 09:20:17 -0700653 final boolean wasFocused = r != null && supervisor.isFocusedStack(sourceStack)
Winson Chung74666102017-02-22 17:49:24 -0800654 && (topRunningActivityLocked() == r);
Bryce Leec4ab62a2018-03-05 14:19:26 -0800655 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
Winson Chung95f8f0e2017-03-24 09:20:17 -0700656 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
Winson Chung74666102017-02-22 17:49:24 -0800657
658 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
659 // Whenever we are moving the top activity from the front stack we want to make sure to
660 // move the stack to the front.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700661 final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
Winson Chung74666102017-02-22 17:49:24 -0800662 && (sourceStack.topRunningActivityLocked() == r);
663
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800664 // Adjust the position for the new parent stack as needed.
Winson Chung74666102017-02-22 17:49:24 -0800665 position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800666
667 // Must reparent first in window manager to avoid a situation where AM can delete the
668 // we are coming from in WM before we reparent because it became empty.
Wale Ogunwale2719cc12017-04-14 09:45:27 -0700669 mWindowContainerController.reparent(toStack.getWindowContainerController(), position,
670 moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800671
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700672 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
673 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
Winson Chung74666102017-02-22 17:49:24 -0800674 // Move the task
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700675 sourceStack.removeTask(this, reason, moveStackToFront
676 ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
Winson Chung5af42fc2017-03-24 17:11:33 -0700677 toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800678
Winson Chung5af42fc2017-03-24 17:11:33 -0700679 if (schedulePictureInPictureModeChange) {
680 // Notify of picture-in-picture mode changes
681 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
682 }
Winson Chung74666102017-02-22 17:49:24 -0800683
684 // TODO: Ensure that this is actually necessary here
685 // Notify the voice session if required
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800686 if (voiceSession != null) {
687 try {
688 voiceSession.taskStarted(intent, taskId);
689 } catch (RemoteException e) {
690 }
691 }
Winson Chung74666102017-02-22 17:49:24 -0800692
693 // If the task had focus before (or we're requested to move focus), move focus to the
694 // new stack by moving the stack to the front.
Winson Chung95f8f0e2017-03-24 09:20:17 -0700695 if (r != null) {
696 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
697 wasPaused, reason);
698 }
Winson Chung74666102017-02-22 17:49:24 -0800699 if (!animate) {
Jorim Jaggifa9ed962018-01-25 00:16:49 +0100700 mService.mStackSupervisor.mNoAnimActivities.add(topActivity);
Winson Chung74666102017-02-22 17:49:24 -0800701 }
702
703 // We might trigger a configuration change. Save the current task bounds for freezing.
704 // TODO: Should this call be moved inside the resize method in WM?
705 toStack.prepareFreezingTaskBounds();
706
707 // Make sure the task has the appropriate bounds/size for the stack it is in.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700708 final boolean toStackSplitScreenPrimary =
709 toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Bryce Leef3c6a472017-11-14 14:53:06 -0800710 final Rect configBounds = getOverrideBounds();
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700711 if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
712 || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
Bryce Leef3c6a472017-11-14 14:53:06 -0800713 && !Objects.equals(configBounds, toStack.getOverrideBounds())) {
714 kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
Winson Chung74666102017-02-22 17:49:24 -0800715 deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700716 } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Winson Chung74666102017-02-22 17:49:24 -0800717 Rect bounds = getLaunchBounds();
718 if (bounds == null) {
Bryce Leeec55eb02017-12-05 20:51:27 -0800719 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Bryce Leef3c6a472017-11-14 14:53:06 -0800720 bounds = configBounds;
Winson Chung74666102017-02-22 17:49:24 -0800721 }
722 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700723 } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
724 if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
Matthew Ng330757d2017-02-28 14:19:17 -0800725 // Move recents to front so it is not behind home stack when going into docked
726 // mode
727 mService.mStackSupervisor.moveRecentsStackToFront(reason);
728 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800729 kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
Winson Chung74666102017-02-22 17:49:24 -0800730 deferResume);
731 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800732 } finally {
Winson Chung74666102017-02-22 17:49:24 -0800733 windowManager.continueSurfaceLayout();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800734 }
Winson Chung74666102017-02-22 17:49:24 -0800735
736 if (mightReplaceWindow) {
737 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
738 // window), we need to clear the replace window settings. Otherwise, we schedule a
739 // timeout to remove the old window if the replacing window is not coming in time.
740 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
741 }
742
743 if (!deferResume) {
744 // The task might have already been running and its visibility needs to be synchronized
745 // with the visibility of the stack / windows.
746 supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
747 supervisor.resumeFocusedStackTopActivityLocked();
748 }
749
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700750 // TODO: Handle incorrect request to move before the actual move, not after.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700751 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700752 DEFAULT_DISPLAY, toStack);
Winson Chung74666102017-02-22 17:49:24 -0800753
Winson Chungdff7a732017-12-11 12:17:06 -0800754 return (preferredStack == toStack);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800755 }
756
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700757 /**
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800758 * @return True if the windows of tasks being moved to the target stack from the source stack
759 * should be replaced, meaning that window manager will keep the old window around until the new
760 * is ready.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700761 */
762 private static boolean replaceWindowsOnTaskMove(
763 int sourceWindowingMode, int targetWindowingMode) {
764 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
765 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
766 }
767
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800768 void cancelWindowTransition() {
769 mWindowContainerController.cancelWindowTransition();
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 Chungfb44d212017-10-04 11:39:10 -0700783 lastActiveTime = SystemClock.elapsedRealtime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700785
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 long getInactiveDuration() {
Winson Chungfb44d212017-10-04 11:39:10 -0700787 return SystemClock.elapsedRealtime() - lastActiveTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800788 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700789
Winson Chungfee26772014-08-05 12:21:52 -0700790 /** Sets the original intent, and the calling uid and package. */
791 void setIntent(ActivityRecord r) {
Winson Chungfee26772014-08-05 12:21:52 -0700792 mCallingUid = r.launchedFromUid;
793 mCallingPackage = r.launchedFromPackage;
Craig Mautner15df08a2015-04-01 12:17:18 -0700794 setIntent(r.intent, r.info);
Charles He2bf28322017-10-12 22:24:49 +0100795 setLockTaskAuth(r);
Winson Chungfee26772014-08-05 12:21:52 -0700796 }
797
798 /** Sets the original intent, _without_ updating the calling uid or package. */
799 private void setIntent(Intent _intent, ActivityInfo info) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700800 if (intent == null) {
801 mNeverRelinquishIdentity =
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700802 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700803 } else if (mNeverRelinquishIdentity) {
804 return;
805 }
806
807 affinity = info.taskAffinity;
Dianne Hackborn79228822014-09-16 11:11:23 -0700808 if (intent == null) {
809 // If this task already has an intent associated with it, don't set the root
810 // affinity -- we don't want it changing after initially set, but the initially
811 // set value may be null.
812 rootAffinity = affinity;
813 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700814 effectiveUid = info.applicationInfo.uid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700815 stringName = null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800816
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800817 if (info.targetActivity == null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800818 if (_intent != null) {
819 // If this Intent has a selector, we want to clear it for the
820 // recent task since it is not relevant if the user later wants
821 // to re-launch the app.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700822 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800823 _intent = new Intent(_intent);
824 _intent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700825 _intent.setSourceBounds(null);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800826 }
827 }
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700828 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800829 intent = _intent;
830 realActivity = _intent != null ? _intent.getComponent() : null;
831 origActivity = null;
832 } else {
833 ComponentName targetComponent = new ComponentName(
834 info.packageName, info.targetActivity);
835 if (_intent != null) {
836 Intent targetIntent = new Intent(_intent);
837 targetIntent.setComponent(targetComponent);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800838 targetIntent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700839 targetIntent.setSourceBounds(null);
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700840 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
Dianne Hackborn7f96b792012-05-29 18:46:45 -0700841 "Setting Intent of " + this + " to target " + targetIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800842 intent = targetIntent;
843 realActivity = targetComponent;
844 origActivity = _intent.getComponent();
845 } else {
846 intent = null;
847 realActivity = targetComponent;
848 origActivity = new ComponentName(info.packageName, info.name);
849 }
850 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700851
Craig Mautner47b20ba2014-09-17 17:23:44 -0700852 final int intentFlags = intent == null ? 0 : intent.getFlags();
853 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 // Once we are set to an Intent with this flag, we count this
855 // task as having a true root activity.
856 rootWasReset = true;
857 }
Dianne Hackborn09233282014-04-30 11:33:59 -0700858 userId = UserHandle.getUserId(info.applicationInfo.uid);
Winson Chung36f3f032016-09-08 23:29:43 +0000859 mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
860 USER_SETUP_COMPLETE, 0, userId) != 0;
Craig Mautner41db4a72014-05-07 17:20:56 -0700861 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700862 // If the activity itself has requested auto-remove, then just always do it.
863 autoRemoveRecents = true;
Wale Ogunwale843bfb92015-03-27 11:06:48 -0700864 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
865 == FLAG_ACTIVITY_NEW_DOCUMENT) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700866 // If the caller has not asked for the document to be retained, then we may
867 // want to turn on auto-remove, depending on whether the target has set its
868 // own document launch mode.
869 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
870 autoRemoveRecents = false;
871 } else {
872 autoRemoveRecents = true;
873 }
874 } else {
875 autoRemoveRecents = false;
Craig Mautner41db4a72014-05-07 17:20:56 -0700876 }
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800877 mResizeMode = info.resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800878 mSupportsPictureInPicture = info.supportsPictureInPicture();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800879 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800880
Andrii Kulian2e751b82016-03-16 16:59:32 -0700881 /** Sets the original minimal width and height. */
882 private void setMinDimensions(ActivityInfo info) {
883 if (info != null && info.windowLayout != null) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700884 mMinWidth = info.windowLayout.minWidth;
885 mMinHeight = info.windowLayout.minHeight;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700886 } else {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700887 mMinWidth = INVALID_MIN_SIZE;
888 mMinHeight = INVALID_MIN_SIZE;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700889 }
890 }
891
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800892 /**
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700893 * Return true if the input activity has the same intent filter as the intent this task
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800894 * record is based on (normally the root activity intent).
895 */
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700896 boolean isSameIntentFilter(ActivityRecord r) {
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800897 final Intent intent = new Intent(r.intent);
898 // Correct the activity intent for aliasing. The task record intent will always be based on
899 // the real activity that will be launched not the alias, so we need to use an intent with
900 // the component name pointing to the real activity not the alias in the activity record.
901 intent.setComponent(r.realActivity);
Bryce Lee1a990e52018-04-23 10:54:11 -0700902 return intent.filterEquals(this.intent);
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800903 }
904
Wale Ogunwale66e16852017-10-19 13:35:52 -0700905 boolean returnsToHomeStack() {
906 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
Bryce Lee1a990e52018-04-23 10:54:11 -0700907 return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700908 }
909
Craig Mautnera228ae92014-07-09 05:44:55 -0700910 void setPrevAffiliate(TaskRecord prevAffiliate) {
911 mPrevAffiliate = prevAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800912 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700913 }
914
915 void setNextAffiliate(TaskRecord nextAffiliate) {
916 mNextAffiliate = nextAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800917 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700918 }
919
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700920 <T extends ActivityStack> T getStack() {
921 return (T) mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700922 }
923
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800924 /**
925 * Must be used for setting parent stack because it performs configuration updates.
926 * Must be called after adding task as a child to the stack.
927 */
Andrii Kulian02b7a832016-10-06 23:11:56 -0700928 void setStack(ActivityStack stack) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800929 if (stack != null && !stack.isInStackLocked(this)) {
930 throw new IllegalStateException("Task must be added as a Stack child first.");
931 }
Bryce Lee84730a02018-04-03 14:10:04 -0700932 final ActivityStack oldStack = mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700933 mStack = stack;
Bryce Lee84730a02018-04-03 14:10:04 -0700934
935 // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
936 // {@link ActivityRecord} from its current {@link ActivityStack}.
937
938 if (oldStack != mStack) {
939 for (int i = getChildCount() - 1; i >= 0; --i) {
940 final ActivityRecord activity = getChildAt(i);
941
942 if (oldStack != null) {
943 oldStack.onActivityRemovedFromStack(activity);
944 }
945
946 if (mStack != null) {
947 stack.onActivityAddedToStack(activity);
948 }
949 }
950 }
951
Andrii Kulian1779e612016-10-12 21:58:25 -0700952 onParentChanged();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700953 }
954
955 /**
956 * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
957 */
958 int getStackId() {
959 return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
960 }
961
Andrii Kulian1779e612016-10-12 21:58:25 -0700962 @Override
963 protected int getChildCount() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700964 return mActivities.size();
Andrii Kulian1779e612016-10-12 21:58:25 -0700965 }
966
967 @Override
chaviw82a0ba82018-03-15 14:26:29 -0700968 protected ActivityRecord getChildAt(int index) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700969 return mActivities.get(index);
Andrii Kulian1779e612016-10-12 21:58:25 -0700970 }
971
972 @Override
973 protected ConfigurationContainer getParent() {
974 return mStack;
975 }
976
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800977 @Override
Wale Ogunwale98d62312017-07-12 09:24:56 -0700978 protected void onParentChanged() {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800979 super.onParentChanged();
980 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
981 }
982
Craig Mautnera228ae92014-07-09 05:44:55 -0700983 // Close up recents linked list.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700984 private void closeRecentsChain() {
Craig Mautnera228ae92014-07-09 05:44:55 -0700985 if (mPrevAffiliate != null) {
986 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
987 }
988 if (mNextAffiliate != null) {
989 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
990 }
991 setPrevAffiliate(null);
992 setNextAffiliate(null);
993 }
994
Winson Chung740c3ac2014-11-12 16:14:38 -0800995 void removedFromRecents() {
Dianne Hackborn852975d2014-08-22 17:42:43 -0700996 closeRecentsChain();
997 if (inRecents) {
998 inRecents = false;
Winson Chung740c3ac2014-11-12 16:14:38 -0800999 mService.notifyTaskPersisterLocked(this, false);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001000 }
Jorim Jaggif9084ec2017-01-16 13:16:59 +01001001
Dianne Hackborn68a06332017-11-15 17:54:18 -08001002 clearRootProcess();
1003
Jorim Jaggif9084ec2017-01-16 13:16:59 +01001004 // TODO: Use window container controller once tasks are better synced between AM and WM
1005 mService.mWindowManager.notifyTaskRemovedFromRecents(taskId, userId);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001006 }
1007
Craig Mautnera228ae92014-07-09 05:44:55 -07001008 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
1009 closeRecentsChain();
1010 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
Winson Chungec396d62014-08-06 17:08:00 -07001011 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
Craig Mautnera228ae92014-07-09 05:44:55 -07001012 // Find the end
1013 while (taskToAffiliateWith.mNextAffiliate != null) {
1014 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate;
1015 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1016 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1017 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1018 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1019 nextRecents.setPrevAffiliate(null);
1020 }
1021 taskToAffiliateWith.setNextAffiliate(null);
1022 break;
1023 }
1024 taskToAffiliateWith = nextRecents;
1025 }
1026 taskToAffiliateWith.setNextAffiliate(this);
1027 setPrevAffiliate(taskToAffiliateWith);
1028 setNextAffiliate(null);
1029 }
1030
Winson Chung1147c402014-05-14 11:05:00 -07001031 /** Returns the intent for the root activity for this task */
1032 Intent getBaseIntent() {
1033 return intent != null ? intent : affinityIntent;
1034 }
1035
Winson Chung3b3f4642014-04-22 10:08:18 -07001036 /** Returns the first non-finishing activity from the root. */
1037 ActivityRecord getRootActivity() {
1038 for (int i = 0; i < mActivities.size(); i++) {
1039 final ActivityRecord r = mActivities.get(i);
1040 if (r.finishing) {
1041 continue;
1042 }
1043 return r;
1044 }
1045 return null;
1046 }
1047
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001048 ActivityRecord getTopActivity() {
Bryce Lee9f6affd2017-09-01 09:18:35 -07001049 return getTopActivity(true /* includeOverlays */);
1050 }
1051
1052 ActivityRecord getTopActivity(boolean includeOverlays) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001053 for (int i = mActivities.size() - 1; i >= 0; --i) {
1054 final ActivityRecord r = mActivities.get(i);
Bryce Lee9f6affd2017-09-01 09:18:35 -07001055 if (r.finishing || (!includeOverlays && r.mTaskOverlay)) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001056 continue;
1057 }
1058 return r;
1059 }
1060 return null;
1061 }
1062
Filip Gruszczynski3e85ba22015-10-05 22:48:30 -07001063 ActivityRecord topRunningActivityLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001064 if (mStack != null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001065 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1066 ActivityRecord r = mActivities.get(activityNdx);
Chong Zhang87761972016-08-22 13:53:24 -07001067 if (!r.finishing && r.okToShowLocked()) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001068 return r;
1069 }
Craig Mautner6b74cb52013-09-27 17:02:21 -07001070 }
1071 }
1072 return null;
1073 }
1074
Jorim Jaggi172e99f2017-10-20 14:33:18 +02001075 boolean isVisible() {
1076 for (int i = mActivities.size() - 1; i >= 0; --i) {
1077 final ActivityRecord r = mActivities.get(i);
1078 if (r.visible) {
1079 return true;
1080 }
1081 }
1082 return false;
1083 }
1084
Jorim Jaggiea039a82017-08-02 14:37:49 +02001085 void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
1086 if (mStack != null) {
1087 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1088 ActivityRecord r = mActivities.get(activityNdx);
Jorim Jaggi02f1d2f2017-08-04 14:29:16 +02001089 if (!r.finishing && r.okToShowLocked() && r.visibleIgnoringKeyguard) {
Jorim Jaggiea039a82017-08-02 14:37:49 +02001090 outActivities.add(r);
1091 }
1092 }
1093 }
1094 }
1095
Wale Ogunwale3b232392016-05-13 15:37:13 -07001096 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001097 if (mStack != null) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001098 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1099 ActivityRecord r = mActivities.get(activityNdx);
1100 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
Chong Zhang87761972016-08-22 13:53:24 -07001101 || r.finishing || !r.okToShowLocked()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001102 continue;
1103 }
1104 return r;
1105 }
1106 }
1107 return null;
1108 }
1109
Winson Chung61c9e5a2017-10-11 10:39:32 -07001110 /**
1111 * Return the number of running activities, and the number of non-finishing/initializing
1112 * activities in the provided {@param reportOut} respectively.
1113 */
1114 void getNumRunningActivities(TaskActivitiesReport reportOut) {
1115 reportOut.reset();
1116 for (int i = mActivities.size() - 1; i >= 0; --i) {
1117 final ActivityRecord r = mActivities.get(i);
1118 if (r.finishing) {
1119 continue;
1120 }
1121
1122 reportOut.base = r;
1123
1124 // Increment the total number of non-finishing activities
1125 reportOut.numActivities++;
1126
Bryce Lee7ace3952018-02-16 14:34:32 -08001127 if (reportOut.top == null || (reportOut.top.isState(ActivityState.INITIALIZING))) {
Winson Chung61c9e5a2017-10-11 10:39:32 -07001128 reportOut.top = r;
1129 // Reset the number of running activities until we hit the first non-initializing
1130 // activity
1131 reportOut.numRunning = 0;
1132 }
1133 if (r.app != null && r.app.thread != null) {
1134 // Increment the number of actually running activities
1135 reportOut.numRunning++;
1136 }
1137 }
1138 }
1139
Chong Zhang87761972016-08-22 13:53:24 -07001140 boolean okToShowLocked() {
1141 // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
1142 // okay to show the activity when locked.
1143 return mService.mStackSupervisor.isCurrentProfileLocked(userId)
1144 || topRunningActivityLocked() != null;
1145 }
1146
Craig Mautner3b475fe2013-12-16 15:58:31 -08001147 /** Call after activity movement or finish to make sure that frontOfTask is set correctly */
Bryce Leed71317c2017-02-07 14:27:22 -08001148 final void setFrontOfTask() {
1149 boolean foundFront = false;
Craig Mautner3b475fe2013-12-16 15:58:31 -08001150 final int numActivities = mActivities.size();
Craig Mautner704e40b2013-12-18 16:43:51 -08001151 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
Craig Mautner3b475fe2013-12-16 15:58:31 -08001152 final ActivityRecord r = mActivities.get(activityNdx);
1153 if (foundFront || r.finishing) {
1154 r.frontOfTask = false;
1155 } else {
1156 r.frontOfTask = true;
1157 // Set frontOfTask false for every following activity.
1158 foundFront = true;
1159 }
1160 }
Craig Mautner9587ee02014-06-23 15:00:10 +00001161 if (!foundFront && numActivities > 0) {
1162 // All activities of this task are finishing. As we ought to have a frontOfTask
1163 // activity, make the bottom activity front.
1164 mActivities.get(0).frontOfTask = true;
1165 }
Craig Mautner3b475fe2013-12-16 15:58:31 -08001166 }
1167
Craig Mautnerde4ef022013-04-07 19:01:33 -07001168 /**
Craig Mautner3b475fe2013-12-16 15:58:31 -08001169 * Reorder the history stack so that the passed activity is brought to the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001170 */
1171 final void moveActivityToFrontLocked(ActivityRecord newTop) {
Wale Ogunwale0fc365c2015-05-25 19:35:42 -07001172 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
1173 "Removing and adding activity " + newTop
1174 + " to stack at top callers=" + Debug.getCallers(4));
Craig Mautnerde4ef022013-04-07 19:01:33 -07001175
Craig Mautnerde4ef022013-04-07 19:01:33 -07001176 mActivities.remove(newTop);
1177 mActivities.add(newTop);
Bryce Leed58d7b32017-09-08 15:55:22 -07001178
1179 // Make sure window manager is aware of the position change.
1180 mWindowContainerController.positionChildAtTop(newTop.mWindowContainerController);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001181 updateEffectiveIntent();
Craig Mautner3b475fe2013-12-16 15:58:31 -08001182
Bryce Leed71317c2017-02-07 14:27:22 -08001183 setFrontOfTask();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001184 }
1185
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001186 void addActivityAtBottom(ActivityRecord r) {
Craig Mautner77878772013-03-04 19:46:24 -08001187 addActivityAtIndex(0, r);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001188 }
1189
1190 void addActivityToTop(ActivityRecord r) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001191 addActivityAtIndex(mActivities.size(), r);
1192 }
1193
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001194 @Override
Wale Ogunwaleeea34ee92017-08-31 20:07:45 -07001195 /*@WindowConfiguration.ActivityType*/
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001196 public int getActivityType() {
1197 final int applicationType = super.getActivityType();
1198 if (applicationType != ACTIVITY_TYPE_UNDEFINED || mActivities.isEmpty()) {
1199 return applicationType;
1200 }
1201 return mActivities.get(0).getActivityType();
1202 }
1203
Winson Chung30480042017-01-26 10:55:34 -08001204 /**
1205 * Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
1206 * be in the current task or unparented to any task.
1207 */
Craig Mautner1602ec22013-05-12 10:24:27 -07001208 void addActivityAtIndex(int index, ActivityRecord r) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001209 TaskRecord task = r.getTask();
1210 if (task != null && task != this) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001211 throw new IllegalArgumentException("Can not add r=" + " to task=" + this
Bryce Leeaf691c02017-03-20 14:20:22 -07001212 + " current parent=" + task);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001213 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001214
1215 r.setTask(this);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001216
Craig Mautner6170f732013-04-02 13:05:23 -07001217 // 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 -08001218 if (!mActivities.remove(r) && r.fullscreen) {
1219 // Was not previously in list.
1220 numFullscreen++;
1221 }
Craig Mautner2c1faed2013-07-23 12:56:02 -07001222 // Only set this based on the first activity
1223 if (mActivities.isEmpty()) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001224 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1225 // Normally non-standard activity type for the activity record will be set when the
1226 // object is created, however we delay setting the standard application type until
1227 // this point so that the task can set the type for additional activities added in
1228 // the else condition below.
1229 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1230 }
1231 setActivityType(r.getActivityType());
Craig Mautner21d24a22014-04-23 11:45:37 -07001232 isPersistable = r.isPersistable();
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001233 mCallingUid = r.launchedFromUid;
1234 mCallingPackage = r.launchedFromPackage;
Dianne Hackborn852975d2014-08-22 17:42:43 -07001235 // Clamp to [1, max].
1236 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
Wale Ogunwale65ebd952018-04-25 15:41:44 -07001237 ActivityTaskManager.getMaxAppRecentsLimitStatic());
Craig Mautner2c1faed2013-07-23 12:56:02 -07001238 } else {
1239 // Otherwise make all added activities match this one.
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001240 r.setActivityType(getActivityType());
Craig Mautner78733002013-06-10 13:54:49 -07001241 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001242
1243 final int size = mActivities.size();
1244
1245 if (index == size && size > 0) {
1246 final ActivityRecord top = mActivities.get(size - 1);
1247 if (top.mTaskOverlay) {
1248 // Place below the task overlay activity since the overlay activity should always
1249 // be on top.
1250 index--;
1251 }
1252 }
1253
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001254 index = Math.min(size, index);
Craig Mautner77878772013-03-04 19:46:24 -08001255 mActivities.add(index, r);
Bryce Lee84730a02018-04-03 14:10:04 -07001256
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001257 updateEffectiveIntent();
Craig Mautner21d24a22014-04-23 11:45:37 -07001258 if (r.isPersistable()) {
1259 mService.notifyTaskPersisterLocked(this, false);
1260 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001261
1262 // Sync. with window manager
1263 updateOverrideConfigurationFromLaunchBounds();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001264 final AppWindowContainerController appController = r.getWindowContainerController();
1265 if (appController != null) {
1266 // Only attempt to move in WM if the child has a controller. It is possible we haven't
1267 // created controller for the activity we are starting yet.
1268 mWindowContainerController.positionChildAt(appController, index);
1269 }
David Stevens82ea6cb2017-03-03 16:18:50 -08001270
1271 // Make sure the list of display UID whitelists is updated
1272 // now that this record is in a new task.
1273 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
Craig Mautner77878772013-03-04 19:46:24 -08001274 }
1275
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001276 /**
Bryce Leeaf691c02017-03-20 14:20:22 -07001277 * Removes the specified activity from this task.
1278 * @param r The {@link ActivityRecord} to remove.
1279 * @return true if this was the last activity in the task.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001280 */
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001281 boolean removeActivity(ActivityRecord r) {
Bryce Lee84730a02018-04-03 14:10:04 -07001282 return removeActivity(r, false /* reparenting */);
Bryce Leeaf691c02017-03-20 14:20:22 -07001283 }
1284
1285 boolean removeActivity(ActivityRecord r, boolean reparenting) {
1286 if (r.getTask() != this) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001287 throw new IllegalArgumentException(
1288 "Activity=" + r + " does not belong to task=" + this);
1289 }
1290
Bryce Lee84730a02018-04-03 14:10:04 -07001291 r.setTask(null /* task */, reparenting /* reparenting */);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001292
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001293 if (mActivities.remove(r) && r.fullscreen) {
1294 // Was previously in list.
1295 numFullscreen--;
1296 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001297 if (r.isPersistable()) {
1298 mService.notifyTaskPersisterLocked(this, false);
1299 }
Wale Ogunwale89182d52016-03-11 10:38:36 -08001300
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001301 if (inPinnedWindowingMode()) {
Wale Ogunwale89182d52016-03-11 10:38:36 -08001302 // We normally notify listeners of task stack changes on pause, however pinned stack
1303 // activities are normally in the paused state so no notification will be sent there
1304 // before the activity is removed. We send it here so instead.
Yorke Leebd54c2a2016-10-25 13:49:23 -07001305 mService.mTaskChangeNotificationController.notifyTaskStackChanged();
Wale Ogunwale89182d52016-03-11 10:38:36 -08001306 }
1307
Craig Mautner41326202014-06-20 14:38:21 -07001308 if (mActivities.isEmpty()) {
Craig Mautner5afcd4d2014-06-21 18:11:33 -07001309 return !mReuseTask;
Craig Mautner41326202014-06-20 14:38:21 -07001310 }
1311 updateEffectiveIntent();
1312 return false;
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001313 }
1314
Winson Chung6954fc92017-03-24 16:22:12 -07001315 /**
1316 * @return whether or not there are ONLY task overlay activities in the stack.
1317 * If {@param excludeFinishing} is set, then ignore finishing activities in the check.
1318 * If there are no task overlay activities, this call returns false.
1319 */
1320 boolean onlyHasTaskOverlayActivities(boolean excludeFinishing) {
1321 int count = 0;
1322 for (int i = mActivities.size() - 1; i >= 0; i--) {
1323 final ActivityRecord r = mActivities.get(i);
1324 if (excludeFinishing && r.finishing) {
1325 continue;
1326 }
1327 if (!r.mTaskOverlay) {
1328 return false;
1329 }
1330 count++;
1331 }
1332 return count > 0;
1333 }
1334
Craig Mautner41db4a72014-05-07 17:20:56 -07001335 boolean autoRemoveFromRecents() {
Dianne Hackbornd38aed82014-06-10 21:36:35 -07001336 // We will automatically remove the task either if it has explicitly asked for
1337 // this, or it is empty and has never contained an activity that got shown to
1338 // the user.
Dianne Hackborn13420f22014-07-18 15:43:56 -07001339 return autoRemoveRecents || (mActivities.isEmpty() && !hasBeenVisible);
Craig Mautner41db4a72014-05-07 17:20:56 -07001340 }
1341
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001342 /**
1343 * Completely remove all activities associated with an existing
1344 * task starting at a specified index.
1345 */
Winson Chung0ec2a352017-10-26 11:38:30 -07001346 final void performClearTaskAtIndexLocked(int activityNdx, boolean pauseImmediately,
1347 String reason) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001348 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001349 for ( ; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001350 final ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001351 if (r.finishing) {
1352 continue;
1353 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001354 if (mStack == null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001355 // Task was restored from persistent storage.
1356 r.takeFromHistory();
1357 mActivities.remove(activityNdx);
1358 --activityNdx;
1359 --numActivities;
Winson Chung6954fc92017-03-24 16:22:12 -07001360 } else if (mStack.finishActivityLocked(r, Activity.RESULT_CANCELED, null,
Winson Chung0ec2a352017-10-26 11:38:30 -07001361 reason, false, pauseImmediately)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001362 --activityNdx;
1363 --numActivities;
1364 }
1365 }
1366 }
1367
1368 /**
1369 * Completely remove all activities associated with an existing task.
1370 */
Benjamin Franza83859f2017-07-03 16:34:14 +01001371 void performClearTaskLocked() {
Craig Mautner362449a2014-06-20 14:04:39 -07001372 mReuseTask = true;
Winson Chung0ec2a352017-10-26 11:38:30 -07001373 performClearTaskAtIndexLocked(0, !PAUSE_IMMEDIATELY, "clear-task-all");
Craig Mautner362449a2014-06-20 14:04:39 -07001374 mReuseTask = false;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001375 }
1376
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -08001377 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1378 mReuseTask = true;
1379 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1380 mReuseTask = false;
1381 return result;
1382 }
1383
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001384 /**
1385 * Perform clear operation as requested by
1386 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1387 * stack to the given task, then look for
1388 * an instance of that activity in the stack and, if found, finish all
1389 * activities on top of it and return the instance.
1390 *
1391 * @param newR Description of the new activity being started.
1392 * @return Returns the old activity that should be continued to be used,
1393 * or null if none was found.
1394 */
1395 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001396 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001397 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001398 ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001399 if (r.finishing) {
1400 continue;
1401 }
1402 if (r.realActivity.equals(newR.realActivity)) {
1403 // Here it is! Now finish everything in front...
Craig Mautner1602ec22013-05-12 10:24:27 -07001404 final ActivityRecord ret = r;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001405
1406 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001407 r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001408 if (r.finishing) {
1409 continue;
1410 }
1411 ActivityOptions opts = r.takeOptionsLocked();
1412 if (opts != null) {
1413 ret.updateOptionsLocked(opts);
1414 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001415 if (mStack != null && mStack.finishActivityLocked(
Todd Kennedy539db512014-12-15 09:57:55 -08001416 r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001417 --activityNdx;
1418 --numActivities;
1419 }
1420 }
1421
1422 // Finally, if this is a normal launch mode (that is, not
1423 // expecting onNewIntent()), then we will finish the current
1424 // instance of the activity so a new fresh one can be started.
1425 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
Daichi Hirono15a02992016-04-27 18:47:01 +09001426 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1427 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001428 if (!ret.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001429 if (mStack != null) {
1430 mStack.finishActivityLocked(
Wale Ogunwale7d701172015-03-11 15:36:30 -07001431 ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
1432 }
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001433 return null;
1434 }
1435 }
1436
1437 return ret;
1438 }
1439 }
1440
1441 return null;
1442 }
1443
Winson Chung0ec2a352017-10-26 11:38:30 -07001444 void removeTaskActivitiesLocked(boolean pauseImmediately, String reason) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001445 // Just remove the entire task.
Winson Chung0ec2a352017-10-26 11:38:30 -07001446 performClearTaskAtIndexLocked(0, pauseImmediately, reason);
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001447 }
1448
Craig Mautner432f64e2015-05-20 14:59:57 -07001449 String lockTaskAuthToString() {
1450 switch (mLockTaskAuth) {
1451 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1452 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1453 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1454 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
Benjamin Franz469dd582015-06-09 14:24:36 +01001455 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
Craig Mautner432f64e2015-05-20 14:59:57 -07001456 default: return "unknown=" + mLockTaskAuth;
1457 }
1458 }
1459
Craig Mautner15df08a2015-04-01 12:17:18 -07001460 void setLockTaskAuth() {
Charles He2bf28322017-10-12 22:24:49 +01001461 setLockTaskAuth(getRootActivity());
1462 }
1463
1464 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1465 if (r == null) {
1466 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1467 return;
1468 }
1469
Charles He520b2832017-09-02 15:27:16 +01001470 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
Bryce Lee2b8e0372018-04-05 17:01:37 -07001471 final LockTaskController lockTaskController = mService.getLockTaskController();
Charles He2bf28322017-10-12 22:24:49 +01001472 switch (r.lockTaskLaunchMode) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001473 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
Bryce Lee2b8e0372018-04-05 17:01:37 -07001474 mLockTaskAuth = lockTaskController.isPackageWhitelisted(userId, pkg)
Charles He520b2832017-09-02 15:27:16 +01001475 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001476 break;
1477
1478 case LOCK_TASK_LAUNCH_MODE_NEVER:
Benjamin Franz469dd582015-06-09 14:24:36 +01001479 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
Craig Mautner15df08a2015-04-01 12:17:18 -07001480 break;
1481
1482 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
Benjamin Franz469dd582015-06-09 14:24:36 +01001483 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
Craig Mautner15df08a2015-04-01 12:17:18 -07001484 break;
1485
1486 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
Bryce Lee2b8e0372018-04-05 17:01:37 -07001487 mLockTaskAuth = lockTaskController.isPackageWhitelisted(userId, pkg)
Charles He520b2832017-09-02 15:27:16 +01001488 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001489 break;
1490 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001491 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this +
1492 " mLockTaskAuth=" + lockTaskAuthToString());
Craig Mautner15df08a2015-04-01 12:17:18 -07001493 }
1494
Winson Chungd3395382016-12-13 11:49:09 -08001495 private boolean isResizeable(boolean checkSupportsPip) {
1496 return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001497 || (checkSupportsPip && mSupportsPictureInPicture));
Winson Chungd3395382016-12-13 11:49:09 -08001498 }
1499
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001500 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08001501 return isResizeable(true /* checkSupportsPip */);
1502 }
1503
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001504 @Override
1505 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08001506 // A task can not be docked even if it is considered resizeable because it only supports
1507 // picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001508 return super.supportsSplitScreenWindowingMode()
1509 && mService.mSupportsSplitScreenMultiWindow
Bryce Leec857a5b2017-08-16 10:04:52 -07001510 && (mService.mForceResizableActivities
1511 || (isResizeable(false /* checkSupportsPip */)
1512 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001513 }
1514
skuhne@google.com322347b2016-12-02 12:54:03 -08001515 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001516 * Check whether this task can be launched on the specified display.
1517 * @param displayId Target display id.
1518 * @return {@code true} if either it is the default display or this activity is resizeable and
1519 * can be put a secondary screen.
1520 */
1521 boolean canBeLaunchedOnDisplay(int displayId) {
1522 return mService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Andrii Kulian02689a72017-07-06 14:28:59 -07001523 isResizeable(false /* checkSupportsPip */), -1 /* don't check PID */,
1524 -1 /* don't check UID */, null /* activityInfo */);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001525 }
1526
1527 /**
skuhne@google.com322347b2016-12-02 12:54:03 -08001528 * Check that a given bounds matches the application requested orientation.
1529 *
1530 * @param bounds The bounds to be tested.
1531 * @return True if the requested bounds are okay for a resizing request.
1532 */
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001533 private boolean canResizeToBounds(Rect bounds) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001534 if (bounds == null || !inFreeformWindowingMode()) {
skuhne@google.com322347b2016-12-02 12:54:03 -08001535 // Note: If not on the freeform workspace, we ignore the bounds.
1536 return true;
1537 }
1538 final boolean landscape = bounds.width() > bounds.height();
Bryce Leef3c6a472017-11-14 14:53:06 -08001539 final Rect configBounds = getOverrideBounds();
skuhne@google.com322347b2016-12-02 12:54:03 -08001540 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001541 return configBounds.isEmpty()
1542 || landscape == (configBounds.width() > configBounds.height());
skuhne@google.com322347b2016-12-02 12:54:03 -08001543 }
1544 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1545 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1546 }
1547
Craig Mautner525f3d92013-05-07 14:01:50 -07001548 /**
Yorke Leebdef5372017-04-10 16:38:51 -07001549 * @return {@code true} if the task is being cleared for the purposes of being reused.
1550 */
1551 boolean isClearingToReuseTask() {
1552 return mReuseTask;
1553 }
1554
1555 /**
Craig Mautner525f3d92013-05-07 14:01:50 -07001556 * Find the activity in the history stack within the given task. Returns
1557 * the index within the history at which it's found, or < 0 if not found.
1558 */
1559 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
1560 final ComponentName realActivity = r.realActivity;
1561 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1562 ActivityRecord candidate = mActivities.get(activityNdx);
1563 if (candidate.finishing) {
1564 continue;
1565 }
1566 if (candidate.realActivity.equals(realActivity)) {
1567 return candidate;
1568 }
1569 }
1570 return null;
1571 }
1572
Winson Chunga449dc02014-05-16 11:15:04 -07001573 /** Updates the last task description values. */
1574 void updateTaskDescription() {
1575 // Traverse upwards looking for any break between main task activities and
1576 // utility activities.
1577 int activityNdx;
1578 final int numActivities = mActivities.size();
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001579 final boolean relinquish = numActivities != 0 &&
1580 (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001581 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
Craig Mautner21d24a22014-04-23 11:45:37 -07001582 ++activityNdx) {
Winson Chunga449dc02014-05-16 11:15:04 -07001583 final ActivityRecord r = mActivities.get(activityNdx);
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001584 if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001585 // This will be the top activity for determining taskDescription. Pre-inc to
1586 // overcome initial decrement below.
1587 ++activityNdx;
1588 break;
1589 }
Winson Chunga449dc02014-05-16 11:15:04 -07001590 if (r.intent != null &&
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001591 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
Winson Chunga449dc02014-05-16 11:15:04 -07001592 break;
1593 }
1594 }
1595 if (activityNdx > 0) {
1596 // Traverse downwards starting below break looking for set label, icon.
1597 // Note that if there are activities in the task but none of them set the
1598 // recent activity values, then we do not fall back to the last set
1599 // values in the TaskRecord.
1600 String label = null;
Craig Mautner648f69b2014-09-18 14:16:26 -07001601 String iconFilename = null;
Matthew Ng54bc9422017-10-02 17:16:28 -07001602 int iconResource = -1;
Winson Chunga449dc02014-05-16 11:15:04 -07001603 int colorPrimary = 0;
Winson Chung1af8eda2016-02-05 17:55:56 +00001604 int colorBackground = 0;
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001605 int statusBarColor = 0;
1606 int navigationBarColor = 0;
1607 boolean topActivity = true;
Winson Chunga449dc02014-05-16 11:15:04 -07001608 for (--activityNdx; activityNdx >= 0; --activityNdx) {
1609 final ActivityRecord r = mActivities.get(activityNdx);
Winson Chung80f80db2018-05-30 21:13:25 -07001610 if (r.mTaskOverlay) {
1611 continue;
1612 }
Winson Chunga449dc02014-05-16 11:15:04 -07001613 if (r.taskDescription != null) {
1614 if (label == null) {
1615 label = r.taskDescription.getLabel();
1616 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001617 if (iconResource == -1) {
1618 iconResource = r.taskDescription.getIconResource();
1619 }
Craig Mautner648f69b2014-09-18 14:16:26 -07001620 if (iconFilename == null) {
1621 iconFilename = r.taskDescription.getIconFilename();
Winson Chunga449dc02014-05-16 11:15:04 -07001622 }
1623 if (colorPrimary == 0) {
1624 colorPrimary = r.taskDescription.getPrimaryColor();
Winson Chunga449dc02014-05-16 11:15:04 -07001625 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001626 if (topActivity) {
Winson Chung1af8eda2016-02-05 17:55:56 +00001627 colorBackground = r.taskDescription.getBackgroundColor();
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001628 statusBarColor = r.taskDescription.getStatusBarColor();
1629 navigationBarColor = r.taskDescription.getNavigationBarColor();
Winson Chung1af8eda2016-02-05 17:55:56 +00001630 }
Winson Chunga449dc02014-05-16 11:15:04 -07001631 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001632 topActivity = false;
Winson Chunga449dc02014-05-16 11:15:04 -07001633 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001634 lastTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
1635 colorPrimary, colorBackground, statusBarColor, navigationBarColor);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001636 if (mWindowContainerController != null) {
1637 mWindowContainerController.setTaskDescription(lastTaskDescription);
1638 }
Winson Chungec396d62014-08-06 17:08:00 -07001639 // Update the task affiliation color if we are the parent of the group
1640 if (taskId == mAffiliatedTaskId) {
1641 mAffiliatedTaskColor = lastTaskDescription.getPrimaryColor();
1642 }
Winson Chunga449dc02014-05-16 11:15:04 -07001643 }
1644 }
1645
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001646 int findEffectiveRootIndex() {
Craig Mautner4767f4b2014-09-18 15:38:33 -07001647 int effectiveNdx = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001648 final int topActivityNdx = mActivities.size() - 1;
Dianne Hackborn39569af2014-09-23 10:56:58 -07001649 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001650 final ActivityRecord r = mActivities.get(activityNdx);
1651 if (r.finishing) {
1652 continue;
1653 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001654 effectiveNdx = activityNdx;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001655 if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001656 break;
1657 }
1658 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001659 return effectiveNdx;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001660 }
1661
1662 void updateEffectiveIntent() {
1663 final int effectiveRootIndex = findEffectiveRootIndex();
1664 final ActivityRecord r = mActivities.get(effectiveRootIndex);
Winson Chungfee26772014-08-05 12:21:52 -07001665 setIntent(r);
Winson Chung8d9009e2017-11-16 15:43:05 -08001666
1667 // Update the task description when the activities change
1668 updateTaskDescription();
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001669 }
1670
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001671 private void adjustForMinimalTaskDimensions(Rect bounds) {
1672 if (bounds == null) {
1673 return;
1674 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001675 int minWidth = mMinWidth;
1676 int minHeight = mMinHeight;
Robert Carr9c5867d2016-03-10 15:52:46 -08001677 // If the task has no requested minimal size, we'd like to enforce a minimal size
1678 // so that the user can not render the task too small to manipulate. We don't need
1679 // to do this for the pinned stack as the bounds are controlled by the system.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001680 if (!inPinnedWindowingMode()) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001681 if (minWidth == INVALID_MIN_SIZE) {
1682 minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001683 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001684 if (minHeight == INVALID_MIN_SIZE) {
1685 minHeight = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001686 }
Robert Carr9c5867d2016-03-10 15:52:46 -08001687 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001688 final boolean adjustWidth = minWidth > bounds.width();
1689 final boolean adjustHeight = minHeight > bounds.height();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001690 if (!(adjustWidth || adjustHeight)) {
1691 return;
1692 }
1693
Bryce Leef3c6a472017-11-14 14:53:06 -08001694 final Rect configBounds = getOverrideBounds();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001695 if (adjustWidth) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001696 if (!configBounds.isEmpty() && bounds.right == configBounds.right) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001697 bounds.left = bounds.right - minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001698 } else {
1699 // Either left bounds match, or neither match, or the previous bounds were
1700 // fullscreen and we default to keeping left.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001701 bounds.right = bounds.left + minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001702 }
1703 }
1704 if (adjustHeight) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001705 if (!configBounds.isEmpty() && bounds.bottom == configBounds.bottom) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001706 bounds.top = bounds.bottom - minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001707 } else {
1708 // Either top bounds match, or neither match, or the previous bounds were
1709 // fullscreen and we default to keeping top.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001710 bounds.bottom = bounds.top + minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001711 }
1712 }
1713 }
1714
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001715 /**
Winson Chung5af42fc2017-03-24 17:11:33 -07001716 * @return a new Configuration for this Task, given the provided {@param bounds} and
1717 * {@param insetBounds}.
1718 */
1719 Configuration computeNewOverrideConfigurationForBounds(Rect bounds, Rect insetBounds) {
1720 // Compute a new override configuration for the given bounds, if fullscreen bounds
1721 // (bounds == null), then leave the override config unset
1722 final Configuration newOverrideConfig = new Configuration();
1723 if (bounds != null) {
1724 newOverrideConfig.setTo(getOverrideConfiguration());
1725 mTmpRect.set(bounds);
1726 adjustForMinimalTaskDimensions(mTmpRect);
1727 computeOverrideConfiguration(newOverrideConfig, mTmpRect, insetBounds,
1728 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
1729 }
1730
1731 return newOverrideConfig;
1732 }
1733
1734 /**
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001735 * Update task's override configuration based on the bounds.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001736 * @param bounds The bounds of the task.
Andrii Kulian8072d112016-09-16 11:11:01 -07001737 * @return True if the override configuration was updated.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001738 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001739 boolean updateOverrideConfiguration(Rect bounds) {
Jorim Jaggi0a932142016-02-01 17:42:25 -08001740 return updateOverrideConfiguration(bounds, null /* insetBounds */);
1741 }
1742
1743 /**
1744 * Update task's override configuration based on the bounds.
1745 * @param bounds The bounds of the task.
1746 * @param insetBounds The bounds used to calculate the system insets, which is used here to
1747 * subtract the navigation bar/status bar size from the screen size reported
1748 * to the application. See {@link IActivityManager#resizeDockedStack}.
Andrii Kulian8072d112016-09-16 11:11:01 -07001749 * @return True if the override configuration was updated.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001750 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001751 boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001752 if (equivalentOverrideBounds(bounds)) {
Andrii Kulian8072d112016-09-16 11:11:01 -07001753 return false;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001754 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001755 final Rect currentBounds = getOverrideBounds();
1756
Andrii Kulian1779e612016-10-12 21:58:25 -07001757 mTmpConfig.setTo(getOverrideConfiguration());
Andrii Kulian1779e612016-10-12 21:58:25 -07001758 final Configuration newConfig = getOverrideConfiguration();
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001759
Bryce Leef3c6a472017-11-14 14:53:06 -08001760 final boolean matchParentBounds = bounds == null || bounds.isEmpty();
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001761 final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
Bryce Leef3c6a472017-11-14 14:53:06 -08001762 if (matchParentBounds) {
1763 if (!currentBounds.isEmpty() && persistBounds) {
1764 mLastNonFullscreenBounds = currentBounds;
Wale Ogunwale706ed792015-08-02 10:29:44 -07001765 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001766 setBounds(null);
Andrii Kulian1779e612016-10-12 21:58:25 -07001767 newConfig.unset();
Wale Ogunwale706ed792015-08-02 10:29:44 -07001768 } else {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001769 mTmpRect.set(bounds);
1770 adjustForMinimalTaskDimensions(mTmpRect);
Bryce Leef3c6a472017-11-14 14:53:06 -08001771 setBounds(mTmpRect);
1772
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001773 if (mStack == null || persistBounds) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001774 mLastNonFullscreenBounds = getOverrideBounds();
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -07001775 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001776 computeOverrideConfiguration(newConfig, mTmpRect, insetBounds,
Andrii Kuliandaea3572016-04-08 13:20:51 -07001777 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
Wale Ogunwale706ed792015-08-02 10:29:44 -07001778 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001779 onOverrideConfigurationChanged(newConfig);
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001780 return !mTmpConfig.equals(newConfig);
1781 }
Wale Ogunwale5f986092015-12-04 15:35:38 -08001782
Bryce Leec4ab62a2018-03-05 14:19:26 -08001783 /**
1784 * This should be called when an child activity changes state. This should only
1785 * be called from
1786 * {@link ActivityRecord#setState(ActivityState, String)} .
1787 * @param record The {@link ActivityRecord} whose state has changed.
1788 * @param state The new state.
1789 * @param reason The reason for the change.
1790 */
1791 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
1792 final ActivityStack parent = getStack();
1793
1794 if (parent != null) {
1795 parent.onActivityStateChanged(record, state, reason);
1796 }
1797 }
1798
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001799 @Override
1800 public void onConfigurationChanged(Configuration newParentConfig) {
1801 final boolean wasInMultiWindowMode = inMultiWindowMode();
1802 super.onConfigurationChanged(newParentConfig);
1803 if (wasInMultiWindowMode != inMultiWindowMode()) {
Winson Chung5af42fc2017-03-24 17:11:33 -07001804 mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001805 }
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001806 // TODO: Should also take care of Pip mode changes here.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001807 }
1808
Andrii Kulian1779e612016-10-12 21:58:25 -07001809 /** Clears passed config and fills it with new override values. */
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001810 // TODO(b/36505427): TaskRecord.computeOverrideConfiguration() is a utility method that doesn't
1811 // depend on task or stacks, but uses those object to get the display to base the calculation
1812 // on. Probably best to centralize calculations like this in ConfigurationContainer.
1813 void computeOverrideConfiguration(Configuration config, Rect bounds, Rect insetBounds,
Andrii Kuliana8a9bc52016-10-14 11:00:13 -07001814 boolean overrideWidth, boolean overrideHeight) {
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001815 mTmpNonDecorBounds.set(bounds);
1816 mTmpStableBounds.set(bounds);
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001817
Andrii Kulian1779e612016-10-12 21:58:25 -07001818 config.unset();
Winson Chungbdc646f2017-02-13 12:12:22 -08001819 final Configuration parentConfig = getParent().getConfiguration();
Bryce Lee7566d762017-03-30 09:34:15 -07001820
Andrii Kulian1779e612016-10-12 21:58:25 -07001821 final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001822
Winson Chungbdc646f2017-02-13 12:12:22 -08001823 if (mStack != null) {
1824 final StackWindowController stackController = mStack.getWindowContainerController();
1825 stackController.adjustConfigurationForBounds(bounds, insetBounds,
1826 mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
Evan Roskyb0e38882018-04-25 12:48:54 -07001827 config, parentConfig, getWindowingMode());
Winson Chungbdc646f2017-02-13 12:12:22 -08001828 } else {
Bryce Lee7566d762017-03-30 09:34:15 -07001829 throw new IllegalArgumentException("Expected stack when calculating override config");
Winson Chungbdc646f2017-02-13 12:12:22 -08001830 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001831
Winson Chung60c1aba2017-03-14 17:47:42 -07001832 config.orientation = (config.screenWidthDp <= config.screenHeightDp)
1833 ? Configuration.ORIENTATION_PORTRAIT
1834 : Configuration.ORIENTATION_LANDSCAPE;
1835
Jorim Jaggi85639432016-05-06 17:27:55 -07001836 // For calculating screen layout, we need to use the non-decor inset screen area for the
1837 // calculation for compatibility reasons, i.e. screen area without system bars that could
1838 // never go away in Honeycomb.
Winson Chungbdc646f2017-02-13 12:12:22 -08001839 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
1840 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Andrii Kulian1779e612016-10-12 21:58:25 -07001841 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
1842 // calculation with partial default.
1843 final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001844 final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
Andrii Kulian1779e612016-10-12 21:58:25 -07001845 final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
Jorim Jaggi85639432016-05-06 17:27:55 -07001846 config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001847 }
1848
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001849 Rect updateOverrideConfigurationFromLaunchBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08001850 final Rect bounds = getLaunchBounds();
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001851 updateOverrideConfiguration(bounds);
Bryce Leef3c6a472017-11-14 14:53:06 -08001852 if (bounds != null && !bounds.isEmpty()) {
1853 // TODO: Review if we actually want to do this - we are setting the launch bounds
1854 // directly here.
1855 bounds.set(getOverrideBounds());
Andrii Kulian73336d812016-03-24 12:56:08 -07001856 }
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001857 return bounds;
1858 }
1859
Wale Ogunwale935e5022015-11-10 12:36:10 -08001860 /** Updates the task's bounds and override configuration to match what is expected for the
1861 * input stack. */
1862 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001863 if (mStack != null && mStack == inStack) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001864 return;
1865 }
1866
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001867 if (inStack.inFreeformWindowingMode()) {
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001868 if (!isResizeable()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001869 throw new IllegalArgumentException("Can not position non-resizeable task="
1870 + this + " in stack=" + inStack);
1871 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001872 if (!matchParentBounds()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001873 return;
1874 }
1875 if (mLastNonFullscreenBounds != null) {
1876 updateOverrideConfiguration(mLastNonFullscreenBounds);
1877 } else {
Bryce Leeec55eb02017-12-05 20:51:27 -08001878 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Wale Ogunwale935e5022015-11-10 12:36:10 -08001879 }
1880 } else {
Bryce Leef3c6a472017-11-14 14:53:06 -08001881 updateOverrideConfiguration(inStack.getOverrideBounds());
Wale Ogunwale935e5022015-11-10 12:36:10 -08001882 }
1883 }
1884
Wale Ogunwale706ed792015-08-02 10:29:44 -07001885 /** Returns the bounds that should be used to launch this task. */
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001886 Rect getLaunchBounds() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001887 if (mStack == null) {
Chong Zhang7d5f5102016-01-13 10:29:24 -08001888 return null;
1889 }
1890
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001891 final int windowingMode = getWindowingMode();
1892 if (!isActivityTypeStandardOrUndefined()
1893 || windowingMode == WINDOWING_MODE_FULLSCREEN
1894 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001895 return isResizeable() ? mStack.getOverrideBounds() : null;
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001896 } else if (!getWindowConfiguration().persistTaskBounds()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001897 return mStack.getOverrideBounds();
Wale Ogunwale706ed792015-08-02 10:29:44 -07001898 }
1899 return mLastNonFullscreenBounds;
1900 }
1901
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01001902 void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
1903 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1904 final ActivityRecord r = mActivities.get(activityNdx);
1905 if (r.visible) {
1906 r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
1907 }
1908 }
1909 }
1910
Dianne Hackborn68a06332017-11-15 17:54:18 -08001911 void setRootProcess(ProcessRecord proc) {
1912 clearRootProcess();
1913 if (intent != null &&
1914 (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
1915 mRootProcess = proc;
1916 proc.recentTasks.add(this);
1917 }
1918 }
1919
1920 void clearRootProcess() {
1921 if (mRootProcess != null) {
1922 mRootProcess.recentTasks.remove(this);
1923 mRootProcess = null;
1924 }
1925 }
1926
chaviw82a0ba82018-03-15 14:26:29 -07001927 void clearAllPendingOptions() {
1928 for (int i = getChildCount() - 1; i >= 0; i--) {
1929 getChildAt(i).clearOptionsLocked(false /* withAbort */);
1930 }
1931 }
1932
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001933 void dump(PrintWriter pw, String prefix) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001934 pw.print(prefix); pw.print("userId="); pw.print(userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001935 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
1936 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
Suprabh Shukla7745c142016-03-07 18:21:10 -08001937 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001938 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
Dianne Hackborn79228822014-09-16 11:11:23 -07001939 if (affinity != null || rootAffinity != null) {
1940 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
1941 if (affinity == null || !affinity.equals(rootAffinity)) {
1942 pw.print(" root="); pw.println(rootAffinity);
1943 } else {
1944 pw.println();
1945 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001946 }
Dianne Hackborn91097de2014-04-04 18:02:06 -07001947 if (voiceSession != null || voiceInteractor != null) {
1948 pw.print(prefix); pw.print("VOICE: session=0x");
1949 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
1950 pw.print(" interactor=0x");
1951 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
1952 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001953 if (intent != null) {
1954 StringBuilder sb = new StringBuilder(128);
1955 sb.append(prefix); sb.append("intent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08001956 intent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001957 sb.append('}');
1958 pw.println(sb.toString());
1959 }
1960 if (affinityIntent != null) {
1961 StringBuilder sb = new StringBuilder(128);
1962 sb.append(prefix); sb.append("affinityIntent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08001963 affinityIntent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001964 sb.append('}');
1965 pw.println(sb.toString());
1966 }
1967 if (origActivity != null) {
1968 pw.print(prefix); pw.print("origActivity=");
1969 pw.println(origActivity.flattenToShortString());
1970 }
1971 if (realActivity != null) {
1972 pw.print(prefix); pw.print("realActivity=");
1973 pw.println(realActivity.flattenToShortString());
1974 }
Wale Ogunwale66e16852017-10-19 13:35:52 -07001975 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard() || numFullscreen != 0) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001976 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001977 pw.print(" isPersistable="); pw.print(isPersistable);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001978 pw.print(" numFullscreen="); pw.print(numFullscreen);
Wale Ogunwale66e16852017-10-19 13:35:52 -07001979 pw.print(" activityType="); pw.println(getActivityType());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001980 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001981 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
1982 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001983 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
1984 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
Craig Mautner432f64e2015-05-20 14:59:57 -07001985 pw.print(" mReuseTask="); pw.print(mReuseTask);
1986 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001987 }
Wale Ogunwale18795a22014-12-03 11:38:33 -08001988 if (mAffiliatedTaskId != taskId || mPrevAffiliateTaskId != INVALID_TASK_ID
1989 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
1990 || mNextAffiliate != null) {
Dianne Hackborn852975d2014-08-22 17:42:43 -07001991 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
1992 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
1993 pw.print(" (");
1994 if (mPrevAffiliate == null) {
1995 pw.print("null");
1996 } else {
1997 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
1998 }
1999 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
2000 pw.print(" (");
2001 if (mNextAffiliate == null) {
2002 pw.print("null");
2003 } else {
2004 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
2005 }
2006 pw.println(")");
2007 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002008 pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002009 if (!askedCompatMode || !inRecents || !isAvailable) {
2010 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
2011 pw.print(" inRecents="); pw.print(inRecents);
2012 pw.print(" isAvailable="); pw.println(isAvailable);
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002013 }
Dianne Hackborn852975d2014-08-22 17:42:43 -07002014 if (lastDescription != null) {
2015 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
2016 }
Dianne Hackborn68a06332017-11-15 17:54:18 -08002017 if (mRootProcess != null) {
2018 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
2019 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002020 pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002021 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
2022 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08002023 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002024 pw.print(" isResizeable=" + isResizeable());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002025 pw.print(" lastActiveTime=" + lastActiveTime);
2026 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002027 }
2028
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002029 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002030 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002031 StringBuilder sb = new StringBuilder(128);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002032 if (stringName != null) {
2033 sb.append(stringName);
2034 sb.append(" U=");
2035 sb.append(userId);
Wale Ogunwale6c5eb1c2015-11-10 07:52:22 -08002036 sb.append(" StackId=");
Andrii Kulian02b7a832016-10-06 23:11:56 -07002037 sb.append(getStackId());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002038 sb.append(" sz=");
2039 sb.append(mActivities.size());
2040 sb.append('}');
2041 return sb.toString();
2042 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002043 sb.append("TaskRecord{");
2044 sb.append(Integer.toHexString(System.identityHashCode(this)));
2045 sb.append(" #");
2046 sb.append(taskId);
2047 if (affinity != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002048 sb.append(" A=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002049 sb.append(affinity);
2050 } else if (intent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002051 sb.append(" I=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002052 sb.append(intent.getComponent().flattenToShortString());
Bryce Leefbd263b42018-03-07 10:33:55 -08002053 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002054 sb.append(" aI=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002055 sb.append(affinityIntent.getComponent().flattenToShortString());
2056 } else {
2057 sb.append(" ??");
2058 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07002059 stringName = sb.toString();
2060 return toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 }
Steven Timotius4346f0a2017-09-12 11:07:21 -07002062
2063 public void writeToProto(ProtoOutputStream proto, long fieldId) {
2064 final long token = proto.start(fieldId);
Adrian Roos4921ccf2017-09-28 16:54:06 +02002065 super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002066 proto.write(ID, taskId);
2067 for (int i = mActivities.size() - 1; i >= 0; i--) {
2068 ActivityRecord activity = mActivities.get(i);
2069 activity.writeToProto(proto, ACTIVITIES);
2070 }
2071 proto.write(STACK_ID, mStack.mStackId);
2072 if (mLastNonFullscreenBounds != null) {
2073 mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
2074 }
2075 if (realActivity != null) {
2076 proto.write(REAL_ACTIVITY, realActivity.flattenToShortString());
2077 }
2078 if (origActivity != null) {
2079 proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString());
2080 }
2081 proto.write(ACTIVITY_TYPE, getActivityType());
Steven Timotius4346f0a2017-09-12 11:07:21 -07002082 proto.write(RESIZE_MODE, mResizeMode);
Bryce Leef3c6a472017-11-14 14:53:06 -08002083 // TODO: Remove, no longer needed with windowingMode.
2084 proto.write(FULLSCREEN, matchParentBounds());
2085
2086 if (!matchParentBounds()) {
2087 final Rect bounds = getOverrideBounds();
2088 bounds.writeToProto(proto, BOUNDS);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002089 }
2090 proto.write(MIN_WIDTH, mMinWidth);
2091 proto.write(MIN_HEIGHT, mMinHeight);
2092 proto.end(token);
2093 }
Winson Chung61c9e5a2017-10-11 10:39:32 -07002094
2095 /**
2096 * See {@link #getNumRunningActivities(TaskActivitiesReport)}.
2097 */
2098 static class TaskActivitiesReport {
2099 int numRunning;
2100 int numActivities;
2101 ActivityRecord top;
2102 ActivityRecord base;
2103
2104 void reset() {
2105 numRunning = numActivities = 0;
2106 top = base = null;
2107 }
2108 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002109
2110 /**
2111 * Saves this {@link TaskRecord} to XML using given serializer.
2112 */
2113 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
2114 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
2115
2116 out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
2117 if (realActivity != null) {
2118 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
2119 }
2120 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
2121 if (origActivity != null) {
2122 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
2123 }
2124 // Write affinity, and root affinity if it is different from affinity.
2125 // We use the special string "@" for a null root affinity, so we can identify
2126 // later whether we were given a root affinity or should just make it the
2127 // same as the affinity.
2128 if (affinity != null) {
2129 out.attribute(null, ATTR_AFFINITY, affinity);
2130 if (!affinity.equals(rootAffinity)) {
2131 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2132 }
2133 } else if (rootAffinity != null) {
2134 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2135 }
2136 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
2137 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
2138 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
2139 out.attribute(null, ATTR_USERID, String.valueOf(userId));
2140 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
2141 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
2142 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
2143 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
2144 if (lastDescription != null) {
2145 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
2146 }
2147 if (lastTaskDescription != null) {
2148 lastTaskDescription.saveToXml(out);
2149 }
2150 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
2151 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
2152 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
2153 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
2154 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
2155 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
2156 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
2157 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
2158 String.valueOf(mSupportsPictureInPicture));
2159 if (mLastNonFullscreenBounds != null) {
2160 out.attribute(
2161 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
2162 }
2163 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
2164 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
2165 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
2166
2167 if (affinityIntent != null) {
2168 out.startTag(null, TAG_AFFINITYINTENT);
2169 affinityIntent.saveToXml(out);
2170 out.endTag(null, TAG_AFFINITYINTENT);
2171 }
2172
Bryce Lee1a990e52018-04-23 10:54:11 -07002173 if (intent != null) {
2174 out.startTag(null, TAG_INTENT);
2175 intent.saveToXml(out);
2176 out.endTag(null, TAG_INTENT);
2177 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002178
2179 final ArrayList<ActivityRecord> activities = mActivities;
2180 final int numActivities = activities.size();
2181 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
2182 final ActivityRecord r = activities.get(activityNdx);
2183 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
2184 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
2185 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
2186 activityNdx > 0) {
2187 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
2188 break;
2189 }
2190 out.startTag(null, TAG_ACTIVITY);
2191 r.saveToXml(out);
2192 out.endTag(null, TAG_ACTIVITY);
2193 }
2194 }
2195
2196 @VisibleForTesting
2197 static TaskRecordFactory getTaskRecordFactory() {
2198 if (sTaskRecordFactory == null) {
2199 setTaskRecordFactory(new TaskRecordFactory());
2200 }
2201 return sTaskRecordFactory;
2202 }
2203
2204 static void setTaskRecordFactory(TaskRecordFactory factory) {
2205 sTaskRecordFactory = factory;
2206 }
2207
2208 static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2209 Intent intent, IVoiceInteractionSession voiceSession,
2210 IVoiceInteractor voiceInteractor) {
2211 return getTaskRecordFactory().create(
2212 service, taskId, info, intent, voiceSession, voiceInteractor);
2213 }
2214
2215 static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2216 Intent intent, TaskDescription taskDescription) {
2217 return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
2218 }
2219
2220 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2221 throws IOException, XmlPullParserException {
2222 return getTaskRecordFactory().restoreFromXml(in, stackSupervisor);
2223 }
2224
2225 /**
2226 * A factory class used to create {@link TaskRecord} or its subclass if any. This can be
2227 * specified when system boots by setting it with
2228 * {@link #setTaskRecordFactory(TaskRecordFactory)}.
2229 */
2230 static class TaskRecordFactory {
2231
2232 TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2233 Intent intent, IVoiceInteractionSession voiceSession,
2234 IVoiceInteractor voiceInteractor) {
2235 return new TaskRecord(
2236 service, taskId, info, intent, voiceSession, voiceInteractor);
2237 }
2238
2239 TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2240 Intent intent, TaskDescription taskDescription) {
2241 return new TaskRecord(service, taskId, info, intent, taskDescription);
2242 }
2243
2244 /**
2245 * Should only be used when we're restoring {@link TaskRecord} from storage.
2246 */
2247 TaskRecord create(ActivityManagerService service, int taskId, Intent intent,
2248 Intent affinityIntent, String affinity, String rootAffinity,
2249 ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
2250 boolean autoRemoveRecents, boolean askedCompatMode, int userId,
2251 int effectiveUid, String lastDescription, ArrayList<ActivityRecord> activities,
2252 long lastTimeMoved, boolean neverRelinquishIdentity,
2253 TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
2254 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
2255 int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
2256 boolean userSetupComplete, int minWidth, int minHeight) {
2257 return new TaskRecord(service, taskId, intent, affinityIntent, affinity,
2258 rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
2259 askedCompatMode, userId, effectiveUid, lastDescription, activities,
2260 lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
2261 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
2262 resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
2263 minWidth, minHeight);
2264 }
2265
2266 TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2267 throws IOException, XmlPullParserException {
2268 Intent intent = null;
2269 Intent affinityIntent = null;
2270 ArrayList<ActivityRecord> activities = new ArrayList<>();
2271 ComponentName realActivity = null;
2272 boolean realActivitySuspended = false;
2273 ComponentName origActivity = null;
2274 String affinity = null;
2275 String rootAffinity = null;
2276 boolean hasRootAffinity = false;
2277 boolean rootHasReset = false;
2278 boolean autoRemoveRecents = false;
2279 boolean askedCompatMode = false;
2280 int taskType = 0;
2281 int userId = 0;
2282 boolean userSetupComplete = true;
2283 int effectiveUid = -1;
2284 String lastDescription = null;
2285 long lastTimeOnTop = 0;
2286 boolean neverRelinquishIdentity = true;
2287 int taskId = INVALID_TASK_ID;
2288 final int outerDepth = in.getDepth();
2289 TaskDescription taskDescription = new TaskDescription();
2290 int taskAffiliation = INVALID_TASK_ID;
2291 int taskAffiliationColor = 0;
2292 int prevTaskId = INVALID_TASK_ID;
2293 int nextTaskId = INVALID_TASK_ID;
2294 int callingUid = -1;
2295 String callingPackage = "";
2296 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
2297 boolean supportsPictureInPicture = false;
Garfield Tan367b35a2017-12-13 12:16:21 -08002298 Rect lastNonFullscreenBounds = null;
Garfield Tan9b1efea2017-12-05 16:43:46 -08002299 int minWidth = INVALID_MIN_SIZE;
2300 int minHeight = INVALID_MIN_SIZE;
2301 int persistTaskVersion = 0;
2302
2303 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
2304 final String attrName = in.getAttributeName(attrNdx);
2305 final String attrValue = in.getAttributeValue(attrNdx);
2306 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
2307 attrName + " value=" + attrValue);
2308 switch (attrName) {
2309 case ATTR_TASKID:
2310 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
2311 break;
2312 case ATTR_REALACTIVITY:
2313 realActivity = ComponentName.unflattenFromString(attrValue);
2314 break;
2315 case ATTR_REALACTIVITY_SUSPENDED:
2316 realActivitySuspended = Boolean.valueOf(attrValue);
2317 break;
2318 case ATTR_ORIGACTIVITY:
2319 origActivity = ComponentName.unflattenFromString(attrValue);
2320 break;
2321 case ATTR_AFFINITY:
2322 affinity = attrValue;
2323 break;
2324 case ATTR_ROOT_AFFINITY:
2325 rootAffinity = attrValue;
2326 hasRootAffinity = true;
2327 break;
2328 case ATTR_ROOTHASRESET:
2329 rootHasReset = Boolean.parseBoolean(attrValue);
2330 break;
2331 case ATTR_AUTOREMOVERECENTS:
2332 autoRemoveRecents = Boolean.parseBoolean(attrValue);
2333 break;
2334 case ATTR_ASKEDCOMPATMODE:
2335 askedCompatMode = Boolean.parseBoolean(attrValue);
2336 break;
2337 case ATTR_USERID:
2338 userId = Integer.parseInt(attrValue);
2339 break;
2340 case ATTR_USER_SETUP_COMPLETE:
2341 userSetupComplete = Boolean.parseBoolean(attrValue);
2342 break;
2343 case ATTR_EFFECTIVE_UID:
2344 effectiveUid = Integer.parseInt(attrValue);
2345 break;
2346 case ATTR_TASKTYPE:
2347 taskType = Integer.parseInt(attrValue);
2348 break;
2349 case ATTR_LASTDESCRIPTION:
2350 lastDescription = attrValue;
2351 break;
2352 case ATTR_LASTTIMEMOVED:
2353 lastTimeOnTop = Long.parseLong(attrValue);
2354 break;
2355 case ATTR_NEVERRELINQUISH:
2356 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
2357 break;
2358 case ATTR_TASK_AFFILIATION:
2359 taskAffiliation = Integer.parseInt(attrValue);
2360 break;
2361 case ATTR_PREV_AFFILIATION:
2362 prevTaskId = Integer.parseInt(attrValue);
2363 break;
2364 case ATTR_NEXT_AFFILIATION:
2365 nextTaskId = Integer.parseInt(attrValue);
2366 break;
2367 case ATTR_TASK_AFFILIATION_COLOR:
2368 taskAffiliationColor = Integer.parseInt(attrValue);
2369 break;
2370 case ATTR_CALLING_UID:
2371 callingUid = Integer.parseInt(attrValue);
2372 break;
2373 case ATTR_CALLING_PACKAGE:
2374 callingPackage = attrValue;
2375 break;
2376 case ATTR_RESIZE_MODE:
2377 resizeMode = Integer.parseInt(attrValue);
2378 break;
2379 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
2380 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
2381 break;
2382 case ATTR_NON_FULLSCREEN_BOUNDS:
Garfield Tan367b35a2017-12-13 12:16:21 -08002383 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002384 break;
2385 case ATTR_MIN_WIDTH:
2386 minWidth = Integer.parseInt(attrValue);
2387 break;
2388 case ATTR_MIN_HEIGHT:
2389 minHeight = Integer.parseInt(attrValue);
2390 break;
2391 case ATTR_PERSIST_TASK_VERSION:
2392 persistTaskVersion = Integer.parseInt(attrValue);
2393 break;
2394 default:
2395 if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
2396 taskDescription.restoreFromXml(attrName, attrValue);
2397 } else {
2398 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
2399 }
2400 }
2401 }
2402
2403 int event;
2404 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
2405 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
2406 if (event == XmlPullParser.START_TAG) {
2407 final String name = in.getName();
2408 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
2409 "TaskRecord: START_TAG name=" + name);
2410 if (TAG_AFFINITYINTENT.equals(name)) {
2411 affinityIntent = Intent.restoreFromXml(in);
2412 } else if (TAG_INTENT.equals(name)) {
2413 intent = Intent.restoreFromXml(in);
2414 } else if (TAG_ACTIVITY.equals(name)) {
2415 ActivityRecord activity =
2416 ActivityRecord.restoreFromXml(in, stackSupervisor);
2417 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
2418 activity);
2419 if (activity != null) {
2420 activities.add(activity);
2421 }
2422 } else {
Garfield Tan1e740192017-12-12 14:37:42 -08002423 handleUnknownTag(name, in);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002424 }
2425 }
2426 }
2427 if (!hasRootAffinity) {
2428 rootAffinity = affinity;
2429 } else if ("@".equals(rootAffinity)) {
2430 rootAffinity = null;
2431 }
2432 if (effectiveUid <= 0) {
2433 Intent checkIntent = intent != null ? intent : affinityIntent;
2434 effectiveUid = 0;
2435 if (checkIntent != null) {
2436 IPackageManager pm = AppGlobals.getPackageManager();
2437 try {
2438 ApplicationInfo ai = pm.getApplicationInfo(
2439 checkIntent.getComponent().getPackageName(),
2440 PackageManager.MATCH_UNINSTALLED_PACKAGES
2441 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
2442 if (ai != null) {
2443 effectiveUid = ai.uid;
2444 }
2445 } catch (RemoteException e) {
2446 }
2447 }
2448 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
2449 + ": effectiveUid=" + effectiveUid);
2450 }
2451
2452 if (persistTaskVersion < 1) {
2453 // We need to convert the resize mode of home activities saved before version one if
2454 // they are marked as RESIZE_MODE_RESIZEABLE to
2455 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
2456 // before version 1 and the system didn't resize home activities before then.
2457 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
2458 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
2459 }
2460 } else {
2461 // This activity has previously marked itself explicitly as both resizeable and
2462 // supporting picture-in-picture. Since there is no longer a requirement for
2463 // picture-in-picture activities to be resizeable, we can mark this simply as
2464 // resizeable and supporting picture-in-picture separately.
2465 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
2466 resizeMode = RESIZE_MODE_RESIZEABLE;
2467 supportsPictureInPicture = true;
2468 }
2469 }
2470
2471 final TaskRecord task = create(stackSupervisor.mService, taskId, intent, affinityIntent,
2472 affinity, rootAffinity, realActivity, origActivity, rootHasReset,
2473 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
2474 activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
2475 taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
2476 callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
2477 userSetupComplete, minWidth, minHeight);
Garfield Tan367b35a2017-12-13 12:16:21 -08002478 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
2479 task.setBounds(lastNonFullscreenBounds);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002480
2481 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
2482 activities.get(activityNdx).setTask(task);
2483 }
2484
2485 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
2486 return task;
2487 }
Garfield Tan1e740192017-12-12 14:37:42 -08002488
2489 void handleUnknownTag(String name, XmlPullParser in)
2490 throws IOException, XmlPullParserException {
2491 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
2492 XmlUtils.skipCurrentTag(in);
2493 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002494 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002495}