blob: e3433228f2de98c2b37cdd1956f05eb83af2a55e [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
Wale Ogunwale59507092018-10-29 09:00:30 -070017package com.android.server.wm;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018
Andrii Kulianab132ee2018-07-24 22:10:21 +080019import static android.app.ActivityTaskManager.INVALID_STACK_ID;
Wale Ogunwale98875612018-10-12 07:53:02 -070020import static android.app.ActivityTaskManager.INVALID_TASK_ID;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070021import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED;
22import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -070023import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
24import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070025import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
26import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
27import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
28import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Wale Ogunwale44f036f2017-09-29 05:09:09 -070029import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Evan Rosky1ac84462018-11-13 11:25:30 -080030import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Jorim Jaggi0a932142016-02-01 17:42:25 -080031import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Wale Ogunwale66e16852017-10-19 13:35:52 -070032import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Jorim Jaggi0a932142016-02-01 17:42:25 -080033import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
Wale Ogunwale66e16852017-10-19 13:35:52 -070034import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale3eadad72016-10-13 09:16:59 -070035import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
Jorim Jaggi0a932142016-02-01 17:42:25 -080036import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
37import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
38import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
39import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080040import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
41import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
42import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Wale Ogunwaled829d362016-02-10 19:24:49 -080043import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070044import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -080045import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070046import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080047import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
Suprabh Shukla7745c142016-03-07 18:21:10 -080048import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
Andrii Kulian036e3ad2017-04-19 10:55:10 -070049import static android.view.Display.DEFAULT_DISPLAY;
Garfield Tan891146c2018-10-09 12:14:00 -070050
Yunfan Chen0e7aff92018-12-05 16:35:32 -080051import static com.android.server.EventLogTags.WM_TASK_CREATED;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070052import static com.android.server.am.TaskRecordProto.ACTIVITIES;
Andrii Kulianab132ee2018-07-24 22:10:21 +080053import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070054import static com.android.server.am.TaskRecordProto.BOUNDS;
55import static com.android.server.am.TaskRecordProto.CONFIGURATION_CONTAINER;
56import static com.android.server.am.TaskRecordProto.FULLSCREEN;
57import static com.android.server.am.TaskRecordProto.ID;
58import static com.android.server.am.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
59import static com.android.server.am.TaskRecordProto.MIN_HEIGHT;
60import static com.android.server.am.TaskRecordProto.MIN_WIDTH;
61import static com.android.server.am.TaskRecordProto.ORIG_ACTIVITY;
62import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
63import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
64import static com.android.server.am.TaskRecordProto.STACK_ID;
Garfield Tan891146c2018-10-09 12:14:00 -070065import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
66import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
67import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
68import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
69import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
70import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
71import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
72import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
73import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
74import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
75import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
76import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
77import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
78import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
79import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
80import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Yunfan Chen0e7aff92018-12-05 16:35:32 -080081import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
82import static com.android.server.wm.WindowContainer.POSITION_TOP;
83import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
84import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Garfield Tan891146c2018-10-09 12:14:00 -070085
Winson Chung74666102017-02-22 17:49:24 -080086import static java.lang.Integer.MAX_VALUE;
87
Jorim Jaggie7d2b852017-08-28 17:55:15 +020088import android.annotation.IntDef;
Evan Rosky1ac84462018-11-13 11:25:30 -080089import android.annotation.NonNull;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020090import android.annotation.Nullable;
91import android.app.Activity;
92import android.app.ActivityManager;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020093import android.app.ActivityManager.TaskDescription;
94import android.app.ActivityManager.TaskSnapshot;
95import android.app.ActivityOptions;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070096import android.app.ActivityTaskManager;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020097import android.app.AppGlobals;
Winson Chungabfdcce2018-07-02 17:23:33 -070098import android.app.TaskInfo;
Garfield Tan891146c2018-10-09 12:14:00 -070099import android.app.WindowConfiguration;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200100import android.content.ComponentName;
101import android.content.Intent;
102import android.content.pm.ActivityInfo;
103import android.content.pm.ApplicationInfo;
104import android.content.pm.IPackageManager;
105import android.content.pm.PackageManager;
106import android.content.res.Configuration;
107import android.graphics.Rect;
108import android.os.Debug;
109import android.os.RemoteException;
Winson Chungfb44d212017-10-04 11:39:10 -0700110import android.os.SystemClock;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200111import android.os.Trace;
112import android.os.UserHandle;
113import android.provider.Settings;
114import android.service.voice.IVoiceInteractionSession;
115import android.util.DisplayMetrics;
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800116import android.util.EventLog;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200117import android.util.Slog;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700118import android.util.proto.ProtoOutputStream;
Evan Rosky1ac84462018-11-13 11:25:30 -0800119import android.view.DisplayInfo;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200120
121import com.android.internal.annotations.VisibleForTesting;
122import com.android.internal.app.IVoiceInteractor;
123import com.android.internal.util.XmlUtils;
Wale Ogunwale59507092018-10-29 09:00:30 -0700124import com.android.server.wm.ActivityStack.ActivityState;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200125
126import org.xmlpull.v1.XmlPullParser;
127import org.xmlpull.v1.XmlPullParserException;
128import org.xmlpull.v1.XmlSerializer;
129
130import java.io.IOException;
131import java.io.PrintWriter;
132import java.lang.annotation.Retention;
133import java.lang.annotation.RetentionPolicy;
134import java.util.ArrayList;
135import java.util.Objects;
136
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800137class TaskRecord extends ConfigurationContainer {
Wale Ogunwale98875612018-10-12 07:53:02 -0700138 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_ATM;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700139 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700140 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
Craig Mautnere0570202015-05-13 13:06:11 -0700141 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700142 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800143
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700144 private static final String ATTR_TASKID = "task_id";
Craig Mautner21d24a22014-04-23 11:45:37 -0700145 private static final String TAG_INTENT = "intent";
146 private static final String TAG_AFFINITYINTENT = "affinity_intent";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700147 private static final String ATTR_REALACTIVITY = "real_activity";
148 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
Craig Mautner21d24a22014-04-23 11:45:37 -0700149 private static final String ATTR_ORIGACTIVITY = "orig_activity";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700150 private static final String TAG_ACTIVITY = "activity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700151 private static final String ATTR_AFFINITY = "affinity";
Dianne Hackborn79228822014-09-16 11:11:23 -0700152 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700153 private static final String ATTR_ROOTHASRESET = "root_has_reset";
Dianne Hackborn13420f22014-07-18 15:43:56 -0700154 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
Craig Mautner21d24a22014-04-23 11:45:37 -0700155 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
156 private static final String ATTR_USERID = "user_id";
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800157 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700158 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700159 @Deprecated
Craig Mautner21d24a22014-04-23 11:45:37 -0700160 private static final String ATTR_TASKTYPE = "task_type";
Craig Mautner21d24a22014-04-23 11:45:37 -0700161 private static final String ATTR_LASTDESCRIPTION = "last_description";
162 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700163 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700164 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
Craig Mautnera228ae92014-07-09 05:44:55 -0700165 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
166 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
Winson Chungec396d62014-08-06 17:08:00 -0700167 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700168 private static final String ATTR_CALLING_UID = "calling_uid";
169 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Winson Chungd3395382016-12-13 11:49:09 -0800170 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800171 private static final String ATTR_RESIZE_MODE = "resize_mode";
Wale Ogunwale706ed792015-08-02 10:29:44 -0700172 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700173 private static final String ATTR_MIN_WIDTH = "min_width";
174 private static final String ATTR_MIN_HEIGHT = "min_height";
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700175 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Andrii Kulian18d75122016-03-27 20:20:28 -0700176
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700177 // Current version of the task record we persist. Used to check if we need to run any upgrade
178 // code.
179 private static final int PERSIST_TASK_VERSION = 1;
Craig Mautner21d24a22014-04-23 11:45:37 -0700180
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700181 private static final int INVALID_MIN_SIZE = -1;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800182
Winson Chung74666102017-02-22 17:49:24 -0800183 /**
184 * The modes to control how the stack is moved to the front when calling
185 * {@link TaskRecord#reparent}.
186 */
187 @Retention(RetentionPolicy.SOURCE)
188 @IntDef({
189 REPARENT_MOVE_STACK_TO_FRONT,
190 REPARENT_KEEP_STACK_AT_FRONT,
191 REPARENT_LEAVE_STACK_IN_PLACE
192 })
Wale Ogunwale66e16852017-10-19 13:35:52 -0700193 @interface ReparentMoveStackMode {}
Winson Chung74666102017-02-22 17:49:24 -0800194 // Moves the stack to the front if it was not at the front
Wale Ogunwale66e16852017-10-19 13:35:52 -0700195 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
Winson Chung74666102017-02-22 17:49:24 -0800196 // Only moves the stack to the front if it was focused or front most already
Wale Ogunwale66e16852017-10-19 13:35:52 -0700197 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
Winson Chung74666102017-02-22 17:49:24 -0800198 // Do not move the stack as a part of reparenting
Wale Ogunwale66e16852017-10-19 13:35:52 -0700199 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
Winson Chung74666102017-02-22 17:49:24 -0800200
Evan Rosky1ac84462018-11-13 11:25:30 -0800201 // The height/width divide used when fitting a task within a bounds with method
202 // {@link #fitWithinBounds}.
203 // We always want the task to to be visible in the bounds without affecting its size when
204 // fitting. To make sure this is the case, we don't adjust the task left or top side pass
205 // the input bounds right or bottom side minus the width or height divided by this value.
206 private static final int FIT_WITHIN_BOUNDS_DIVIDER = 3;
207
Garfield Tan9b1efea2017-12-05 16:43:46 -0800208 /**
209 * The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}.
210 */
211 private static TaskRecordFactory sTaskRecordFactory;
212
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 final int taskId; // Unique identifier for this task.
Dianne Hackborn79228822014-09-16 11:11:23 -0700214 String affinity; // The affinity name for this task, or null; may change identity.
215 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Dianne Hackborn91097de2014-04-04 18:02:06 -0700216 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
217 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Bryce Lee1a990e52018-04-23 10:54:11 -0700218 Intent intent; // The original intent that started the task. Note that this value can
219 // be null.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700221 int effectiveUid; // The current effective uid of the identity of this task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 ComponentName origActivity; // The non-alias activity component of the intent.
223 ComponentName realActivity; // The actual activity component that started the task.
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +0000224 boolean realActivitySuspended; // True if the actual activity component that started the
225 // task is suspended.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700226 boolean inRecents; // Actually in the recents list?
Winson Chungfb44d212017-10-04 11:39:10 -0700227 long lastActiveTime; // Last time this task was active in the current device session,
228 // including sleep. This time is initialized to the elapsed time when
229 // restored from disk.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700230 boolean isAvailable; // Is the activity available to be launched?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 boolean rootWasReset; // True if the intent at the root of the task had
232 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700233 boolean autoRemoveRecents; // If true, we should automatically remove the task from
234 // recents when activity finishes
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700235 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700236 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 -0800237
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700238 String stringName; // caching of toString() result.
Dianne Hackborn9da2d402012-03-15 13:43:08 -0700239 int userId; // user for which this task was created
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800240 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
241 // was changed.
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800242
243 int numFullscreen; // Number of fullscreen activities.
244
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800245 int mResizeMode; // The resize mode of this task and its activities.
246 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800247 private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
248 // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
249 // of the root activity.
Craig Mautner15df08a2015-04-01 12:17:18 -0700250 /** Can't be put in lockTask mode. */
251 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
Benjamin Franz469dd582015-06-09 14:24:36 +0100252 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700253 final static int LOCK_TASK_AUTH_PINNABLE = 1;
254 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
255 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
Benjamin Franz469dd582015-06-09 14:24:36 +0100256 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700257 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
Benjamin Franz469dd582015-06-09 14:24:36 +0100258 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
259 * lockTask task. */
260 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
Craig Mautner15df08a2015-04-01 12:17:18 -0700261 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
262
263 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800264
Winson Chung03a9bae2014-05-02 09:56:12 -0700265 // This represents the last resolved activity values for this task
266 // NOTE: This value needs to be persisted with each task
Craig Mautner648f69b2014-09-18 14:16:26 -0700267 TaskDescription lastTaskDescription = new TaskDescription();
Winson Chung03a9bae2014-05-02 09:56:12 -0700268
Craig Mautnerd2328952013-03-05 12:46:26 -0800269 /** List of all activities in the task arranged in history order */
Craig Mautner21d24a22014-04-23 11:45:37 -0700270 final ArrayList<ActivityRecord> mActivities;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800271
Andrii Kulian02b7a832016-10-06 23:11:56 -0700272 /** Current stack. Setter must always be used to update the value. */
273 private ActivityStack mStack;
Craig Mautnerd2328952013-03-05 12:46:26 -0800274
Dianne Hackborn68a06332017-11-15 17:54:18 -0800275 /** The process that had previously hosted the root activity of this task.
276 * Used to know that we should try harder to keep this process around, in case the
277 * user wants to return to it. */
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700278 private WindowProcessController mRootProcess;
Dianne Hackborn68a06332017-11-15 17:54:18 -0800279
Craig Mautner21d24a22014-04-23 11:45:37 -0700280 /** Takes on same value as first root activity */
281 boolean isPersistable = false;
Craig Mautnerffcfcaa2014-06-05 09:54:38 -0700282 int maxRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700283
284 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
285 * determining the order when restoring. Sign indicates whether last task movement was to front
286 * (positive) or back (negative). Absolute value indicates time. */
287 long mLastTimeMoved = System.currentTimeMillis();
288
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700289 /** If original intent did not allow relinquishing task identity, save that information */
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700290 private boolean mNeverRelinquishIdentity = true;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700291
Craig Mautner362449a2014-06-20 14:04:39 -0700292 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
293 // do not want to delete the stack when the task goes empty.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800294 private boolean mReuseTask = false;
Craig Mautner362449a2014-06-20 14:04:39 -0700295
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700296 CharSequence lastDescription; // Last description captured for this item.
297
Craig Mautnera228ae92014-07-09 05:44:55 -0700298 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Winson Chungec396d62014-08-06 17:08:00 -0700299 int mAffiliatedTaskColor; // color of the parent task affiliation.
Craig Mautnera228ae92014-07-09 05:44:55 -0700300 TaskRecord mPrevAffiliate; // previous task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800301 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700302 TaskRecord mNextAffiliate; // next task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800303 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700304
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700305 // For relaunching the task from recents as though it was launched by the original launcher.
306 int mCallingUid;
307 String mCallingPackage;
308
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700309 final ActivityTaskManagerService mService;
Craig Mautner21d24a22014-04-23 11:45:37 -0700310
Jorim Jaggi82c9dc92016-02-05 15:10:33 -0800311 private final Rect mTmpStableBounds = new Rect();
312 private final Rect mTmpNonDecorBounds = new Rect();
Evan Rosky1ac84462018-11-13 11:25:30 -0800313 private final Rect mTmpBounds = new Rect();
314 private final Rect mTmpInsets = new Rect();
Jorim Jaggi0a932142016-02-01 17:42:25 -0800315
Wale Ogunwale706ed792015-08-02 10:29:44 -0700316 // Last non-fullscreen bounds the task was launched in or resized to.
317 // The information is persisted and used to determine the appropriate stack to launch the
318 // task into on restore.
319 Rect mLastNonFullscreenBounds = null;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700320 // Minimal width and height of this task when it's resizeable. -1 means it should use the
321 // default minimal width/height.
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700322 int mMinWidth;
323 int mMinHeight;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700324
Chong Zhangfdcc4d42015-10-14 16:50:12 -0700325 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
326 // This number will be assigned when we evaluate OOM scores for all visible tasks.
327 int mLayerRank = -1;
328
Evan Roskyed6767f2018-10-26 17:21:06 -0700329 // When non-empty, this represents the bounds this task will be drawn at. This gets set during
330 // transient operations such as split-divider dragging and animations.
331 // TODO(b/119687367): This member is temporary.
332 final Rect mDisplayedBounds = new Rect();
333
Andrii Kulian1779e612016-10-12 21:58:25 -0700334 /** Helper object used for updating override configuration. */
335 private Configuration mTmpConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700336
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800337 // TODO: remove after unification
338 Task mTask;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800339
Garfield Tan9b1efea2017-12-05 16:43:46 -0800340 /**
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700341 * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
342 * ActivityInfo, Intent, TaskDescription)} instead.
Garfield Tan9b1efea2017-12-05 16:43:46 -0800343 */
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700344 TaskRecord(ActivityTaskManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700345 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700346 mService = service;
Suprabh Shukla23593142015-11-03 17:31:15 -0800347 userId = UserHandle.getUserId(info.applicationInfo.uid);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 taskId = _taskId;
Winson Chungfb44d212017-10-04 11:39:10 -0700349 lastActiveTime = SystemClock.elapsedRealtime();
Craig Mautnera228ae92014-07-09 05:44:55 -0700350 mAffiliatedTaskId = _taskId;
Dianne Hackborn91097de2014-04-04 18:02:06 -0700351 voiceSession = _voiceSession;
352 voiceInteractor = _voiceInteractor;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700353 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800354 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700355 mCallingUid = info.applicationInfo.uid;
356 mCallingPackage = info.packageName;
Martijn Coenend4a69702014-06-30 11:12:17 -0700357 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700358 setMinDimensions(info);
Winson730bf062016-03-31 18:04:56 -0700359 touchActiveTime();
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700360 mService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
Craig Mautner21d24a22014-04-23 11:45:37 -0700361 }
362
Garfield Tan9b1efea2017-12-05 16:43:46 -0800363 /**
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700364 * Don't use constructor directly.
365 * Use {@link #create(ActivityTaskManagerService, int, ActivityInfo,
Garfield Tan9b1efea2017-12-05 16:43:46 -0800366 * Intent, IVoiceInteractionSession, IVoiceInteractor)} instead.
367 */
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700368 TaskRecord(ActivityTaskManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200369 TaskDescription _taskDescription) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700370 mService = service;
Suprabh Shukla23593142015-11-03 17:31:15 -0800371 userId = UserHandle.getUserId(info.applicationInfo.uid);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700372 taskId = _taskId;
Winson Chungfb44d212017-10-04 11:39:10 -0700373 lastActiveTime = SystemClock.elapsedRealtime();
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700374 mAffiliatedTaskId = _taskId;
375 voiceSession = null;
376 voiceInteractor = null;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700377 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800378 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700379 mCallingUid = info.applicationInfo.uid;
380 mCallingPackage = info.packageName;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700381 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700382 setMinDimensions(info);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700383
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700384 isPersistable = true;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700385 // Clamp to [1, max].
386 maxRecents = Math.min(Math.max(info.maxRecents, 1),
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700387 ActivityTaskManager.getMaxAppRecentsLimitStatic());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700388
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700389 lastTaskDescription = _taskDescription;
Winson730bf062016-03-31 18:04:56 -0700390 touchActiveTime();
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700391 mService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700392 }
393
Garfield Tan9b1efea2017-12-05 16:43:46 -0800394 /**
395 * Don't use constructor directly. This is only used by XML parser.
396 */
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700397 TaskRecord(ActivityTaskManagerService service, int _taskId, Intent _intent,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800398 Intent _affinityIntent, String _affinity, String _rootAffinity,
399 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700400 boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800401 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
Winson Chungfb44d212017-10-04 11:39:10 -0700402 long lastTimeMoved, boolean neverRelinquishIdentity,
403 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
404 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Charles He2bf28322017-10-12 22:24:49 +0100405 int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
406 boolean userSetupComplete, int minWidth, int minHeight) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700407 mService = service;
408 taskId = _taskId;
409 intent = _intent;
410 affinityIntent = _affinityIntent;
411 affinity = _affinity;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800412 rootAffinity = _rootAffinity;
Craig Mautner21d24a22014-04-23 11:45:37 -0700413 voiceSession = null;
414 voiceInteractor = null;
415 realActivity = _realActivity;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800416 realActivitySuspended = _realActivitySuspended;
Craig Mautner21d24a22014-04-23 11:45:37 -0700417 origActivity = _origActivity;
418 rootWasReset = _rootWasReset;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700419 isAvailable = true;
Dianne Hackborn13420f22014-07-18 15:43:56 -0700420 autoRemoveRecents = _autoRemoveRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700421 askedCompatMode = _askedCompatMode;
Craig Mautner21d24a22014-04-23 11:45:37 -0700422 userId = _userId;
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800423 mUserSetupComplete = userSetupComplete;
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700424 effectiveUid = _effectiveUid;
Winson Chungfb44d212017-10-04 11:39:10 -0700425 lastActiveTime = SystemClock.elapsedRealtime();
Craig Mautner21d24a22014-04-23 11:45:37 -0700426 lastDescription = _lastDescription;
427 mActivities = activities;
428 mLastTimeMoved = lastTimeMoved;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700429 mNeverRelinquishIdentity = neverRelinquishIdentity;
Winson Chung2cb86c72014-06-25 12:03:30 -0700430 lastTaskDescription = _lastTaskDescription;
Craig Mautnera228ae92014-07-09 05:44:55 -0700431 mAffiliatedTaskId = taskAffiliation;
Winson Chungec396d62014-08-06 17:08:00 -0700432 mAffiliatedTaskColor = taskAffiliationColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700433 mPrevAffiliateTaskId = prevTaskId;
434 mNextAffiliateTaskId = nextTaskId;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700435 mCallingUid = callingUid;
436 mCallingPackage = callingPackage;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800437 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800438 mSupportsPictureInPicture = supportsPictureInPicture;
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700439 mMinWidth = minWidth;
440 mMinHeight = minHeight;
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700441 mService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800442 }
443
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800444 Task getTask() {
445 return mTask;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800446 }
447
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800448 void createTask(boolean onTop, boolean showForAllUsers) {
449 if (mTask != null) {
450 throw new IllegalArgumentException("mTask=" + mTask
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800451 + " already created for task=" + this);
452 }
453
454 final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800455 final StackWindowController stackController = getStack().getWindowContainerController();
456
457 if (DEBUG_STACK) {
458 Slog.i(TAG_WM, "TaskRecord: taskId=" + taskId
459 + " stack=" + stackController + " bounds=" + bounds);
460 }
461
462 final TaskStack stack = stackController.mContainer;
463 if (stack == null) {
464 throw new IllegalArgumentException("TaskRecord: invalid stack="
465 + stackController);
466 }
467 EventLog.writeEvent(WM_TASK_CREATED, taskId, stack.mStackId);
468 mTask = new Task(taskId, stack, userId, mService.mWindowManager, mResizeMode,
469 mSupportsPictureInPicture, lastTaskDescription, this);
470 final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
471
472 if (!mDisplayedBounds.isEmpty()) {
473 mTask.setOverrideDisplayedBounds(mDisplayedBounds);
474 }
475 // We only want to move the parents to the parents if we are creating this task at the
476 // top of its stack.
477 stack.addTask(mTask, position, showForAllUsers, onTop /* moveParents */);
Bryce Lee04ab3462017-04-10 15:06:33 -0700478 }
479
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800480 void setTask(Task task) {
481 mTask = task;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800482 }
483
Garfield Tan347bd602018-12-21 15:11:12 -0800484 void cleanUpResourcesForDestroy() {
485 if (!mActivities.isEmpty()) {
486 return;
487 }
488
489 // This task is going away, so save the last state if necessary.
490 saveLaunchingStateIfNeeded();
491
492 // TODO: VI what about activity?
493 final boolean isVoiceSession = voiceSession != null;
494 if (isVoiceSession) {
495 try {
496 voiceSession.taskFinished(intent, taskId);
497 } catch (RemoteException e) {
498 }
499 }
500 if (autoRemoveFromRecents() || isVoiceSession) {
501 // Task creator asked to remove this when done, or this task was a voice
502 // interaction, so it should not remain on the recent tasks list.
503 mService.mStackSupervisor.mRecentTasks.remove(this);
504 }
505
506 removeWindowContainer();
507 }
508
509 @VisibleForTesting
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800510 void removeWindowContainer() {
Bryce Lee2b8e0372018-04-05 17:01:37 -0700511 mService.getLockTaskController().clearLockedTask(this);
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800512 if (mTask == null) {
513 if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + taskId);
514 return;
515 }
516 mTask.removeIfPossible();
517 mTask = null;
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700518 if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800519 // Reset current bounds for task whose bounds shouldn't be persisted so it uses
520 // default configuration the next time it launches.
521 updateOverrideConfiguration(null);
522 }
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700523 mService.getTaskChangeNotificationController().notifyTaskRemoved(taskId);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800524 }
525
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100526 public void onSnapshotChanged(TaskSnapshot snapshot) {
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700527 mService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(taskId, snapshot);
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100528 }
529
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800530 void setResizeMode(int resizeMode) {
531 if (mResizeMode == resizeMode) {
532 return;
533 }
534 mResizeMode = resizeMode;
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800535 mTask.setResizeable(resizeMode);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800536 mService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
537 mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800538 }
539
540 void setTaskDockedResizing(boolean resizing) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800541 if (mTask == null) {
542 Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + taskId + " not found.");
543 return;
544 }
545 mTask.setTaskDockedResizing(resizing);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800546 }
547
Wale Ogunwale1666e312016-12-16 11:27:18 -0800548 // TODO: Consolidate this with the resize() method below.
Wale Ogunwale1666e312016-12-16 11:27:18 -0800549 public void requestResize(Rect bounds, int resizeMode) {
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700550 mService.resizeTask(taskId, bounds, resizeMode);
Wale Ogunwale1666e312016-12-16 11:27:18 -0800551 }
552
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800553 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800554 mService.mWindowManager.deferSurfaceLayout();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800555
Bryce Leef3c6a472017-11-14 14:53:06 -0800556 try {
557 if (!isResizeable()) {
558 Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
559 return true;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800560 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800561
Bryce Leef3c6a472017-11-14 14:53:06 -0800562 // If this is a forced resize, let it go through even if the bounds is not changing,
563 // as we might need a relayout due to surface size change (to/from fullscreen).
564 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
Evan Roskydfe3da72018-10-26 17:21:06 -0700565 if (equivalentRequestedOverrideBounds(bounds) && !forced) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800566 // Nothing to do here...
567 return true;
568 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800569
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800570 if (mTask == null) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800571 // Task doesn't exist in window manager yet (e.g. was restored from recents).
572 // All we can do for now is update the bounds so it can be used when the task is
573 // added to window manager.
574 updateOverrideConfiguration(bounds);
575 if (!inFreeformWindowingMode()) {
576 // re-restore the task so it can have the proper stack association.
577 mService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
578 }
579 return true;
580 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800581
Bryce Leef3c6a472017-11-14 14:53:06 -0800582 if (!canResizeToBounds(bounds)) {
583 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
584 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
585 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800586
Bryce Leef3c6a472017-11-14 14:53:06 -0800587 // Do not move the task to another stack here.
588 // This method assumes that the task is already placed in the right stack.
589 // we do not mess with that decision and we only do the resize!
590
591 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId);
592
593 final boolean updatedConfig = updateOverrideConfiguration(bounds);
594 // This variable holds information whether the configuration didn't change in a significant
595
596 // way and the activity was kept the way it was. If it's false, it means the activity
597 // had
598 // to be relaunched due to configuration change.
599 boolean kept = true;
600 if (updatedConfig) {
601 final ActivityRecord r = topRunningActivityLocked();
602 if (r != null && !deferResume) {
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800603 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
Bryce Leef3c6a472017-11-14 14:53:06 -0800604 preserveWindow);
Garfield Tanb9151182018-06-25 16:29:21 -0700605 // Preserve other windows for resizing because if resizing happens when there
606 // is a dialog activity in the front, the activity that still shows some
607 // content to the user will become black and cause flickers. Note in most cases
608 // this won't cause tons of irrelevant windows being preserved because only
609 // activities in this task may experience a bounds change. Configs for other
610 // activities stay the same.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800611 mService.mRootActivityContainer.ensureActivitiesVisible(r, 0, preserveWindow);
Bryce Leef3c6a472017-11-14 14:53:06 -0800612 if (!kept) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800613 mService.mRootActivityContainer.resumeFocusedStacksTopActivities();
Bryce Leef3c6a472017-11-14 14:53:06 -0800614 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800615 }
616 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800617 mTask.resize(kept, forced);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800618
Garfield Tan891146c2018-10-09 12:14:00 -0700619 saveLaunchingStateIfNeeded();
620
Bryce Leef3c6a472017-11-14 14:53:06 -0800621 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
622 return kept;
623 } finally {
624 mService.mWindowManager.continueSurfaceLayout();
625 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800626 }
627
628 // TODO: Investigate combining with the resize() method above.
629 void resizeWindowContainer() {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800630 mTask.resize(false /* relayout */, false /* forced */);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800631 }
632
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800633 void getWindowContainerBounds(Rect bounds) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800634 if (mTask != null) {
635 mTask.getBounds(bounds);
636 } else {
637 bounds.setEmpty();
638 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800639 }
640
Winson Chung74666102017-02-22 17:49:24 -0800641 /**
642 * Convenience method to reparent a task to the top or bottom position of the stack.
643 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700644 boolean reparent(ActivityStack preferredStack, boolean toTop,
645 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
646 String reason) {
647 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
648 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung5af42fc2017-03-24 17:11:33 -0700649 }
650
651 /**
652 * Convenience method to reparent a task to the top or bottom position of the stack, with
653 * an option to skip scheduling the picture-in-picture mode change.
654 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700655 boolean reparent(ActivityStack preferredStack, boolean toTop,
656 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
657 boolean schedulePictureInPictureModeChange, String reason) {
658 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
Winson Chung5af42fc2017-03-24 17:11:33 -0700659 deferResume, schedulePictureInPictureModeChange, reason);
660 }
661
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700662 /** Convenience method to reparent a task to a specific position of the stack. */
663 boolean reparent(ActivityStack preferredStack, int position,
664 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
665 String reason) {
666 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
Winson Chung5af42fc2017-03-24 17:11:33 -0700667 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800668 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800669
Winson Chung74666102017-02-22 17:49:24 -0800670 /**
671 * Reparents the task into a preferred stack, creating it if necessary.
672 *
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700673 * @param preferredStack the target stack to move this task
Winson Chung74666102017-02-22 17:49:24 -0800674 * @param position the position to place this task in the new stack
675 * @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 -0700676 * reparenting to be drawn and animated in
Winson Chung74666102017-02-22 17:49:24 -0800677 * @param moveStackMode whether or not to move the stack to the front always, only if it was
Winson Chung5af42fc2017-03-24 17:11:33 -0700678 * previously focused & in front, or never
Winson Chung74666102017-02-22 17:49:24 -0800679 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
Winson Chung5af42fc2017-03-24 17:11:33 -0700680 * have changed as a result of this reparenting
681 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
682 * change. Callers may set this to false if they are explicitly scheduling PiP mode
683 * changes themselves, like during the PiP animation
Winson Chung74666102017-02-22 17:49:24 -0800684 * @param reason the caller of this reparenting
Winson Chung5af42fc2017-03-24 17:11:33 -0700685 * @return whether the task was reparented
Winson Chung74666102017-02-22 17:49:24 -0800686 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700687 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700688 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700689 boolean reparent(ActivityStack preferredStack, int position,
690 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
691 boolean schedulePictureInPictureModeChange, String reason) {
Winson Chung74666102017-02-22 17:49:24 -0800692 final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800693 final RootActivityContainer root = mService.mRootActivityContainer;
Winson Chung74666102017-02-22 17:49:24 -0800694 final WindowManagerService windowManager = mService.mWindowManager;
695 final ActivityStack sourceStack = getStack();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700696 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
Winson Chung74666102017-02-22 17:49:24 -0800697 position == MAX_VALUE);
698 if (toStack == sourceStack) {
699 return false;
700 }
Andrii Kulianb850ea52017-12-12 23:49:10 -0800701 if (!canBeLaunchedOnDisplay(toStack.mDisplayId)) {
702 return false;
703 }
Winson Chung74666102017-02-22 17:49:24 -0800704
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700705 final int toStackWindowingMode = toStack.getWindowingMode();
Winson Chung74666102017-02-22 17:49:24 -0800706 final ActivityRecord topActivity = getTopActivity();
707
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800708 final boolean mightReplaceWindow = topActivity != null
709 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
Winson Chung74666102017-02-22 17:49:24 -0800710 if (mightReplaceWindow) {
711 // We are about to relaunch the activity because its configuration changed due to
712 // being maximized, i.e. size change. The activity will first remove the old window
713 // and then add a new one. This call will tell window manager about this, so it can
714 // preserve the old window until the new one is drawn. This prevents having a gap
715 // between the removal and addition, in which no window is visible. We also want the
716 // entrance of the new window to be properly animated.
717 // Note here we always set the replacing window first, as the flags might be needed
718 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
719 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
720 }
721
722 windowManager.deferSurfaceLayout();
723 boolean kept = true;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800724 try {
Winson Chung74666102017-02-22 17:49:24 -0800725 final ActivityRecord r = topRunningActivityLocked();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800726 final boolean wasFocused = r != null && root.isTopDisplayFocusedStack(sourceStack)
Winson Chung74666102017-02-22 17:49:24 -0800727 && (topRunningActivityLocked() == r);
Bryce Leec4ab62a2018-03-05 14:19:26 -0800728 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
Winson Chung95f8f0e2017-03-24 09:20:17 -0700729 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
Winson Chung74666102017-02-22 17:49:24 -0800730
731 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
732 // Whenever we are moving the top activity from the front stack we want to make sure to
733 // move the stack to the front.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700734 final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
Winson Chung74666102017-02-22 17:49:24 -0800735 && (sourceStack.topRunningActivityLocked() == r);
736
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800737 // Adjust the position for the new parent stack as needed.
Winson Chung74666102017-02-22 17:49:24 -0800738 position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800739
740 // Must reparent first in window manager to avoid a situation where AM can delete the
741 // we are coming from in WM before we reparent because it became empty.
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800742 mTask.reparent(toStack.getWindowContainerController(), position,
Wale Ogunwale2719cc12017-04-14 09:45:27 -0700743 moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800744
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700745 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
746 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
Winson Chung74666102017-02-22 17:49:24 -0800747 // Move the task
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700748 sourceStack.removeTask(this, reason, moveStackToFront
749 ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
Winson Chung5af42fc2017-03-24 17:11:33 -0700750 toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800751
Winson Chung5af42fc2017-03-24 17:11:33 -0700752 if (schedulePictureInPictureModeChange) {
753 // Notify of picture-in-picture mode changes
754 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
755 }
Winson Chung74666102017-02-22 17:49:24 -0800756
757 // TODO: Ensure that this is actually necessary here
758 // Notify the voice session if required
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800759 if (voiceSession != null) {
760 try {
761 voiceSession.taskStarted(intent, taskId);
762 } catch (RemoteException e) {
763 }
764 }
Winson Chung74666102017-02-22 17:49:24 -0800765
766 // If the task had focus before (or we're requested to move focus), move focus to the
767 // new stack by moving the stack to the front.
Winson Chung95f8f0e2017-03-24 09:20:17 -0700768 if (r != null) {
769 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
770 wasPaused, reason);
771 }
Winson Chung74666102017-02-22 17:49:24 -0800772 if (!animate) {
Jorim Jaggifa9ed962018-01-25 00:16:49 +0100773 mService.mStackSupervisor.mNoAnimActivities.add(topActivity);
Winson Chung74666102017-02-22 17:49:24 -0800774 }
775
776 // We might trigger a configuration change. Save the current task bounds for freezing.
777 // TODO: Should this call be moved inside the resize method in WM?
778 toStack.prepareFreezingTaskBounds();
779
780 // Make sure the task has the appropriate bounds/size for the stack it is in.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700781 final boolean toStackSplitScreenPrimary =
782 toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Evan Roskydfe3da72018-10-26 17:21:06 -0700783 final Rect configBounds = getRequestedOverrideBounds();
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700784 if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
785 || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
Evan Roskydfe3da72018-10-26 17:21:06 -0700786 && !Objects.equals(configBounds, toStack.getRequestedOverrideBounds())) {
787 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
788 !mightReplaceWindow, deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700789 } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Winson Chung74666102017-02-22 17:49:24 -0800790 Rect bounds = getLaunchBounds();
791 if (bounds == null) {
Bryce Leeec55eb02017-12-05 20:51:27 -0800792 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Bryce Leef3c6a472017-11-14 14:53:06 -0800793 bounds = configBounds;
Winson Chung74666102017-02-22 17:49:24 -0800794 }
795 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700796 } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
797 if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
Matthew Ng330757d2017-02-28 14:19:17 -0800798 // Move recents to front so it is not behind home stack when going into docked
799 // mode
800 mService.mStackSupervisor.moveRecentsStackToFront(reason);
801 }
Evan Roskydfe3da72018-10-26 17:21:06 -0700802 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
803 !mightReplaceWindow, deferResume);
Winson Chung74666102017-02-22 17:49:24 -0800804 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800805 } finally {
Winson Chung74666102017-02-22 17:49:24 -0800806 windowManager.continueSurfaceLayout();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800807 }
Winson Chung74666102017-02-22 17:49:24 -0800808
809 if (mightReplaceWindow) {
810 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
811 // window), we need to clear the replace window settings. Otherwise, we schedule a
812 // timeout to remove the old window if the replacing window is not coming in time.
813 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
814 }
815
816 if (!deferResume) {
817 // The task might have already been running and its visibility needs to be synchronized
818 // with the visibility of the stack / windows.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800819 root.ensureActivitiesVisible(null, 0, !mightReplaceWindow);
820 root.resumeFocusedStacksTopActivities();
Winson Chung74666102017-02-22 17:49:24 -0800821 }
822
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700823 // TODO: Handle incorrect request to move before the actual move, not after.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700824 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700825 DEFAULT_DISPLAY, toStack);
Winson Chung74666102017-02-22 17:49:24 -0800826
Winson Chungdff7a732017-12-11 12:17:06 -0800827 return (preferredStack == toStack);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800828 }
829
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700830 /**
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800831 * @return True if the windows of tasks being moved to the target stack from the source stack
832 * should be replaced, meaning that window manager will keep the old window around until the new
833 * is ready.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700834 */
835 private static boolean replaceWindowsOnTaskMove(
836 int sourceWindowingMode, int targetWindowingMode) {
837 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
838 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
839 }
840
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800841 void cancelWindowTransition() {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800842 if (mTask == null) {
843 Slog.w(TAG_WM, "cancelWindowTransition: taskId " + taskId + " not found.");
844 return;
845 }
846 mTask.cancelTaskWindowTransition();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800847 }
848
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100849 /**
850 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
851 */
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100852 TaskSnapshot getSnapshot(boolean reducedResolution) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100853
854 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
855 // synchronized between AM and WM.
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100856 return mService.mWindowManager.getTaskSnapshot(taskId, userId, reducedResolution);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800857 }
858
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800859 void touchActiveTime() {
Winson Chungfb44d212017-10-04 11:39:10 -0700860 lastActiveTime = SystemClock.elapsedRealtime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700862
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 long getInactiveDuration() {
Winson Chungfb44d212017-10-04 11:39:10 -0700864 return SystemClock.elapsedRealtime() - lastActiveTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700866
Winson Chungfee26772014-08-05 12:21:52 -0700867 /** Sets the original intent, and the calling uid and package. */
868 void setIntent(ActivityRecord r) {
Winson Chungfee26772014-08-05 12:21:52 -0700869 mCallingUid = r.launchedFromUid;
870 mCallingPackage = r.launchedFromPackage;
Craig Mautner15df08a2015-04-01 12:17:18 -0700871 setIntent(r.intent, r.info);
Charles He2bf28322017-10-12 22:24:49 +0100872 setLockTaskAuth(r);
Winson Chungfee26772014-08-05 12:21:52 -0700873 }
874
875 /** Sets the original intent, _without_ updating the calling uid or package. */
876 private void setIntent(Intent _intent, ActivityInfo info) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700877 if (intent == null) {
878 mNeverRelinquishIdentity =
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700879 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700880 } else if (mNeverRelinquishIdentity) {
881 return;
882 }
883
884 affinity = info.taskAffinity;
Dianne Hackborn79228822014-09-16 11:11:23 -0700885 if (intent == null) {
886 // If this task already has an intent associated with it, don't set the root
887 // affinity -- we don't want it changing after initially set, but the initially
888 // set value may be null.
889 rootAffinity = affinity;
890 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700891 effectiveUid = info.applicationInfo.uid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700892 stringName = null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800893
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800894 if (info.targetActivity == null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800895 if (_intent != null) {
896 // If this Intent has a selector, we want to clear it for the
897 // recent task since it is not relevant if the user later wants
898 // to re-launch the app.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700899 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800900 _intent = new Intent(_intent);
901 _intent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700902 _intent.setSourceBounds(null);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800903 }
904 }
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700905 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800906 intent = _intent;
907 realActivity = _intent != null ? _intent.getComponent() : null;
908 origActivity = null;
909 } else {
910 ComponentName targetComponent = new ComponentName(
911 info.packageName, info.targetActivity);
912 if (_intent != null) {
913 Intent targetIntent = new Intent(_intent);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800914 targetIntent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700915 targetIntent.setSourceBounds(null);
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700916 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
Dianne Hackborn7f96b792012-05-29 18:46:45 -0700917 "Setting Intent of " + this + " to target " + targetIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800918 intent = targetIntent;
919 realActivity = targetComponent;
920 origActivity = _intent.getComponent();
921 } else {
922 intent = null;
923 realActivity = targetComponent;
924 origActivity = new ComponentName(info.packageName, info.name);
925 }
926 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700927
Craig Mautner47b20ba2014-09-17 17:23:44 -0700928 final int intentFlags = intent == null ? 0 : intent.getFlags();
929 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800930 // Once we are set to an Intent with this flag, we count this
931 // task as having a true root activity.
932 rootWasReset = true;
933 }
Dianne Hackborn09233282014-04-30 11:33:59 -0700934 userId = UserHandle.getUserId(info.applicationInfo.uid);
Winson Chung36f3f032016-09-08 23:29:43 +0000935 mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
936 USER_SETUP_COMPLETE, 0, userId) != 0;
Craig Mautner41db4a72014-05-07 17:20:56 -0700937 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700938 // If the activity itself has requested auto-remove, then just always do it.
939 autoRemoveRecents = true;
Wale Ogunwale843bfb92015-03-27 11:06:48 -0700940 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
941 == FLAG_ACTIVITY_NEW_DOCUMENT) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700942 // If the caller has not asked for the document to be retained, then we may
943 // want to turn on auto-remove, depending on whether the target has set its
944 // own document launch mode.
945 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
946 autoRemoveRecents = false;
947 } else {
948 autoRemoveRecents = true;
949 }
950 } else {
951 autoRemoveRecents = false;
Craig Mautner41db4a72014-05-07 17:20:56 -0700952 }
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800953 mResizeMode = info.resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800954 mSupportsPictureInPicture = info.supportsPictureInPicture();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800955 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800956
Andrii Kulian2e751b82016-03-16 16:59:32 -0700957 /** Sets the original minimal width and height. */
958 private void setMinDimensions(ActivityInfo info) {
959 if (info != null && info.windowLayout != null) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700960 mMinWidth = info.windowLayout.minWidth;
961 mMinHeight = info.windowLayout.minHeight;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700962 } else {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700963 mMinWidth = INVALID_MIN_SIZE;
964 mMinHeight = INVALID_MIN_SIZE;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700965 }
966 }
967
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800968 /**
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700969 * Return true if the input activity has the same intent filter as the intent this task
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800970 * record is based on (normally the root activity intent).
971 */
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700972 boolean isSameIntentFilter(ActivityRecord r) {
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800973 final Intent intent = new Intent(r.intent);
974 // Correct the activity intent for aliasing. The task record intent will always be based on
975 // the real activity that will be launched not the alias, so we need to use an intent with
976 // the component name pointing to the real activity not the alias in the activity record.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800977 intent.setComponent(r.mActivityComponent);
Bryce Lee1a990e52018-04-23 10:54:11 -0700978 return intent.filterEquals(this.intent);
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800979 }
980
Wale Ogunwale66e16852017-10-19 13:35:52 -0700981 boolean returnsToHomeStack() {
982 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
Bryce Lee1a990e52018-04-23 10:54:11 -0700983 return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700984 }
985
Craig Mautnera228ae92014-07-09 05:44:55 -0700986 void setPrevAffiliate(TaskRecord prevAffiliate) {
987 mPrevAffiliate = prevAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800988 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700989 }
990
991 void setNextAffiliate(TaskRecord nextAffiliate) {
992 mNextAffiliate = nextAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800993 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700994 }
995
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700996 <T extends ActivityStack> T getStack() {
997 return (T) mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700998 }
999
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001000 /**
1001 * Must be used for setting parent stack because it performs configuration updates.
1002 * Must be called after adding task as a child to the stack.
1003 */
Andrii Kulian02b7a832016-10-06 23:11:56 -07001004 void setStack(ActivityStack stack) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001005 if (stack != null && !stack.isInStackLocked(this)) {
1006 throw new IllegalStateException("Task must be added as a Stack child first.");
1007 }
Bryce Lee84730a02018-04-03 14:10:04 -07001008 final ActivityStack oldStack = mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -07001009 mStack = stack;
Bryce Lee84730a02018-04-03 14:10:04 -07001010
1011 // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
1012 // {@link ActivityRecord} from its current {@link ActivityStack}.
1013
1014 if (oldStack != mStack) {
1015 for (int i = getChildCount() - 1; i >= 0; --i) {
1016 final ActivityRecord activity = getChildAt(i);
1017
1018 if (oldStack != null) {
1019 oldStack.onActivityRemovedFromStack(activity);
1020 }
1021
1022 if (mStack != null) {
1023 stack.onActivityAddedToStack(activity);
1024 }
1025 }
1026 }
1027
Andrii Kulian1779e612016-10-12 21:58:25 -07001028 onParentChanged();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001029 }
1030
1031 /**
1032 * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
1033 */
1034 int getStackId() {
1035 return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
1036 }
1037
Andrii Kulian1779e612016-10-12 21:58:25 -07001038 @Override
1039 protected int getChildCount() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001040 return mActivities.size();
Andrii Kulian1779e612016-10-12 21:58:25 -07001041 }
1042
1043 @Override
chaviw82a0ba82018-03-15 14:26:29 -07001044 protected ActivityRecord getChildAt(int index) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001045 return mActivities.get(index);
Andrii Kulian1779e612016-10-12 21:58:25 -07001046 }
1047
1048 @Override
1049 protected ConfigurationContainer getParent() {
1050 return mStack;
1051 }
1052
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001053 @Override
Wale Ogunwale98d62312017-07-12 09:24:56 -07001054 protected void onParentChanged() {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001055 super.onParentChanged();
Wale Ogunwaled32da472018-11-16 07:19:28 -08001056 mService.mRootActivityContainer.updateUIDsPresentOnDisplay();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001057 }
1058
Craig Mautnera228ae92014-07-09 05:44:55 -07001059 // Close up recents linked list.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001060 private void closeRecentsChain() {
Craig Mautnera228ae92014-07-09 05:44:55 -07001061 if (mPrevAffiliate != null) {
1062 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
1063 }
1064 if (mNextAffiliate != null) {
1065 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
1066 }
1067 setPrevAffiliate(null);
1068 setNextAffiliate(null);
1069 }
1070
Winson Chung740c3ac2014-11-12 16:14:38 -08001071 void removedFromRecents() {
Dianne Hackborn852975d2014-08-22 17:42:43 -07001072 closeRecentsChain();
1073 if (inRecents) {
1074 inRecents = false;
Winson Chung740c3ac2014-11-12 16:14:38 -08001075 mService.notifyTaskPersisterLocked(this, false);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001076 }
Jorim Jaggif9084ec2017-01-16 13:16:59 +01001077
Dianne Hackborn68a06332017-11-15 17:54:18 -08001078 clearRootProcess();
1079
Jorim Jaggif9084ec2017-01-16 13:16:59 +01001080 // TODO: Use window container controller once tasks are better synced between AM and WM
1081 mService.mWindowManager.notifyTaskRemovedFromRecents(taskId, userId);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001082 }
1083
Craig Mautnera228ae92014-07-09 05:44:55 -07001084 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
1085 closeRecentsChain();
1086 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
Winson Chungec396d62014-08-06 17:08:00 -07001087 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
Craig Mautnera228ae92014-07-09 05:44:55 -07001088 // Find the end
1089 while (taskToAffiliateWith.mNextAffiliate != null) {
1090 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate;
1091 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1092 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1093 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1094 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1095 nextRecents.setPrevAffiliate(null);
1096 }
1097 taskToAffiliateWith.setNextAffiliate(null);
1098 break;
1099 }
1100 taskToAffiliateWith = nextRecents;
1101 }
1102 taskToAffiliateWith.setNextAffiliate(this);
1103 setPrevAffiliate(taskToAffiliateWith);
1104 setNextAffiliate(null);
1105 }
1106
Winson Chung1147c402014-05-14 11:05:00 -07001107 /** Returns the intent for the root activity for this task */
1108 Intent getBaseIntent() {
1109 return intent != null ? intent : affinityIntent;
1110 }
1111
Winson Chung3b3f4642014-04-22 10:08:18 -07001112 /** Returns the first non-finishing activity from the root. */
1113 ActivityRecord getRootActivity() {
1114 for (int i = 0; i < mActivities.size(); i++) {
1115 final ActivityRecord r = mActivities.get(i);
1116 if (r.finishing) {
1117 continue;
1118 }
1119 return r;
1120 }
1121 return null;
1122 }
1123
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001124 ActivityRecord getTopActivity() {
Bryce Lee9f6affd2017-09-01 09:18:35 -07001125 return getTopActivity(true /* includeOverlays */);
1126 }
1127
1128 ActivityRecord getTopActivity(boolean includeOverlays) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001129 for (int i = mActivities.size() - 1; i >= 0; --i) {
1130 final ActivityRecord r = mActivities.get(i);
Bryce Lee9f6affd2017-09-01 09:18:35 -07001131 if (r.finishing || (!includeOverlays && r.mTaskOverlay)) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001132 continue;
1133 }
1134 return r;
1135 }
1136 return null;
1137 }
1138
Filip Gruszczynski3e85ba22015-10-05 22:48:30 -07001139 ActivityRecord topRunningActivityLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001140 if (mStack != null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001141 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1142 ActivityRecord r = mActivities.get(activityNdx);
Chong Zhang87761972016-08-22 13:53:24 -07001143 if (!r.finishing && r.okToShowLocked()) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001144 return r;
1145 }
Craig Mautner6b74cb52013-09-27 17:02:21 -07001146 }
1147 }
1148 return null;
1149 }
1150
Jorim Jaggi172e99f2017-10-20 14:33:18 +02001151 boolean isVisible() {
1152 for (int i = mActivities.size() - 1; i >= 0; --i) {
1153 final ActivityRecord r = mActivities.get(i);
1154 if (r.visible) {
1155 return true;
1156 }
1157 }
1158 return false;
1159 }
1160
Jorim Jaggiea039a82017-08-02 14:37:49 +02001161 void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
1162 if (mStack != null) {
1163 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1164 ActivityRecord r = mActivities.get(activityNdx);
Jorim Jaggi02f1d2f2017-08-04 14:29:16 +02001165 if (!r.finishing && r.okToShowLocked() && r.visibleIgnoringKeyguard) {
Jorim Jaggiea039a82017-08-02 14:37:49 +02001166 outActivities.add(r);
1167 }
1168 }
1169 }
1170 }
1171
Wale Ogunwale3b232392016-05-13 15:37:13 -07001172 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001173 if (mStack != null) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001174 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1175 ActivityRecord r = mActivities.get(activityNdx);
1176 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
Chong Zhang87761972016-08-22 13:53:24 -07001177 || r.finishing || !r.okToShowLocked()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001178 continue;
1179 }
1180 return r;
1181 }
1182 }
1183 return null;
1184 }
1185
Winson Chung61c9e5a2017-10-11 10:39:32 -07001186 /**
1187 * Return the number of running activities, and the number of non-finishing/initializing
1188 * activities in the provided {@param reportOut} respectively.
1189 */
1190 void getNumRunningActivities(TaskActivitiesReport reportOut) {
1191 reportOut.reset();
1192 for (int i = mActivities.size() - 1; i >= 0; --i) {
1193 final ActivityRecord r = mActivities.get(i);
1194 if (r.finishing) {
1195 continue;
1196 }
1197
1198 reportOut.base = r;
1199
1200 // Increment the total number of non-finishing activities
1201 reportOut.numActivities++;
1202
Bryce Lee7ace3952018-02-16 14:34:32 -08001203 if (reportOut.top == null || (reportOut.top.isState(ActivityState.INITIALIZING))) {
Winson Chung61c9e5a2017-10-11 10:39:32 -07001204 reportOut.top = r;
1205 // Reset the number of running activities until we hit the first non-initializing
1206 // activity
1207 reportOut.numRunning = 0;
1208 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001209 if (r.attachedToProcess()) {
Winson Chung61c9e5a2017-10-11 10:39:32 -07001210 // Increment the number of actually running activities
1211 reportOut.numRunning++;
1212 }
1213 }
1214 }
1215
Chong Zhang87761972016-08-22 13:53:24 -07001216 boolean okToShowLocked() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001217 // NOTE: If {@link TaskRecord#topRunningActivity} return is not null then it is
Chong Zhang87761972016-08-22 13:53:24 -07001218 // okay to show the activity when locked.
1219 return mService.mStackSupervisor.isCurrentProfileLocked(userId)
1220 || topRunningActivityLocked() != null;
1221 }
1222
Craig Mautner3b475fe2013-12-16 15:58:31 -08001223 /** Call after activity movement or finish to make sure that frontOfTask is set correctly */
Bryce Leed71317c2017-02-07 14:27:22 -08001224 final void setFrontOfTask() {
1225 boolean foundFront = false;
Craig Mautner3b475fe2013-12-16 15:58:31 -08001226 final int numActivities = mActivities.size();
Craig Mautner704e40b2013-12-18 16:43:51 -08001227 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
Craig Mautner3b475fe2013-12-16 15:58:31 -08001228 final ActivityRecord r = mActivities.get(activityNdx);
1229 if (foundFront || r.finishing) {
1230 r.frontOfTask = false;
1231 } else {
1232 r.frontOfTask = true;
1233 // Set frontOfTask false for every following activity.
1234 foundFront = true;
1235 }
1236 }
Craig Mautner9587ee02014-06-23 15:00:10 +00001237 if (!foundFront && numActivities > 0) {
1238 // All activities of this task are finishing. As we ought to have a frontOfTask
1239 // activity, make the bottom activity front.
1240 mActivities.get(0).frontOfTask = true;
1241 }
Craig Mautner3b475fe2013-12-16 15:58:31 -08001242 }
1243
Craig Mautnerde4ef022013-04-07 19:01:33 -07001244 /**
Craig Mautner3b475fe2013-12-16 15:58:31 -08001245 * Reorder the history stack so that the passed activity is brought to the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001246 */
1247 final void moveActivityToFrontLocked(ActivityRecord newTop) {
Wale Ogunwale0fc365c2015-05-25 19:35:42 -07001248 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
1249 "Removing and adding activity " + newTop
1250 + " to stack at top callers=" + Debug.getCallers(4));
Craig Mautnerde4ef022013-04-07 19:01:33 -07001251
Craig Mautnerde4ef022013-04-07 19:01:33 -07001252 mActivities.remove(newTop);
1253 mActivities.add(newTop);
Bryce Leed58d7b32017-09-08 15:55:22 -07001254
1255 // Make sure window manager is aware of the position change.
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001256 mTask.positionChildAtTop(newTop.mAppWindowToken);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001257 updateEffectiveIntent();
Craig Mautner3b475fe2013-12-16 15:58:31 -08001258
Bryce Leed71317c2017-02-07 14:27:22 -08001259 setFrontOfTask();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001260 }
1261
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001262 void addActivityAtBottom(ActivityRecord r) {
Craig Mautner77878772013-03-04 19:46:24 -08001263 addActivityAtIndex(0, r);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001264 }
1265
1266 void addActivityToTop(ActivityRecord r) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001267 addActivityAtIndex(mActivities.size(), r);
1268 }
1269
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001270 @Override
Wale Ogunwaleeea34ee92017-08-31 20:07:45 -07001271 /*@WindowConfiguration.ActivityType*/
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001272 public int getActivityType() {
1273 final int applicationType = super.getActivityType();
1274 if (applicationType != ACTIVITY_TYPE_UNDEFINED || mActivities.isEmpty()) {
1275 return applicationType;
1276 }
1277 return mActivities.get(0).getActivityType();
1278 }
1279
Winson Chung30480042017-01-26 10:55:34 -08001280 /**
1281 * Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
1282 * be in the current task or unparented to any task.
1283 */
Craig Mautner1602ec22013-05-12 10:24:27 -07001284 void addActivityAtIndex(int index, ActivityRecord r) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001285 TaskRecord task = r.getTaskRecord();
Bryce Leeaf691c02017-03-20 14:20:22 -07001286 if (task != null && task != this) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001287 throw new IllegalArgumentException("Can not add r=" + " to task=" + this
Bryce Leeaf691c02017-03-20 14:20:22 -07001288 + " current parent=" + task);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001289 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001290
1291 r.setTask(this);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001292
Craig Mautner6170f732013-04-02 13:05:23 -07001293 // 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 -08001294 if (!mActivities.remove(r) && r.fullscreen) {
1295 // Was not previously in list.
1296 numFullscreen++;
1297 }
Craig Mautner2c1faed2013-07-23 12:56:02 -07001298 // Only set this based on the first activity
1299 if (mActivities.isEmpty()) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001300 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1301 // Normally non-standard activity type for the activity record will be set when the
1302 // object is created, however we delay setting the standard application type until
1303 // this point so that the task can set the type for additional activities added in
1304 // the else condition below.
1305 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1306 }
1307 setActivityType(r.getActivityType());
Craig Mautner21d24a22014-04-23 11:45:37 -07001308 isPersistable = r.isPersistable();
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001309 mCallingUid = r.launchedFromUid;
1310 mCallingPackage = r.launchedFromPackage;
Dianne Hackborn852975d2014-08-22 17:42:43 -07001311 // Clamp to [1, max].
1312 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
Wale Ogunwale65ebd952018-04-25 15:41:44 -07001313 ActivityTaskManager.getMaxAppRecentsLimitStatic());
Craig Mautner2c1faed2013-07-23 12:56:02 -07001314 } else {
1315 // Otherwise make all added activities match this one.
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001316 r.setActivityType(getActivityType());
Craig Mautner78733002013-06-10 13:54:49 -07001317 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001318
1319 final int size = mActivities.size();
1320
1321 if (index == size && size > 0) {
1322 final ActivityRecord top = mActivities.get(size - 1);
1323 if (top.mTaskOverlay) {
1324 // Place below the task overlay activity since the overlay activity should always
1325 // be on top.
1326 index--;
1327 }
1328 }
1329
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001330 index = Math.min(size, index);
Craig Mautner77878772013-03-04 19:46:24 -08001331 mActivities.add(index, r);
Bryce Lee84730a02018-04-03 14:10:04 -07001332
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001333 updateEffectiveIntent();
Craig Mautner21d24a22014-04-23 11:45:37 -07001334 if (r.isPersistable()) {
1335 mService.notifyTaskPersisterLocked(this, false);
1336 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001337
Yunfan Chen1ee84ea2018-11-13 16:03:37 -08001338 if (r.mAppWindowToken != null) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001339 // Only attempt to move in WM if the child has a controller. It is possible we haven't
1340 // created controller for the activity we are starting yet.
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001341 mTask.positionChildAt(r.mAppWindowToken, index);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001342 }
David Stevens82ea6cb2017-03-03 16:18:50 -08001343
1344 // Make sure the list of display UID whitelists is updated
1345 // now that this record is in a new task.
Wale Ogunwaled32da472018-11-16 07:19:28 -08001346 mService.mRootActivityContainer.updateUIDsPresentOnDisplay();
Craig Mautner77878772013-03-04 19:46:24 -08001347 }
1348
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001349 /**
Bryce Leeaf691c02017-03-20 14:20:22 -07001350 * Removes the specified activity from this task.
1351 * @param r The {@link ActivityRecord} to remove.
1352 * @return true if this was the last activity in the task.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001353 */
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001354 boolean removeActivity(ActivityRecord r) {
Bryce Lee84730a02018-04-03 14:10:04 -07001355 return removeActivity(r, false /* reparenting */);
Bryce Leeaf691c02017-03-20 14:20:22 -07001356 }
1357
1358 boolean removeActivity(ActivityRecord r, boolean reparenting) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001359 if (r.getTaskRecord() != this) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001360 throw new IllegalArgumentException(
1361 "Activity=" + r + " does not belong to task=" + this);
1362 }
1363
Bryce Lee84730a02018-04-03 14:10:04 -07001364 r.setTask(null /* task */, reparenting /* reparenting */);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001365
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001366 if (mActivities.remove(r) && r.fullscreen) {
1367 // Was previously in list.
1368 numFullscreen--;
1369 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001370 if (r.isPersistable()) {
1371 mService.notifyTaskPersisterLocked(this, false);
1372 }
Wale Ogunwale89182d52016-03-11 10:38:36 -08001373
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001374 if (inPinnedWindowingMode()) {
Wale Ogunwale89182d52016-03-11 10:38:36 -08001375 // We normally notify listeners of task stack changes on pause, however pinned stack
1376 // activities are normally in the paused state so no notification will be sent there
1377 // before the activity is removed. We send it here so instead.
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07001378 mService.getTaskChangeNotificationController().notifyTaskStackChanged();
Wale Ogunwale89182d52016-03-11 10:38:36 -08001379 }
1380
Craig Mautner41326202014-06-20 14:38:21 -07001381 if (mActivities.isEmpty()) {
Craig Mautner5afcd4d2014-06-21 18:11:33 -07001382 return !mReuseTask;
Craig Mautner41326202014-06-20 14:38:21 -07001383 }
1384 updateEffectiveIntent();
1385 return false;
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001386 }
1387
Winson Chung6954fc92017-03-24 16:22:12 -07001388 /**
1389 * @return whether or not there are ONLY task overlay activities in the stack.
1390 * If {@param excludeFinishing} is set, then ignore finishing activities in the check.
1391 * If there are no task overlay activities, this call returns false.
1392 */
1393 boolean onlyHasTaskOverlayActivities(boolean excludeFinishing) {
1394 int count = 0;
1395 for (int i = mActivities.size() - 1; i >= 0; i--) {
1396 final ActivityRecord r = mActivities.get(i);
1397 if (excludeFinishing && r.finishing) {
1398 continue;
1399 }
1400 if (!r.mTaskOverlay) {
1401 return false;
1402 }
1403 count++;
1404 }
1405 return count > 0;
1406 }
1407
Craig Mautner41db4a72014-05-07 17:20:56 -07001408 boolean autoRemoveFromRecents() {
Dianne Hackbornd38aed82014-06-10 21:36:35 -07001409 // We will automatically remove the task either if it has explicitly asked for
1410 // this, or it is empty and has never contained an activity that got shown to
1411 // the user.
Dianne Hackborn13420f22014-07-18 15:43:56 -07001412 return autoRemoveRecents || (mActivities.isEmpty() && !hasBeenVisible);
Craig Mautner41db4a72014-05-07 17:20:56 -07001413 }
1414
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001415 /**
1416 * Completely remove all activities associated with an existing
1417 * task starting at a specified index.
1418 */
Winson Chung0ec2a352017-10-26 11:38:30 -07001419 final void performClearTaskAtIndexLocked(int activityNdx, boolean pauseImmediately,
1420 String reason) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001421 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001422 for ( ; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001423 final ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001424 if (r.finishing) {
1425 continue;
1426 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001427 if (mStack == null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001428 // Task was restored from persistent storage.
1429 r.takeFromHistory();
1430 mActivities.remove(activityNdx);
1431 --activityNdx;
1432 --numActivities;
Winson Chung6954fc92017-03-24 16:22:12 -07001433 } else if (mStack.finishActivityLocked(r, Activity.RESULT_CANCELED, null,
Winson Chung0ec2a352017-10-26 11:38:30 -07001434 reason, false, pauseImmediately)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001435 --activityNdx;
1436 --numActivities;
1437 }
1438 }
1439 }
1440
1441 /**
1442 * Completely remove all activities associated with an existing task.
1443 */
Benjamin Franza83859f2017-07-03 16:34:14 +01001444 void performClearTaskLocked() {
Craig Mautner362449a2014-06-20 14:04:39 -07001445 mReuseTask = true;
Winson Chung0ec2a352017-10-26 11:38:30 -07001446 performClearTaskAtIndexLocked(0, !PAUSE_IMMEDIATELY, "clear-task-all");
Craig Mautner362449a2014-06-20 14:04:39 -07001447 mReuseTask = false;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001448 }
1449
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -08001450 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1451 mReuseTask = true;
1452 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1453 mReuseTask = false;
1454 return result;
1455 }
1456
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001457 /**
1458 * Perform clear operation as requested by
1459 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1460 * stack to the given task, then look for
1461 * an instance of that activity in the stack and, if found, finish all
1462 * activities on top of it and return the instance.
1463 *
1464 * @param newR Description of the new activity being started.
1465 * @return Returns the old activity that should be continued to be used,
1466 * or null if none was found.
1467 */
1468 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001469 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001470 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001471 ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001472 if (r.finishing) {
1473 continue;
1474 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001475 if (r.mActivityComponent.equals(newR.mActivityComponent)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001476 // Here it is! Now finish everything in front...
Craig Mautner1602ec22013-05-12 10:24:27 -07001477 final ActivityRecord ret = r;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001478
1479 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001480 r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001481 if (r.finishing) {
1482 continue;
1483 }
1484 ActivityOptions opts = r.takeOptionsLocked();
1485 if (opts != null) {
1486 ret.updateOptionsLocked(opts);
1487 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001488 if (mStack != null && mStack.finishActivityLocked(
Todd Kennedy539db512014-12-15 09:57:55 -08001489 r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001490 --activityNdx;
1491 --numActivities;
1492 }
1493 }
1494
1495 // Finally, if this is a normal launch mode (that is, not
1496 // expecting onNewIntent()), then we will finish the current
1497 // instance of the activity so a new fresh one can be started.
1498 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
Daichi Hirono15a02992016-04-27 18:47:01 +09001499 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1500 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001501 if (!ret.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001502 if (mStack != null) {
1503 mStack.finishActivityLocked(
Wale Ogunwale7d701172015-03-11 15:36:30 -07001504 ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
1505 }
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001506 return null;
1507 }
1508 }
1509
1510 return ret;
1511 }
1512 }
1513
1514 return null;
1515 }
1516
Winson Chung0ec2a352017-10-26 11:38:30 -07001517 void removeTaskActivitiesLocked(boolean pauseImmediately, String reason) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001518 // Just remove the entire task.
Winson Chung0ec2a352017-10-26 11:38:30 -07001519 performClearTaskAtIndexLocked(0, pauseImmediately, reason);
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001520 }
1521
Craig Mautner432f64e2015-05-20 14:59:57 -07001522 String lockTaskAuthToString() {
1523 switch (mLockTaskAuth) {
1524 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1525 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1526 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1527 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
Benjamin Franz469dd582015-06-09 14:24:36 +01001528 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
Craig Mautner432f64e2015-05-20 14:59:57 -07001529 default: return "unknown=" + mLockTaskAuth;
1530 }
1531 }
1532
Craig Mautner15df08a2015-04-01 12:17:18 -07001533 void setLockTaskAuth() {
Charles He2bf28322017-10-12 22:24:49 +01001534 setLockTaskAuth(getRootActivity());
1535 }
1536
1537 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1538 if (r == null) {
1539 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1540 return;
1541 }
1542
Charles He520b2832017-09-02 15:27:16 +01001543 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
Bryce Lee2b8e0372018-04-05 17:01:37 -07001544 final LockTaskController lockTaskController = mService.getLockTaskController();
Charles He2bf28322017-10-12 22:24:49 +01001545 switch (r.lockTaskLaunchMode) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001546 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
Bryce Lee2b8e0372018-04-05 17:01:37 -07001547 mLockTaskAuth = lockTaskController.isPackageWhitelisted(userId, pkg)
Charles He520b2832017-09-02 15:27:16 +01001548 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001549 break;
1550
1551 case LOCK_TASK_LAUNCH_MODE_NEVER:
Benjamin Franz469dd582015-06-09 14:24:36 +01001552 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
Craig Mautner15df08a2015-04-01 12:17:18 -07001553 break;
1554
1555 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
Benjamin Franz469dd582015-06-09 14:24:36 +01001556 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
Craig Mautner15df08a2015-04-01 12:17:18 -07001557 break;
1558
1559 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
Bryce Lee2b8e0372018-04-05 17:01:37 -07001560 mLockTaskAuth = lockTaskController.isPackageWhitelisted(userId, pkg)
Charles He520b2832017-09-02 15:27:16 +01001561 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001562 break;
1563 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001564 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this +
1565 " mLockTaskAuth=" + lockTaskAuthToString());
Craig Mautner15df08a2015-04-01 12:17:18 -07001566 }
1567
Winson Chungd3395382016-12-13 11:49:09 -08001568 private boolean isResizeable(boolean checkSupportsPip) {
Wale Ogunwalea6191b42018-05-09 07:41:32 -07001569 return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001570 || (checkSupportsPip && mSupportsPictureInPicture));
Winson Chungd3395382016-12-13 11:49:09 -08001571 }
1572
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001573 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08001574 return isResizeable(true /* checkSupportsPip */);
1575 }
1576
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001577 @Override
1578 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08001579 // A task can not be docked even if it is considered resizeable because it only supports
1580 // picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001581 return super.supportsSplitScreenWindowingMode()
Wale Ogunwalea6191b42018-05-09 07:41:32 -07001582 && mService.mSupportsSplitScreenMultiWindow
1583 && (mService.mForceResizableActivities
Bryce Leec857a5b2017-08-16 10:04:52 -07001584 || (isResizeable(false /* checkSupportsPip */)
1585 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001586 }
1587
skuhne@google.com322347b2016-12-02 12:54:03 -08001588 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001589 * Check whether this task can be launched on the specified display.
Riddle Hsu16567132018-08-16 21:37:47 +08001590 *
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001591 * @param displayId Target display id.
Riddle Hsu16567132018-08-16 21:37:47 +08001592 * @return {@code true} if either it is the default display or this activity can be put on a
1593 * secondary display.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001594 */
1595 boolean canBeLaunchedOnDisplay(int displayId) {
1596 return mService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Riddle Hsu16567132018-08-16 21:37:47 +08001597 -1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001598 }
1599
1600 /**
skuhne@google.com322347b2016-12-02 12:54:03 -08001601 * Check that a given bounds matches the application requested orientation.
1602 *
1603 * @param bounds The bounds to be tested.
1604 * @return True if the requested bounds are okay for a resizing request.
1605 */
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001606 private boolean canResizeToBounds(Rect bounds) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001607 if (bounds == null || !inFreeformWindowingMode()) {
skuhne@google.com322347b2016-12-02 12:54:03 -08001608 // Note: If not on the freeform workspace, we ignore the bounds.
1609 return true;
1610 }
1611 final boolean landscape = bounds.width() > bounds.height();
Evan Roskydfe3da72018-10-26 17:21:06 -07001612 final Rect configBounds = getRequestedOverrideBounds();
skuhne@google.com322347b2016-12-02 12:54:03 -08001613 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001614 return configBounds.isEmpty()
1615 || landscape == (configBounds.width() > configBounds.height());
skuhne@google.com322347b2016-12-02 12:54:03 -08001616 }
1617 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1618 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1619 }
1620
Craig Mautner525f3d92013-05-07 14:01:50 -07001621 /**
Yorke Leebdef5372017-04-10 16:38:51 -07001622 * @return {@code true} if the task is being cleared for the purposes of being reused.
1623 */
1624 boolean isClearingToReuseTask() {
1625 return mReuseTask;
1626 }
1627
1628 /**
Craig Mautner525f3d92013-05-07 14:01:50 -07001629 * Find the activity in the history stack within the given task. Returns
1630 * the index within the history at which it's found, or < 0 if not found.
1631 */
1632 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001633 final ComponentName realActivity = r.mActivityComponent;
Craig Mautner525f3d92013-05-07 14:01:50 -07001634 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1635 ActivityRecord candidate = mActivities.get(activityNdx);
1636 if (candidate.finishing) {
1637 continue;
1638 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001639 if (candidate.mActivityComponent.equals(realActivity)) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001640 return candidate;
1641 }
1642 }
1643 return null;
1644 }
1645
Winson Chunga449dc02014-05-16 11:15:04 -07001646 /** Updates the last task description values. */
1647 void updateTaskDescription() {
1648 // Traverse upwards looking for any break between main task activities and
1649 // utility activities.
1650 int activityNdx;
1651 final int numActivities = mActivities.size();
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001652 final boolean relinquish = numActivities != 0 &&
1653 (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001654 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
Craig Mautner21d24a22014-04-23 11:45:37 -07001655 ++activityNdx) {
Winson Chunga449dc02014-05-16 11:15:04 -07001656 final ActivityRecord r = mActivities.get(activityNdx);
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001657 if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001658 // This will be the top activity for determining taskDescription. Pre-inc to
1659 // overcome initial decrement below.
1660 ++activityNdx;
1661 break;
1662 }
Winson Chunga449dc02014-05-16 11:15:04 -07001663 if (r.intent != null &&
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001664 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
Winson Chunga449dc02014-05-16 11:15:04 -07001665 break;
1666 }
1667 }
1668 if (activityNdx > 0) {
1669 // Traverse downwards starting below break looking for set label, icon.
1670 // Note that if there are activities in the task but none of them set the
1671 // recent activity values, then we do not fall back to the last set
1672 // values in the TaskRecord.
1673 String label = null;
Craig Mautner648f69b2014-09-18 14:16:26 -07001674 String iconFilename = null;
Matthew Ng54bc9422017-10-02 17:16:28 -07001675 int iconResource = -1;
Winson Chunga449dc02014-05-16 11:15:04 -07001676 int colorPrimary = 0;
Winson Chung1af8eda2016-02-05 17:55:56 +00001677 int colorBackground = 0;
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001678 int statusBarColor = 0;
1679 int navigationBarColor = 0;
1680 boolean topActivity = true;
Winson Chunga449dc02014-05-16 11:15:04 -07001681 for (--activityNdx; activityNdx >= 0; --activityNdx) {
1682 final ActivityRecord r = mActivities.get(activityNdx);
Winson Chung80f80db2018-05-30 21:13:25 -07001683 if (r.mTaskOverlay) {
1684 continue;
1685 }
Winson Chunga449dc02014-05-16 11:15:04 -07001686 if (r.taskDescription != null) {
1687 if (label == null) {
1688 label = r.taskDescription.getLabel();
1689 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001690 if (iconResource == -1) {
1691 iconResource = r.taskDescription.getIconResource();
1692 }
Craig Mautner648f69b2014-09-18 14:16:26 -07001693 if (iconFilename == null) {
1694 iconFilename = r.taskDescription.getIconFilename();
Winson Chunga449dc02014-05-16 11:15:04 -07001695 }
1696 if (colorPrimary == 0) {
1697 colorPrimary = r.taskDescription.getPrimaryColor();
Winson Chunga449dc02014-05-16 11:15:04 -07001698 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001699 if (topActivity) {
Winson Chung1af8eda2016-02-05 17:55:56 +00001700 colorBackground = r.taskDescription.getBackgroundColor();
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001701 statusBarColor = r.taskDescription.getStatusBarColor();
1702 navigationBarColor = r.taskDescription.getNavigationBarColor();
Winson Chung1af8eda2016-02-05 17:55:56 +00001703 }
Winson Chunga449dc02014-05-16 11:15:04 -07001704 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001705 topActivity = false;
Winson Chunga449dc02014-05-16 11:15:04 -07001706 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001707 lastTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
1708 colorPrimary, colorBackground, statusBarColor, navigationBarColor);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001709 if (mTask != null) {
1710 mTask.setTaskDescription(lastTaskDescription);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001711 }
Winson Chungec396d62014-08-06 17:08:00 -07001712 // Update the task affiliation color if we are the parent of the group
1713 if (taskId == mAffiliatedTaskId) {
1714 mAffiliatedTaskColor = lastTaskDescription.getPrimaryColor();
1715 }
Winson Chunga449dc02014-05-16 11:15:04 -07001716 }
1717 }
1718
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001719 int findEffectiveRootIndex() {
Craig Mautner4767f4b2014-09-18 15:38:33 -07001720 int effectiveNdx = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001721 final int topActivityNdx = mActivities.size() - 1;
Dianne Hackborn39569af2014-09-23 10:56:58 -07001722 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001723 final ActivityRecord r = mActivities.get(activityNdx);
1724 if (r.finishing) {
1725 continue;
1726 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001727 effectiveNdx = activityNdx;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001728 if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001729 break;
1730 }
1731 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001732 return effectiveNdx;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001733 }
1734
1735 void updateEffectiveIntent() {
1736 final int effectiveRootIndex = findEffectiveRootIndex();
1737 final ActivityRecord r = mActivities.get(effectiveRootIndex);
Winson Chungfee26772014-08-05 12:21:52 -07001738 setIntent(r);
Winson Chung8d9009e2017-11-16 15:43:05 -08001739
1740 // Update the task description when the activities change
1741 updateTaskDescription();
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001742 }
1743
Garfield Tan020607d2018-12-17 17:01:58 -08001744 private void adjustForMinimalTaskDimensions(Rect bounds, Rect previousBounds) {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001745 if (bounds == null) {
1746 return;
1747 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001748 int minWidth = mMinWidth;
1749 int minHeight = mMinHeight;
Robert Carr9c5867d2016-03-10 15:52:46 -08001750 // If the task has no requested minimal size, we'd like to enforce a minimal size
1751 // so that the user can not render the task too small to manipulate. We don't need
1752 // to do this for the pinned stack as the bounds are controlled by the system.
Evan Rosky1ac84462018-11-13 11:25:30 -08001753 if (!inPinnedWindowingMode() && mStack != null) {
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001754 final int defaultMinSizeDp =
Wale Ogunwaled32da472018-11-16 07:19:28 -08001755 mService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp;
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001756 final ActivityDisplay display =
Wale Ogunwaled32da472018-11-16 07:19:28 -08001757 mService.mRootActivityContainer.getActivityDisplay(mStack.mDisplayId);
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001758 final float density =
1759 (float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
1760 final int defaultMinSize = (int) (defaultMinSizeDp * density);
1761
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001762 if (minWidth == INVALID_MIN_SIZE) {
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001763 minWidth = defaultMinSize;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001764 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001765 if (minHeight == INVALID_MIN_SIZE) {
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001766 minHeight = defaultMinSize;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001767 }
Robert Carr9c5867d2016-03-10 15:52:46 -08001768 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001769 final boolean adjustWidth = minWidth > bounds.width();
1770 final boolean adjustHeight = minHeight > bounds.height();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001771 if (!(adjustWidth || adjustHeight)) {
1772 return;
1773 }
1774
1775 if (adjustWidth) {
Garfield Tan020607d2018-12-17 17:01:58 -08001776 if (!previousBounds.isEmpty() && bounds.right == previousBounds.right) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001777 bounds.left = bounds.right - minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001778 } else {
1779 // Either left bounds match, or neither match, or the previous bounds were
1780 // fullscreen and we default to keeping left.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001781 bounds.right = bounds.left + minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001782 }
1783 }
1784 if (adjustHeight) {
Garfield Tan020607d2018-12-17 17:01:58 -08001785 if (!previousBounds.isEmpty() && bounds.bottom == previousBounds.bottom) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001786 bounds.top = bounds.bottom - minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001787 } else {
1788 // Either top bounds match, or neither match, or the previous bounds were
1789 // fullscreen and we default to keeping top.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001790 bounds.bottom = bounds.top + minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001791 }
1792 }
1793 }
1794
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001795 /**
1796 * Update task's override configuration based on the bounds.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001797 * @param bounds The bounds of the task.
Andrii Kulian8072d112016-09-16 11:11:01 -07001798 * @return True if the override configuration was updated.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001799 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001800 boolean updateOverrideConfiguration(Rect bounds) {
Jorim Jaggi0a932142016-02-01 17:42:25 -08001801 return updateOverrideConfiguration(bounds, null /* insetBounds */);
1802 }
1803
Evan Rosky9ba524e2018-01-03 16:27:56 -08001804 void setLastNonFullscreenBounds(Rect bounds) {
1805 if (mLastNonFullscreenBounds == null) {
1806 mLastNonFullscreenBounds = new Rect(bounds);
1807 } else {
1808 mLastNonFullscreenBounds.set(bounds);
1809 }
1810 }
1811
Jorim Jaggi0a932142016-02-01 17:42:25 -08001812 /**
1813 * Update task's override configuration based on the bounds.
1814 * @param bounds The bounds of the task.
1815 * @param insetBounds The bounds used to calculate the system insets, which is used here to
1816 * subtract the navigation bar/status bar size from the screen size reported
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001817 * to the application. See {@link IActivityTaskManager#resizeDockedStack}.
Andrii Kulian8072d112016-09-16 11:11:01 -07001818 * @return True if the override configuration was updated.
Jorim Jaggi0a932142016-02-01 17:42:25 -08001819 */
Andrii Kulian8072d112016-09-16 11:11:01 -07001820 boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
Evan Rosky1ac84462018-11-13 11:25:30 -08001821 final boolean hasSetDisplayedBounds = (insetBounds != null && !insetBounds.isEmpty());
1822 if (hasSetDisplayedBounds) {
1823 setDisplayedBounds(bounds);
1824 } else {
1825 setDisplayedBounds(null);
1826 }
1827 // "steady" bounds do not include any temporary offsets from animation or interaction.
1828 Rect steadyBounds = hasSetDisplayedBounds ? insetBounds : bounds;
1829 if (equivalentRequestedOverrideBounds(steadyBounds)) {
Andrii Kulian8072d112016-09-16 11:11:01 -07001830 return false;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07001831 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001832
Evan Rosky1ac84462018-11-13 11:25:30 -08001833 mTmpConfig.setTo(getResolvedOverrideConfiguration());
1834 setBounds(steadyBounds);
1835 return !mTmpConfig.equals(getResolvedOverrideConfiguration());
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001836 }
Wale Ogunwale5f986092015-12-04 15:35:38 -08001837
Bryce Leec4ab62a2018-03-05 14:19:26 -08001838 /**
1839 * This should be called when an child activity changes state. This should only
1840 * be called from
1841 * {@link ActivityRecord#setState(ActivityState, String)} .
1842 * @param record The {@link ActivityRecord} whose state has changed.
1843 * @param state The new state.
1844 * @param reason The reason for the change.
1845 */
1846 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
1847 final ActivityStack parent = getStack();
1848
1849 if (parent != null) {
1850 parent.onActivityStateChanged(record, state, reason);
1851 }
1852 }
1853
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001854 @Override
1855 public void onConfigurationChanged(Configuration newParentConfig) {
1856 final boolean wasInMultiWindowMode = inMultiWindowMode();
1857 super.onConfigurationChanged(newParentConfig);
1858 if (wasInMultiWindowMode != inMultiWindowMode()) {
Winson Chung5af42fc2017-03-24 17:11:33 -07001859 mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001860 }
Evan Rosky1ac84462018-11-13 11:25:30 -08001861 if (getWindowConfiguration().persistTaskBounds()) {
1862 final Rect currentBounds = getRequestedOverrideBounds();
1863 if (!currentBounds.isEmpty()) {
1864 setLastNonFullscreenBounds(currentBounds);
1865 }
1866 }
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001867 // TODO: Should also take care of Pip mode changes here.
Garfield Tan891146c2018-10-09 12:14:00 -07001868
1869 saveLaunchingStateIfNeeded();
1870 }
1871
1872 /**
1873 * Saves launching state if necessary so that we can launch the activity to its latest state.
1874 * It only saves state if this task has been shown to user and it's in fullscreen or freeform
1875 * mode.
1876 */
1877 void saveLaunchingStateIfNeeded() {
1878 if (!hasBeenVisible) {
1879 // Not ever visible to user.
1880 return;
1881 }
1882
1883 final int windowingMode = getWindowingMode();
1884 if (windowingMode != WindowConfiguration.WINDOWING_MODE_FULLSCREEN
1885 && windowingMode != WindowConfiguration.WINDOWING_MODE_FREEFORM) {
1886 return;
1887 }
1888
1889 // Saves the new state so that we can launch the activity at the same location.
1890 mService.mStackSupervisor.mLaunchParamsPersister.saveTask(this);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001891 }
1892
Evan Roskyed6767f2018-10-26 17:21:06 -07001893 /**
Evan Rosky1ac84462018-11-13 11:25:30 -08001894 * Adjust bounds to stay within stack bounds.
1895 *
1896 * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
1897 * that keep them unchanged, but be contained within the stack bounds.
1898 *
1899 * @param bounds Bounds to be adjusted.
1900 * @param stackBounds Bounds within which the other bounds should remain.
1901 */
1902 private static void fitWithinBounds(Rect bounds, Rect stackBounds) {
1903 if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
1904 return;
1905 }
1906
1907 if (bounds.left < stackBounds.left || bounds.right > stackBounds.right) {
1908 final int maxRight = stackBounds.right
1909 - (stackBounds.width() / FIT_WITHIN_BOUNDS_DIVIDER);
1910 int horizontalDiff = stackBounds.left - bounds.left;
1911 if ((horizontalDiff < 0 && bounds.left >= maxRight)
1912 || (bounds.left + horizontalDiff >= maxRight)) {
1913 horizontalDiff = maxRight - bounds.left;
1914 }
1915 bounds.left += horizontalDiff;
1916 bounds.right += horizontalDiff;
1917 }
1918
1919 if (bounds.top < stackBounds.top || bounds.bottom > stackBounds.bottom) {
1920 final int maxBottom = stackBounds.bottom
1921 - (stackBounds.height() / FIT_WITHIN_BOUNDS_DIVIDER);
1922 int verticalDiff = stackBounds.top - bounds.top;
1923 if ((verticalDiff < 0 && bounds.top >= maxBottom)
1924 || (bounds.top + verticalDiff >= maxBottom)) {
1925 verticalDiff = maxBottom - bounds.top;
1926 }
1927 bounds.top += verticalDiff;
1928 bounds.bottom += verticalDiff;
1929 }
1930 }
1931
1932 /**
Evan Roskyed6767f2018-10-26 17:21:06 -07001933 * Displayed bounds are used to set where the task is drawn at any given time. This is
1934 * separate from its actual bounds so that the app doesn't see any meaningful configuration
1935 * changes during transitionary periods.
1936 */
1937 void setDisplayedBounds(Rect bounds) {
1938 if (bounds == null) {
1939 mDisplayedBounds.setEmpty();
1940 } else {
1941 mDisplayedBounds.set(bounds);
1942 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001943 if (mTask != null) {
1944 mTask.setOverrideDisplayedBounds(
Evan Roskyed6767f2018-10-26 17:21:06 -07001945 mDisplayedBounds.isEmpty() ? null : mDisplayedBounds);
1946 }
1947 }
1948
1949 /**
1950 * Gets the current overridden displayed bounds. These will be empty if the task is not
1951 * currently overriding where it is displayed.
1952 */
1953 Rect getDisplayedBounds() {
1954 return mDisplayedBounds;
1955 }
1956
1957 /**
1958 * @return {@code true} if this has overridden displayed bounds.
1959 */
1960 boolean hasDisplayedBounds() {
1961 return !mDisplayedBounds.isEmpty();
1962 }
1963
Evan Rosky1ac84462018-11-13 11:25:30 -08001964 /**
1965 * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
1966 * intersectBounds on a side, then the respective side will not be intersected.
1967 *
1968 * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
1969 * inset on that side is no-longer applicable. This scenario happens when a task's minimal
1970 * bounds are larger than the provided parent/display bounds.
1971 *
1972 * @param inOutBounds the bounds to intersect.
1973 * @param intersectBounds the bounds to intersect with.
1974 * @param intersectInsets insets to apply to intersectBounds before intersecting.
1975 */
1976 private static void intersectWithInsetsIfFits(
1977 Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
1978 if (inOutBounds.right <= intersectBounds.right) {
1979 inOutBounds.right =
1980 Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
1981 }
1982 if (inOutBounds.bottom <= intersectBounds.bottom) {
1983 inOutBounds.bottom =
1984 Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
1985 }
1986 if (inOutBounds.left >= intersectBounds.left) {
1987 inOutBounds.left =
1988 Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
1989 }
1990 if (inOutBounds.top >= intersectBounds.top) {
1991 inOutBounds.top =
1992 Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
1993 }
1994 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001995
Evan Rosky1ac84462018-11-13 11:25:30 -08001996 /**
1997 * Gets bounds with non-decor and stable insets applied respectively.
1998 *
1999 * If bounds overhangs the display, those edges will not get insets. See
2000 * {@link #intersectWithInsetsIfFits}
2001 *
2002 * @param outNonDecorBounds where to place bounds with non-decor insets applied.
2003 * @param outStableBounds where to place bounds with stable insets applied.
2004 * @param bounds the bounds to inset.
2005 */
2006 private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
2007 DisplayInfo displayInfo) {
2008 outNonDecorBounds.set(bounds);
2009 outStableBounds.set(bounds);
2010 if (getStack() == null || getStack().getDisplay() == null) {
2011 return;
2012 }
2013 DisplayPolicy policy = getStack().getDisplay().mDisplayContent.getDisplayPolicy();
2014 if (policy == null) {
2015 return;
2016 }
2017 mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
Bryce Lee7566d762017-03-30 09:34:15 -07002018
Evan Rosky1ac84462018-11-13 11:25:30 -08002019 policy.getStableInsetsLw(displayInfo.rotation,
2020 displayInfo.logicalWidth, displayInfo.logicalHeight, displayInfo.displayCutout,
2021 mTmpInsets);
2022 intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002023
Evan Rosky1ac84462018-11-13 11:25:30 -08002024 policy.getNonDecorInsetsLw(displayInfo.rotation,
2025 displayInfo.logicalWidth, displayInfo.logicalHeight, displayInfo.displayCutout,
2026 mTmpInsets);
2027 intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);
2028 }
2029
2030 /**
2031 * Asks docked-divider controller for the smallestwidthdp given bounds.
2032 * @param bounds bounds to calculate smallestwidthdp for.
2033 */
2034 private int getSmallestScreenWidthDpForDockedBounds(Rect bounds) {
2035 DisplayContent dc = mStack.getDisplay().mDisplayContent;
2036 if (dc != null) {
2037 return dc.getDockedDividerController().getSmallestWidthDpForBounds(bounds);
2038 }
2039 return Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
2040 }
2041
2042 /**
2043 * Calculates configuration values used by the client to get resources. This should be run
2044 * using app-facing bounds (bounds unmodified by animations or transient interactions).
2045 *
2046 * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
2047 * configuring an "inherit-bounds" window which means that all configuration settings would
2048 * just be inherited from the parent configuration.
2049 **/
2050 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig, @NonNull Rect bounds,
2051 @NonNull Configuration parentConfig) {
2052 int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
2053 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2054 windowingMode = parentConfig.windowConfiguration.getWindowingMode();
Winson Chungbdc646f2017-02-13 12:12:22 -08002055 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002056
Evan Rosky1ac84462018-11-13 11:25:30 -08002057 float density = inOutConfig.densityDpi;
2058 if (density == Configuration.DENSITY_DPI_UNDEFINED) {
2059 density = parentConfig.densityDpi;
2060 }
2061 density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
Winson Chung60c1aba2017-03-14 17:47:42 -07002062
Evan Rosky1ac84462018-11-13 11:25:30 -08002063 Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2064 if (outAppBounds == null || outAppBounds.isEmpty()) {
2065 inOutConfig.windowConfiguration.setAppBounds(bounds);
2066 outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2067 }
2068 if (windowingMode != WINDOWING_MODE_FREEFORM) {
2069 final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
2070 if (parentAppBounds != null && !parentAppBounds.isEmpty()) {
2071 outAppBounds.intersect(parentAppBounds);
2072 }
2073 }
2074
2075 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
2076 || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2077 if (mStack != null) {
2078 final DisplayInfo di = new DisplayInfo();
2079 mStack.getDisplay().mDisplay.getDisplayInfo(di);
2080
2081 // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
2082 // area, i.e. the screen area without the system bars.
2083 // The non decor inset are areas that could never be removed in Honeycomb. See
2084 // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
2085 calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, bounds, di);
2086 } else {
2087 mTmpNonDecorBounds.set(bounds);
2088 mTmpStableBounds.set(bounds);
2089 }
2090
2091 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
2092 inOutConfig.screenWidthDp = Math.min((int) (mTmpStableBounds.width() / density),
2093 parentConfig.screenWidthDp);
2094 }
2095 if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2096 inOutConfig.screenHeightDp = Math.min((int) (mTmpStableBounds.height() / density),
2097 parentConfig.screenHeightDp);
2098 }
2099
2100 if (inOutConfig.smallestScreenWidthDp
2101 == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2102 if (WindowConfiguration.isFloating(windowingMode)) {
2103 // For floating tasks, calculate the smallest width from the bounds of the task
2104 inOutConfig.smallestScreenWidthDp = (int) (
2105 Math.min(bounds.width(), bounds.height()) / density);
2106 } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
2107 // Iterating across all screen orientations, and return the minimum of the task
2108 // width taking into account that the bounds might change because the snap
2109 // algorithm snaps to a different value
2110 getSmallestScreenWidthDpForDockedBounds(bounds);
2111 }
2112 // otherwise, it will just inherit
2113 }
2114 }
2115
2116 if (inOutConfig.orientation == Configuration.ORIENTATION_UNDEFINED) {
2117 inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
2118 ? Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
2119 }
2120 if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
2121 // For calculating screen layout, we need to use the non-decor inset screen area for the
2122 // calculation for compatibility reasons, i.e. screen area without system bars that
2123 // could never go away in Honeycomb.
2124 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
2125 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
2126 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start
2127 // override calculation with partial default.
2128 // Reducing the screen layout starting from its parent config.
2129 final int sl = parentConfig.screenLayout
2130 & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
2131 final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
2132 final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
2133 inOutConfig.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
2134 }
2135 }
2136
2137 // TODO(b/113900640): remove this once ActivityRecord is changed to not need it anymore.
2138 void computeResolvedOverrideConfiguration(Configuration inOutConfig, Configuration parentConfig,
2139 Configuration overrideConfig) {
Garfield Tan020607d2018-12-17 17:01:58 -08002140 // Save previous bounds because adjustForMinimalTaskDimensions uses that to determine if it
2141 // changes left bound vs. right bound, or top bound vs. bottom bound.
2142 mTmpBounds.set(inOutConfig.windowConfiguration.getBounds());
2143
Evan Rosky1ac84462018-11-13 11:25:30 -08002144 inOutConfig.setTo(overrideConfig);
2145
2146 Rect outOverrideBounds = inOutConfig.windowConfiguration.getBounds();
2147 if (outOverrideBounds != null && !outOverrideBounds.isEmpty()) {
Garfield Tan020607d2018-12-17 17:01:58 -08002148 adjustForMinimalTaskDimensions(outOverrideBounds, mTmpBounds);
Evan Rosky1ac84462018-11-13 11:25:30 -08002149
2150 int windowingMode = overrideConfig.windowConfiguration.getWindowingMode();
2151 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2152 windowingMode = parentConfig.windowConfiguration.getWindowingMode();
2153 }
2154 if (windowingMode == WINDOWING_MODE_FREEFORM) {
2155 // by policy, make sure the window remains within parent
2156 fitWithinBounds(outOverrideBounds, parentConfig.windowConfiguration.getBounds());
2157 }
2158
2159 computeConfigResourceOverrides(inOutConfig, outOverrideBounds, parentConfig);
2160 }
2161 }
2162
2163 @Override
2164 void resolveOverrideConfiguration(Configuration newParentConfig) {
2165 computeResolvedOverrideConfiguration(getResolvedOverrideConfiguration(), newParentConfig,
2166 getRequestedOverrideConfiguration());
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08002167 }
2168
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002169 Rect updateOverrideConfigurationFromLaunchBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08002170 final Rect bounds = getLaunchBounds();
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002171 updateOverrideConfiguration(bounds);
Bryce Leef3c6a472017-11-14 14:53:06 -08002172 if (bounds != null && !bounds.isEmpty()) {
2173 // TODO: Review if we actually want to do this - we are setting the launch bounds
2174 // directly here.
Evan Roskydfe3da72018-10-26 17:21:06 -07002175 bounds.set(getRequestedOverrideBounds());
Andrii Kulian73336d812016-03-24 12:56:08 -07002176 }
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002177 return bounds;
2178 }
2179
Wale Ogunwale935e5022015-11-10 12:36:10 -08002180 /** Updates the task's bounds and override configuration to match what is expected for the
2181 * input stack. */
2182 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002183 if (mStack != null && mStack == inStack) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002184 return;
2185 }
2186
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002187 if (inStack.inFreeformWindowingMode()) {
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002188 if (!isResizeable()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002189 throw new IllegalArgumentException("Can not position non-resizeable task="
2190 + this + " in stack=" + inStack);
2191 }
Bryce Leef3c6a472017-11-14 14:53:06 -08002192 if (!matchParentBounds()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002193 return;
2194 }
2195 if (mLastNonFullscreenBounds != null) {
2196 updateOverrideConfiguration(mLastNonFullscreenBounds);
2197 } else {
Bryce Leeec55eb02017-12-05 20:51:27 -08002198 mService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Wale Ogunwale935e5022015-11-10 12:36:10 -08002199 }
2200 } else {
Evan Roskydfe3da72018-10-26 17:21:06 -07002201 updateOverrideConfiguration(inStack.getRequestedOverrideBounds());
Wale Ogunwale935e5022015-11-10 12:36:10 -08002202 }
2203 }
2204
Wale Ogunwale706ed792015-08-02 10:29:44 -07002205 /** Returns the bounds that should be used to launch this task. */
Wale Ogunwale30e441d2017-11-09 08:28:45 -08002206 Rect getLaunchBounds() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002207 if (mStack == null) {
Chong Zhang7d5f5102016-01-13 10:29:24 -08002208 return null;
2209 }
2210
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002211 final int windowingMode = getWindowingMode();
2212 if (!isActivityTypeStandardOrUndefined()
2213 || windowingMode == WINDOWING_MODE_FULLSCREEN
2214 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Evan Roskydfe3da72018-10-26 17:21:06 -07002215 return isResizeable() ? mStack.getRequestedOverrideBounds() : null;
Wale Ogunwale3382ab12017-07-27 08:55:03 -07002216 } else if (!getWindowConfiguration().persistTaskBounds()) {
Evan Roskydfe3da72018-10-26 17:21:06 -07002217 return mStack.getRequestedOverrideBounds();
Wale Ogunwale706ed792015-08-02 10:29:44 -07002218 }
2219 return mLastNonFullscreenBounds;
2220 }
2221
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01002222 void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
2223 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
2224 final ActivityRecord r = mActivities.get(activityNdx);
2225 if (r.visible) {
2226 r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
2227 }
2228 }
2229 }
2230
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07002231 void setRootProcess(WindowProcessController proc) {
Dianne Hackborn68a06332017-11-15 17:54:18 -08002232 clearRootProcess();
2233 if (intent != null &&
2234 (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
2235 mRootProcess = proc;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07002236 mRootProcess.addRecentTask(this);
Dianne Hackborn68a06332017-11-15 17:54:18 -08002237 }
2238 }
2239
2240 void clearRootProcess() {
2241 if (mRootProcess != null) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07002242 mRootProcess.removeRecentTask(this);
Dianne Hackborn68a06332017-11-15 17:54:18 -08002243 mRootProcess = null;
2244 }
2245 }
2246
chaviw82a0ba82018-03-15 14:26:29 -07002247 void clearAllPendingOptions() {
2248 for (int i = getChildCount() - 1; i >= 0; i--) {
2249 getChildAt(i).clearOptionsLocked(false /* withAbort */);
2250 }
2251 }
2252
Winson Chungabfdcce2018-07-02 17:23:33 -07002253 /**
2254 * Fills in a {@link TaskInfo} with information from this task.
2255 * @param info the {@link TaskInfo} to fill in
2256 * @param reuseActivitiesReport a temporary activities report that we can reuse to fetch the
2257 * running activities
2258 */
2259 void fillTaskInfo(TaskInfo info, TaskActivitiesReport reuseActivitiesReport) {
2260 getNumRunningActivities(reuseActivitiesReport);
2261 info.userId = userId;
2262 info.stackId = getStackId();
2263 info.taskId = taskId;
2264 info.isRunning = getTopActivity() != null;
Riddle Hsu2f9acd22018-11-06 23:44:43 +08002265 info.baseIntent = new Intent(getBaseIntent());
Winson Chungabfdcce2018-07-02 17:23:33 -07002266 info.baseActivity = reuseActivitiesReport.base != null
2267 ? reuseActivitiesReport.base.intent.getComponent()
2268 : null;
2269 info.topActivity = reuseActivitiesReport.top != null
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002270 ? reuseActivitiesReport.top.mActivityComponent
Winson Chungabfdcce2018-07-02 17:23:33 -07002271 : null;
2272 info.origActivity = origActivity;
2273 info.realActivity = realActivity;
2274 info.numActivities = reuseActivitiesReport.numActivities;
2275 info.lastActiveTime = lastActiveTime;
2276 info.taskDescription = new ActivityManager.TaskDescription(lastTaskDescription);
2277 info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
2278 info.resizeMode = mResizeMode;
2279 info.configuration.setTo(getConfiguration());
2280 }
2281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002282 void dump(PrintWriter pw, String prefix) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002283 pw.print(prefix); pw.print("userId="); pw.print(userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07002284 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
2285 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
Suprabh Shukla7745c142016-03-07 18:21:10 -08002286 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002287 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
Dianne Hackborn79228822014-09-16 11:11:23 -07002288 if (affinity != null || rootAffinity != null) {
2289 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
2290 if (affinity == null || !affinity.equals(rootAffinity)) {
2291 pw.print(" root="); pw.println(rootAffinity);
2292 } else {
2293 pw.println();
2294 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002295 }
Dianne Hackborn91097de2014-04-04 18:02:06 -07002296 if (voiceSession != null || voiceInteractor != null) {
2297 pw.print(prefix); pw.print("VOICE: session=0x");
2298 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
2299 pw.print(" interactor=0x");
2300 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
2301 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002302 if (intent != null) {
2303 StringBuilder sb = new StringBuilder(128);
2304 sb.append(prefix); sb.append("intent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08002305 intent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002306 sb.append('}');
2307 pw.println(sb.toString());
2308 }
2309 if (affinityIntent != null) {
2310 StringBuilder sb = new StringBuilder(128);
2311 sb.append(prefix); sb.append("affinityIntent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08002312 affinityIntent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002313 sb.append('}');
2314 pw.println(sb.toString());
2315 }
2316 if (origActivity != null) {
2317 pw.print(prefix); pw.print("origActivity=");
2318 pw.println(origActivity.flattenToShortString());
2319 }
2320 if (realActivity != null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002321 pw.print(prefix); pw.print("mActivityComponent=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002322 pw.println(realActivity.flattenToShortString());
2323 }
Wale Ogunwale66e16852017-10-19 13:35:52 -07002324 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard() || numFullscreen != 0) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002325 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002326 pw.print(" isPersistable="); pw.print(isPersistable);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002327 pw.print(" numFullscreen="); pw.print(numFullscreen);
Wale Ogunwale66e16852017-10-19 13:35:52 -07002328 pw.print(" activityType="); pw.println(getActivityType());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002329 }
Craig Mautner432f64e2015-05-20 14:59:57 -07002330 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
2331 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002332 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
2333 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
Craig Mautner432f64e2015-05-20 14:59:57 -07002334 pw.print(" mReuseTask="); pw.print(mReuseTask);
2335 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002336 }
Wale Ogunwale18795a22014-12-03 11:38:33 -08002337 if (mAffiliatedTaskId != taskId || mPrevAffiliateTaskId != INVALID_TASK_ID
2338 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
2339 || mNextAffiliate != null) {
Dianne Hackborn852975d2014-08-22 17:42:43 -07002340 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
2341 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
2342 pw.print(" (");
2343 if (mPrevAffiliate == null) {
2344 pw.print("null");
2345 } else {
2346 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
2347 }
2348 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
2349 pw.print(" (");
2350 if (mNextAffiliate == null) {
2351 pw.print("null");
2352 } else {
2353 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
2354 }
2355 pw.println(")");
2356 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002357 pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002358 if (!askedCompatMode || !inRecents || !isAvailable) {
2359 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
2360 pw.print(" inRecents="); pw.print(inRecents);
2361 pw.print(" isAvailable="); pw.println(isAvailable);
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002362 }
Dianne Hackborn852975d2014-08-22 17:42:43 -07002363 if (lastDescription != null) {
2364 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
2365 }
Dianne Hackborn68a06332017-11-15 17:54:18 -08002366 if (mRootProcess != null) {
2367 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
2368 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002369 pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002370 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
2371 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08002372 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002373 pw.print(" isResizeable=" + isResizeable());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002374 pw.print(" lastActiveTime=" + lastActiveTime);
2375 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002376 }
2377
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002378 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002379 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002380 StringBuilder sb = new StringBuilder(128);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002381 if (stringName != null) {
2382 sb.append(stringName);
2383 sb.append(" U=");
2384 sb.append(userId);
Wale Ogunwale6c5eb1c2015-11-10 07:52:22 -08002385 sb.append(" StackId=");
Andrii Kulian02b7a832016-10-06 23:11:56 -07002386 sb.append(getStackId());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002387 sb.append(" sz=");
2388 sb.append(mActivities.size());
2389 sb.append('}');
2390 return sb.toString();
2391 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002392 sb.append("TaskRecord{");
2393 sb.append(Integer.toHexString(System.identityHashCode(this)));
2394 sb.append(" #");
2395 sb.append(taskId);
2396 if (affinity != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002397 sb.append(" A=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002398 sb.append(affinity);
2399 } else if (intent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002400 sb.append(" I=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002401 sb.append(intent.getComponent().flattenToShortString());
Bryce Leefbd263b42018-03-07 10:33:55 -08002402 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002403 sb.append(" aI=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002404 sb.append(affinityIntent.getComponent().flattenToShortString());
2405 } else {
2406 sb.append(" ??");
2407 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07002408 stringName = sb.toString();
2409 return toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002410 }
Steven Timotius4346f0a2017-09-12 11:07:21 -07002411
2412 public void writeToProto(ProtoOutputStream proto, long fieldId) {
2413 final long token = proto.start(fieldId);
Adrian Roos4921ccf2017-09-28 16:54:06 +02002414 super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002415 proto.write(ID, taskId);
2416 for (int i = mActivities.size() - 1; i >= 0; i--) {
2417 ActivityRecord activity = mActivities.get(i);
2418 activity.writeToProto(proto, ACTIVITIES);
2419 }
2420 proto.write(STACK_ID, mStack.mStackId);
2421 if (mLastNonFullscreenBounds != null) {
2422 mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
2423 }
2424 if (realActivity != null) {
2425 proto.write(REAL_ACTIVITY, realActivity.flattenToShortString());
2426 }
2427 if (origActivity != null) {
2428 proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString());
2429 }
2430 proto.write(ACTIVITY_TYPE, getActivityType());
Steven Timotius4346f0a2017-09-12 11:07:21 -07002431 proto.write(RESIZE_MODE, mResizeMode);
Bryce Leef3c6a472017-11-14 14:53:06 -08002432 // TODO: Remove, no longer needed with windowingMode.
2433 proto.write(FULLSCREEN, matchParentBounds());
2434
2435 if (!matchParentBounds()) {
Evan Roskydfe3da72018-10-26 17:21:06 -07002436 final Rect bounds = getRequestedOverrideBounds();
Bryce Leef3c6a472017-11-14 14:53:06 -08002437 bounds.writeToProto(proto, BOUNDS);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002438 }
2439 proto.write(MIN_WIDTH, mMinWidth);
2440 proto.write(MIN_HEIGHT, mMinHeight);
2441 proto.end(token);
2442 }
Winson Chung61c9e5a2017-10-11 10:39:32 -07002443
2444 /**
2445 * See {@link #getNumRunningActivities(TaskActivitiesReport)}.
2446 */
2447 static class TaskActivitiesReport {
2448 int numRunning;
2449 int numActivities;
2450 ActivityRecord top;
2451 ActivityRecord base;
2452
2453 void reset() {
2454 numRunning = numActivities = 0;
2455 top = base = null;
2456 }
2457 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002458
2459 /**
2460 * Saves this {@link TaskRecord} to XML using given serializer.
2461 */
2462 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
2463 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
2464
2465 out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
2466 if (realActivity != null) {
2467 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
2468 }
2469 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
2470 if (origActivity != null) {
2471 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
2472 }
2473 // Write affinity, and root affinity if it is different from affinity.
2474 // We use the special string "@" for a null root affinity, so we can identify
2475 // later whether we were given a root affinity or should just make it the
2476 // same as the affinity.
2477 if (affinity != null) {
2478 out.attribute(null, ATTR_AFFINITY, affinity);
2479 if (!affinity.equals(rootAffinity)) {
2480 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2481 }
2482 } else if (rootAffinity != null) {
2483 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2484 }
2485 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
2486 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
2487 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
2488 out.attribute(null, ATTR_USERID, String.valueOf(userId));
2489 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
2490 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
2491 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
2492 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
2493 if (lastDescription != null) {
2494 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
2495 }
2496 if (lastTaskDescription != null) {
2497 lastTaskDescription.saveToXml(out);
2498 }
2499 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
2500 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
2501 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
2502 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
2503 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
2504 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
2505 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
2506 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
2507 String.valueOf(mSupportsPictureInPicture));
2508 if (mLastNonFullscreenBounds != null) {
2509 out.attribute(
2510 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
2511 }
2512 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
2513 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
2514 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
2515
2516 if (affinityIntent != null) {
2517 out.startTag(null, TAG_AFFINITYINTENT);
2518 affinityIntent.saveToXml(out);
2519 out.endTag(null, TAG_AFFINITYINTENT);
2520 }
2521
Bryce Lee1a990e52018-04-23 10:54:11 -07002522 if (intent != null) {
2523 out.startTag(null, TAG_INTENT);
2524 intent.saveToXml(out);
2525 out.endTag(null, TAG_INTENT);
2526 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002527
2528 final ArrayList<ActivityRecord> activities = mActivities;
2529 final int numActivities = activities.size();
2530 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
2531 final ActivityRecord r = activities.get(activityNdx);
2532 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
2533 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
2534 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
2535 activityNdx > 0) {
2536 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
2537 break;
2538 }
2539 out.startTag(null, TAG_ACTIVITY);
2540 r.saveToXml(out);
2541 out.endTag(null, TAG_ACTIVITY);
2542 }
2543 }
2544
2545 @VisibleForTesting
2546 static TaskRecordFactory getTaskRecordFactory() {
2547 if (sTaskRecordFactory == null) {
2548 setTaskRecordFactory(new TaskRecordFactory());
2549 }
2550 return sTaskRecordFactory;
2551 }
2552
2553 static void setTaskRecordFactory(TaskRecordFactory factory) {
2554 sTaskRecordFactory = factory;
2555 }
2556
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002557 static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002558 Intent intent, IVoiceInteractionSession voiceSession,
2559 IVoiceInteractor voiceInteractor) {
2560 return getTaskRecordFactory().create(
2561 service, taskId, info, intent, voiceSession, voiceInteractor);
2562 }
2563
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002564 static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002565 Intent intent, TaskDescription taskDescription) {
2566 return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
2567 }
2568
2569 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2570 throws IOException, XmlPullParserException {
2571 return getTaskRecordFactory().restoreFromXml(in, stackSupervisor);
2572 }
2573
2574 /**
2575 * A factory class used to create {@link TaskRecord} or its subclass if any. This can be
2576 * specified when system boots by setting it with
2577 * {@link #setTaskRecordFactory(TaskRecordFactory)}.
2578 */
2579 static class TaskRecordFactory {
2580
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002581 TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002582 Intent intent, IVoiceInteractionSession voiceSession,
2583 IVoiceInteractor voiceInteractor) {
2584 return new TaskRecord(
2585 service, taskId, info, intent, voiceSession, voiceInteractor);
2586 }
2587
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002588 TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002589 Intent intent, TaskDescription taskDescription) {
2590 return new TaskRecord(service, taskId, info, intent, taskDescription);
2591 }
2592
2593 /**
2594 * Should only be used when we're restoring {@link TaskRecord} from storage.
2595 */
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002596 TaskRecord create(ActivityTaskManagerService service, int taskId, Intent intent,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002597 Intent affinityIntent, String affinity, String rootAffinity,
2598 ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
2599 boolean autoRemoveRecents, boolean askedCompatMode, int userId,
2600 int effectiveUid, String lastDescription, ArrayList<ActivityRecord> activities,
2601 long lastTimeMoved, boolean neverRelinquishIdentity,
2602 TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
2603 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
2604 int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
2605 boolean userSetupComplete, int minWidth, int minHeight) {
2606 return new TaskRecord(service, taskId, intent, affinityIntent, affinity,
2607 rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
2608 askedCompatMode, userId, effectiveUid, lastDescription, activities,
2609 lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
2610 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
2611 resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
2612 minWidth, minHeight);
2613 }
2614
2615 TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2616 throws IOException, XmlPullParserException {
2617 Intent intent = null;
2618 Intent affinityIntent = null;
2619 ArrayList<ActivityRecord> activities = new ArrayList<>();
2620 ComponentName realActivity = null;
2621 boolean realActivitySuspended = false;
2622 ComponentName origActivity = null;
2623 String affinity = null;
2624 String rootAffinity = null;
2625 boolean hasRootAffinity = false;
2626 boolean rootHasReset = false;
2627 boolean autoRemoveRecents = false;
2628 boolean askedCompatMode = false;
2629 int taskType = 0;
2630 int userId = 0;
2631 boolean userSetupComplete = true;
2632 int effectiveUid = -1;
2633 String lastDescription = null;
2634 long lastTimeOnTop = 0;
2635 boolean neverRelinquishIdentity = true;
2636 int taskId = INVALID_TASK_ID;
2637 final int outerDepth = in.getDepth();
2638 TaskDescription taskDescription = new TaskDescription();
2639 int taskAffiliation = INVALID_TASK_ID;
2640 int taskAffiliationColor = 0;
2641 int prevTaskId = INVALID_TASK_ID;
2642 int nextTaskId = INVALID_TASK_ID;
2643 int callingUid = -1;
2644 String callingPackage = "";
2645 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
2646 boolean supportsPictureInPicture = false;
Garfield Tan367b35a2017-12-13 12:16:21 -08002647 Rect lastNonFullscreenBounds = null;
Garfield Tan9b1efea2017-12-05 16:43:46 -08002648 int minWidth = INVALID_MIN_SIZE;
2649 int minHeight = INVALID_MIN_SIZE;
2650 int persistTaskVersion = 0;
2651
2652 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
2653 final String attrName = in.getAttributeName(attrNdx);
2654 final String attrValue = in.getAttributeValue(attrNdx);
2655 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
2656 attrName + " value=" + attrValue);
2657 switch (attrName) {
2658 case ATTR_TASKID:
2659 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
2660 break;
2661 case ATTR_REALACTIVITY:
2662 realActivity = ComponentName.unflattenFromString(attrValue);
2663 break;
2664 case ATTR_REALACTIVITY_SUSPENDED:
2665 realActivitySuspended = Boolean.valueOf(attrValue);
2666 break;
2667 case ATTR_ORIGACTIVITY:
2668 origActivity = ComponentName.unflattenFromString(attrValue);
2669 break;
2670 case ATTR_AFFINITY:
2671 affinity = attrValue;
2672 break;
2673 case ATTR_ROOT_AFFINITY:
2674 rootAffinity = attrValue;
2675 hasRootAffinity = true;
2676 break;
2677 case ATTR_ROOTHASRESET:
2678 rootHasReset = Boolean.parseBoolean(attrValue);
2679 break;
2680 case ATTR_AUTOREMOVERECENTS:
2681 autoRemoveRecents = Boolean.parseBoolean(attrValue);
2682 break;
2683 case ATTR_ASKEDCOMPATMODE:
2684 askedCompatMode = Boolean.parseBoolean(attrValue);
2685 break;
2686 case ATTR_USERID:
2687 userId = Integer.parseInt(attrValue);
2688 break;
2689 case ATTR_USER_SETUP_COMPLETE:
2690 userSetupComplete = Boolean.parseBoolean(attrValue);
2691 break;
2692 case ATTR_EFFECTIVE_UID:
2693 effectiveUid = Integer.parseInt(attrValue);
2694 break;
2695 case ATTR_TASKTYPE:
2696 taskType = Integer.parseInt(attrValue);
2697 break;
2698 case ATTR_LASTDESCRIPTION:
2699 lastDescription = attrValue;
2700 break;
2701 case ATTR_LASTTIMEMOVED:
2702 lastTimeOnTop = Long.parseLong(attrValue);
2703 break;
2704 case ATTR_NEVERRELINQUISH:
2705 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
2706 break;
2707 case ATTR_TASK_AFFILIATION:
2708 taskAffiliation = Integer.parseInt(attrValue);
2709 break;
2710 case ATTR_PREV_AFFILIATION:
2711 prevTaskId = Integer.parseInt(attrValue);
2712 break;
2713 case ATTR_NEXT_AFFILIATION:
2714 nextTaskId = Integer.parseInt(attrValue);
2715 break;
2716 case ATTR_TASK_AFFILIATION_COLOR:
2717 taskAffiliationColor = Integer.parseInt(attrValue);
2718 break;
2719 case ATTR_CALLING_UID:
2720 callingUid = Integer.parseInt(attrValue);
2721 break;
2722 case ATTR_CALLING_PACKAGE:
2723 callingPackage = attrValue;
2724 break;
2725 case ATTR_RESIZE_MODE:
2726 resizeMode = Integer.parseInt(attrValue);
2727 break;
2728 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
2729 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
2730 break;
2731 case ATTR_NON_FULLSCREEN_BOUNDS:
Garfield Tan367b35a2017-12-13 12:16:21 -08002732 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002733 break;
2734 case ATTR_MIN_WIDTH:
2735 minWidth = Integer.parseInt(attrValue);
2736 break;
2737 case ATTR_MIN_HEIGHT:
2738 minHeight = Integer.parseInt(attrValue);
2739 break;
2740 case ATTR_PERSIST_TASK_VERSION:
2741 persistTaskVersion = Integer.parseInt(attrValue);
2742 break;
2743 default:
2744 if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
2745 taskDescription.restoreFromXml(attrName, attrValue);
2746 } else {
2747 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
2748 }
2749 }
2750 }
2751
2752 int event;
2753 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
2754 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
2755 if (event == XmlPullParser.START_TAG) {
2756 final String name = in.getName();
2757 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
2758 "TaskRecord: START_TAG name=" + name);
2759 if (TAG_AFFINITYINTENT.equals(name)) {
2760 affinityIntent = Intent.restoreFromXml(in);
2761 } else if (TAG_INTENT.equals(name)) {
2762 intent = Intent.restoreFromXml(in);
2763 } else if (TAG_ACTIVITY.equals(name)) {
2764 ActivityRecord activity =
2765 ActivityRecord.restoreFromXml(in, stackSupervisor);
2766 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
2767 activity);
2768 if (activity != null) {
2769 activities.add(activity);
2770 }
2771 } else {
Garfield Tan1e740192017-12-12 14:37:42 -08002772 handleUnknownTag(name, in);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002773 }
2774 }
2775 }
2776 if (!hasRootAffinity) {
2777 rootAffinity = affinity;
2778 } else if ("@".equals(rootAffinity)) {
2779 rootAffinity = null;
2780 }
2781 if (effectiveUid <= 0) {
2782 Intent checkIntent = intent != null ? intent : affinityIntent;
2783 effectiveUid = 0;
2784 if (checkIntent != null) {
2785 IPackageManager pm = AppGlobals.getPackageManager();
2786 try {
2787 ApplicationInfo ai = pm.getApplicationInfo(
2788 checkIntent.getComponent().getPackageName(),
2789 PackageManager.MATCH_UNINSTALLED_PACKAGES
2790 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
2791 if (ai != null) {
2792 effectiveUid = ai.uid;
2793 }
2794 } catch (RemoteException e) {
2795 }
2796 }
2797 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
2798 + ": effectiveUid=" + effectiveUid);
2799 }
2800
2801 if (persistTaskVersion < 1) {
2802 // We need to convert the resize mode of home activities saved before version one if
2803 // they are marked as RESIZE_MODE_RESIZEABLE to
2804 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
2805 // before version 1 and the system didn't resize home activities before then.
2806 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
2807 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
2808 }
2809 } else {
2810 // This activity has previously marked itself explicitly as both resizeable and
2811 // supporting picture-in-picture. Since there is no longer a requirement for
2812 // picture-in-picture activities to be resizeable, we can mark this simply as
2813 // resizeable and supporting picture-in-picture separately.
2814 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
2815 resizeMode = RESIZE_MODE_RESIZEABLE;
2816 supportsPictureInPicture = true;
2817 }
2818 }
2819
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07002820 final TaskRecord task = create(stackSupervisor.mService,
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002821 taskId, intent, affinityIntent,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002822 affinity, rootAffinity, realActivity, origActivity, rootHasReset,
2823 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
2824 activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
2825 taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
2826 callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
2827 userSetupComplete, minWidth, minHeight);
Garfield Tan367b35a2017-12-13 12:16:21 -08002828 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
2829 task.setBounds(lastNonFullscreenBounds);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002830
2831 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
2832 activities.get(activityNdx).setTask(task);
2833 }
2834
2835 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
2836 return task;
2837 }
Garfield Tan1e740192017-12-12 14:37:42 -08002838
2839 void handleUnknownTag(String name, XmlPullParser in)
2840 throws IOException, XmlPullParserException {
2841 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
2842 XmlUtils.skipCurrentTag(in);
2843 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002844 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002845}