blob: c7b89d3d47eba7d6f02976c61cc5e1262f096b71 [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 Ogunwalee1fe7fa22016-12-15 18:27:00 -080019import static android.app.ActivityManager.RESIZE_MODE_FORCED;
Winson Chung74666102017-02-22 17:49:24 -080020import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
Jorim Jaggi0a932142016-02-01 17:42:25 -080021import static android.app.ActivityManager.StackId.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;
Steven Timotius4346f0a2017-09-12 11:07:21 -070065import static com.android.server.am.proto.TaskRecordProto.ACTIVITIES;
66import static com.android.server.am.proto.TaskRecordProto.BOUNDS;
67import static com.android.server.am.proto.TaskRecordProto.CONFIGURATION_CONTAINER;
68import static com.android.server.am.proto.TaskRecordProto.FULLSCREEN;
69import static com.android.server.am.proto.TaskRecordProto.ID;
70import static com.android.server.am.proto.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
71import static com.android.server.am.proto.TaskRecordProto.MIN_HEIGHT;
72import static com.android.server.am.proto.TaskRecordProto.MIN_WIDTH;
73import static com.android.server.am.proto.TaskRecordProto.ORIG_ACTIVITY;
74import static com.android.server.am.proto.TaskRecordProto.REAL_ACTIVITY;
75import static com.android.server.am.proto.TaskRecordProto.RESIZE_MODE;
Steven Timotius4346f0a2017-09-12 11:07:21 -070076import static com.android.server.am.proto.TaskRecordProto.STACK_ID;
77import static com.android.server.am.proto.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;
88import android.app.AppGlobals;
89import android.app.IActivityManager;
90import android.content.ComponentName;
91import android.content.Intent;
92import android.content.pm.ActivityInfo;
93import android.content.pm.ApplicationInfo;
94import android.content.pm.IPackageManager;
95import android.content.pm.PackageManager;
96import android.content.res.Configuration;
97import android.graphics.Rect;
98import android.os.Debug;
99import android.os.RemoteException;
Winson Chungfb44d212017-10-04 11:39:10 -0700100import android.os.SystemClock;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200101import android.os.Trace;
102import android.os.UserHandle;
103import android.provider.Settings;
104import android.service.voice.IVoiceInteractionSession;
105import android.util.DisplayMetrics;
106import android.util.Slog;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700107import android.util.proto.ProtoOutputStream;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200108
109import com.android.internal.annotations.VisibleForTesting;
110import com.android.internal.app.IVoiceInteractor;
111import com.android.internal.util.XmlUtils;
Winson Chung61c9e5a2017-10-11 10:39:32 -0700112import com.android.server.am.ActivityStack.ActivityState;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200113import com.android.server.wm.AppWindowContainerController;
114import com.android.server.wm.ConfigurationContainer;
115import com.android.server.wm.StackWindowController;
116import com.android.server.wm.TaskWindowContainerController;
117import com.android.server.wm.TaskWindowContainerListener;
118import com.android.server.wm.WindowManagerService;
119
120import org.xmlpull.v1.XmlPullParser;
121import org.xmlpull.v1.XmlPullParserException;
122import org.xmlpull.v1.XmlSerializer;
123
124import java.io.IOException;
125import java.io.PrintWriter;
126import java.lang.annotation.Retention;
127import java.lang.annotation.RetentionPolicy;
128import java.util.ArrayList;
129import java.util.Objects;
130
Benjamin Franza83859f2017-07-03 16:34:14 +0100131class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800132 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700133 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700134 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
Craig Mautnere0570202015-05-13 13:06:11 -0700135 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700136 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800137
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700138 private static final String ATTR_TASKID = "task_id";
Craig Mautner21d24a22014-04-23 11:45:37 -0700139 private static final String TAG_INTENT = "intent";
140 private static final String TAG_AFFINITYINTENT = "affinity_intent";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700141 private static final String ATTR_REALACTIVITY = "real_activity";
142 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
Craig Mautner21d24a22014-04-23 11:45:37 -0700143 private static final String ATTR_ORIGACTIVITY = "orig_activity";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700144 private static final String TAG_ACTIVITY = "activity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700145 private static final String ATTR_AFFINITY = "affinity";
Dianne Hackborn79228822014-09-16 11:11:23 -0700146 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700147 private static final String ATTR_ROOTHASRESET = "root_has_reset";
Dianne Hackborn13420f22014-07-18 15:43:56 -0700148 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
Craig Mautner21d24a22014-04-23 11:45:37 -0700149 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
150 private static final String ATTR_USERID = "user_id";
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800151 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700152 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700153 @Deprecated
Craig Mautner21d24a22014-04-23 11:45:37 -0700154 private static final String ATTR_TASKTYPE = "task_type";
Craig Mautner21d24a22014-04-23 11:45:37 -0700155 private static final String ATTR_LASTDESCRIPTION = "last_description";
156 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700157 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700158 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
Craig Mautnera228ae92014-07-09 05:44:55 -0700159 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
160 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
Winson Chungec396d62014-08-06 17:08:00 -0700161 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700162 private static final String ATTR_CALLING_UID = "calling_uid";
163 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Winson Chungd3395382016-12-13 11:49:09 -0800164 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800165 private static final String ATTR_RESIZE_MODE = "resize_mode";
Wale Ogunwale706ed792015-08-02 10:29:44 -0700166 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700167 private static final String ATTR_MIN_WIDTH = "min_width";
168 private static final String ATTR_MIN_HEIGHT = "min_height";
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700169 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Andrii Kulian18d75122016-03-27 20:20:28 -0700170
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700171 // Current version of the task record we persist. Used to check if we need to run any upgrade
172 // code.
173 private static final int PERSIST_TASK_VERSION = 1;
Craig Mautner21d24a22014-04-23 11:45:37 -0700174
Wale Ogunwale18795a22014-12-03 11:38:33 -0800175 static final int INVALID_TASK_ID = -1;
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700176 private static final int INVALID_MIN_SIZE = -1;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800177
Winson Chung74666102017-02-22 17:49:24 -0800178 /**
179 * The modes to control how the stack is moved to the front when calling
180 * {@link TaskRecord#reparent}.
181 */
182 @Retention(RetentionPolicy.SOURCE)
183 @IntDef({
184 REPARENT_MOVE_STACK_TO_FRONT,
185 REPARENT_KEEP_STACK_AT_FRONT,
186 REPARENT_LEAVE_STACK_IN_PLACE
187 })
Wale Ogunwale66e16852017-10-19 13:35:52 -0700188 @interface ReparentMoveStackMode {}
Winson Chung74666102017-02-22 17:49:24 -0800189 // Moves the stack to the front if it was not at the front
Wale Ogunwale66e16852017-10-19 13:35:52 -0700190 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
Winson Chung74666102017-02-22 17:49:24 -0800191 // Only moves the stack to the front if it was focused or front most already
Wale Ogunwale66e16852017-10-19 13:35:52 -0700192 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
Winson Chung74666102017-02-22 17:49:24 -0800193 // Do not move the stack as a part of reparenting
Wale Ogunwale66e16852017-10-19 13:35:52 -0700194 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
Winson Chung74666102017-02-22 17:49:24 -0800195
Garfield Tan9b1efea2017-12-05 16:43:46 -0800196 /**
197 * The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}.
198 */
199 private static TaskRecordFactory sTaskRecordFactory;
200
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 final int taskId; // Unique identifier for this task.
Dianne Hackborn79228822014-09-16 11:11:23 -0700202 String affinity; // The affinity name for this task, or null; may change identity.
203 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Dianne Hackborn91097de2014-04-04 18:02:06 -0700204 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
205 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 Intent intent; // The original intent that started the task.
207 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700208 int effectiveUid; // The current effective uid of the identity of this task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800209 ComponentName origActivity; // The non-alias activity component of the intent.
210 ComponentName realActivity; // The actual activity component that started the task.
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +0000211 boolean realActivitySuspended; // True if the actual activity component that started the
212 // task is suspended.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700213 boolean inRecents; // Actually in the recents list?
Winson Chungfb44d212017-10-04 11:39:10 -0700214 long lastActiveTime; // Last time this task was active in the current device session,
215 // including sleep. This time is initialized to the elapsed time when
216 // restored from disk.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700217 boolean isAvailable; // Is the activity available to be launched?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 boolean rootWasReset; // True if the intent at the root of the task had
219 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700220 boolean autoRemoveRecents; // If true, we should automatically remove the task from
221 // recents when activity finishes
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700222 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700223 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 -0800224
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700225 String stringName; // caching of toString() result.
Dianne Hackborn9da2d402012-03-15 13:43:08 -0700226 int userId; // user for which this task was created
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800227 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
228 // was changed.
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800229
230 int numFullscreen; // Number of fullscreen activities.
231
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800232 int mResizeMode; // The resize mode of this task and its activities.
233 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800234 private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
235 // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
236 // of the root activity.
Craig Mautner15df08a2015-04-01 12:17:18 -0700237 /** Can't be put in lockTask mode. */
238 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
Benjamin Franz469dd582015-06-09 14:24:36 +0100239 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700240 final static int LOCK_TASK_AUTH_PINNABLE = 1;
241 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
242 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
Benjamin Franz469dd582015-06-09 14:24:36 +0100243 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700244 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
Benjamin Franz469dd582015-06-09 14:24:36 +0100245 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
246 * lockTask task. */
247 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
Craig Mautner15df08a2015-04-01 12:17:18 -0700248 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
249
250 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800251
Winson Chung03a9bae2014-05-02 09:56:12 -0700252 // This represents the last resolved activity values for this task
253 // NOTE: This value needs to be persisted with each task
Craig Mautner648f69b2014-09-18 14:16:26 -0700254 TaskDescription lastTaskDescription = new TaskDescription();
Winson Chung03a9bae2014-05-02 09:56:12 -0700255
Craig Mautnerd2328952013-03-05 12:46:26 -0800256 /** List of all activities in the task arranged in history order */
Craig Mautner21d24a22014-04-23 11:45:37 -0700257 final ArrayList<ActivityRecord> mActivities;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800258
Andrii Kulian02b7a832016-10-06 23:11:56 -0700259 /** Current stack. Setter must always be used to update the value. */
260 private ActivityStack mStack;
Craig Mautnerd2328952013-03-05 12:46:26 -0800261
Dianne Hackborn68a06332017-11-15 17:54:18 -0800262 /** The process that had previously hosted the root activity of this task.
263 * Used to know that we should try harder to keep this process around, in case the
264 * user wants to return to it. */
265 private ProcessRecord mRootProcess;
266
Craig Mautner21d24a22014-04-23 11:45:37 -0700267 /** Takes on same value as first root activity */
268 boolean isPersistable = false;
Craig Mautnerffcfcaa2014-06-05 09:54:38 -0700269 int maxRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700270
271 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
272 * determining the order when restoring. Sign indicates whether last task movement was to front
273 * (positive) or back (negative). Absolute value indicates time. */
274 long mLastTimeMoved = System.currentTimeMillis();
275
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700276 /** If original intent did not allow relinquishing task identity, save that information */
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700277 private boolean mNeverRelinquishIdentity = true;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700278
Craig Mautner362449a2014-06-20 14:04:39 -0700279 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
280 // do not want to delete the stack when the task goes empty.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800281 private boolean mReuseTask = false;
Craig Mautner362449a2014-06-20 14:04:39 -0700282
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700283 CharSequence lastDescription; // Last description captured for this item.
284
Craig Mautnera228ae92014-07-09 05:44:55 -0700285 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Winson Chungec396d62014-08-06 17:08:00 -0700286 int mAffiliatedTaskColor; // color of the parent task affiliation.
Craig Mautnera228ae92014-07-09 05:44:55 -0700287 TaskRecord mPrevAffiliate; // previous task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800288 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700289 TaskRecord mNextAffiliate; // next task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800290 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700291
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700292 // For relaunching the task from recents as though it was launched by the original launcher.
293 int mCallingUid;
294 String mCallingPackage;
295
Craig Mautner21d24a22014-04-23 11:45:37 -0700296 final ActivityManagerService mService;
297
Jorim Jaggi82c9dc92016-02-05 15:10:33 -0800298 private final Rect mTmpStableBounds = new Rect();
299 private final Rect mTmpNonDecorBounds = new Rect();
Wale Ogunwale9a08f822016-02-17 19:03:58 -0800300 private final Rect mTmpRect = new Rect();
Jorim Jaggi0a932142016-02-01 17:42:25 -0800301
Wale Ogunwale706ed792015-08-02 10:29:44 -0700302 // Last non-fullscreen bounds the task was launched in or resized to.
303 // The information is persisted and used to determine the appropriate stack to launch the
304 // task into on restore.
305 Rect mLastNonFullscreenBounds = null;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700306 // Minimal width and height of this task when it's resizeable. -1 means it should use the
307 // default minimal width/height.
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700308 int mMinWidth;
309 int mMinHeight;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700310
Chong Zhangfdcc4d42015-10-14 16:50:12 -0700311 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
312 // This number will be assigned when we evaluate OOM scores for all visible tasks.
313 int mLayerRank = -1;
314
Andrii Kulian1779e612016-10-12 21:58:25 -0700315 /** Helper object used for updating override configuration. */
316 private Configuration mTmpConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700317
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800318 private TaskWindowContainerController mWindowContainerController;
319
Garfield Tan9b1efea2017-12-05 16:43:46 -0800320 /**
321 * Don't use constructor directly. Use {@link #create(ActivityManagerService, int, ActivityInfo,
322 * Intent, TaskDescription)} instead.
323 */
Craig Mautner21d24a22014-04-23 11:45:37 -0700324 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700325 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700326 mService = service;
Suprabh Shukla23593142015-11-03 17:31:15 -0800327 userId = UserHandle.getUserId(info.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 taskId = _taskId;
Winson Chungfb44d212017-10-04 11:39:10 -0700329 lastActiveTime = SystemClock.elapsedRealtime();
Craig Mautnera228ae92014-07-09 05:44:55 -0700330 mAffiliatedTaskId = _taskId;
Dianne Hackborn91097de2014-04-04 18:02:06 -0700331 voiceSession = _voiceSession;
332 voiceInteractor = _voiceInteractor;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700333 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800334 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700335 mCallingUid = info.applicationInfo.uid;
336 mCallingPackage = info.packageName;
Martijn Coenend4a69702014-06-30 11:12:17 -0700337 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700338 setMinDimensions(info);
Winson730bf062016-03-31 18:04:56 -0700339 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700340 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Craig Mautner21d24a22014-04-23 11:45:37 -0700341 }
342
Garfield Tan9b1efea2017-12-05 16:43:46 -0800343 /**
344 * Don't use constructor directly. Use {@link #create(ActivityManagerService, int, ActivityInfo,
345 * Intent, IVoiceInteractionSession, IVoiceInteractor)} instead.
346 */
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700347 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200348 TaskDescription _taskDescription) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700349 mService = service;
Suprabh Shukla23593142015-11-03 17:31:15 -0800350 userId = UserHandle.getUserId(info.applicationInfo.uid);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700351 taskId = _taskId;
Winson Chungfb44d212017-10-04 11:39:10 -0700352 lastActiveTime = SystemClock.elapsedRealtime();
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700353 mAffiliatedTaskId = _taskId;
354 voiceSession = null;
355 voiceInteractor = null;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700356 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800357 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700358 mCallingUid = info.applicationInfo.uid;
359 mCallingPackage = info.packageName;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700360 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700361 setMinDimensions(info);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700362
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700363 isPersistable = true;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700364 // Clamp to [1, max].
365 maxRecents = Math.min(Math.max(info.maxRecents, 1),
366 ActivityManager.getMaxAppRecentsLimitStatic());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700367
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700368 lastTaskDescription = _taskDescription;
Winson730bf062016-03-31 18:04:56 -0700369 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700370 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700371 }
372
Garfield Tan9b1efea2017-12-05 16:43:46 -0800373 /**
374 * Don't use constructor directly. This is only used by XML parser.
375 */
376 TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800377 Intent _affinityIntent, String _affinity, String _rootAffinity,
378 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700379 boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800380 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
Winson Chungfb44d212017-10-04 11:39:10 -0700381 long lastTimeMoved, boolean neverRelinquishIdentity,
382 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
383 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Charles He2bf28322017-10-12 22:24:49 +0100384 int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
385 boolean userSetupComplete, int minWidth, int minHeight) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700386 mService = service;
387 taskId = _taskId;
388 intent = _intent;
389 affinityIntent = _affinityIntent;
390 affinity = _affinity;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800391 rootAffinity = _rootAffinity;
Craig Mautner21d24a22014-04-23 11:45:37 -0700392 voiceSession = null;
393 voiceInteractor = null;
394 realActivity = _realActivity;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800395 realActivitySuspended = _realActivitySuspended;
Craig Mautner21d24a22014-04-23 11:45:37 -0700396 origActivity = _origActivity;
397 rootWasReset = _rootWasReset;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700398 isAvailable = true;
Dianne Hackborn13420f22014-07-18 15:43:56 -0700399 autoRemoveRecents = _autoRemoveRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700400 askedCompatMode = _askedCompatMode;
Craig Mautner21d24a22014-04-23 11:45:37 -0700401 userId = _userId;
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800402 mUserSetupComplete = userSetupComplete;
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700403 effectiveUid = _effectiveUid;
Winson Chungfb44d212017-10-04 11:39:10 -0700404 lastActiveTime = SystemClock.elapsedRealtime();
Craig Mautner21d24a22014-04-23 11:45:37 -0700405 lastDescription = _lastDescription;
406 mActivities = activities;
407 mLastTimeMoved = lastTimeMoved;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700408 mNeverRelinquishIdentity = neverRelinquishIdentity;
Winson Chung2cb86c72014-06-25 12:03:30 -0700409 lastTaskDescription = _lastTaskDescription;
Craig Mautnera228ae92014-07-09 05:44:55 -0700410 mAffiliatedTaskId = taskAffiliation;
Winson Chungec396d62014-08-06 17:08:00 -0700411 mAffiliatedTaskColor = taskAffiliationColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700412 mPrevAffiliateTaskId = prevTaskId;
413 mNextAffiliateTaskId = nextTaskId;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700414 mCallingUid = callingUid;
415 mCallingPackage = callingPackage;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800416 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800417 mSupportsPictureInPicture = supportsPictureInPicture;
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700418 mMinWidth = minWidth;
419 mMinHeight = minHeight;
Yorke Leebd54c2a2016-10-25 13:49:23 -0700420 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 }
422
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800423 TaskWindowContainerController getWindowContainerController() {
424 return mWindowContainerController;
425 }
426
427 void createWindowContainer(boolean onTop, boolean showForAllUsers) {
428 if (mWindowContainerController != null) {
429 throw new IllegalArgumentException("Window container=" + mWindowContainerController
430 + " already created for task=" + this);
431 }
432
433 final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
Bryce Lee04ab3462017-04-10 15:06:33 -0700434 setWindowContainerController(new TaskWindowContainerController(taskId, this,
Wale Ogunwale034a8ec2017-09-02 17:14:40 -0700435 getStack().getWindowContainerController(), userId, bounds,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700436 mResizeMode, mSupportsPictureInPicture, onTop,
437 showForAllUsers, lastTaskDescription));
Bryce Lee04ab3462017-04-10 15:06:33 -0700438 }
439
440 /**
441 * Should only be invoked from {@link #createWindowContainer(boolean, boolean)}.
442 */
443 @VisibleForTesting
444 protected void setWindowContainerController(TaskWindowContainerController controller) {
445 if (mWindowContainerController != null) {
446 throw new IllegalArgumentException("Window container=" + mWindowContainerController
447 + " already created for task=" + this);
448 }
449
450 mWindowContainerController = controller;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800451 }
452
453 void removeWindowContainer() {
Charles Heff9b4dff2017-09-22 10:18:37 +0100454 mService.mLockTaskController.clearLockedTask(this);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800455 mWindowContainerController.removeContainer();
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700456 if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800457 // Reset current bounds for task whose bounds shouldn't be persisted so it uses
458 // default configuration the next time it launches.
459 updateOverrideConfiguration(null);
460 }
461 mService.mTaskChangeNotificationController.notifyTaskRemoved(taskId);
462 mWindowContainerController = null;
463 }
464
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100465 @Override
466 public void onSnapshotChanged(TaskSnapshot snapshot) {
467 mService.mTaskChangeNotificationController.notifyTaskSnapshotChanged(taskId, snapshot);
468 }
469
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800470 void setResizeMode(int resizeMode) {
471 if (mResizeMode == resizeMode) {
472 return;
473 }
474 mResizeMode = resizeMode;
475 mWindowContainerController.setResizeable(resizeMode);
476 mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
477 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
478 }
479
480 void setTaskDockedResizing(boolean resizing) {
481 mWindowContainerController.setTaskDockedResizing(resizing);
482 }
483
Wale Ogunwale1666e312016-12-16 11:27:18 -0800484 // TODO: Consolidate this with the resize() method below.
485 @Override
486 public void requestResize(Rect bounds, int resizeMode) {
487 mService.resizeTask(taskId, bounds, resizeMode);
488 }
489
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800490 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800491 mService.mWindowManager.deferSurfaceLayout();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800492
Bryce Leef3c6a472017-11-14 14:53:06 -0800493 try {
494 if (!isResizeable()) {
495 Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
496 return true;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800497 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800498
Bryce Leef3c6a472017-11-14 14:53:06 -0800499 // If this is a forced resize, let it go through even if the bounds is not changing,
500 // as we might need a relayout due to surface size change (to/from fullscreen).
501 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
502 if (equivalentOverrideBounds(bounds) && !forced) {
503 // Nothing to do here...
504 return true;
505 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800506
Bryce Leef3c6a472017-11-14 14:53:06 -0800507 if (mWindowContainerController == null) {
508 // Task doesn't exist in window manager yet (e.g. was restored from recents).
509 // All we can do for now is update the bounds so it can be used when the task is
510 // added to window manager.
511 updateOverrideConfiguration(bounds);
512 if (!inFreeformWindowingMode()) {
513 // re-restore the task so it can have the proper stack association.
514 mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
515 }
516 return true;
517 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800518
Bryce Leef3c6a472017-11-14 14:53:06 -0800519 if (!canResizeToBounds(bounds)) {
520 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
521 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
522 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800523
Bryce Leef3c6a472017-11-14 14:53:06 -0800524 // Do not move the task to another stack here.
525 // This method assumes that the task is already placed in the right stack.
526 // we do not mess with that decision and we only do the resize!
527
528 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId);
529
530 final boolean updatedConfig = updateOverrideConfiguration(bounds);
531 // This variable holds information whether the configuration didn't change in a significant
532
533 // way and the activity was kept the way it was. If it's false, it means the activity
534 // had
535 // to be relaunched due to configuration change.
536 boolean kept = true;
537 if (updatedConfig) {
538 final ActivityRecord r = topRunningActivityLocked();
539 if (r != null && !deferResume) {
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800540 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
Bryce Leef3c6a472017-11-14 14:53:06 -0800541 preserveWindow);
542 mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0,
543 !PRESERVE_WINDOWS);
544 if (!kept) {
545 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
546 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800547 }
548 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800549 mWindowContainerController.resize(kept, forced);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800550
Bryce Leef3c6a472017-11-14 14:53:06 -0800551 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
552 return kept;
553 } finally {
554 mService.mWindowManager.continueSurfaceLayout();
555 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800556 }
557
558 // TODO: Investigate combining with the resize() method above.
559 void resizeWindowContainer() {
Bryce Leef3c6a472017-11-14 14:53:06 -0800560 mWindowContainerController.resize(false /* relayout */, false /* forced */);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800561 }
562
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800563 void getWindowContainerBounds(Rect bounds) {
564 mWindowContainerController.getBounds(bounds);
565 }
566
Winson Chung74666102017-02-22 17:49:24 -0800567 /**
568 * Convenience method to reparent a task to the top or bottom position of the stack.
569 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700570 boolean reparent(ActivityStack preferredStack, boolean toTop,
571 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
572 String reason) {
573 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
574 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung5af42fc2017-03-24 17:11:33 -0700575 }
576
577 /**
578 * Convenience method to reparent a task to the top or bottom position of the stack, with
579 * an option to skip scheduling the picture-in-picture mode change.
580 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700581 boolean reparent(ActivityStack preferredStack, boolean toTop,
582 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
583 boolean schedulePictureInPictureModeChange, String reason) {
584 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
Winson Chung5af42fc2017-03-24 17:11:33 -0700585 deferResume, schedulePictureInPictureModeChange, reason);
586 }
587
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700588 /** Convenience method to reparent a task to a specific position of the stack. */
589 boolean reparent(ActivityStack preferredStack, int position,
590 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
591 String reason) {
592 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
Winson Chung5af42fc2017-03-24 17:11:33 -0700593 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800594 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800595
Winson Chung74666102017-02-22 17:49:24 -0800596 /**
597 * Reparents the task into a preferred stack, creating it if necessary.
598 *
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700599 * @param preferredStack the target stack to move this task
Winson Chung74666102017-02-22 17:49:24 -0800600 * @param position the position to place this task in the new stack
601 * @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 -0700602 * reparenting to be drawn and animated in
Winson Chung74666102017-02-22 17:49:24 -0800603 * @param moveStackMode whether or not to move the stack to the front always, only if it was
Winson Chung5af42fc2017-03-24 17:11:33 -0700604 * previously focused & in front, or never
Winson Chung74666102017-02-22 17:49:24 -0800605 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
Winson Chung5af42fc2017-03-24 17:11:33 -0700606 * have changed as a result of this reparenting
607 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
608 * change. Callers may set this to false if they are explicitly scheduling PiP mode
609 * changes themselves, like during the PiP animation
Winson Chung74666102017-02-22 17:49:24 -0800610 * @param reason the caller of this reparenting
Winson Chung5af42fc2017-03-24 17:11:33 -0700611 * @return whether the task was reparented
Winson Chung74666102017-02-22 17:49:24 -0800612 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700613 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700614 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700615 boolean reparent(ActivityStack preferredStack, int position,
616 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
617 boolean schedulePictureInPictureModeChange, String reason) {
Winson Chung74666102017-02-22 17:49:24 -0800618 final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
619 final WindowManagerService windowManager = mService.mWindowManager;
620 final ActivityStack sourceStack = getStack();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700621 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
Winson Chung74666102017-02-22 17:49:24 -0800622 position == MAX_VALUE);
623 if (toStack == sourceStack) {
624 return false;
625 }
Andrii Kulianb850ea52017-12-12 23:49:10 -0800626 if (!canBeLaunchedOnDisplay(toStack.mDisplayId)) {
627 return false;
628 }
Winson Chung74666102017-02-22 17:49:24 -0800629
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700630 final int toStackWindowingMode = toStack.getWindowingMode();
Winson Chung74666102017-02-22 17:49:24 -0800631 final ActivityRecord topActivity = getTopActivity();
632
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800633 final boolean mightReplaceWindow = topActivity != null
634 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
Winson Chung74666102017-02-22 17:49:24 -0800635 if (mightReplaceWindow) {
636 // We are about to relaunch the activity because its configuration changed due to
637 // being maximized, i.e. size change. The activity will first remove the old window
638 // and then add a new one. This call will tell window manager about this, so it can
639 // preserve the old window until the new one is drawn. This prevents having a gap
640 // between the removal and addition, in which no window is visible. We also want the
641 // entrance of the new window to be properly animated.
642 // Note here we always set the replacing window first, as the flags might be needed
643 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
644 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
645 }
646
647 windowManager.deferSurfaceLayout();
648 boolean kept = true;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800649 try {
Winson Chung74666102017-02-22 17:49:24 -0800650 final ActivityRecord r = topRunningActivityLocked();
Winson Chung95f8f0e2017-03-24 09:20:17 -0700651 final boolean wasFocused = r != null && supervisor.isFocusedStack(sourceStack)
Winson Chung74666102017-02-22 17:49:24 -0800652 && (topRunningActivityLocked() == r);
Bryce Leec4ab62a2018-03-05 14:19:26 -0800653 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
Winson Chung95f8f0e2017-03-24 09:20:17 -0700654 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
Winson Chung74666102017-02-22 17:49:24 -0800655
656 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
657 // Whenever we are moving the top activity from the front stack we want to make sure to
658 // move the stack to the front.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700659 final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
Winson Chung74666102017-02-22 17:49:24 -0800660 && (sourceStack.topRunningActivityLocked() == r);
661
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800662 // Adjust the position for the new parent stack as needed.
Winson Chung74666102017-02-22 17:49:24 -0800663 position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800664
665 // Must reparent first in window manager to avoid a situation where AM can delete the
666 // we are coming from in WM before we reparent because it became empty.
Wale Ogunwale2719cc12017-04-14 09:45:27 -0700667 mWindowContainerController.reparent(toStack.getWindowContainerController(), position,
668 moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800669
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700670 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
671 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
Winson Chung74666102017-02-22 17:49:24 -0800672 // Move the task
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700673 sourceStack.removeTask(this, reason, moveStackToFront
674 ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
Winson Chung5af42fc2017-03-24 17:11:33 -0700675 toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800676
Winson Chung5af42fc2017-03-24 17:11:33 -0700677 if (schedulePictureInPictureModeChange) {
678 // Notify of picture-in-picture mode changes
679 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
680 }
Winson Chung74666102017-02-22 17:49:24 -0800681
682 // TODO: Ensure that this is actually necessary here
683 // Notify the voice session if required
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800684 if (voiceSession != null) {
685 try {
686 voiceSession.taskStarted(intent, taskId);
687 } catch (RemoteException e) {
688 }
689 }
Winson Chung74666102017-02-22 17:49:24 -0800690
691 // If the task had focus before (or we're requested to move focus), move focus to the
692 // new stack by moving the stack to the front.
Winson Chung95f8f0e2017-03-24 09:20:17 -0700693 if (r != null) {
694 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
695 wasPaused, reason);
696 }
Winson Chung74666102017-02-22 17:49:24 -0800697 if (!animate) {
Jorim Jaggifa9ed962018-01-25 00:16:49 +0100698 mService.mStackSupervisor.mNoAnimActivities.add(topActivity);
Winson Chung74666102017-02-22 17:49:24 -0800699 }
700
701 // We might trigger a configuration change. Save the current task bounds for freezing.
702 // TODO: Should this call be moved inside the resize method in WM?
703 toStack.prepareFreezingTaskBounds();
704
705 // Make sure the task has the appropriate bounds/size for the stack it is in.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700706 final boolean toStackSplitScreenPrimary =
707 toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Bryce Leef3c6a472017-11-14 14:53:06 -0800708 final Rect configBounds = getOverrideBounds();
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700709 if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
710 || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
Bryce Leef3c6a472017-11-14 14:53:06 -0800711 && !Objects.equals(configBounds, toStack.getOverrideBounds())) {
712 kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
Winson Chung74666102017-02-22 17:49:24 -0800713 deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700714 } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Winson Chung74666102017-02-22 17:49:24 -0800715 Rect bounds = getLaunchBounds();
716 if (bounds == null) {
Bryce Leeec55eb02017-12-05 20:51:27 -0800717 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Bryce Leef3c6a472017-11-14 14:53:06 -0800718 bounds = configBounds;
Winson Chung74666102017-02-22 17:49:24 -0800719 }
720 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700721 } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
722 if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
Matthew Ng330757d2017-02-28 14:19:17 -0800723 // Move recents to front so it is not behind home stack when going into docked
724 // mode
725 mService.mStackSupervisor.moveRecentsStackToFront(reason);
726 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800727 kept = resize(toStack.getOverrideBounds(), RESIZE_MODE_SYSTEM, !mightReplaceWindow,
Winson Chung74666102017-02-22 17:49:24 -0800728 deferResume);
729 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800730 } finally {
Winson Chung74666102017-02-22 17:49:24 -0800731 windowManager.continueSurfaceLayout();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800732 }
Winson Chung74666102017-02-22 17:49:24 -0800733
734 if (mightReplaceWindow) {
735 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
736 // window), we need to clear the replace window settings. Otherwise, we schedule a
737 // timeout to remove the old window if the replacing window is not coming in time.
738 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
739 }
740
741 if (!deferResume) {
742 // The task might have already been running and its visibility needs to be synchronized
743 // with the visibility of the stack / windows.
744 supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
745 supervisor.resumeFocusedStackTopActivityLocked();
746 }
747
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700748 // TODO: Handle incorrect request to move before the actual move, not after.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700749 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700750 DEFAULT_DISPLAY, toStack);
Winson Chung74666102017-02-22 17:49:24 -0800751
Winson Chungdff7a732017-12-11 12:17:06 -0800752 return (preferredStack == toStack);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800753 }
754
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700755 /**
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800756 * @return True if the windows of tasks being moved to the target stack from the source stack
757 * should be replaced, meaning that window manager will keep the old window around until the new
758 * is ready.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700759 */
760 private static boolean replaceWindowsOnTaskMove(
761 int sourceWindowingMode, int targetWindowingMode) {
762 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
763 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
764 }
765
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800766 void cancelWindowTransition() {
767 mWindowContainerController.cancelWindowTransition();
768 }
769
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100770 /**
771 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
772 */
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100773 TaskSnapshot getSnapshot(boolean reducedResolution) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100774
775 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
776 // synchronized between AM and WM.
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100777 return mService.mWindowManager.getTaskSnapshot(taskId, userId, reducedResolution);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800778 }
779
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800780 void touchActiveTime() {
Winson Chungfb44d212017-10-04 11:39:10 -0700781 lastActiveTime = SystemClock.elapsedRealtime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700783
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784 long getInactiveDuration() {
Winson Chungfb44d212017-10-04 11:39:10 -0700785 return SystemClock.elapsedRealtime() - lastActiveTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800786 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700787
Winson Chungfee26772014-08-05 12:21:52 -0700788 /** Sets the original intent, and the calling uid and package. */
789 void setIntent(ActivityRecord r) {
Winson Chungfee26772014-08-05 12:21:52 -0700790 mCallingUid = r.launchedFromUid;
791 mCallingPackage = r.launchedFromPackage;
Craig Mautner15df08a2015-04-01 12:17:18 -0700792 setIntent(r.intent, r.info);
Charles He2bf28322017-10-12 22:24:49 +0100793 setLockTaskAuth(r);
Winson Chungfee26772014-08-05 12:21:52 -0700794 }
795
796 /** Sets the original intent, _without_ updating the calling uid or package. */
797 private void setIntent(Intent _intent, ActivityInfo info) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700798 if (intent == null) {
799 mNeverRelinquishIdentity =
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700800 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700801 } else if (mNeverRelinquishIdentity) {
802 return;
803 }
804
805 affinity = info.taskAffinity;
Dianne Hackborn79228822014-09-16 11:11:23 -0700806 if (intent == null) {
807 // If this task already has an intent associated with it, don't set the root
808 // affinity -- we don't want it changing after initially set, but the initially
809 // set value may be null.
810 rootAffinity = affinity;
811 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700812 effectiveUid = info.applicationInfo.uid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700813 stringName = null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800814
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800815 if (info.targetActivity == null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800816 if (_intent != null) {
817 // If this Intent has a selector, we want to clear it for the
818 // recent task since it is not relevant if the user later wants
819 // to re-launch the app.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700820 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800821 _intent = new Intent(_intent);
822 _intent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700823 _intent.setSourceBounds(null);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800824 }
825 }
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700826 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800827 intent = _intent;
828 realActivity = _intent != null ? _intent.getComponent() : null;
829 origActivity = null;
830 } else {
831 ComponentName targetComponent = new ComponentName(
832 info.packageName, info.targetActivity);
833 if (_intent != null) {
834 Intent targetIntent = new Intent(_intent);
835 targetIntent.setComponent(targetComponent);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800836 targetIntent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700837 targetIntent.setSourceBounds(null);
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700838 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
Dianne Hackborn7f96b792012-05-29 18:46:45 -0700839 "Setting Intent of " + this + " to target " + targetIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800840 intent = targetIntent;
841 realActivity = targetComponent;
842 origActivity = _intent.getComponent();
843 } else {
844 intent = null;
845 realActivity = targetComponent;
846 origActivity = new ComponentName(info.packageName, info.name);
847 }
848 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700849
Craig Mautner47b20ba2014-09-17 17:23:44 -0700850 final int intentFlags = intent == null ? 0 : intent.getFlags();
851 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 // Once we are set to an Intent with this flag, we count this
853 // task as having a true root activity.
854 rootWasReset = true;
855 }
Dianne Hackborn09233282014-04-30 11:33:59 -0700856 userId = UserHandle.getUserId(info.applicationInfo.uid);
Winson Chung36f3f032016-09-08 23:29:43 +0000857 mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
858 USER_SETUP_COMPLETE, 0, userId) != 0;
Craig Mautner41db4a72014-05-07 17:20:56 -0700859 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700860 // If the activity itself has requested auto-remove, then just always do it.
861 autoRemoveRecents = true;
Wale Ogunwale843bfb92015-03-27 11:06:48 -0700862 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
863 == FLAG_ACTIVITY_NEW_DOCUMENT) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700864 // If the caller has not asked for the document to be retained, then we may
865 // want to turn on auto-remove, depending on whether the target has set its
866 // own document launch mode.
867 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
868 autoRemoveRecents = false;
869 } else {
870 autoRemoveRecents = true;
871 }
872 } else {
873 autoRemoveRecents = false;
Craig Mautner41db4a72014-05-07 17:20:56 -0700874 }
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800875 mResizeMode = info.resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800876 mSupportsPictureInPicture = info.supportsPictureInPicture();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800877 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800878
Andrii Kulian2e751b82016-03-16 16:59:32 -0700879 /** Sets the original minimal width and height. */
880 private void setMinDimensions(ActivityInfo info) {
881 if (info != null && info.windowLayout != null) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700882 mMinWidth = info.windowLayout.minWidth;
883 mMinHeight = info.windowLayout.minHeight;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700884 } else {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700885 mMinWidth = INVALID_MIN_SIZE;
886 mMinHeight = INVALID_MIN_SIZE;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700887 }
888 }
889
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800890 /**
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700891 * Return true if the input activity has the same intent filter as the intent this task
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800892 * record is based on (normally the root activity intent).
893 */
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700894 boolean isSameIntentFilter(ActivityRecord r) {
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800895 final Intent intent = new Intent(r.intent);
896 // Correct the activity intent for aliasing. The task record intent will always be based on
897 // the real activity that will be launched not the alias, so we need to use an intent with
898 // the component name pointing to the real activity not the alias in the activity record.
899 intent.setComponent(r.realActivity);
900 return this.intent.filterEquals(intent);
901 }
902
Wale Ogunwale66e16852017-10-19 13:35:52 -0700903 boolean returnsToHomeStack() {
904 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
905 return (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700906 }
907
Craig Mautnera228ae92014-07-09 05:44:55 -0700908 void setPrevAffiliate(TaskRecord prevAffiliate) {
909 mPrevAffiliate = prevAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800910 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700911 }
912
913 void setNextAffiliate(TaskRecord nextAffiliate) {
914 mNextAffiliate = nextAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800915 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700916 }
917
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700918 <T extends ActivityStack> T getStack() {
919 return (T) mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700920 }
921
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800922 /**
923 * Must be used for setting parent stack because it performs configuration updates.
924 * Must be called after adding task as a child to the stack.
925 */
Andrii Kulian02b7a832016-10-06 23:11:56 -0700926 void setStack(ActivityStack stack) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800927 if (stack != null && !stack.isInStackLocked(this)) {
928 throw new IllegalStateException("Task must be added as a Stack child first.");
929 }
Andrii Kulian02b7a832016-10-06 23:11:56 -0700930 mStack = stack;
Andrii Kulian1779e612016-10-12 21:58:25 -0700931 onParentChanged();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700932 }
933
934 /**
935 * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
936 */
937 int getStackId() {
938 return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
939 }
940
Andrii Kulian1779e612016-10-12 21:58:25 -0700941 @Override
942 protected int getChildCount() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700943 return mActivities.size();
Andrii Kulian1779e612016-10-12 21:58:25 -0700944 }
945
946 @Override
chaviw82a0ba82018-03-15 14:26:29 -0700947 protected ActivityRecord getChildAt(int index) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700948 return mActivities.get(index);
Andrii Kulian1779e612016-10-12 21:58:25 -0700949 }
950
951 @Override
952 protected ConfigurationContainer getParent() {
953 return mStack;
954 }
955
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800956 @Override
Wale Ogunwale98d62312017-07-12 09:24:56 -0700957 protected void onParentChanged() {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800958 super.onParentChanged();
959 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
960 }
961
Craig Mautnera228ae92014-07-09 05:44:55 -0700962 // Close up recents linked list.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700963 private void closeRecentsChain() {
Craig Mautnera228ae92014-07-09 05:44:55 -0700964 if (mPrevAffiliate != null) {
965 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
966 }
967 if (mNextAffiliate != null) {
968 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
969 }
970 setPrevAffiliate(null);
971 setNextAffiliate(null);
972 }
973
Winson Chung740c3ac2014-11-12 16:14:38 -0800974 void removedFromRecents() {
Dianne Hackborn852975d2014-08-22 17:42:43 -0700975 closeRecentsChain();
976 if (inRecents) {
977 inRecents = false;
Winson Chung740c3ac2014-11-12 16:14:38 -0800978 mService.notifyTaskPersisterLocked(this, false);
Dianne Hackborn852975d2014-08-22 17:42:43 -0700979 }
Jorim Jaggif9084ec2017-01-16 13:16:59 +0100980
Dianne Hackborn68a06332017-11-15 17:54:18 -0800981 clearRootProcess();
982
Jorim Jaggif9084ec2017-01-16 13:16:59 +0100983 // TODO: Use window container controller once tasks are better synced between AM and WM
984 mService.mWindowManager.notifyTaskRemovedFromRecents(taskId, userId);
Dianne Hackborn852975d2014-08-22 17:42:43 -0700985 }
986
Craig Mautnera228ae92014-07-09 05:44:55 -0700987 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
988 closeRecentsChain();
989 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
Winson Chungec396d62014-08-06 17:08:00 -0700990 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700991 // Find the end
992 while (taskToAffiliateWith.mNextAffiliate != null) {
993 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate;
994 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
995 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
996 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
997 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
998 nextRecents.setPrevAffiliate(null);
999 }
1000 taskToAffiliateWith.setNextAffiliate(null);
1001 break;
1002 }
1003 taskToAffiliateWith = nextRecents;
1004 }
1005 taskToAffiliateWith.setNextAffiliate(this);
1006 setPrevAffiliate(taskToAffiliateWith);
1007 setNextAffiliate(null);
1008 }
1009
Winson Chung1147c402014-05-14 11:05:00 -07001010 /** Returns the intent for the root activity for this task */
1011 Intent getBaseIntent() {
1012 return intent != null ? intent : affinityIntent;
1013 }
1014
Winson Chung3b3f4642014-04-22 10:08:18 -07001015 /** Returns the first non-finishing activity from the root. */
1016 ActivityRecord getRootActivity() {
1017 for (int i = 0; i < mActivities.size(); i++) {
1018 final ActivityRecord r = mActivities.get(i);
1019 if (r.finishing) {
1020 continue;
1021 }
1022 return r;
1023 }
1024 return null;
1025 }
1026
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001027 ActivityRecord getTopActivity() {
Bryce Lee9f6affd2017-09-01 09:18:35 -07001028 return getTopActivity(true /* includeOverlays */);
1029 }
1030
1031 ActivityRecord getTopActivity(boolean includeOverlays) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001032 for (int i = mActivities.size() - 1; i >= 0; --i) {
1033 final ActivityRecord r = mActivities.get(i);
Bryce Lee9f6affd2017-09-01 09:18:35 -07001034 if (r.finishing || (!includeOverlays && r.mTaskOverlay)) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001035 continue;
1036 }
1037 return r;
1038 }
1039 return null;
1040 }
1041
Filip Gruszczynski3e85ba22015-10-05 22:48:30 -07001042 ActivityRecord topRunningActivityLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001043 if (mStack != null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001044 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1045 ActivityRecord r = mActivities.get(activityNdx);
Chong Zhang87761972016-08-22 13:53:24 -07001046 if (!r.finishing && r.okToShowLocked()) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001047 return r;
1048 }
Craig Mautner6b74cb52013-09-27 17:02:21 -07001049 }
1050 }
1051 return null;
1052 }
1053
Jorim Jaggi172e99f2017-10-20 14:33:18 +02001054 boolean isVisible() {
1055 for (int i = mActivities.size() - 1; i >= 0; --i) {
1056 final ActivityRecord r = mActivities.get(i);
1057 if (r.visible) {
1058 return true;
1059 }
1060 }
1061 return false;
1062 }
1063
Jorim Jaggiea039a82017-08-02 14:37:49 +02001064 void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
1065 if (mStack != null) {
1066 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1067 ActivityRecord r = mActivities.get(activityNdx);
Jorim Jaggi02f1d2f2017-08-04 14:29:16 +02001068 if (!r.finishing && r.okToShowLocked() && r.visibleIgnoringKeyguard) {
Jorim Jaggiea039a82017-08-02 14:37:49 +02001069 outActivities.add(r);
1070 }
1071 }
1072 }
1073 }
1074
Wale Ogunwale3b232392016-05-13 15:37:13 -07001075 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001076 if (mStack != null) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001077 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1078 ActivityRecord r = mActivities.get(activityNdx);
1079 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
Chong Zhang87761972016-08-22 13:53:24 -07001080 || r.finishing || !r.okToShowLocked()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001081 continue;
1082 }
1083 return r;
1084 }
1085 }
1086 return null;
1087 }
1088
Winson Chung61c9e5a2017-10-11 10:39:32 -07001089 /**
1090 * Return the number of running activities, and the number of non-finishing/initializing
1091 * activities in the provided {@param reportOut} respectively.
1092 */
1093 void getNumRunningActivities(TaskActivitiesReport reportOut) {
1094 reportOut.reset();
1095 for (int i = mActivities.size() - 1; i >= 0; --i) {
1096 final ActivityRecord r = mActivities.get(i);
1097 if (r.finishing) {
1098 continue;
1099 }
1100
1101 reportOut.base = r;
1102
1103 // Increment the total number of non-finishing activities
1104 reportOut.numActivities++;
1105
Bryce Lee7ace3952018-02-16 14:34:32 -08001106 if (reportOut.top == null || (reportOut.top.isState(ActivityState.INITIALIZING))) {
Winson Chung61c9e5a2017-10-11 10:39:32 -07001107 reportOut.top = r;
1108 // Reset the number of running activities until we hit the first non-initializing
1109 // activity
1110 reportOut.numRunning = 0;
1111 }
1112 if (r.app != null && r.app.thread != null) {
1113 // Increment the number of actually running activities
1114 reportOut.numRunning++;
1115 }
1116 }
1117 }
1118
Chong Zhang87761972016-08-22 13:53:24 -07001119 boolean okToShowLocked() {
1120 // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
1121 // okay to show the activity when locked.
1122 return mService.mStackSupervisor.isCurrentProfileLocked(userId)
1123 || topRunningActivityLocked() != null;
1124 }
1125
Craig Mautner3b475fe2013-12-16 15:58:31 -08001126 /** Call after activity movement or finish to make sure that frontOfTask is set correctly */
Bryce Leed71317c2017-02-07 14:27:22 -08001127 final void setFrontOfTask() {
1128 boolean foundFront = false;
Craig Mautner3b475fe2013-12-16 15:58:31 -08001129 final int numActivities = mActivities.size();
Craig Mautner704e40b2013-12-18 16:43:51 -08001130 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
Craig Mautner3b475fe2013-12-16 15:58:31 -08001131 final ActivityRecord r = mActivities.get(activityNdx);
1132 if (foundFront || r.finishing) {
1133 r.frontOfTask = false;
1134 } else {
1135 r.frontOfTask = true;
1136 // Set frontOfTask false for every following activity.
1137 foundFront = true;
1138 }
1139 }
Craig Mautner9587ee02014-06-23 15:00:10 +00001140 if (!foundFront && numActivities > 0) {
1141 // All activities of this task are finishing. As we ought to have a frontOfTask
1142 // activity, make the bottom activity front.
1143 mActivities.get(0).frontOfTask = true;
1144 }
Craig Mautner3b475fe2013-12-16 15:58:31 -08001145 }
1146
Craig Mautnerde4ef022013-04-07 19:01:33 -07001147 /**
Craig Mautner3b475fe2013-12-16 15:58:31 -08001148 * Reorder the history stack so that the passed activity is brought to the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001149 */
1150 final void moveActivityToFrontLocked(ActivityRecord newTop) {
Wale Ogunwale0fc365c2015-05-25 19:35:42 -07001151 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
1152 "Removing and adding activity " + newTop
1153 + " to stack at top callers=" + Debug.getCallers(4));
Craig Mautnerde4ef022013-04-07 19:01:33 -07001154
Craig Mautnerde4ef022013-04-07 19:01:33 -07001155 mActivities.remove(newTop);
1156 mActivities.add(newTop);
Bryce Leed58d7b32017-09-08 15:55:22 -07001157
1158 // Make sure window manager is aware of the position change.
1159 mWindowContainerController.positionChildAtTop(newTop.mWindowContainerController);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001160 updateEffectiveIntent();
Craig Mautner3b475fe2013-12-16 15:58:31 -08001161
Bryce Leed71317c2017-02-07 14:27:22 -08001162 setFrontOfTask();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001163 }
1164
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001165 void addActivityAtBottom(ActivityRecord r) {
Craig Mautner77878772013-03-04 19:46:24 -08001166 addActivityAtIndex(0, r);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001167 }
1168
1169 void addActivityToTop(ActivityRecord r) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001170 addActivityAtIndex(mActivities.size(), r);
1171 }
1172
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001173 @Override
Wale Ogunwaleeea34ee92017-08-31 20:07:45 -07001174 /*@WindowConfiguration.ActivityType*/
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001175 public int getActivityType() {
1176 final int applicationType = super.getActivityType();
1177 if (applicationType != ACTIVITY_TYPE_UNDEFINED || mActivities.isEmpty()) {
1178 return applicationType;
1179 }
1180 return mActivities.get(0).getActivityType();
1181 }
1182
Winson Chung30480042017-01-26 10:55:34 -08001183 /**
1184 * Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
1185 * be in the current task or unparented to any task.
1186 */
Craig Mautner1602ec22013-05-12 10:24:27 -07001187 void addActivityAtIndex(int index, ActivityRecord r) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001188 TaskRecord task = r.getTask();
1189 if (task != null && task != this) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001190 throw new IllegalArgumentException("Can not add r=" + " to task=" + this
Bryce Leeaf691c02017-03-20 14:20:22 -07001191 + " current parent=" + task);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001192 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001193
1194 r.setTask(this);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001195
Craig Mautner6170f732013-04-02 13:05:23 -07001196 // 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 -08001197 if (!mActivities.remove(r) && r.fullscreen) {
1198 // Was not previously in list.
1199 numFullscreen++;
1200 }
Craig Mautner2c1faed2013-07-23 12:56:02 -07001201 // Only set this based on the first activity
1202 if (mActivities.isEmpty()) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001203 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1204 // Normally non-standard activity type for the activity record will be set when the
1205 // object is created, however we delay setting the standard application type until
1206 // this point so that the task can set the type for additional activities added in
1207 // the else condition below.
1208 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1209 }
1210 setActivityType(r.getActivityType());
Craig Mautner21d24a22014-04-23 11:45:37 -07001211 isPersistable = r.isPersistable();
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001212 mCallingUid = r.launchedFromUid;
1213 mCallingPackage = r.launchedFromPackage;
Dianne Hackborn852975d2014-08-22 17:42:43 -07001214 // Clamp to [1, max].
1215 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1216 ActivityManager.getMaxAppRecentsLimitStatic());
Craig Mautner2c1faed2013-07-23 12:56:02 -07001217 } else {
1218 // Otherwise make all added activities match this one.
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001219 r.setActivityType(getActivityType());
Craig Mautner78733002013-06-10 13:54:49 -07001220 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001221
1222 final int size = mActivities.size();
1223
1224 if (index == size && size > 0) {
1225 final ActivityRecord top = mActivities.get(size - 1);
1226 if (top.mTaskOverlay) {
1227 // Place below the task overlay activity since the overlay activity should always
1228 // be on top.
1229 index--;
1230 }
1231 }
1232
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001233 index = Math.min(size, index);
Craig Mautner77878772013-03-04 19:46:24 -08001234 mActivities.add(index, r);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001235 updateEffectiveIntent();
Craig Mautner21d24a22014-04-23 11:45:37 -07001236 if (r.isPersistable()) {
1237 mService.notifyTaskPersisterLocked(this, false);
1238 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001239
1240 // Sync. with window manager
1241 updateOverrideConfigurationFromLaunchBounds();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001242 final AppWindowContainerController appController = r.getWindowContainerController();
1243 if (appController != null) {
1244 // Only attempt to move in WM if the child has a controller. It is possible we haven't
1245 // created controller for the activity we are starting yet.
1246 mWindowContainerController.positionChildAt(appController, index);
1247 }
David Stevens82ea6cb2017-03-03 16:18:50 -08001248
1249 // Make sure the list of display UID whitelists is updated
1250 // now that this record is in a new task.
1251 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
Craig Mautner77878772013-03-04 19:46:24 -08001252 }
1253
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001254 /**
Bryce Leeaf691c02017-03-20 14:20:22 -07001255 * Removes the specified activity from this task.
1256 * @param r The {@link ActivityRecord} to remove.
1257 * @return true if this was the last activity in the task.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001258 */
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001259 boolean removeActivity(ActivityRecord r) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001260 return removeActivity(r, false /*reparenting*/);
1261 }
1262
1263 boolean removeActivity(ActivityRecord r, boolean reparenting) {
1264 if (r.getTask() != this) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001265 throw new IllegalArgumentException(
1266 "Activity=" + r + " does not belong to task=" + this);
1267 }
1268
Bryce Leeaf691c02017-03-20 14:20:22 -07001269 r.setTask(null /*task*/, reparenting);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001270
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001271 if (mActivities.remove(r) && r.fullscreen) {
1272 // Was previously in list.
1273 numFullscreen--;
1274 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001275 if (r.isPersistable()) {
1276 mService.notifyTaskPersisterLocked(this, false);
1277 }
Wale Ogunwale89182d52016-03-11 10:38:36 -08001278
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001279 if (inPinnedWindowingMode()) {
Wale Ogunwale89182d52016-03-11 10:38:36 -08001280 // We normally notify listeners of task stack changes on pause, however pinned stack
1281 // activities are normally in the paused state so no notification will be sent there
1282 // before the activity is removed. We send it here so instead.
Yorke Leebd54c2a2016-10-25 13:49:23 -07001283 mService.mTaskChangeNotificationController.notifyTaskStackChanged();
Wale Ogunwale89182d52016-03-11 10:38:36 -08001284 }
1285
Craig Mautner41326202014-06-20 14:38:21 -07001286 if (mActivities.isEmpty()) {
Craig Mautner5afcd4d2014-06-21 18:11:33 -07001287 return !mReuseTask;
Craig Mautner41326202014-06-20 14:38:21 -07001288 }
1289 updateEffectiveIntent();
1290 return false;
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001291 }
1292
Winson Chung6954fc92017-03-24 16:22:12 -07001293 /**
1294 * @return whether or not there are ONLY task overlay activities in the stack.
1295 * If {@param excludeFinishing} is set, then ignore finishing activities in the check.
1296 * If there are no task overlay activities, this call returns false.
1297 */
1298 boolean onlyHasTaskOverlayActivities(boolean excludeFinishing) {
1299 int count = 0;
1300 for (int i = mActivities.size() - 1; i >= 0; i--) {
1301 final ActivityRecord r = mActivities.get(i);
1302 if (excludeFinishing && r.finishing) {
1303 continue;
1304 }
1305 if (!r.mTaskOverlay) {
1306 return false;
1307 }
1308 count++;
1309 }
1310 return count > 0;
1311 }
1312
Craig Mautner41db4a72014-05-07 17:20:56 -07001313 boolean autoRemoveFromRecents() {
Dianne Hackbornd38aed82014-06-10 21:36:35 -07001314 // We will automatically remove the task either if it has explicitly asked for
1315 // this, or it is empty and has never contained an activity that got shown to
1316 // the user.
Dianne Hackborn13420f22014-07-18 15:43:56 -07001317 return autoRemoveRecents || (mActivities.isEmpty() && !hasBeenVisible);
Craig Mautner41db4a72014-05-07 17:20:56 -07001318 }
1319
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001320 /**
1321 * Completely remove all activities associated with an existing
1322 * task starting at a specified index.
1323 */
Winson Chung0ec2a352017-10-26 11:38:30 -07001324 final void performClearTaskAtIndexLocked(int activityNdx, boolean pauseImmediately,
1325 String reason) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001326 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001327 for ( ; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001328 final ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001329 if (r.finishing) {
1330 continue;
1331 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001332 if (mStack == null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001333 // Task was restored from persistent storage.
1334 r.takeFromHistory();
1335 mActivities.remove(activityNdx);
1336 --activityNdx;
1337 --numActivities;
Winson Chung6954fc92017-03-24 16:22:12 -07001338 } else if (mStack.finishActivityLocked(r, Activity.RESULT_CANCELED, null,
Winson Chung0ec2a352017-10-26 11:38:30 -07001339 reason, false, pauseImmediately)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001340 --activityNdx;
1341 --numActivities;
1342 }
1343 }
1344 }
1345
1346 /**
1347 * Completely remove all activities associated with an existing task.
1348 */
Benjamin Franza83859f2017-07-03 16:34:14 +01001349 void performClearTaskLocked() {
Craig Mautner362449a2014-06-20 14:04:39 -07001350 mReuseTask = true;
Winson Chung0ec2a352017-10-26 11:38:30 -07001351 performClearTaskAtIndexLocked(0, !PAUSE_IMMEDIATELY, "clear-task-all");
Craig Mautner362449a2014-06-20 14:04:39 -07001352 mReuseTask = false;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001353 }
1354
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -08001355 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1356 mReuseTask = true;
1357 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1358 mReuseTask = false;
1359 return result;
1360 }
1361
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001362 /**
1363 * Perform clear operation as requested by
1364 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1365 * stack to the given task, then look for
1366 * an instance of that activity in the stack and, if found, finish all
1367 * activities on top of it and return the instance.
1368 *
1369 * @param newR Description of the new activity being started.
1370 * @return Returns the old activity that should be continued to be used,
1371 * or null if none was found.
1372 */
1373 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001374 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001375 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001376 ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001377 if (r.finishing) {
1378 continue;
1379 }
1380 if (r.realActivity.equals(newR.realActivity)) {
1381 // Here it is! Now finish everything in front...
Craig Mautner1602ec22013-05-12 10:24:27 -07001382 final ActivityRecord ret = r;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001383
1384 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001385 r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001386 if (r.finishing) {
1387 continue;
1388 }
1389 ActivityOptions opts = r.takeOptionsLocked();
1390 if (opts != null) {
1391 ret.updateOptionsLocked(opts);
1392 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001393 if (mStack != null && mStack.finishActivityLocked(
Todd Kennedy539db512014-12-15 09:57:55 -08001394 r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001395 --activityNdx;
1396 --numActivities;
1397 }
1398 }
1399
1400 // Finally, if this is a normal launch mode (that is, not
1401 // expecting onNewIntent()), then we will finish the current
1402 // instance of the activity so a new fresh one can be started.
1403 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
Daichi Hirono15a02992016-04-27 18:47:01 +09001404 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1405 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001406 if (!ret.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001407 if (mStack != null) {
1408 mStack.finishActivityLocked(
Wale Ogunwale7d701172015-03-11 15:36:30 -07001409 ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
1410 }
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001411 return null;
1412 }
1413 }
1414
1415 return ret;
1416 }
1417 }
1418
1419 return null;
1420 }
1421
Winson Chung0ec2a352017-10-26 11:38:30 -07001422 void removeTaskActivitiesLocked(boolean pauseImmediately, String reason) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001423 // Just remove the entire task.
Winson Chung0ec2a352017-10-26 11:38:30 -07001424 performClearTaskAtIndexLocked(0, pauseImmediately, reason);
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001425 }
1426
Craig Mautner432f64e2015-05-20 14:59:57 -07001427 String lockTaskAuthToString() {
1428 switch (mLockTaskAuth) {
1429 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1430 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1431 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1432 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
Benjamin Franz469dd582015-06-09 14:24:36 +01001433 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
Craig Mautner432f64e2015-05-20 14:59:57 -07001434 default: return "unknown=" + mLockTaskAuth;
1435 }
1436 }
1437
Craig Mautner15df08a2015-04-01 12:17:18 -07001438 void setLockTaskAuth() {
Charles He2bf28322017-10-12 22:24:49 +01001439 setLockTaskAuth(getRootActivity());
1440 }
1441
1442 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1443 if (r == null) {
1444 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1445 return;
1446 }
1447
Charles He520b2832017-09-02 15:27:16 +01001448 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
Charles He2bf28322017-10-12 22:24:49 +01001449 switch (r.lockTaskLaunchMode) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001450 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
Charles He520b2832017-09-02 15:27:16 +01001451 mLockTaskAuth = mService.mLockTaskController.isPackageWhitelisted(userId, pkg)
1452 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001453 break;
1454
1455 case LOCK_TASK_LAUNCH_MODE_NEVER:
Benjamin Franz469dd582015-06-09 14:24:36 +01001456 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
Craig Mautner15df08a2015-04-01 12:17:18 -07001457 break;
1458
1459 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
Benjamin Franz469dd582015-06-09 14:24:36 +01001460 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
Craig Mautner15df08a2015-04-01 12:17:18 -07001461 break;
1462
1463 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
Charles He520b2832017-09-02 15:27:16 +01001464 mLockTaskAuth = mService.mLockTaskController.isPackageWhitelisted(userId, pkg)
1465 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001466 break;
1467 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001468 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this +
1469 " mLockTaskAuth=" + lockTaskAuthToString());
Craig Mautner15df08a2015-04-01 12:17:18 -07001470 }
1471
Winson Chungd3395382016-12-13 11:49:09 -08001472 private boolean isResizeable(boolean checkSupportsPip) {
1473 return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001474 || (checkSupportsPip && mSupportsPictureInPicture));
Winson Chungd3395382016-12-13 11:49:09 -08001475 }
1476
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001477 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08001478 return isResizeable(true /* checkSupportsPip */);
1479 }
1480
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001481 @Override
1482 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08001483 // A task can not be docked even if it is considered resizeable because it only supports
1484 // picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001485 return super.supportsSplitScreenWindowingMode()
1486 && mService.mSupportsSplitScreenMultiWindow
Bryce Leec857a5b2017-08-16 10:04:52 -07001487 && (mService.mForceResizableActivities
1488 || (isResizeable(false /* checkSupportsPip */)
1489 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001490 }
1491
skuhne@google.com322347b2016-12-02 12:54:03 -08001492 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001493 * Check whether this task can be launched on the specified display.
1494 * @param displayId Target display id.
1495 * @return {@code true} if either it is the default display or this activity is resizeable and
1496 * can be put a secondary screen.
1497 */
1498 boolean canBeLaunchedOnDisplay(int displayId) {
1499 return mService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Andrii Kulian02689a72017-07-06 14:28:59 -07001500 isResizeable(false /* checkSupportsPip */), -1 /* don't check PID */,
1501 -1 /* don't check UID */, null /* activityInfo */);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001502 }
1503
1504 /**
skuhne@google.com322347b2016-12-02 12:54:03 -08001505 * Check that a given bounds matches the application requested orientation.
1506 *
1507 * @param bounds The bounds to be tested.
1508 * @return True if the requested bounds are okay for a resizing request.
1509 */
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001510 private boolean canResizeToBounds(Rect bounds) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001511 if (bounds == null || !inFreeformWindowingMode()) {
skuhne@google.com322347b2016-12-02 12:54:03 -08001512 // Note: If not on the freeform workspace, we ignore the bounds.
1513 return true;
1514 }
1515 final boolean landscape = bounds.width() > bounds.height();
Bryce Leef3c6a472017-11-14 14:53:06 -08001516 final Rect configBounds = getOverrideBounds();
skuhne@google.com322347b2016-12-02 12:54:03 -08001517 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001518 return configBounds.isEmpty()
1519 || landscape == (configBounds.width() > configBounds.height());
skuhne@google.com322347b2016-12-02 12:54:03 -08001520 }
1521 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1522 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1523 }
1524
Craig Mautner525f3d92013-05-07 14:01:50 -07001525 /**
Yorke Leebdef5372017-04-10 16:38:51 -07001526 * @return {@code true} if the task is being cleared for the purposes of being reused.
1527 */
1528 boolean isClearingToReuseTask() {
1529 return mReuseTask;
1530 }
1531
1532 /**
Craig Mautner525f3d92013-05-07 14:01:50 -07001533 * Find the activity in the history stack within the given task. Returns
1534 * the index within the history at which it's found, or < 0 if not found.
1535 */
1536 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
1537 final ComponentName realActivity = r.realActivity;
1538 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1539 ActivityRecord candidate = mActivities.get(activityNdx);
1540 if (candidate.finishing) {
1541 continue;
1542 }
1543 if (candidate.realActivity.equals(realActivity)) {
1544 return candidate;
1545 }
1546 }
1547 return null;
1548 }
1549
Winson Chunga449dc02014-05-16 11:15:04 -07001550 /** Updates the last task description values. */
1551 void updateTaskDescription() {
1552 // Traverse upwards looking for any break between main task activities and
1553 // utility activities.
1554 int activityNdx;
1555 final int numActivities = mActivities.size();
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001556 final boolean relinquish = numActivities != 0 &&
1557 (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001558 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
Craig Mautner21d24a22014-04-23 11:45:37 -07001559 ++activityNdx) {
Winson Chunga449dc02014-05-16 11:15:04 -07001560 final ActivityRecord r = mActivities.get(activityNdx);
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001561 if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001562 // This will be the top activity for determining taskDescription. Pre-inc to
1563 // overcome initial decrement below.
1564 ++activityNdx;
1565 break;
1566 }
Winson Chunga449dc02014-05-16 11:15:04 -07001567 if (r.intent != null &&
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001568 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
Winson Chunga449dc02014-05-16 11:15:04 -07001569 break;
1570 }
1571 }
1572 if (activityNdx > 0) {
1573 // Traverse downwards starting below break looking for set label, icon.
1574 // Note that if there are activities in the task but none of them set the
1575 // recent activity values, then we do not fall back to the last set
1576 // values in the TaskRecord.
1577 String label = null;
Craig Mautner648f69b2014-09-18 14:16:26 -07001578 String iconFilename = null;
Matthew Ng54bc9422017-10-02 17:16:28 -07001579 int iconResource = -1;
Winson Chunga449dc02014-05-16 11:15:04 -07001580 int colorPrimary = 0;
Winson Chung1af8eda2016-02-05 17:55:56 +00001581 int colorBackground = 0;
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001582 int statusBarColor = 0;
1583 int navigationBarColor = 0;
1584 boolean topActivity = true;
Winson Chunga449dc02014-05-16 11:15:04 -07001585 for (--activityNdx; activityNdx >= 0; --activityNdx) {
1586 final ActivityRecord r = mActivities.get(activityNdx);
1587 if (r.taskDescription != null) {
1588 if (label == null) {
1589 label = r.taskDescription.getLabel();
1590 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001591 if (iconResource == -1) {
1592 iconResource = r.taskDescription.getIconResource();
1593 }
Craig Mautner648f69b2014-09-18 14:16:26 -07001594 if (iconFilename == null) {
1595 iconFilename = r.taskDescription.getIconFilename();
Winson Chunga449dc02014-05-16 11:15:04 -07001596 }
1597 if (colorPrimary == 0) {
1598 colorPrimary = r.taskDescription.getPrimaryColor();
Winson Chunga449dc02014-05-16 11:15:04 -07001599 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001600 if (topActivity) {
Winson Chung1af8eda2016-02-05 17:55:56 +00001601 colorBackground = r.taskDescription.getBackgroundColor();
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001602 statusBarColor = r.taskDescription.getStatusBarColor();
1603 navigationBarColor = r.taskDescription.getNavigationBarColor();
Winson Chung1af8eda2016-02-05 17:55:56 +00001604 }
Winson Chunga449dc02014-05-16 11:15:04 -07001605 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001606 topActivity = false;
Winson Chunga449dc02014-05-16 11:15:04 -07001607 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001608 lastTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
1609 colorPrimary, colorBackground, statusBarColor, navigationBarColor);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001610 if (mWindowContainerController != null) {
1611 mWindowContainerController.setTaskDescription(lastTaskDescription);
1612 }
Winson Chungec396d62014-08-06 17:08:00 -07001613 // Update the task affiliation color if we are the parent of the group
1614 if (taskId == mAffiliatedTaskId) {
1615 mAffiliatedTaskColor = lastTaskDescription.getPrimaryColor();
1616 }
Winson Chunga449dc02014-05-16 11:15:04 -07001617 }
1618 }
1619
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001620 int findEffectiveRootIndex() {
Craig Mautner4767f4b2014-09-18 15:38:33 -07001621 int effectiveNdx = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001622 final int topActivityNdx = mActivities.size() - 1;
Dianne Hackborn39569af2014-09-23 10:56:58 -07001623 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001624 final ActivityRecord r = mActivities.get(activityNdx);
1625 if (r.finishing) {
1626 continue;
1627 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001628 effectiveNdx = activityNdx;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001629 if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001630 break;
1631 }
1632 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001633 return effectiveNdx;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001634 }
1635
1636 void updateEffectiveIntent() {
1637 final int effectiveRootIndex = findEffectiveRootIndex();
1638 final ActivityRecord r = mActivities.get(effectiveRootIndex);
Winson Chungfee26772014-08-05 12:21:52 -07001639 setIntent(r);
Winson Chung8d9009e2017-11-16 15:43:05 -08001640
1641 // Update the task description when the activities change
1642 updateTaskDescription();
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001643 }
1644
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001645 private void adjustForMinimalTaskDimensions(Rect bounds) {
1646 if (bounds == null) {
1647 return;
1648 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001649 int minWidth = mMinWidth;
1650 int minHeight = mMinHeight;
Robert Carr9c5867d2016-03-10 15:52:46 -08001651 // If the task has no requested minimal size, we'd like to enforce a minimal size
1652 // so that the user can not render the task too small to manipulate. We don't need
1653 // to do this for the pinned stack as the bounds are controlled by the system.
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001654 if (!inPinnedWindowingMode()) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001655 if (minWidth == INVALID_MIN_SIZE) {
1656 minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001657 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001658 if (minHeight == INVALID_MIN_SIZE) {
1659 minHeight = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001660 }
Robert Carr9c5867d2016-03-10 15:52:46 -08001661 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001662 final boolean adjustWidth = minWidth > bounds.width();
1663 final boolean adjustHeight = minHeight > bounds.height();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001664 if (!(adjustWidth || adjustHeight)) {
1665 return;
1666 }
1667
Bryce Leef3c6a472017-11-14 14:53:06 -08001668 final Rect configBounds = getOverrideBounds();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001669 if (adjustWidth) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001670 if (!configBounds.isEmpty() && bounds.right == configBounds.right) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001671 bounds.left = bounds.right - minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001672 } else {
1673 // Either left bounds match, or neither match, or the previous bounds were
1674 // fullscreen and we default to keeping left.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001675 bounds.right = bounds.left + minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001676 }
1677 }
1678 if (adjustHeight) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001679 if (!configBounds.isEmpty() && bounds.bottom == configBounds.bottom) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001680 bounds.top = bounds.bottom - minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001681 } else {
1682 // Either top bounds match, or neither match, or the previous bounds were
1683 // fullscreen and we default to keeping top.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001684 bounds.bottom = bounds.top + minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001685 }
1686 }
1687 }
1688
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001689 /**
Winson Chung5af42fc2017-03-24 17:11:33 -07001690 * @return a new Configuration for this Task, given the provided {@param bounds} and
1691 * {@param insetBounds}.
1692 */
1693 Configuration computeNewOverrideConfigurationForBounds(Rect bounds, Rect insetBounds) {
1694 // Compute a new override configuration for the given bounds, if fullscreen bounds
1695 // (bounds == null), then leave the override config unset
1696 final Configuration newOverrideConfig = new Configuration();
1697 if (bounds != null) {
1698 newOverrideConfig.setTo(getOverrideConfiguration());
1699 mTmpRect.set(bounds);
1700 adjustForMinimalTaskDimensions(mTmpRect);
1701 computeOverrideConfiguration(newOverrideConfig, mTmpRect, insetBounds,
1702 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
1703 }
1704
1705 return newOverrideConfig;
1706 }
1707
1708 /**
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001709 * Update task's override configuration based on the bounds.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001710 * @param bounds The bounds of the task.
Andrii Kulian8072d112016-09-16 11:11:01 -07001711 * @return True if the override configuration was updated.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001712 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001713 boolean updateOverrideConfiguration(Rect bounds) {
Jorim Jaggi0a932142016-02-01 17:42:25 -08001714 return updateOverrideConfiguration(bounds, null /* insetBounds */);
1715 }
1716
1717 /**
1718 * Update task's override configuration based on the bounds.
1719 * @param bounds The bounds of the task.
1720 * @param insetBounds The bounds used to calculate the system insets, which is used here to
1721 * subtract the navigation bar/status bar size from the screen size reported
1722 * to the application. See {@link IActivityManager#resizeDockedStack}.
Andrii Kulian8072d112016-09-16 11:11:01 -07001723 * @return True if the override configuration was updated.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001724 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001725 boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001726 if (equivalentOverrideBounds(bounds)) {
Andrii Kulian8072d112016-09-16 11:11:01 -07001727 return false;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001728 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001729 final Rect currentBounds = getOverrideBounds();
1730
Andrii Kulian1779e612016-10-12 21:58:25 -07001731 mTmpConfig.setTo(getOverrideConfiguration());
Andrii Kulian1779e612016-10-12 21:58:25 -07001732 final Configuration newConfig = getOverrideConfiguration();
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001733
Bryce Leef3c6a472017-11-14 14:53:06 -08001734 final boolean matchParentBounds = bounds == null || bounds.isEmpty();
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001735 final boolean persistBounds = getWindowConfiguration().persistTaskBounds();
Bryce Leef3c6a472017-11-14 14:53:06 -08001736 if (matchParentBounds) {
1737 if (!currentBounds.isEmpty() && persistBounds) {
1738 mLastNonFullscreenBounds = currentBounds;
Wale Ogunwale706ed792015-08-02 10:29:44 -07001739 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001740 setBounds(null);
Andrii Kulian1779e612016-10-12 21:58:25 -07001741 newConfig.unset();
Wale Ogunwale706ed792015-08-02 10:29:44 -07001742 } else {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001743 mTmpRect.set(bounds);
1744 adjustForMinimalTaskDimensions(mTmpRect);
Bryce Leef3c6a472017-11-14 14:53:06 -08001745 setBounds(mTmpRect);
1746
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001747 if (mStack == null || persistBounds) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001748 mLastNonFullscreenBounds = getOverrideBounds();
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -07001749 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001750 computeOverrideConfiguration(newConfig, mTmpRect, insetBounds,
Andrii Kuliandaea3572016-04-08 13:20:51 -07001751 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
Wale Ogunwale706ed792015-08-02 10:29:44 -07001752 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001753 onOverrideConfigurationChanged(newConfig);
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001754 return !mTmpConfig.equals(newConfig);
1755 }
Wale Ogunwale5f986092015-12-04 15:35:38 -08001756
Bryce Leec4ab62a2018-03-05 14:19:26 -08001757 /**
1758 * This should be called when an child activity changes state. This should only
1759 * be called from
1760 * {@link ActivityRecord#setState(ActivityState, String)} .
1761 * @param record The {@link ActivityRecord} whose state has changed.
1762 * @param state The new state.
1763 * @param reason The reason for the change.
1764 */
1765 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
1766 final ActivityStack parent = getStack();
1767
1768 if (parent != null) {
1769 parent.onActivityStateChanged(record, state, reason);
1770 }
1771 }
1772
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001773 @Override
1774 public void onConfigurationChanged(Configuration newParentConfig) {
1775 final boolean wasInMultiWindowMode = inMultiWindowMode();
1776 super.onConfigurationChanged(newParentConfig);
1777 if (wasInMultiWindowMode != inMultiWindowMode()) {
Winson Chung5af42fc2017-03-24 17:11:33 -07001778 mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001779 }
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001780 // TODO: Should also take care of Pip mode changes here.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001781 }
1782
Andrii Kulian1779e612016-10-12 21:58:25 -07001783 /** Clears passed config and fills it with new override values. */
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001784 // TODO(b/36505427): TaskRecord.computeOverrideConfiguration() is a utility method that doesn't
1785 // depend on task or stacks, but uses those object to get the display to base the calculation
1786 // on. Probably best to centralize calculations like this in ConfigurationContainer.
1787 void computeOverrideConfiguration(Configuration config, Rect bounds, Rect insetBounds,
Andrii Kuliana8a9bc52016-10-14 11:00:13 -07001788 boolean overrideWidth, boolean overrideHeight) {
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001789 mTmpNonDecorBounds.set(bounds);
1790 mTmpStableBounds.set(bounds);
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001791
Andrii Kulian1779e612016-10-12 21:58:25 -07001792 config.unset();
Winson Chungbdc646f2017-02-13 12:12:22 -08001793 final Configuration parentConfig = getParent().getConfiguration();
Bryce Lee7566d762017-03-30 09:34:15 -07001794
Andrii Kulian1779e612016-10-12 21:58:25 -07001795 final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001796
Winson Chungbdc646f2017-02-13 12:12:22 -08001797 if (mStack != null) {
1798 final StackWindowController stackController = mStack.getWindowContainerController();
1799 stackController.adjustConfigurationForBounds(bounds, insetBounds,
1800 mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
1801 config, parentConfig);
1802 } else {
Bryce Lee7566d762017-03-30 09:34:15 -07001803 throw new IllegalArgumentException("Expected stack when calculating override config");
Winson Chungbdc646f2017-02-13 12:12:22 -08001804 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001805
Winson Chung60c1aba2017-03-14 17:47:42 -07001806 config.orientation = (config.screenWidthDp <= config.screenHeightDp)
1807 ? Configuration.ORIENTATION_PORTRAIT
1808 : Configuration.ORIENTATION_LANDSCAPE;
1809
Jorim Jaggi85639432016-05-06 17:27:55 -07001810 // For calculating screen layout, we need to use the non-decor inset screen area for the
1811 // calculation for compatibility reasons, i.e. screen area without system bars that could
1812 // never go away in Honeycomb.
Winson Chungbdc646f2017-02-13 12:12:22 -08001813 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
1814 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Andrii Kulian1779e612016-10-12 21:58:25 -07001815 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
1816 // calculation with partial default.
1817 final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001818 final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
Andrii Kulian1779e612016-10-12 21:58:25 -07001819 final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
Jorim Jaggi85639432016-05-06 17:27:55 -07001820 config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08001821 }
1822
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001823 Rect updateOverrideConfigurationFromLaunchBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08001824 final Rect bounds = getLaunchBounds();
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001825 updateOverrideConfiguration(bounds);
Bryce Leef3c6a472017-11-14 14:53:06 -08001826 if (bounds != null && !bounds.isEmpty()) {
1827 // TODO: Review if we actually want to do this - we are setting the launch bounds
1828 // directly here.
1829 bounds.set(getOverrideBounds());
Andrii Kulian73336d812016-03-24 12:56:08 -07001830 }
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08001831 return bounds;
1832 }
1833
Wale Ogunwale935e5022015-11-10 12:36:10 -08001834 /** Updates the task's bounds and override configuration to match what is expected for the
1835 * input stack. */
1836 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001837 if (mStack != null && mStack == inStack) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001838 return;
1839 }
1840
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001841 if (inStack.inFreeformWindowingMode()) {
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001842 if (!isResizeable()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001843 throw new IllegalArgumentException("Can not position non-resizeable task="
1844 + this + " in stack=" + inStack);
1845 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001846 if (!matchParentBounds()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08001847 return;
1848 }
1849 if (mLastNonFullscreenBounds != null) {
1850 updateOverrideConfiguration(mLastNonFullscreenBounds);
1851 } else {
Bryce Leeec55eb02017-12-05 20:51:27 -08001852 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Wale Ogunwale935e5022015-11-10 12:36:10 -08001853 }
1854 } else {
Bryce Leef3c6a472017-11-14 14:53:06 -08001855 updateOverrideConfiguration(inStack.getOverrideBounds());
Wale Ogunwale935e5022015-11-10 12:36:10 -08001856 }
1857 }
1858
Wale Ogunwale706ed792015-08-02 10:29:44 -07001859 /** Returns the bounds that should be used to launch this task. */
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001860 Rect getLaunchBounds() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001861 if (mStack == null) {
Chong Zhang7d5f5102016-01-13 10:29:24 -08001862 return null;
1863 }
1864
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001865 final int windowingMode = getWindowingMode();
1866 if (!isActivityTypeStandardOrUndefined()
1867 || windowingMode == WINDOWING_MODE_FULLSCREEN
1868 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001869 return isResizeable() ? mStack.getOverrideBounds() : null;
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001870 } else if (!getWindowConfiguration().persistTaskBounds()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001871 return mStack.getOverrideBounds();
Wale Ogunwale706ed792015-08-02 10:29:44 -07001872 }
1873 return mLastNonFullscreenBounds;
1874 }
1875
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01001876 void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
1877 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1878 final ActivityRecord r = mActivities.get(activityNdx);
1879 if (r.visible) {
1880 r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
1881 }
1882 }
1883 }
1884
Dianne Hackborn68a06332017-11-15 17:54:18 -08001885 void setRootProcess(ProcessRecord proc) {
1886 clearRootProcess();
1887 if (intent != null &&
1888 (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
1889 mRootProcess = proc;
1890 proc.recentTasks.add(this);
1891 }
1892 }
1893
1894 void clearRootProcess() {
1895 if (mRootProcess != null) {
1896 mRootProcess.recentTasks.remove(this);
1897 mRootProcess = null;
1898 }
1899 }
1900
chaviw82a0ba82018-03-15 14:26:29 -07001901 void clearAllPendingOptions() {
1902 for (int i = getChildCount() - 1; i >= 0; i--) {
1903 getChildAt(i).clearOptionsLocked(false /* withAbort */);
1904 }
1905 }
1906
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001907 void dump(PrintWriter pw, String prefix) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001908 pw.print(prefix); pw.print("userId="); pw.print(userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001909 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
1910 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
Suprabh Shukla7745c142016-03-07 18:21:10 -08001911 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001912 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
Dianne Hackborn79228822014-09-16 11:11:23 -07001913 if (affinity != null || rootAffinity != null) {
1914 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
1915 if (affinity == null || !affinity.equals(rootAffinity)) {
1916 pw.print(" root="); pw.println(rootAffinity);
1917 } else {
1918 pw.println();
1919 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001920 }
Dianne Hackborn91097de2014-04-04 18:02:06 -07001921 if (voiceSession != null || voiceInteractor != null) {
1922 pw.print(prefix); pw.print("VOICE: session=0x");
1923 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
1924 pw.print(" interactor=0x");
1925 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
1926 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001927 if (intent != null) {
1928 StringBuilder sb = new StringBuilder(128);
1929 sb.append(prefix); sb.append("intent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08001930 intent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001931 sb.append('}');
1932 pw.println(sb.toString());
1933 }
1934 if (affinityIntent != null) {
1935 StringBuilder sb = new StringBuilder(128);
1936 sb.append(prefix); sb.append("affinityIntent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08001937 affinityIntent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07001938 sb.append('}');
1939 pw.println(sb.toString());
1940 }
1941 if (origActivity != null) {
1942 pw.print(prefix); pw.print("origActivity=");
1943 pw.println(origActivity.flattenToShortString());
1944 }
1945 if (realActivity != null) {
1946 pw.print(prefix); pw.print("realActivity=");
1947 pw.println(realActivity.flattenToShortString());
1948 }
Wale Ogunwale66e16852017-10-19 13:35:52 -07001949 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard() || numFullscreen != 0) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001950 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001951 pw.print(" isPersistable="); pw.print(isPersistable);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001952 pw.print(" numFullscreen="); pw.print(numFullscreen);
Wale Ogunwale66e16852017-10-19 13:35:52 -07001953 pw.print(" activityType="); pw.println(getActivityType());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001954 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001955 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
1956 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001957 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
1958 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
Craig Mautner432f64e2015-05-20 14:59:57 -07001959 pw.print(" mReuseTask="); pw.print(mReuseTask);
1960 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07001961 }
Wale Ogunwale18795a22014-12-03 11:38:33 -08001962 if (mAffiliatedTaskId != taskId || mPrevAffiliateTaskId != INVALID_TASK_ID
1963 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
1964 || mNextAffiliate != null) {
Dianne Hackborn852975d2014-08-22 17:42:43 -07001965 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
1966 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
1967 pw.print(" (");
1968 if (mPrevAffiliate == null) {
1969 pw.print("null");
1970 } else {
1971 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
1972 }
1973 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
1974 pw.print(" (");
1975 if (mNextAffiliate == null) {
1976 pw.print("null");
1977 } else {
1978 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
1979 }
1980 pw.println(")");
1981 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001982 pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001983 if (!askedCompatMode || !inRecents || !isAvailable) {
1984 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
1985 pw.print(" inRecents="); pw.print(inRecents);
1986 pw.print(" isAvailable="); pw.println(isAvailable);
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07001987 }
Dianne Hackborn852975d2014-08-22 17:42:43 -07001988 if (lastDescription != null) {
1989 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
1990 }
Dianne Hackborn68a06332017-11-15 17:54:18 -08001991 if (mRootProcess != null) {
1992 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
1993 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001994 pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001995 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
1996 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08001997 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001998 pw.print(" isResizeable=" + isResizeable());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001999 pw.print(" lastActiveTime=" + lastActiveTime);
2000 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002001 }
2002
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002003 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002004 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002005 StringBuilder sb = new StringBuilder(128);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002006 if (stringName != null) {
2007 sb.append(stringName);
2008 sb.append(" U=");
2009 sb.append(userId);
Wale Ogunwale6c5eb1c2015-11-10 07:52:22 -08002010 sb.append(" StackId=");
Andrii Kulian02b7a832016-10-06 23:11:56 -07002011 sb.append(getStackId());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002012 sb.append(" sz=");
2013 sb.append(mActivities.size());
2014 sb.append('}');
2015 return sb.toString();
2016 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002017 sb.append("TaskRecord{");
2018 sb.append(Integer.toHexString(System.identityHashCode(this)));
2019 sb.append(" #");
2020 sb.append(taskId);
2021 if (affinity != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002022 sb.append(" A=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002023 sb.append(affinity);
2024 } else if (intent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002025 sb.append(" I=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002026 sb.append(intent.getComponent().flattenToShortString());
Bryce Leefbd263b42018-03-07 10:33:55 -08002027 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002028 sb.append(" aI=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002029 sb.append(affinityIntent.getComponent().flattenToShortString());
2030 } else {
2031 sb.append(" ??");
2032 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07002033 stringName = sb.toString();
2034 return toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002035 }
Steven Timotius4346f0a2017-09-12 11:07:21 -07002036
2037 public void writeToProto(ProtoOutputStream proto, long fieldId) {
2038 final long token = proto.start(fieldId);
Adrian Roos4921ccf2017-09-28 16:54:06 +02002039 super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002040 proto.write(ID, taskId);
2041 for (int i = mActivities.size() - 1; i >= 0; i--) {
2042 ActivityRecord activity = mActivities.get(i);
2043 activity.writeToProto(proto, ACTIVITIES);
2044 }
2045 proto.write(STACK_ID, mStack.mStackId);
2046 if (mLastNonFullscreenBounds != null) {
2047 mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
2048 }
2049 if (realActivity != null) {
2050 proto.write(REAL_ACTIVITY, realActivity.flattenToShortString());
2051 }
2052 if (origActivity != null) {
2053 proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString());
2054 }
2055 proto.write(ACTIVITY_TYPE, getActivityType());
Steven Timotius4346f0a2017-09-12 11:07:21 -07002056 proto.write(RESIZE_MODE, mResizeMode);
Bryce Leef3c6a472017-11-14 14:53:06 -08002057 // TODO: Remove, no longer needed with windowingMode.
2058 proto.write(FULLSCREEN, matchParentBounds());
2059
2060 if (!matchParentBounds()) {
2061 final Rect bounds = getOverrideBounds();
2062 bounds.writeToProto(proto, BOUNDS);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002063 }
2064 proto.write(MIN_WIDTH, mMinWidth);
2065 proto.write(MIN_HEIGHT, mMinHeight);
2066 proto.end(token);
2067 }
Winson Chung61c9e5a2017-10-11 10:39:32 -07002068
2069 /**
2070 * See {@link #getNumRunningActivities(TaskActivitiesReport)}.
2071 */
2072 static class TaskActivitiesReport {
2073 int numRunning;
2074 int numActivities;
2075 ActivityRecord top;
2076 ActivityRecord base;
2077
2078 void reset() {
2079 numRunning = numActivities = 0;
2080 top = base = null;
2081 }
2082 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002083
2084 /**
2085 * Saves this {@link TaskRecord} to XML using given serializer.
2086 */
2087 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
2088 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
2089
2090 out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
2091 if (realActivity != null) {
2092 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
2093 }
2094 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
2095 if (origActivity != null) {
2096 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
2097 }
2098 // Write affinity, and root affinity if it is different from affinity.
2099 // We use the special string "@" for a null root affinity, so we can identify
2100 // later whether we were given a root affinity or should just make it the
2101 // same as the affinity.
2102 if (affinity != null) {
2103 out.attribute(null, ATTR_AFFINITY, affinity);
2104 if (!affinity.equals(rootAffinity)) {
2105 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2106 }
2107 } else if (rootAffinity != null) {
2108 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2109 }
2110 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
2111 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
2112 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
2113 out.attribute(null, ATTR_USERID, String.valueOf(userId));
2114 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
2115 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
2116 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
2117 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
2118 if (lastDescription != null) {
2119 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
2120 }
2121 if (lastTaskDescription != null) {
2122 lastTaskDescription.saveToXml(out);
2123 }
2124 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
2125 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
2126 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
2127 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
2128 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
2129 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
2130 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
2131 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
2132 String.valueOf(mSupportsPictureInPicture));
2133 if (mLastNonFullscreenBounds != null) {
2134 out.attribute(
2135 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
2136 }
2137 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
2138 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
2139 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
2140
2141 if (affinityIntent != null) {
2142 out.startTag(null, TAG_AFFINITYINTENT);
2143 affinityIntent.saveToXml(out);
2144 out.endTag(null, TAG_AFFINITYINTENT);
2145 }
2146
2147 out.startTag(null, TAG_INTENT);
2148 intent.saveToXml(out);
2149 out.endTag(null, TAG_INTENT);
2150
2151 final ArrayList<ActivityRecord> activities = mActivities;
2152 final int numActivities = activities.size();
2153 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
2154 final ActivityRecord r = activities.get(activityNdx);
2155 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
2156 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
2157 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
2158 activityNdx > 0) {
2159 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
2160 break;
2161 }
2162 out.startTag(null, TAG_ACTIVITY);
2163 r.saveToXml(out);
2164 out.endTag(null, TAG_ACTIVITY);
2165 }
2166 }
2167
2168 @VisibleForTesting
2169 static TaskRecordFactory getTaskRecordFactory() {
2170 if (sTaskRecordFactory == null) {
2171 setTaskRecordFactory(new TaskRecordFactory());
2172 }
2173 return sTaskRecordFactory;
2174 }
2175
2176 static void setTaskRecordFactory(TaskRecordFactory factory) {
2177 sTaskRecordFactory = factory;
2178 }
2179
2180 static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2181 Intent intent, IVoiceInteractionSession voiceSession,
2182 IVoiceInteractor voiceInteractor) {
2183 return getTaskRecordFactory().create(
2184 service, taskId, info, intent, voiceSession, voiceInteractor);
2185 }
2186
2187 static TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2188 Intent intent, TaskDescription taskDescription) {
2189 return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
2190 }
2191
2192 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2193 throws IOException, XmlPullParserException {
2194 return getTaskRecordFactory().restoreFromXml(in, stackSupervisor);
2195 }
2196
2197 /**
2198 * A factory class used to create {@link TaskRecord} or its subclass if any. This can be
2199 * specified when system boots by setting it with
2200 * {@link #setTaskRecordFactory(TaskRecordFactory)}.
2201 */
2202 static class TaskRecordFactory {
2203
2204 TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2205 Intent intent, IVoiceInteractionSession voiceSession,
2206 IVoiceInteractor voiceInteractor) {
2207 return new TaskRecord(
2208 service, taskId, info, intent, voiceSession, voiceInteractor);
2209 }
2210
2211 TaskRecord create(ActivityManagerService service, int taskId, ActivityInfo info,
2212 Intent intent, TaskDescription taskDescription) {
2213 return new TaskRecord(service, taskId, info, intent, taskDescription);
2214 }
2215
2216 /**
2217 * Should only be used when we're restoring {@link TaskRecord} from storage.
2218 */
2219 TaskRecord create(ActivityManagerService service, int taskId, Intent intent,
2220 Intent affinityIntent, String affinity, String rootAffinity,
2221 ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
2222 boolean autoRemoveRecents, boolean askedCompatMode, int userId,
2223 int effectiveUid, String lastDescription, ArrayList<ActivityRecord> activities,
2224 long lastTimeMoved, boolean neverRelinquishIdentity,
2225 TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
2226 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
2227 int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
2228 boolean userSetupComplete, int minWidth, int minHeight) {
2229 return new TaskRecord(service, taskId, intent, affinityIntent, affinity,
2230 rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
2231 askedCompatMode, userId, effectiveUid, lastDescription, activities,
2232 lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
2233 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
2234 resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
2235 minWidth, minHeight);
2236 }
2237
2238 TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2239 throws IOException, XmlPullParserException {
2240 Intent intent = null;
2241 Intent affinityIntent = null;
2242 ArrayList<ActivityRecord> activities = new ArrayList<>();
2243 ComponentName realActivity = null;
2244 boolean realActivitySuspended = false;
2245 ComponentName origActivity = null;
2246 String affinity = null;
2247 String rootAffinity = null;
2248 boolean hasRootAffinity = false;
2249 boolean rootHasReset = false;
2250 boolean autoRemoveRecents = false;
2251 boolean askedCompatMode = false;
2252 int taskType = 0;
2253 int userId = 0;
2254 boolean userSetupComplete = true;
2255 int effectiveUid = -1;
2256 String lastDescription = null;
2257 long lastTimeOnTop = 0;
2258 boolean neverRelinquishIdentity = true;
2259 int taskId = INVALID_TASK_ID;
2260 final int outerDepth = in.getDepth();
2261 TaskDescription taskDescription = new TaskDescription();
2262 int taskAffiliation = INVALID_TASK_ID;
2263 int taskAffiliationColor = 0;
2264 int prevTaskId = INVALID_TASK_ID;
2265 int nextTaskId = INVALID_TASK_ID;
2266 int callingUid = -1;
2267 String callingPackage = "";
2268 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
2269 boolean supportsPictureInPicture = false;
Garfield Tan367b35a2017-12-13 12:16:21 -08002270 Rect lastNonFullscreenBounds = null;
Garfield Tan9b1efea2017-12-05 16:43:46 -08002271 int minWidth = INVALID_MIN_SIZE;
2272 int minHeight = INVALID_MIN_SIZE;
2273 int persistTaskVersion = 0;
2274
2275 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
2276 final String attrName = in.getAttributeName(attrNdx);
2277 final String attrValue = in.getAttributeValue(attrNdx);
2278 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
2279 attrName + " value=" + attrValue);
2280 switch (attrName) {
2281 case ATTR_TASKID:
2282 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
2283 break;
2284 case ATTR_REALACTIVITY:
2285 realActivity = ComponentName.unflattenFromString(attrValue);
2286 break;
2287 case ATTR_REALACTIVITY_SUSPENDED:
2288 realActivitySuspended = Boolean.valueOf(attrValue);
2289 break;
2290 case ATTR_ORIGACTIVITY:
2291 origActivity = ComponentName.unflattenFromString(attrValue);
2292 break;
2293 case ATTR_AFFINITY:
2294 affinity = attrValue;
2295 break;
2296 case ATTR_ROOT_AFFINITY:
2297 rootAffinity = attrValue;
2298 hasRootAffinity = true;
2299 break;
2300 case ATTR_ROOTHASRESET:
2301 rootHasReset = Boolean.parseBoolean(attrValue);
2302 break;
2303 case ATTR_AUTOREMOVERECENTS:
2304 autoRemoveRecents = Boolean.parseBoolean(attrValue);
2305 break;
2306 case ATTR_ASKEDCOMPATMODE:
2307 askedCompatMode = Boolean.parseBoolean(attrValue);
2308 break;
2309 case ATTR_USERID:
2310 userId = Integer.parseInt(attrValue);
2311 break;
2312 case ATTR_USER_SETUP_COMPLETE:
2313 userSetupComplete = Boolean.parseBoolean(attrValue);
2314 break;
2315 case ATTR_EFFECTIVE_UID:
2316 effectiveUid = Integer.parseInt(attrValue);
2317 break;
2318 case ATTR_TASKTYPE:
2319 taskType = Integer.parseInt(attrValue);
2320 break;
2321 case ATTR_LASTDESCRIPTION:
2322 lastDescription = attrValue;
2323 break;
2324 case ATTR_LASTTIMEMOVED:
2325 lastTimeOnTop = Long.parseLong(attrValue);
2326 break;
2327 case ATTR_NEVERRELINQUISH:
2328 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
2329 break;
2330 case ATTR_TASK_AFFILIATION:
2331 taskAffiliation = Integer.parseInt(attrValue);
2332 break;
2333 case ATTR_PREV_AFFILIATION:
2334 prevTaskId = Integer.parseInt(attrValue);
2335 break;
2336 case ATTR_NEXT_AFFILIATION:
2337 nextTaskId = Integer.parseInt(attrValue);
2338 break;
2339 case ATTR_TASK_AFFILIATION_COLOR:
2340 taskAffiliationColor = Integer.parseInt(attrValue);
2341 break;
2342 case ATTR_CALLING_UID:
2343 callingUid = Integer.parseInt(attrValue);
2344 break;
2345 case ATTR_CALLING_PACKAGE:
2346 callingPackage = attrValue;
2347 break;
2348 case ATTR_RESIZE_MODE:
2349 resizeMode = Integer.parseInt(attrValue);
2350 break;
2351 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
2352 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
2353 break;
2354 case ATTR_NON_FULLSCREEN_BOUNDS:
Garfield Tan367b35a2017-12-13 12:16:21 -08002355 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002356 break;
2357 case ATTR_MIN_WIDTH:
2358 minWidth = Integer.parseInt(attrValue);
2359 break;
2360 case ATTR_MIN_HEIGHT:
2361 minHeight = Integer.parseInt(attrValue);
2362 break;
2363 case ATTR_PERSIST_TASK_VERSION:
2364 persistTaskVersion = Integer.parseInt(attrValue);
2365 break;
2366 default:
2367 if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
2368 taskDescription.restoreFromXml(attrName, attrValue);
2369 } else {
2370 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
2371 }
2372 }
2373 }
2374
2375 int event;
2376 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
2377 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
2378 if (event == XmlPullParser.START_TAG) {
2379 final String name = in.getName();
2380 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
2381 "TaskRecord: START_TAG name=" + name);
2382 if (TAG_AFFINITYINTENT.equals(name)) {
2383 affinityIntent = Intent.restoreFromXml(in);
2384 } else if (TAG_INTENT.equals(name)) {
2385 intent = Intent.restoreFromXml(in);
2386 } else if (TAG_ACTIVITY.equals(name)) {
2387 ActivityRecord activity =
2388 ActivityRecord.restoreFromXml(in, stackSupervisor);
2389 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
2390 activity);
2391 if (activity != null) {
2392 activities.add(activity);
2393 }
2394 } else {
Garfield Tan1e740192017-12-12 14:37:42 -08002395 handleUnknownTag(name, in);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002396 }
2397 }
2398 }
2399 if (!hasRootAffinity) {
2400 rootAffinity = affinity;
2401 } else if ("@".equals(rootAffinity)) {
2402 rootAffinity = null;
2403 }
2404 if (effectiveUid <= 0) {
2405 Intent checkIntent = intent != null ? intent : affinityIntent;
2406 effectiveUid = 0;
2407 if (checkIntent != null) {
2408 IPackageManager pm = AppGlobals.getPackageManager();
2409 try {
2410 ApplicationInfo ai = pm.getApplicationInfo(
2411 checkIntent.getComponent().getPackageName(),
2412 PackageManager.MATCH_UNINSTALLED_PACKAGES
2413 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
2414 if (ai != null) {
2415 effectiveUid = ai.uid;
2416 }
2417 } catch (RemoteException e) {
2418 }
2419 }
2420 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
2421 + ": effectiveUid=" + effectiveUid);
2422 }
2423
2424 if (persistTaskVersion < 1) {
2425 // We need to convert the resize mode of home activities saved before version one if
2426 // they are marked as RESIZE_MODE_RESIZEABLE to
2427 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
2428 // before version 1 and the system didn't resize home activities before then.
2429 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
2430 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
2431 }
2432 } else {
2433 // This activity has previously marked itself explicitly as both resizeable and
2434 // supporting picture-in-picture. Since there is no longer a requirement for
2435 // picture-in-picture activities to be resizeable, we can mark this simply as
2436 // resizeable and supporting picture-in-picture separately.
2437 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
2438 resizeMode = RESIZE_MODE_RESIZEABLE;
2439 supportsPictureInPicture = true;
2440 }
2441 }
2442
2443 final TaskRecord task = create(stackSupervisor.mService, taskId, intent, affinityIntent,
2444 affinity, rootAffinity, realActivity, origActivity, rootHasReset,
2445 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
2446 activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
2447 taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
2448 callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
2449 userSetupComplete, minWidth, minHeight);
Garfield Tan367b35a2017-12-13 12:16:21 -08002450 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
2451 task.setBounds(lastNonFullscreenBounds);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002452
2453 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
2454 activities.get(activityNdx).setTask(task);
2455 }
2456
2457 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
2458 return task;
2459 }
Garfield Tan1e740192017-12-12 14:37:42 -08002460
2461 void handleUnknownTag(String name, XmlPullParser in)
2462 throws IOException, XmlPullParserException {
2463 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
2464 XmlUtils.skipCurrentTag(in);
2465 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002466 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002467}