blob: 89499d695dd063d178b8bb9440f6b4d0efd057ee [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;
Riddle Hsu61987bc2019-04-03 13:08:47 +080025import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070026import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
27import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
28import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
29import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Wale Ogunwale44f036f2017-09-29 05:09:09 -070030import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Evan Rosky1ac84462018-11-13 11:25:30 -080031import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Jorim Jaggi0a932142016-02-01 17:42:25 -080032import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
Wale Ogunwale66e16852017-10-19 13:35:52 -070033import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Jorim Jaggi0a932142016-02-01 17:42:25 -080034import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
Wale Ogunwale66e16852017-10-19 13:35:52 -070035import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
Wale Ogunwale3eadad72016-10-13 09:16:59 -070036import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
Jorim Jaggi0a932142016-02-01 17:42:25 -080037import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
38import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
39import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
40import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080041import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
42import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
43import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Wale Ogunwaled829d362016-02-10 19:24:49 -080044import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070045import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -080046import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070047import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Evan Rosky730f6e82018-12-03 17:40:11 -080048import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
49import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
50import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
Riddle Hsu2ca561b2019-10-08 21:58:58 +080051import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
Suprabh Shukla7745c142016-03-07 18:21:10 -080052import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
Andrii Kulian036e3ad2017-04-19 10:55:10 -070053import static android.view.Display.DEFAULT_DISPLAY;
Garfield Tan891146c2018-10-09 12:14:00 -070054
Yunfan Chen0e7aff92018-12-05 16:35:32 -080055import static com.android.server.EventLogTags.WM_TASK_CREATED;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070056import static com.android.server.am.TaskRecordProto.ACTIVITIES;
Andrii Kulianab132ee2018-07-24 22:10:21 +080057import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070058import static com.android.server.am.TaskRecordProto.BOUNDS;
59import static com.android.server.am.TaskRecordProto.CONFIGURATION_CONTAINER;
60import static com.android.server.am.TaskRecordProto.FULLSCREEN;
61import static com.android.server.am.TaskRecordProto.ID;
62import static com.android.server.am.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
63import static com.android.server.am.TaskRecordProto.MIN_HEIGHT;
64import static com.android.server.am.TaskRecordProto.MIN_WIDTH;
65import static com.android.server.am.TaskRecordProto.ORIG_ACTIVITY;
66import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
67import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
68import static com.android.server.am.TaskRecordProto.STACK_ID;
Andrii Kulian057a6512019-07-15 16:15:51 -070069import static com.android.server.wm.ActivityRecord.FINISH_RESULT_REMOVED;
Garfield Tan891146c2018-10-09 12:14:00 -070070import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
71import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
72import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
73import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
Garfield Tan891146c2018-10-09 12:14:00 -070074import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
75import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
76import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
77import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
78import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
79import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
80import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
81import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
82import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
83import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
84import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Yunfan Chen0e7aff92018-12-05 16:35:32 -080085import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
86import static com.android.server.wm.WindowContainer.POSITION_TOP;
87import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
88import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Garfield Tan891146c2018-10-09 12:14:00 -070089
Winson Chung74666102017-02-22 17:49:24 -080090import static java.lang.Integer.MAX_VALUE;
91
Jorim Jaggie7d2b852017-08-28 17:55:15 +020092import android.annotation.IntDef;
Evan Rosky1ac84462018-11-13 11:25:30 -080093import android.annotation.NonNull;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020094import android.annotation.Nullable;
95import android.app.Activity;
96import android.app.ActivityManager;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020097import android.app.ActivityManager.TaskDescription;
98import android.app.ActivityManager.TaskSnapshot;
99import android.app.ActivityOptions;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700100import android.app.ActivityTaskManager;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200101import android.app.AppGlobals;
Winson Chungabfdcce2018-07-02 17:23:33 -0700102import android.app.TaskInfo;
Garfield Tan891146c2018-10-09 12:14:00 -0700103import android.app.WindowConfiguration;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200104import android.content.ComponentName;
105import android.content.Intent;
106import android.content.pm.ActivityInfo;
107import android.content.pm.ApplicationInfo;
108import android.content.pm.IPackageManager;
109import android.content.pm.PackageManager;
110import android.content.res.Configuration;
111import android.graphics.Rect;
112import android.os.Debug;
113import android.os.RemoteException;
Winson Chungfb44d212017-10-04 11:39:10 -0700114import android.os.SystemClock;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200115import android.os.Trace;
116import android.os.UserHandle;
117import android.provider.Settings;
118import android.service.voice.IVoiceInteractionSession;
119import android.util.DisplayMetrics;
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800120import android.util.EventLog;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200121import android.util.Slog;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700122import android.util.proto.ProtoOutputStream;
Mark Renoufb1abb552019-02-08 13:51:41 -0500123import android.view.Display;
Evan Rosky1ac84462018-11-13 11:25:30 -0800124import android.view.DisplayInfo;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200125
126import com.android.internal.annotations.VisibleForTesting;
127import com.android.internal.app.IVoiceInteractor;
128import com.android.internal.util.XmlUtils;
Wale Ogunwale59507092018-10-29 09:00:30 -0700129import com.android.server.wm.ActivityStack.ActivityState;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200130
131import org.xmlpull.v1.XmlPullParser;
132import org.xmlpull.v1.XmlPullParserException;
133import org.xmlpull.v1.XmlSerializer;
134
135import java.io.IOException;
136import java.io.PrintWriter;
137import java.lang.annotation.Retention;
138import java.lang.annotation.RetentionPolicy;
139import java.util.ArrayList;
140import java.util.Objects;
141
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800142class TaskRecord extends ConfigurationContainer {
Wale Ogunwale98875612018-10-12 07:53:02 -0700143 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_ATM;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700144 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700145 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
Craig Mautnere0570202015-05-13 13:06:11 -0700146 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700147 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800148
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700149 private static final String ATTR_TASKID = "task_id";
Craig Mautner21d24a22014-04-23 11:45:37 -0700150 private static final String TAG_INTENT = "intent";
151 private static final String TAG_AFFINITYINTENT = "affinity_intent";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700152 private static final String ATTR_REALACTIVITY = "real_activity";
153 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
Craig Mautner21d24a22014-04-23 11:45:37 -0700154 private static final String ATTR_ORIGACTIVITY = "orig_activity";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700155 private static final String TAG_ACTIVITY = "activity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700156 private static final String ATTR_AFFINITY = "affinity";
Dianne Hackborn79228822014-09-16 11:11:23 -0700157 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700158 private static final String ATTR_ROOTHASRESET = "root_has_reset";
Dianne Hackborn13420f22014-07-18 15:43:56 -0700159 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
Craig Mautner21d24a22014-04-23 11:45:37 -0700160 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
161 private static final String ATTR_USERID = "user_id";
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800162 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700163 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700164 @Deprecated
Craig Mautner21d24a22014-04-23 11:45:37 -0700165 private static final String ATTR_TASKTYPE = "task_type";
Craig Mautner21d24a22014-04-23 11:45:37 -0700166 private static final String ATTR_LASTDESCRIPTION = "last_description";
167 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700168 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700169 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
Craig Mautnera228ae92014-07-09 05:44:55 -0700170 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
171 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
Winson Chungec396d62014-08-06 17:08:00 -0700172 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700173 private static final String ATTR_CALLING_UID = "calling_uid";
174 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Winson Chungd3395382016-12-13 11:49:09 -0800175 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800176 private static final String ATTR_RESIZE_MODE = "resize_mode";
Wale Ogunwale706ed792015-08-02 10:29:44 -0700177 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700178 private static final String ATTR_MIN_WIDTH = "min_width";
179 private static final String ATTR_MIN_HEIGHT = "min_height";
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700180 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Andrii Kulian18d75122016-03-27 20:20:28 -0700181
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700182 // Current version of the task record we persist. Used to check if we need to run any upgrade
183 // code.
184 private static final int PERSIST_TASK_VERSION = 1;
Craig Mautner21d24a22014-04-23 11:45:37 -0700185
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700186 private static final int INVALID_MIN_SIZE = -1;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800187
Winson Chung74666102017-02-22 17:49:24 -0800188 /**
189 * The modes to control how the stack is moved to the front when calling
190 * {@link TaskRecord#reparent}.
191 */
192 @Retention(RetentionPolicy.SOURCE)
193 @IntDef({
194 REPARENT_MOVE_STACK_TO_FRONT,
195 REPARENT_KEEP_STACK_AT_FRONT,
196 REPARENT_LEAVE_STACK_IN_PLACE
197 })
Wale Ogunwale66e16852017-10-19 13:35:52 -0700198 @interface ReparentMoveStackMode {}
Winson Chung74666102017-02-22 17:49:24 -0800199 // Moves the stack to the front if it was not at the front
Wale Ogunwale66e16852017-10-19 13:35:52 -0700200 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
Winson Chung74666102017-02-22 17:49:24 -0800201 // Only moves the stack to the front if it was focused or front most already
Wale Ogunwale66e16852017-10-19 13:35:52 -0700202 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
Winson Chung74666102017-02-22 17:49:24 -0800203 // Do not move the stack as a part of reparenting
Wale Ogunwale66e16852017-10-19 13:35:52 -0700204 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
Winson Chung74666102017-02-22 17:49:24 -0800205
Garfield Tan9b1efea2017-12-05 16:43:46 -0800206 /**
207 * The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}.
208 */
209 private static TaskRecordFactory sTaskRecordFactory;
210
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700211 final int mTaskId; // Unique identifier for this task.
Dianne Hackborn79228822014-09-16 11:11:23 -0700212 String affinity; // The affinity name for this task, or null; may change identity.
213 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Dianne Hackborn91097de2014-04-04 18:02:06 -0700214 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
215 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Bryce Lee1a990e52018-04-23 10:54:11 -0700216 Intent intent; // The original intent that started the task. Note that this value can
217 // be null.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700219 int effectiveUid; // The current effective uid of the identity of this task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 ComponentName origActivity; // The non-alias activity component of the intent.
221 ComponentName realActivity; // The actual activity component that started the task.
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +0000222 boolean realActivitySuspended; // True if the actual activity component that started the
223 // task is suspended.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700224 boolean inRecents; // Actually in the recents list?
Winson Chungfb44d212017-10-04 11:39:10 -0700225 long lastActiveTime; // Last time this task was active in the current device session,
226 // including sleep. This time is initialized to the elapsed time when
227 // restored from disk.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700228 boolean isAvailable; // Is the activity available to be launched?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800229 boolean rootWasReset; // True if the intent at the root of the task had
230 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700231 boolean autoRemoveRecents; // If true, we should automatically remove the task from
232 // recents when activity finishes
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700233 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700234 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 -0800235
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700236 String stringName; // caching of toString() result.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700237 int mUserId; // user for which this task was created
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800238 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
239 // was changed.
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800240
241 int numFullscreen; // Number of fullscreen activities.
242
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800243 int mResizeMode; // The resize mode of this task and its activities.
244 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800245 private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
246 // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
247 // of the root activity.
Craig Mautner15df08a2015-04-01 12:17:18 -0700248 /** Can't be put in lockTask mode. */
249 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
Benjamin Franz469dd582015-06-09 14:24:36 +0100250 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700251 final static int LOCK_TASK_AUTH_PINNABLE = 1;
252 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
253 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
Benjamin Franz469dd582015-06-09 14:24:36 +0100254 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700255 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
Benjamin Franz469dd582015-06-09 14:24:36 +0100256 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
257 * lockTask task. */
258 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
Craig Mautner15df08a2015-04-01 12:17:18 -0700259 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
260
261 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800262
Winson Chung03a9bae2014-05-02 09:56:12 -0700263 // This represents the last resolved activity values for this task
264 // NOTE: This value needs to be persisted with each task
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700265 TaskDescription mTaskDescription;
Winson Chung03a9bae2014-05-02 09:56:12 -0700266
Craig Mautnerd2328952013-03-05 12:46:26 -0800267 /** List of all activities in the task arranged in history order */
Craig Mautner21d24a22014-04-23 11:45:37 -0700268 final ArrayList<ActivityRecord> mActivities;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800269
Andrii Kulian02b7a832016-10-06 23:11:56 -0700270 /** Current stack. Setter must always be used to update the value. */
271 private ActivityStack mStack;
Craig Mautnerd2328952013-03-05 12:46:26 -0800272
Dianne Hackborn68a06332017-11-15 17:54:18 -0800273 /** The process that had previously hosted the root activity of this task.
274 * Used to know that we should try harder to keep this process around, in case the
275 * user wants to return to it. */
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700276 private WindowProcessController mRootProcess;
Dianne Hackborn68a06332017-11-15 17:54:18 -0800277
Craig Mautner21d24a22014-04-23 11:45:37 -0700278 /** Takes on same value as first root activity */
279 boolean isPersistable = false;
Craig Mautnerffcfcaa2014-06-05 09:54:38 -0700280 int maxRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700281
282 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
283 * determining the order when restoring. Sign indicates whether last task movement was to front
284 * (positive) or back (negative). Absolute value indicates time. */
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700285 long mLastTimeMoved;
Craig Mautner21d24a22014-04-23 11:45:37 -0700286
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700287 /** If original intent did not allow relinquishing task identity, save that information */
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700288 private boolean mNeverRelinquishIdentity = true;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700289
Craig Mautner362449a2014-06-20 14:04:39 -0700290 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
291 // do not want to delete the stack when the task goes empty.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800292 private boolean mReuseTask = false;
Craig Mautner362449a2014-06-20 14:04:39 -0700293
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700294 CharSequence lastDescription; // Last description captured for this item.
295
Craig Mautnera228ae92014-07-09 05:44:55 -0700296 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Winson Chungec396d62014-08-06 17:08:00 -0700297 int mAffiliatedTaskColor; // color of the parent task affiliation.
Craig Mautnera228ae92014-07-09 05:44:55 -0700298 TaskRecord mPrevAffiliate; // previous task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800299 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700300 TaskRecord mNextAffiliate; // next task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800301 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700302
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700303 // For relaunching the task from recents as though it was launched by the original launcher.
304 int mCallingUid;
305 String mCallingPackage;
306
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700307 final ActivityTaskManagerService mAtmService;
Craig Mautner21d24a22014-04-23 11:45:37 -0700308
Jorim Jaggi82c9dc92016-02-05 15:10:33 -0800309 private final Rect mTmpStableBounds = new Rect();
310 private final Rect mTmpNonDecorBounds = new Rect();
Evan Rosky1ac84462018-11-13 11:25:30 -0800311 private final Rect mTmpBounds = new Rect();
312 private final Rect mTmpInsets = new Rect();
Jorim Jaggi0a932142016-02-01 17:42:25 -0800313
Wale Ogunwale706ed792015-08-02 10:29:44 -0700314 // Last non-fullscreen bounds the task was launched in or resized to.
315 // The information is persisted and used to determine the appropriate stack to launch the
316 // task into on restore.
317 Rect mLastNonFullscreenBounds = null;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700318 // Minimal width and height of this task when it's resizeable. -1 means it should use the
319 // default minimal width/height.
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700320 int mMinWidth;
321 int mMinHeight;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700322
Chong Zhangfdcc4d42015-10-14 16:50:12 -0700323 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
324 // This number will be assigned when we evaluate OOM scores for all visible tasks.
325 int mLayerRank = -1;
326
Evan Roskyed6767f2018-10-26 17:21:06 -0700327 // When non-empty, this represents the bounds this task will be drawn at. This gets set during
328 // transient operations such as split-divider dragging and animations.
329 // TODO(b/119687367): This member is temporary.
330 final Rect mDisplayedBounds = new Rect();
331
Andrii Kulian1779e612016-10-12 21:58:25 -0700332 /** Helper object used for updating override configuration. */
333 private Configuration mTmpConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700334
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800335 // TODO: remove after unification
336 Task mTask;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800337
Mark Renoufc808f062019-02-07 15:20:37 -0500338 /** Used by fillTaskInfo */
339 final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
340
Garfield Tan9b1efea2017-12-05 16:43:46 -0800341 /**
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700342 * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
343 * ActivityInfo, Intent, TaskDescription)} instead.
Garfield Tan9b1efea2017-12-05 16:43:46 -0800344 */
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700345 TaskRecord(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info,
346 Intent _intent, IVoiceInteractionSession _voiceSession,
347 IVoiceInteractor _voiceInteractor, TaskDescription _taskDescription) {
348 this(atmService, _taskId, _intent, null /*_affinityIntent*/, null /*_affinity*/,
349 null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
350 false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
351 UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
352 null /*_lastDescription*/, new ArrayList<>(), System.currentTimeMillis(),
353 true /*neverRelinquishIdentity*/,
354 _taskDescription != null ? _taskDescription : new TaskDescription(),
355 _taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
356 info.applicationInfo.uid, info.packageName, info.resizeMode,
357 info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
358 false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
359 _voiceSession, _voiceInteractor);
Craig Mautner21d24a22014-04-23 11:45:37 -0700360 }
361
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700362 /** Don't use constructor directly. This is only used by XML parser. */
363 TaskRecord(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800364 Intent _affinityIntent, String _affinity, String _rootAffinity,
365 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700366 boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800367 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
Winson Chungfb44d212017-10-04 11:39:10 -0700368 long lastTimeMoved, boolean neverRelinquishIdentity,
369 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
370 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Charles He2bf28322017-10-12 22:24:49 +0100371 int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700372 boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info,
373 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
374 mAtmService = atmService;
375 mTaskId = _taskId;
Craig Mautner21d24a22014-04-23 11:45:37 -0700376 affinityIntent = _affinityIntent;
377 affinity = _affinity;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800378 rootAffinity = _rootAffinity;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700379 voiceSession = _voiceSession;
380 voiceInteractor = _voiceInteractor;
Craig Mautner21d24a22014-04-23 11:45:37 -0700381 realActivity = _realActivity;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800382 realActivitySuspended = _realActivitySuspended;
Craig Mautner21d24a22014-04-23 11:45:37 -0700383 origActivity = _origActivity;
384 rootWasReset = _rootWasReset;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700385 isAvailable = true;
Dianne Hackborn13420f22014-07-18 15:43:56 -0700386 autoRemoveRecents = _autoRemoveRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700387 askedCompatMode = _askedCompatMode;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700388 mUserId = _userId;
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800389 mUserSetupComplete = userSetupComplete;
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700390 effectiveUid = _effectiveUid;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700391 touchActiveTime();
Craig Mautner21d24a22014-04-23 11:45:37 -0700392 lastDescription = _lastDescription;
393 mActivities = activities;
394 mLastTimeMoved = lastTimeMoved;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700395 mNeverRelinquishIdentity = neverRelinquishIdentity;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700396 mTaskDescription = _lastTaskDescription;
Craig Mautnera228ae92014-07-09 05:44:55 -0700397 mAffiliatedTaskId = taskAffiliation;
Winson Chungec396d62014-08-06 17:08:00 -0700398 mAffiliatedTaskColor = taskAffiliationColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700399 mPrevAffiliateTaskId = prevTaskId;
400 mNextAffiliateTaskId = nextTaskId;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700401 mCallingUid = callingUid;
402 mCallingPackage = callingPackage;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800403 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800404 mSupportsPictureInPicture = supportsPictureInPicture;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700405 if (info != null) {
406 setIntent(_intent, info);
407 setMinDimensions(info);
408 } else {
409 intent = _intent;
410 mMinWidth = minWidth;
411 mMinHeight = minHeight;
412 }
413 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800414 }
415
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800416 Task getTask() {
417 return mTask;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800418 }
419
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800420 void createTask(boolean onTop, boolean showForAllUsers) {
421 if (mTask != null) {
422 throw new IllegalArgumentException("mTask=" + mTask
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800423 + " already created for task=" + this);
424 }
425
426 final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
Yunfan Chen279f5582018-12-12 15:24:50 -0800427 final TaskStack stack = getStack().getTaskStack();
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800428
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800429 if (stack == null) {
Yunfan Chen279f5582018-12-12 15:24:50 -0800430 throw new IllegalArgumentException("TaskRecord: invalid stack=" + mStack);
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800431 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700432 EventLog.writeEvent(WM_TASK_CREATED, mTaskId, stack.mStackId);
433 mTask = new Task(mTaskId, stack, mUserId, mAtmService.mWindowManager, mResizeMode,
434 mSupportsPictureInPicture, mTaskDescription, this);
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800435 final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
436
437 if (!mDisplayedBounds.isEmpty()) {
438 mTask.setOverrideDisplayedBounds(mDisplayedBounds);
439 }
440 // We only want to move the parents to the parents if we are creating this task at the
441 // top of its stack.
442 stack.addTask(mTask, position, showForAllUsers, onTop /* moveParents */);
Bryce Lee04ab3462017-04-10 15:06:33 -0700443 }
444
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800445 void setTask(Task task) {
446 mTask = task;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800447 }
448
Garfield Tan347bd602018-12-21 15:11:12 -0800449 void cleanUpResourcesForDestroy() {
Wale Ogunwale1a06f152019-10-11 11:26:30 +0200450 if (hasChild()) {
Garfield Tan347bd602018-12-21 15:11:12 -0800451 return;
452 }
453
454 // This task is going away, so save the last state if necessary.
455 saveLaunchingStateIfNeeded();
456
457 // TODO: VI what about activity?
458 final boolean isVoiceSession = voiceSession != null;
459 if (isVoiceSession) {
460 try {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700461 voiceSession.taskFinished(intent, mTaskId);
Garfield Tan347bd602018-12-21 15:11:12 -0800462 } catch (RemoteException e) {
463 }
464 }
465 if (autoRemoveFromRecents() || isVoiceSession) {
466 // Task creator asked to remove this when done, or this task was a voice
467 // interaction, so it should not remain on the recent tasks list.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700468 mAtmService.mStackSupervisor.mRecentTasks.remove(this);
Garfield Tan347bd602018-12-21 15:11:12 -0800469 }
470
471 removeWindowContainer();
472 }
473
474 @VisibleForTesting
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800475 void removeWindowContainer() {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700476 mAtmService.getLockTaskController().clearLockedTask(this);
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800477 if (mTask == null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700478 if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800479 return;
480 }
481 mTask.removeIfPossible();
482 mTask = null;
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700483 if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800484 // Reset current bounds for task whose bounds shouldn't be persisted so it uses
485 // default configuration the next time it launches.
Evan Roskya4cc3a92019-06-28 13:25:01 -0700486 setBounds(null);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800487 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700488 mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800489 }
490
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700491 void onSnapshotChanged(TaskSnapshot snapshot) {
492 mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(mTaskId, snapshot);
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100493 }
494
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800495 void setResizeMode(int resizeMode) {
496 if (mResizeMode == resizeMode) {
497 return;
498 }
499 mResizeMode = resizeMode;
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800500 mTask.setResizeable(resizeMode);
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700501 mAtmService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
502 mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800503 }
504
505 void setTaskDockedResizing(boolean resizing) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800506 if (mTask == null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700507 Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found.");
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800508 return;
509 }
510 mTask.setTaskDockedResizing(resizing);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800511 }
512
Wale Ogunwale1666e312016-12-16 11:27:18 -0800513 // TODO: Consolidate this with the resize() method below.
Wale Ogunwale1666e312016-12-16 11:27:18 -0800514 public void requestResize(Rect bounds, int resizeMode) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700515 mAtmService.resizeTask(mTaskId, bounds, resizeMode);
Wale Ogunwale1666e312016-12-16 11:27:18 -0800516 }
517
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800518 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700519 mAtmService.deferWindowLayout();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800520
Bryce Leef3c6a472017-11-14 14:53:06 -0800521 try {
Bryce Leef3c6a472017-11-14 14:53:06 -0800522 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800523
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800524 if (mTask == null) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800525 // Task doesn't exist in window manager yet (e.g. was restored from recents).
526 // All we can do for now is update the bounds so it can be used when the task is
527 // added to window manager.
Evan Roskya4cc3a92019-06-28 13:25:01 -0700528 setBounds(bounds);
Bryce Leef3c6a472017-11-14 14:53:06 -0800529 if (!inFreeformWindowingMode()) {
530 // re-restore the task so it can have the proper stack association.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700531 mAtmService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
Bryce Leef3c6a472017-11-14 14:53:06 -0800532 }
533 return true;
534 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800535
Bryce Leef3c6a472017-11-14 14:53:06 -0800536 if (!canResizeToBounds(bounds)) {
537 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
538 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
539 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800540
Bryce Leef3c6a472017-11-14 14:53:06 -0800541 // Do not move the task to another stack here.
542 // This method assumes that the task is already placed in the right stack.
543 // we do not mess with that decision and we only do the resize!
544
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800545 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeTask_" + mTaskId);
Bryce Leef3c6a472017-11-14 14:53:06 -0800546
Evan Roskya4cc3a92019-06-28 13:25:01 -0700547 boolean updatedConfig = false;
548 mTmpConfig.setTo(getResolvedOverrideConfiguration());
549 if (setBounds(bounds) != BOUNDS_CHANGE_NONE) {
550 updatedConfig = !mTmpConfig.equals(getResolvedOverrideConfiguration());
551 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800552 // This variable holds information whether the configuration didn't change in a significant
553
554 // way and the activity was kept the way it was. If it's false, it means the activity
555 // had
556 // to be relaunched due to configuration change.
557 boolean kept = true;
558 if (updatedConfig) {
559 final ActivityRecord r = topRunningActivityLocked();
560 if (r != null && !deferResume) {
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800561 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
Bryce Leef3c6a472017-11-14 14:53:06 -0800562 preserveWindow);
Garfield Tanb9151182018-06-25 16:29:21 -0700563 // Preserve other windows for resizing because if resizing happens when there
564 // is a dialog activity in the front, the activity that still shows some
565 // content to the user will become black and cause flickers. Note in most cases
566 // this won't cause tons of irrelevant windows being preserved because only
567 // activities in this task may experience a bounds change. Configs for other
568 // activities stay the same.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700569 mAtmService.mRootActivityContainer.ensureActivitiesVisible(r, 0, preserveWindow);
Bryce Leef3c6a472017-11-14 14:53:06 -0800570 if (!kept) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700571 mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
Bryce Leef3c6a472017-11-14 14:53:06 -0800572 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800573 }
574 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800575 mTask.resize(kept, forced);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800576
Garfield Tan891146c2018-10-09 12:14:00 -0700577 saveLaunchingStateIfNeeded();
578
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800579 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Bryce Leef3c6a472017-11-14 14:53:06 -0800580 return kept;
581 } finally {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700582 mAtmService.continueWindowLayout();
Bryce Leef3c6a472017-11-14 14:53:06 -0800583 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800584 }
585
586 // TODO: Investigate combining with the resize() method above.
587 void resizeWindowContainer() {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800588 mTask.resize(false /* relayout */, false /* forced */);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800589 }
590
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800591 void getWindowContainerBounds(Rect bounds) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800592 if (mTask != null) {
593 mTask.getBounds(bounds);
594 } else {
595 bounds.setEmpty();
596 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800597 }
598
Winson Chung74666102017-02-22 17:49:24 -0800599 /**
600 * Convenience method to reparent a task to the top or bottom position of the stack.
601 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700602 boolean reparent(ActivityStack preferredStack, boolean toTop,
603 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
604 String reason) {
605 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
606 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung5af42fc2017-03-24 17:11:33 -0700607 }
608
609 /**
610 * Convenience method to reparent a task to the top or bottom position of the stack, with
611 * an option to skip scheduling the picture-in-picture mode change.
612 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700613 boolean reparent(ActivityStack preferredStack, boolean toTop,
614 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
615 boolean schedulePictureInPictureModeChange, String reason) {
616 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
Winson Chung5af42fc2017-03-24 17:11:33 -0700617 deferResume, schedulePictureInPictureModeChange, reason);
618 }
619
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700620 /** Convenience method to reparent a task to a specific position of the stack. */
621 boolean reparent(ActivityStack preferredStack, int position,
622 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
623 String reason) {
624 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
Winson Chung5af42fc2017-03-24 17:11:33 -0700625 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800626 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800627
Winson Chung74666102017-02-22 17:49:24 -0800628 /**
629 * Reparents the task into a preferred stack, creating it if necessary.
630 *
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700631 * @param preferredStack the target stack to move this task
Winson Chung74666102017-02-22 17:49:24 -0800632 * @param position the position to place this task in the new stack
633 * @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 -0700634 * reparenting to be drawn and animated in
Winson Chung74666102017-02-22 17:49:24 -0800635 * @param moveStackMode whether or not to move the stack to the front always, only if it was
Winson Chung5af42fc2017-03-24 17:11:33 -0700636 * previously focused & in front, or never
Winson Chung74666102017-02-22 17:49:24 -0800637 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
Winson Chung5af42fc2017-03-24 17:11:33 -0700638 * have changed as a result of this reparenting
639 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
640 * change. Callers may set this to false if they are explicitly scheduling PiP mode
641 * changes themselves, like during the PiP animation
Winson Chung74666102017-02-22 17:49:24 -0800642 * @param reason the caller of this reparenting
Winson Chung5af42fc2017-03-24 17:11:33 -0700643 * @return whether the task was reparented
Winson Chung74666102017-02-22 17:49:24 -0800644 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700645 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700646 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700647 boolean reparent(ActivityStack preferredStack, int position,
648 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
649 boolean schedulePictureInPictureModeChange, String reason) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700650 final ActivityStackSupervisor supervisor = mAtmService.mStackSupervisor;
651 final RootActivityContainer root = mAtmService.mRootActivityContainer;
652 final WindowManagerService windowManager = mAtmService.mWindowManager;
Winson Chung74666102017-02-22 17:49:24 -0800653 final ActivityStack sourceStack = getStack();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700654 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
Winson Chung74666102017-02-22 17:49:24 -0800655 position == MAX_VALUE);
656 if (toStack == sourceStack) {
657 return false;
658 }
Andrii Kulianb850ea52017-12-12 23:49:10 -0800659 if (!canBeLaunchedOnDisplay(toStack.mDisplayId)) {
660 return false;
661 }
Winson Chung74666102017-02-22 17:49:24 -0800662
Andrii Kulian6b321512019-01-23 06:37:00 +0000663 final boolean toTopOfStack = position == MAX_VALUE;
664 if (toTopOfStack && toStack.getResumedActivity() != null
665 && toStack.topRunningActivityLocked() != null) {
666 // Pause the resumed activity on the target stack while re-parenting task on top of it.
667 toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
Louis Chang7b03ad92019-08-21 12:32:33 +0800668 null /* resuming */);
Andrii Kulian6b321512019-01-23 06:37:00 +0000669 }
670
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700671 final int toStackWindowingMode = toStack.getWindowingMode();
Winson Chung74666102017-02-22 17:49:24 -0800672 final ActivityRecord topActivity = getTopActivity();
673
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800674 final boolean mightReplaceWindow = topActivity != null
675 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
Winson Chung74666102017-02-22 17:49:24 -0800676 if (mightReplaceWindow) {
677 // We are about to relaunch the activity because its configuration changed due to
678 // being maximized, i.e. size change. The activity will first remove the old window
679 // and then add a new one. This call will tell window manager about this, so it can
680 // preserve the old window until the new one is drawn. This prevents having a gap
681 // between the removal and addition, in which no window is visible. We also want the
682 // entrance of the new window to be properly animated.
683 // Note here we always set the replacing window first, as the flags might be needed
684 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
685 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
686 }
687
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700688 mAtmService.deferWindowLayout();
Winson Chung74666102017-02-22 17:49:24 -0800689 boolean kept = true;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800690 try {
Winson Chung74666102017-02-22 17:49:24 -0800691 final ActivityRecord r = topRunningActivityLocked();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800692 final boolean wasFocused = r != null && root.isTopDisplayFocusedStack(sourceStack)
Winson Chung74666102017-02-22 17:49:24 -0800693 && (topRunningActivityLocked() == r);
Bryce Leec4ab62a2018-03-05 14:19:26 -0800694 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
Winson Chung95f8f0e2017-03-24 09:20:17 -0700695 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
Winson Chung74666102017-02-22 17:49:24 -0800696
697 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
698 // Whenever we are moving the top activity from the front stack we want to make sure to
699 // move the stack to the front.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700700 final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
Winson Chung74666102017-02-22 17:49:24 -0800701 && (sourceStack.topRunningActivityLocked() == r);
702
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800703 // Adjust the position for the new parent stack as needed.
Winson Chung74666102017-02-22 17:49:24 -0800704 position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800705
706 // Must reparent first in window manager to avoid a situation where AM can delete the
707 // we are coming from in WM before we reparent because it became empty.
Yunfan Chen279f5582018-12-12 15:24:50 -0800708 mTask.reparent(toStack.getTaskStack(), position,
Wale Ogunwale2719cc12017-04-14 09:45:27 -0700709 moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800710
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700711 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
712 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
Winson Chung74666102017-02-22 17:49:24 -0800713 // Move the task
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700714 sourceStack.removeTask(this, reason, moveStackToFront
715 ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
Winson Chung5af42fc2017-03-24 17:11:33 -0700716 toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800717
Winson Chung5af42fc2017-03-24 17:11:33 -0700718 if (schedulePictureInPictureModeChange) {
719 // Notify of picture-in-picture mode changes
720 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
721 }
Winson Chung74666102017-02-22 17:49:24 -0800722
723 // TODO: Ensure that this is actually necessary here
724 // Notify the voice session if required
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800725 if (voiceSession != null) {
726 try {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700727 voiceSession.taskStarted(intent, mTaskId);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800728 } catch (RemoteException e) {
729 }
730 }
Winson Chung74666102017-02-22 17:49:24 -0800731
732 // If the task had focus before (or we're requested to move focus), move focus to the
733 // new stack by moving the stack to the front.
Winson Chung95f8f0e2017-03-24 09:20:17 -0700734 if (r != null) {
735 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
736 wasPaused, reason);
737 }
Winson Chung74666102017-02-22 17:49:24 -0800738 if (!animate) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700739 mAtmService.mStackSupervisor.mNoAnimActivities.add(topActivity);
Winson Chung74666102017-02-22 17:49:24 -0800740 }
741
742 // We might trigger a configuration change. Save the current task bounds for freezing.
743 // TODO: Should this call be moved inside the resize method in WM?
744 toStack.prepareFreezingTaskBounds();
745
746 // Make sure the task has the appropriate bounds/size for the stack it is in.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700747 final boolean toStackSplitScreenPrimary =
748 toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Evan Roskydfe3da72018-10-26 17:21:06 -0700749 final Rect configBounds = getRequestedOverrideBounds();
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700750 if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
751 || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
Evan Roskydfe3da72018-10-26 17:21:06 -0700752 && !Objects.equals(configBounds, toStack.getRequestedOverrideBounds())) {
753 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
754 !mightReplaceWindow, deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700755 } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Winson Chung74666102017-02-22 17:49:24 -0800756 Rect bounds = getLaunchBounds();
757 if (bounds == null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700758 mAtmService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Bryce Leef3c6a472017-11-14 14:53:06 -0800759 bounds = configBounds;
Winson Chung74666102017-02-22 17:49:24 -0800760 }
761 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700762 } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
763 if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
Matthew Ng330757d2017-02-28 14:19:17 -0800764 // Move recents to front so it is not behind home stack when going into docked
765 // mode
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700766 mAtmService.mStackSupervisor.moveRecentsStackToFront(reason);
Matthew Ng330757d2017-02-28 14:19:17 -0800767 }
Evan Roskydfe3da72018-10-26 17:21:06 -0700768 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
769 !mightReplaceWindow, deferResume);
Winson Chung74666102017-02-22 17:49:24 -0800770 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800771 } finally {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700772 mAtmService.continueWindowLayout();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800773 }
Winson Chung74666102017-02-22 17:49:24 -0800774
775 if (mightReplaceWindow) {
776 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
777 // window), we need to clear the replace window settings. Otherwise, we schedule a
778 // timeout to remove the old window if the replacing window is not coming in time.
779 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
780 }
781
782 if (!deferResume) {
783 // The task might have already been running and its visibility needs to be synchronized
784 // with the visibility of the stack / windows.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800785 root.ensureActivitiesVisible(null, 0, !mightReplaceWindow);
786 root.resumeFocusedStacksTopActivities();
Winson Chung74666102017-02-22 17:49:24 -0800787 }
788
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700789 // TODO: Handle incorrect request to move before the actual move, not after.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700790 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700791 DEFAULT_DISPLAY, toStack);
Winson Chung74666102017-02-22 17:49:24 -0800792
Winson Chungdff7a732017-12-11 12:17:06 -0800793 return (preferredStack == toStack);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800794 }
795
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700796 /**
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800797 * @return True if the windows of tasks being moved to the target stack from the source stack
798 * should be replaced, meaning that window manager will keep the old window around until the new
799 * is ready.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700800 */
801 private static boolean replaceWindowsOnTaskMove(
802 int sourceWindowingMode, int targetWindowingMode) {
803 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
804 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
805 }
806
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800807 void cancelWindowTransition() {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800808 if (mTask == null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700809 Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800810 return;
811 }
812 mTask.cancelTaskWindowTransition();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800813 }
814
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100815 /**
816 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
817 */
Jorim Jaggi925bb3c2019-06-04 19:51:45 +0200818 TaskSnapshot getSnapshot(boolean reducedResolution, boolean restoreFromDisk) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100819
820 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
821 // synchronized between AM and WM.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700822 return mAtmService.mWindowManager.getTaskSnapshot(mTaskId, mUserId, reducedResolution,
Jorim Jaggi925bb3c2019-06-04 19:51:45 +0200823 restoreFromDisk);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800824 }
825
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800826 void touchActiveTime() {
Winson Chungfb44d212017-10-04 11:39:10 -0700827 lastActiveTime = SystemClock.elapsedRealtime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800828 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700829
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800830 long getInactiveDuration() {
Winson Chungfb44d212017-10-04 11:39:10 -0700831 return SystemClock.elapsedRealtime() - lastActiveTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800832 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700833
Winson Chungfee26772014-08-05 12:21:52 -0700834 /** Sets the original intent, and the calling uid and package. */
835 void setIntent(ActivityRecord r) {
Winson Chungfee26772014-08-05 12:21:52 -0700836 mCallingUid = r.launchedFromUid;
837 mCallingPackage = r.launchedFromPackage;
Craig Mautner15df08a2015-04-01 12:17:18 -0700838 setIntent(r.intent, r.info);
Charles He2bf28322017-10-12 22:24:49 +0100839 setLockTaskAuth(r);
Winson Chungfee26772014-08-05 12:21:52 -0700840 }
841
842 /** Sets the original intent, _without_ updating the calling uid or package. */
843 private void setIntent(Intent _intent, ActivityInfo info) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700844 if (intent == null) {
845 mNeverRelinquishIdentity =
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700846 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700847 } else if (mNeverRelinquishIdentity) {
848 return;
849 }
850
851 affinity = info.taskAffinity;
Dianne Hackborn79228822014-09-16 11:11:23 -0700852 if (intent == null) {
853 // If this task already has an intent associated with it, don't set the root
854 // affinity -- we don't want it changing after initially set, but the initially
855 // set value may be null.
856 rootAffinity = affinity;
857 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700858 effectiveUid = info.applicationInfo.uid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700859 stringName = null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800860
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800861 if (info.targetActivity == null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800862 if (_intent != null) {
863 // If this Intent has a selector, we want to clear it for the
864 // recent task since it is not relevant if the user later wants
865 // to re-launch the app.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700866 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800867 _intent = new Intent(_intent);
868 _intent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700869 _intent.setSourceBounds(null);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800870 }
871 }
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700872 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800873 intent = _intent;
874 realActivity = _intent != null ? _intent.getComponent() : null;
875 origActivity = null;
876 } else {
877 ComponentName targetComponent = new ComponentName(
878 info.packageName, info.targetActivity);
879 if (_intent != null) {
880 Intent targetIntent = new Intent(_intent);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800881 targetIntent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700882 targetIntent.setSourceBounds(null);
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700883 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
Dianne Hackborn7f96b792012-05-29 18:46:45 -0700884 "Setting Intent of " + this + " to target " + targetIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800885 intent = targetIntent;
886 realActivity = targetComponent;
887 origActivity = _intent.getComponent();
888 } else {
889 intent = null;
890 realActivity = targetComponent;
891 origActivity = new ComponentName(info.packageName, info.name);
892 }
893 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700894
Craig Mautner47b20ba2014-09-17 17:23:44 -0700895 final int intentFlags = intent == null ? 0 : intent.getFlags();
896 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800897 // Once we are set to an Intent with this flag, we count this
898 // task as having a true root activity.
899 rootWasReset = true;
900 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700901 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
902 mUserSetupComplete = Settings.Secure.getIntForUser(
903 mAtmService.mContext.getContentResolver(), USER_SETUP_COMPLETE, 0, mUserId) != 0;
Craig Mautner41db4a72014-05-07 17:20:56 -0700904 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700905 // If the activity itself has requested auto-remove, then just always do it.
906 autoRemoveRecents = true;
Wale Ogunwale843bfb92015-03-27 11:06:48 -0700907 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
908 == FLAG_ACTIVITY_NEW_DOCUMENT) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700909 // If the caller has not asked for the document to be retained, then we may
910 // want to turn on auto-remove, depending on whether the target has set its
911 // own document launch mode.
912 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
913 autoRemoveRecents = false;
914 } else {
915 autoRemoveRecents = true;
916 }
917 } else {
918 autoRemoveRecents = false;
Craig Mautner41db4a72014-05-07 17:20:56 -0700919 }
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800920 mResizeMode = info.resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800921 mSupportsPictureInPicture = info.supportsPictureInPicture();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800922 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800923
Andrii Kulian2e751b82016-03-16 16:59:32 -0700924 /** Sets the original minimal width and height. */
925 private void setMinDimensions(ActivityInfo info) {
926 if (info != null && info.windowLayout != null) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700927 mMinWidth = info.windowLayout.minWidth;
928 mMinHeight = info.windowLayout.minHeight;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700929 } else {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700930 mMinWidth = INVALID_MIN_SIZE;
931 mMinHeight = INVALID_MIN_SIZE;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700932 }
933 }
934
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800935 /**
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700936 * Return true if the input activity has the same intent filter as the intent this task
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800937 * record is based on (normally the root activity intent).
938 */
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700939 boolean isSameIntentFilter(ActivityRecord r) {
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800940 final Intent intent = new Intent(r.intent);
Louis Chang23df1a62019-01-09 15:10:49 +0800941 // Make sure the component are the same if the input activity has the same real activity
942 // as the one in the task because either one of them could be the alias activity.
943 if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) {
944 intent.setComponent(this.intent.getComponent());
945 }
Bryce Lee1a990e52018-04-23 10:54:11 -0700946 return intent.filterEquals(this.intent);
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800947 }
948
Wale Ogunwale66e16852017-10-19 13:35:52 -0700949 boolean returnsToHomeStack() {
950 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
Bryce Lee1a990e52018-04-23 10:54:11 -0700951 return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700952 }
953
Craig Mautnera228ae92014-07-09 05:44:55 -0700954 void setPrevAffiliate(TaskRecord prevAffiliate) {
955 mPrevAffiliate = prevAffiliate;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700956 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.mTaskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700957 }
958
959 void setNextAffiliate(TaskRecord nextAffiliate) {
960 mNextAffiliate = nextAffiliate;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700961 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700962 }
963
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700964 <T extends ActivityStack> T getStack() {
965 return (T) mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700966 }
967
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800968 /**
969 * Must be used for setting parent stack because it performs configuration updates.
970 * Must be called after adding task as a child to the stack.
971 */
Andrii Kulian02b7a832016-10-06 23:11:56 -0700972 void setStack(ActivityStack stack) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800973 if (stack != null && !stack.isInStackLocked(this)) {
974 throw new IllegalStateException("Task must be added as a Stack child first.");
975 }
Bryce Lee84730a02018-04-03 14:10:04 -0700976 final ActivityStack oldStack = mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700977 mStack = stack;
Bryce Lee84730a02018-04-03 14:10:04 -0700978
979 // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
980 // {@link ActivityRecord} from its current {@link ActivityStack}.
981
982 if (oldStack != mStack) {
983 for (int i = getChildCount() - 1; i >= 0; --i) {
984 final ActivityRecord activity = getChildAt(i);
985
986 if (oldStack != null) {
987 oldStack.onActivityRemovedFromStack(activity);
988 }
989
990 if (mStack != null) {
991 stack.onActivityAddedToStack(activity);
992 }
993 }
994 }
995
Andrii Kulian1779e612016-10-12 21:58:25 -0700996 onParentChanged();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700997 }
998
999 /**
1000 * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
1001 */
1002 int getStackId() {
1003 return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
1004 }
1005
Andrii Kulian1779e612016-10-12 21:58:25 -07001006 @Override
1007 protected int getChildCount() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001008 return mActivities.size();
Andrii Kulian1779e612016-10-12 21:58:25 -07001009 }
1010
1011 @Override
chaviw82a0ba82018-03-15 14:26:29 -07001012 protected ActivityRecord getChildAt(int index) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001013 return mActivities.get(index);
Andrii Kulian1779e612016-10-12 21:58:25 -07001014 }
1015
1016 @Override
1017 protected ConfigurationContainer getParent() {
1018 return mStack;
1019 }
1020
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001021 @Override
Wale Ogunwale98d62312017-07-12 09:24:56 -07001022 protected void onParentChanged() {
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001023 super.onParentChanged();
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001024 mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001025 }
1026
Craig Mautnera228ae92014-07-09 05:44:55 -07001027 // Close up recents linked list.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001028 private void closeRecentsChain() {
Craig Mautnera228ae92014-07-09 05:44:55 -07001029 if (mPrevAffiliate != null) {
1030 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
1031 }
1032 if (mNextAffiliate != null) {
1033 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
1034 }
1035 setPrevAffiliate(null);
1036 setNextAffiliate(null);
1037 }
1038
Winson Chung740c3ac2014-11-12 16:14:38 -08001039 void removedFromRecents() {
Dianne Hackborn852975d2014-08-22 17:42:43 -07001040 closeRecentsChain();
1041 if (inRecents) {
1042 inRecents = false;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001043 mAtmService.notifyTaskPersisterLocked(this, false);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001044 }
Jorim Jaggif9084ec2017-01-16 13:16:59 +01001045
Dianne Hackborn68a06332017-11-15 17:54:18 -08001046 clearRootProcess();
1047
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001048 mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
1049 mTaskId, mUserId);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001050 }
1051
Craig Mautnera228ae92014-07-09 05:44:55 -07001052 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
1053 closeRecentsChain();
1054 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
Winson Chungec396d62014-08-06 17:08:00 -07001055 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
Craig Mautnera228ae92014-07-09 05:44:55 -07001056 // Find the end
1057 while (taskToAffiliateWith.mNextAffiliate != null) {
1058 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate;
1059 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1060 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1061 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1062 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1063 nextRecents.setPrevAffiliate(null);
1064 }
1065 taskToAffiliateWith.setNextAffiliate(null);
1066 break;
1067 }
1068 taskToAffiliateWith = nextRecents;
1069 }
1070 taskToAffiliateWith.setNextAffiliate(this);
1071 setPrevAffiliate(taskToAffiliateWith);
1072 setNextAffiliate(null);
1073 }
1074
Winson Chung1147c402014-05-14 11:05:00 -07001075 /** Returns the intent for the root activity for this task */
1076 Intent getBaseIntent() {
1077 return intent != null ? intent : affinityIntent;
1078 }
1079
Andrii Kulian39f27442019-06-26 19:09:19 -07001080 /** Returns the first non-finishing activity from the bottom. */
Winson Chung3b3f4642014-04-22 10:08:18 -07001081 ActivityRecord getRootActivity() {
Andrii Kulian39f27442019-06-26 19:09:19 -07001082 final int rootActivityIndex = findRootIndex(false /* effectiveRoot */);
1083 if (rootActivityIndex == -1) {
1084 // There are no non-finishing activities in the task.
1085 return null;
Winson Chung3b3f4642014-04-22 10:08:18 -07001086 }
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001087 return getChildAt(rootActivityIndex);
Winson Chung3b3f4642014-04-22 10:08:18 -07001088 }
1089
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001090 ActivityRecord getTopActivity() {
Bryce Lee9f6affd2017-09-01 09:18:35 -07001091 return getTopActivity(true /* includeOverlays */);
1092 }
1093
1094 ActivityRecord getTopActivity(boolean includeOverlays) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001095 for (int i = getChildCount() - 1; i >= 0; --i) {
1096 final ActivityRecord r = getChildAt(i);
Bryce Lee9f6affd2017-09-01 09:18:35 -07001097 if (r.finishing || (!includeOverlays && r.mTaskOverlay)) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001098 continue;
1099 }
1100 return r;
1101 }
1102 return null;
1103 }
1104
Filip Gruszczynski3e85ba22015-10-05 22:48:30 -07001105 ActivityRecord topRunningActivityLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001106 if (mStack != null) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001107 for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
1108 ActivityRecord r = getChildAt(activityNdx);
Chong Zhang87761972016-08-22 13:53:24 -07001109 if (!r.finishing && r.okToShowLocked()) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001110 return r;
1111 }
Craig Mautner6b74cb52013-09-27 17:02:21 -07001112 }
1113 }
1114 return null;
1115 }
1116
Jorim Jaggi172e99f2017-10-20 14:33:18 +02001117 boolean isVisible() {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001118 for (int i = getChildCount() - 1; i >= 0; --i) {
1119 final ActivityRecord r = getChildAt(i);
Jorim Jaggi172e99f2017-10-20 14:33:18 +02001120 if (r.visible) {
1121 return true;
1122 }
1123 }
1124 return false;
1125 }
1126
Ricky Waib147fa12019-04-25 16:08:30 +01001127 /**
1128 * Return true if any activities in this task belongs to input uid.
1129 */
1130 boolean containsAppUid(int uid) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001131 for (int i = getChildCount() - 1; i >= 0; --i) {
1132 final ActivityRecord r = getChildAt(i);
Ricky Waib147fa12019-04-25 16:08:30 +01001133 if (r.getUid() == uid) {
1134 return true;
1135 }
1136 }
1137 return false;
1138 }
1139
Jorim Jaggiea039a82017-08-02 14:37:49 +02001140 void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
1141 if (mStack != null) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001142 for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
1143 ActivityRecord r = getChildAt(activityNdx);
Jorim Jaggi02f1d2f2017-08-04 14:29:16 +02001144 if (!r.finishing && r.okToShowLocked() && r.visibleIgnoringKeyguard) {
Jorim Jaggiea039a82017-08-02 14:37:49 +02001145 outActivities.add(r);
1146 }
1147 }
1148 }
1149 }
1150
Wale Ogunwale3b232392016-05-13 15:37:13 -07001151 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001152 if (mStack != null) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001153 for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
1154 ActivityRecord r = getChildAt(activityNdx);
Wale Ogunwale3b232392016-05-13 15:37:13 -07001155 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
Chong Zhang87761972016-08-22 13:53:24 -07001156 || r.finishing || !r.okToShowLocked()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001157 continue;
1158 }
1159 return r;
1160 }
1161 }
1162 return null;
1163 }
1164
Winson Chung61c9e5a2017-10-11 10:39:32 -07001165 /**
1166 * Return the number of running activities, and the number of non-finishing/initializing
1167 * activities in the provided {@param reportOut} respectively.
1168 */
1169 void getNumRunningActivities(TaskActivitiesReport reportOut) {
1170 reportOut.reset();
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001171 for (int i = getChildCount() - 1; i >= 0; --i) {
1172 final ActivityRecord r = getChildAt(i);
Winson Chung61c9e5a2017-10-11 10:39:32 -07001173 if (r.finishing) {
1174 continue;
1175 }
1176
1177 reportOut.base = r;
1178
1179 // Increment the total number of non-finishing activities
1180 reportOut.numActivities++;
1181
Bryce Lee7ace3952018-02-16 14:34:32 -08001182 if (reportOut.top == null || (reportOut.top.isState(ActivityState.INITIALIZING))) {
Winson Chung61c9e5a2017-10-11 10:39:32 -07001183 reportOut.top = r;
1184 // Reset the number of running activities until we hit the first non-initializing
1185 // activity
1186 reportOut.numRunning = 0;
1187 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001188 if (r.attachedToProcess()) {
Winson Chung61c9e5a2017-10-11 10:39:32 -07001189 // Increment the number of actually running activities
1190 reportOut.numRunning++;
1191 }
1192 }
1193 }
1194
Chong Zhang87761972016-08-22 13:53:24 -07001195 boolean okToShowLocked() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001196 // NOTE: If {@link TaskRecord#topRunningActivity} return is not null then it is
Chong Zhang87761972016-08-22 13:53:24 -07001197 // okay to show the activity when locked.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001198 return mAtmService.mStackSupervisor.isCurrentProfileLocked(mUserId)
Chong Zhang87761972016-08-22 13:53:24 -07001199 || topRunningActivityLocked() != null;
1200 }
1201
Craig Mautnerde4ef022013-04-07 19:01:33 -07001202 /**
Craig Mautner3b475fe2013-12-16 15:58:31 -08001203 * Reorder the history stack so that the passed activity is brought to the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001204 */
1205 final void moveActivityToFrontLocked(ActivityRecord newTop) {
Wale Ogunwale0fc365c2015-05-25 19:35:42 -07001206 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
1207 "Removing and adding activity " + newTop
1208 + " to stack at top callers=" + Debug.getCallers(4));
Craig Mautnerde4ef022013-04-07 19:01:33 -07001209
Craig Mautnerde4ef022013-04-07 19:01:33 -07001210 mActivities.remove(newTop);
1211 mActivities.add(newTop);
Bryce Leed58d7b32017-09-08 15:55:22 -07001212
1213 // Make sure window manager is aware of the position change.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001214 mTask.positionChildAtTop(newTop);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001215 updateEffectiveIntent();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001216 }
1217
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001218 void addActivityToTop(ActivityRecord r) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001219 addActivityAtIndex(getChildCount(), r);
Craig Mautner1602ec22013-05-12 10:24:27 -07001220 }
1221
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001222 @Override
Wale Ogunwaleeea34ee92017-08-31 20:07:45 -07001223 /*@WindowConfiguration.ActivityType*/
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001224 public int getActivityType() {
1225 final int applicationType = super.getActivityType();
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001226 if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001227 return applicationType;
1228 }
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001229 return getChildAt(0).getActivityType();
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001230 }
1231
Winson Chung30480042017-01-26 10:55:34 -08001232 /**
1233 * Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
1234 * be in the current task or unparented to any task.
1235 */
Craig Mautner1602ec22013-05-12 10:24:27 -07001236 void addActivityAtIndex(int index, ActivityRecord r) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001237 TaskRecord task = r.getTaskRecord();
Bryce Leeaf691c02017-03-20 14:20:22 -07001238 if (task != null && task != this) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001239 throw new IllegalArgumentException("Can not add r=" + " to task=" + this
Bryce Leeaf691c02017-03-20 14:20:22 -07001240 + " current parent=" + task);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001241 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001242
1243 r.setTask(this);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001244
Craig Mautner6170f732013-04-02 13:05:23 -07001245 // Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001246 if (!mActivities.remove(r) && r.occludesParent()) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001247 // Was not previously in list.
1248 numFullscreen++;
1249 }
Craig Mautner2c1faed2013-07-23 12:56:02 -07001250 // Only set this based on the first activity
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001251 if (!hasChild()) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001252 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1253 // Normally non-standard activity type for the activity record will be set when the
1254 // object is created, however we delay setting the standard application type until
1255 // this point so that the task can set the type for additional activities added in
1256 // the else condition below.
1257 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1258 }
1259 setActivityType(r.getActivityType());
Craig Mautner21d24a22014-04-23 11:45:37 -07001260 isPersistable = r.isPersistable();
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001261 mCallingUid = r.launchedFromUid;
1262 mCallingPackage = r.launchedFromPackage;
Dianne Hackborn852975d2014-08-22 17:42:43 -07001263 // Clamp to [1, max].
1264 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
Wale Ogunwale65ebd952018-04-25 15:41:44 -07001265 ActivityTaskManager.getMaxAppRecentsLimitStatic());
Craig Mautner2c1faed2013-07-23 12:56:02 -07001266 } else {
1267 // Otherwise make all added activities match this one.
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001268 r.setActivityType(getActivityType());
Craig Mautner78733002013-06-10 13:54:49 -07001269 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001270
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001271 final int size = getChildCount();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001272
1273 if (index == size && size > 0) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001274 final ActivityRecord top = getChildAt(size - 1);
Wale Ogunwale3b232392016-05-13 15:37:13 -07001275 if (top.mTaskOverlay) {
1276 // Place below the task overlay activity since the overlay activity should always
1277 // be on top.
1278 index--;
1279 }
1280 }
1281
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001282 index = Math.min(size, index);
Craig Mautner77878772013-03-04 19:46:24 -08001283 mActivities.add(index, r);
Bryce Lee84730a02018-04-03 14:10:04 -07001284
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001285 updateEffectiveIntent();
Craig Mautner21d24a22014-04-23 11:45:37 -07001286 if (r.isPersistable()) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001287 mAtmService.notifyTaskPersisterLocked(this, false);
Craig Mautner21d24a22014-04-23 11:45:37 -07001288 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001289
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001290 if (r.getParent() != null) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001291 // Only attempt to move in WM if the child has a controller. It is possible we haven't
1292 // created controller for the activity we are starting yet.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001293 mTask.positionChildAt(r, index);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001294 }
David Stevens82ea6cb2017-03-03 16:18:50 -08001295
1296 // Make sure the list of display UID whitelists is updated
1297 // now that this record is in a new task.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001298 mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
Craig Mautner77878772013-03-04 19:46:24 -08001299 }
1300
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001301 /**
Bryce Leeaf691c02017-03-20 14:20:22 -07001302 * Removes the specified activity from this task.
1303 * @param r The {@link ActivityRecord} to remove.
1304 * @return true if this was the last activity in the task.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001305 */
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001306 boolean removeActivity(ActivityRecord r) {
Bryce Lee84730a02018-04-03 14:10:04 -07001307 return removeActivity(r, false /* reparenting */);
Bryce Leeaf691c02017-03-20 14:20:22 -07001308 }
1309
1310 boolean removeActivity(ActivityRecord r, boolean reparenting) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001311 if (r.getTaskRecord() != this) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001312 throw new IllegalArgumentException(
1313 "Activity=" + r + " does not belong to task=" + this);
1314 }
1315
Bryce Lee84730a02018-04-03 14:10:04 -07001316 r.setTask(null /* task */, reparenting /* reparenting */);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001317
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001318 if (mActivities.remove(r) && r.occludesParent()) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001319 // Was previously in list.
1320 numFullscreen--;
1321 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001322 if (r.isPersistable()) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001323 mAtmService.notifyTaskPersisterLocked(this, false);
Craig Mautner21d24a22014-04-23 11:45:37 -07001324 }
Wale Ogunwale89182d52016-03-11 10:38:36 -08001325
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001326 if (inPinnedWindowingMode()) {
Wale Ogunwale89182d52016-03-11 10:38:36 -08001327 // We normally notify listeners of task stack changes on pause, however pinned stack
1328 // activities are normally in the paused state so no notification will be sent there
1329 // before the activity is removed. We send it here so instead.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001330 mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
Wale Ogunwale89182d52016-03-11 10:38:36 -08001331 }
1332
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001333 if (!hasChild()) {
Craig Mautner5afcd4d2014-06-21 18:11:33 -07001334 return !mReuseTask;
Craig Mautner41326202014-06-20 14:38:21 -07001335 }
1336 updateEffectiveIntent();
1337 return false;
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001338 }
1339
Winson Chung6954fc92017-03-24 16:22:12 -07001340 /**
1341 * @return whether or not there are ONLY task overlay activities in the stack.
1342 * If {@param excludeFinishing} is set, then ignore finishing activities in the check.
1343 * If there are no task overlay activities, this call returns false.
1344 */
1345 boolean onlyHasTaskOverlayActivities(boolean excludeFinishing) {
1346 int count = 0;
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001347 for (int i = getChildCount() - 1; i >= 0; i--) {
1348 final ActivityRecord r = getChildAt(i);
Winson Chung6954fc92017-03-24 16:22:12 -07001349 if (excludeFinishing && r.finishing) {
1350 continue;
1351 }
1352 if (!r.mTaskOverlay) {
1353 return false;
1354 }
1355 count++;
1356 }
1357 return count > 0;
1358 }
1359
Craig Mautner41db4a72014-05-07 17:20:56 -07001360 boolean autoRemoveFromRecents() {
Dianne Hackbornd38aed82014-06-10 21:36:35 -07001361 // We will automatically remove the task either if it has explicitly asked for
1362 // this, or it is empty and has never contained an activity that got shown to
1363 // the user.
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001364 return autoRemoveRecents || (!hasChild() && !hasBeenVisible);
Craig Mautner41db4a72014-05-07 17:20:56 -07001365 }
1366
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001367 /**
1368 * Completely remove all activities associated with an existing
1369 * task starting at a specified index.
1370 */
Louis Chang7b03ad92019-08-21 12:32:33 +08001371 final void performClearTaskAtIndexLocked(int activityNdx, String reason) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001372 int numActivities = getChildCount();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001373 for ( ; activityNdx < numActivities; ++activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001374 final ActivityRecord r = getChildAt(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001375 if (r.finishing) {
1376 continue;
1377 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001378 if (mStack == null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001379 // Task was restored from persistent storage.
1380 r.takeFromHistory();
1381 mActivities.remove(activityNdx);
1382 --activityNdx;
1383 --numActivities;
Louis Chang7b03ad92019-08-21 12:32:33 +08001384 } else if (r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
1385 false /* oomAdj */)
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001386 == FINISH_RESULT_REMOVED) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001387 --activityNdx;
1388 --numActivities;
1389 }
1390 }
1391 }
1392
1393 /**
1394 * Completely remove all activities associated with an existing task.
1395 */
Benjamin Franza83859f2017-07-03 16:34:14 +01001396 void performClearTaskLocked() {
Craig Mautner362449a2014-06-20 14:04:39 -07001397 mReuseTask = true;
Louis Chang7b03ad92019-08-21 12:32:33 +08001398 performClearTaskAtIndexLocked(0, "clear-task-all");
Craig Mautner362449a2014-06-20 14:04:39 -07001399 mReuseTask = false;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001400 }
1401
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -08001402 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1403 mReuseTask = true;
1404 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1405 mReuseTask = false;
1406 return result;
1407 }
1408
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001409 /**
1410 * Perform clear operation as requested by
1411 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1412 * stack to the given task, then look for
1413 * an instance of that activity in the stack and, if found, finish all
1414 * activities on top of it and return the instance.
1415 *
1416 * @param newR Description of the new activity being started.
1417 * @return Returns the old activity that should be continued to be used,
1418 * or null if none was found.
1419 */
1420 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001421 int numActivities = getChildCount();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001422 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001423 ActivityRecord r = getChildAt(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001424 if (r.finishing) {
1425 continue;
1426 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001427 if (r.mActivityComponent.equals(newR.mActivityComponent)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001428 // Here it is! Now finish everything in front...
Craig Mautner1602ec22013-05-12 10:24:27 -07001429 final ActivityRecord ret = r;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001430
1431 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001432 r = getChildAt(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001433 if (r.finishing) {
1434 continue;
1435 }
Jorim Jaggi346702a2019-05-08 17:49:33 +02001436 ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001437 if (opts != null) {
1438 ret.updateOptionsLocked(opts);
1439 }
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001440 if (r.finishIfPossible("clear-task-stack", false /* oomAdj */)
1441 == FINISH_RESULT_REMOVED) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001442 --activityNdx;
1443 --numActivities;
1444 }
1445 }
1446
1447 // Finally, if this is a normal launch mode (that is, not
1448 // expecting onNewIntent()), then we will finish the current
1449 // instance of the activity so a new fresh one can be started.
1450 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
Daichi Hirono15a02992016-04-27 18:47:01 +09001451 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1452 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001453 if (!ret.finishing) {
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001454 ret.finishIfPossible("clear-task-top", false /* oomAdj */);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001455 return null;
1456 }
1457 }
1458
1459 return ret;
1460 }
1461 }
1462
1463 return null;
1464 }
1465
Louis Chang7b03ad92019-08-21 12:32:33 +08001466 void removeTaskActivitiesLocked(String reason) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001467 // Just remove the entire task.
Louis Chang7b03ad92019-08-21 12:32:33 +08001468 performClearTaskAtIndexLocked(0, reason);
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001469 }
1470
Craig Mautner432f64e2015-05-20 14:59:57 -07001471 String lockTaskAuthToString() {
1472 switch (mLockTaskAuth) {
1473 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1474 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1475 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1476 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
Benjamin Franz469dd582015-06-09 14:24:36 +01001477 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
Craig Mautner432f64e2015-05-20 14:59:57 -07001478 default: return "unknown=" + mLockTaskAuth;
1479 }
1480 }
1481
Craig Mautner15df08a2015-04-01 12:17:18 -07001482 void setLockTaskAuth() {
Charles He2bf28322017-10-12 22:24:49 +01001483 setLockTaskAuth(getRootActivity());
1484 }
1485
1486 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1487 if (r == null) {
1488 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1489 return;
1490 }
1491
Charles He520b2832017-09-02 15:27:16 +01001492 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001493 final LockTaskController lockTaskController = mAtmService.getLockTaskController();
Charles He2bf28322017-10-12 22:24:49 +01001494 switch (r.lockTaskLaunchMode) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001495 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001496 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
Charles He520b2832017-09-02 15:27:16 +01001497 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001498 break;
1499
1500 case LOCK_TASK_LAUNCH_MODE_NEVER:
Benjamin Franz469dd582015-06-09 14:24:36 +01001501 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
Craig Mautner15df08a2015-04-01 12:17:18 -07001502 break;
1503
1504 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
Benjamin Franz469dd582015-06-09 14:24:36 +01001505 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
Craig Mautner15df08a2015-04-01 12:17:18 -07001506 break;
1507
1508 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001509 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
Charles He520b2832017-09-02 15:27:16 +01001510 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001511 break;
1512 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001513 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this +
1514 " mLockTaskAuth=" + lockTaskAuthToString());
Craig Mautner15df08a2015-04-01 12:17:18 -07001515 }
1516
Winson Chungd3395382016-12-13 11:49:09 -08001517 private boolean isResizeable(boolean checkSupportsPip) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001518 return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001519 || (checkSupportsPip && mSupportsPictureInPicture));
Winson Chungd3395382016-12-13 11:49:09 -08001520 }
1521
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001522 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08001523 return isResizeable(true /* checkSupportsPip */);
1524 }
1525
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001526 @Override
1527 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08001528 // A task can not be docked even if it is considered resizeable because it only supports
1529 // picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001530 return super.supportsSplitScreenWindowingMode()
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001531 && mAtmService.mSupportsSplitScreenMultiWindow
1532 && (mAtmService.mForceResizableActivities
Bryce Leec857a5b2017-08-16 10:04:52 -07001533 || (isResizeable(false /* checkSupportsPip */)
1534 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001535 }
1536
skuhne@google.com322347b2016-12-02 12:54:03 -08001537 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001538 * Check whether this task can be launched on the specified display.
Riddle Hsu16567132018-08-16 21:37:47 +08001539 *
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001540 * @param displayId Target display id.
Riddle Hsu16567132018-08-16 21:37:47 +08001541 * @return {@code true} if either it is the default display or this activity can be put on a
1542 * secondary display.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001543 */
1544 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001545 return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Riddle Hsu16567132018-08-16 21:37:47 +08001546 -1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001547 }
1548
1549 /**
skuhne@google.com322347b2016-12-02 12:54:03 -08001550 * Check that a given bounds matches the application requested orientation.
1551 *
1552 * @param bounds The bounds to be tested.
1553 * @return True if the requested bounds are okay for a resizing request.
1554 */
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001555 private boolean canResizeToBounds(Rect bounds) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001556 if (bounds == null || !inFreeformWindowingMode()) {
skuhne@google.com322347b2016-12-02 12:54:03 -08001557 // Note: If not on the freeform workspace, we ignore the bounds.
1558 return true;
1559 }
1560 final boolean landscape = bounds.width() > bounds.height();
Evan Roskydfe3da72018-10-26 17:21:06 -07001561 final Rect configBounds = getRequestedOverrideBounds();
skuhne@google.com322347b2016-12-02 12:54:03 -08001562 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001563 return configBounds.isEmpty()
1564 || landscape == (configBounds.width() > configBounds.height());
skuhne@google.com322347b2016-12-02 12:54:03 -08001565 }
1566 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1567 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1568 }
1569
Craig Mautner525f3d92013-05-07 14:01:50 -07001570 /**
Yorke Leebdef5372017-04-10 16:38:51 -07001571 * @return {@code true} if the task is being cleared for the purposes of being reused.
1572 */
1573 boolean isClearingToReuseTask() {
1574 return mReuseTask;
1575 }
1576
1577 /**
Craig Mautner525f3d92013-05-07 14:01:50 -07001578 * Find the activity in the history stack within the given task. Returns
1579 * the index within the history at which it's found, or < 0 if not found.
1580 */
1581 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001582 final ComponentName realActivity = r.mActivityComponent;
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001583 for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
1584 ActivityRecord candidate = getChildAt(activityNdx);
Craig Mautner525f3d92013-05-07 14:01:50 -07001585 if (candidate.finishing) {
1586 continue;
1587 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001588 if (candidate.mActivityComponent.equals(realActivity)) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001589 return candidate;
1590 }
1591 }
1592 return null;
1593 }
1594
Winson Chunga449dc02014-05-16 11:15:04 -07001595 /** Updates the last task description values. */
1596 void updateTaskDescription() {
Andrii Kulian39f27442019-06-26 19:09:19 -07001597 // TODO(AM refactor): Cleanup to use findRootIndex()
Winson Chunga449dc02014-05-16 11:15:04 -07001598 // Traverse upwards looking for any break between main task activities and
1599 // utility activities.
1600 int activityNdx;
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001601 final int numActivities = getChildCount();
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001602 final boolean relinquish = numActivities != 0 &&
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001603 (getChildAt(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001604 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
Craig Mautner21d24a22014-04-23 11:45:37 -07001605 ++activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001606 final ActivityRecord r = getChildAt(activityNdx);
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001607 if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001608 // This will be the top activity for determining taskDescription. Pre-inc to
1609 // overcome initial decrement below.
1610 ++activityNdx;
1611 break;
1612 }
Winson Chunga449dc02014-05-16 11:15:04 -07001613 if (r.intent != null &&
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001614 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
Winson Chunga449dc02014-05-16 11:15:04 -07001615 break;
1616 }
1617 }
1618 if (activityNdx > 0) {
1619 // Traverse downwards starting below break looking for set label, icon.
1620 // Note that if there are activities in the task but none of them set the
1621 // recent activity values, then we do not fall back to the last set
1622 // values in the TaskRecord.
1623 String label = null;
Craig Mautner648f69b2014-09-18 14:16:26 -07001624 String iconFilename = null;
Matthew Ng54bc9422017-10-02 17:16:28 -07001625 int iconResource = -1;
Winson Chunga449dc02014-05-16 11:15:04 -07001626 int colorPrimary = 0;
Winson Chung1af8eda2016-02-05 17:55:56 +00001627 int colorBackground = 0;
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001628 int statusBarColor = 0;
1629 int navigationBarColor = 0;
Adrian Roos4c864592019-04-10 14:47:57 +02001630 boolean statusBarContrastWhenTransparent = false;
1631 boolean navigationBarContrastWhenTransparent = false;
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001632 boolean topActivity = true;
Winson Chunga449dc02014-05-16 11:15:04 -07001633 for (--activityNdx; activityNdx >= 0; --activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001634 final ActivityRecord r = getChildAt(activityNdx);
Winson Chung80f80db2018-05-30 21:13:25 -07001635 if (r.mTaskOverlay) {
1636 continue;
1637 }
Winson Chunga449dc02014-05-16 11:15:04 -07001638 if (r.taskDescription != null) {
1639 if (label == null) {
1640 label = r.taskDescription.getLabel();
1641 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001642 if (iconResource == -1) {
1643 iconResource = r.taskDescription.getIconResource();
1644 }
Craig Mautner648f69b2014-09-18 14:16:26 -07001645 if (iconFilename == null) {
1646 iconFilename = r.taskDescription.getIconFilename();
Winson Chunga449dc02014-05-16 11:15:04 -07001647 }
1648 if (colorPrimary == 0) {
1649 colorPrimary = r.taskDescription.getPrimaryColor();
Winson Chunga449dc02014-05-16 11:15:04 -07001650 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001651 if (topActivity) {
Winson Chung1af8eda2016-02-05 17:55:56 +00001652 colorBackground = r.taskDescription.getBackgroundColor();
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001653 statusBarColor = r.taskDescription.getStatusBarColor();
1654 navigationBarColor = r.taskDescription.getNavigationBarColor();
Adrian Roos4c864592019-04-10 14:47:57 +02001655 statusBarContrastWhenTransparent =
1656 r.taskDescription.getEnsureStatusBarContrastWhenTransparent();
1657 navigationBarContrastWhenTransparent =
1658 r.taskDescription.getEnsureNavigationBarContrastWhenTransparent();
Winson Chung1af8eda2016-02-05 17:55:56 +00001659 }
Winson Chunga449dc02014-05-16 11:15:04 -07001660 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001661 topActivity = false;
Winson Chunga449dc02014-05-16 11:15:04 -07001662 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001663 mTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
Adrian Roos4c864592019-04-10 14:47:57 +02001664 colorPrimary, colorBackground, statusBarColor, navigationBarColor,
1665 statusBarContrastWhenTransparent, navigationBarContrastWhenTransparent);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001666 if (mTask != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001667 mTask.setTaskDescription(mTaskDescription);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001668 }
Winson Chungec396d62014-08-06 17:08:00 -07001669 // Update the task affiliation color if we are the parent of the group
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001670 if (mTaskId == mAffiliatedTaskId) {
1671 mAffiliatedTaskColor = mTaskDescription.getPrimaryColor();
Winson Chungec396d62014-08-06 17:08:00 -07001672 }
Winson Chunga449dc02014-05-16 11:15:04 -07001673 }
1674 }
1675
Andrii Kulian39f27442019-06-26 19:09:19 -07001676 /**
1677 * Find the index of the root activity in the task. It will be the first activity from the
1678 * bottom that is not finishing.
1679 *
1680 * @param effectiveRoot Flag indicating whether 'effective root' should be returned - an
1681 * activity that defines the task identity (its base intent). It's the
1682 * first one that does not have
1683 * {@link ActivityInfo#FLAG_RELINQUISH_TASK_IDENTITY}.
1684 * @return index of the 'root' or 'effective' root in the list of activities, -1 if no eligible
1685 * activity was found.
1686 */
1687 int findRootIndex(boolean effectiveRoot) {
1688 int effectiveNdx = -1;
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001689 final int topActivityNdx = getChildCount() - 1;
Dianne Hackborn39569af2014-09-23 10:56:58 -07001690 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001691 final ActivityRecord r = getChildAt(activityNdx);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001692 if (r.finishing) {
1693 continue;
1694 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001695 effectiveNdx = activityNdx;
Andrii Kulian39f27442019-06-26 19:09:19 -07001696 if (!effectiveRoot || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001697 break;
1698 }
1699 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001700 return effectiveNdx;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001701 }
1702
Andrii Kulian39f27442019-06-26 19:09:19 -07001703 // TODO (AM refactor): Invoke automatically when there is a change in children
1704 @VisibleForTesting
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001705 void updateEffectiveIntent() {
Andrii Kulian39f27442019-06-26 19:09:19 -07001706 int effectiveRootIndex = findRootIndex(true /* effectiveRoot */);
1707 if (effectiveRootIndex == -1) {
1708 // All activities in the task are either finishing or relinquish task identity.
1709 // But we still want to update the intent, so let's use the bottom activity.
1710 effectiveRootIndex = 0;
1711 }
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001712 final ActivityRecord r = getChildAt(effectiveRootIndex);
Winson Chungfee26772014-08-05 12:21:52 -07001713 setIntent(r);
Winson Chung8d9009e2017-11-16 15:43:05 -08001714
1715 // Update the task description when the activities change
1716 updateTaskDescription();
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001717 }
1718
Evan Rosky730f6e82018-12-03 17:40:11 -08001719 void adjustForMinimalTaskDimensions(Rect bounds, Rect previousBounds) {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001720 if (bounds == null) {
1721 return;
1722 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001723 int minWidth = mMinWidth;
1724 int minHeight = mMinHeight;
Robert Carr9c5867d2016-03-10 15:52:46 -08001725 // If the task has no requested minimal size, we'd like to enforce a minimal size
1726 // so that the user can not render the task too small to manipulate. We don't need
1727 // to do this for the pinned stack as the bounds are controlled by the system.
Evan Rosky1ac84462018-11-13 11:25:30 -08001728 if (!inPinnedWindowingMode() && mStack != null) {
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001729 final int defaultMinSizeDp =
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001730 mAtmService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp;
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001731 final ActivityDisplay display =
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001732 mAtmService.mRootActivityContainer.getActivityDisplay(mStack.mDisplayId);
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001733 final float density =
1734 (float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
1735 final int defaultMinSize = (int) (defaultMinSizeDp * density);
1736
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001737 if (minWidth == INVALID_MIN_SIZE) {
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001738 minWidth = defaultMinSize;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001739 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001740 if (minHeight == INVALID_MIN_SIZE) {
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001741 minHeight = defaultMinSize;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001742 }
Robert Carr9c5867d2016-03-10 15:52:46 -08001743 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001744 final boolean adjustWidth = minWidth > bounds.width();
1745 final boolean adjustHeight = minHeight > bounds.height();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001746 if (!(adjustWidth || adjustHeight)) {
1747 return;
1748 }
1749
1750 if (adjustWidth) {
Garfield Tan020607d2018-12-17 17:01:58 -08001751 if (!previousBounds.isEmpty() && bounds.right == previousBounds.right) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001752 bounds.left = bounds.right - minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001753 } else {
1754 // Either left bounds match, or neither match, or the previous bounds were
1755 // fullscreen and we default to keeping left.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001756 bounds.right = bounds.left + minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001757 }
1758 }
1759 if (adjustHeight) {
Garfield Tan020607d2018-12-17 17:01:58 -08001760 if (!previousBounds.isEmpty() && bounds.bottom == previousBounds.bottom) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001761 bounds.top = bounds.bottom - minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001762 } else {
1763 // Either top bounds match, or neither match, or the previous bounds were
1764 // fullscreen and we default to keeping top.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001765 bounds.bottom = bounds.top + minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001766 }
1767 }
1768 }
1769
Evan Rosky9ba524e2018-01-03 16:27:56 -08001770 void setLastNonFullscreenBounds(Rect bounds) {
1771 if (mLastNonFullscreenBounds == null) {
1772 mLastNonFullscreenBounds = new Rect(bounds);
1773 } else {
1774 mLastNonFullscreenBounds.set(bounds);
1775 }
1776 }
1777
Jorim Jaggi0a932142016-02-01 17:42:25 -08001778 /**
Bryce Leec4ab62a2018-03-05 14:19:26 -08001779 * This should be called when an child activity changes state. This should only
1780 * be called from
1781 * {@link ActivityRecord#setState(ActivityState, String)} .
1782 * @param record The {@link ActivityRecord} whose state has changed.
1783 * @param state The new state.
1784 * @param reason The reason for the change.
1785 */
1786 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
1787 final ActivityStack parent = getStack();
1788
1789 if (parent != null) {
1790 parent.onActivityStateChanged(record, state, reason);
1791 }
1792 }
1793
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001794 @Override
1795 public void onConfigurationChanged(Configuration newParentConfig) {
Evan Rosky730f6e82018-12-03 17:40:11 -08001796 // Check if the new configuration supports persistent bounds (eg. is Freeform) and if so
1797 // restore the last recorded non-fullscreen bounds.
1798 final boolean prevPersistTaskBounds = getWindowConfiguration().persistTaskBounds();
1799 final boolean nextPersistTaskBounds =
1800 getRequestedOverrideConfiguration().windowConfiguration.persistTaskBounds()
1801 || newParentConfig.windowConfiguration.persistTaskBounds();
1802 if (!prevPersistTaskBounds && nextPersistTaskBounds
1803 && mLastNonFullscreenBounds != null && !mLastNonFullscreenBounds.isEmpty()) {
1804 // Bypass onRequestedOverrideConfigurationChanged here to avoid infinite loop.
1805 getRequestedOverrideConfiguration().windowConfiguration
1806 .setBounds(mLastNonFullscreenBounds);
1807 }
1808
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001809 final boolean wasInMultiWindowMode = inMultiWindowMode();
1810 super.onConfigurationChanged(newParentConfig);
1811 if (wasInMultiWindowMode != inMultiWindowMode()) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001812 mAtmService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001813 }
Evan Rosky730f6e82018-12-03 17:40:11 -08001814
1815 // If the configuration supports persistent bounds (eg. Freeform), keep track of the
1816 // current (non-fullscreen) bounds for persistence.
Evan Rosky1ac84462018-11-13 11:25:30 -08001817 if (getWindowConfiguration().persistTaskBounds()) {
1818 final Rect currentBounds = getRequestedOverrideBounds();
1819 if (!currentBounds.isEmpty()) {
1820 setLastNonFullscreenBounds(currentBounds);
1821 }
1822 }
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001823 // TODO: Should also take care of Pip mode changes here.
Garfield Tan891146c2018-10-09 12:14:00 -07001824
1825 saveLaunchingStateIfNeeded();
1826 }
1827
1828 /**
1829 * Saves launching state if necessary so that we can launch the activity to its latest state.
1830 * It only saves state if this task has been shown to user and it's in fullscreen or freeform
Garfield Tan3129b852019-06-24 16:51:20 -07001831 * mode on freeform displays.
Garfield Tan891146c2018-10-09 12:14:00 -07001832 */
1833 void saveLaunchingStateIfNeeded() {
1834 if (!hasBeenVisible) {
1835 // Not ever visible to user.
1836 return;
1837 }
1838
1839 final int windowingMode = getWindowingMode();
Garfield Tan3129b852019-06-24 16:51:20 -07001840 if (windowingMode != WINDOWING_MODE_FULLSCREEN
1841 && windowingMode != WINDOWING_MODE_FREEFORM) {
1842 return;
1843 }
1844
1845 // Don't persist state if display isn't in freeform mode. Then the task will be launched
1846 // back to its last state in a freeform display when it's launched in a freeform display
1847 // next time.
1848 if (getWindowConfiguration().getDisplayWindowingMode() != WINDOWING_MODE_FREEFORM) {
Garfield Tan891146c2018-10-09 12:14:00 -07001849 return;
1850 }
1851
1852 // Saves the new state so that we can launch the activity at the same location.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001853 mAtmService.mStackSupervisor.mLaunchParamsPersister.saveTask(this);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001854 }
1855
Evan Roskyed6767f2018-10-26 17:21:06 -07001856 /**
Evan Rosky1ac84462018-11-13 11:25:30 -08001857 * Adjust bounds to stay within stack bounds.
1858 *
1859 * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
1860 * that keep them unchanged, but be contained within the stack bounds.
1861 *
1862 * @param bounds Bounds to be adjusted.
1863 * @param stackBounds Bounds within which the other bounds should remain.
Evan Rosky60dba2f2019-02-01 10:58:38 -08001864 * @param overlapPxX The amount of px required to be visible in the X dimension.
1865 * @param overlapPxY The amount of px required to be visible in the Y dimension.
Evan Rosky1ac84462018-11-13 11:25:30 -08001866 */
Evan Rosky60dba2f2019-02-01 10:58:38 -08001867 private static void fitWithinBounds(Rect bounds, Rect stackBounds, int overlapPxX,
1868 int overlapPxY) {
Evan Rosky1ac84462018-11-13 11:25:30 -08001869 if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
1870 return;
1871 }
1872
Evan Rosky60dba2f2019-02-01 10:58:38 -08001873 // For each side of the parent (eg. left), check if the opposing side of the window (eg.
1874 // right) is at least overlap pixels away. If less, offset the window by that difference.
1875 int horizontalDiff = 0;
1876 // If window is smaller than overlap, use it's smallest dimension instead
1877 int overlapLR = Math.min(overlapPxX, bounds.width());
1878 if (bounds.right < (stackBounds.left + overlapLR)) {
1879 horizontalDiff = overlapLR - (bounds.right - stackBounds.left);
1880 } else if (bounds.left > (stackBounds.right - overlapLR)) {
1881 horizontalDiff = -(overlapLR - (stackBounds.right - bounds.left));
Evan Rosky1ac84462018-11-13 11:25:30 -08001882 }
Evan Rosky60dba2f2019-02-01 10:58:38 -08001883 int verticalDiff = 0;
1884 int overlapTB = Math.min(overlapPxY, bounds.width());
1885 if (bounds.bottom < (stackBounds.top + overlapTB)) {
1886 verticalDiff = overlapTB - (bounds.bottom - stackBounds.top);
1887 } else if (bounds.top > (stackBounds.bottom - overlapTB)) {
1888 verticalDiff = -(overlapTB - (stackBounds.bottom - bounds.top));
Evan Rosky1ac84462018-11-13 11:25:30 -08001889 }
Evan Rosky60dba2f2019-02-01 10:58:38 -08001890 bounds.offset(horizontalDiff, verticalDiff);
Evan Rosky1ac84462018-11-13 11:25:30 -08001891 }
1892
1893 /**
Evan Roskyed6767f2018-10-26 17:21:06 -07001894 * Displayed bounds are used to set where the task is drawn at any given time. This is
1895 * separate from its actual bounds so that the app doesn't see any meaningful configuration
1896 * changes during transitionary periods.
1897 */
1898 void setDisplayedBounds(Rect bounds) {
1899 if (bounds == null) {
1900 mDisplayedBounds.setEmpty();
1901 } else {
1902 mDisplayedBounds.set(bounds);
1903 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001904 if (mTask != null) {
1905 mTask.setOverrideDisplayedBounds(
Evan Roskyed6767f2018-10-26 17:21:06 -07001906 mDisplayedBounds.isEmpty() ? null : mDisplayedBounds);
1907 }
1908 }
1909
1910 /**
1911 * Gets the current overridden displayed bounds. These will be empty if the task is not
1912 * currently overriding where it is displayed.
1913 */
1914 Rect getDisplayedBounds() {
1915 return mDisplayedBounds;
1916 }
1917
1918 /**
1919 * @return {@code true} if this has overridden displayed bounds.
1920 */
1921 boolean hasDisplayedBounds() {
1922 return !mDisplayedBounds.isEmpty();
1923 }
1924
Evan Rosky1ac84462018-11-13 11:25:30 -08001925 /**
1926 * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
1927 * intersectBounds on a side, then the respective side will not be intersected.
1928 *
1929 * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
1930 * inset on that side is no-longer applicable. This scenario happens when a task's minimal
1931 * bounds are larger than the provided parent/display bounds.
1932 *
1933 * @param inOutBounds the bounds to intersect.
1934 * @param intersectBounds the bounds to intersect with.
1935 * @param intersectInsets insets to apply to intersectBounds before intersecting.
1936 */
Riddle Hsu74826262019-04-17 14:57:42 +08001937 static void intersectWithInsetsIfFits(
Evan Rosky1ac84462018-11-13 11:25:30 -08001938 Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
1939 if (inOutBounds.right <= intersectBounds.right) {
1940 inOutBounds.right =
1941 Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
1942 }
1943 if (inOutBounds.bottom <= intersectBounds.bottom) {
1944 inOutBounds.bottom =
1945 Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
1946 }
1947 if (inOutBounds.left >= intersectBounds.left) {
1948 inOutBounds.left =
1949 Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
1950 }
1951 if (inOutBounds.top >= intersectBounds.top) {
1952 inOutBounds.top =
1953 Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
1954 }
1955 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001956
Evan Rosky1ac84462018-11-13 11:25:30 -08001957 /**
1958 * Gets bounds with non-decor and stable insets applied respectively.
1959 *
1960 * If bounds overhangs the display, those edges will not get insets. See
1961 * {@link #intersectWithInsetsIfFits}
1962 *
1963 * @param outNonDecorBounds where to place bounds with non-decor insets applied.
1964 * @param outStableBounds where to place bounds with stable insets applied.
1965 * @param bounds the bounds to inset.
1966 */
1967 private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
1968 DisplayInfo displayInfo) {
1969 outNonDecorBounds.set(bounds);
1970 outStableBounds.set(bounds);
1971 if (getStack() == null || getStack().getDisplay() == null) {
1972 return;
1973 }
1974 DisplayPolicy policy = getStack().getDisplay().mDisplayContent.getDisplayPolicy();
1975 if (policy == null) {
1976 return;
1977 }
1978 mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
Bryce Lee7566d762017-03-30 09:34:15 -07001979
Riddle Hsu61987bc2019-04-03 13:08:47 +08001980 policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
1981 displayInfo.logicalHeight, displayInfo.displayCutout, mTmpInsets);
Evan Rosky1ac84462018-11-13 11:25:30 -08001982 intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);
Riddle Hsu61987bc2019-04-03 13:08:47 +08001983
1984 policy.convertNonDecorInsetsToStableInsets(mTmpInsets, displayInfo.rotation);
1985 intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
Evan Rosky1ac84462018-11-13 11:25:30 -08001986 }
1987
1988 /**
1989 * Asks docked-divider controller for the smallestwidthdp given bounds.
1990 * @param bounds bounds to calculate smallestwidthdp for.
1991 */
1992 private int getSmallestScreenWidthDpForDockedBounds(Rect bounds) {
1993 DisplayContent dc = mStack.getDisplay().mDisplayContent;
1994 if (dc != null) {
1995 return dc.getDockedDividerController().getSmallestWidthDpForBounds(bounds);
1996 }
1997 return Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
1998 }
1999
Riddle Hsu0a343c32018-12-21 00:40:48 +08002000 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
2001 @NonNull Configuration parentConfig) {
Riddle Hsu61987bc2019-04-03 13:08:47 +08002002 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* compatInsets */);
Riddle Hsu0a343c32018-12-21 00:40:48 +08002003 }
2004
Evan Rosky1ac84462018-11-13 11:25:30 -08002005 /**
2006 * Calculates configuration values used by the client to get resources. This should be run
2007 * using app-facing bounds (bounds unmodified by animations or transient interactions).
2008 *
2009 * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
2010 * configuring an "inherit-bounds" window which means that all configuration settings would
2011 * just be inherited from the parent configuration.
2012 **/
Evan Rosky730f6e82018-12-03 17:40:11 -08002013 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Riddle Hsu61987bc2019-04-03 13:08:47 +08002014 @NonNull Configuration parentConfig,
2015 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
Evan Rosky1ac84462018-11-13 11:25:30 -08002016 int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
2017 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2018 windowingMode = parentConfig.windowConfiguration.getWindowingMode();
Winson Chungbdc646f2017-02-13 12:12:22 -08002019 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002020
Evan Rosky1ac84462018-11-13 11:25:30 -08002021 float density = inOutConfig.densityDpi;
2022 if (density == Configuration.DENSITY_DPI_UNDEFINED) {
2023 density = parentConfig.densityDpi;
2024 }
2025 density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
Winson Chung60c1aba2017-03-14 17:47:42 -07002026
Evan Rosky730f6e82018-12-03 17:40:11 -08002027 final Rect bounds = inOutConfig.windowConfiguration.getBounds();
Evan Rosky1ac84462018-11-13 11:25:30 -08002028 Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2029 if (outAppBounds == null || outAppBounds.isEmpty()) {
2030 inOutConfig.windowConfiguration.setAppBounds(bounds);
2031 outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2032 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08002033 // Non-null compatibility insets means the activity prefers to keep its original size, so
2034 // the out bounds doesn't need to be restricted by the parent.
2035 final boolean insideParentBounds = compatInsets == null;
Riddle Hsu0a343c32018-12-21 00:40:48 +08002036 if (insideParentBounds && windowingMode != WINDOWING_MODE_FREEFORM) {
Evan Rosky1ac84462018-11-13 11:25:30 -08002037 final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
2038 if (parentAppBounds != null && !parentAppBounds.isEmpty()) {
2039 outAppBounds.intersect(parentAppBounds);
2040 }
2041 }
2042
2043 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
2044 || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
Riddle Hsu0a343c32018-12-21 00:40:48 +08002045 if (insideParentBounds && mStack != null) {
Evan Rosky1ac84462018-11-13 11:25:30 -08002046 final DisplayInfo di = new DisplayInfo();
2047 mStack.getDisplay().mDisplay.getDisplayInfo(di);
2048
2049 // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
2050 // area, i.e. the screen area without the system bars.
2051 // The non decor inset are areas that could never be removed in Honeycomb. See
2052 // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
2053 calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, bounds, di);
2054 } else {
Riddle Hsu61987bc2019-04-03 13:08:47 +08002055 // Apply the given non-decor and stable insets to calculate the corresponding bounds
2056 // for screen size of configuration.
Evan Rosky72f084d2019-09-11 17:05:16 -07002057 int rotation = inOutConfig.windowConfiguration.getRotation();
2058 if (rotation == ROTATION_UNDEFINED) {
2059 rotation = parentConfig.windowConfiguration.getRotation();
2060 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08002061 if (rotation != ROTATION_UNDEFINED && compatInsets != null) {
Riddle Hsu74826262019-04-17 14:57:42 +08002062 mTmpNonDecorBounds.set(bounds);
2063 mTmpStableBounds.set(bounds);
2064 compatInsets.getDisplayBoundsByRotation(mTmpBounds, rotation);
Riddle Hsu61987bc2019-04-03 13:08:47 +08002065 intersectWithInsetsIfFits(mTmpNonDecorBounds, mTmpBounds,
2066 compatInsets.mNonDecorInsets[rotation]);
2067 intersectWithInsetsIfFits(mTmpStableBounds, mTmpBounds,
2068 compatInsets.mStableInsets[rotation]);
Riddle Hsu74826262019-04-17 14:57:42 +08002069 outAppBounds.set(mTmpNonDecorBounds);
2070 } else {
2071 // Set to app bounds because it excludes decor insets.
2072 mTmpNonDecorBounds.set(outAppBounds);
2073 mTmpStableBounds.set(outAppBounds);
Riddle Hsu61987bc2019-04-03 13:08:47 +08002074 }
Evan Rosky1ac84462018-11-13 11:25:30 -08002075 }
2076
2077 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
Riddle Hsu0a343c32018-12-21 00:40:48 +08002078 final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density);
2079 inOutConfig.screenWidthDp = insideParentBounds
2080 ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
2081 : overrideScreenWidthDp;
Evan Rosky1ac84462018-11-13 11:25:30 -08002082 }
2083 if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
Riddle Hsu0a343c32018-12-21 00:40:48 +08002084 final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
2085 inOutConfig.screenHeightDp = insideParentBounds
Riddle Hsu88e3c8732019-02-18 19:15:12 +08002086 ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
Riddle Hsu0a343c32018-12-21 00:40:48 +08002087 : overrideScreenHeightDp;
Evan Rosky1ac84462018-11-13 11:25:30 -08002088 }
2089
2090 if (inOutConfig.smallestScreenWidthDp
2091 == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2092 if (WindowConfiguration.isFloating(windowingMode)) {
2093 // For floating tasks, calculate the smallest width from the bounds of the task
2094 inOutConfig.smallestScreenWidthDp = (int) (
2095 Math.min(bounds.width(), bounds.height()) / density);
2096 } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
2097 // Iterating across all screen orientations, and return the minimum of the task
2098 // width taking into account that the bounds might change because the snap
2099 // algorithm snaps to a different value
Evan Rosky730f6e82018-12-03 17:40:11 -08002100 inOutConfig.smallestScreenWidthDp =
2101 getSmallestScreenWidthDpForDockedBounds(bounds);
Evan Rosky1ac84462018-11-13 11:25:30 -08002102 }
2103 // otherwise, it will just inherit
2104 }
2105 }
2106
Evan Rosky730f6e82018-12-03 17:40:11 -08002107 if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
Evan Rosky1ac84462018-11-13 11:25:30 -08002108 inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
Riddle Hsu0a343c32018-12-21 00:40:48 +08002109 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
Evan Rosky1ac84462018-11-13 11:25:30 -08002110 }
2111 if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
2112 // For calculating screen layout, we need to use the non-decor inset screen area for the
2113 // calculation for compatibility reasons, i.e. screen area without system bars that
2114 // could never go away in Honeycomb.
2115 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
2116 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
2117 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start
2118 // override calculation with partial default.
2119 // Reducing the screen layout starting from its parent config.
2120 final int sl = parentConfig.screenLayout
2121 & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
2122 final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
2123 final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
2124 inOutConfig.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
2125 }
2126 }
2127
Evan Rosky1ac84462018-11-13 11:25:30 -08002128 @Override
2129 void resolveOverrideConfiguration(Configuration newParentConfig) {
Evan Rosky730f6e82018-12-03 17:40:11 -08002130 mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
2131 super.resolveOverrideConfiguration(newParentConfig);
2132 int windowingMode =
2133 getRequestedOverrideConfiguration().windowConfiguration.getWindowingMode();
2134 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2135 windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
2136 }
2137 Rect outOverrideBounds =
2138 getResolvedOverrideConfiguration().windowConfiguration.getBounds();
2139
2140 if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
Riddle Hsu74826262019-04-17 14:57:42 +08002141 computeFullscreenBounds(outOverrideBounds, null /* refActivity */,
2142 newParentConfig.windowConfiguration.getBounds(),
2143 newParentConfig.orientation);
Evan Rosky730f6e82018-12-03 17:40:11 -08002144 }
2145
2146 if (outOverrideBounds.isEmpty()) {
2147 // If the task fills the parent, just inherit all the other configs from parent.
2148 return;
2149 }
2150
2151 adjustForMinimalTaskDimensions(outOverrideBounds, mTmpBounds);
2152 if (windowingMode == WINDOWING_MODE_FREEFORM) {
2153 // by policy, make sure the window remains within parent somewhere
Evan Rosky60dba2f2019-02-01 10:58:38 -08002154 final float density =
2155 ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;
GyeHun Jeon84b30d22019-04-24 14:20:15 -07002156 final Rect parentBounds =
2157 new Rect(newParentConfig.windowConfiguration.getBounds());
2158 final ActivityDisplay display = mStack.getDisplay();
2159 if (display != null && display.mDisplayContent != null) {
2160 // If a freeform window moves below system bar, there is no way to move it again
2161 // by touch. Because its caption is covered by system bar. So we exclude them
2162 // from stack bounds. and then caption will be shown inside stable area.
2163 final Rect stableBounds = new Rect();
2164 display.mDisplayContent.getStableRect(stableBounds);
2165 parentBounds.intersect(stableBounds);
2166 }
2167
2168 fitWithinBounds(outOverrideBounds, parentBounds,
Evan Rosky60dba2f2019-02-01 10:58:38 -08002169 (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP),
2170 (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP));
GyeHun Jeon84b30d22019-04-24 14:20:15 -07002171
2172 // Prevent to overlap caption with stable insets.
2173 final int offsetTop = parentBounds.top - outOverrideBounds.top;
2174 if (offsetTop > 0) {
2175 outOverrideBounds.offset(0, offsetTop);
2176 }
Evan Rosky730f6e82018-12-03 17:40:11 -08002177 }
2178 computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08002179 }
2180
Riddle Hsu74826262019-04-17 14:57:42 +08002181 /** @see WindowContainer#handlesOrientationChangeFromDescendant */
2182 boolean handlesOrientationChangeFromDescendant() {
2183 return mTask != null && mTask.getParent() != null
2184 && mTask.getParent().handlesOrientationChangeFromDescendant();
2185 }
2186
2187 /**
2188 * Compute bounds (letterbox or pillarbox) for {@link #WINDOWING_MODE_FULLSCREEN} when the
2189 * parent doesn't handle the orientation change and the requested orientation is different from
2190 * the parent.
2191 */
2192 void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
2193 @NonNull Rect parentBounds, int parentOrientation) {
2194 // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
2195 outBounds.setEmpty();
2196 if (handlesOrientationChangeFromDescendant()) {
2197 return;
2198 }
2199 if (refActivity == null) {
2200 // Use the top activity as the reference of orientation. Don't include overlays because
2201 // it is usually not the actual content or just temporarily shown.
2202 // E.g. ForcedResizableInfoActivity.
2203 refActivity = getTopActivity(false /* includeOverlays */);
2204 }
2205
2206 // If the task or the reference activity requires a different orientation (either by
2207 // override or activityInfo), make it fit the available bounds by scaling down its bounds.
2208 final int overrideOrientation = getRequestedOverrideConfiguration().orientation;
2209 final int forcedOrientation =
2210 (overrideOrientation != ORIENTATION_UNDEFINED || refActivity == null)
2211 ? overrideOrientation : refActivity.getRequestedConfigurationOrientation();
2212 if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
2213 return;
2214 }
2215
2216 final int parentWidth = parentBounds.width();
2217 final int parentHeight = parentBounds.height();
2218 final float aspect = ((float) parentHeight) / parentWidth;
2219 if (forcedOrientation == ORIENTATION_LANDSCAPE) {
2220 final int height = (int) (parentWidth / aspect);
2221 final int top = parentBounds.centerY() - height / 2;
2222 outBounds.set(parentBounds.left, top, parentBounds.right, top + height);
2223 } else {
2224 final int width = (int) (parentHeight * aspect);
2225 final int left = parentBounds.centerX() - width / 2;
2226 outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
2227 }
2228 }
2229
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002230 Rect updateOverrideConfigurationFromLaunchBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08002231 final Rect bounds = getLaunchBounds();
Evan Roskya4cc3a92019-06-28 13:25:01 -07002232 setBounds(bounds);
Bryce Leef3c6a472017-11-14 14:53:06 -08002233 if (bounds != null && !bounds.isEmpty()) {
2234 // TODO: Review if we actually want to do this - we are setting the launch bounds
2235 // directly here.
Evan Roskydfe3da72018-10-26 17:21:06 -07002236 bounds.set(getRequestedOverrideBounds());
Andrii Kulian73336d812016-03-24 12:56:08 -07002237 }
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002238 return bounds;
2239 }
2240
Wale Ogunwale935e5022015-11-10 12:36:10 -08002241 /** Updates the task's bounds and override configuration to match what is expected for the
2242 * input stack. */
2243 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002244 if (mStack != null && mStack == inStack) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002245 return;
2246 }
2247
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002248 if (inStack.inFreeformWindowingMode()) {
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002249 if (!isResizeable()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002250 throw new IllegalArgumentException("Can not position non-resizeable task="
2251 + this + " in stack=" + inStack);
2252 }
Bryce Leef3c6a472017-11-14 14:53:06 -08002253 if (!matchParentBounds()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002254 return;
2255 }
2256 if (mLastNonFullscreenBounds != null) {
Evan Roskya4cc3a92019-06-28 13:25:01 -07002257 setBounds(mLastNonFullscreenBounds);
Wale Ogunwale935e5022015-11-10 12:36:10 -08002258 } else {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002259 mAtmService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Wale Ogunwale935e5022015-11-10 12:36:10 -08002260 }
2261 } else {
Evan Roskya4cc3a92019-06-28 13:25:01 -07002262 setBounds(inStack.getRequestedOverrideBounds());
Wale Ogunwale935e5022015-11-10 12:36:10 -08002263 }
2264 }
2265
Wale Ogunwale706ed792015-08-02 10:29:44 -07002266 /** Returns the bounds that should be used to launch this task. */
Wale Ogunwale30e441d2017-11-09 08:28:45 -08002267 Rect getLaunchBounds() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002268 if (mStack == null) {
Chong Zhang7d5f5102016-01-13 10:29:24 -08002269 return null;
2270 }
2271
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002272 final int windowingMode = getWindowingMode();
2273 if (!isActivityTypeStandardOrUndefined()
2274 || windowingMode == WINDOWING_MODE_FULLSCREEN
2275 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Evan Roskydfe3da72018-10-26 17:21:06 -07002276 return isResizeable() ? mStack.getRequestedOverrideBounds() : null;
Wale Ogunwale3382ab12017-07-27 08:55:03 -07002277 } else if (!getWindowConfiguration().persistTaskBounds()) {
Evan Roskydfe3da72018-10-26 17:21:06 -07002278 return mStack.getRequestedOverrideBounds();
Wale Ogunwale706ed792015-08-02 10:29:44 -07002279 }
2280 return mLastNonFullscreenBounds;
2281 }
2282
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01002283 void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002284 for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
2285 final ActivityRecord r = getChildAt(activityNdx);
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01002286 if (r.visible) {
2287 r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
2288 }
2289 }
2290 }
2291
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07002292 void setRootProcess(WindowProcessController proc) {
Dianne Hackborn68a06332017-11-15 17:54:18 -08002293 clearRootProcess();
2294 if (intent != null &&
2295 (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
2296 mRootProcess = proc;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07002297 mRootProcess.addRecentTask(this);
Dianne Hackborn68a06332017-11-15 17:54:18 -08002298 }
2299 }
2300
2301 void clearRootProcess() {
2302 if (mRootProcess != null) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07002303 mRootProcess.removeRecentTask(this);
Dianne Hackborn68a06332017-11-15 17:54:18 -08002304 mRootProcess = null;
2305 }
2306 }
2307
chaviw82a0ba82018-03-15 14:26:29 -07002308 void clearAllPendingOptions() {
2309 for (int i = getChildCount() - 1; i >= 0; i--) {
2310 getChildAt(i).clearOptionsLocked(false /* withAbort */);
2311 }
2312 }
2313
Winson Chungabfdcce2018-07-02 17:23:33 -07002314 /**
2315 * Fills in a {@link TaskInfo} with information from this task.
2316 * @param info the {@link TaskInfo} to fill in
Winson Chungabfdcce2018-07-02 17:23:33 -07002317 */
Mark Renoufc808f062019-02-07 15:20:37 -05002318 void fillTaskInfo(TaskInfo info) {
2319 getNumRunningActivities(mReuseActivitiesReport);
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002320 info.userId = mUserId;
Winson Chungabfdcce2018-07-02 17:23:33 -07002321 info.stackId = getStackId();
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002322 info.taskId = mTaskId;
Mark Renoufb1abb552019-02-08 13:51:41 -05002323 info.displayId = mStack == null ? Display.INVALID_DISPLAY : mStack.mDisplayId;
Winson Chungabfdcce2018-07-02 17:23:33 -07002324 info.isRunning = getTopActivity() != null;
Riddle Hsu2f9acd22018-11-06 23:44:43 +08002325 info.baseIntent = new Intent(getBaseIntent());
Mark Renoufc808f062019-02-07 15:20:37 -05002326 info.baseActivity = mReuseActivitiesReport.base != null
2327 ? mReuseActivitiesReport.base.intent.getComponent()
Winson Chungabfdcce2018-07-02 17:23:33 -07002328 : null;
Mark Renoufc808f062019-02-07 15:20:37 -05002329 info.topActivity = mReuseActivitiesReport.top != null
2330 ? mReuseActivitiesReport.top.mActivityComponent
Winson Chungabfdcce2018-07-02 17:23:33 -07002331 : null;
2332 info.origActivity = origActivity;
2333 info.realActivity = realActivity;
Mark Renoufc808f062019-02-07 15:20:37 -05002334 info.numActivities = mReuseActivitiesReport.numActivities;
Winson Chungabfdcce2018-07-02 17:23:33 -07002335 info.lastActiveTime = lastActiveTime;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002336 info.taskDescription = new ActivityManager.TaskDescription(mTaskDescription);
Winson Chungabfdcce2018-07-02 17:23:33 -07002337 info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
2338 info.resizeMode = mResizeMode;
2339 info.configuration.setTo(getConfiguration());
2340 }
2341
Mark Renoufc808f062019-02-07 15:20:37 -05002342 /**
2343 * Returns a {@link TaskInfo} with information from this task.
2344 */
2345 ActivityManager.RunningTaskInfo getTaskInfo() {
2346 ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
2347 fillTaskInfo(info);
2348 return info;
2349 }
2350
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002351 void dump(PrintWriter pw, String prefix) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002352 pw.print(prefix); pw.print("userId="); pw.print(mUserId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07002353 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
2354 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
Suprabh Shukla7745c142016-03-07 18:21:10 -08002355 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002356 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
Dianne Hackborn79228822014-09-16 11:11:23 -07002357 if (affinity != null || rootAffinity != null) {
2358 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
2359 if (affinity == null || !affinity.equals(rootAffinity)) {
2360 pw.print(" root="); pw.println(rootAffinity);
2361 } else {
2362 pw.println();
2363 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002364 }
Dianne Hackborn91097de2014-04-04 18:02:06 -07002365 if (voiceSession != null || voiceInteractor != null) {
2366 pw.print(prefix); pw.print("VOICE: session=0x");
2367 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
2368 pw.print(" interactor=0x");
2369 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
2370 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002371 if (intent != null) {
2372 StringBuilder sb = new StringBuilder(128);
2373 sb.append(prefix); sb.append("intent={");
Hui Yu6d5c3b92019-10-22 15:35:53 -07002374 intent.toShortString(sb, false, true, false, false);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002375 sb.append('}');
2376 pw.println(sb.toString());
2377 }
2378 if (affinityIntent != null) {
2379 StringBuilder sb = new StringBuilder(128);
2380 sb.append(prefix); sb.append("affinityIntent={");
Hui Yu6d5c3b92019-10-22 15:35:53 -07002381 affinityIntent.toShortString(sb, false, true, false, false);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002382 sb.append('}');
2383 pw.println(sb.toString());
2384 }
2385 if (origActivity != null) {
2386 pw.print(prefix); pw.print("origActivity=");
2387 pw.println(origActivity.flattenToShortString());
2388 }
2389 if (realActivity != null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002390 pw.print(prefix); pw.print("mActivityComponent=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002391 pw.println(realActivity.flattenToShortString());
2392 }
Wale Ogunwale66e16852017-10-19 13:35:52 -07002393 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard() || numFullscreen != 0) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002394 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002395 pw.print(" isPersistable="); pw.print(isPersistable);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002396 pw.print(" numFullscreen="); pw.print(numFullscreen);
Wale Ogunwale66e16852017-10-19 13:35:52 -07002397 pw.print(" activityType="); pw.println(getActivityType());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002398 }
Craig Mautner432f64e2015-05-20 14:59:57 -07002399 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
2400 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002401 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
2402 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
Craig Mautner432f64e2015-05-20 14:59:57 -07002403 pw.print(" mReuseTask="); pw.print(mReuseTask);
2404 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002405 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002406 if (mAffiliatedTaskId != mTaskId || mPrevAffiliateTaskId != INVALID_TASK_ID
Wale Ogunwale18795a22014-12-03 11:38:33 -08002407 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
2408 || mNextAffiliate != null) {
Dianne Hackborn852975d2014-08-22 17:42:43 -07002409 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
2410 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
2411 pw.print(" (");
2412 if (mPrevAffiliate == null) {
2413 pw.print("null");
2414 } else {
2415 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
2416 }
2417 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
2418 pw.print(" (");
2419 if (mNextAffiliate == null) {
2420 pw.print("null");
2421 } else {
2422 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
2423 }
2424 pw.println(")");
2425 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002426 pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002427 if (!askedCompatMode || !inRecents || !isAvailable) {
2428 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
2429 pw.print(" inRecents="); pw.print(inRecents);
2430 pw.print(" isAvailable="); pw.println(isAvailable);
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002431 }
Dianne Hackborn852975d2014-08-22 17:42:43 -07002432 if (lastDescription != null) {
2433 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
2434 }
Dianne Hackborn68a06332017-11-15 17:54:18 -08002435 if (mRootProcess != null) {
2436 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
2437 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002438 pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002439 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
2440 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08002441 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002442 pw.print(" isResizeable=" + isResizeable());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002443 pw.print(" lastActiveTime=" + lastActiveTime);
2444 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002445 }
2446
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002447 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002448 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002449 StringBuilder sb = new StringBuilder(128);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002450 if (stringName != null) {
2451 sb.append(stringName);
2452 sb.append(" U=");
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002453 sb.append(mUserId);
Wale Ogunwale6c5eb1c2015-11-10 07:52:22 -08002454 sb.append(" StackId=");
Andrii Kulian02b7a832016-10-06 23:11:56 -07002455 sb.append(getStackId());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002456 sb.append(" sz=");
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002457 sb.append(getChildCount());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002458 sb.append('}');
2459 return sb.toString();
2460 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002461 sb.append("TaskRecord{");
2462 sb.append(Integer.toHexString(System.identityHashCode(this)));
2463 sb.append(" #");
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002464 sb.append(mTaskId);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002465 if (affinity != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002466 sb.append(" A=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002467 sb.append(affinity);
2468 } else if (intent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002469 sb.append(" I=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002470 sb.append(intent.getComponent().flattenToShortString());
Bryce Leefbd263b42018-03-07 10:33:55 -08002471 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002472 sb.append(" aI=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002473 sb.append(affinityIntent.getComponent().flattenToShortString());
2474 } else {
2475 sb.append(" ??");
2476 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07002477 stringName = sb.toString();
2478 return toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002479 }
Steven Timotius4346f0a2017-09-12 11:07:21 -07002480
Nataniel Borges023ecb52019-01-16 14:15:43 -08002481 public void writeToProto(ProtoOutputStream proto, long fieldId,
2482 @WindowTraceLogLevel int logLevel) {
2483 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
2484 return;
2485 }
2486
Steven Timotius4346f0a2017-09-12 11:07:21 -07002487 final long token = proto.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -08002488 super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002489 proto.write(ID, mTaskId);
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002490 for (int i = getChildCount() - 1; i >= 0; i--) {
2491 ActivityRecord activity = getChildAt(i);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002492 activity.writeToProto(proto, ACTIVITIES);
2493 }
2494 proto.write(STACK_ID, mStack.mStackId);
2495 if (mLastNonFullscreenBounds != null) {
2496 mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
2497 }
2498 if (realActivity != null) {
2499 proto.write(REAL_ACTIVITY, realActivity.flattenToShortString());
2500 }
2501 if (origActivity != null) {
2502 proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString());
2503 }
2504 proto.write(ACTIVITY_TYPE, getActivityType());
Steven Timotius4346f0a2017-09-12 11:07:21 -07002505 proto.write(RESIZE_MODE, mResizeMode);
Bryce Leef3c6a472017-11-14 14:53:06 -08002506 // TODO: Remove, no longer needed with windowingMode.
2507 proto.write(FULLSCREEN, matchParentBounds());
2508
2509 if (!matchParentBounds()) {
Evan Roskydfe3da72018-10-26 17:21:06 -07002510 final Rect bounds = getRequestedOverrideBounds();
Bryce Leef3c6a472017-11-14 14:53:06 -08002511 bounds.writeToProto(proto, BOUNDS);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002512 }
2513 proto.write(MIN_WIDTH, mMinWidth);
2514 proto.write(MIN_HEIGHT, mMinHeight);
2515 proto.end(token);
2516 }
Winson Chung61c9e5a2017-10-11 10:39:32 -07002517
2518 /**
2519 * See {@link #getNumRunningActivities(TaskActivitiesReport)}.
2520 */
2521 static class TaskActivitiesReport {
2522 int numRunning;
2523 int numActivities;
2524 ActivityRecord top;
2525 ActivityRecord base;
2526
2527 void reset() {
2528 numRunning = numActivities = 0;
2529 top = base = null;
2530 }
2531 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002532
2533 /**
2534 * Saves this {@link TaskRecord} to XML using given serializer.
2535 */
2536 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
2537 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
2538
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002539 out.attribute(null, ATTR_TASKID, String.valueOf(mTaskId));
Garfield Tan9b1efea2017-12-05 16:43:46 -08002540 if (realActivity != null) {
2541 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
2542 }
2543 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
2544 if (origActivity != null) {
2545 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
2546 }
2547 // Write affinity, and root affinity if it is different from affinity.
2548 // We use the special string "@" for a null root affinity, so we can identify
2549 // later whether we were given a root affinity or should just make it the
2550 // same as the affinity.
2551 if (affinity != null) {
2552 out.attribute(null, ATTR_AFFINITY, affinity);
2553 if (!affinity.equals(rootAffinity)) {
2554 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2555 }
2556 } else if (rootAffinity != null) {
2557 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2558 }
2559 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
2560 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
2561 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002562 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
Garfield Tan9b1efea2017-12-05 16:43:46 -08002563 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
2564 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
2565 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
2566 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
2567 if (lastDescription != null) {
2568 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
2569 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002570 if (mTaskDescription != null) {
2571 mTaskDescription.saveToXml(out);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002572 }
2573 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
2574 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
2575 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
2576 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
2577 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
2578 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
2579 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
2580 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
2581 String.valueOf(mSupportsPictureInPicture));
2582 if (mLastNonFullscreenBounds != null) {
2583 out.attribute(
2584 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
2585 }
2586 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
2587 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
2588 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
2589
2590 if (affinityIntent != null) {
2591 out.startTag(null, TAG_AFFINITYINTENT);
2592 affinityIntent.saveToXml(out);
2593 out.endTag(null, TAG_AFFINITYINTENT);
2594 }
2595
Bryce Lee1a990e52018-04-23 10:54:11 -07002596 if (intent != null) {
2597 out.startTag(null, TAG_INTENT);
2598 intent.saveToXml(out);
2599 out.endTag(null, TAG_INTENT);
2600 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002601
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002602 final int numActivities = getChildCount();
Garfield Tan9b1efea2017-12-05 16:43:46 -08002603 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002604 final ActivityRecord r = getChildAt(activityNdx);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002605 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
2606 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
2607 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
2608 activityNdx > 0) {
2609 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
2610 break;
2611 }
2612 out.startTag(null, TAG_ACTIVITY);
2613 r.saveToXml(out);
2614 out.endTag(null, TAG_ACTIVITY);
2615 }
2616 }
2617
2618 @VisibleForTesting
2619 static TaskRecordFactory getTaskRecordFactory() {
2620 if (sTaskRecordFactory == null) {
2621 setTaskRecordFactory(new TaskRecordFactory());
2622 }
2623 return sTaskRecordFactory;
2624 }
2625
2626 static void setTaskRecordFactory(TaskRecordFactory factory) {
2627 sTaskRecordFactory = factory;
2628 }
2629
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002630 static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002631 Intent intent, IVoiceInteractionSession voiceSession,
2632 IVoiceInteractor voiceInteractor) {
2633 return getTaskRecordFactory().create(
2634 service, taskId, info, intent, voiceSession, voiceInteractor);
2635 }
2636
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002637 static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002638 Intent intent, TaskDescription taskDescription) {
2639 return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
2640 }
2641
2642 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2643 throws IOException, XmlPullParserException {
2644 return getTaskRecordFactory().restoreFromXml(in, stackSupervisor);
2645 }
2646
2647 /**
2648 * A factory class used to create {@link TaskRecord} or its subclass if any. This can be
2649 * specified when system boots by setting it with
2650 * {@link #setTaskRecordFactory(TaskRecordFactory)}.
2651 */
2652 static class TaskRecordFactory {
2653
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002654 TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002655 Intent intent, IVoiceInteractionSession voiceSession,
2656 IVoiceInteractor voiceInteractor) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002657 return new TaskRecord(service, taskId, info, intent, voiceSession, voiceInteractor,
2658 null /*taskDescription*/);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002659 }
2660
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002661 TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002662 Intent intent, TaskDescription taskDescription) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002663 return new TaskRecord(service, taskId, info, intent, null /*voiceSession*/,
2664 null /*voiceInteractor*/, taskDescription);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002665 }
2666
2667 /**
2668 * Should only be used when we're restoring {@link TaskRecord} from storage.
2669 */
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002670 TaskRecord create(ActivityTaskManagerService service, int taskId, Intent intent,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002671 Intent affinityIntent, String affinity, String rootAffinity,
2672 ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
2673 boolean autoRemoveRecents, boolean askedCompatMode, int userId,
2674 int effectiveUid, String lastDescription, ArrayList<ActivityRecord> activities,
2675 long lastTimeMoved, boolean neverRelinquishIdentity,
2676 TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
2677 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
2678 int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
2679 boolean userSetupComplete, int minWidth, int minHeight) {
2680 return new TaskRecord(service, taskId, intent, affinityIntent, affinity,
2681 rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
2682 askedCompatMode, userId, effectiveUid, lastDescription, activities,
2683 lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
2684 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
2685 resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002686 minWidth, minHeight, null /*ActivityInfo*/, null /*_voiceSession*/,
2687 null /*_voiceInteractor*/);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002688 }
2689
2690 TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2691 throws IOException, XmlPullParserException {
2692 Intent intent = null;
2693 Intent affinityIntent = null;
2694 ArrayList<ActivityRecord> activities = new ArrayList<>();
2695 ComponentName realActivity = null;
2696 boolean realActivitySuspended = false;
2697 ComponentName origActivity = null;
2698 String affinity = null;
2699 String rootAffinity = null;
2700 boolean hasRootAffinity = false;
2701 boolean rootHasReset = false;
2702 boolean autoRemoveRecents = false;
2703 boolean askedCompatMode = false;
2704 int taskType = 0;
2705 int userId = 0;
2706 boolean userSetupComplete = true;
2707 int effectiveUid = -1;
2708 String lastDescription = null;
2709 long lastTimeOnTop = 0;
2710 boolean neverRelinquishIdentity = true;
2711 int taskId = INVALID_TASK_ID;
2712 final int outerDepth = in.getDepth();
2713 TaskDescription taskDescription = new TaskDescription();
2714 int taskAffiliation = INVALID_TASK_ID;
2715 int taskAffiliationColor = 0;
2716 int prevTaskId = INVALID_TASK_ID;
2717 int nextTaskId = INVALID_TASK_ID;
2718 int callingUid = -1;
2719 String callingPackage = "";
2720 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
2721 boolean supportsPictureInPicture = false;
Garfield Tan367b35a2017-12-13 12:16:21 -08002722 Rect lastNonFullscreenBounds = null;
Garfield Tan9b1efea2017-12-05 16:43:46 -08002723 int minWidth = INVALID_MIN_SIZE;
2724 int minHeight = INVALID_MIN_SIZE;
2725 int persistTaskVersion = 0;
2726
2727 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
2728 final String attrName = in.getAttributeName(attrNdx);
2729 final String attrValue = in.getAttributeValue(attrNdx);
2730 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
2731 attrName + " value=" + attrValue);
2732 switch (attrName) {
2733 case ATTR_TASKID:
2734 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
2735 break;
2736 case ATTR_REALACTIVITY:
2737 realActivity = ComponentName.unflattenFromString(attrValue);
2738 break;
2739 case ATTR_REALACTIVITY_SUSPENDED:
2740 realActivitySuspended = Boolean.valueOf(attrValue);
2741 break;
2742 case ATTR_ORIGACTIVITY:
2743 origActivity = ComponentName.unflattenFromString(attrValue);
2744 break;
2745 case ATTR_AFFINITY:
2746 affinity = attrValue;
2747 break;
2748 case ATTR_ROOT_AFFINITY:
2749 rootAffinity = attrValue;
2750 hasRootAffinity = true;
2751 break;
2752 case ATTR_ROOTHASRESET:
2753 rootHasReset = Boolean.parseBoolean(attrValue);
2754 break;
2755 case ATTR_AUTOREMOVERECENTS:
2756 autoRemoveRecents = Boolean.parseBoolean(attrValue);
2757 break;
2758 case ATTR_ASKEDCOMPATMODE:
2759 askedCompatMode = Boolean.parseBoolean(attrValue);
2760 break;
2761 case ATTR_USERID:
2762 userId = Integer.parseInt(attrValue);
2763 break;
2764 case ATTR_USER_SETUP_COMPLETE:
2765 userSetupComplete = Boolean.parseBoolean(attrValue);
2766 break;
2767 case ATTR_EFFECTIVE_UID:
2768 effectiveUid = Integer.parseInt(attrValue);
2769 break;
2770 case ATTR_TASKTYPE:
2771 taskType = Integer.parseInt(attrValue);
2772 break;
2773 case ATTR_LASTDESCRIPTION:
2774 lastDescription = attrValue;
2775 break;
2776 case ATTR_LASTTIMEMOVED:
2777 lastTimeOnTop = Long.parseLong(attrValue);
2778 break;
2779 case ATTR_NEVERRELINQUISH:
2780 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
2781 break;
2782 case ATTR_TASK_AFFILIATION:
2783 taskAffiliation = Integer.parseInt(attrValue);
2784 break;
2785 case ATTR_PREV_AFFILIATION:
2786 prevTaskId = Integer.parseInt(attrValue);
2787 break;
2788 case ATTR_NEXT_AFFILIATION:
2789 nextTaskId = Integer.parseInt(attrValue);
2790 break;
2791 case ATTR_TASK_AFFILIATION_COLOR:
2792 taskAffiliationColor = Integer.parseInt(attrValue);
2793 break;
2794 case ATTR_CALLING_UID:
2795 callingUid = Integer.parseInt(attrValue);
2796 break;
2797 case ATTR_CALLING_PACKAGE:
2798 callingPackage = attrValue;
2799 break;
2800 case ATTR_RESIZE_MODE:
2801 resizeMode = Integer.parseInt(attrValue);
2802 break;
2803 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
2804 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
2805 break;
2806 case ATTR_NON_FULLSCREEN_BOUNDS:
Garfield Tan367b35a2017-12-13 12:16:21 -08002807 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002808 break;
2809 case ATTR_MIN_WIDTH:
2810 minWidth = Integer.parseInt(attrValue);
2811 break;
2812 case ATTR_MIN_HEIGHT:
2813 minHeight = Integer.parseInt(attrValue);
2814 break;
2815 case ATTR_PERSIST_TASK_VERSION:
2816 persistTaskVersion = Integer.parseInt(attrValue);
2817 break;
2818 default:
2819 if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
2820 taskDescription.restoreFromXml(attrName, attrValue);
2821 } else {
2822 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
2823 }
2824 }
2825 }
2826
2827 int event;
2828 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
2829 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
2830 if (event == XmlPullParser.START_TAG) {
2831 final String name = in.getName();
2832 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
2833 "TaskRecord: START_TAG name=" + name);
2834 if (TAG_AFFINITYINTENT.equals(name)) {
2835 affinityIntent = Intent.restoreFromXml(in);
2836 } else if (TAG_INTENT.equals(name)) {
2837 intent = Intent.restoreFromXml(in);
2838 } else if (TAG_ACTIVITY.equals(name)) {
2839 ActivityRecord activity =
2840 ActivityRecord.restoreFromXml(in, stackSupervisor);
2841 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
2842 activity);
2843 if (activity != null) {
2844 activities.add(activity);
2845 }
2846 } else {
Garfield Tan1e740192017-12-12 14:37:42 -08002847 handleUnknownTag(name, in);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002848 }
2849 }
2850 }
2851 if (!hasRootAffinity) {
2852 rootAffinity = affinity;
2853 } else if ("@".equals(rootAffinity)) {
2854 rootAffinity = null;
2855 }
2856 if (effectiveUid <= 0) {
2857 Intent checkIntent = intent != null ? intent : affinityIntent;
2858 effectiveUid = 0;
2859 if (checkIntent != null) {
2860 IPackageManager pm = AppGlobals.getPackageManager();
2861 try {
2862 ApplicationInfo ai = pm.getApplicationInfo(
2863 checkIntent.getComponent().getPackageName(),
2864 PackageManager.MATCH_UNINSTALLED_PACKAGES
2865 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
2866 if (ai != null) {
2867 effectiveUid = ai.uid;
2868 }
2869 } catch (RemoteException e) {
2870 }
2871 }
2872 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
2873 + ": effectiveUid=" + effectiveUid);
2874 }
2875
2876 if (persistTaskVersion < 1) {
2877 // We need to convert the resize mode of home activities saved before version one if
2878 // they are marked as RESIZE_MODE_RESIZEABLE to
2879 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
2880 // before version 1 and the system didn't resize home activities before then.
2881 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
2882 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
2883 }
2884 } else {
2885 // This activity has previously marked itself explicitly as both resizeable and
2886 // supporting picture-in-picture. Since there is no longer a requirement for
2887 // picture-in-picture activities to be resizeable, we can mark this simply as
2888 // resizeable and supporting picture-in-picture separately.
2889 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
2890 resizeMode = RESIZE_MODE_RESIZEABLE;
2891 supportsPictureInPicture = true;
2892 }
2893 }
2894
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07002895 final TaskRecord task = create(stackSupervisor.mService,
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002896 taskId, intent, affinityIntent,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002897 affinity, rootAffinity, realActivity, origActivity, rootHasReset,
2898 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
2899 activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
2900 taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
2901 callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
2902 userSetupComplete, minWidth, minHeight);
Garfield Tan367b35a2017-12-13 12:16:21 -08002903 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
2904 task.setBounds(lastNonFullscreenBounds);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002905
2906 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
2907 activities.get(activityNdx).setTask(task);
2908 }
2909
2910 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
2911 return task;
2912 }
Garfield Tan1e740192017-12-12 14:37:42 -08002913
2914 void handleUnknownTag(String name, XmlPullParser in)
2915 throws IOException, XmlPullParserException {
2916 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
2917 XmlUtils.skipCurrentTag(in);
2918 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002920}