blob: 6920d9d3a7706c26a108b69ace3e77d23b4d834f [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;
Wale Ogunwalec17418e2019-10-13 23:00:40 +020071import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
Garfield Tan891146c2018-10-09 12:14:00 -070072import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
73import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
74import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
Garfield Tan891146c2018-10-09 12:14:00 -070075import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
Wale Ogunwalec17418e2019-10-13 23:00:40 +020076import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
Garfield Tan891146c2018-10-09 12:14:00 -070077import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
78import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
79import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
80import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
81import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
82import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
83import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
84import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
85import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
86import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwalec17418e2019-10-13 23:00:40 +020087import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
Yunfan Chen0e7aff92018-12-05 16:35:32 -080088import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
89import static com.android.server.wm.WindowContainer.POSITION_TOP;
90import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
91import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Garfield Tan891146c2018-10-09 12:14:00 -070092
Winson Chung74666102017-02-22 17:49:24 -080093import static java.lang.Integer.MAX_VALUE;
94
Jorim Jaggie7d2b852017-08-28 17:55:15 +020095import android.annotation.IntDef;
Evan Rosky1ac84462018-11-13 11:25:30 -080096import android.annotation.NonNull;
Jorim Jaggie7d2b852017-08-28 17:55:15 +020097import android.annotation.Nullable;
98import android.app.Activity;
99import android.app.ActivityManager;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200100import android.app.ActivityManager.TaskDescription;
101import android.app.ActivityManager.TaskSnapshot;
102import android.app.ActivityOptions;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700103import android.app.ActivityTaskManager;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200104import android.app.AppGlobals;
Winson Chungabfdcce2018-07-02 17:23:33 -0700105import android.app.TaskInfo;
Garfield Tan891146c2018-10-09 12:14:00 -0700106import android.app.WindowConfiguration;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200107import android.content.ComponentName;
108import android.content.Intent;
109import android.content.pm.ActivityInfo;
110import android.content.pm.ApplicationInfo;
111import android.content.pm.IPackageManager;
112import android.content.pm.PackageManager;
113import android.content.res.Configuration;
114import android.graphics.Rect;
115import android.os.Debug;
116import android.os.RemoteException;
Winson Chungfb44d212017-10-04 11:39:10 -0700117import android.os.SystemClock;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200118import android.os.Trace;
119import android.os.UserHandle;
120import android.provider.Settings;
121import android.service.voice.IVoiceInteractionSession;
122import android.util.DisplayMetrics;
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800123import android.util.EventLog;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200124import android.util.Slog;
Steven Timotius4346f0a2017-09-12 11:07:21 -0700125import android.util.proto.ProtoOutputStream;
Mark Renoufb1abb552019-02-08 13:51:41 -0500126import android.view.Display;
Evan Rosky1ac84462018-11-13 11:25:30 -0800127import android.view.DisplayInfo;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200128
129import com.android.internal.annotations.VisibleForTesting;
130import com.android.internal.app.IVoiceInteractor;
131import com.android.internal.util.XmlUtils;
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200132import com.android.server.protolog.common.ProtoLog;
Wale Ogunwale59507092018-10-29 09:00:30 -0700133import com.android.server.wm.ActivityStack.ActivityState;
Jorim Jaggie7d2b852017-08-28 17:55:15 +0200134
135import org.xmlpull.v1.XmlPullParser;
136import org.xmlpull.v1.XmlPullParserException;
137import org.xmlpull.v1.XmlSerializer;
138
139import java.io.IOException;
140import java.io.PrintWriter;
141import java.lang.annotation.Retention;
142import java.lang.annotation.RetentionPolicy;
143import java.util.ArrayList;
144import java.util.Objects;
145
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800146class TaskRecord extends ConfigurationContainer {
Wale Ogunwale98875612018-10-12 07:53:02 -0700147 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_ATM;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700148 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700149 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
Craig Mautnere0570202015-05-13 13:06:11 -0700150 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700151 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800152
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700153 private static final String ATTR_TASKID = "task_id";
Craig Mautner21d24a22014-04-23 11:45:37 -0700154 private static final String TAG_INTENT = "intent";
155 private static final String TAG_AFFINITYINTENT = "affinity_intent";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700156 private static final String ATTR_REALACTIVITY = "real_activity";
157 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
Craig Mautner21d24a22014-04-23 11:45:37 -0700158 private static final String ATTR_ORIGACTIVITY = "orig_activity";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700159 private static final String TAG_ACTIVITY = "activity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700160 private static final String ATTR_AFFINITY = "affinity";
Dianne Hackborn79228822014-09-16 11:11:23 -0700161 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700162 private static final String ATTR_ROOTHASRESET = "root_has_reset";
Dianne Hackborn13420f22014-07-18 15:43:56 -0700163 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
Craig Mautner21d24a22014-04-23 11:45:37 -0700164 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
165 private static final String ATTR_USERID = "user_id";
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800166 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700167 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700168 @Deprecated
Craig Mautner21d24a22014-04-23 11:45:37 -0700169 private static final String ATTR_TASKTYPE = "task_type";
Craig Mautner21d24a22014-04-23 11:45:37 -0700170 private static final String ATTR_LASTDESCRIPTION = "last_description";
171 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700172 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700173 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
Craig Mautnera228ae92014-07-09 05:44:55 -0700174 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
175 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
Winson Chungec396d62014-08-06 17:08:00 -0700176 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700177 private static final String ATTR_CALLING_UID = "calling_uid";
178 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Winson Chungd3395382016-12-13 11:49:09 -0800179 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800180 private static final String ATTR_RESIZE_MODE = "resize_mode";
Wale Ogunwale706ed792015-08-02 10:29:44 -0700181 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700182 private static final String ATTR_MIN_WIDTH = "min_width";
183 private static final String ATTR_MIN_HEIGHT = "min_height";
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700184 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Andrii Kulian18d75122016-03-27 20:20:28 -0700185
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700186 // Current version of the task record we persist. Used to check if we need to run any upgrade
187 // code.
188 private static final int PERSIST_TASK_VERSION = 1;
Craig Mautner21d24a22014-04-23 11:45:37 -0700189
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700190 private static final int INVALID_MIN_SIZE = -1;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800191
Winson Chung74666102017-02-22 17:49:24 -0800192 /**
193 * The modes to control how the stack is moved to the front when calling
194 * {@link TaskRecord#reparent}.
195 */
196 @Retention(RetentionPolicy.SOURCE)
197 @IntDef({
198 REPARENT_MOVE_STACK_TO_FRONT,
199 REPARENT_KEEP_STACK_AT_FRONT,
200 REPARENT_LEAVE_STACK_IN_PLACE
201 })
Wale Ogunwale66e16852017-10-19 13:35:52 -0700202 @interface ReparentMoveStackMode {}
Winson Chung74666102017-02-22 17:49:24 -0800203 // Moves the stack to the front if it was not at the front
Wale Ogunwale66e16852017-10-19 13:35:52 -0700204 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
Winson Chung74666102017-02-22 17:49:24 -0800205 // Only moves the stack to the front if it was focused or front most already
Wale Ogunwale66e16852017-10-19 13:35:52 -0700206 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
Winson Chung74666102017-02-22 17:49:24 -0800207 // Do not move the stack as a part of reparenting
Wale Ogunwale66e16852017-10-19 13:35:52 -0700208 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
Winson Chung74666102017-02-22 17:49:24 -0800209
Garfield Tan9b1efea2017-12-05 16:43:46 -0800210 /**
211 * The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}.
212 */
213 private static TaskRecordFactory sTaskRecordFactory;
214
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700215 final int mTaskId; // Unique identifier for this task.
Dianne Hackborn79228822014-09-16 11:11:23 -0700216 String affinity; // The affinity name for this task, or null; may change identity.
217 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Dianne Hackborn91097de2014-04-04 18:02:06 -0700218 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
219 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Bryce Lee1a990e52018-04-23 10:54:11 -0700220 Intent intent; // The original intent that started the task. Note that this value can
221 // be null.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700223 int effectiveUid; // The current effective uid of the identity of this task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 ComponentName origActivity; // The non-alias activity component of the intent.
225 ComponentName realActivity; // The actual activity component that started the task.
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +0000226 boolean realActivitySuspended; // True if the actual activity component that started the
227 // task is suspended.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700228 boolean inRecents; // Actually in the recents list?
Winson Chungfb44d212017-10-04 11:39:10 -0700229 long lastActiveTime; // Last time this task was active in the current device session,
230 // including sleep. This time is initialized to the elapsed time when
231 // restored from disk.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700232 boolean isAvailable; // Is the activity available to be launched?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 boolean rootWasReset; // True if the intent at the root of the task had
234 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700235 boolean autoRemoveRecents; // If true, we should automatically remove the task from
236 // recents when activity finishes
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700237 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700238 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 -0800239
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700240 String stringName; // caching of toString() result.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700241 int mUserId; // user for which this task was created
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800242 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
243 // was changed.
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800244
245 int numFullscreen; // Number of fullscreen activities.
246
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800247 int mResizeMode; // The resize mode of this task and its activities.
248 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800249 private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
250 // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
251 // of the root activity.
Craig Mautner15df08a2015-04-01 12:17:18 -0700252 /** Can't be put in lockTask mode. */
253 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
Benjamin Franz469dd582015-06-09 14:24:36 +0100254 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700255 final static int LOCK_TASK_AUTH_PINNABLE = 1;
256 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
257 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
Benjamin Franz469dd582015-06-09 14:24:36 +0100258 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700259 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
Benjamin Franz469dd582015-06-09 14:24:36 +0100260 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
261 * lockTask task. */
262 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
Craig Mautner15df08a2015-04-01 12:17:18 -0700263 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
264
265 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800266
Winson Chung03a9bae2014-05-02 09:56:12 -0700267 // This represents the last resolved activity values for this task
268 // NOTE: This value needs to be persisted with each task
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700269 TaskDescription mTaskDescription;
Winson Chung03a9bae2014-05-02 09:56:12 -0700270
Craig Mautnerd2328952013-03-05 12:46:26 -0800271 /** List of all activities in the task arranged in history order */
Craig Mautner21d24a22014-04-23 11:45:37 -0700272 final ArrayList<ActivityRecord> mActivities;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800273
Andrii Kulian02b7a832016-10-06 23:11:56 -0700274 /** Current stack. Setter must always be used to update the value. */
275 private ActivityStack mStack;
Craig Mautnerd2328952013-03-05 12:46:26 -0800276
Dianne Hackborn68a06332017-11-15 17:54:18 -0800277 /** The process that had previously hosted the root activity of this task.
278 * Used to know that we should try harder to keep this process around, in case the
279 * user wants to return to it. */
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -0700280 private WindowProcessController mRootProcess;
Dianne Hackborn68a06332017-11-15 17:54:18 -0800281
Craig Mautner21d24a22014-04-23 11:45:37 -0700282 /** Takes on same value as first root activity */
283 boolean isPersistable = false;
Craig Mautnerffcfcaa2014-06-05 09:54:38 -0700284 int maxRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700285
286 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
287 * determining the order when restoring. Sign indicates whether last task movement was to front
288 * (positive) or back (negative). Absolute value indicates time. */
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700289 long mLastTimeMoved;
Craig Mautner21d24a22014-04-23 11:45:37 -0700290
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700291 /** If original intent did not allow relinquishing task identity, save that information */
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700292 private boolean mNeverRelinquishIdentity = true;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700293
Craig Mautner362449a2014-06-20 14:04:39 -0700294 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
295 // do not want to delete the stack when the task goes empty.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800296 private boolean mReuseTask = false;
Craig Mautner362449a2014-06-20 14:04:39 -0700297
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700298 CharSequence lastDescription; // Last description captured for this item.
299
Craig Mautnera228ae92014-07-09 05:44:55 -0700300 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Winson Chungec396d62014-08-06 17:08:00 -0700301 int mAffiliatedTaskColor; // color of the parent task affiliation.
Craig Mautnera228ae92014-07-09 05:44:55 -0700302 TaskRecord mPrevAffiliate; // previous task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800303 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700304 TaskRecord mNextAffiliate; // next task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800305 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700306
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700307 // For relaunching the task from recents as though it was launched by the original launcher.
308 int mCallingUid;
309 String mCallingPackage;
310
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700311 final ActivityTaskManagerService mAtmService;
Craig Mautner21d24a22014-04-23 11:45:37 -0700312
Jorim Jaggi82c9dc92016-02-05 15:10:33 -0800313 private final Rect mTmpStableBounds = new Rect();
314 private final Rect mTmpNonDecorBounds = new Rect();
Evan Rosky1ac84462018-11-13 11:25:30 -0800315 private final Rect mTmpBounds = new Rect();
316 private final Rect mTmpInsets = new Rect();
Jorim Jaggi0a932142016-02-01 17:42:25 -0800317
Wale Ogunwale706ed792015-08-02 10:29:44 -0700318 // Last non-fullscreen bounds the task was launched in or resized to.
319 // The information is persisted and used to determine the appropriate stack to launch the
320 // task into on restore.
321 Rect mLastNonFullscreenBounds = null;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700322 // Minimal width and height of this task when it's resizeable. -1 means it should use the
323 // default minimal width/height.
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700324 int mMinWidth;
325 int mMinHeight;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700326
Chong Zhangfdcc4d42015-10-14 16:50:12 -0700327 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
328 // This number will be assigned when we evaluate OOM scores for all visible tasks.
329 int mLayerRank = -1;
330
Evan Roskyed6767f2018-10-26 17:21:06 -0700331 // When non-empty, this represents the bounds this task will be drawn at. This gets set during
332 // transient operations such as split-divider dragging and animations.
333 // TODO(b/119687367): This member is temporary.
334 final Rect mDisplayedBounds = new Rect();
335
Andrii Kulian1779e612016-10-12 21:58:25 -0700336 /** Helper object used for updating override configuration. */
337 private Configuration mTmpConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700338
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800339 // TODO: remove after unification
340 Task mTask;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800341
Mark Renoufc808f062019-02-07 15:20:37 -0500342 /** Used by fillTaskInfo */
343 final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
344
Garfield Tan9b1efea2017-12-05 16:43:46 -0800345 /**
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700346 * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
347 * ActivityInfo, Intent, TaskDescription)} instead.
Garfield Tan9b1efea2017-12-05 16:43:46 -0800348 */
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700349 TaskRecord(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info,
350 Intent _intent, IVoiceInteractionSession _voiceSession,
351 IVoiceInteractor _voiceInteractor, TaskDescription _taskDescription) {
352 this(atmService, _taskId, _intent, null /*_affinityIntent*/, null /*_affinity*/,
353 null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
354 false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
355 UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
356 null /*_lastDescription*/, new ArrayList<>(), System.currentTimeMillis(),
357 true /*neverRelinquishIdentity*/,
358 _taskDescription != null ? _taskDescription : new TaskDescription(),
359 _taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
360 info.applicationInfo.uid, info.packageName, info.resizeMode,
361 info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
362 false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
363 _voiceSession, _voiceInteractor);
Craig Mautner21d24a22014-04-23 11:45:37 -0700364 }
365
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700366 /** Don't use constructor directly. This is only used by XML parser. */
367 TaskRecord(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800368 Intent _affinityIntent, String _affinity, String _rootAffinity,
369 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700370 boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800371 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
Winson Chungfb44d212017-10-04 11:39:10 -0700372 long lastTimeMoved, boolean neverRelinquishIdentity,
373 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
374 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Charles He2bf28322017-10-12 22:24:49 +0100375 int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700376 boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info,
377 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
378 mAtmService = atmService;
379 mTaskId = _taskId;
Evan Roskyddedfd42019-10-04 13:38:38 -0700380 mRemoteToken = new RemoteToken(this);
Craig Mautner21d24a22014-04-23 11:45:37 -0700381 affinityIntent = _affinityIntent;
382 affinity = _affinity;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800383 rootAffinity = _rootAffinity;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700384 voiceSession = _voiceSession;
385 voiceInteractor = _voiceInteractor;
Craig Mautner21d24a22014-04-23 11:45:37 -0700386 realActivity = _realActivity;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800387 realActivitySuspended = _realActivitySuspended;
Craig Mautner21d24a22014-04-23 11:45:37 -0700388 origActivity = _origActivity;
389 rootWasReset = _rootWasReset;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700390 isAvailable = true;
Dianne Hackborn13420f22014-07-18 15:43:56 -0700391 autoRemoveRecents = _autoRemoveRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700392 askedCompatMode = _askedCompatMode;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700393 mUserId = _userId;
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800394 mUserSetupComplete = userSetupComplete;
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700395 effectiveUid = _effectiveUid;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700396 touchActiveTime();
Craig Mautner21d24a22014-04-23 11:45:37 -0700397 lastDescription = _lastDescription;
398 mActivities = activities;
399 mLastTimeMoved = lastTimeMoved;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700400 mNeverRelinquishIdentity = neverRelinquishIdentity;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700401 mTaskDescription = _lastTaskDescription;
Craig Mautnera228ae92014-07-09 05:44:55 -0700402 mAffiliatedTaskId = taskAffiliation;
Winson Chungec396d62014-08-06 17:08:00 -0700403 mAffiliatedTaskColor = taskAffiliationColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700404 mPrevAffiliateTaskId = prevTaskId;
405 mNextAffiliateTaskId = nextTaskId;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700406 mCallingUid = callingUid;
407 mCallingPackage = callingPackage;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800408 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800409 mSupportsPictureInPicture = supportsPictureInPicture;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700410 if (info != null) {
411 setIntent(_intent, info);
412 setMinDimensions(info);
413 } else {
414 intent = _intent;
415 mMinWidth = minWidth;
416 mMinHeight = minHeight;
417 }
418 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 }
420
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800421 Task getTask() {
422 return mTask;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800423 }
424
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800425 void createTask(boolean onTop, boolean showForAllUsers) {
426 if (mTask != null) {
427 throw new IllegalArgumentException("mTask=" + mTask
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800428 + " already created for task=" + this);
429 }
430
431 final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
Yunfan Chen279f5582018-12-12 15:24:50 -0800432 final TaskStack stack = getStack().getTaskStack();
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800433
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800434 if (stack == null) {
Yunfan Chen279f5582018-12-12 15:24:50 -0800435 throw new IllegalArgumentException("TaskRecord: invalid stack=" + mStack);
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800436 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700437 EventLog.writeEvent(WM_TASK_CREATED, mTaskId, stack.mStackId);
438 mTask = new Task(mTaskId, stack, mUserId, mAtmService.mWindowManager, mResizeMode,
439 mSupportsPictureInPicture, mTaskDescription, this);
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800440 final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
441
442 if (!mDisplayedBounds.isEmpty()) {
443 mTask.setOverrideDisplayedBounds(mDisplayedBounds);
444 }
445 // We only want to move the parents to the parents if we are creating this task at the
446 // top of its stack.
447 stack.addTask(mTask, position, showForAllUsers, onTop /* moveParents */);
Bryce Lee04ab3462017-04-10 15:06:33 -0700448 }
449
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800450 void setTask(Task task) {
451 mTask = task;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800452 }
453
Garfield Tan347bd602018-12-21 15:11:12 -0800454 void cleanUpResourcesForDestroy() {
Wale Ogunwale1a06f152019-10-11 11:26:30 +0200455 if (hasChild()) {
Garfield Tan347bd602018-12-21 15:11:12 -0800456 return;
457 }
458
459 // This task is going away, so save the last state if necessary.
460 saveLaunchingStateIfNeeded();
461
462 // TODO: VI what about activity?
463 final boolean isVoiceSession = voiceSession != null;
464 if (isVoiceSession) {
465 try {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700466 voiceSession.taskFinished(intent, mTaskId);
Garfield Tan347bd602018-12-21 15:11:12 -0800467 } catch (RemoteException e) {
468 }
469 }
470 if (autoRemoveFromRecents() || isVoiceSession) {
471 // Task creator asked to remove this when done, or this task was a voice
472 // interaction, so it should not remain on the recent tasks list.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700473 mAtmService.mStackSupervisor.mRecentTasks.remove(this);
Garfield Tan347bd602018-12-21 15:11:12 -0800474 }
475
476 removeWindowContainer();
477 }
478
479 @VisibleForTesting
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800480 void removeWindowContainer() {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700481 mAtmService.getLockTaskController().clearLockedTask(this);
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800482 if (mTask == null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700483 if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: could not find taskId=" + mTaskId);
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800484 return;
485 }
486 mTask.removeIfPossible();
487 mTask = null;
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700488 if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800489 // Reset current bounds for task whose bounds shouldn't be persisted so it uses
490 // default configuration the next time it launches.
Evan Roskya4cc3a92019-06-28 13:25:01 -0700491 setBounds(null);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800492 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700493 mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800494 }
495
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700496 void onSnapshotChanged(TaskSnapshot snapshot) {
497 mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(mTaskId, snapshot);
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100498 }
499
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800500 void setResizeMode(int resizeMode) {
501 if (mResizeMode == resizeMode) {
502 return;
503 }
504 mResizeMode = resizeMode;
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800505 mTask.setResizeable(resizeMode);
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700506 mAtmService.mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
507 mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800508 }
509
510 void setTaskDockedResizing(boolean resizing) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800511 if (mTask == null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700512 Slog.w(TAG_WM, "setTaskDockedResizing: taskId " + mTaskId + " not found.");
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800513 return;
514 }
515 mTask.setTaskDockedResizing(resizing);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800516 }
517
Wale Ogunwale1666e312016-12-16 11:27:18 -0800518 // TODO: Consolidate this with the resize() method below.
Wale Ogunwale1666e312016-12-16 11:27:18 -0800519 public void requestResize(Rect bounds, int resizeMode) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700520 mAtmService.resizeTask(mTaskId, bounds, resizeMode);
Wale Ogunwale1666e312016-12-16 11:27:18 -0800521 }
522
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800523 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700524 mAtmService.deferWindowLayout();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800525
Bryce Leef3c6a472017-11-14 14:53:06 -0800526 try {
Bryce Leef3c6a472017-11-14 14:53:06 -0800527 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800528
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800529 if (mTask == null) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800530 // Task doesn't exist in window manager yet (e.g. was restored from recents).
531 // All we can do for now is update the bounds so it can be used when the task is
532 // added to window manager.
Evan Roskya4cc3a92019-06-28 13:25:01 -0700533 setBounds(bounds);
Bryce Leef3c6a472017-11-14 14:53:06 -0800534 if (!inFreeformWindowingMode()) {
535 // re-restore the task so it can have the proper stack association.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700536 mAtmService.mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
Bryce Leef3c6a472017-11-14 14:53:06 -0800537 }
538 return true;
539 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800540
Bryce Leef3c6a472017-11-14 14:53:06 -0800541 if (!canResizeToBounds(bounds)) {
542 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
543 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
544 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800545
Bryce Leef3c6a472017-11-14 14:53:06 -0800546 // Do not move the task to another stack here.
547 // This method assumes that the task is already placed in the right stack.
548 // we do not mess with that decision and we only do the resize!
549
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800550 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeTask_" + mTaskId);
Bryce Leef3c6a472017-11-14 14:53:06 -0800551
Evan Roskya4cc3a92019-06-28 13:25:01 -0700552 boolean updatedConfig = false;
553 mTmpConfig.setTo(getResolvedOverrideConfiguration());
554 if (setBounds(bounds) != BOUNDS_CHANGE_NONE) {
555 updatedConfig = !mTmpConfig.equals(getResolvedOverrideConfiguration());
556 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800557 // This variable holds information whether the configuration didn't change in a significant
558
559 // way and the activity was kept the way it was. If it's false, it means the activity
560 // had
561 // to be relaunched due to configuration change.
562 boolean kept = true;
563 if (updatedConfig) {
564 final ActivityRecord r = topRunningActivityLocked();
565 if (r != null && !deferResume) {
Wale Ogunwaleb6d75f32018-02-22 20:44:56 -0800566 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
Bryce Leef3c6a472017-11-14 14:53:06 -0800567 preserveWindow);
Garfield Tanb9151182018-06-25 16:29:21 -0700568 // Preserve other windows for resizing because if resizing happens when there
569 // is a dialog activity in the front, the activity that still shows some
570 // content to the user will become black and cause flickers. Note in most cases
571 // this won't cause tons of irrelevant windows being preserved because only
572 // activities in this task may experience a bounds change. Configs for other
573 // activities stay the same.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700574 mAtmService.mRootActivityContainer.ensureActivitiesVisible(r, 0, preserveWindow);
Bryce Leef3c6a472017-11-14 14:53:06 -0800575 if (!kept) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700576 mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
Bryce Leef3c6a472017-11-14 14:53:06 -0800577 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800578 }
579 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800580 mTask.resize(kept, forced);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800581
Garfield Tan891146c2018-10-09 12:14:00 -0700582 saveLaunchingStateIfNeeded();
583
Riddle Hsu2ca561b2019-10-08 21:58:58 +0800584 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
Bryce Leef3c6a472017-11-14 14:53:06 -0800585 return kept;
586 } finally {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700587 mAtmService.continueWindowLayout();
Bryce Leef3c6a472017-11-14 14:53:06 -0800588 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800589 }
590
591 // TODO: Investigate combining with the resize() method above.
592 void resizeWindowContainer() {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800593 mTask.resize(false /* relayout */, false /* forced */);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800594 }
595
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800596 void getWindowContainerBounds(Rect bounds) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800597 if (mTask != null) {
598 mTask.getBounds(bounds);
599 } else {
600 bounds.setEmpty();
601 }
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800602 }
603
Winson Chung74666102017-02-22 17:49:24 -0800604 /**
605 * Convenience method to reparent a task to the top or bottom position of the stack.
606 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700607 boolean reparent(ActivityStack preferredStack, boolean toTop,
608 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
609 String reason) {
610 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
611 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung5af42fc2017-03-24 17:11:33 -0700612 }
613
614 /**
615 * Convenience method to reparent a task to the top or bottom position of the stack, with
616 * an option to skip scheduling the picture-in-picture mode change.
617 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700618 boolean reparent(ActivityStack preferredStack, boolean toTop,
619 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
620 boolean schedulePictureInPictureModeChange, String reason) {
621 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
Winson Chung5af42fc2017-03-24 17:11:33 -0700622 deferResume, schedulePictureInPictureModeChange, reason);
623 }
624
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700625 /** Convenience method to reparent a task to a specific position of the stack. */
626 boolean reparent(ActivityStack preferredStack, int position,
627 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
628 String reason) {
629 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
Winson Chung5af42fc2017-03-24 17:11:33 -0700630 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800631 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800632
Winson Chung74666102017-02-22 17:49:24 -0800633 /**
634 * Reparents the task into a preferred stack, creating it if necessary.
635 *
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700636 * @param preferredStack the target stack to move this task
Winson Chung74666102017-02-22 17:49:24 -0800637 * @param position the position to place this task in the new stack
638 * @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 -0700639 * reparenting to be drawn and animated in
Winson Chung74666102017-02-22 17:49:24 -0800640 * @param moveStackMode whether or not to move the stack to the front always, only if it was
Winson Chung5af42fc2017-03-24 17:11:33 -0700641 * previously focused & in front, or never
Winson Chung74666102017-02-22 17:49:24 -0800642 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
Winson Chung5af42fc2017-03-24 17:11:33 -0700643 * have changed as a result of this reparenting
644 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
645 * change. Callers may set this to false if they are explicitly scheduling PiP mode
646 * changes themselves, like during the PiP animation
Winson Chung74666102017-02-22 17:49:24 -0800647 * @param reason the caller of this reparenting
Winson Chung5af42fc2017-03-24 17:11:33 -0700648 * @return whether the task was reparented
Winson Chung74666102017-02-22 17:49:24 -0800649 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700650 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700651 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700652 boolean reparent(ActivityStack preferredStack, int position,
653 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
654 boolean schedulePictureInPictureModeChange, String reason) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700655 final ActivityStackSupervisor supervisor = mAtmService.mStackSupervisor;
656 final RootActivityContainer root = mAtmService.mRootActivityContainer;
657 final WindowManagerService windowManager = mAtmService.mWindowManager;
Winson Chung74666102017-02-22 17:49:24 -0800658 final ActivityStack sourceStack = getStack();
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700659 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
Winson Chung74666102017-02-22 17:49:24 -0800660 position == MAX_VALUE);
661 if (toStack == sourceStack) {
662 return false;
663 }
Andrii Kulianb850ea52017-12-12 23:49:10 -0800664 if (!canBeLaunchedOnDisplay(toStack.mDisplayId)) {
665 return false;
666 }
Winson Chung74666102017-02-22 17:49:24 -0800667
Andrii Kulian6b321512019-01-23 06:37:00 +0000668 final boolean toTopOfStack = position == MAX_VALUE;
669 if (toTopOfStack && toStack.getResumedActivity() != null
670 && toStack.topRunningActivityLocked() != null) {
671 // Pause the resumed activity on the target stack while re-parenting task on top of it.
672 toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
Louis Chang7b03ad92019-08-21 12:32:33 +0800673 null /* resuming */);
Andrii Kulian6b321512019-01-23 06:37:00 +0000674 }
675
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700676 final int toStackWindowingMode = toStack.getWindowingMode();
Winson Chung74666102017-02-22 17:49:24 -0800677 final ActivityRecord topActivity = getTopActivity();
678
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800679 final boolean mightReplaceWindow = topActivity != null
680 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
Winson Chung74666102017-02-22 17:49:24 -0800681 if (mightReplaceWindow) {
682 // We are about to relaunch the activity because its configuration changed due to
683 // being maximized, i.e. size change. The activity will first remove the old window
684 // and then add a new one. This call will tell window manager about this, so it can
685 // preserve the old window until the new one is drawn. This prevents having a gap
686 // between the removal and addition, in which no window is visible. We also want the
687 // entrance of the new window to be properly animated.
688 // Note here we always set the replacing window first, as the flags might be needed
689 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
690 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
691 }
692
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700693 mAtmService.deferWindowLayout();
Winson Chung74666102017-02-22 17:49:24 -0800694 boolean kept = true;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800695 try {
Winson Chung74666102017-02-22 17:49:24 -0800696 final ActivityRecord r = topRunningActivityLocked();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800697 final boolean wasFocused = r != null && root.isTopDisplayFocusedStack(sourceStack)
Winson Chung74666102017-02-22 17:49:24 -0800698 && (topRunningActivityLocked() == r);
Bryce Leec4ab62a2018-03-05 14:19:26 -0800699 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
Winson Chung95f8f0e2017-03-24 09:20:17 -0700700 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
Winson Chung74666102017-02-22 17:49:24 -0800701
702 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
703 // Whenever we are moving the top activity from the front stack we want to make sure to
704 // move the stack to the front.
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700705 final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
Winson Chung74666102017-02-22 17:49:24 -0800706 && (sourceStack.topRunningActivityLocked() == r);
707
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800708 // Adjust the position for the new parent stack as needed.
Winson Chung74666102017-02-22 17:49:24 -0800709 position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800710
711 // Must reparent first in window manager to avoid a situation where AM can delete the
712 // we are coming from in WM before we reparent because it became empty.
Yunfan Chen279f5582018-12-12 15:24:50 -0800713 mTask.reparent(toStack.getTaskStack(), position,
Wale Ogunwale2719cc12017-04-14 09:45:27 -0700714 moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800715
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700716 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
717 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
Winson Chung74666102017-02-22 17:49:24 -0800718 // Move the task
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700719 sourceStack.removeTask(this, reason, moveStackToFront
720 ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
Winson Chung5af42fc2017-03-24 17:11:33 -0700721 toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800722
Winson Chung5af42fc2017-03-24 17:11:33 -0700723 if (schedulePictureInPictureModeChange) {
724 // Notify of picture-in-picture mode changes
725 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
726 }
Winson Chung74666102017-02-22 17:49:24 -0800727
728 // TODO: Ensure that this is actually necessary here
729 // Notify the voice session if required
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800730 if (voiceSession != null) {
731 try {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700732 voiceSession.taskStarted(intent, mTaskId);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800733 } catch (RemoteException e) {
734 }
735 }
Winson Chung74666102017-02-22 17:49:24 -0800736
737 // If the task had focus before (or we're requested to move focus), move focus to the
738 // new stack by moving the stack to the front.
Winson Chung95f8f0e2017-03-24 09:20:17 -0700739 if (r != null) {
740 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
741 wasPaused, reason);
742 }
Winson Chung74666102017-02-22 17:49:24 -0800743 if (!animate) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700744 mAtmService.mStackSupervisor.mNoAnimActivities.add(topActivity);
Winson Chung74666102017-02-22 17:49:24 -0800745 }
746
747 // We might trigger a configuration change. Save the current task bounds for freezing.
748 // TODO: Should this call be moved inside the resize method in WM?
749 toStack.prepareFreezingTaskBounds();
750
751 // Make sure the task has the appropriate bounds/size for the stack it is in.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700752 final boolean toStackSplitScreenPrimary =
753 toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Evan Roskydfe3da72018-10-26 17:21:06 -0700754 final Rect configBounds = getRequestedOverrideBounds();
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700755 if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
756 || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
Evan Roskydfe3da72018-10-26 17:21:06 -0700757 && !Objects.equals(configBounds, toStack.getRequestedOverrideBounds())) {
758 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
759 !mightReplaceWindow, deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700760 } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
Winson Chung74666102017-02-22 17:49:24 -0800761 Rect bounds = getLaunchBounds();
762 if (bounds == null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700763 mAtmService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Bryce Leef3c6a472017-11-14 14:53:06 -0800764 bounds = configBounds;
Winson Chung74666102017-02-22 17:49:24 -0800765 }
766 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700767 } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
768 if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
Matthew Ng330757d2017-02-28 14:19:17 -0800769 // Move recents to front so it is not behind home stack when going into docked
770 // mode
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700771 mAtmService.mStackSupervisor.moveRecentsStackToFront(reason);
Matthew Ng330757d2017-02-28 14:19:17 -0800772 }
Evan Roskydfe3da72018-10-26 17:21:06 -0700773 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
774 !mightReplaceWindow, deferResume);
Winson Chung74666102017-02-22 17:49:24 -0800775 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800776 } finally {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700777 mAtmService.continueWindowLayout();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800778 }
Winson Chung74666102017-02-22 17:49:24 -0800779
780 if (mightReplaceWindow) {
781 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
782 // window), we need to clear the replace window settings. Otherwise, we schedule a
783 // timeout to remove the old window if the replacing window is not coming in time.
784 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
785 }
786
787 if (!deferResume) {
788 // The task might have already been running and its visibility needs to be synchronized
789 // with the visibility of the stack / windows.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800790 root.ensureActivitiesVisible(null, 0, !mightReplaceWindow);
791 root.resumeFocusedStacksTopActivities();
Winson Chung74666102017-02-22 17:49:24 -0800792 }
793
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700794 // TODO: Handle incorrect request to move before the actual move, not after.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700795 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700796 DEFAULT_DISPLAY, toStack);
Winson Chung74666102017-02-22 17:49:24 -0800797
Winson Chungdff7a732017-12-11 12:17:06 -0800798 return (preferredStack == toStack);
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800799 }
800
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700801 /**
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800802 * @return True if the windows of tasks being moved to the target stack from the source stack
803 * should be replaced, meaning that window manager will keep the old window around until the new
804 * is ready.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700805 */
806 private static boolean replaceWindowsOnTaskMove(
807 int sourceWindowingMode, int targetWindowingMode) {
808 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
809 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
810 }
811
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800812 void cancelWindowTransition() {
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800813 if (mTask == null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700814 Slog.w(TAG_WM, "cancelWindowTransition: taskId " + mTaskId + " not found.");
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800815 return;
816 }
817 mTask.cancelTaskWindowTransition();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800818 }
819
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100820 /**
821 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
822 */
Jorim Jaggi925bb3c2019-06-04 19:51:45 +0200823 TaskSnapshot getSnapshot(boolean reducedResolution, boolean restoreFromDisk) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100824
825 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
826 // synchronized between AM and WM.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700827 return mAtmService.mWindowManager.getTaskSnapshot(mTaskId, mUserId, reducedResolution,
Jorim Jaggi925bb3c2019-06-04 19:51:45 +0200828 restoreFromDisk);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800829 }
830
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 void touchActiveTime() {
Winson Chungfb44d212017-10-04 11:39:10 -0700832 lastActiveTime = SystemClock.elapsedRealtime();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800833 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700834
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800835 long getInactiveDuration() {
Winson Chungfb44d212017-10-04 11:39:10 -0700836 return SystemClock.elapsedRealtime() - lastActiveTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800837 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700838
Winson Chungfee26772014-08-05 12:21:52 -0700839 /** Sets the original intent, and the calling uid and package. */
840 void setIntent(ActivityRecord r) {
Winson Chungfee26772014-08-05 12:21:52 -0700841 mCallingUid = r.launchedFromUid;
842 mCallingPackage = r.launchedFromPackage;
Craig Mautner15df08a2015-04-01 12:17:18 -0700843 setIntent(r.intent, r.info);
Charles He2bf28322017-10-12 22:24:49 +0100844 setLockTaskAuth(r);
Winson Chungfee26772014-08-05 12:21:52 -0700845 }
846
847 /** Sets the original intent, _without_ updating the calling uid or package. */
848 private void setIntent(Intent _intent, ActivityInfo info) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700849 if (intent == null) {
850 mNeverRelinquishIdentity =
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700851 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700852 } else if (mNeverRelinquishIdentity) {
853 return;
854 }
855
856 affinity = info.taskAffinity;
Dianne Hackborn79228822014-09-16 11:11:23 -0700857 if (intent == null) {
858 // If this task already has an intent associated with it, don't set the root
859 // affinity -- we don't want it changing after initially set, but the initially
860 // set value may be null.
861 rootAffinity = affinity;
862 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700863 effectiveUid = info.applicationInfo.uid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700864 stringName = null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 if (info.targetActivity == null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800867 if (_intent != null) {
868 // If this Intent has a selector, we want to clear it for the
869 // recent task since it is not relevant if the user later wants
870 // to re-launch the app.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700871 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800872 _intent = new Intent(_intent);
873 _intent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700874 _intent.setSourceBounds(null);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800875 }
876 }
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700877 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 intent = _intent;
879 realActivity = _intent != null ? _intent.getComponent() : null;
880 origActivity = null;
881 } else {
882 ComponentName targetComponent = new ComponentName(
883 info.packageName, info.targetActivity);
884 if (_intent != null) {
885 Intent targetIntent = new Intent(_intent);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800886 targetIntent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700887 targetIntent.setSourceBounds(null);
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700888 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
Dianne Hackborn7f96b792012-05-29 18:46:45 -0700889 "Setting Intent of " + this + " to target " + targetIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 intent = targetIntent;
891 realActivity = targetComponent;
892 origActivity = _intent.getComponent();
893 } else {
894 intent = null;
895 realActivity = targetComponent;
896 origActivity = new ComponentName(info.packageName, info.name);
897 }
898 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700899
Craig Mautner47b20ba2014-09-17 17:23:44 -0700900 final int intentFlags = intent == null ? 0 : intent.getFlags();
901 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 // Once we are set to an Intent with this flag, we count this
903 // task as having a true root activity.
904 rootWasReset = true;
905 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700906 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
907 mUserSetupComplete = Settings.Secure.getIntForUser(
908 mAtmService.mContext.getContentResolver(), USER_SETUP_COMPLETE, 0, mUserId) != 0;
Craig Mautner41db4a72014-05-07 17:20:56 -0700909 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700910 // If the activity itself has requested auto-remove, then just always do it.
911 autoRemoveRecents = true;
Wale Ogunwale843bfb92015-03-27 11:06:48 -0700912 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
913 == FLAG_ACTIVITY_NEW_DOCUMENT) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700914 // If the caller has not asked for the document to be retained, then we may
915 // want to turn on auto-remove, depending on whether the target has set its
916 // own document launch mode.
917 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
918 autoRemoveRecents = false;
919 } else {
920 autoRemoveRecents = true;
921 }
922 } else {
923 autoRemoveRecents = false;
Craig Mautner41db4a72014-05-07 17:20:56 -0700924 }
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800925 mResizeMode = info.resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800926 mSupportsPictureInPicture = info.supportsPictureInPicture();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800927 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800928
Andrii Kulian2e751b82016-03-16 16:59:32 -0700929 /** Sets the original minimal width and height. */
930 private void setMinDimensions(ActivityInfo info) {
931 if (info != null && info.windowLayout != null) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700932 mMinWidth = info.windowLayout.minWidth;
933 mMinHeight = info.windowLayout.minHeight;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700934 } else {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700935 mMinWidth = INVALID_MIN_SIZE;
936 mMinHeight = INVALID_MIN_SIZE;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700937 }
938 }
939
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800940 /**
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700941 * Return true if the input activity has the same intent filter as the intent this task
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800942 * record is based on (normally the root activity intent).
943 */
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700944 boolean isSameIntentFilter(ActivityRecord r) {
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800945 final Intent intent = new Intent(r.intent);
Louis Chang23df1a62019-01-09 15:10:49 +0800946 // Make sure the component are the same if the input activity has the same real activity
947 // as the one in the task because either one of them could be the alias activity.
948 if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) {
949 intent.setComponent(this.intent.getComponent());
950 }
Bryce Lee1a990e52018-04-23 10:54:11 -0700951 return intent.filterEquals(this.intent);
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800952 }
953
Wale Ogunwale66e16852017-10-19 13:35:52 -0700954 boolean returnsToHomeStack() {
955 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
Bryce Lee1a990e52018-04-23 10:54:11 -0700956 return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700957 }
958
Craig Mautnera228ae92014-07-09 05:44:55 -0700959 void setPrevAffiliate(TaskRecord prevAffiliate) {
960 mPrevAffiliate = prevAffiliate;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700961 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.mTaskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700962 }
963
964 void setNextAffiliate(TaskRecord nextAffiliate) {
965 mNextAffiliate = nextAffiliate;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700966 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700967 }
968
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700969 <T extends ActivityStack> T getStack() {
970 return (T) mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700971 }
972
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800973 /**
974 * Must be used for setting parent stack because it performs configuration updates.
975 * Must be called after adding task as a child to the stack.
976 */
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200977 // TODO(task-unify): Remove or rework after task level unification.
Andrii Kulian02b7a832016-10-06 23:11:56 -0700978 void setStack(ActivityStack stack) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800979 if (stack != null && !stack.isInStackLocked(this)) {
980 throw new IllegalStateException("Task must be added as a Stack child first.");
981 }
Bryce Lee84730a02018-04-03 14:10:04 -0700982 final ActivityStack oldStack = mStack;
Andrii Kulian02b7a832016-10-06 23:11:56 -0700983 mStack = stack;
Bryce Lee84730a02018-04-03 14:10:04 -0700984
985 // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
986 // {@link ActivityRecord} from its current {@link ActivityStack}.
987
988 if (oldStack != mStack) {
989 for (int i = getChildCount() - 1; i >= 0; --i) {
990 final ActivityRecord activity = getChildAt(i);
991
992 if (oldStack != null) {
993 oldStack.onActivityRemovedFromStack(activity);
994 }
995
996 if (mStack != null) {
997 stack.onActivityAddedToStack(activity);
998 }
999 }
1000 }
1001
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001002 onParentChanged(mStack, oldStack);
Andrii Kulian02b7a832016-10-06 23:11:56 -07001003 }
1004
1005 /**
1006 * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
1007 */
1008 int getStackId() {
1009 return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
1010 }
1011
Andrii Kulian1779e612016-10-12 21:58:25 -07001012 @Override
1013 protected int getChildCount() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001014 return mActivities.size();
Andrii Kulian1779e612016-10-12 21:58:25 -07001015 }
1016
1017 @Override
chaviw82a0ba82018-03-15 14:26:29 -07001018 protected ActivityRecord getChildAt(int index) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001019 return mActivities.get(index);
Andrii Kulian1779e612016-10-12 21:58:25 -07001020 }
1021
1022 @Override
1023 protected ConfigurationContainer getParent() {
1024 return mStack;
1025 }
1026
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001027 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001028 protected void onParentChanged(
1029 ConfigurationContainer newParent, ConfigurationContainer oldParent) {
1030 super.onParentChanged(newParent, oldParent);
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001031 mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
Andrii Kulianfb1bf692017-01-17 11:17:34 -08001032 }
1033
Craig Mautnera228ae92014-07-09 05:44:55 -07001034 // Close up recents linked list.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07001035 private void closeRecentsChain() {
Craig Mautnera228ae92014-07-09 05:44:55 -07001036 if (mPrevAffiliate != null) {
1037 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
1038 }
1039 if (mNextAffiliate != null) {
1040 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
1041 }
1042 setPrevAffiliate(null);
1043 setNextAffiliate(null);
1044 }
1045
Winson Chung740c3ac2014-11-12 16:14:38 -08001046 void removedFromRecents() {
Dianne Hackborn852975d2014-08-22 17:42:43 -07001047 closeRecentsChain();
1048 if (inRecents) {
1049 inRecents = false;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001050 mAtmService.notifyTaskPersisterLocked(this, false);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001051 }
Jorim Jaggif9084ec2017-01-16 13:16:59 +01001052
Dianne Hackborn68a06332017-11-15 17:54:18 -08001053 clearRootProcess();
1054
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001055 mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
1056 mTaskId, mUserId);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001057 }
1058
Craig Mautnera228ae92014-07-09 05:44:55 -07001059 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
1060 closeRecentsChain();
1061 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
Winson Chungec396d62014-08-06 17:08:00 -07001062 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
Craig Mautnera228ae92014-07-09 05:44:55 -07001063 // Find the end
1064 while (taskToAffiliateWith.mNextAffiliate != null) {
1065 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate;
1066 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1067 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1068 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1069 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1070 nextRecents.setPrevAffiliate(null);
1071 }
1072 taskToAffiliateWith.setNextAffiliate(null);
1073 break;
1074 }
1075 taskToAffiliateWith = nextRecents;
1076 }
1077 taskToAffiliateWith.setNextAffiliate(this);
1078 setPrevAffiliate(taskToAffiliateWith);
1079 setNextAffiliate(null);
1080 }
1081
Winson Chung1147c402014-05-14 11:05:00 -07001082 /** Returns the intent for the root activity for this task */
1083 Intent getBaseIntent() {
1084 return intent != null ? intent : affinityIntent;
1085 }
1086
Andrii Kulian39f27442019-06-26 19:09:19 -07001087 /** Returns the first non-finishing activity from the bottom. */
Winson Chung3b3f4642014-04-22 10:08:18 -07001088 ActivityRecord getRootActivity() {
Andrii Kulian39f27442019-06-26 19:09:19 -07001089 final int rootActivityIndex = findRootIndex(false /* effectiveRoot */);
1090 if (rootActivityIndex == -1) {
1091 // There are no non-finishing activities in the task.
1092 return null;
Winson Chung3b3f4642014-04-22 10:08:18 -07001093 }
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001094 return getChildAt(rootActivityIndex);
Winson Chung3b3f4642014-04-22 10:08:18 -07001095 }
1096
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001097 ActivityRecord getTopActivity() {
Bryce Lee9f6affd2017-09-01 09:18:35 -07001098 return getTopActivity(true /* includeOverlays */);
1099 }
1100
1101 ActivityRecord getTopActivity(boolean includeOverlays) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001102 for (int i = getChildCount() - 1; i >= 0; --i) {
1103 final ActivityRecord r = getChildAt(i);
Bryce Lee9f6affd2017-09-01 09:18:35 -07001104 if (r.finishing || (!includeOverlays && r.mTaskOverlay)) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001105 continue;
1106 }
1107 return r;
1108 }
1109 return null;
1110 }
1111
Filip Gruszczynski3e85ba22015-10-05 22:48:30 -07001112 ActivityRecord topRunningActivityLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001113 if (mStack != null) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001114 for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
1115 ActivityRecord r = getChildAt(activityNdx);
Chong Zhang87761972016-08-22 13:53:24 -07001116 if (!r.finishing && r.okToShowLocked()) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001117 return r;
1118 }
Craig Mautner6b74cb52013-09-27 17:02:21 -07001119 }
1120 }
1121 return null;
1122 }
1123
Jorim Jaggi172e99f2017-10-20 14:33:18 +02001124 boolean isVisible() {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001125 for (int i = getChildCount() - 1; i >= 0; --i) {
1126 final ActivityRecord r = getChildAt(i);
Jorim Jaggi172e99f2017-10-20 14:33:18 +02001127 if (r.visible) {
1128 return true;
1129 }
1130 }
1131 return false;
1132 }
1133
Ricky Waib147fa12019-04-25 16:08:30 +01001134 /**
1135 * Return true if any activities in this task belongs to input uid.
1136 */
1137 boolean containsAppUid(int uid) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001138 for (int i = getChildCount() - 1; i >= 0; --i) {
1139 final ActivityRecord r = getChildAt(i);
Ricky Waib147fa12019-04-25 16:08:30 +01001140 if (r.getUid() == uid) {
1141 return true;
1142 }
1143 }
1144 return false;
1145 }
1146
Jorim Jaggiea039a82017-08-02 14:37:49 +02001147 void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
1148 if (mStack != null) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001149 for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
1150 ActivityRecord r = getChildAt(activityNdx);
Jorim Jaggi02f1d2f2017-08-04 14:29:16 +02001151 if (!r.finishing && r.okToShowLocked() && r.visibleIgnoringKeyguard) {
Jorim Jaggiea039a82017-08-02 14:37:49 +02001152 outActivities.add(r);
1153 }
1154 }
1155 }
1156 }
1157
Wale Ogunwale3b232392016-05-13 15:37:13 -07001158 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001159 if (mStack != null) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001160 for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
1161 ActivityRecord r = getChildAt(activityNdx);
Wale Ogunwale3b232392016-05-13 15:37:13 -07001162 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
Chong Zhang87761972016-08-22 13:53:24 -07001163 || r.finishing || !r.okToShowLocked()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001164 continue;
1165 }
1166 return r;
1167 }
1168 }
1169 return null;
1170 }
1171
Winson Chung61c9e5a2017-10-11 10:39:32 -07001172 /**
1173 * Return the number of running activities, and the number of non-finishing/initializing
1174 * activities in the provided {@param reportOut} respectively.
1175 */
1176 void getNumRunningActivities(TaskActivitiesReport reportOut) {
1177 reportOut.reset();
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001178 for (int i = getChildCount() - 1; i >= 0; --i) {
1179 final ActivityRecord r = getChildAt(i);
Winson Chung61c9e5a2017-10-11 10:39:32 -07001180 if (r.finishing) {
1181 continue;
1182 }
1183
1184 reportOut.base = r;
1185
1186 // Increment the total number of non-finishing activities
1187 reportOut.numActivities++;
1188
Bryce Lee7ace3952018-02-16 14:34:32 -08001189 if (reportOut.top == null || (reportOut.top.isState(ActivityState.INITIALIZING))) {
Winson Chung61c9e5a2017-10-11 10:39:32 -07001190 reportOut.top = r;
1191 // Reset the number of running activities until we hit the first non-initializing
1192 // activity
1193 reportOut.numRunning = 0;
1194 }
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07001195 if (r.attachedToProcess()) {
Winson Chung61c9e5a2017-10-11 10:39:32 -07001196 // Increment the number of actually running activities
1197 reportOut.numRunning++;
1198 }
1199 }
1200 }
1201
Chong Zhang87761972016-08-22 13:53:24 -07001202 boolean okToShowLocked() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001203 // NOTE: If {@link TaskRecord#topRunningActivity} return is not null then it is
Chong Zhang87761972016-08-22 13:53:24 -07001204 // okay to show the activity when locked.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001205 return mAtmService.mStackSupervisor.isCurrentProfileLocked(mUserId)
Chong Zhang87761972016-08-22 13:53:24 -07001206 || topRunningActivityLocked() != null;
1207 }
1208
Craig Mautnerde4ef022013-04-07 19:01:33 -07001209 /**
Craig Mautner3b475fe2013-12-16 15:58:31 -08001210 * Reorder the history stack so that the passed activity is brought to the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001211 */
1212 final void moveActivityToFrontLocked(ActivityRecord newTop) {
Wale Ogunwale0fc365c2015-05-25 19:35:42 -07001213 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
1214 "Removing and adding activity " + newTop
1215 + " to stack at top callers=" + Debug.getCallers(4));
Craig Mautnerde4ef022013-04-07 19:01:33 -07001216
Craig Mautnerde4ef022013-04-07 19:01:33 -07001217 mActivities.remove(newTop);
1218 mActivities.add(newTop);
Bryce Leed58d7b32017-09-08 15:55:22 -07001219
1220 // Make sure window manager is aware of the position change.
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001221 mTask.positionChildAtTop(newTop);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001222 updateEffectiveIntent();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001223 }
1224
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001225 @Override
Wale Ogunwaleeea34ee92017-08-31 20:07:45 -07001226 /*@WindowConfiguration.ActivityType*/
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001227 public int getActivityType() {
1228 final int applicationType = super.getActivityType();
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001229 if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001230 return applicationType;
1231 }
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001232 return getChildAt(0).getActivityType();
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001233 }
1234
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001235 /** Called when a Task child is added from the Task.java side. */
1236 // TODO(task-unify): Just override addChild to do what is needed when someone calls to add a
1237 // child.
1238 void onChildAdded(ActivityRecord r, int index) {
1239 r.inHistory = true;
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001240
Craig Mautner6170f732013-04-02 13:05:23 -07001241 // 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 -08001242 if (!mActivities.remove(r) && r.occludesParent()) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001243 // Was not previously in list.
1244 numFullscreen++;
1245 }
Craig Mautner2c1faed2013-07-23 12:56:02 -07001246 // Only set this based on the first activity
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001247 if (!hasChild()) {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001248 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1249 // Normally non-standard activity type for the activity record will be set when the
1250 // object is created, however we delay setting the standard application type until
1251 // this point so that the task can set the type for additional activities added in
1252 // the else condition below.
1253 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1254 }
1255 setActivityType(r.getActivityType());
Craig Mautner21d24a22014-04-23 11:45:37 -07001256 isPersistable = r.isPersistable();
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001257 mCallingUid = r.launchedFromUid;
1258 mCallingPackage = r.launchedFromPackage;
Dianne Hackborn852975d2014-08-22 17:42:43 -07001259 // Clamp to [1, max].
1260 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
Wale Ogunwale65ebd952018-04-25 15:41:44 -07001261 ActivityTaskManager.getMaxAppRecentsLimitStatic());
Craig Mautner2c1faed2013-07-23 12:56:02 -07001262 } else {
1263 // Otherwise make all added activities match this one.
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001264 r.setActivityType(getActivityType());
Craig Mautner78733002013-06-10 13:54:49 -07001265 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001266
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001267 final int size = getChildCount();
Wale Ogunwale3b232392016-05-13 15:37:13 -07001268
1269 if (index == size && size > 0) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001270 final ActivityRecord top = getChildAt(size - 1);
Wale Ogunwale3b232392016-05-13 15:37:13 -07001271 if (top.mTaskOverlay) {
1272 // Place below the task overlay activity since the overlay activity should always
1273 // be on top.
1274 index--;
1275 }
1276 }
1277
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001278 index = Math.min(size, index);
Craig Mautner77878772013-03-04 19:46:24 -08001279 mActivities.add(index, r);
Bryce Lee84730a02018-04-03 14:10:04 -07001280
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001281 updateEffectiveIntent();
Craig Mautner21d24a22014-04-23 11:45:37 -07001282 if (r.isPersistable()) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001283 mAtmService.notifyTaskPersisterLocked(this, false);
Craig Mautner21d24a22014-04-23 11:45:37 -07001284 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001285
David Stevens82ea6cb2017-03-03 16:18:50 -08001286 // Make sure the list of display UID whitelists is updated
1287 // now that this record is in a new task.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001288 mAtmService.mRootActivityContainer.updateUIDsPresentOnDisplay();
Craig Mautner77878772013-03-04 19:46:24 -08001289 }
1290
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001291 // TODO(task-unify): Merge onChildAdded method below into this since task will be a single
1292 // object.
1293 void addChild(ActivityRecord r) {
1294 if (r.getParent() != null) {
1295 // Shouldn't already have a parent since we are just adding to the task...
1296 throw new IllegalStateException(
1297 "r=" + r + " parent=" + r.getParent() + " task=" + this);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001298 }
1299
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001300 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
1301 // This means the activity isn't attached to Task.java yet. Go ahead and do that.
1302 // TODO(task-unify): Remove/call super once we unify task level.
1303 if (mTask != null) {
1304 mTask.addChild(r, Integer.MAX_VALUE /* add on top */);
1305 } else {
1306 onChildAdded(r, Integer.MAX_VALUE);
1307 }
1308 }
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001309
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001310 /** Called when a Task child is removed from the Task.java side. */
1311 // TODO(task-unify): Just override removeChild to do what is needed when someone calls to remove
1312 // a child.
1313 void onChildRemoved(ActivityRecord r) {
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001314 if (mActivities.remove(r) && r.occludesParent()) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001315 // Was previously in list.
1316 numFullscreen--;
1317 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001318 if (r.isPersistable()) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001319 mAtmService.notifyTaskPersisterLocked(this, false);
Craig Mautner21d24a22014-04-23 11:45:37 -07001320 }
Wale Ogunwale89182d52016-03-11 10:38:36 -08001321
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001322 if (inPinnedWindowingMode()) {
Wale Ogunwale89182d52016-03-11 10:38:36 -08001323 // We normally notify listeners of task stack changes on pause, however pinned stack
1324 // activities are normally in the paused state so no notification will be sent there
1325 // before the activity is removed. We send it here so instead.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001326 mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
Wale Ogunwale89182d52016-03-11 10:38:36 -08001327 }
1328
Wale Ogunwalec17418e2019-10-13 23:00:40 +02001329 if (hasChild()) {
1330 updateEffectiveIntent();
1331
1332 // The following block can be executed multiple times if there is more than one overlay.
1333 // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
1334 // of the task by id and exiting early if not found.
1335 if (onlyHasTaskOverlayActivities(false /* excludingFinishing */)) {
1336 // When destroying a task, tell the supervisor to remove it so that any activity it
1337 // has can be cleaned up correctly. This is currently the only place where we remove
1338 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
1339 // state into removeTask(), we just clear the task here before the other residual
1340 // work.
1341 // TODO: If the callers to removeTask() changes such that we have multiple places
1342 // where we are destroying the task, move this back into removeTask()
1343 mAtmService.mStackSupervisor.removeTaskByIdLocked(mTaskId, false /* killProcess */,
1344 !REMOVE_FROM_RECENTS, "onChildRemoved");
1345 }
1346 } else if (!mReuseTask) {
1347 // Remove entire task if it doesn't have any activity left and it isn't marked for reuse
1348 mStack.removeTask(this, "onChildRemoved", REMOVE_TASK_MODE_DESTROYING);
Craig Mautner41326202014-06-20 14:38:21 -07001349 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001350 }
1351
Winson Chung6954fc92017-03-24 16:22:12 -07001352 /**
1353 * @return whether or not there are ONLY task overlay activities in the stack.
1354 * If {@param excludeFinishing} is set, then ignore finishing activities in the check.
1355 * If there are no task overlay activities, this call returns false.
1356 */
1357 boolean onlyHasTaskOverlayActivities(boolean excludeFinishing) {
1358 int count = 0;
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001359 for (int i = getChildCount() - 1; i >= 0; i--) {
1360 final ActivityRecord r = getChildAt(i);
Winson Chung6954fc92017-03-24 16:22:12 -07001361 if (excludeFinishing && r.finishing) {
1362 continue;
1363 }
1364 if (!r.mTaskOverlay) {
1365 return false;
1366 }
1367 count++;
1368 }
1369 return count > 0;
1370 }
1371
Craig Mautner41db4a72014-05-07 17:20:56 -07001372 boolean autoRemoveFromRecents() {
Dianne Hackbornd38aed82014-06-10 21:36:35 -07001373 // We will automatically remove the task either if it has explicitly asked for
1374 // this, or it is empty and has never contained an activity that got shown to
1375 // the user.
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001376 return autoRemoveRecents || (!hasChild() && !hasBeenVisible);
Craig Mautner41db4a72014-05-07 17:20:56 -07001377 }
1378
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001379 /**
1380 * Completely remove all activities associated with an existing
1381 * task starting at a specified index.
1382 */
Louis Chang7b03ad92019-08-21 12:32:33 +08001383 final void performClearTaskAtIndexLocked(int activityNdx, String reason) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001384 int numActivities = getChildCount();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001385 for ( ; activityNdx < numActivities; ++activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001386 final ActivityRecord r = getChildAt(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001387 if (r.finishing) {
1388 continue;
1389 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001390 if (mStack == null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001391 // Task was restored from persistent storage.
1392 r.takeFromHistory();
1393 mActivities.remove(activityNdx);
1394 --activityNdx;
1395 --numActivities;
Louis Chang7b03ad92019-08-21 12:32:33 +08001396 } else if (r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
1397 false /* oomAdj */)
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001398 == FINISH_RESULT_REMOVED) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001399 --activityNdx;
1400 --numActivities;
1401 }
1402 }
1403 }
1404
1405 /**
1406 * Completely remove all activities associated with an existing task.
1407 */
Benjamin Franza83859f2017-07-03 16:34:14 +01001408 void performClearTaskLocked() {
Craig Mautner362449a2014-06-20 14:04:39 -07001409 mReuseTask = true;
Louis Chang7b03ad92019-08-21 12:32:33 +08001410 performClearTaskAtIndexLocked(0, "clear-task-all");
Craig Mautner362449a2014-06-20 14:04:39 -07001411 mReuseTask = false;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001412 }
1413
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -08001414 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1415 mReuseTask = true;
1416 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1417 mReuseTask = false;
1418 return result;
1419 }
1420
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001421 /**
1422 * Perform clear operation as requested by
1423 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1424 * stack to the given task, then look for
1425 * an instance of that activity in the stack and, if found, finish all
1426 * activities on top of it and return the instance.
1427 *
1428 * @param newR Description of the new activity being started.
1429 * @return Returns the old activity that should be continued to be used,
1430 * or null if none was found.
1431 */
1432 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001433 int numActivities = getChildCount();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001434 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001435 ActivityRecord r = getChildAt(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001436 if (r.finishing) {
1437 continue;
1438 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001439 if (r.mActivityComponent.equals(newR.mActivityComponent)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001440 // Here it is! Now finish everything in front...
Craig Mautner1602ec22013-05-12 10:24:27 -07001441 final ActivityRecord ret = r;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001442
1443 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001444 r = getChildAt(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001445 if (r.finishing) {
1446 continue;
1447 }
Jorim Jaggi346702a2019-05-08 17:49:33 +02001448 ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001449 if (opts != null) {
1450 ret.updateOptionsLocked(opts);
1451 }
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001452 if (r.finishIfPossible("clear-task-stack", false /* oomAdj */)
1453 == FINISH_RESULT_REMOVED) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001454 --activityNdx;
1455 --numActivities;
1456 }
1457 }
1458
1459 // Finally, if this is a normal launch mode (that is, not
1460 // expecting onNewIntent()), then we will finish the current
1461 // instance of the activity so a new fresh one can be started.
1462 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
Daichi Hirono15a02992016-04-27 18:47:01 +09001463 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1464 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001465 if (!ret.finishing) {
Andrii Kulian7dd39bb2019-07-22 13:11:10 -07001466 ret.finishIfPossible("clear-task-top", false /* oomAdj */);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001467 return null;
1468 }
1469 }
1470
1471 return ret;
1472 }
1473 }
1474
1475 return null;
1476 }
1477
Louis Chang7b03ad92019-08-21 12:32:33 +08001478 void removeTaskActivitiesLocked(String reason) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001479 // Just remove the entire task.
Louis Chang7b03ad92019-08-21 12:32:33 +08001480 performClearTaskAtIndexLocked(0, reason);
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001481 }
1482
Craig Mautner432f64e2015-05-20 14:59:57 -07001483 String lockTaskAuthToString() {
1484 switch (mLockTaskAuth) {
1485 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1486 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1487 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1488 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
Benjamin Franz469dd582015-06-09 14:24:36 +01001489 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
Craig Mautner432f64e2015-05-20 14:59:57 -07001490 default: return "unknown=" + mLockTaskAuth;
1491 }
1492 }
1493
Craig Mautner15df08a2015-04-01 12:17:18 -07001494 void setLockTaskAuth() {
Charles He2bf28322017-10-12 22:24:49 +01001495 setLockTaskAuth(getRootActivity());
1496 }
1497
1498 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1499 if (r == null) {
1500 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1501 return;
1502 }
1503
Charles He520b2832017-09-02 15:27:16 +01001504 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001505 final LockTaskController lockTaskController = mAtmService.getLockTaskController();
Charles He2bf28322017-10-12 22:24:49 +01001506 switch (r.lockTaskLaunchMode) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001507 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001508 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
Charles He520b2832017-09-02 15:27:16 +01001509 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001510 break;
1511
1512 case LOCK_TASK_LAUNCH_MODE_NEVER:
Benjamin Franz469dd582015-06-09 14:24:36 +01001513 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
Craig Mautner15df08a2015-04-01 12:17:18 -07001514 break;
1515
1516 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
Benjamin Franz469dd582015-06-09 14:24:36 +01001517 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
Craig Mautner15df08a2015-04-01 12:17:18 -07001518 break;
1519
1520 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001521 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
Charles He520b2832017-09-02 15:27:16 +01001522 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
Craig Mautner15df08a2015-04-01 12:17:18 -07001523 break;
1524 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001525 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this +
1526 " mLockTaskAuth=" + lockTaskAuthToString());
Craig Mautner15df08a2015-04-01 12:17:18 -07001527 }
1528
Winson Chungd3395382016-12-13 11:49:09 -08001529 private boolean isResizeable(boolean checkSupportsPip) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001530 return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001531 || (checkSupportsPip && mSupportsPictureInPicture));
Winson Chungd3395382016-12-13 11:49:09 -08001532 }
1533
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001534 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08001535 return isResizeable(true /* checkSupportsPip */);
1536 }
1537
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001538 @Override
1539 public boolean supportsSplitScreenWindowingMode() {
Winson Chungd3395382016-12-13 11:49:09 -08001540 // A task can not be docked even if it is considered resizeable because it only supports
1541 // picture-in-picture mode but has a non-resizeable resizeMode
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001542 return super.supportsSplitScreenWindowingMode()
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001543 && mAtmService.mSupportsSplitScreenMultiWindow
1544 && (mAtmService.mForceResizableActivities
Bryce Leec857a5b2017-08-16 10:04:52 -07001545 || (isResizeable(false /* checkSupportsPip */)
1546 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001547 }
1548
skuhne@google.com322347b2016-12-02 12:54:03 -08001549 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001550 * Check whether this task can be launched on the specified display.
Riddle Hsu16567132018-08-16 21:37:47 +08001551 *
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001552 * @param displayId Target display id.
Riddle Hsu16567132018-08-16 21:37:47 +08001553 * @return {@code true} if either it is the default display or this activity can be put on a
1554 * secondary display.
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001555 */
1556 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001557 return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Riddle Hsu16567132018-08-16 21:37:47 +08001558 -1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001559 }
1560
1561 /**
skuhne@google.com322347b2016-12-02 12:54:03 -08001562 * Check that a given bounds matches the application requested orientation.
1563 *
1564 * @param bounds The bounds to be tested.
1565 * @return True if the requested bounds are okay for a resizing request.
1566 */
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001567 private boolean canResizeToBounds(Rect bounds) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001568 if (bounds == null || !inFreeformWindowingMode()) {
skuhne@google.com322347b2016-12-02 12:54:03 -08001569 // Note: If not on the freeform workspace, we ignore the bounds.
1570 return true;
1571 }
1572 final boolean landscape = bounds.width() > bounds.height();
Evan Roskydfe3da72018-10-26 17:21:06 -07001573 final Rect configBounds = getRequestedOverrideBounds();
skuhne@google.com322347b2016-12-02 12:54:03 -08001574 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001575 return configBounds.isEmpty()
1576 || landscape == (configBounds.width() > configBounds.height());
skuhne@google.com322347b2016-12-02 12:54:03 -08001577 }
1578 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1579 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1580 }
1581
Craig Mautner525f3d92013-05-07 14:01:50 -07001582 /**
Yorke Leebdef5372017-04-10 16:38:51 -07001583 * @return {@code true} if the task is being cleared for the purposes of being reused.
1584 */
1585 boolean isClearingToReuseTask() {
1586 return mReuseTask;
1587 }
1588
1589 /**
Craig Mautner525f3d92013-05-07 14:01:50 -07001590 * Find the activity in the history stack within the given task. Returns
1591 * the index within the history at which it's found, or < 0 if not found.
1592 */
1593 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001594 final ComponentName realActivity = r.mActivityComponent;
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001595 for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
1596 ActivityRecord candidate = getChildAt(activityNdx);
Craig Mautner525f3d92013-05-07 14:01:50 -07001597 if (candidate.finishing) {
1598 continue;
1599 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001600 if (candidate.mActivityComponent.equals(realActivity)) {
Craig Mautner525f3d92013-05-07 14:01:50 -07001601 return candidate;
1602 }
1603 }
1604 return null;
1605 }
1606
Winson Chunga449dc02014-05-16 11:15:04 -07001607 /** Updates the last task description values. */
1608 void updateTaskDescription() {
Andrii Kulian39f27442019-06-26 19:09:19 -07001609 // TODO(AM refactor): Cleanup to use findRootIndex()
Winson Chunga449dc02014-05-16 11:15:04 -07001610 // Traverse upwards looking for any break between main task activities and
1611 // utility activities.
1612 int activityNdx;
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001613 final int numActivities = getChildCount();
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001614 final boolean relinquish = numActivities != 0 &&
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001615 (getChildAt(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001616 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
Craig Mautner21d24a22014-04-23 11:45:37 -07001617 ++activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001618 final ActivityRecord r = getChildAt(activityNdx);
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001619 if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001620 // This will be the top activity for determining taskDescription. Pre-inc to
1621 // overcome initial decrement below.
1622 ++activityNdx;
1623 break;
1624 }
Winson Chunga449dc02014-05-16 11:15:04 -07001625 if (r.intent != null &&
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001626 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
Winson Chunga449dc02014-05-16 11:15:04 -07001627 break;
1628 }
1629 }
1630 if (activityNdx > 0) {
1631 // Traverse downwards starting below break looking for set label, icon.
1632 // Note that if there are activities in the task but none of them set the
1633 // recent activity values, then we do not fall back to the last set
1634 // values in the TaskRecord.
1635 String label = null;
Craig Mautner648f69b2014-09-18 14:16:26 -07001636 String iconFilename = null;
Matthew Ng54bc9422017-10-02 17:16:28 -07001637 int iconResource = -1;
Winson Chunga449dc02014-05-16 11:15:04 -07001638 int colorPrimary = 0;
Winson Chung1af8eda2016-02-05 17:55:56 +00001639 int colorBackground = 0;
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001640 int statusBarColor = 0;
1641 int navigationBarColor = 0;
Adrian Roos4c864592019-04-10 14:47:57 +02001642 boolean statusBarContrastWhenTransparent = false;
1643 boolean navigationBarContrastWhenTransparent = false;
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001644 boolean topActivity = true;
Winson Chunga449dc02014-05-16 11:15:04 -07001645 for (--activityNdx; activityNdx >= 0; --activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001646 final ActivityRecord r = getChildAt(activityNdx);
Winson Chung80f80db2018-05-30 21:13:25 -07001647 if (r.mTaskOverlay) {
1648 continue;
1649 }
Winson Chunga449dc02014-05-16 11:15:04 -07001650 if (r.taskDescription != null) {
1651 if (label == null) {
1652 label = r.taskDescription.getLabel();
1653 }
Matthew Ng54bc9422017-10-02 17:16:28 -07001654 if (iconResource == -1) {
1655 iconResource = r.taskDescription.getIconResource();
1656 }
Craig Mautner648f69b2014-09-18 14:16:26 -07001657 if (iconFilename == null) {
1658 iconFilename = r.taskDescription.getIconFilename();
Winson Chunga449dc02014-05-16 11:15:04 -07001659 }
1660 if (colorPrimary == 0) {
1661 colorPrimary = r.taskDescription.getPrimaryColor();
Winson Chunga449dc02014-05-16 11:15:04 -07001662 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001663 if (topActivity) {
Winson Chung1af8eda2016-02-05 17:55:56 +00001664 colorBackground = r.taskDescription.getBackgroundColor();
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001665 statusBarColor = r.taskDescription.getStatusBarColor();
1666 navigationBarColor = r.taskDescription.getNavigationBarColor();
Adrian Roos4c864592019-04-10 14:47:57 +02001667 statusBarContrastWhenTransparent =
1668 r.taskDescription.getEnsureStatusBarContrastWhenTransparent();
1669 navigationBarContrastWhenTransparent =
1670 r.taskDescription.getEnsureNavigationBarContrastWhenTransparent();
Winson Chung1af8eda2016-02-05 17:55:56 +00001671 }
Winson Chunga449dc02014-05-16 11:15:04 -07001672 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001673 topActivity = false;
Winson Chunga449dc02014-05-16 11:15:04 -07001674 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001675 mTaskDescription = new TaskDescription(label, null, iconResource, iconFilename,
Adrian Roos4c864592019-04-10 14:47:57 +02001676 colorPrimary, colorBackground, statusBarColor, navigationBarColor,
1677 statusBarContrastWhenTransparent, navigationBarContrastWhenTransparent);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001678 if (mTask != null) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001679 mTask.setTaskDescription(mTaskDescription);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001680 }
Winson Chungec396d62014-08-06 17:08:00 -07001681 // Update the task affiliation color if we are the parent of the group
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001682 if (mTaskId == mAffiliatedTaskId) {
1683 mAffiliatedTaskColor = mTaskDescription.getPrimaryColor();
Winson Chungec396d62014-08-06 17:08:00 -07001684 }
Winson Chunga449dc02014-05-16 11:15:04 -07001685 }
1686 }
1687
Andrii Kulian39f27442019-06-26 19:09:19 -07001688 /**
1689 * Find the index of the root activity in the task. It will be the first activity from the
1690 * bottom that is not finishing.
1691 *
1692 * @param effectiveRoot Flag indicating whether 'effective root' should be returned - an
1693 * activity that defines the task identity (its base intent). It's the
1694 * first one that does not have
1695 * {@link ActivityInfo#FLAG_RELINQUISH_TASK_IDENTITY}.
1696 * @return index of the 'root' or 'effective' root in the list of activities, -1 if no eligible
1697 * activity was found.
1698 */
1699 int findRootIndex(boolean effectiveRoot) {
1700 int effectiveNdx = -1;
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001701 final int topActivityNdx = getChildCount() - 1;
Dianne Hackborn39569af2014-09-23 10:56:58 -07001702 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001703 final ActivityRecord r = getChildAt(activityNdx);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001704 if (r.finishing) {
1705 continue;
1706 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001707 effectiveNdx = activityNdx;
Andrii Kulian39f27442019-06-26 19:09:19 -07001708 if (!effectiveRoot || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001709 break;
1710 }
1711 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001712 return effectiveNdx;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001713 }
1714
Andrii Kulian39f27442019-06-26 19:09:19 -07001715 // TODO (AM refactor): Invoke automatically when there is a change in children
1716 @VisibleForTesting
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001717 void updateEffectiveIntent() {
Andrii Kulian39f27442019-06-26 19:09:19 -07001718 int effectiveRootIndex = findRootIndex(true /* effectiveRoot */);
1719 if (effectiveRootIndex == -1) {
1720 // All activities in the task are either finishing or relinquish task identity.
1721 // But we still want to update the intent, so let's use the bottom activity.
1722 effectiveRootIndex = 0;
1723 }
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001724 final ActivityRecord r = getChildAt(effectiveRootIndex);
Winson Chungfee26772014-08-05 12:21:52 -07001725 setIntent(r);
Winson Chung8d9009e2017-11-16 15:43:05 -08001726
1727 // Update the task description when the activities change
1728 updateTaskDescription();
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001729 }
1730
Evan Rosky730f6e82018-12-03 17:40:11 -08001731 void adjustForMinimalTaskDimensions(Rect bounds, Rect previousBounds) {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001732 if (bounds == null) {
1733 return;
1734 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001735 int minWidth = mMinWidth;
1736 int minHeight = mMinHeight;
Robert Carr9c5867d2016-03-10 15:52:46 -08001737 // If the task has no requested minimal size, we'd like to enforce a minimal size
1738 // so that the user can not render the task too small to manipulate. We don't need
1739 // to do this for the pinned stack as the bounds are controlled by the system.
Evan Rosky1ac84462018-11-13 11:25:30 -08001740 if (!inPinnedWindowingMode() && mStack != null) {
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001741 final int defaultMinSizeDp =
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001742 mAtmService.mRootActivityContainer.mDefaultMinSizeOfResizeableTaskDp;
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001743 final ActivityDisplay display =
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001744 mAtmService.mRootActivityContainer.getActivityDisplay(mStack.mDisplayId);
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001745 final float density =
1746 (float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
1747 final int defaultMinSize = (int) (defaultMinSizeDp * density);
1748
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001749 if (minWidth == INVALID_MIN_SIZE) {
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001750 minWidth = defaultMinSize;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001751 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001752 if (minHeight == INVALID_MIN_SIZE) {
Garfield Tan4a48a7f2018-10-02 14:23:55 -07001753 minHeight = defaultMinSize;
Andrii Kulian2e751b82016-03-16 16:59:32 -07001754 }
Robert Carr9c5867d2016-03-10 15:52:46 -08001755 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001756 final boolean adjustWidth = minWidth > bounds.width();
1757 final boolean adjustHeight = minHeight > bounds.height();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001758 if (!(adjustWidth || adjustHeight)) {
1759 return;
1760 }
1761
1762 if (adjustWidth) {
Garfield Tan020607d2018-12-17 17:01:58 -08001763 if (!previousBounds.isEmpty() && bounds.right == previousBounds.right) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001764 bounds.left = bounds.right - minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001765 } else {
1766 // Either left bounds match, or neither match, or the previous bounds were
1767 // fullscreen and we default to keeping left.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001768 bounds.right = bounds.left + minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001769 }
1770 }
1771 if (adjustHeight) {
Garfield Tan020607d2018-12-17 17:01:58 -08001772 if (!previousBounds.isEmpty() && bounds.bottom == previousBounds.bottom) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001773 bounds.top = bounds.bottom - minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001774 } else {
1775 // Either top bounds match, or neither match, or the previous bounds were
1776 // fullscreen and we default to keeping top.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001777 bounds.bottom = bounds.top + minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08001778 }
1779 }
1780 }
1781
Evan Rosky9ba524e2018-01-03 16:27:56 -08001782 void setLastNonFullscreenBounds(Rect bounds) {
1783 if (mLastNonFullscreenBounds == null) {
1784 mLastNonFullscreenBounds = new Rect(bounds);
1785 } else {
1786 mLastNonFullscreenBounds.set(bounds);
1787 }
1788 }
1789
Jorim Jaggi0a932142016-02-01 17:42:25 -08001790 /**
Bryce Leec4ab62a2018-03-05 14:19:26 -08001791 * This should be called when an child activity changes state. This should only
1792 * be called from
1793 * {@link ActivityRecord#setState(ActivityState, String)} .
1794 * @param record The {@link ActivityRecord} whose state has changed.
1795 * @param state The new state.
1796 * @param reason The reason for the change.
1797 */
1798 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
1799 final ActivityStack parent = getStack();
1800
1801 if (parent != null) {
1802 parent.onActivityStateChanged(record, state, reason);
1803 }
1804 }
1805
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001806 @Override
1807 public void onConfigurationChanged(Configuration newParentConfig) {
Evan Rosky730f6e82018-12-03 17:40:11 -08001808 // Check if the new configuration supports persistent bounds (eg. is Freeform) and if so
1809 // restore the last recorded non-fullscreen bounds.
1810 final boolean prevPersistTaskBounds = getWindowConfiguration().persistTaskBounds();
1811 final boolean nextPersistTaskBounds =
1812 getRequestedOverrideConfiguration().windowConfiguration.persistTaskBounds()
1813 || newParentConfig.windowConfiguration.persistTaskBounds();
1814 if (!prevPersistTaskBounds && nextPersistTaskBounds
1815 && mLastNonFullscreenBounds != null && !mLastNonFullscreenBounds.isEmpty()) {
1816 // Bypass onRequestedOverrideConfigurationChanged here to avoid infinite loop.
1817 getRequestedOverrideConfiguration().windowConfiguration
1818 .setBounds(mLastNonFullscreenBounds);
1819 }
1820
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001821 final boolean wasInMultiWindowMode = inMultiWindowMode();
1822 super.onConfigurationChanged(newParentConfig);
1823 if (wasInMultiWindowMode != inMultiWindowMode()) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001824 mAtmService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Wale Ogunwale5f986092015-12-04 15:35:38 -08001825 }
Evan Rosky730f6e82018-12-03 17:40:11 -08001826
1827 // If the configuration supports persistent bounds (eg. Freeform), keep track of the
1828 // current (non-fullscreen) bounds for persistence.
Evan Rosky1ac84462018-11-13 11:25:30 -08001829 if (getWindowConfiguration().persistTaskBounds()) {
1830 final Rect currentBounds = getRequestedOverrideBounds();
1831 if (!currentBounds.isEmpty()) {
1832 setLastNonFullscreenBounds(currentBounds);
1833 }
1834 }
Wale Ogunwaleeb76b762017-11-17 10:08:04 -08001835 // TODO: Should also take care of Pip mode changes here.
Garfield Tan891146c2018-10-09 12:14:00 -07001836
1837 saveLaunchingStateIfNeeded();
1838 }
1839
1840 /**
1841 * Saves launching state if necessary so that we can launch the activity to its latest state.
1842 * 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 -07001843 * mode on freeform displays.
Garfield Tan891146c2018-10-09 12:14:00 -07001844 */
1845 void saveLaunchingStateIfNeeded() {
1846 if (!hasBeenVisible) {
1847 // Not ever visible to user.
1848 return;
1849 }
1850
1851 final int windowingMode = getWindowingMode();
Garfield Tan3129b852019-06-24 16:51:20 -07001852 if (windowingMode != WINDOWING_MODE_FULLSCREEN
1853 && windowingMode != WINDOWING_MODE_FREEFORM) {
1854 return;
1855 }
1856
1857 // Don't persist state if display isn't in freeform mode. Then the task will be launched
1858 // back to its last state in a freeform display when it's launched in a freeform display
1859 // next time.
1860 if (getWindowConfiguration().getDisplayWindowingMode() != WINDOWING_MODE_FREEFORM) {
Garfield Tan891146c2018-10-09 12:14:00 -07001861 return;
1862 }
1863
1864 // Saves the new state so that we can launch the activity at the same location.
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07001865 mAtmService.mStackSupervisor.mLaunchParamsPersister.saveTask(this);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001866 }
1867
Evan Roskyed6767f2018-10-26 17:21:06 -07001868 /**
Evan Rosky1ac84462018-11-13 11:25:30 -08001869 * Adjust bounds to stay within stack bounds.
1870 *
1871 * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
1872 * that keep them unchanged, but be contained within the stack bounds.
1873 *
1874 * @param bounds Bounds to be adjusted.
1875 * @param stackBounds Bounds within which the other bounds should remain.
Evan Rosky60dba2f2019-02-01 10:58:38 -08001876 * @param overlapPxX The amount of px required to be visible in the X dimension.
1877 * @param overlapPxY The amount of px required to be visible in the Y dimension.
Evan Rosky1ac84462018-11-13 11:25:30 -08001878 */
Evan Rosky60dba2f2019-02-01 10:58:38 -08001879 private static void fitWithinBounds(Rect bounds, Rect stackBounds, int overlapPxX,
1880 int overlapPxY) {
Evan Rosky1ac84462018-11-13 11:25:30 -08001881 if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
1882 return;
1883 }
1884
Evan Rosky60dba2f2019-02-01 10:58:38 -08001885 // For each side of the parent (eg. left), check if the opposing side of the window (eg.
1886 // right) is at least overlap pixels away. If less, offset the window by that difference.
1887 int horizontalDiff = 0;
1888 // If window is smaller than overlap, use it's smallest dimension instead
1889 int overlapLR = Math.min(overlapPxX, bounds.width());
1890 if (bounds.right < (stackBounds.left + overlapLR)) {
1891 horizontalDiff = overlapLR - (bounds.right - stackBounds.left);
1892 } else if (bounds.left > (stackBounds.right - overlapLR)) {
1893 horizontalDiff = -(overlapLR - (stackBounds.right - bounds.left));
Evan Rosky1ac84462018-11-13 11:25:30 -08001894 }
Evan Rosky60dba2f2019-02-01 10:58:38 -08001895 int verticalDiff = 0;
1896 int overlapTB = Math.min(overlapPxY, bounds.width());
1897 if (bounds.bottom < (stackBounds.top + overlapTB)) {
1898 verticalDiff = overlapTB - (bounds.bottom - stackBounds.top);
1899 } else if (bounds.top > (stackBounds.bottom - overlapTB)) {
1900 verticalDiff = -(overlapTB - (stackBounds.bottom - bounds.top));
Evan Rosky1ac84462018-11-13 11:25:30 -08001901 }
Evan Rosky60dba2f2019-02-01 10:58:38 -08001902 bounds.offset(horizontalDiff, verticalDiff);
Evan Rosky1ac84462018-11-13 11:25:30 -08001903 }
1904
1905 /**
Evan Roskyed6767f2018-10-26 17:21:06 -07001906 * Displayed bounds are used to set where the task is drawn at any given time. This is
1907 * separate from its actual bounds so that the app doesn't see any meaningful configuration
1908 * changes during transitionary periods.
1909 */
1910 void setDisplayedBounds(Rect bounds) {
1911 if (bounds == null) {
1912 mDisplayedBounds.setEmpty();
1913 } else {
1914 mDisplayedBounds.set(bounds);
1915 }
Yunfan Chen0e7aff92018-12-05 16:35:32 -08001916 if (mTask != null) {
1917 mTask.setOverrideDisplayedBounds(
Evan Roskyed6767f2018-10-26 17:21:06 -07001918 mDisplayedBounds.isEmpty() ? null : mDisplayedBounds);
1919 }
1920 }
1921
1922 /**
1923 * Gets the current overridden displayed bounds. These will be empty if the task is not
1924 * currently overriding where it is displayed.
1925 */
1926 Rect getDisplayedBounds() {
1927 return mDisplayedBounds;
1928 }
1929
1930 /**
1931 * @return {@code true} if this has overridden displayed bounds.
1932 */
1933 boolean hasDisplayedBounds() {
1934 return !mDisplayedBounds.isEmpty();
1935 }
1936
Evan Rosky1ac84462018-11-13 11:25:30 -08001937 /**
1938 * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
1939 * intersectBounds on a side, then the respective side will not be intersected.
1940 *
1941 * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
1942 * inset on that side is no-longer applicable. This scenario happens when a task's minimal
1943 * bounds are larger than the provided parent/display bounds.
1944 *
1945 * @param inOutBounds the bounds to intersect.
1946 * @param intersectBounds the bounds to intersect with.
1947 * @param intersectInsets insets to apply to intersectBounds before intersecting.
1948 */
Riddle Hsu74826262019-04-17 14:57:42 +08001949 static void intersectWithInsetsIfFits(
Evan Rosky1ac84462018-11-13 11:25:30 -08001950 Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
1951 if (inOutBounds.right <= intersectBounds.right) {
1952 inOutBounds.right =
1953 Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
1954 }
1955 if (inOutBounds.bottom <= intersectBounds.bottom) {
1956 inOutBounds.bottom =
1957 Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
1958 }
1959 if (inOutBounds.left >= intersectBounds.left) {
1960 inOutBounds.left =
1961 Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
1962 }
1963 if (inOutBounds.top >= intersectBounds.top) {
1964 inOutBounds.top =
1965 Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
1966 }
1967 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08001968
Evan Rosky1ac84462018-11-13 11:25:30 -08001969 /**
1970 * Gets bounds with non-decor and stable insets applied respectively.
1971 *
1972 * If bounds overhangs the display, those edges will not get insets. See
1973 * {@link #intersectWithInsetsIfFits}
1974 *
1975 * @param outNonDecorBounds where to place bounds with non-decor insets applied.
1976 * @param outStableBounds where to place bounds with stable insets applied.
1977 * @param bounds the bounds to inset.
1978 */
1979 private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
1980 DisplayInfo displayInfo) {
1981 outNonDecorBounds.set(bounds);
1982 outStableBounds.set(bounds);
1983 if (getStack() == null || getStack().getDisplay() == null) {
1984 return;
1985 }
1986 DisplayPolicy policy = getStack().getDisplay().mDisplayContent.getDisplayPolicy();
1987 if (policy == null) {
1988 return;
1989 }
1990 mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
Bryce Lee7566d762017-03-30 09:34:15 -07001991
Riddle Hsu61987bc2019-04-03 13:08:47 +08001992 policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
1993 displayInfo.logicalHeight, displayInfo.displayCutout, mTmpInsets);
Evan Rosky1ac84462018-11-13 11:25:30 -08001994 intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);
Riddle Hsu61987bc2019-04-03 13:08:47 +08001995
1996 policy.convertNonDecorInsetsToStableInsets(mTmpInsets, displayInfo.rotation);
1997 intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
Evan Rosky1ac84462018-11-13 11:25:30 -08001998 }
1999
2000 /**
2001 * Asks docked-divider controller for the smallestwidthdp given bounds.
2002 * @param bounds bounds to calculate smallestwidthdp for.
2003 */
2004 private int getSmallestScreenWidthDpForDockedBounds(Rect bounds) {
2005 DisplayContent dc = mStack.getDisplay().mDisplayContent;
2006 if (dc != null) {
2007 return dc.getDockedDividerController().getSmallestWidthDpForBounds(bounds);
2008 }
2009 return Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
2010 }
2011
Riddle Hsu0a343c32018-12-21 00:40:48 +08002012 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
2013 @NonNull Configuration parentConfig) {
Riddle Hsu61987bc2019-04-03 13:08:47 +08002014 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* compatInsets */);
Riddle Hsu0a343c32018-12-21 00:40:48 +08002015 }
2016
Evan Rosky1ac84462018-11-13 11:25:30 -08002017 /**
2018 * Calculates configuration values used by the client to get resources. This should be run
2019 * using app-facing bounds (bounds unmodified by animations or transient interactions).
2020 *
2021 * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
2022 * configuring an "inherit-bounds" window which means that all configuration settings would
2023 * just be inherited from the parent configuration.
2024 **/
Evan Rosky730f6e82018-12-03 17:40:11 -08002025 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Riddle Hsu61987bc2019-04-03 13:08:47 +08002026 @NonNull Configuration parentConfig,
2027 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
Evan Rosky1ac84462018-11-13 11:25:30 -08002028 int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
2029 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2030 windowingMode = parentConfig.windowConfiguration.getWindowingMode();
Winson Chungbdc646f2017-02-13 12:12:22 -08002031 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002032
Evan Rosky1ac84462018-11-13 11:25:30 -08002033 float density = inOutConfig.densityDpi;
2034 if (density == Configuration.DENSITY_DPI_UNDEFINED) {
2035 density = parentConfig.densityDpi;
2036 }
2037 density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
Winson Chung60c1aba2017-03-14 17:47:42 -07002038
Evan Rosky730f6e82018-12-03 17:40:11 -08002039 final Rect bounds = inOutConfig.windowConfiguration.getBounds();
Evan Rosky1ac84462018-11-13 11:25:30 -08002040 Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2041 if (outAppBounds == null || outAppBounds.isEmpty()) {
2042 inOutConfig.windowConfiguration.setAppBounds(bounds);
2043 outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2044 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08002045 // Non-null compatibility insets means the activity prefers to keep its original size, so
2046 // the out bounds doesn't need to be restricted by the parent.
2047 final boolean insideParentBounds = compatInsets == null;
Riddle Hsu0a343c32018-12-21 00:40:48 +08002048 if (insideParentBounds && windowingMode != WINDOWING_MODE_FREEFORM) {
Evan Rosky1ac84462018-11-13 11:25:30 -08002049 final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
2050 if (parentAppBounds != null && !parentAppBounds.isEmpty()) {
2051 outAppBounds.intersect(parentAppBounds);
2052 }
2053 }
2054
2055 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
2056 || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
Riddle Hsu0a343c32018-12-21 00:40:48 +08002057 if (insideParentBounds && mStack != null) {
Evan Rosky1ac84462018-11-13 11:25:30 -08002058 final DisplayInfo di = new DisplayInfo();
2059 mStack.getDisplay().mDisplay.getDisplayInfo(di);
2060
2061 // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
2062 // area, i.e. the screen area without the system bars.
2063 // The non decor inset are areas that could never be removed in Honeycomb. See
2064 // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
2065 calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, bounds, di);
2066 } else {
Riddle Hsu61987bc2019-04-03 13:08:47 +08002067 // Apply the given non-decor and stable insets to calculate the corresponding bounds
2068 // for screen size of configuration.
Evan Rosky72f084d2019-09-11 17:05:16 -07002069 int rotation = inOutConfig.windowConfiguration.getRotation();
2070 if (rotation == ROTATION_UNDEFINED) {
2071 rotation = parentConfig.windowConfiguration.getRotation();
2072 }
Riddle Hsu61987bc2019-04-03 13:08:47 +08002073 if (rotation != ROTATION_UNDEFINED && compatInsets != null) {
Riddle Hsu74826262019-04-17 14:57:42 +08002074 mTmpNonDecorBounds.set(bounds);
2075 mTmpStableBounds.set(bounds);
2076 compatInsets.getDisplayBoundsByRotation(mTmpBounds, rotation);
Riddle Hsu61987bc2019-04-03 13:08:47 +08002077 intersectWithInsetsIfFits(mTmpNonDecorBounds, mTmpBounds,
2078 compatInsets.mNonDecorInsets[rotation]);
2079 intersectWithInsetsIfFits(mTmpStableBounds, mTmpBounds,
2080 compatInsets.mStableInsets[rotation]);
Riddle Hsu74826262019-04-17 14:57:42 +08002081 outAppBounds.set(mTmpNonDecorBounds);
2082 } else {
2083 // Set to app bounds because it excludes decor insets.
2084 mTmpNonDecorBounds.set(outAppBounds);
2085 mTmpStableBounds.set(outAppBounds);
Riddle Hsu61987bc2019-04-03 13:08:47 +08002086 }
Evan Rosky1ac84462018-11-13 11:25:30 -08002087 }
2088
2089 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
Riddle Hsu0a343c32018-12-21 00:40:48 +08002090 final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density);
2091 inOutConfig.screenWidthDp = insideParentBounds
2092 ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
2093 : overrideScreenWidthDp;
Evan Rosky1ac84462018-11-13 11:25:30 -08002094 }
2095 if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
Riddle Hsu0a343c32018-12-21 00:40:48 +08002096 final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
2097 inOutConfig.screenHeightDp = insideParentBounds
Riddle Hsu88e3c8732019-02-18 19:15:12 +08002098 ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
Riddle Hsu0a343c32018-12-21 00:40:48 +08002099 : overrideScreenHeightDp;
Evan Rosky1ac84462018-11-13 11:25:30 -08002100 }
2101
2102 if (inOutConfig.smallestScreenWidthDp
2103 == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2104 if (WindowConfiguration.isFloating(windowingMode)) {
2105 // For floating tasks, calculate the smallest width from the bounds of the task
2106 inOutConfig.smallestScreenWidthDp = (int) (
2107 Math.min(bounds.width(), bounds.height()) / density);
2108 } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
2109 // Iterating across all screen orientations, and return the minimum of the task
2110 // width taking into account that the bounds might change because the snap
2111 // algorithm snaps to a different value
Evan Rosky730f6e82018-12-03 17:40:11 -08002112 inOutConfig.smallestScreenWidthDp =
2113 getSmallestScreenWidthDpForDockedBounds(bounds);
Evan Rosky1ac84462018-11-13 11:25:30 -08002114 }
2115 // otherwise, it will just inherit
2116 }
2117 }
2118
Evan Rosky730f6e82018-12-03 17:40:11 -08002119 if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
Evan Rosky1ac84462018-11-13 11:25:30 -08002120 inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
Riddle Hsu0a343c32018-12-21 00:40:48 +08002121 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
Evan Rosky1ac84462018-11-13 11:25:30 -08002122 }
2123 if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
2124 // For calculating screen layout, we need to use the non-decor inset screen area for the
2125 // calculation for compatibility reasons, i.e. screen area without system bars that
2126 // could never go away in Honeycomb.
2127 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
2128 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
2129 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start
2130 // override calculation with partial default.
2131 // Reducing the screen layout starting from its parent config.
2132 final int sl = parentConfig.screenLayout
2133 & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
2134 final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
2135 final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
2136 inOutConfig.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
2137 }
2138 }
2139
Evan Rosky1ac84462018-11-13 11:25:30 -08002140 @Override
2141 void resolveOverrideConfiguration(Configuration newParentConfig) {
Evan Rosky730f6e82018-12-03 17:40:11 -08002142 mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
2143 super.resolveOverrideConfiguration(newParentConfig);
2144 int windowingMode =
2145 getRequestedOverrideConfiguration().windowConfiguration.getWindowingMode();
2146 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2147 windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
2148 }
2149 Rect outOverrideBounds =
2150 getResolvedOverrideConfiguration().windowConfiguration.getBounds();
2151
2152 if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
Riddle Hsu74826262019-04-17 14:57:42 +08002153 computeFullscreenBounds(outOverrideBounds, null /* refActivity */,
2154 newParentConfig.windowConfiguration.getBounds(),
2155 newParentConfig.orientation);
Evan Rosky730f6e82018-12-03 17:40:11 -08002156 }
2157
2158 if (outOverrideBounds.isEmpty()) {
2159 // If the task fills the parent, just inherit all the other configs from parent.
2160 return;
2161 }
2162
2163 adjustForMinimalTaskDimensions(outOverrideBounds, mTmpBounds);
2164 if (windowingMode == WINDOWING_MODE_FREEFORM) {
2165 // by policy, make sure the window remains within parent somewhere
Evan Rosky60dba2f2019-02-01 10:58:38 -08002166 final float density =
2167 ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;
GyeHun Jeon84b30d22019-04-24 14:20:15 -07002168 final Rect parentBounds =
2169 new Rect(newParentConfig.windowConfiguration.getBounds());
2170 final ActivityDisplay display = mStack.getDisplay();
2171 if (display != null && display.mDisplayContent != null) {
2172 // If a freeform window moves below system bar, there is no way to move it again
2173 // by touch. Because its caption is covered by system bar. So we exclude them
2174 // from stack bounds. and then caption will be shown inside stable area.
2175 final Rect stableBounds = new Rect();
2176 display.mDisplayContent.getStableRect(stableBounds);
2177 parentBounds.intersect(stableBounds);
2178 }
2179
2180 fitWithinBounds(outOverrideBounds, parentBounds,
Evan Rosky60dba2f2019-02-01 10:58:38 -08002181 (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP),
2182 (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP));
GyeHun Jeon84b30d22019-04-24 14:20:15 -07002183
2184 // Prevent to overlap caption with stable insets.
2185 final int offsetTop = parentBounds.top - outOverrideBounds.top;
2186 if (offsetTop > 0) {
2187 outOverrideBounds.offset(0, offsetTop);
2188 }
Evan Rosky730f6e82018-12-03 17:40:11 -08002189 }
2190 computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08002191 }
2192
Riddle Hsu74826262019-04-17 14:57:42 +08002193 /** @see WindowContainer#handlesOrientationChangeFromDescendant */
2194 boolean handlesOrientationChangeFromDescendant() {
2195 return mTask != null && mTask.getParent() != null
2196 && mTask.getParent().handlesOrientationChangeFromDescendant();
2197 }
2198
2199 /**
2200 * Compute bounds (letterbox or pillarbox) for {@link #WINDOWING_MODE_FULLSCREEN} when the
2201 * parent doesn't handle the orientation change and the requested orientation is different from
2202 * the parent.
2203 */
2204 void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
2205 @NonNull Rect parentBounds, int parentOrientation) {
2206 // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
2207 outBounds.setEmpty();
2208 if (handlesOrientationChangeFromDescendant()) {
2209 return;
2210 }
2211 if (refActivity == null) {
2212 // Use the top activity as the reference of orientation. Don't include overlays because
2213 // it is usually not the actual content or just temporarily shown.
2214 // E.g. ForcedResizableInfoActivity.
2215 refActivity = getTopActivity(false /* includeOverlays */);
2216 }
2217
2218 // If the task or the reference activity requires a different orientation (either by
2219 // override or activityInfo), make it fit the available bounds by scaling down its bounds.
2220 final int overrideOrientation = getRequestedOverrideConfiguration().orientation;
2221 final int forcedOrientation =
2222 (overrideOrientation != ORIENTATION_UNDEFINED || refActivity == null)
2223 ? overrideOrientation : refActivity.getRequestedConfigurationOrientation();
2224 if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
2225 return;
2226 }
2227
2228 final int parentWidth = parentBounds.width();
2229 final int parentHeight = parentBounds.height();
2230 final float aspect = ((float) parentHeight) / parentWidth;
2231 if (forcedOrientation == ORIENTATION_LANDSCAPE) {
2232 final int height = (int) (parentWidth / aspect);
2233 final int top = parentBounds.centerY() - height / 2;
2234 outBounds.set(parentBounds.left, top, parentBounds.right, top + height);
2235 } else {
2236 final int width = (int) (parentHeight * aspect);
2237 final int left = parentBounds.centerX() - width / 2;
2238 outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
2239 }
2240 }
2241
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002242 Rect updateOverrideConfigurationFromLaunchBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08002243 final Rect bounds = getLaunchBounds();
Evan Roskya4cc3a92019-06-28 13:25:01 -07002244 setBounds(bounds);
Bryce Leef3c6a472017-11-14 14:53:06 -08002245 if (bounds != null && !bounds.isEmpty()) {
2246 // TODO: Review if we actually want to do this - we are setting the launch bounds
2247 // directly here.
Evan Roskydfe3da72018-10-26 17:21:06 -07002248 bounds.set(getRequestedOverrideBounds());
Andrii Kulian73336d812016-03-24 12:56:08 -07002249 }
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002250 return bounds;
2251 }
2252
Wale Ogunwale935e5022015-11-10 12:36:10 -08002253 /** Updates the task's bounds and override configuration to match what is expected for the
2254 * input stack. */
2255 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002256 if (mStack != null && mStack == inStack) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002257 return;
2258 }
2259
Wale Ogunwale44f036f2017-09-29 05:09:09 -07002260 if (inStack.inFreeformWindowingMode()) {
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002261 if (!isResizeable()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002262 throw new IllegalArgumentException("Can not position non-resizeable task="
2263 + this + " in stack=" + inStack);
2264 }
Bryce Leef3c6a472017-11-14 14:53:06 -08002265 if (!matchParentBounds()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002266 return;
2267 }
2268 if (mLastNonFullscreenBounds != null) {
Evan Roskya4cc3a92019-06-28 13:25:01 -07002269 setBounds(mLastNonFullscreenBounds);
Wale Ogunwale935e5022015-11-10 12:36:10 -08002270 } else {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002271 mAtmService.mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Wale Ogunwale935e5022015-11-10 12:36:10 -08002272 }
2273 } else {
Evan Roskya4cc3a92019-06-28 13:25:01 -07002274 setBounds(inStack.getRequestedOverrideBounds());
Wale Ogunwale935e5022015-11-10 12:36:10 -08002275 }
2276 }
2277
Wale Ogunwale706ed792015-08-02 10:29:44 -07002278 /** Returns the bounds that should be used to launch this task. */
Wale Ogunwale30e441d2017-11-09 08:28:45 -08002279 Rect getLaunchBounds() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002280 if (mStack == null) {
Chong Zhang7d5f5102016-01-13 10:29:24 -08002281 return null;
2282 }
2283
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07002284 final int windowingMode = getWindowingMode();
2285 if (!isActivityTypeStandardOrUndefined()
2286 || windowingMode == WINDOWING_MODE_FULLSCREEN
2287 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Evan Roskydfe3da72018-10-26 17:21:06 -07002288 return isResizeable() ? mStack.getRequestedOverrideBounds() : null;
Wale Ogunwale3382ab12017-07-27 08:55:03 -07002289 } else if (!getWindowConfiguration().persistTaskBounds()) {
Evan Roskydfe3da72018-10-26 17:21:06 -07002290 return mStack.getRequestedOverrideBounds();
Wale Ogunwale706ed792015-08-02 10:29:44 -07002291 }
2292 return mLastNonFullscreenBounds;
2293 }
2294
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01002295 void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002296 for (int activityNdx = getChildCount() - 1; activityNdx >= 0; --activityNdx) {
2297 final ActivityRecord r = getChildAt(activityNdx);
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01002298 if (r.visible) {
2299 r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
2300 }
2301 }
2302 }
2303
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07002304 void setRootProcess(WindowProcessController proc) {
Dianne Hackborn68a06332017-11-15 17:54:18 -08002305 clearRootProcess();
2306 if (intent != null &&
2307 (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
2308 mRootProcess = proc;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07002309 mRootProcess.addRecentTask(this);
Dianne Hackborn68a06332017-11-15 17:54:18 -08002310 }
2311 }
2312
2313 void clearRootProcess() {
2314 if (mRootProcess != null) {
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -07002315 mRootProcess.removeRecentTask(this);
Dianne Hackborn68a06332017-11-15 17:54:18 -08002316 mRootProcess = null;
2317 }
2318 }
2319
chaviw82a0ba82018-03-15 14:26:29 -07002320 void clearAllPendingOptions() {
2321 for (int i = getChildCount() - 1; i >= 0; i--) {
2322 getChildAt(i).clearOptionsLocked(false /* withAbort */);
2323 }
2324 }
2325
Winson Chungabfdcce2018-07-02 17:23:33 -07002326 /**
2327 * Fills in a {@link TaskInfo} with information from this task.
2328 * @param info the {@link TaskInfo} to fill in
Winson Chungabfdcce2018-07-02 17:23:33 -07002329 */
Mark Renoufc808f062019-02-07 15:20:37 -05002330 void fillTaskInfo(TaskInfo info) {
2331 getNumRunningActivities(mReuseActivitiesReport);
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002332 info.userId = mUserId;
Winson Chungabfdcce2018-07-02 17:23:33 -07002333 info.stackId = getStackId();
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002334 info.taskId = mTaskId;
Mark Renoufb1abb552019-02-08 13:51:41 -05002335 info.displayId = mStack == null ? Display.INVALID_DISPLAY : mStack.mDisplayId;
Winson Chungabfdcce2018-07-02 17:23:33 -07002336 info.isRunning = getTopActivity() != null;
Riddle Hsu2f9acd22018-11-06 23:44:43 +08002337 info.baseIntent = new Intent(getBaseIntent());
Mark Renoufc808f062019-02-07 15:20:37 -05002338 info.baseActivity = mReuseActivitiesReport.base != null
2339 ? mReuseActivitiesReport.base.intent.getComponent()
Winson Chungabfdcce2018-07-02 17:23:33 -07002340 : null;
Mark Renoufc808f062019-02-07 15:20:37 -05002341 info.topActivity = mReuseActivitiesReport.top != null
2342 ? mReuseActivitiesReport.top.mActivityComponent
Winson Chungabfdcce2018-07-02 17:23:33 -07002343 : null;
2344 info.origActivity = origActivity;
2345 info.realActivity = realActivity;
Mark Renoufc808f062019-02-07 15:20:37 -05002346 info.numActivities = mReuseActivitiesReport.numActivities;
Winson Chungabfdcce2018-07-02 17:23:33 -07002347 info.lastActiveTime = lastActiveTime;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002348 info.taskDescription = new ActivityManager.TaskDescription(mTaskDescription);
Winson Chungabfdcce2018-07-02 17:23:33 -07002349 info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
2350 info.resizeMode = mResizeMode;
2351 info.configuration.setTo(getConfiguration());
2352 }
2353
Mark Renoufc808f062019-02-07 15:20:37 -05002354 /**
2355 * Returns a {@link TaskInfo} with information from this task.
2356 */
2357 ActivityManager.RunningTaskInfo getTaskInfo() {
2358 ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
2359 fillTaskInfo(info);
2360 return info;
2361 }
2362
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002363 void dump(PrintWriter pw, String prefix) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002364 pw.print(prefix); pw.print("userId="); pw.print(mUserId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07002365 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
2366 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
Suprabh Shukla7745c142016-03-07 18:21:10 -08002367 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002368 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
Dianne Hackborn79228822014-09-16 11:11:23 -07002369 if (affinity != null || rootAffinity != null) {
2370 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
2371 if (affinity == null || !affinity.equals(rootAffinity)) {
2372 pw.print(" root="); pw.println(rootAffinity);
2373 } else {
2374 pw.println();
2375 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002376 }
Dianne Hackborn91097de2014-04-04 18:02:06 -07002377 if (voiceSession != null || voiceInteractor != null) {
2378 pw.print(prefix); pw.print("VOICE: session=0x");
2379 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
2380 pw.print(" interactor=0x");
2381 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
2382 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002383 if (intent != null) {
2384 StringBuilder sb = new StringBuilder(128);
2385 sb.append(prefix); sb.append("intent={");
Hui Yu6d5c3b92019-10-22 15:35:53 -07002386 intent.toShortString(sb, false, true, false, false);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002387 sb.append('}');
2388 pw.println(sb.toString());
2389 }
2390 if (affinityIntent != null) {
2391 StringBuilder sb = new StringBuilder(128);
2392 sb.append(prefix); sb.append("affinityIntent={");
Hui Yu6d5c3b92019-10-22 15:35:53 -07002393 affinityIntent.toShortString(sb, false, true, false, false);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002394 sb.append('}');
2395 pw.println(sb.toString());
2396 }
2397 if (origActivity != null) {
2398 pw.print(prefix); pw.print("origActivity=");
2399 pw.println(origActivity.flattenToShortString());
2400 }
2401 if (realActivity != null) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002402 pw.print(prefix); pw.print("mActivityComponent=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002403 pw.println(realActivity.flattenToShortString());
2404 }
Wale Ogunwale66e16852017-10-19 13:35:52 -07002405 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard() || numFullscreen != 0) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002406 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002407 pw.print(" isPersistable="); pw.print(isPersistable);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002408 pw.print(" numFullscreen="); pw.print(numFullscreen);
Wale Ogunwale66e16852017-10-19 13:35:52 -07002409 pw.print(" activityType="); pw.println(getActivityType());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002410 }
Craig Mautner432f64e2015-05-20 14:59:57 -07002411 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
2412 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002413 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
2414 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
Craig Mautner432f64e2015-05-20 14:59:57 -07002415 pw.print(" mReuseTask="); pw.print(mReuseTask);
2416 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002417 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002418 if (mAffiliatedTaskId != mTaskId || mPrevAffiliateTaskId != INVALID_TASK_ID
Wale Ogunwale18795a22014-12-03 11:38:33 -08002419 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
2420 || mNextAffiliate != null) {
Dianne Hackborn852975d2014-08-22 17:42:43 -07002421 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
2422 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
2423 pw.print(" (");
2424 if (mPrevAffiliate == null) {
2425 pw.print("null");
2426 } else {
2427 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
2428 }
2429 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
2430 pw.print(" (");
2431 if (mNextAffiliate == null) {
2432 pw.print("null");
2433 } else {
2434 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
2435 }
2436 pw.println(")");
2437 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002438 pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002439 if (!askedCompatMode || !inRecents || !isAvailable) {
2440 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
2441 pw.print(" inRecents="); pw.print(inRecents);
2442 pw.print(" isAvailable="); pw.println(isAvailable);
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002443 }
Dianne Hackborn852975d2014-08-22 17:42:43 -07002444 if (lastDescription != null) {
2445 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
2446 }
Dianne Hackborn68a06332017-11-15 17:54:18 -08002447 if (mRootProcess != null) {
2448 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
2449 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002450 pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002451 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
2452 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08002453 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002454 pw.print(" isResizeable=" + isResizeable());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002455 pw.print(" lastActiveTime=" + lastActiveTime);
2456 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002457 }
2458
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002459 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002460 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002461 StringBuilder sb = new StringBuilder(128);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002462 if (stringName != null) {
2463 sb.append(stringName);
2464 sb.append(" U=");
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002465 sb.append(mUserId);
Wale Ogunwale6c5eb1c2015-11-10 07:52:22 -08002466 sb.append(" StackId=");
Andrii Kulian02b7a832016-10-06 23:11:56 -07002467 sb.append(getStackId());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002468 sb.append(" sz=");
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002469 sb.append(getChildCount());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002470 sb.append('}');
2471 return sb.toString();
2472 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002473 sb.append("TaskRecord{");
2474 sb.append(Integer.toHexString(System.identityHashCode(this)));
2475 sb.append(" #");
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002476 sb.append(mTaskId);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002477 if (affinity != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002478 sb.append(" A=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002479 sb.append(affinity);
2480 } else if (intent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002481 sb.append(" I=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002482 sb.append(intent.getComponent().flattenToShortString());
Bryce Leefbd263b42018-03-07 10:33:55 -08002483 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002484 sb.append(" aI=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002485 sb.append(affinityIntent.getComponent().flattenToShortString());
2486 } else {
2487 sb.append(" ??");
2488 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07002489 stringName = sb.toString();
2490 return toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002491 }
Steven Timotius4346f0a2017-09-12 11:07:21 -07002492
Nataniel Borges023ecb52019-01-16 14:15:43 -08002493 public void writeToProto(ProtoOutputStream proto, long fieldId,
2494 @WindowTraceLogLevel int logLevel) {
2495 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
2496 return;
2497 }
2498
Steven Timotius4346f0a2017-09-12 11:07:21 -07002499 final long token = proto.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -08002500 super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002501 proto.write(ID, mTaskId);
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002502 for (int i = getChildCount() - 1; i >= 0; i--) {
2503 ActivityRecord activity = getChildAt(i);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002504 activity.writeToProto(proto, ACTIVITIES);
2505 }
2506 proto.write(STACK_ID, mStack.mStackId);
2507 if (mLastNonFullscreenBounds != null) {
2508 mLastNonFullscreenBounds.writeToProto(proto, LAST_NON_FULLSCREEN_BOUNDS);
2509 }
2510 if (realActivity != null) {
2511 proto.write(REAL_ACTIVITY, realActivity.flattenToShortString());
2512 }
2513 if (origActivity != null) {
2514 proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString());
2515 }
2516 proto.write(ACTIVITY_TYPE, getActivityType());
Steven Timotius4346f0a2017-09-12 11:07:21 -07002517 proto.write(RESIZE_MODE, mResizeMode);
Bryce Leef3c6a472017-11-14 14:53:06 -08002518 // TODO: Remove, no longer needed with windowingMode.
2519 proto.write(FULLSCREEN, matchParentBounds());
2520
2521 if (!matchParentBounds()) {
Evan Roskydfe3da72018-10-26 17:21:06 -07002522 final Rect bounds = getRequestedOverrideBounds();
Bryce Leef3c6a472017-11-14 14:53:06 -08002523 bounds.writeToProto(proto, BOUNDS);
Steven Timotius4346f0a2017-09-12 11:07:21 -07002524 }
2525 proto.write(MIN_WIDTH, mMinWidth);
2526 proto.write(MIN_HEIGHT, mMinHeight);
2527 proto.end(token);
2528 }
Winson Chung61c9e5a2017-10-11 10:39:32 -07002529
2530 /**
2531 * See {@link #getNumRunningActivities(TaskActivitiesReport)}.
2532 */
2533 static class TaskActivitiesReport {
2534 int numRunning;
2535 int numActivities;
2536 ActivityRecord top;
2537 ActivityRecord base;
2538
2539 void reset() {
2540 numRunning = numActivities = 0;
2541 top = base = null;
2542 }
2543 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002544
2545 /**
2546 * Saves this {@link TaskRecord} to XML using given serializer.
2547 */
2548 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
2549 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
2550
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002551 out.attribute(null, ATTR_TASKID, String.valueOf(mTaskId));
Garfield Tan9b1efea2017-12-05 16:43:46 -08002552 if (realActivity != null) {
2553 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
2554 }
2555 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
2556 if (origActivity != null) {
2557 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
2558 }
2559 // Write affinity, and root affinity if it is different from affinity.
2560 // We use the special string "@" for a null root affinity, so we can identify
2561 // later whether we were given a root affinity or should just make it the
2562 // same as the affinity.
2563 if (affinity != null) {
2564 out.attribute(null, ATTR_AFFINITY, affinity);
2565 if (!affinity.equals(rootAffinity)) {
2566 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2567 }
2568 } else if (rootAffinity != null) {
2569 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
2570 }
2571 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
2572 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
2573 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002574 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
Garfield Tan9b1efea2017-12-05 16:43:46 -08002575 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
2576 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
2577 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
2578 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
2579 if (lastDescription != null) {
2580 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
2581 }
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002582 if (mTaskDescription != null) {
2583 mTaskDescription.saveToXml(out);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002584 }
2585 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
2586 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
2587 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
2588 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
2589 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
2590 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
2591 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
2592 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
2593 String.valueOf(mSupportsPictureInPicture));
2594 if (mLastNonFullscreenBounds != null) {
2595 out.attribute(
2596 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
2597 }
2598 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
2599 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
2600 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
2601
2602 if (affinityIntent != null) {
2603 out.startTag(null, TAG_AFFINITYINTENT);
2604 affinityIntent.saveToXml(out);
2605 out.endTag(null, TAG_AFFINITYINTENT);
2606 }
2607
Bryce Lee1a990e52018-04-23 10:54:11 -07002608 if (intent != null) {
2609 out.startTag(null, TAG_INTENT);
2610 intent.saveToXml(out);
2611 out.endTag(null, TAG_INTENT);
2612 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002613
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002614 final int numActivities = getChildCount();
Garfield Tan9b1efea2017-12-05 16:43:46 -08002615 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
Wale Ogunwale1a06f152019-10-11 11:26:30 +02002616 final ActivityRecord r = getChildAt(activityNdx);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002617 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
2618 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
2619 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
2620 activityNdx > 0) {
2621 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
2622 break;
2623 }
2624 out.startTag(null, TAG_ACTIVITY);
2625 r.saveToXml(out);
2626 out.endTag(null, TAG_ACTIVITY);
2627 }
2628 }
2629
2630 @VisibleForTesting
2631 static TaskRecordFactory getTaskRecordFactory() {
2632 if (sTaskRecordFactory == null) {
2633 setTaskRecordFactory(new TaskRecordFactory());
2634 }
2635 return sTaskRecordFactory;
2636 }
2637
2638 static void setTaskRecordFactory(TaskRecordFactory factory) {
2639 sTaskRecordFactory = factory;
2640 }
2641
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002642 static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002643 Intent intent, IVoiceInteractionSession voiceSession,
2644 IVoiceInteractor voiceInteractor) {
2645 return getTaskRecordFactory().create(
2646 service, taskId, info, intent, voiceSession, voiceInteractor);
2647 }
2648
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002649 static TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002650 Intent intent, TaskDescription taskDescription) {
2651 return getTaskRecordFactory().create(service, taskId, info, intent, taskDescription);
2652 }
2653
2654 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2655 throws IOException, XmlPullParserException {
2656 return getTaskRecordFactory().restoreFromXml(in, stackSupervisor);
2657 }
2658
2659 /**
2660 * A factory class used to create {@link TaskRecord} or its subclass if any. This can be
2661 * specified when system boots by setting it with
2662 * {@link #setTaskRecordFactory(TaskRecordFactory)}.
2663 */
2664 static class TaskRecordFactory {
2665
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002666 TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002667 Intent intent, IVoiceInteractionSession voiceSession,
2668 IVoiceInteractor voiceInteractor) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002669 return new TaskRecord(service, taskId, info, intent, voiceSession, voiceInteractor,
2670 null /*taskDescription*/);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002671 }
2672
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002673 TaskRecord create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002674 Intent intent, TaskDescription taskDescription) {
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002675 return new TaskRecord(service, taskId, info, intent, null /*voiceSession*/,
2676 null /*voiceInteractor*/, taskDescription);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002677 }
2678
2679 /**
2680 * Should only be used when we're restoring {@link TaskRecord} from storage.
2681 */
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002682 TaskRecord create(ActivityTaskManagerService service, int taskId, Intent intent,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002683 Intent affinityIntent, String affinity, String rootAffinity,
2684 ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
2685 boolean autoRemoveRecents, boolean askedCompatMode, int userId,
2686 int effectiveUid, String lastDescription, ArrayList<ActivityRecord> activities,
2687 long lastTimeMoved, boolean neverRelinquishIdentity,
2688 TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
2689 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
2690 int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
2691 boolean userSetupComplete, int minWidth, int minHeight) {
2692 return new TaskRecord(service, taskId, intent, affinityIntent, affinity,
2693 rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
2694 askedCompatMode, userId, effectiveUid, lastDescription, activities,
2695 lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
2696 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
2697 resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -07002698 minWidth, minHeight, null /*ActivityInfo*/, null /*_voiceSession*/,
2699 null /*_voiceInteractor*/);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002700 }
2701
2702 TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
2703 throws IOException, XmlPullParserException {
2704 Intent intent = null;
2705 Intent affinityIntent = null;
2706 ArrayList<ActivityRecord> activities = new ArrayList<>();
2707 ComponentName realActivity = null;
2708 boolean realActivitySuspended = false;
2709 ComponentName origActivity = null;
2710 String affinity = null;
2711 String rootAffinity = null;
2712 boolean hasRootAffinity = false;
2713 boolean rootHasReset = false;
2714 boolean autoRemoveRecents = false;
2715 boolean askedCompatMode = false;
2716 int taskType = 0;
2717 int userId = 0;
2718 boolean userSetupComplete = true;
2719 int effectiveUid = -1;
2720 String lastDescription = null;
2721 long lastTimeOnTop = 0;
2722 boolean neverRelinquishIdentity = true;
2723 int taskId = INVALID_TASK_ID;
2724 final int outerDepth = in.getDepth();
2725 TaskDescription taskDescription = new TaskDescription();
2726 int taskAffiliation = INVALID_TASK_ID;
2727 int taskAffiliationColor = 0;
2728 int prevTaskId = INVALID_TASK_ID;
2729 int nextTaskId = INVALID_TASK_ID;
2730 int callingUid = -1;
2731 String callingPackage = "";
2732 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
2733 boolean supportsPictureInPicture = false;
Garfield Tan367b35a2017-12-13 12:16:21 -08002734 Rect lastNonFullscreenBounds = null;
Garfield Tan9b1efea2017-12-05 16:43:46 -08002735 int minWidth = INVALID_MIN_SIZE;
2736 int minHeight = INVALID_MIN_SIZE;
2737 int persistTaskVersion = 0;
2738
2739 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
2740 final String attrName = in.getAttributeName(attrNdx);
2741 final String attrValue = in.getAttributeValue(attrNdx);
2742 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
2743 attrName + " value=" + attrValue);
2744 switch (attrName) {
2745 case ATTR_TASKID:
2746 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
2747 break;
2748 case ATTR_REALACTIVITY:
2749 realActivity = ComponentName.unflattenFromString(attrValue);
2750 break;
2751 case ATTR_REALACTIVITY_SUSPENDED:
2752 realActivitySuspended = Boolean.valueOf(attrValue);
2753 break;
2754 case ATTR_ORIGACTIVITY:
2755 origActivity = ComponentName.unflattenFromString(attrValue);
2756 break;
2757 case ATTR_AFFINITY:
2758 affinity = attrValue;
2759 break;
2760 case ATTR_ROOT_AFFINITY:
2761 rootAffinity = attrValue;
2762 hasRootAffinity = true;
2763 break;
2764 case ATTR_ROOTHASRESET:
2765 rootHasReset = Boolean.parseBoolean(attrValue);
2766 break;
2767 case ATTR_AUTOREMOVERECENTS:
2768 autoRemoveRecents = Boolean.parseBoolean(attrValue);
2769 break;
2770 case ATTR_ASKEDCOMPATMODE:
2771 askedCompatMode = Boolean.parseBoolean(attrValue);
2772 break;
2773 case ATTR_USERID:
2774 userId = Integer.parseInt(attrValue);
2775 break;
2776 case ATTR_USER_SETUP_COMPLETE:
2777 userSetupComplete = Boolean.parseBoolean(attrValue);
2778 break;
2779 case ATTR_EFFECTIVE_UID:
2780 effectiveUid = Integer.parseInt(attrValue);
2781 break;
2782 case ATTR_TASKTYPE:
2783 taskType = Integer.parseInt(attrValue);
2784 break;
2785 case ATTR_LASTDESCRIPTION:
2786 lastDescription = attrValue;
2787 break;
2788 case ATTR_LASTTIMEMOVED:
2789 lastTimeOnTop = Long.parseLong(attrValue);
2790 break;
2791 case ATTR_NEVERRELINQUISH:
2792 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
2793 break;
2794 case ATTR_TASK_AFFILIATION:
2795 taskAffiliation = Integer.parseInt(attrValue);
2796 break;
2797 case ATTR_PREV_AFFILIATION:
2798 prevTaskId = Integer.parseInt(attrValue);
2799 break;
2800 case ATTR_NEXT_AFFILIATION:
2801 nextTaskId = Integer.parseInt(attrValue);
2802 break;
2803 case ATTR_TASK_AFFILIATION_COLOR:
2804 taskAffiliationColor = Integer.parseInt(attrValue);
2805 break;
2806 case ATTR_CALLING_UID:
2807 callingUid = Integer.parseInt(attrValue);
2808 break;
2809 case ATTR_CALLING_PACKAGE:
2810 callingPackage = attrValue;
2811 break;
2812 case ATTR_RESIZE_MODE:
2813 resizeMode = Integer.parseInt(attrValue);
2814 break;
2815 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
2816 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
2817 break;
2818 case ATTR_NON_FULLSCREEN_BOUNDS:
Garfield Tan367b35a2017-12-13 12:16:21 -08002819 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002820 break;
2821 case ATTR_MIN_WIDTH:
2822 minWidth = Integer.parseInt(attrValue);
2823 break;
2824 case ATTR_MIN_HEIGHT:
2825 minHeight = Integer.parseInt(attrValue);
2826 break;
2827 case ATTR_PERSIST_TASK_VERSION:
2828 persistTaskVersion = Integer.parseInt(attrValue);
2829 break;
2830 default:
2831 if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
2832 taskDescription.restoreFromXml(attrName, attrValue);
2833 } else {
2834 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
2835 }
2836 }
2837 }
2838
2839 int event;
2840 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
2841 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
2842 if (event == XmlPullParser.START_TAG) {
2843 final String name = in.getName();
2844 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
2845 "TaskRecord: START_TAG name=" + name);
2846 if (TAG_AFFINITYINTENT.equals(name)) {
2847 affinityIntent = Intent.restoreFromXml(in);
2848 } else if (TAG_INTENT.equals(name)) {
2849 intent = Intent.restoreFromXml(in);
2850 } else if (TAG_ACTIVITY.equals(name)) {
2851 ActivityRecord activity =
2852 ActivityRecord.restoreFromXml(in, stackSupervisor);
2853 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
2854 activity);
2855 if (activity != null) {
2856 activities.add(activity);
2857 }
2858 } else {
Garfield Tan1e740192017-12-12 14:37:42 -08002859 handleUnknownTag(name, in);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002860 }
2861 }
2862 }
2863 if (!hasRootAffinity) {
2864 rootAffinity = affinity;
2865 } else if ("@".equals(rootAffinity)) {
2866 rootAffinity = null;
2867 }
2868 if (effectiveUid <= 0) {
2869 Intent checkIntent = intent != null ? intent : affinityIntent;
2870 effectiveUid = 0;
2871 if (checkIntent != null) {
2872 IPackageManager pm = AppGlobals.getPackageManager();
2873 try {
2874 ApplicationInfo ai = pm.getApplicationInfo(
2875 checkIntent.getComponent().getPackageName(),
2876 PackageManager.MATCH_UNINSTALLED_PACKAGES
2877 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
2878 if (ai != null) {
2879 effectiveUid = ai.uid;
2880 }
2881 } catch (RemoteException e) {
2882 }
2883 }
2884 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
2885 + ": effectiveUid=" + effectiveUid);
2886 }
2887
2888 if (persistTaskVersion < 1) {
2889 // We need to convert the resize mode of home activities saved before version one if
2890 // they are marked as RESIZE_MODE_RESIZEABLE to
2891 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
2892 // before version 1 and the system didn't resize home activities before then.
2893 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
2894 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
2895 }
2896 } else {
2897 // This activity has previously marked itself explicitly as both resizeable and
2898 // supporting picture-in-picture. Since there is no longer a requirement for
2899 // picture-in-picture activities to be resizeable, we can mark this simply as
2900 // resizeable and supporting picture-in-picture separately.
2901 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
2902 resizeMode = RESIZE_MODE_RESIZEABLE;
2903 supportsPictureInPicture = true;
2904 }
2905 }
2906
Wale Ogunwalec9e57de2018-05-08 14:28:07 -07002907 final TaskRecord task = create(stackSupervisor.mService,
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002908 taskId, intent, affinityIntent,
Garfield Tan9b1efea2017-12-05 16:43:46 -08002909 affinity, rootAffinity, realActivity, origActivity, rootHasReset,
2910 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
2911 activities, lastTimeOnTop, neverRelinquishIdentity, taskDescription,
2912 taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
2913 callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
2914 userSetupComplete, minWidth, minHeight);
Garfield Tan367b35a2017-12-13 12:16:21 -08002915 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
2916 task.setBounds(lastNonFullscreenBounds);
Garfield Tan9b1efea2017-12-05 16:43:46 -08002917
2918 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
2919 activities.get(activityNdx).setTask(task);
2920 }
2921
2922 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
2923 return task;
2924 }
Garfield Tan1e740192017-12-12 14:37:42 -08002925
2926 void handleUnknownTag(String name, XmlPullParser in)
2927 throws IOException, XmlPullParserException {
2928 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
2929 XmlUtils.skipCurrentTag(in);
2930 }
Garfield Tan9b1efea2017-12-05 16:43:46 -08002931 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002932}