blob: 4845da1926386bbc5c9c2c5cfd313dc4abdc6930 [file] [log] [blame]
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08001/*
Louis Changcdec0802019-11-11 11:45:07 +08002 * Copyright (C) 2006 The Android Open Source Project
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Louis Changcdec0802019-11-11 11:45:07 +080019import static android.app.ActivityTaskManager.INVALID_TASK_ID;
20import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070021import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
Riddle Hsu9a8e3ae2020-03-24 15:22:48 +080022import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
23import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
24import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
Louis Changcdec0802019-11-11 11:45:07 +080025import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
26import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -080027import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
Louis Changcdec0802019-11-11 11:45:07 +080028import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
29import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
30import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Louis Changcdec0802019-11-11 11:45:07 +080031import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
32import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
33import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080034import static android.app.WindowConfiguration.activityTypeToString;
35import static android.app.WindowConfiguration.windowingModeToString;
Louis Changcdec0802019-11-11 11:45:07 +080036import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
37import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
38import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
39import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
40import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
41import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
42import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
43import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
44import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080045import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
Jason Monkba53d8a2017-04-06 18:28:19 +000046import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020047import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Louis Changcdec0802019-11-11 11:45:07 +080048import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
49import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
50import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
51import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Bryce Lee61fbcbc2017-03-10 14:14:03 -080052import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Louis Changcdec0802019-11-11 11:45:07 +080053import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
54import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
55import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
56import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
57import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -080058import static android.view.Display.INVALID_DISPLAY;
Evan Rosky9020c072018-12-06 14:11:12 -080059import static android.view.SurfaceControl.METADATA_TASK_ID;
Evan Rosky55bddd82020-01-29 13:07:18 -080060import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
chaviw8c9d1f52018-07-25 14:56:07 -070061
Vishnu Nairf6ef1c72020-01-23 16:28:33 -080062import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
63import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
Louis Changcdec0802019-11-11 11:45:07 +080064import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080065import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
Wale Ogunwale0db64ac2020-04-11 10:00:42 -070066import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
67import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
68import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
Louis Changcdec0802019-11-11 11:45:07 +080069import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
70import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
71import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
72import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
73import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
74import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
75import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
76import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
77import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
78import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
79import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
80import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
81import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080082import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
Evan Rosky55bddd82020-01-29 13:07:18 -080083import static com.android.server.wm.IdentifierProto.HASH_CODE;
84import static com.android.server.wm.IdentifierProto.TITLE;
85import static com.android.server.wm.IdentifierProto.USER_ID;
Louis Changcdec0802019-11-11 11:45:07 +080086import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
lumark04bceb92020-03-07 00:03:33 +080087import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
88import static com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
lumark9bca6b42019-10-17 18:35:22 +080089import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
90import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Vishnu Nairdddc9f52020-03-09 09:37:27 -070091import static com.android.server.wm.WindowContainerChildProto.TASK;
chaviw8c9d1f52018-07-25 14:56:07 -070092import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080093import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
chaviw8c9d1f52018-07-25 14:56:07 -070094import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -080095import static com.android.server.wm.WindowManagerService.dipToPixel;
lumark5341d1c2019-12-14 01:54:02 +080096import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Wale Ogunwale99db1862015-10-23 20:08:22 -070097
Louis Changcdec0802019-11-11 11:45:07 +080098import static java.lang.Integer.MAX_VALUE;
99
100import android.annotation.IntDef;
101import android.annotation.NonNull;
102import android.annotation.Nullable;
103import android.app.Activity;
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800104import android.app.ActivityManager;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100105import android.app.ActivityManager.TaskDescription;
Louis Changcdec0802019-11-11 11:45:07 +0800106import android.app.ActivityManager.TaskSnapshot;
107import android.app.ActivityOptions;
108import android.app.ActivityTaskManager;
109import android.app.AppGlobals;
Jorim Jaggi785edb42020-05-08 12:34:47 +0000110import android.app.PictureInPictureParams;
Louis Changcdec0802019-11-11 11:45:07 +0800111import android.app.TaskInfo;
112import android.app.WindowConfiguration;
113import android.content.ComponentName;
114import android.content.Intent;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800115import android.content.pm.ActivityInfo;
Louis Changcdec0802019-11-11 11:45:07 +0800116import android.content.pm.ApplicationInfo;
117import android.content.pm.IPackageManager;
118import android.content.pm.PackageManager;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700119import android.content.res.Configuration;
Louis Chang2570e332020-04-10 11:58:49 +0800120import android.graphics.Point;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700121import android.graphics.Rect;
Louis Changcdec0802019-11-11 11:45:07 +0800122import android.os.Debug;
Garfield Tan90b04282018-12-11 14:04:42 -0800123import android.os.IBinder;
Louis Changcdec0802019-11-11 11:45:07 +0800124import android.os.RemoteException;
125import android.os.SystemClock;
126import android.os.Trace;
127import android.os.UserHandle;
128import android.provider.Settings;
129import android.service.voice.IVoiceInteractionSession;
Evan Rosky55bddd82020-01-29 13:07:18 -0800130import android.util.ArraySet;
Louis Changcdec0802019-11-11 11:45:07 +0800131import android.util.DisplayMetrics;
Craig Mautner42bf39e2014-02-21 16:46:22 -0800132import android.util.Slog;
Evan Rosky55bddd82020-01-29 13:07:18 -0800133import android.util.proto.ProtoOutputStream;
Louis Changcdec0802019-11-11 11:45:07 +0800134import android.view.DisplayInfo;
Evan Rosky55bddd82020-01-29 13:07:18 -0800135import android.view.RemoteAnimationAdapter;
lumark19a5d2e2019-10-11 16:19:30 +0800136import android.view.RemoteAnimationTarget;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700137import android.view.Surface;
Winson Chungd41f71d2018-03-16 15:26:07 -0700138import android.view.SurfaceControl;
lumark04bceb92020-03-07 00:03:33 +0800139import android.view.WindowManager;
Garfield Tana7c9f7c2020-03-13 15:56:51 -0700140import android.window.ITaskOrganizer;
chaviw8c9d1f52018-07-25 14:56:07 -0700141
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800142import com.android.internal.annotations.VisibleForTesting;
Louis Changcdec0802019-11-11 11:45:07 +0800143import com.android.internal.app.IVoiceInteractor;
Louis Changcdec0802019-11-11 11:45:07 +0800144import com.android.internal.util.XmlUtils;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800145import com.android.internal.util.function.pooled.PooledConsumer;
146import com.android.internal.util.function.pooled.PooledFunction;
147import com.android.internal.util.function.pooled.PooledLambda;
148import com.android.internal.util.function.pooled.PooledPredicate;
Louis Changcdec0802019-11-11 11:45:07 +0800149import com.android.server.protolog.common.ProtoLog;
150import com.android.server.wm.ActivityStack.ActivityState;
Craig Mautner2c2549c2013-11-12 08:31:15 -0800151
Louis Changcdec0802019-11-11 11:45:07 +0800152import org.xmlpull.v1.XmlPullParser;
153import org.xmlpull.v1.XmlPullParserException;
154import org.xmlpull.v1.XmlSerializer;
155
156import java.io.IOException;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700157import java.io.PrintWriter;
Louis Changcdec0802019-11-11 11:45:07 +0800158import java.lang.annotation.Retention;
159import java.lang.annotation.RetentionPolicy;
160import java.util.ArrayList;
161import java.util.Objects;
Jorim Jaggi51304d72017-05-17 17:25:32 +0200162import java.util.function.Consumer;
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900163import java.util.function.Function;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800164import java.util.function.Predicate;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700165
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800166class Task extends WindowContainer<WindowContainer> {
Louis Changcdec0802019-11-11 11:45:07 +0800167 private static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_ATM;
168 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
169 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
170 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
171 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
172
173 private static final String ATTR_TASKID = "task_id";
174 private static final String TAG_INTENT = "intent";
175 private static final String TAG_AFFINITYINTENT = "affinity_intent";
176 private static final String ATTR_REALACTIVITY = "real_activity";
177 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
178 private static final String ATTR_ORIGACTIVITY = "orig_activity";
179 private static final String TAG_ACTIVITY = "activity";
180 private static final String ATTR_AFFINITY = "affinity";
181 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
182 private static final String ATTR_ROOTHASRESET = "root_has_reset";
183 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
184 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
185 private static final String ATTR_USERID = "user_id";
186 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
187 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
188 @Deprecated
189 private static final String ATTR_TASKTYPE = "task_type";
190 private static final String ATTR_LASTDESCRIPTION = "last_description";
191 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
192 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
193 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
194 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
195 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
196 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
197 private static final String ATTR_CALLING_UID = "calling_uid";
198 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Philip P. Moltmannee295092020-02-10 08:46:26 -0800199 private static final String ATTR_CALLING_FEATURE_ID = "calling_feature_id";
Louis Changcdec0802019-11-11 11:45:07 +0800200 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
201 private static final String ATTR_RESIZE_MODE = "resize_mode";
202 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
203 private static final String ATTR_MIN_WIDTH = "min_width";
204 private static final String ATTR_MIN_HEIGHT = "min_height";
205 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Garfield Tan5901e7c2020-02-07 17:12:22 -0800206 private static final String ATTR_WINDOW_LAYOUT_AFFINITY = "window_layout_affinity";
Louis Changcdec0802019-11-11 11:45:07 +0800207
208 // Current version of the task record we persist. Used to check if we need to run any upgrade
209 // code.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800210 static final int PERSIST_TASK_VERSION = 1;
Louis Changcdec0802019-11-11 11:45:07 +0800211
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800212 static final int INVALID_MIN_SIZE = -1;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -0800213 private float mShadowRadius = 0;
Louis Changcdec0802019-11-11 11:45:07 +0800214
215 /**
216 * The modes to control how the stack is moved to the front when calling {@link Task#reparent}.
217 */
218 @Retention(RetentionPolicy.SOURCE)
219 @IntDef({
220 REPARENT_MOVE_STACK_TO_FRONT,
221 REPARENT_KEEP_STACK_AT_FRONT,
222 REPARENT_LEAVE_STACK_IN_PLACE
223 })
224 @interface ReparentMoveStackMode {}
225 // Moves the stack to the front if it was not at the front
226 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
227 // Only moves the stack to the front if it was focused or front most already
228 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
229 // Do not move the stack as a part of reparenting
230 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
231
Louis Changcdec0802019-11-11 11:45:07 +0800232 String affinity; // The affinity name for this task, or null; may change identity.
233 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Garfield Tan5901e7c2020-02-07 17:12:22 -0800234 String mWindowLayoutAffinity; // Launch param affinity of this task or null. Used when saving
235 // launch params of this task.
Wale Ogunwale0d465192020-01-23 19:14:44 -0800236 IVoiceInteractionSession voiceSession; // Voice interaction session driving task
237 IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Louis Changcdec0802019-11-11 11:45:07 +0800238 Intent intent; // The original intent that started the task. Note that this value can
239 // be null.
240 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
241 int effectiveUid; // The current effective uid of the identity of this task.
242 ComponentName origActivity; // The non-alias activity component of the intent.
243 ComponentName realActivity; // The actual activity component that started the task.
244 boolean realActivitySuspended; // True if the actual activity component that started the
245 // task is suspended.
246 boolean inRecents; // Actually in the recents list?
247 long lastActiveTime; // Last time this task was active in the current device session,
248 // including sleep. This time is initialized to the elapsed time when
249 // restored from disk.
250 boolean isAvailable; // Is the activity available to be launched?
251 boolean rootWasReset; // True if the intent at the root of the task had
252 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
253 boolean autoRemoveRecents; // If true, we should automatically remove the task from
254 // recents when activity finishes
255 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Robert Carrde96c8a2020-03-24 15:22:21 -0700256 private boolean mHasBeenVisible; // Set if any activities in the task have been visible
Louis Changcdec0802019-11-11 11:45:07 +0800257
258 String stringName; // caching of toString() result.
259 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
260 // was changed.
261
Louis Changcdec0802019-11-11 11:45:07 +0800262 /** Can't be put in lockTask mode. */
263 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
264 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
265 final static int LOCK_TASK_AUTH_PINNABLE = 1;
266 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
267 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
268 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
269 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
270 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
271 * lockTask task. */
272 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
273 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
274
275 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
276
Louis Changcdec0802019-11-11 11:45:07 +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. */
280 private WindowProcessController mRootProcess;
281
282 /** Takes on same value as first root activity */
283 boolean isPersistable = false;
284 int maxRecents;
285
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. */
289 long mLastTimeMoved;
290
291 /** If original intent did not allow relinquishing task identity, save that information */
292 private boolean mNeverRelinquishIdentity = true;
293
294 // 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.
296 private boolean mReuseTask = false;
297
298 CharSequence lastDescription; // Last description captured for this item.
299
300 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
301 int mAffiliatedTaskColor; // color of the parent task affiliation.
302 Task mPrevAffiliate; // previous task in affiliated chain.
303 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
304 Task mNextAffiliate; // next task in affiliated chain.
305 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
306
307 // For relaunching the task from recents as though it was launched by the original launcher.
308 int mCallingUid;
309 String mCallingPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800310 String mCallingFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +0800311
312 private final Rect mTmpStableBounds = new Rect();
313 private final Rect mTmpNonDecorBounds = new Rect();
314 private final Rect mTmpBounds = new Rect();
315 private final Rect mTmpInsets = new Rect();
Evan Rosky70213702019-11-05 10:26:24 -0800316 private final Rect mTmpFullBounds = new Rect();
Louis Changcdec0802019-11-11 11:45:07 +0800317
318 // 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;
322 // Minimal width and height of this task when it's resizeable. -1 means it should use the
323 // default minimal width/height.
324 int mMinWidth;
325 int mMinHeight;
326
327 // 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
331 /** Helper object used for updating override configuration. */
332 private Configuration mTmpConfig = new Configuration();
333
334 /** Used by fillTaskInfo */
335 final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700336
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200337 final ActivityTaskManagerService mAtmService;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800338 final ActivityStackSupervisor mStackSupervisor;
339 final RootWindowContainer mRootWindowContainer;
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200340
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700341 /* Unique identifier for this task. */
Craig Mautner83162a92015-01-26 14:43:30 -0800342 final int mTaskId;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700343 /* User for which this task was created. */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200344 // TODO: Make final
345 int mUserId;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800346
Jorim Jaggi0429f352015-12-22 16:29:16 +0100347 final Rect mPreparedFrozenBounds = new Rect();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700348 final Configuration mPreparedFrozenMergedConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700349
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800350 // Id of the previous display the stack was on.
351 int mPrevDisplayId = INVALID_DISPLAY;
352
Garfield Tandec96db2018-10-30 11:28:49 -0700353 /** ID of the display which rotation {@link #mRotation} has. */
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800354 private int mLastRotationDisplayId = INVALID_DISPLAY;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800355
Garfield Tandec96db2018-10-30 11:28:49 -0700356 /**
357 * Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
358 * moved to a new display.
359 */
Vadim Caenfc14c662020-01-20 16:00:31 +0100360 @Surface.Rotation
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700361 private int mRotation;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700362
Garfield Tanafa0de82020-03-03 16:07:07 -0800363 /**
364 * Last requested orientation reported to DisplayContent. This is different from {@link
365 * #mOrientation} in the sense that this takes activities' requested orientation into
366 * account. Start with {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} so that we don't need
367 * to notify for activities that don't specify any orientation.
368 */
369 int mLastReportedRequestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
370
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700371 // For comparison with DisplayContent bounds.
372 private Rect mTmpRect = new Rect();
373 // For handling display rotations.
374 private Rect mTmpRect2 = new Rect();
375
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800376 // Resize mode of the task. See {@link ActivityInfo#resizeMode}
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200377 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
378 int mResizeMode;
Chong Zhangb15758a2015-11-17 12:12:03 -0800379
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200380 // Whether or not this task and its activities support PiP. Based on the
381 // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity.
382 boolean mSupportsPictureInPicture;
Winson Chungd3395382016-12-13 11:49:09 -0800383
Chong Zhang3005e752015-09-18 18:46:28 -0700384 // Whether the task is currently being drag-resized
385 private boolean mDragResizing;
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +0100386 private int mDragResizeMode;
Chong Zhang3005e752015-09-18 18:46:28 -0700387
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700388 // This represents the last resolved activity values for this task
389 // NOTE: This value needs to be persisted with each task
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100390 private TaskDescription mTaskDescription;
391
Robert Carr18f622f2017-05-08 11:20:43 -0700392 // If set to true, the task will report that it is not in the floating
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700393 // state regardless of it's stack affiliation. As the floating state drives
Robert Carr18f622f2017-05-08 11:20:43 -0700394 // production of content insets this can be used to preserve them across
395 // stack moves and we in fact do so when moving from full screen to pinned.
396 private boolean mPreserveNonFloatingState = false;
397
Robert Carrf59b8dd2017-10-02 18:58:36 -0700398 private Dimmer mDimmer = new Dimmer(this);
399 private final Rect mTmpDimBoundsRect = new Rect();
Louis Chang2570e332020-04-10 11:58:49 +0800400 private final Point mLastSurfaceSize = new Point();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700401
Jorim Jaggi50bf59c2018-03-09 17:29:48 +0100402 /** @see #setCanAffectSystemUiFlags */
403 private boolean mCanAffectSystemUiFlags = true;
404
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800405 private static Exception sTmpException;
406
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800407 /** ActivityRecords that are exiting, but still on screen for animations. */
408 final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
409
410 /**
411 * When we are in the process of pausing an activity, before starting the
412 * next one, this variable holds the activity that is currently being paused.
413 */
414 ActivityRecord mPausingActivity = null;
415
416 /**
417 * This is the last activity that we put into the paused state. This is
418 * used to determine if we need to do an activity transition while sleeping,
419 * when we normally hold the top activity paused.
420 */
421 ActivityRecord mLastPausedActivity = null;
422
423 /**
424 * Activities that specify No History must be removed once the user navigates away from them.
425 * If the device goes to sleep with such an activity in the paused state then we save it here
426 * and finish it later if another activity replaces it on wakeup.
427 */
428 ActivityRecord mLastNoHistoryActivity = null;
429
430 /** Current activity that is resumed, or null if there is none. */
431 ActivityRecord mResumedActivity = null;
432
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -0800433 private boolean mForceShowForAllUsers;
434
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800435 /** When set, will force the task to report as invisible. */
Robert Carrf6878a42019-12-18 02:13:12 -0800436 static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1;
437 static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1;
438 private int mForceHiddenFlags = 0;
439
Robert Carr711e7052020-02-19 11:14:33 -0800440 SurfaceControl.Transaction mMainWindowSizeChangeTransaction;
441
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800442 private final FindRootHelper mFindRootHelper = new FindRootHelper();
443 private class FindRootHelper {
444 private ActivityRecord mRoot;
445
446 private void clear() {
447 mRoot = null;
448 }
449
450 ActivityRecord findRoot(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
451 final PooledFunction f = PooledLambda.obtainFunction(FindRootHelper::processActivity,
452 this, PooledLambda.__(ActivityRecord.class), ignoreRelinquishIdentity,
453 setToBottomIfNone);
454 clear();
455 forAllActivities(f, false /*traverseTopToBottom*/);
456 f.recycle();
457 return mRoot;
458 }
459
460 private boolean processActivity(ActivityRecord r,
461 boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
462 if (mRoot == null && setToBottomIfNone) {
463 // This is the first activity we are process. Set it as the candidate root in case
464 // we don't find a better one.
465 mRoot = r;
466 }
467
468 if (r.finishing) return false;
469
470 // Set this as the candidate root since it isn't finishing.
471 mRoot = r;
472
473 // Only end search if we are ignore relinquishing identity or we are not relinquishing.
474 return ignoreRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
475 }
476 }
477
Louis Changcdec0802019-11-11 11:45:07 +0800478 /**
Robert Carr8a2f9132019-11-11 15:03:15 -0800479 * The TaskOrganizer which is delegated presentation of this task. If set the Task will
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700480 * emit an WindowContainerToken (allowing access to it's SurfaceControl leash) to the organizers
Robert Carr8a2f9132019-11-11 15:03:15 -0800481 * taskAppeared callback, and emit a taskRemoved callback when the Task is vanished.
482 */
483 ITaskOrganizer mTaskOrganizer;
Winson Chung77338ab2020-03-09 16:32:34 -0700484 private int mLastTaskOrganizerWindowingMode = -1;
Robert Carrde96c8a2020-03-24 15:22:21 -0700485 /**
486 * Prevent duplicate calls to onTaskAppeared.
487 */
488 boolean mTaskAppearedSent;
Robert Carr8a2f9132019-11-11 15:03:15 -0800489
Robert Carrf6690d12020-02-04 14:16:21 -0800490 /**
Jorim Jaggi785edb42020-05-08 12:34:47 +0000491 * Last Picture-in-Picture params applicable to the task. Updated when the app
492 * enters Picture-in-Picture or when setPictureInPictureParams is called.
493 */
494 PictureInPictureParams mPictureInPictureParams = new PictureInPictureParams.Builder().build();
495
496 /**
Louis Changa009c762020-02-26 11:21:31 +0800497 * This task was created by the task organizer which has the following implementations.
498 * <ul>
499 * <lis>The task won't be removed when it is empty. Removal has to be an explicit request
500 * from the task organizer.</li>
501 * <li>Unlike other non-root tasks, it's direct children are visible to the task
502 * organizer for ordering purposes.</li>
503 * </ul>
504 */
505 boolean mCreatedByOrganizer;
506
507 /**
Louis Changcdec0802019-11-11 11:45:07 +0800508 * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
509 * ActivityInfo, Intent, TaskDescription)} instead.
510 */
511 Task(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info, Intent _intent,
512 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
513 TaskDescription _taskDescription, ActivityStack stack) {
514 this(atmService, _taskId, _intent, null /*_affinityIntent*/, null /*_affinity*/,
515 null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
516 false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
517 UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
518 null /*_lastDescription*/, System.currentTimeMillis(),
519 true /*neverRelinquishIdentity*/,
520 _taskDescription != null ? _taskDescription : new TaskDescription(),
521 _taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
Philip P. Moltmannee295092020-02-10 08:46:26 -0800522 info.applicationInfo.uid, info.packageName, null /* default featureId */,
523 info.resizeMode, info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
Louis Changcdec0802019-11-11 11:45:07 +0800524 false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
525 _voiceSession, _voiceInteractor, stack);
526 }
527
528 /** Don't use constructor directly. This is only used by XML parser. */
Philip P. Moltmannee295092020-02-10 08:46:26 -0800529 Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent, Intent _affinityIntent,
530 String _affinity, String _rootAffinity, ComponentName _realActivity,
531 ComponentName _origActivity, boolean _rootWasReset, boolean _autoRemoveRecents,
532 boolean _askedCompatMode, int _userId, int _effectiveUid, String _lastDescription,
Louis Changcdec0802019-11-11 11:45:07 +0800533 long lastTimeMoved, boolean neverRelinquishIdentity,
534 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
535 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Philip P. Moltmannee295092020-02-10 08:46:26 -0800536 @Nullable String callingFeatureId, int resizeMode, boolean supportsPictureInPicture,
537 boolean _realActivitySuspended, boolean userSetupComplete, int minWidth, int minHeight,
538 ActivityInfo info, IVoiceInteractionSession _voiceSession,
539 IVoiceInteractor _voiceInteractor, ActivityStack stack) {
Louis Changcdec0802019-11-11 11:45:07 +0800540 super(atmService.mWindowManager);
541
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -0800542 EventLogTags.writeWmTaskCreated(_taskId, stack != null ? getRootTaskId() : INVALID_TASK_ID);
Louis Changcdec0802019-11-11 11:45:07 +0800543 mAtmService = atmService;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800544 mStackSupervisor = atmService.mStackSupervisor;
545 mRootWindowContainer = mAtmService.mRootWindowContainer;
Louis Changcdec0802019-11-11 11:45:07 +0800546 mTaskId = _taskId;
547 mUserId = _userId;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800548 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800549 mSupportsPictureInPicture = supportsPictureInPicture;
Louis Changcdec0802019-11-11 11:45:07 +0800550 mTaskDescription = _lastTaskDescription;
Riddle Hsu6b76cd32019-10-08 00:37:19 +0800551 // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
552 setOrientation(SCREEN_ORIENTATION_UNSET);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700553 mRemoteToken = new RemoteToken(this);
Louis Changcdec0802019-11-11 11:45:07 +0800554 affinityIntent = _affinityIntent;
555 affinity = _affinity;
556 rootAffinity = _rootAffinity;
557 voiceSession = _voiceSession;
558 voiceInteractor = _voiceInteractor;
559 realActivity = _realActivity;
560 realActivitySuspended = _realActivitySuspended;
561 origActivity = _origActivity;
562 rootWasReset = _rootWasReset;
563 isAvailable = true;
564 autoRemoveRecents = _autoRemoveRecents;
565 askedCompatMode = _askedCompatMode;
566 mUserSetupComplete = userSetupComplete;
567 effectiveUid = _effectiveUid;
568 touchActiveTime();
569 lastDescription = _lastDescription;
570 mLastTimeMoved = lastTimeMoved;
571 mNeverRelinquishIdentity = neverRelinquishIdentity;
572 mAffiliatedTaskId = taskAffiliation;
573 mAffiliatedTaskColor = taskAffiliationColor;
574 mPrevAffiliateTaskId = prevTaskId;
575 mNextAffiliateTaskId = nextTaskId;
576 mCallingUid = callingUid;
577 mCallingPackage = callingPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800578 mCallingFeatureId = callingFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +0800579 mResizeMode = resizeMode;
580 if (info != null) {
581 setIntent(_intent, info);
582 setMinDimensions(info);
583 } else {
584 intent = _intent;
585 mMinWidth = minWidth;
586 mMinHeight = minHeight;
587 }
588 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
589 }
590
Wale Ogunwale0d465192020-01-23 19:14:44 -0800591 Task reuseAsLeafTask(IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
Louis Changfbcf55f2020-03-02 12:27:15 +0800592 Intent intent, ActivityInfo info, ActivityRecord activity) {
Wale Ogunwale0d465192020-01-23 19:14:44 -0800593 voiceSession = _voiceSession;
594 voiceInteractor = _voiceInteractor;
Louis Changfbcf55f2020-03-02 12:27:15 +0800595 setIntent(activity, intent, info);
Wale Ogunwale0d465192020-01-23 19:14:44 -0800596 setMinDimensions(info);
Garfield Tana7c9f7c2020-03-13 15:56:51 -0700597 // Before we began to reuse a root task (old ActivityStack) as the leaf task, we used to
598 // create a leaf task in this case. Therefore now we won't send out the task created
599 // notification when we decide to reuse it here, so we send out the notification below.
600 // The reason why the created notification sent out when root task is created doesn't work
601 // is that realActivity isn't set until setIntent() method above is called for the first
602 // time. Eventually this notification will be removed when we can populate those information
603 // when root task is created.
604 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(mTaskId, realActivity);
Wale Ogunwale0d465192020-01-23 19:14:44 -0800605 return this;
606 }
607
Garfield Tan8b096b22020-01-07 14:55:20 -0800608 private void cleanUpResourcesForDestroy(ConfigurationContainer oldParent) {
Louis Changcdec0802019-11-11 11:45:07 +0800609 if (hasChild()) {
610 return;
611 }
612
Garfield Tan59a60fa2020-03-24 10:32:29 -0700613 if (isLeafTask()) {
Garfield Tan8b096b22020-01-07 14:55:20 -0800614 // This task is going away, so save the last state if necessary.
615 saveLaunchingStateIfNeeded(((WindowContainer) oldParent).getDisplayContent());
616 }
Louis Changcdec0802019-11-11 11:45:07 +0800617
618 // TODO: VI what about activity?
619 final boolean isVoiceSession = voiceSession != null;
620 if (isVoiceSession) {
621 try {
622 voiceSession.taskFinished(intent, mTaskId);
623 } catch (RemoteException e) {
624 }
625 }
626 if (autoRemoveFromRecents() || isVoiceSession) {
627 // Task creator asked to remove this when done, or this task was a voice
628 // interaction, so it should not remain on the recent tasks list.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800629 mStackSupervisor.mRecentTasks.remove(this);
Louis Changcdec0802019-11-11 11:45:07 +0800630 }
631
632 removeIfPossible();
633 }
634
635 @VisibleForTesting
636 @Override
637 void removeIfPossible() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800638 final boolean isRootTask = isRootTask();
639 if (!isRootTask) {
640 mAtmService.getLockTaskController().clearLockedTask(this);
641 }
Louis Changcdec0802019-11-11 11:45:07 +0800642 if (shouldDeferRemoval()) {
643 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId);
644 return;
645 }
646 removeImmediately();
Yuncheol Heo1c211c22020-04-20 13:08:43 -0700647 if (isLeafTask()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800648 mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
649 }
Louis Changcdec0802019-11-11 11:45:07 +0800650 }
651
652 void setResizeMode(int resizeMode) {
653 if (mResizeMode == resizeMode) {
654 return;
655 }
656 mResizeMode = resizeMode;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800657 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
658 mRootWindowContainer.resumeFocusedStacksTopActivities();
Louis Changcdec0802019-11-11 11:45:07 +0800659 updateTaskDescription();
660 }
661
Evan Rosky18e00a72020-05-08 09:36:27 -0700662 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow) {
Louis Changcdec0802019-11-11 11:45:07 +0800663 mAtmService.deferWindowLayout();
664
665 try {
666 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
667
668 if (getParent() == null) {
669 // Task doesn't exist in window manager yet (e.g. was restored from recents).
670 // All we can do for now is update the bounds so it can be used when the task is
671 // added to window manager.
672 setBounds(bounds);
673 if (!inFreeformWindowingMode()) {
674 // re-restore the task so it can have the proper stack association.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800675 mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
Louis Changcdec0802019-11-11 11:45:07 +0800676 }
677 return true;
678 }
679
680 if (!canResizeToBounds(bounds)) {
681 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
682 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
683 }
684
685 // Do not move the task to another stack here.
686 // This method assumes that the task is already placed in the right stack.
687 // we do not mess with that decision and we only do the resize!
688
689 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeTask_" + mTaskId);
690
691 boolean updatedConfig = false;
692 mTmpConfig.setTo(getResolvedOverrideConfiguration());
693 if (setBounds(bounds) != BOUNDS_CHANGE_NONE) {
694 updatedConfig = !mTmpConfig.equals(getResolvedOverrideConfiguration());
695 }
696 // This variable holds information whether the configuration didn't change in a
697 // significant way and the activity was kept the way it was. If it's false, it means
698 // the activity had to be relaunched due to configuration change.
699 boolean kept = true;
700 if (updatedConfig) {
701 final ActivityRecord r = topRunningActivityLocked();
Evan Rosky18e00a72020-05-08 09:36:27 -0700702 if (r != null) {
Louis Changcdec0802019-11-11 11:45:07 +0800703 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
704 preserveWindow);
705 // Preserve other windows for resizing because if resizing happens when there
706 // is a dialog activity in the front, the activity that still shows some
707 // content to the user will become black and cause flickers. Note in most cases
708 // this won't cause tons of irrelevant windows being preserved because only
709 // activities in this task may experience a bounds change. Configs for other
710 // activities stay the same.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800711 mRootWindowContainer.ensureActivitiesVisible(r, 0, preserveWindow);
Louis Changcdec0802019-11-11 11:45:07 +0800712 if (!kept) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800713 mRootWindowContainer.resumeFocusedStacksTopActivities();
Louis Changcdec0802019-11-11 11:45:07 +0800714 }
715 }
716 }
717 resize(kept, forced);
718
719 saveLaunchingStateIfNeeded();
720
721 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
722 return kept;
723 } finally {
724 mAtmService.continueWindowLayout();
725 }
726 }
727
728 /** Convenience method to reparent a task to the top or bottom position of the stack. */
729 boolean reparent(ActivityStack preferredStack, boolean toTop,
730 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
731 String reason) {
732 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
733 true /* schedulePictureInPictureModeChange */, reason);
734 }
735
736 /**
737 * Convenience method to reparent a task to the top or bottom position of the stack, with
738 * an option to skip scheduling the picture-in-picture mode change.
739 */
740 boolean reparent(ActivityStack preferredStack, boolean toTop,
741 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
742 boolean schedulePictureInPictureModeChange, String reason) {
743 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
744 deferResume, schedulePictureInPictureModeChange, reason);
745 }
746
747 /** Convenience method to reparent a task to a specific position of the stack. */
748 boolean reparent(ActivityStack preferredStack, int position,
749 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
750 String reason) {
751 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
752 true /* schedulePictureInPictureModeChange */, reason);
753 }
754
755 /**
756 * Reparents the task into a preferred stack, creating it if necessary.
757 *
758 * @param preferredStack the target stack to move this task
759 * @param position the position to place this task in the new stack
760 * @param animate whether or not we should wait for the new window created as a part of the
761 * reparenting to be drawn and animated in
762 * @param moveStackMode whether or not to move the stack to the front always, only if it was
763 * previously focused & in front, or never
764 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
765 * have changed as a result of this reparenting
766 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
767 * change. Callers may set this to false if they are explicitly scheduling PiP mode
768 * changes themselves, like during the PiP animation
769 * @param reason the caller of this reparenting
770 * @return whether the task was reparented
771 */
772 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
773 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
774 boolean reparent(ActivityStack preferredStack, int position,
775 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
776 boolean schedulePictureInPictureModeChange, String reason) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800777 final ActivityStackSupervisor supervisor = mStackSupervisor;
778 final RootWindowContainer root = mRootWindowContainer;
Louis Changcdec0802019-11-11 11:45:07 +0800779 final WindowManagerService windowManager = mAtmService.mWindowManager;
780 final ActivityStack sourceStack = getStack();
781 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
782 position == MAX_VALUE);
783 if (toStack == sourceStack) {
784 return false;
785 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800786 if (!canBeLaunchedOnDisplay(toStack.getDisplayId())) {
Louis Changcdec0802019-11-11 11:45:07 +0800787 return false;
788 }
789
790 final boolean toTopOfStack = position == MAX_VALUE;
791 if (toTopOfStack && toStack.getResumedActivity() != null
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900792 && toStack.topRunningActivity() != null) {
Louis Changcdec0802019-11-11 11:45:07 +0800793 // Pause the resumed activity on the target stack while re-parenting task on top of it.
794 toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
795 null /* resuming */);
796 }
797
798 final int toStackWindowingMode = toStack.getWindowingMode();
Wale Ogunwale21e06482019-11-18 05:14:15 -0800799 final ActivityRecord topActivity = getTopNonFinishingActivity();
Louis Changcdec0802019-11-11 11:45:07 +0800800
801 final boolean mightReplaceWindow = topActivity != null
802 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
803 if (mightReplaceWindow) {
804 // We are about to relaunch the activity because its configuration changed due to
805 // being maximized, i.e. size change. The activity will first remove the old window
806 // and then add a new one. This call will tell window manager about this, so it can
807 // preserve the old window until the new one is drawn. This prevents having a gap
808 // between the removal and addition, in which no window is visible. We also want the
809 // entrance of the new window to be properly animated.
810 // Note here we always set the replacing window first, as the flags might be needed
811 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
812 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
813 }
814
815 mAtmService.deferWindowLayout();
816 boolean kept = true;
817 try {
818 final ActivityRecord r = topRunningActivityLocked();
Louis Changcdec0802019-11-11 11:45:07 +0800819 final boolean wasFocused = r != null && root.isTopDisplayFocusedStack(sourceStack)
820 && (topRunningActivityLocked() == r);
821 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
822 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
823
824 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
825 // Whenever we are moving the top activity from the front stack we want to make sure to
826 // move the stack to the front.
Andrii Kulian86d676c2020-03-27 19:34:54 -0700827 final boolean wasFront = r != null && sourceStack.isTopStackInDisplayArea()
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900828 && (sourceStack.topRunningActivity() == r);
Louis Changcdec0802019-11-11 11:45:07 +0800829
830 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
831 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
832
833 reparent(toStack, position, moveStackToFront, reason);
834
835 if (schedulePictureInPictureModeChange) {
836 // Notify of picture-in-picture mode changes
837 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
838 }
839
840 // If the task had focus before (or we're requested to move focus), move focus to the
841 // new stack by moving the stack to the front.
842 if (r != null) {
843 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
844 wasPaused, reason);
845 }
846 if (!animate) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800847 mStackSupervisor.mNoAnimActivities.add(topActivity);
Louis Changcdec0802019-11-11 11:45:07 +0800848 }
849
850 // We might trigger a configuration change. Save the current task bounds for freezing.
851 // TODO: Should this call be moved inside the resize method in WM?
852 toStack.prepareFreezingTaskBounds();
853
Evan Rosky18e00a72020-05-08 09:36:27 -0700854 if (toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
855 && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
856 // Move recents to front so it is not behind home stack when going into docked
857 // mode
858 mStackSupervisor.moveRecentsStackToFront(reason);
Louis Changcdec0802019-11-11 11:45:07 +0800859 }
860 } finally {
861 mAtmService.continueWindowLayout();
862 }
863
864 if (mightReplaceWindow) {
865 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
866 // window), we need to clear the replace window settings. Otherwise, we schedule a
867 // timeout to remove the old window if the replacing window is not coming in time.
868 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
869 }
870
871 if (!deferResume) {
872 // The task might have already been running and its visibility needs to be synchronized
873 // with the visibility of the stack / windows.
874 root.ensureActivitiesVisible(null, 0, !mightReplaceWindow);
875 root.resumeFocusedStacksTopActivities();
876 }
877
878 // TODO: Handle incorrect request to move before the actual move, not after.
879 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Andrii Kulian1cb59dd2020-04-10 12:17:17 -0700880 mRootWindowContainer.getDefaultTaskDisplayArea(), toStack);
Louis Changcdec0802019-11-11 11:45:07 +0800881
882 return (preferredStack == toStack);
883 }
884
885 /**
886 * @return {@code true} if the windows of tasks being moved to the target stack from the
887 * source stack should be replaced, meaning that window manager will keep the old window
888 * around until the new is ready.
889 */
890 private static boolean replaceWindowsOnTaskMove(
891 int sourceWindowingMode, int targetWindowingMode) {
892 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
893 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
894 }
895
896 /**
897 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
898 */
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800899 TaskSnapshot getSnapshot(boolean isLowResolution, boolean restoreFromDisk) {
Louis Changcdec0802019-11-11 11:45:07 +0800900
901 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
902 // synchronized between AM and WM.
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800903 return mAtmService.mWindowManager.getTaskSnapshot(mTaskId, mUserId, isLowResolution,
Louis Changcdec0802019-11-11 11:45:07 +0800904 restoreFromDisk);
905 }
906
907 void touchActiveTime() {
908 lastActiveTime = SystemClock.elapsedRealtime();
909 }
910
911 long getInactiveDuration() {
912 return SystemClock.elapsedRealtime() - lastActiveTime;
913 }
914
Louis Changfbcf55f2020-03-02 12:27:15 +0800915 /** @see #setIntent(ActivityRecord, Intent, ActivityInfo) */
Louis Changcdec0802019-11-11 11:45:07 +0800916 void setIntent(ActivityRecord r) {
Louis Changfbcf55f2020-03-02 12:27:15 +0800917 setIntent(r, null /* intent */, null /* info */);
918 }
919
920 /**
921 * Sets the original intent, and the calling uid and package.
922 *
923 * @param r The activity that started the task
924 * @param intent The task info which could be different from {@code r.intent} if set.
925 * @param info The activity info which could be different from {@code r.info} if set.
926 */
927 void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) {
Louis Changcdec0802019-11-11 11:45:07 +0800928 mCallingUid = r.launchedFromUid;
929 mCallingPackage = r.launchedFromPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800930 mCallingFeatureId = r.launchedFromFeatureId;
Louis Changfbcf55f2020-03-02 12:27:15 +0800931 setIntent(intent != null ? intent : r.intent, info != null ? info : r.info);
Louis Changcdec0802019-11-11 11:45:07 +0800932 setLockTaskAuth(r);
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800933
934 final WindowContainer parent = getParent();
935 if (parent != null) {
936 final Task t = parent.asTask();
937 if (t != null) {
938 t.setIntent(r);
939 }
940 }
Louis Changcdec0802019-11-11 11:45:07 +0800941 }
942
943 /** Sets the original intent, _without_ updating the calling uid or package. */
944 private void setIntent(Intent _intent, ActivityInfo info) {
945 if (intent == null) {
946 mNeverRelinquishIdentity =
947 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
948 } else if (mNeverRelinquishIdentity) {
949 return;
950 }
951
952 affinity = info.taskAffinity;
953 if (intent == null) {
954 // If this task already has an intent associated with it, don't set the root
955 // affinity -- we don't want it changing after initially set, but the initially
956 // set value may be null.
957 rootAffinity = affinity;
958 }
959 effectiveUid = info.applicationInfo.uid;
960 stringName = null;
961
962 if (info.targetActivity == null) {
963 if (_intent != null) {
964 // If this Intent has a selector, we want to clear it for the
965 // recent task since it is not relevant if the user later wants
966 // to re-launch the app.
967 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
968 _intent = new Intent(_intent);
969 _intent.setSelector(null);
970 _intent.setSourceBounds(null);
971 }
972 }
973 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
974 intent = _intent;
975 realActivity = _intent != null ? _intent.getComponent() : null;
976 origActivity = null;
977 } else {
978 ComponentName targetComponent = new ComponentName(
979 info.packageName, info.targetActivity);
980 if (_intent != null) {
981 Intent targetIntent = new Intent(_intent);
982 targetIntent.setSelector(null);
983 targetIntent.setSourceBounds(null);
984 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
985 "Setting Intent of " + this + " to target " + targetIntent);
986 intent = targetIntent;
987 realActivity = targetComponent;
988 origActivity = _intent.getComponent();
989 } else {
990 intent = null;
991 realActivity = targetComponent;
992 origActivity = new ComponentName(info.packageName, info.name);
993 }
994 }
Garfield Tan5901e7c2020-02-07 17:12:22 -0800995 mWindowLayoutAffinity =
996 info.windowLayout == null ? null : info.windowLayout.windowLayoutAffinity;
Louis Changcdec0802019-11-11 11:45:07 +0800997
998 final int intentFlags = intent == null ? 0 : intent.getFlags();
999 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1000 // Once we are set to an Intent with this flag, we count this
1001 // task as having a true root activity.
1002 rootWasReset = true;
1003 }
1004 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
1005 mUserSetupComplete = Settings.Secure.getIntForUser(
1006 mAtmService.mContext.getContentResolver(), USER_SETUP_COMPLETE, 0, mUserId) != 0;
1007 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
1008 // If the activity itself has requested auto-remove, then just always do it.
1009 autoRemoveRecents = true;
1010 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
1011 == FLAG_ACTIVITY_NEW_DOCUMENT) {
1012 // If the caller has not asked for the document to be retained, then we may
1013 // want to turn on auto-remove, depending on whether the target has set its
1014 // own document launch mode.
1015 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
1016 autoRemoveRecents = false;
1017 } else {
1018 autoRemoveRecents = true;
1019 }
1020 } else {
1021 autoRemoveRecents = false;
1022 }
1023 if (mResizeMode != info.resizeMode) {
1024 mResizeMode = info.resizeMode;
1025 updateTaskDescription();
1026 }
1027 mSupportsPictureInPicture = info.supportsPictureInPicture();
1028 }
1029
1030 /** Sets the original minimal width and height. */
Wale Ogunwale0d465192020-01-23 19:14:44 -08001031 void setMinDimensions(ActivityInfo info) {
Louis Changcdec0802019-11-11 11:45:07 +08001032 if (info != null && info.windowLayout != null) {
1033 mMinWidth = info.windowLayout.minWidth;
1034 mMinHeight = info.windowLayout.minHeight;
1035 } else {
1036 mMinWidth = INVALID_MIN_SIZE;
1037 mMinHeight = INVALID_MIN_SIZE;
1038 }
1039 }
1040
1041 /**
1042 * Return true if the input activity has the same intent filter as the intent this task
1043 * record is based on (normally the root activity intent).
1044 */
1045 boolean isSameIntentFilter(ActivityRecord r) {
1046 final Intent intent = new Intent(r.intent);
1047 // Make sure the component are the same if the input activity has the same real activity
1048 // as the one in the task because either one of them could be the alias activity.
1049 if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) {
1050 intent.setComponent(this.intent.getComponent());
1051 }
1052 return intent.filterEquals(this.intent);
1053 }
1054
1055 boolean returnsToHomeStack() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001056 if (inMultiWindowMode() || !hasChild()) return false;
1057 if (intent != null) {
1058 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
1059 return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
1060 }
1061 final Task bottomTask = getBottomMostTask();
1062 return bottomTask != this && bottomTask.returnsToHomeStack();
Louis Changcdec0802019-11-11 11:45:07 +08001063 }
1064
1065 void setPrevAffiliate(Task prevAffiliate) {
1066 mPrevAffiliate = prevAffiliate;
1067 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.mTaskId;
1068 }
1069
1070 void setNextAffiliate(Task nextAffiliate) {
1071 mNextAffiliate = nextAffiliate;
1072 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
1073 }
1074
Louis Changcdec0802019-11-11 11:45:07 +08001075 @Override
1076 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001077 final DisplayContent display = newParent != null
1078 ? ((WindowContainer) newParent).getDisplayContent() : null;
1079 final DisplayContent oldDisplay = oldParent != null
1080 ? ((WindowContainer) oldParent).getDisplayContent() : null;
1081
1082 mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
Louis Changcdec0802019-11-11 11:45:07 +08001083
Louis Chang8bda2322019-12-05 16:38:11 +08001084 if (oldParent != null && newParent == null) {
Garfield Tan8b096b22020-01-07 14:55:20 -08001085 cleanUpResourcesForDestroy(oldParent);
Louis Chang8bda2322019-12-05 16:38:11 +08001086 }
1087
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001088 if (display != null) {
1089 // TODO(NOW!): Chat with the erosky@ of this code to see if this really makes sense here...
1090 // Rotations are relative to the display. This means if there are 2 displays rotated
1091 // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
1092 // from one to the other could look like a rotation change. To prevent this
1093 // apparent rotation change (and corresponding bounds rotation), pretend like our
1094 // current rotation is already the same as the new display.
1095 // Note, if ActivityStack or related logic ever gets nested, this logic will need
1096 // to move to onConfigurationChanged.
1097 getConfiguration().windowConfiguration.setRotation(
1098 display.getWindowConfiguration().getRotation());
1099 }
1100
Louis Changcdec0802019-11-11 11:45:07 +08001101 super.onParentChanged(newParent, oldParent);
1102
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001103 // TODO(NOW): The check for null display content and setting it to null doesn't really
1104 // make sense here...
Louis Changcdec0802019-11-11 11:45:07 +08001105
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001106 // TODO(stack-merge): This is mostly taking care of the case where the stask is removing from
1107 // the display, so we should probably consolidate it there instead.
1108
1109 if (getParent() == null && mDisplayContent != null) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08001110 EventLogTags.writeWmStackRemoved(getRootTaskId());
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001111 mDisplayContent = null;
1112 mWmService.mWindowPlacerLocked.requestTraversal();
1113 }
1114
1115 if (oldParent != null) {
1116 final Task oldParentTask = ((WindowContainer) oldParent).asTask();
1117 if (oldParentTask != null) {
1118 final PooledConsumer c = PooledLambda.obtainConsumer(
1119 Task::cleanUpActivityReferences, oldParentTask,
1120 PooledLambda.__(ActivityRecord.class));
1121 forAllActivities(c);
1122 c.recycle();
1123 }
1124
1125 if (oldParent.inPinnedWindowingMode()
1126 && (newParent == null || !newParent.inPinnedWindowingMode())) {
Louis Changcdec0802019-11-11 11:45:07 +08001127 // Notify if a task from the pinned stack is being removed
1128 // (or moved depending on the mode).
1129 mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
1130 }
1131 }
1132
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001133 if (newParent != null) {
1134 final Task newParentTask = ((WindowContainer) newParent).asTask();
1135 if (newParentTask != null) {
1136 final ActivityRecord top = newParentTask.getTopNonFinishingActivity(
1137 false /* includeOverlays */);
1138 if (top != null && top.isState(RESUMED)) {
1139 newParentTask.setResumedActivity(top, "addedToTask");
1140 }
1141 }
Louis Changcdec0802019-11-11 11:45:07 +08001142
1143 // TODO: Ensure that this is actually necessary here
1144 // Notify the voice session if required
1145 if (voiceSession != null) {
1146 try {
1147 voiceSession.taskStarted(intent, mTaskId);
1148 } catch (RemoteException e) {
1149 }
1150 }
1151 }
1152
1153 // First time we are adding the task to the system.
1154 if (oldParent == null && newParent != null) {
1155
1156 // TODO: Super random place to be doing this, but aligns with what used to be done
1157 // before we unified Task level. Look into if this can be done in a better place.
1158 updateOverrideConfigurationFromLaunchBounds();
1159 }
1160
Louis Changcdec0802019-11-11 11:45:07 +08001161 // Update task bounds if needed.
1162 adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
1163
1164 if (getWindowConfiguration().windowsAreScaleable()) {
1165 // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
1166 // while a resize is pending.
1167 forceWindowsScaleable(true /* force */);
1168 } else {
1169 forceWindowsScaleable(false /* force */);
1170 }
1171
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001172 mRootWindowContainer.updateUIDsPresentOnDisplay();
1173 }
1174
1175 void cleanUpActivityReferences(ActivityRecord r) {
1176 final WindowContainer parent = getParent();
1177 if (parent != null && parent.asTask() != null) {
1178 parent.asTask().cleanUpActivityReferences(r);
1179 return;
1180 }
1181 r.removeTimeouts();
1182 mExitingActivities.remove(r);
1183
1184 if (mResumedActivity != null && mResumedActivity == r) {
1185 setResumedActivity(null, "cleanUpActivityReferences");
1186 }
1187 if (mPausingActivity != null && mPausingActivity == r) {
1188 mPausingActivity = null;
1189 }
1190 }
1191
1192 /** @return the currently resumed activity. */
1193 ActivityRecord getResumedActivity() {
1194 return mResumedActivity;
1195 }
1196
1197 void setResumedActivity(ActivityRecord r, String reason) {
1198 if (mResumedActivity == r) {
1199 return;
1200 }
1201
1202 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) Slog.d(TAG_STACK,
1203 "setResumedActivity stack:" + this + " + from: "
1204 + mResumedActivity + " to:" + r + " reason:" + reason);
1205 mResumedActivity = r;
1206 mStackSupervisor.updateTopResumedActivityIfNeeded();
Louis Changcdec0802019-11-11 11:45:07 +08001207 }
1208
1209 void updateTaskMovement(boolean toFront) {
1210 if (isPersistable) {
1211 mLastTimeMoved = System.currentTimeMillis();
1212 // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
1213 // recently will be most negative, tasks sent to the bottom before that will be less
1214 // negative. Similarly for recent tasks moved to the top which will be most positive.
1215 if (!toFront) {
1216 mLastTimeMoved *= -1;
1217 }
1218 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001219 mRootWindowContainer.invalidateTaskLayers();
Louis Changcdec0802019-11-11 11:45:07 +08001220 }
1221
Louis Changcdec0802019-11-11 11:45:07 +08001222 // Close up recents linked list.
1223 private void closeRecentsChain() {
1224 if (mPrevAffiliate != null) {
1225 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
1226 }
1227 if (mNextAffiliate != null) {
1228 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
1229 }
1230 setPrevAffiliate(null);
1231 setNextAffiliate(null);
1232 }
1233
1234 void removedFromRecents() {
1235 closeRecentsChain();
1236 if (inRecents) {
1237 inRecents = false;
1238 mAtmService.notifyTaskPersisterLocked(this, false);
1239 }
1240
1241 clearRootProcess();
1242
1243 mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
1244 mTaskId, mUserId);
1245 }
1246
1247 void setTaskToAffiliateWith(Task taskToAffiliateWith) {
1248 closeRecentsChain();
1249 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
1250 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
1251 // Find the end
1252 while (taskToAffiliateWith.mNextAffiliate != null) {
1253 final Task nextRecents = taskToAffiliateWith.mNextAffiliate;
1254 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1255 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1256 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1257 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1258 nextRecents.setPrevAffiliate(null);
1259 }
1260 taskToAffiliateWith.setNextAffiliate(null);
1261 break;
1262 }
1263 taskToAffiliateWith = nextRecents;
1264 }
1265 taskToAffiliateWith.setNextAffiliate(this);
1266 setPrevAffiliate(taskToAffiliateWith);
1267 setNextAffiliate(null);
1268 }
1269
1270 /** Returns the intent for the root activity for this task */
1271 Intent getBaseIntent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001272 if (intent != null) return intent;
1273 if (affinityIntent != null) return affinityIntent;
1274 // Probably a task that contains other tasks, so return the intent for the top task?
1275 final Task topTask = getTopMostTask();
Evan Rosky0037e5f2019-11-05 10:26:24 -08001276 return (topTask != this && topTask != null) ? topTask.getBaseIntent() : null;
Louis Changcdec0802019-11-11 11:45:07 +08001277 }
1278
1279 /** Returns the first non-finishing activity from the bottom. */
1280 ActivityRecord getRootActivity() {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001281 // TODO: Figure out why we historical ignore relinquish identity for this case...
1282 return getRootActivity(true /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
1283 }
1284
1285 ActivityRecord getRootActivity(boolean setToBottomIfNone) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001286 return getRootActivity(false /*ignoreRelinquishIdentity*/, setToBottomIfNone);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001287 }
1288
1289 ActivityRecord getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001290 return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone);
Louis Changcdec0802019-11-11 11:45:07 +08001291 }
1292
Wale Ogunwale21e06482019-11-18 05:14:15 -08001293 ActivityRecord getTopNonFinishingActivity() {
1294 return getTopNonFinishingActivity(true /* includeOverlays */);
Louis Changcdec0802019-11-11 11:45:07 +08001295 }
1296
Wale Ogunwale21e06482019-11-18 05:14:15 -08001297 ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001298 return getTopActivity(false /*includeFinishing*/, includeOverlays);
Louis Changcdec0802019-11-11 11:45:07 +08001299 }
1300
1301 ActivityRecord topRunningActivityLocked() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001302 if (getParent() == null) {
1303 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001304 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001305 return getActivity(ActivityRecord::canBeTopRunning);
Louis Changcdec0802019-11-11 11:45:07 +08001306 }
1307
1308 /**
1309 * Return true if any activities in this task belongs to input uid.
1310 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001311 boolean isUidPresent(int uid) {
1312 final PooledPredicate p = PooledLambda.obtainPredicate(
1313 ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid);
1314 final boolean isUidPresent = getActivity(p) != null;
1315 p.recycle();
1316 return isUidPresent;
Louis Changcdec0802019-11-11 11:45:07 +08001317 }
1318
1319 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001320 if (getParent() == null) {
1321 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001322 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001323 return getActivity((r) -> r.mStartingWindowState == STARTING_WINDOW_SHOWN
1324 && r.canBeTopRunning());
Louis Changcdec0802019-11-11 11:45:07 +08001325 }
1326
1327 /**
1328 * Return the number of running activities, and the number of non-finishing/initializing
1329 * activities in the provided {@param reportOut} respectively.
1330 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001331 private void getNumRunningActivities(TaskActivitiesReport reportOut) {
Louis Changcdec0802019-11-11 11:45:07 +08001332 reportOut.reset();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001333 forAllActivities(reportOut);
Louis Changcdec0802019-11-11 11:45:07 +08001334 }
1335
1336 /**
1337 * Reorder the history stack so that the passed activity is brought to the front.
1338 */
1339 final void moveActivityToFrontLocked(ActivityRecord newTop) {
1340 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, "Removing and adding activity "
1341 + newTop + " to stack at top callers=" + Debug.getCallers(4));
1342
1343 positionChildAtTop(newTop);
1344 updateEffectiveIntent();
1345 }
1346
1347 @Override
1348 public int getActivityType() {
1349 final int applicationType = super.getActivityType();
1350 if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
1351 return applicationType;
1352 }
Louis Changa009c762020-02-26 11:21:31 +08001353 return getTopChild().getActivityType();
Louis Changcdec0802019-11-11 11:45:07 +08001354 }
1355
1356 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001357 void addChild(WindowContainer child, int index) {
Louis Changcdec0802019-11-11 11:45:07 +08001358 // If this task had any child before we added this one.
1359 boolean hadChild = hasChild();
Evan Rosky660b1752020-04-15 18:07:15 -07001360 // getActivityType() looks at the top child, so we need to read the type before adding
1361 // a new child in case the new child is on top and UNDEFINED.
1362 final int activityType = getActivityType();
Louis Changcdec0802019-11-11 11:45:07 +08001363
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001364 index = getAdjustedChildPosition(child, index);
1365 super.addChild(child, index);
Louis Changcdec0802019-11-11 11:45:07 +08001366
1367 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001368
Louis Changa009c762020-02-26 11:21:31 +08001369 // A rootable task that is now being added to be the child of an organized task. Making
1370 // sure the stack references is keep updated.
1371 if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001372 getDisplayArea().addStackReferenceIfNeeded((ActivityStack) child);
Louis Changa009c762020-02-26 11:21:31 +08001373 }
1374
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001375 // Make sure the list of display UID whitelists is updated
1376 // now that this record is in a new task.
1377 mRootWindowContainer.updateUIDsPresentOnDisplay();
1378
1379 final ActivityRecord r = child.asActivityRecord();
1380 if (r == null) return;
1381
Louis Changcdec0802019-11-11 11:45:07 +08001382 r.inHistory = true;
1383
Louis Changcdec0802019-11-11 11:45:07 +08001384 // Only set this based on the first activity
1385 if (!hadChild) {
1386 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1387 // Normally non-standard activity type for the activity record will be set when the
1388 // object is created, however we delay setting the standard application type until
1389 // this point so that the task can set the type for additional activities added in
1390 // the else condition below.
1391 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1392 }
1393 setActivityType(r.getActivityType());
1394 isPersistable = r.isPersistable();
1395 mCallingUid = r.launchedFromUid;
1396 mCallingPackage = r.launchedFromPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -08001397 mCallingFeatureId = r.launchedFromFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +08001398 // Clamp to [1, max].
1399 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1400 ActivityTaskManager.getMaxAppRecentsLimitStatic());
1401 } else {
1402 // Otherwise make all added activities match this one.
Evan Rosky660b1752020-04-15 18:07:15 -07001403 r.setActivityType(activityType);
Louis Changcdec0802019-11-11 11:45:07 +08001404 }
1405
1406 updateEffectiveIntent();
Louis Changcdec0802019-11-11 11:45:07 +08001407 }
1408
1409 void addChild(ActivityRecord r) {
1410 addChild(r, Integer.MAX_VALUE /* add on top */);
1411 }
1412
1413 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001414 void removeChild(WindowContainer child) {
1415 removeChild(child, "removeChild");
1416 }
1417
1418 void removeChild(WindowContainer r, String reason) {
Riddle Hsu9adc55f2020-04-28 17:07:33 +08001419 // A rootable child task that is now being removed from an organized task. Making sure
1420 // the stack references is keep updated.
1421 if (mTaskOrganizer != null && mCreatedByOrganizer && r.asTask() != null) {
1422 getDisplayArea().removeStackReferenceIfNeeded((ActivityStack) r);
1423 }
Louis Changcdec0802019-11-11 11:45:07 +08001424 if (!mChildren.contains(r)) {
1425 Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
1426 return;
1427 }
1428
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001429 if (DEBUG_TASK_MOVEMENT) {
1430 Slog.d(TAG_WM, "removeChild: child=" + r + " reason=" + reason);
1431 }
Louis Changcdec0802019-11-11 11:45:07 +08001432 super.removeChild(r);
Louis Changcdec0802019-11-11 11:45:07 +08001433
1434 if (inPinnedWindowingMode()) {
1435 // We normally notify listeners of task stack changes on pause, however pinned stack
1436 // activities are normally in the paused state so no notification will be sent there
1437 // before the activity is removed. We send it here so instead.
1438 mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
1439 }
1440
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001441 final boolean isRootTask = isRootTask();
1442 if (isRootTask) {
1443 final DisplayContent display = getDisplayContent();
1444 if (display.isSingleTaskInstance()) {
1445 mAtmService.notifySingleTaskDisplayEmpty(display.mDisplayId);
1446 }
1447 display.mDisplayContent.setLayoutNeeded();
1448 }
1449
Louis Changcdec0802019-11-11 11:45:07 +08001450 if (hasChild()) {
1451 updateEffectiveIntent();
1452
1453 // The following block can be executed multiple times if there is more than one overlay.
1454 // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
1455 // of the task by id and exiting early if not found.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001456 if (onlyHasTaskOverlayActivities(true /*includeFinishing*/)) {
Louis Changcdec0802019-11-11 11:45:07 +08001457 // When destroying a task, tell the supervisor to remove it so that any activity it
1458 // has can be cleaned up correctly. This is currently the only place where we remove
1459 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
1460 // state into removeChild(), we just clear the task here before the other residual
1461 // work.
1462 // TODO: If the callers to removeChild() changes such that we have multiple places
1463 // where we are destroying the task, move this back into removeChild()
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001464 mStackSupervisor.removeTask(this, false /* killProcess */,
Louis Changcdec0802019-11-11 11:45:07 +08001465 !REMOVE_FROM_RECENTS, reason);
1466 }
Louis Changa009c762020-02-26 11:21:31 +08001467 } else if (!mReuseTask && !mCreatedByOrganizer) {
Louis Changcdec0802019-11-11 11:45:07 +08001468 // Remove entire task if it doesn't have any activity left and it isn't marked for reuse
Louis Changa009c762020-02-26 11:21:31 +08001469 // or created by task organizer.
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001470 if (!isRootTask) {
1471 getStack().removeChild(this, reason);
1472 }
Jeff Changd136e772019-11-05 20:33:52 +08001473 EventLogTags.writeWmTaskRemoved(mTaskId,
Louis Changcdec0802019-11-11 11:45:07 +08001474 "removeChild: last r=" + r + " in t=" + this);
1475 removeIfPossible();
1476 }
1477 }
1478
1479 /**
Louis Changfd5539e2020-02-04 14:34:24 +08001480 * @return whether or not there are ONLY task overlay activities in the task.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001481 * If {@param includeFinishing} is set, then don't ignore finishing activities in the
1482 * check. If there are no task overlay activities, this call returns false.
Louis Changcdec0802019-11-11 11:45:07 +08001483 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001484 boolean onlyHasTaskOverlayActivities(boolean includeFinishing) {
Louis Changfd5539e2020-02-04 14:34:24 +08001485 int count = 0;
1486 for (int i = getChildCount() - 1; i >= 0; i--) {
1487 final ActivityRecord r = getChildAt(i).asActivityRecord();
1488 if (r == null) {
1489 // Has a child that is other than Activity.
1490 return false;
1491 }
1492 if (!includeFinishing && r.finishing) {
1493 continue;
1494 }
1495 if (!r.isTaskOverlay()) {
1496 return false;
1497 }
1498 count++;
Louis Changcdec0802019-11-11 11:45:07 +08001499 }
Louis Changfd5539e2020-02-04 14:34:24 +08001500 return count > 0;
Louis Changcdec0802019-11-11 11:45:07 +08001501 }
1502
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001503 private boolean autoRemoveFromRecents() {
Louis Changcdec0802019-11-11 11:45:07 +08001504 // We will automatically remove the task either if it has explicitly asked for
1505 // this, or it is empty and has never contained an activity that got shown to
1506 // the user.
Robert Carrde96c8a2020-03-24 15:22:21 -07001507 return autoRemoveRecents || (!hasChild() && !getHasBeenVisible());
Louis Changcdec0802019-11-11 11:45:07 +08001508 }
1509
1510 /**
1511 * Completely remove all activities associated with an existing
1512 * task starting at a specified index.
1513 */
Wale Ogunwale21e06482019-11-18 05:14:15 -08001514 private void performClearTaskAtIndexLocked(String reason) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001515 // Broken down into to cases to avoid object create due to capturing mStack.
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001516 if (getStack() == null) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001517 forAllActivities((r) -> {
1518 if (r.finishing) return;
Louis Changcdec0802019-11-11 11:45:07 +08001519 // Task was restored from persistent storage.
1520 r.takeFromHistory();
1521 removeChild(r);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001522 });
1523 } else {
1524 forAllActivities((r) -> {
1525 if (r.finishing) return;
1526 // TODO: figure-out how to avoid object creation due to capture of reason variable.
1527 r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
1528 false /* oomAdj */);
1529 });
Louis Changcdec0802019-11-11 11:45:07 +08001530 }
1531 }
1532
1533 /**
1534 * Completely remove all activities associated with an existing task.
1535 */
1536 void performClearTaskLocked() {
1537 mReuseTask = true;
Wale Ogunwale21e06482019-11-18 05:14:15 -08001538 performClearTaskAtIndexLocked("clear-task-all");
Louis Changcdec0802019-11-11 11:45:07 +08001539 mReuseTask = false;
1540 }
1541
1542 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1543 mReuseTask = true;
1544 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1545 mReuseTask = false;
1546 return result;
1547 }
1548
1549 /**
1550 * Perform clear operation as requested by
1551 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1552 * stack to the given task, then look for
1553 * an instance of that activity in the stack and, if found, finish all
1554 * activities on top of it and return the instance.
1555 *
1556 * @param newR Description of the new activity being started.
1557 * @return Returns the old activity that should be continued to be used,
1558 * or {@code null} if none was found.
1559 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001560 private ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
1561 final ActivityRecord r = findActivityInHistory(newR.mActivityComponent);
1562 if (r == null) return null;
Louis Changcdec0802019-11-11 11:45:07 +08001563
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001564 final PooledFunction f = PooledLambda.obtainFunction(Task::finishActivityAbove,
1565 PooledLambda.__(ActivityRecord.class), r);
1566 forAllActivities(f);
1567 f.recycle();
Louis Changcdec0802019-11-11 11:45:07 +08001568
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001569 // Finally, if this is a normal launch mode (that is, not expecting onNewIntent()), then we
1570 // will finish the current instance of the activity so a new fresh one can be started.
1571 if (r.launchMode == ActivityInfo.LAUNCH_MULTIPLE
1572 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1573 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
1574 if (!r.finishing) {
1575 r.finishIfPossible("clear-task-top", false /* oomAdj */);
1576 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001577 }
1578 }
1579
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001580 return r;
1581 }
1582
1583 private static boolean finishActivityAbove(ActivityRecord r, ActivityRecord boundaryActivity) {
1584 // Stop operation once we reach the boundary activity.
1585 if (r == boundaryActivity) return true;
1586
1587 if (!r.finishing) {
1588 final ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
1589 if (opts != null) {
1590 // TODO: Why is this updating the boundary activity vs. the current activity???
1591 boundaryActivity.updateOptionsLocked(opts);
1592 }
1593 r.finishIfPossible("clear-task-stack", false /* oomAdj */);
1594 }
1595
1596 return false;
Louis Changcdec0802019-11-11 11:45:07 +08001597 }
1598
1599 void removeTaskActivitiesLocked(String reason) {
1600 // Just remove the entire task.
Wale Ogunwale21e06482019-11-18 05:14:15 -08001601 performClearTaskAtIndexLocked(reason);
Louis Changcdec0802019-11-11 11:45:07 +08001602 }
1603
1604 String lockTaskAuthToString() {
1605 switch (mLockTaskAuth) {
1606 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1607 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1608 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1609 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
1610 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
1611 default: return "unknown=" + mLockTaskAuth;
1612 }
1613 }
1614
1615 void setLockTaskAuth() {
1616 setLockTaskAuth(getRootActivity());
1617 }
1618
1619 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1620 if (r == null) {
1621 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1622 return;
1623 }
1624
1625 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
1626 final LockTaskController lockTaskController = mAtmService.getLockTaskController();
1627 switch (r.lockTaskLaunchMode) {
1628 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
1629 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
1630 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
1631 break;
1632
1633 case LOCK_TASK_LAUNCH_MODE_NEVER:
1634 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
1635 break;
1636
1637 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
1638 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
1639 break;
1640
1641 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
1642 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
1643 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
1644 break;
1645 }
1646 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this
1647 + " mLockTaskAuth=" + lockTaskAuthToString());
1648 }
1649
1650 @Override
1651 public boolean supportsSplitScreenWindowingMode() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001652 final Task topTask = getTopMostTask();
1653 return super.supportsSplitScreenWindowingMode()
1654 && (topTask == null || topTask.supportsSplitScreenWindowingModeInner());
1655 }
1656
1657 private boolean supportsSplitScreenWindowingModeInner() {
Louis Changcdec0802019-11-11 11:45:07 +08001658 // A task can not be docked even if it is considered resizeable because it only supports
1659 // picture-in-picture mode but has a non-resizeable resizeMode
1660 return super.supportsSplitScreenWindowingMode()
Louis Changcdec0802019-11-11 11:45:07 +08001661 && mAtmService.mSupportsSplitScreenMultiWindow
1662 && (mAtmService.mForceResizableActivities
1663 || (isResizeable(false /* checkSupportsPip */)
1664 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
1665 }
1666
1667 /**
1668 * Check whether this task can be launched on the specified display.
1669 *
1670 * @param displayId Target display id.
1671 * @return {@code true} if either it is the default display or this activity can be put on a
1672 * secondary display.
1673 */
1674 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001675 return mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Louis Changcdec0802019-11-11 11:45:07 +08001676 -1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
1677 }
1678
1679 /**
1680 * Check that a given bounds matches the application requested orientation.
1681 *
1682 * @param bounds The bounds to be tested.
1683 * @return True if the requested bounds are okay for a resizing request.
1684 */
1685 private boolean canResizeToBounds(Rect bounds) {
1686 if (bounds == null || !inFreeformWindowingMode()) {
1687 // Note: If not on the freeform workspace, we ignore the bounds.
1688 return true;
1689 }
1690 final boolean landscape = bounds.width() > bounds.height();
1691 final Rect configBounds = getRequestedOverrideBounds();
1692 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
1693 return configBounds.isEmpty()
1694 || landscape == (configBounds.width() > configBounds.height());
1695 }
1696 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1697 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1698 }
1699
1700 /**
1701 * @return {@code true} if the task is being cleared for the purposes of being reused.
1702 */
1703 boolean isClearingToReuseTask() {
1704 return mReuseTask;
1705 }
1706
1707 /**
1708 * Find the activity in the history stack within the given task. Returns
1709 * the index within the history at which it's found, or < 0 if not found.
1710 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001711 ActivityRecord findActivityInHistory(ComponentName component) {
1712 final PooledPredicate p = PooledLambda.obtainPredicate(Task::matchesActivityInHistory,
1713 PooledLambda.__(ActivityRecord.class), component);
1714 final ActivityRecord r = getActivity(p);
1715 p.recycle();
1716 return r;
1717 }
1718
1719 private static boolean matchesActivityInHistory(
1720 ActivityRecord r, ComponentName activityComponent) {
1721 return !r.finishing && r.mActivityComponent.equals(activityComponent);
Louis Changcdec0802019-11-11 11:45:07 +08001722 }
1723
1724 /** Updates the last task description values. */
1725 void updateTaskDescription() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001726 final ActivityRecord root = getRootActivity(true);
1727 if (root == null) return;
1728
1729 final TaskDescription taskDescription = new TaskDescription();
1730 final PooledFunction f = PooledLambda.obtainFunction(
1731 Task::setTaskDescriptionFromActivityAboveRoot,
1732 PooledLambda.__(ActivityRecord.class), root, taskDescription);
1733 forAllActivities(f);
1734 f.recycle();
1735 taskDescription.setResizeMode(mResizeMode);
1736 taskDescription.setMinWidth(mMinWidth);
1737 taskDescription.setMinHeight(mMinHeight);
1738 setTaskDescription(taskDescription);
1739 // Update the task affiliation color if we are the parent of the group
1740 if (mTaskId == mAffiliatedTaskId) {
1741 mAffiliatedTaskColor = taskDescription.getPrimaryColor();
Louis Changcdec0802019-11-11 11:45:07 +08001742 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001743 mAtmService.getTaskChangeNotificationController().notifyTaskDescriptionChanged(
1744 getTaskInfo());
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001745
1746 final WindowContainer parent = getParent();
1747 if (parent != null) {
1748 final Task t = parent.asTask();
1749 if (t != null) {
1750 t.updateTaskDescription();
1751 }
1752 }
Winson Chung1df39e22020-04-09 14:30:55 -07001753
1754 if (isOrganized()) {
1755 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
1756 }
Louis Changcdec0802019-11-11 11:45:07 +08001757 }
1758
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001759 private static boolean setTaskDescriptionFromActivityAboveRoot(
1760 ActivityRecord r, ActivityRecord root, TaskDescription td) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001761 if (!r.isTaskOverlay() && r.taskDescription != null) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001762 final TaskDescription atd = r.taskDescription;
1763 if (td.getLabel() == null) {
1764 td.setLabel(atd.getLabel());
Louis Changcdec0802019-11-11 11:45:07 +08001765 }
Winson Chungd6722032020-02-18 15:16:08 -08001766 if (td.getRawIcon() == null) {
1767 td.setIcon(atd.getRawIcon());
Louis Changcdec0802019-11-11 11:45:07 +08001768 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001769 if (td.getIconFilename() == null) {
1770 td.setIconFilename(atd.getIconFilename());
1771 }
1772 if (td.getPrimaryColor() == 0) {
1773 td.setPrimaryColor(atd.getPrimaryColor());
1774 }
1775 if (td.getBackgroundColor() == 0) {
1776 td.setBackgroundColor(atd.getBackgroundColor());
1777 }
1778 if (td.getStatusBarColor() == 0) {
1779 td.setStatusBarColor(atd.getStatusBarColor());
1780 td.setEnsureStatusBarContrastWhenTransparent(
1781 atd.getEnsureStatusBarContrastWhenTransparent());
1782 }
1783 if (td.getNavigationBarColor() == 0) {
1784 td.setNavigationBarColor(atd.getNavigationBarColor());
1785 td.setEnsureNavigationBarContrastWhenTransparent(
1786 atd.getEnsureNavigationBarContrastWhenTransparent());
1787 }
1788
Louis Changcdec0802019-11-11 11:45:07 +08001789 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001790
1791 // End search once we get to root.
1792 return r == root;
Louis Changcdec0802019-11-11 11:45:07 +08001793 }
1794
1795 // TODO (AM refactor): Invoke automatically when there is a change in children
1796 @VisibleForTesting
1797 void updateEffectiveIntent() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001798 final ActivityRecord root = getRootActivity(true /*setToBottomIfNone*/);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001799 if (root != null) {
1800 setIntent(root);
1801 // Update the task description when the activities change
1802 updateTaskDescription();
1803 }
Louis Changcdec0802019-11-11 11:45:07 +08001804 }
1805
Riddle Hsudd49c632020-04-30 22:39:51 +08001806 void adjustForMinimalTaskDimensions(@NonNull Rect bounds, @NonNull Rect previousBounds,
1807 @NonNull Configuration parentConfig) {
Louis Changcdec0802019-11-11 11:45:07 +08001808 int minWidth = mMinWidth;
1809 int minHeight = mMinHeight;
1810 // If the task has no requested minimal size, we'd like to enforce a minimal size
1811 // so that the user can not render the task too small to manipulate. We don't need
1812 // to do this for the pinned stack as the bounds are controlled by the system.
Riddle Hsudd49c632020-04-30 22:39:51 +08001813 if (!inPinnedWindowingMode()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001814 final int defaultMinSizeDp = mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp;
Riddle Hsudd49c632020-04-30 22:39:51 +08001815 final float density = (float) parentConfig.densityDpi / DisplayMetrics.DENSITY_DEFAULT;
Louis Changcdec0802019-11-11 11:45:07 +08001816 final int defaultMinSize = (int) (defaultMinSizeDp * density);
1817
1818 if (minWidth == INVALID_MIN_SIZE) {
1819 minWidth = defaultMinSize;
1820 }
1821 if (minHeight == INVALID_MIN_SIZE) {
1822 minHeight = defaultMinSize;
1823 }
1824 }
Evan Rosky70213702019-11-05 10:26:24 -08001825 if (bounds.isEmpty()) {
1826 // If inheriting parent bounds, check if parent bounds adhere to minimum size. If they
1827 // do, we can just skip.
Riddle Hsudd49c632020-04-30 22:39:51 +08001828 final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
Evan Rosky70213702019-11-05 10:26:24 -08001829 if (parentBounds.width() >= minWidth && parentBounds.height() >= minHeight) {
1830 return;
1831 }
1832 bounds.set(parentBounds);
1833 }
Louis Changcdec0802019-11-11 11:45:07 +08001834 final boolean adjustWidth = minWidth > bounds.width();
1835 final boolean adjustHeight = minHeight > bounds.height();
1836 if (!(adjustWidth || adjustHeight)) {
1837 return;
1838 }
1839
1840 if (adjustWidth) {
1841 if (!previousBounds.isEmpty() && bounds.right == previousBounds.right) {
1842 bounds.left = bounds.right - minWidth;
1843 } else {
1844 // Either left bounds match, or neither match, or the previous bounds were
1845 // fullscreen and we default to keeping left.
1846 bounds.right = bounds.left + minWidth;
1847 }
1848 }
1849 if (adjustHeight) {
1850 if (!previousBounds.isEmpty() && bounds.bottom == previousBounds.bottom) {
1851 bounds.top = bounds.bottom - minHeight;
1852 } else {
1853 // Either top bounds match, or neither match, or the previous bounds were
1854 // fullscreen and we default to keeping top.
1855 bounds.bottom = bounds.top + minHeight;
1856 }
1857 }
1858 }
1859
1860 void setLastNonFullscreenBounds(Rect bounds) {
1861 if (mLastNonFullscreenBounds == null) {
1862 mLastNonFullscreenBounds = new Rect(bounds);
1863 } else {
1864 mLastNonFullscreenBounds.set(bounds);
1865 }
1866 }
1867
1868 /**
1869 * This should be called when an child activity changes state. This should only
1870 * be called from
1871 * {@link ActivityRecord#setState(ActivityState, String)} .
1872 * @param record The {@link ActivityRecord} whose state has changed.
1873 * @param state The new state.
1874 * @param reason The reason for the change.
1875 */
1876 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001877 final Task parentTask = getParent().asTask();
1878 if (parentTask != null) {
1879 parentTask.onActivityStateChanged(record, state, reason);
Louis Changa009c762020-02-26 11:21:31 +08001880 // We still want to update the resumed activity if the parent task is created by
1881 // organizer in order to keep the information synced once got reparented out from the
1882 // organized task.
1883 if (!parentTask.mCreatedByOrganizer) {
1884 return;
1885 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001886 }
Louis Changcdec0802019-11-11 11:45:07 +08001887
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001888 if (record == mResumedActivity && state != RESUMED) {
1889 setResumedActivity(null, reason + " - onActivityStateChanged");
1890 }
1891
1892 if (state == RESUMED) {
1893 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
1894 Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" + reason);
1895 }
1896 setResumedActivity(record, reason + " - onActivityStateChanged");
1897 if (record == mRootWindowContainer.getTopResumedActivity()) {
1898 mAtmService.setResumedActivityUncheckLocked(record, reason);
1899 }
1900 mStackSupervisor.mRecentTasks.add(record.getTask());
Louis Changcdec0802019-11-11 11:45:07 +08001901 }
1902 }
1903
1904 @Override
1905 public void onConfigurationChanged(Configuration newParentConfig) {
1906 // Check if the new configuration supports persistent bounds (eg. is Freeform) and if so
1907 // restore the last recorded non-fullscreen bounds.
1908 final boolean prevPersistTaskBounds = getWindowConfiguration().persistTaskBounds();
Ben Lin50038ee2020-04-24 17:09:12 -07001909 boolean nextPersistTaskBounds =
1910 getRequestedOverrideConfiguration().windowConfiguration.persistTaskBounds();
1911 if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_UNDEFINED) {
1912 nextPersistTaskBounds = newParentConfig.windowConfiguration.persistTaskBounds();
1913 }
Louis Changcdec0802019-11-11 11:45:07 +08001914 if (!prevPersistTaskBounds && nextPersistTaskBounds
1915 && mLastNonFullscreenBounds != null && !mLastNonFullscreenBounds.isEmpty()) {
1916 // Bypass onRequestedOverrideConfigurationChanged here to avoid infinite loop.
1917 getRequestedOverrideConfiguration().windowConfiguration
1918 .setBounds(mLastNonFullscreenBounds);
1919 }
1920
Evan Rosky55bddd82020-01-29 13:07:18 -08001921 final int prevWinMode = getWindowingMode();
1922 mTmpPrevBounds.set(getBounds());
Louis Changcdec0802019-11-11 11:45:07 +08001923 final boolean wasInMultiWindowMode = inMultiWindowMode();
Hongwei Wang5c52ff82020-04-20 16:02:30 -07001924 final boolean wasInPictureInPicture = inPinnedWindowingMode();
Louis Changcdec0802019-11-11 11:45:07 +08001925 super.onConfigurationChanged(newParentConfig);
Louis Chang2570e332020-04-10 11:58:49 +08001926 // Only need to update surface size here since the super method will handle updating
1927 // surface position.
1928 updateSurfaceSize(getPendingTransaction());
1929
Hongwei Wang5c52ff82020-04-20 16:02:30 -07001930 if (wasInPictureInPicture != inPinnedWindowingMode()) {
1931 mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, getStack());
1932 } else if (wasInMultiWindowMode != inMultiWindowMode()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001933 mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Louis Changcdec0802019-11-11 11:45:07 +08001934 }
1935
Evan Rosky55bddd82020-01-29 13:07:18 -08001936 final int newWinMode = getWindowingMode();
1937 if ((prevWinMode != newWinMode) && (mDisplayContent != null)
1938 && shouldStartChangeTransition(prevWinMode, newWinMode)) {
1939 initializeChangeTransition(mTmpPrevBounds);
1940 }
1941
Louis Changcdec0802019-11-11 11:45:07 +08001942 // If the configuration supports persistent bounds (eg. Freeform), keep track of the
1943 // current (non-fullscreen) bounds for persistence.
1944 if (getWindowConfiguration().persistTaskBounds()) {
1945 final Rect currentBounds = getRequestedOverrideBounds();
1946 if (!currentBounds.isEmpty()) {
1947 setLastNonFullscreenBounds(currentBounds);
1948 }
1949 }
1950 // TODO: Should also take care of Pip mode changes here.
1951
1952 saveLaunchingStateIfNeeded();
Evan Roskyf64f5da2020-03-16 13:47:48 -07001953 final boolean taskOrgChanged = updateTaskOrganizerState(false /* forceUpdate */);
1954 // If the task organizer has changed, then it will already be receiving taskAppeared with
1955 // the latest task-info thus the task-info won't have changed.
Winson Chung1df39e22020-04-09 14:30:55 -07001956 if (!taskOrgChanged && isOrganized()) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07001957 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, false /* force */);
1958 }
Louis Changcdec0802019-11-11 11:45:07 +08001959 }
1960
1961 /**
Evan Rosky55bddd82020-01-29 13:07:18 -08001962 * Initializes a change transition. See {@link SurfaceFreezer} for more information.
1963 */
1964 private void initializeChangeTransition(Rect startBounds) {
1965 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1966 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1967 mDisplayContent.mChangingContainers.add(this);
1968
1969 mSurfaceFreezer.freeze(getPendingTransaction(), startBounds);
1970 }
1971
1972 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
1973 if (mWmService.mDisableTransitionAnimation
1974 || !isVisible()
1975 || getDisplayContent().mAppTransition.isTransitionSet()
Evan Rosky8d4ee722020-04-21 17:28:31 -07001976 || getSurfaceControl() == null
1977 || !isLeafTask()) {
Evan Rosky55bddd82020-01-29 13:07:18 -08001978 return false;
1979 }
1980 // Only do an animation into and out-of freeform mode for now. Other mode
1981 // transition animations are currently handled by system-ui.
1982 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1983 }
1984
chaviwda7b3c22020-04-24 11:25:08 -07001985 @Override
1986 void migrateToNewSurfaceControl() {
1987 super.migrateToNewSurfaceControl();
1988 mLastSurfaceSize.x = 0;
1989 mLastSurfaceSize.y = 0;
1990 updateSurfaceSize(getPendingTransaction());
1991 }
1992
Louis Chang2570e332020-04-10 11:58:49 +08001993 void updateSurfaceSize(SurfaceControl.Transaction transaction) {
Robert Carr1530eee2020-05-05 15:15:01 -07001994 if (mSurfaceControl == null || isOrganized()) {
Louis Chang2570e332020-04-10 11:58:49 +08001995 return;
1996 }
1997
1998 // Apply crop to root tasks only and clear the crops of the descendant tasks.
1999 int width = 0;
2000 int height = 0;
2001 if (isRootTask()) {
2002 final Rect taskBounds = getBounds();
2003 width = taskBounds.width();
2004 height = taskBounds.height();
2005
2006 final int outset = getTaskOutset();
2007 width += 2 * outset;
2008 height += 2 * outset;
2009 }
2010 if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
2011 return;
2012 }
2013 transaction.setWindowCrop(mSurfaceControl, width, height);
2014 mLastSurfaceSize.set(width, height);
2015 }
2016
2017 /**
2018 * Calculate an amount by which to expand the task bounds in each direction.
2019 * Used to make room for shadows in the pinned windowing mode.
2020 */
2021 int getTaskOutset() {
2022 // If we are drawing shadows on the task then don't outset the stack.
2023 if (mWmService.mRenderShadowsInCompositor) {
2024 return 0;
2025 }
2026 DisplayContent displayContent = getDisplayContent();
2027 if (inPinnedWindowingMode() && displayContent != null) {
2028 final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
2029
2030 // We multiply by two to match the client logic for converting view elevation
2031 // to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets}
2032 return (int) Math.ceil(
2033 mWmService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP, displayMetrics)
2034 * 2);
2035 }
2036 return 0;
2037 }
2038
2039 @VisibleForTesting
2040 Point getLastSurfaceSize() {
2041 return mLastSurfaceSize;
2042 }
2043
Evan Rosky55bddd82020-01-29 13:07:18 -08002044 @VisibleForTesting
2045 boolean isInChangeTransition() {
2046 return mSurfaceFreezer.hasLeash() || AppTransition.isChangeTransit(mTransit);
2047 }
2048
2049 @Override
2050 public SurfaceControl getFreezeSnapshotTarget() {
2051 final int transit = mDisplayContent.mAppTransition.getAppTransition();
2052 if (!AppTransition.isChangeTransit(transit)) {
2053 return null;
2054 }
2055 // Skip creating snapshot if this transition is controlled by a remote animator which
2056 // doesn't need it.
2057 final ArraySet<Integer> activityTypes = new ArraySet<>();
2058 activityTypes.add(getActivityType());
2059 final RemoteAnimationAdapter adapter =
2060 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
2061 this, transit, activityTypes);
2062 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
2063 return null;
2064 }
2065 return getSurfaceControl();
2066 }
2067
2068 @Override
2069 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
2070 final long token = proto.start(fieldId);
2071 proto.write(HASH_CODE, System.identityHashCode(this));
2072 proto.write(USER_ID, mUserId);
2073 proto.write(TITLE, intent != null && intent.getComponent() != null
2074 ? intent.getComponent().flattenToShortString() : "Task");
2075 proto.end(token);
2076 }
2077
2078 /**
Louis Changcdec0802019-11-11 11:45:07 +08002079 * Saves launching state if necessary so that we can launch the activity to its latest state.
2080 * It only saves state if this task has been shown to user and it's in fullscreen or freeform
2081 * mode on freeform displays.
2082 */
Garfield Tan8b096b22020-01-07 14:55:20 -08002083 private void saveLaunchingStateIfNeeded() {
2084 saveLaunchingStateIfNeeded(getDisplayContent());
2085 }
2086
2087 private void saveLaunchingStateIfNeeded(DisplayContent display) {
Robert Carrde96c8a2020-03-24 15:22:21 -07002088 if (!getHasBeenVisible()) {
Louis Changcdec0802019-11-11 11:45:07 +08002089 // Not ever visible to user.
2090 return;
2091 }
2092
2093 final int windowingMode = getWindowingMode();
2094 if (windowingMode != WINDOWING_MODE_FULLSCREEN
2095 && windowingMode != WINDOWING_MODE_FREEFORM) {
2096 return;
2097 }
2098
2099 // Don't persist state if display isn't in freeform mode. Then the task will be launched
2100 // back to its last state in a freeform display when it's launched in a freeform display
2101 // next time.
2102 if (getWindowConfiguration().getDisplayWindowingMode() != WINDOWING_MODE_FREEFORM) {
2103 return;
2104 }
2105
2106 // Saves the new state so that we can launch the activity at the same location.
Garfield Tan8b096b22020-01-07 14:55:20 -08002107 mStackSupervisor.mLaunchParamsPersister.saveTask(this, display);
Louis Changcdec0802019-11-11 11:45:07 +08002108 }
2109
2110 /**
2111 * Adjust bounds to stay within stack bounds.
2112 *
2113 * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
2114 * that keep them unchanged, but be contained within the stack bounds.
2115 *
2116 * @param bounds Bounds to be adjusted.
2117 * @param stackBounds Bounds within which the other bounds should remain.
2118 * @param overlapPxX The amount of px required to be visible in the X dimension.
2119 * @param overlapPxY The amount of px required to be visible in the Y dimension.
2120 */
2121 private static void fitWithinBounds(Rect bounds, Rect stackBounds, int overlapPxX,
2122 int overlapPxY) {
2123 if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
2124 return;
2125 }
2126
2127 // For each side of the parent (eg. left), check if the opposing side of the window (eg.
2128 // right) is at least overlap pixels away. If less, offset the window by that difference.
2129 int horizontalDiff = 0;
2130 // If window is smaller than overlap, use it's smallest dimension instead
2131 int overlapLR = Math.min(overlapPxX, bounds.width());
2132 if (bounds.right < (stackBounds.left + overlapLR)) {
2133 horizontalDiff = overlapLR - (bounds.right - stackBounds.left);
2134 } else if (bounds.left > (stackBounds.right - overlapLR)) {
2135 horizontalDiff = -(overlapLR - (stackBounds.right - bounds.left));
2136 }
2137 int verticalDiff = 0;
2138 int overlapTB = Math.min(overlapPxY, bounds.width());
2139 if (bounds.bottom < (stackBounds.top + overlapTB)) {
2140 verticalDiff = overlapTB - (bounds.bottom - stackBounds.top);
2141 } else if (bounds.top > (stackBounds.bottom - overlapTB)) {
2142 verticalDiff = -(overlapTB - (stackBounds.bottom - bounds.top));
2143 }
2144 bounds.offset(horizontalDiff, verticalDiff);
2145 }
2146
2147 /**
2148 * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
2149 * intersectBounds on a side, then the respective side will not be intersected.
2150 *
2151 * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
2152 * inset on that side is no-longer applicable. This scenario happens when a task's minimal
2153 * bounds are larger than the provided parent/display bounds.
2154 *
2155 * @param inOutBounds the bounds to intersect.
2156 * @param intersectBounds the bounds to intersect with.
2157 * @param intersectInsets insets to apply to intersectBounds before intersecting.
2158 */
2159 static void intersectWithInsetsIfFits(
2160 Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
2161 if (inOutBounds.right <= intersectBounds.right) {
2162 inOutBounds.right =
2163 Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
2164 }
2165 if (inOutBounds.bottom <= intersectBounds.bottom) {
2166 inOutBounds.bottom =
2167 Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
2168 }
2169 if (inOutBounds.left >= intersectBounds.left) {
2170 inOutBounds.left =
2171 Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
2172 }
2173 if (inOutBounds.top >= intersectBounds.top) {
2174 inOutBounds.top =
2175 Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
2176 }
2177 }
2178
2179 /**
2180 * Gets bounds with non-decor and stable insets applied respectively.
2181 *
2182 * If bounds overhangs the display, those edges will not get insets. See
2183 * {@link #intersectWithInsetsIfFits}
2184 *
2185 * @param outNonDecorBounds where to place bounds with non-decor insets applied.
2186 * @param outStableBounds where to place bounds with stable insets applied.
2187 * @param bounds the bounds to inset.
2188 */
2189 private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
2190 DisplayInfo displayInfo) {
2191 outNonDecorBounds.set(bounds);
2192 outStableBounds.set(bounds);
2193 if (getStack() == null || getStack().getDisplay() == null) {
2194 return;
2195 }
2196 DisplayPolicy policy = getStack().getDisplay().mDisplayContent.getDisplayPolicy();
2197 if (policy == null) {
2198 return;
2199 }
2200 mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
2201
2202 policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
2203 displayInfo.logicalHeight, displayInfo.displayCutout, mTmpInsets);
2204 intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);
2205
2206 policy.convertNonDecorInsetsToStableInsets(mTmpInsets, displayInfo.rotation);
2207 intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
2208 }
2209
Riddle Hsu23e18a92020-03-10 00:26:51 +08002210 /**
2211 * Forces the app bounds related configuration can be computed by
2212 * {@link #computeConfigResourceOverrides(Configuration, Configuration, DisplayInfo,
2213 * ActivityRecord.CompatDisplayInsets)}.
2214 */
2215 private static void invalidateAppBoundsConfig(@NonNull Configuration inOutConfig) {
2216 final Rect appBounds = inOutConfig.windowConfiguration.getAppBounds();
2217 if (appBounds != null) {
2218 appBounds.setEmpty();
2219 }
2220 inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
2221 inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
2222 }
2223
Louis Changcdec0802019-11-11 11:45:07 +08002224 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Riddle Hsu9264a272020-03-04 23:10:41 +08002225 @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo) {
2226 if (overrideDisplayInfo != null) {
2227 // Make sure the screen related configs can be computed by the provided display info.
Riddle Hsu9264a272020-03-04 23:10:41 +08002228 inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
Riddle Hsu23e18a92020-03-10 00:26:51 +08002229 invalidateAppBoundsConfig(inOutConfig);
Riddle Hsu9264a272020-03-04 23:10:41 +08002230 }
2231 computeConfigResourceOverrides(inOutConfig, parentConfig, overrideDisplayInfo,
2232 null /* compatInsets */);
2233 }
2234
2235 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Louis Changcdec0802019-11-11 11:45:07 +08002236 @NonNull Configuration parentConfig) {
Riddle Hsu9264a272020-03-04 23:10:41 +08002237 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
2238 null /* compatInsets */);
2239 }
2240
2241 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
2242 @NonNull Configuration parentConfig,
2243 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
Riddle Hsu23e18a92020-03-10 00:26:51 +08002244 if (compatInsets != null) {
2245 // Make sure the app bounds can be computed by the compat insets.
2246 invalidateAppBoundsConfig(inOutConfig);
2247 }
Riddle Hsu9264a272020-03-04 23:10:41 +08002248 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
2249 compatInsets);
Louis Changcdec0802019-11-11 11:45:07 +08002250 }
2251
2252 /**
2253 * Calculates configuration values used by the client to get resources. This should be run
2254 * using app-facing bounds (bounds unmodified by animations or transient interactions).
2255 *
2256 * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
2257 * configuring an "inherit-bounds" window which means that all configuration settings would
2258 * just be inherited from the parent configuration.
2259 **/
2260 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Riddle Hsu9264a272020-03-04 23:10:41 +08002261 @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo,
Louis Changcdec0802019-11-11 11:45:07 +08002262 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
2263 int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
2264 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2265 windowingMode = parentConfig.windowConfiguration.getWindowingMode();
2266 }
2267
2268 float density = inOutConfig.densityDpi;
2269 if (density == Configuration.DENSITY_DPI_UNDEFINED) {
2270 density = parentConfig.densityDpi;
2271 }
2272 density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
2273
Riddle Hsu1f931a592020-04-22 21:15:38 +08002274 // The bounds may have been overridden at this level. If the parent cannot cover these
2275 // bounds, the configuration is still computed according to the override bounds.
2276 final boolean insideParentBounds;
Evan Roskyc440b4e2020-04-17 15:11:22 -07002277
Riddle Hsu1f931a592020-04-22 21:15:38 +08002278 final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
Evan Rosky70213702019-11-05 10:26:24 -08002279 final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds();
Evan Roskyc440b4e2020-04-17 15:11:22 -07002280 if (resolvedBounds == null || resolvedBounds.isEmpty()) {
Riddle Hsu1f931a592020-04-22 21:15:38 +08002281 mTmpFullBounds.set(parentBounds);
2282 insideParentBounds = true;
Evan Rosky70213702019-11-05 10:26:24 -08002283 } else {
2284 mTmpFullBounds.set(resolvedBounds);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002285 insideParentBounds = parentBounds.contains(resolvedBounds);
Evan Rosky70213702019-11-05 10:26:24 -08002286 }
2287
Evan Roskye067ddf2020-04-24 18:28:25 -07002288 // Non-null compatibility insets means the activity prefers to keep its original size, so
2289 // out bounds doesn't need to be restricted by the parent or current display
2290 final boolean customContainerPolicy = compatInsets != null;
2291
Louis Changcdec0802019-11-11 11:45:07 +08002292 Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2293 if (outAppBounds == null || outAppBounds.isEmpty()) {
Evan Roskye067ddf2020-04-24 18:28:25 -07002294 // App-bounds hasn't been overridden, so calculate a value for it.
Evan Rosky70213702019-11-05 10:26:24 -08002295 inOutConfig.windowConfiguration.setAppBounds(mTmpFullBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002296 outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
Evan Roskye067ddf2020-04-24 18:28:25 -07002297
2298 if (!customContainerPolicy && windowingMode != WINDOWING_MODE_FREEFORM) {
2299 final Rect containingAppBounds;
2300 if (insideParentBounds) {
2301 containingAppBounds = parentConfig.windowConfiguration.getAppBounds();
2302 } else {
2303 // Restrict appBounds to display non-decor rather than parent because the
2304 // override bounds are beyond the parent. Otherwise, it won't match the
2305 // overridden bounds.
2306 final TaskDisplayArea displayArea = getDisplayArea();
2307 containingAppBounds = displayArea != null
2308 ? displayArea.getWindowConfiguration().getAppBounds() : null;
2309 }
2310 if (containingAppBounds != null && !containingAppBounds.isEmpty()) {
2311 outAppBounds.intersect(containingAppBounds);
2312 }
Louis Changcdec0802019-11-11 11:45:07 +08002313 }
2314 }
2315
2316 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
2317 || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
Riddle Hsu1f931a592020-04-22 21:15:38 +08002318 if (!customContainerPolicy && WindowConfiguration.isFloating(windowingMode)) {
jaehoon.kim643293e2019-11-08 06:36:28 +09002319 mTmpNonDecorBounds.set(mTmpFullBounds);
2320 mTmpStableBounds.set(mTmpFullBounds);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002321 } else if (!customContainerPolicy
Riddle Hsu9264a272020-03-04 23:10:41 +08002322 && (overrideDisplayInfo != null || getDisplayContent() != null)) {
2323 final DisplayInfo di = overrideDisplayInfo != null
2324 ? overrideDisplayInfo
2325 : getDisplayContent().getDisplayInfo();
Louis Changcdec0802019-11-11 11:45:07 +08002326
2327 // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
2328 // area, i.e. the screen area without the system bars.
2329 // The non decor inset are areas that could never be removed in Honeycomb. See
2330 // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
Evan Rosky70213702019-11-05 10:26:24 -08002331 calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di);
Louis Changcdec0802019-11-11 11:45:07 +08002332 } else {
2333 // Apply the given non-decor and stable insets to calculate the corresponding bounds
2334 // for screen size of configuration.
2335 int rotation = inOutConfig.windowConfiguration.getRotation();
2336 if (rotation == ROTATION_UNDEFINED) {
2337 rotation = parentConfig.windowConfiguration.getRotation();
2338 }
Riddle Hsu1f931a592020-04-22 21:15:38 +08002339 if (rotation != ROTATION_UNDEFINED && customContainerPolicy) {
Evan Rosky70213702019-11-05 10:26:24 -08002340 mTmpNonDecorBounds.set(mTmpFullBounds);
2341 mTmpStableBounds.set(mTmpFullBounds);
Riddle Hsue47501b2020-02-18 12:45:41 +08002342 compatInsets.getBoundsByRotation(mTmpBounds, rotation);
Louis Changcdec0802019-11-11 11:45:07 +08002343 intersectWithInsetsIfFits(mTmpNonDecorBounds, mTmpBounds,
2344 compatInsets.mNonDecorInsets[rotation]);
2345 intersectWithInsetsIfFits(mTmpStableBounds, mTmpBounds,
2346 compatInsets.mStableInsets[rotation]);
2347 outAppBounds.set(mTmpNonDecorBounds);
2348 } else {
2349 // Set to app bounds because it excludes decor insets.
2350 mTmpNonDecorBounds.set(outAppBounds);
2351 mTmpStableBounds.set(outAppBounds);
2352 }
2353 }
2354
2355 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
2356 final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002357 inOutConfig.screenWidthDp = (insideParentBounds && !customContainerPolicy)
Louis Changcdec0802019-11-11 11:45:07 +08002358 ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
2359 : overrideScreenWidthDp;
2360 }
2361 if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2362 final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002363 inOutConfig.screenHeightDp = (insideParentBounds && !customContainerPolicy)
Louis Changcdec0802019-11-11 11:45:07 +08002364 ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
2365 : overrideScreenHeightDp;
2366 }
2367
2368 if (inOutConfig.smallestScreenWidthDp
2369 == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2370 if (WindowConfiguration.isFloating(windowingMode)) {
2371 // For floating tasks, calculate the smallest width from the bounds of the task
2372 inOutConfig.smallestScreenWidthDp = (int) (
Evan Rosky70213702019-11-05 10:26:24 -08002373 Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density);
Louis Changcdec0802019-11-11 11:45:07 +08002374 }
2375 // otherwise, it will just inherit
2376 }
2377 }
2378
2379 if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
2380 inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
2381 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
2382 }
2383 if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
2384 // For calculating screen layout, we need to use the non-decor inset screen area for the
2385 // calculation for compatibility reasons, i.e. screen area without system bars that
2386 // could never go away in Honeycomb.
2387 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
2388 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Louis Changcdec0802019-11-11 11:45:07 +08002389 // Reducing the screen layout starting from its parent config.
Riddle Hsuca928562019-11-22 01:04:14 +08002390 inOutConfig.screenLayout = computeScreenLayoutOverride(parentConfig.screenLayout,
2391 compatScreenWidthDp, compatScreenHeightDp);
Louis Changcdec0802019-11-11 11:45:07 +08002392 }
2393 }
2394
Riddle Hsuca928562019-11-22 01:04:14 +08002395 /** Computes LONG, SIZE and COMPAT parts of {@link Configuration#screenLayout}. */
2396 static int computeScreenLayoutOverride(int sourceScreenLayout, int screenWidthDp,
2397 int screenHeightDp) {
2398 sourceScreenLayout = sourceScreenLayout
2399 & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
2400 final int longSize = Math.max(screenWidthDp, screenHeightDp);
2401 final int shortSize = Math.min(screenWidthDp, screenHeightDp);
2402 return Configuration.reduceScreenLayout(sourceScreenLayout, longSize, shortSize);
2403 }
2404
Louis Changcdec0802019-11-11 11:45:07 +08002405 @Override
2406 void resolveOverrideConfiguration(Configuration newParentConfig) {
2407 mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
Louis Changdff902b2020-03-31 13:32:47 +08002408 super.resolveOverrideConfiguration(newParentConfig);
2409
Louis Changcdec0802019-11-11 11:45:07 +08002410 int windowingMode =
Wale Ogunwale0d465192020-01-23 19:14:44 -08002411 getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
Evan Roskyc440b4e2020-04-17 15:11:22 -07002412
2413 // Resolve override windowing mode to fullscreen for home task (even on freeform
2414 // display), or split-screen if in split-screen mode.
Louis Changdff902b2020-03-31 13:32:47 +08002415 if (getActivityType() == ACTIVITY_TYPE_HOME && windowingMode == WINDOWING_MODE_UNDEFINED) {
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07002416 final int parentWindowingMode = newParentConfig.windowConfiguration.getWindowingMode();
Evan Roskyc440b4e2020-04-17 15:11:22 -07002417 windowingMode = WindowConfiguration.isSplitScreenWindowingMode(parentWindowingMode)
2418 ? parentWindowingMode : WINDOWING_MODE_FULLSCREEN;
Louis Changdff902b2020-03-31 13:32:47 +08002419 getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
2420 }
2421
Evan Roskyc440b4e2020-04-17 15:11:22 -07002422 if (isLeafTask()) {
Riddle Hsudd49c632020-04-30 22:39:51 +08002423 resolveLeafOnlyOverrideConfigs(newParentConfig, mTmpBounds /* previousBounds */);
Louis Changdff902b2020-03-31 13:32:47 +08002424 }
Evan Roskyc440b4e2020-04-17 15:11:22 -07002425 computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
2426 }
Louis Changdff902b2020-03-31 13:32:47 +08002427
Riddle Hsudd49c632020-04-30 22:39:51 +08002428 private void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig,
2429 Rect previousBounds) {
Evan Roskyc440b4e2020-04-17 15:11:22 -07002430 int windowingMode =
2431 getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
Louis Changcdec0802019-11-11 11:45:07 +08002432 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2433 windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
2434 }
2435 Rect outOverrideBounds =
2436 getResolvedOverrideConfiguration().windowConfiguration.getBounds();
2437
2438 if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
2439 computeFullscreenBounds(outOverrideBounds, null /* refActivity */,
2440 newParentConfig.windowConfiguration.getBounds(),
2441 newParentConfig.orientation);
Riddle Hsudd49c632020-04-30 22:39:51 +08002442 // The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
2443 // the parent or display is smaller than the size, the content may be cropped.
2444 return;
Louis Changcdec0802019-11-11 11:45:07 +08002445 }
2446
Riddle Hsudd49c632020-04-30 22:39:51 +08002447 adjustForMinimalTaskDimensions(outOverrideBounds, previousBounds, newParentConfig);
Louis Changcdec0802019-11-11 11:45:07 +08002448 if (windowingMode == WINDOWING_MODE_FREEFORM) {
2449 // by policy, make sure the window remains within parent somewhere
2450 final float density =
2451 ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;
2452 final Rect parentBounds =
2453 new Rect(newParentConfig.windowConfiguration.getBounds());
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002454 final DisplayContent display = getDisplayContent();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002455 if (display != null) {
Louis Changcdec0802019-11-11 11:45:07 +08002456 // If a freeform window moves below system bar, there is no way to move it again
2457 // by touch. Because its caption is covered by system bar. So we exclude them
2458 // from stack bounds. and then caption will be shown inside stable area.
2459 final Rect stableBounds = new Rect();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002460 display.getStableRect(stableBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002461 parentBounds.intersect(stableBounds);
2462 }
2463
2464 fitWithinBounds(outOverrideBounds, parentBounds,
2465 (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP),
2466 (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP));
2467
2468 // Prevent to overlap caption with stable insets.
2469 final int offsetTop = parentBounds.top - outOverrideBounds.top;
2470 if (offsetTop > 0) {
2471 outOverrideBounds.offset(0, offsetTop);
2472 }
2473 }
Louis Changcdec0802019-11-11 11:45:07 +08002474 }
2475
2476 /**
2477 * Compute bounds (letterbox or pillarbox) for
2478 * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the
2479 * orientation change and the requested orientation is different from the parent.
2480 */
2481 void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
2482 @NonNull Rect parentBounds, int parentOrientation) {
2483 // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
2484 outBounds.setEmpty();
2485 if (handlesOrientationChangeFromDescendant()) {
2486 return;
2487 }
2488 if (refActivity == null) {
2489 // Use the top activity as the reference of orientation. Don't include overlays because
2490 // it is usually not the actual content or just temporarily shown.
2491 // E.g. ForcedResizableInfoActivity.
Wale Ogunwale21e06482019-11-18 05:14:15 -08002492 refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
Louis Changcdec0802019-11-11 11:45:07 +08002493 }
2494
2495 // If the task or the reference activity requires a different orientation (either by
2496 // override or activityInfo), make it fit the available bounds by scaling down its bounds.
2497 final int overrideOrientation = getRequestedOverrideConfiguration().orientation;
2498 final int forcedOrientation =
2499 (overrideOrientation != ORIENTATION_UNDEFINED || refActivity == null)
2500 ? overrideOrientation : refActivity.getRequestedConfigurationOrientation();
2501 if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
2502 return;
2503 }
2504
2505 final int parentWidth = parentBounds.width();
2506 final int parentHeight = parentBounds.height();
2507 final float aspect = ((float) parentHeight) / parentWidth;
2508 if (forcedOrientation == ORIENTATION_LANDSCAPE) {
2509 final int height = (int) (parentWidth / aspect);
2510 final int top = parentBounds.centerY() - height / 2;
2511 outBounds.set(parentBounds.left, top, parentBounds.right, top + height);
2512 } else {
2513 final int width = (int) (parentHeight * aspect);
2514 final int left = parentBounds.centerX() - width / 2;
2515 outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
2516 }
2517 }
2518
2519 Rect updateOverrideConfigurationFromLaunchBounds() {
Louis Changa009c762020-02-26 11:21:31 +08002520 // If the task is controlled by another organized task, do not set override
2521 // configurations and let its parent (organized task) to control it;
Louis Chang06107a32020-04-06 11:55:46 +08002522 final Task rootTask = getRootTask();
2523 final Rect bounds = rootTask != this && rootTask.isOrganized() ? null : getLaunchBounds();
Louis Changcdec0802019-11-11 11:45:07 +08002524 setBounds(bounds);
2525 if (bounds != null && !bounds.isEmpty()) {
2526 // TODO: Review if we actually want to do this - we are setting the launch bounds
2527 // directly here.
2528 bounds.set(getRequestedOverrideBounds());
2529 }
2530 return bounds;
2531 }
2532
2533 /** Updates the task's bounds and override configuration to match what is expected for the
2534 * input stack. */
2535 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002536 final ActivityStack stack = getStack();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002537
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002538 if (stack != null && stack == inStack) {
Louis Changcdec0802019-11-11 11:45:07 +08002539 return;
2540 }
2541
2542 if (inStack.inFreeformWindowingMode()) {
2543 if (!isResizeable()) {
2544 throw new IllegalArgumentException("Can not position non-resizeable task="
2545 + this + " in stack=" + inStack);
2546 }
2547 if (!matchParentBounds()) {
2548 return;
2549 }
2550 if (mLastNonFullscreenBounds != null) {
2551 setBounds(mLastNonFullscreenBounds);
2552 } else {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002553 mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Louis Changcdec0802019-11-11 11:45:07 +08002554 }
2555 } else {
2556 setBounds(inStack.getRequestedOverrideBounds());
2557 }
2558 }
2559
2560 /** Returns the bounds that should be used to launch this task. */
2561 Rect getLaunchBounds() {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002562 final ActivityStack stack = getStack();
2563 if (stack == null) {
Louis Changcdec0802019-11-11 11:45:07 +08002564 return null;
2565 }
2566
2567 final int windowingMode = getWindowingMode();
2568 if (!isActivityTypeStandardOrUndefined()
2569 || windowingMode == WINDOWING_MODE_FULLSCREEN
2570 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002571 return isResizeable() ? stack.getRequestedOverrideBounds() : null;
Louis Changcdec0802019-11-11 11:45:07 +08002572 } else if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002573 return stack.getRequestedOverrideBounds();
Louis Changcdec0802019-11-11 11:45:07 +08002574 }
2575 return mLastNonFullscreenBounds;
2576 }
2577
Louis Changcdec0802019-11-11 11:45:07 +08002578 void setRootProcess(WindowProcessController proc) {
2579 clearRootProcess();
2580 if (intent != null
2581 && (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
2582 mRootProcess = proc;
2583 mRootProcess.addRecentTask(this);
2584 }
2585 }
2586
2587 void clearRootProcess() {
2588 if (mRootProcess != null) {
2589 mRootProcess.removeRecentTask(this);
2590 mRootProcess = null;
2591 }
2592 }
2593
Tiger Huanged6794e2019-05-07 20:07:59 +08002594 @Override
Craig Mautnerc00204b2013-03-05 15:02:14 -08002595 DisplayContent getDisplayContent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002596 // TODO: Why aren't we just using our own display content vs. parent's???
2597 final ActivityStack stack = getStack();
2598 return stack != null && stack != this
2599 ? stack.getDisplayContent() : super.getDisplayContent();
Wale Ogunwale8577a052019-10-26 23:22:34 -07002600 }
2601
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002602 int getDisplayId() {
2603 final DisplayContent dc = getDisplayContent();
2604 return dc != null ? dc.mDisplayId : INVALID_DISPLAY;
2605 }
2606
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002607 // TODO: Migrate callers to getRootTask()
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002608 ActivityStack getStack() {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002609 return (ActivityStack) getRootTask();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002610 }
2611
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002612 /** @return Id of root task. */
2613 int getRootTaskId() {
2614 return getRootTask().mTaskId;
2615 }
2616
2617 Task getRootTask() {
2618 final WindowContainer parent = getParent();
2619 if (parent == null) return this;
2620
2621 final Task parentTask = parent.asTask();
2622 return parentTask == null ? this : parentTask.getRootTask();
2623 }
2624
2625 // TODO(task-merge): Figure out what's the right thing to do for places that used it.
2626 boolean isRootTask() {
2627 return getRootTask() == this;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002628 }
2629
Louis Changfd5539e2020-02-04 14:34:24 +08002630 boolean isLeafTask() {
2631 for (int i = mChildren.size() - 1; i >= 0; --i) {
2632 if (mChildren.get(i).asTask() != null) {
2633 return false;
2634 }
2635 }
2636 return true;
2637 }
2638
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002639 int getDescendantTaskCount() {
2640 final int[] currentCount = {0};
2641 final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
2642 PooledLambda.__(Task.class), currentCount);
Wale Ogunwale0d465192020-01-23 19:14:44 -08002643 forAllLeafTasks(c, false /* traverseTopToBottom */);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002644 c.recycle();
2645 return currentCount[0];
2646 }
2647
Louis Chang6434be42020-04-10 17:39:35 +08002648 /**
2649 * Find next proper focusable stack and make it focused.
2650 * @return The stack that now got the focus, {@code null} if none found.
2651 */
2652 ActivityStack adjustFocusToNextFocusableTask(String reason) {
2653 return adjustFocusToNextFocusableTask(reason, false /* allowFocusSelf */,
2654 true /* moveParentsToTop */);
2655 }
2656
2657 /** Return the next focusable task by looking from the siblings and parent tasks */
2658 private Task getNextFocusableTask(boolean allowFocusSelf) {
2659 final WindowContainer parent = getParent();
2660 if (parent == null) {
2661 return null;
2662 }
2663
2664 final Task focusableTask = parent.getTask((task) -> (allowFocusSelf || task != this)
2665 && ((ActivityStack) task).isFocusableAndVisible());
2666 if (focusableTask == null && parent.asTask() != null) {
2667 return parent.asTask().getNextFocusableTask(allowFocusSelf);
2668 } else {
2669 return focusableTask;
2670 }
2671 }
2672
2673 /**
2674 * Find next proper focusable task and make it focused.
2675 * @param reason The reason of making the adjustment.
2676 * @param allowFocusSelf Is the focus allowed to remain on the same task.
2677 * @param moveParentsToTop Whether to move parents to top while making the task focused.
2678 * @return The root task that now got the focus, {@code null} if none found.
2679 */
2680 ActivityStack adjustFocusToNextFocusableTask(String reason, boolean allowFocusSelf,
2681 boolean moveParentsToTop) {
2682 ActivityStack focusableTask = (ActivityStack) getNextFocusableTask(allowFocusSelf);
2683 if (focusableTask == null) {
2684 focusableTask = mRootWindowContainer.getNextFocusableStack((ActivityStack) this,
2685 !allowFocusSelf);
2686 }
2687 if (focusableTask == null) {
2688 return null;
2689 }
2690
Louis Chang6434be42020-04-10 17:39:35 +08002691 final ActivityStack rootTask = (ActivityStack) focusableTask.getRootTask();
Louis Chang6434be42020-04-10 17:39:35 +08002692 if (!moveParentsToTop) {
2693 // Only move the next stack to top in its task container.
2694 WindowContainer parent = focusableTask.getParent();
2695 parent.positionChildAt(POSITION_TOP, focusableTask, false /* includingParents */);
2696 return rootTask;
2697 }
2698
wilsonshiha31e01f2020-04-24 11:41:29 +08002699 final String myReason = reason + " adjustFocusToNextFocusableStack";
2700 final ActivityRecord top = focusableTask.topRunningActivity();
2701 if (focusableTask.isActivityTypeHome() && (top == null || !top.mVisibleRequested)) {
2702 // If we will be focusing on the home stack next and its current top activity isn't
2703 // visible, then use the move the home stack task to top to make the activity visible.
2704 focusableTask.getDisplayArea().moveHomeActivityToTop(myReason);
2705 return rootTask;
2706 }
2707
Louis Chang6434be42020-04-10 17:39:35 +08002708 // Move the entire hierarchy to top with updating global top resumed activity
2709 // and focused application if needed.
2710 focusableTask.moveToFront(myReason);
2711 // Top display focused stack is changed, update top resumed activity if needed.
2712 if (rootTask.mResumedActivity != null) {
2713 mStackSupervisor.updateTopResumedActivityIfNeeded();
2714 // Set focused app directly because if the next focused activity is already resumed
2715 // (e.g. the next top activity is on a different display), there won't have activity
2716 // state change to update it.
2717 mAtmService.setResumedActivityUncheckLocked(rootTask.mResumedActivity, reason);
2718 }
2719 return rootTask;
2720 }
2721
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002722 /** Calculate the minimum possible position for a task that can be shown to the user.
2723 * The minimum position will be above all other tasks that can't be shown.
2724 * @param minPosition The minimum position the caller is suggesting.
2725 * We will start adjusting up from here.
2726 * @param size The size of the current task list.
2727 */
2728 // TODO: Move user to their own window container.
2729 private int computeMinUserPosition(int minPosition, int size) {
2730 while (minPosition < size) {
2731 final WindowContainer child = mChildren.get(minPosition);
2732 final boolean canShow = child.showToCurrentUser();
2733 if (canShow) {
2734 break;
2735 }
2736 minPosition++;
2737 }
2738 return minPosition;
2739 }
2740
2741 /** Calculate the maximum possible position for a task that can't be shown to the user.
2742 * The maximum position will be below all other tasks that can be shown.
2743 * @param maxPosition The maximum position the caller is suggesting.
2744 * We will start adjusting down from here.
2745 */
2746 // TODO: Move user to their own window container.
2747 private int computeMaxUserPosition(int maxPosition) {
2748 while (maxPosition > 0) {
2749 final WindowContainer child = mChildren.get(maxPosition);
2750 final boolean canShow = child.showToCurrentUser();
2751 if (!canShow) {
2752 break;
2753 }
2754 maxPosition--;
2755 }
2756 return maxPosition;
2757 }
2758
2759 private int getAdjustedChildPosition(WindowContainer wc, int suggestedPosition) {
2760 final boolean canShowChild = wc.showToCurrentUser();
2761
2762 final int size = mChildren.size();
2763
2764 // Figure-out min/max possible position depending on if child can show for current user.
2765 int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0;
2766 int maxPosition = (canShowChild) ? size : computeMaxUserPosition(size - 1);
2767
2768 // Factor in always-on-top children in max possible position.
2769 if (!wc.isAlwaysOnTop()) {
2770
2771 // We want to place all non-always-on-top containers below always-on-top ones.
2772 while (maxPosition > minPosition) {
2773 if (!mChildren.get(maxPosition - 1).isAlwaysOnTop()) break;
2774 --maxPosition;
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002775 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002776 }
2777
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002778 // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
2779 if (suggestedPosition == POSITION_BOTTOM && minPosition == 0) {
2780 return POSITION_BOTTOM;
Louis Changa009c762020-02-26 11:21:31 +08002781 } else if (suggestedPosition == POSITION_TOP && maxPosition >= (size - 1)) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002782 return POSITION_TOP;
2783 }
2784 // Reset position based on minimum/maximum possible positions.
2785 return Math.min(Math.max(suggestedPosition, minPosition), maxPosition);
Craig Mautnerc00204b2013-03-05 15:02:14 -08002786 }
2787
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002788 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002789 void positionChildAt(int position, WindowContainer child, boolean includingParents) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002790 position = getAdjustedChildPosition(child, position);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002791 super.positionChildAt(position, child, includingParents);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002792
2793 // Log positioning.
2794 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "positionChildAt: child=" + child
2795 + " position=" + position + " parent=" + this);
2796
2797 final int toTop = position >= (mChildren.size() - 1) ? 1 : 0;
2798 final Task task = child.asTask();
2799 if (task != null) {
2800 EventLogTags.writeWmTaskMoved(task.mTaskId, toTop, position);
2801 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002802 }
2803
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002804 @VisibleForTesting
2805 boolean hasWindowsAlive() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002806 return getActivity(ActivityRecord::hasWindowsAlive) != null;
Chong Zhang7e8eeb72016-01-06 19:14:47 -08002807 }
2808
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002809 @VisibleForTesting
2810 boolean shouldDeferRemoval() {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02002811 if (mChildren.isEmpty()) {
2812 // No reason to defer removal of a Task that doesn't have any child.
2813 return false;
2814 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002815 return hasWindowsAlive() && getStack().isAnimating(TRANSITION | CHILDREN);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002816 }
2817
Wale Ogunwalef6192862016-09-10 13:42:30 -07002818 @Override
Andrii Kulian45a61fe2017-01-05 16:53:19 -08002819 void removeImmediately() {
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08002820 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
Jeff Changd136e772019-11-05 20:33:52 +08002821 EventLogTags.writeWmTaskRemoved(mTaskId, "removeTask");
Robert Carr8a2f9132019-11-11 15:03:15 -08002822
2823 // If applicable let the TaskOrganizer know the Task is vanishing.
2824 setTaskOrganizer(null);
2825
Andrii Kulian45a61fe2017-01-05 16:53:19 -08002826 super.removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -08002827 }
2828
Louis Changcdec0802019-11-11 11:45:07 +08002829 // TODO: Consolidate this with Task.reparent()
Louis Changdc077272019-11-12 16:52:56 +08002830 void reparent(ActivityStack stack, int position, boolean moveParents, String reason) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -08002831 if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002832 + " from stack=" + getStack());
Louis Chang074cdf22019-12-13 13:15:13 +08002833 EventLogTags.writeWmTaskRemoved(mTaskId, "reParentTask:" + reason);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002834
2835 reparent(stack, position);
2836
Louis Changcdec0802019-11-11 11:45:07 +08002837 stack.positionChildAt(position, this, moveParents);
Andrii Kulian7cd7c2d2017-01-18 12:14:37 -08002838
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002839 // If we are moving from the fullscreen stack to the pinned stack then we want to preserve
2840 // our insets so that there will not be a jump in the area covered by system decorations.
2841 // We rely on the pinned animation to later unset this value.
2842 mPreserveNonFloatingState = stack.inPinnedWindowingMode();
Wale Ogunwale53a29a92015-02-23 15:42:52 -08002843 }
2844
Bryce Leef3c6a472017-11-14 14:53:06 -08002845 public int setBounds(Rect bounds, boolean forceResize) {
2846 final int boundsChanged = setBounds(bounds);
2847
2848 if (forceResize && (boundsChanged & BOUNDS_CHANGE_SIZE) != BOUNDS_CHANGE_SIZE) {
2849 onResize();
2850 return BOUNDS_CHANGE_SIZE | boundsChanged;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002851 }
Wale Ogunwale68278562017-09-23 17:13:55 -07002852
Bryce Leef3c6a472017-11-14 14:53:06 -08002853 return boundsChanged;
2854 }
2855
2856 /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
2857 @Override
2858 public int setBounds(Rect bounds) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002859 int rotation = Surface.ROTATION_0;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002860 final DisplayContent displayContent = getStack() != null
2861 ? getStack().getDisplayContent() : null;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002862 if (displayContent != null) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002863 rotation = displayContent.getDisplayInfo().rotation;
Wale Ogunwale2cc92f52015-09-09 13:12:10 -07002864 }
2865
Bryce Leef3c6a472017-11-14 14:53:06 -08002866 final int boundsChange = super.setBounds(bounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002867 mRotation = rotation;
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002868 updateSurfacePosition();
Wale Ogunwale2cc92f52015-09-09 13:12:10 -07002869 return boundsChange;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002870 }
2871
Garfield Tan90b04282018-12-11 14:04:42 -08002872 @Override
2873 public boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
2874 ConfigurationContainer requestingContainer) {
2875 if (super.onDescendantOrientationChanged(freezeDisplayToken, requestingContainer)) {
2876 return true;
2877 }
2878
2879 // No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
2880 // it if possible.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002881 if (getParent() != null) {
2882 onConfigurationChanged(getParent().getConfiguration());
Garfield Tan90b04282018-12-11 14:04:42 -08002883 return true;
2884 }
2885 return false;
2886 }
2887
Yunfan Chen0e7aff92018-12-05 16:35:32 -08002888 void resize(boolean relayout, boolean forced) {
2889 if (setBounds(getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE && relayout) {
2890 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
2891 }
2892 }
2893
Louis Chang7501e332018-08-20 13:08:39 +08002894 @Override
2895 void onDisplayChanged(DisplayContent dc) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002896 final boolean isRootTask = isRootTask();
2897 if (!isRootTask) {
2898 adjustBoundsForDisplayChangeIfNeeded(dc);
2899 }
Louis Chang7501e332018-08-20 13:08:39 +08002900 super.onDisplayChanged(dc);
Yuncheol Heo1c211c22020-04-20 13:08:43 -07002901 if (isLeafTask()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002902 final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY;
2903 mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged(
2904 mTaskId, displayId);
2905 }
Louis Chang7501e332018-08-20 13:08:39 +08002906 }
2907
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002908 boolean isResizeable(boolean checkSupportsPip) {
2909 return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
2910 || (checkSupportsPip && mSupportsPictureInPicture));
Chong Zhangb15758a2015-11-17 12:12:03 -08002911 }
2912
2913 boolean isResizeable() {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002914 return isResizeable(true /* checkSupportsPip */);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002915 }
2916
skuhne@google.com322347b2016-12-02 12:54:03 -08002917 /**
2918 * Tests if the orientation should be preserved upon user interactive resizig operations.
2919
2920 * @return true if orientation should not get changed upon resizing operation.
2921 */
2922 boolean preserveOrientationOnResize() {
2923 return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
2924 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
2925 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
2926 }
2927
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002928 boolean cropWindowsToStackBounds() {
Wale Ogunwaledf241e92016-10-13 15:14:21 -07002929 return isResizeable();
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002930 }
2931
Jorim Jaggi0429f352015-12-22 16:29:16 +01002932 /**
2933 * Prepares the task bounds to be frozen with the current size. See
Garfield Tane8d84ab2019-10-11 09:49:40 -07002934 * {@link ActivityRecord#freezeBounds}.
Jorim Jaggi0429f352015-12-22 16:29:16 +01002935 */
2936 void prepareFreezingBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08002937 mPreparedFrozenBounds.set(getBounds());
Andrii Kulian441e4492016-09-29 15:25:00 -07002938 mPreparedFrozenMergedConfig.setTo(getConfiguration());
Jorim Jaggi0429f352015-12-22 16:29:16 +01002939 }
2940
Issei Suzukiad287d02019-10-31 16:19:44 +01002941 @Override
2942 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2943 Rect outSurfaceInsets) {
2944 final WindowState windowState = getTopVisibleAppMainWindow();
2945 if (windowState != null) {
2946 windowState.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2947 } else {
2948 super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2949 }
2950 }
2951
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002952 /**
2953 * Calculate the maximum visible area of this task. If the task has only one app,
2954 * the result will be visible frame of that app. If the task has more than one apps,
2955 * we search from top down if the next app got different visible area.
2956 *
2957 * This effort is to handle the case where some task (eg. GMail composer) might pop up
2958 * a dialog that's different in size from the activity below, in which case we should
2959 * be dimming the entire task area behind the dialog.
2960 *
2961 * @param out Rect containing the max visible bounds.
2962 * @return true if the task has some visible app windows; false otherwise.
2963 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002964 private static void getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop) {
2965 // skip hidden (or about to hide) apps
2966 if (token.mIsExiting || !token.isClientVisible() || !token.mVisibleRequested) {
2967 return;
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002968 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002969 final WindowState win = token.findMainWindow();
2970 if (win == null) {
2971 return;
2972 }
2973 if (!foundTop[0]) {
2974 foundTop[0] = true;
2975 out.setEmpty();
2976 }
2977
2978 win.getMaxVisibleBounds(out);
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002979 }
2980
2981 /** Bounds of the task to be used for dimming, as well as touch related tests. */
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002982 void getDimBounds(Rect out) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002983 final DisplayContent displayContent = getStack().getDisplayContent();
Robert Carra86a6bf2016-04-08 17:34:16 -07002984 // It doesn't matter if we in particular are part of the resize, since we couldn't have
2985 // a DimLayer anyway if we weren't visible.
Wale Ogunwalef6192862016-09-10 13:42:30 -07002986 final boolean dockedResizing = displayContent != null
2987 && displayContent.mDividerControllerLocked.isResizing();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002988 if (inFreeformWindowingMode()) {
2989 boolean[] foundTop = { false };
2990 final PooledConsumer c = PooledLambda.obtainConsumer(Task::getMaxVisibleBounds,
2991 PooledLambda.__(ActivityRecord.class), out, foundTop);
Vishnu Nair4d7a6002020-01-23 14:34:40 -08002992 forAllActivities(c);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002993 c.recycle();
2994 if (foundTop[0]) {
2995 return;
2996 }
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002997 }
2998
Evan Rosky4fb1e912019-03-06 13:54:43 -08002999 if (!matchParentBounds()) {
3000 // When minimizing the docked stack when going home, we don't adjust the task bounds
3001 // so we need to intersect the task bounds with the stack bounds here.
3002 //
3003 // If we are Docked Resizing with snap points, the task bounds could be smaller than the
3004 // stack bounds and so we don't even want to use them. Even if the app should not be
3005 // resized the Dim should keep up with the divider.
3006 if (dockedResizing) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003007 getStack().getBounds(out);
Evan Rosky4fb1e912019-03-06 13:54:43 -08003008 } else {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003009 getStack().getBounds(mTmpRect);
Evan Rosky4fb1e912019-03-06 13:54:43 -08003010 mTmpRect.intersect(getBounds());
3011 out.set(mTmpRect);
3012 }
3013 } else {
3014 out.set(getBounds());
Wale Ogunwalef6192862016-09-10 13:42:30 -07003015 }
Evan Rosky4fb1e912019-03-06 13:54:43 -08003016 return;
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08003017 }
3018
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003019 void setDragResizing(boolean dragResizing, int dragResizeMode) {
Jorim Jaggic662d8e2016-02-05 16:54:54 -08003020 if (mDragResizing != dragResizing) {
chaviw8c9d1f52018-07-25 14:56:07 -07003021 // No need to check if the mode is allowed if it's leaving dragResize
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003022 if (dragResizing && !DragResizeMode.isModeAllowedForStack(getStack(), dragResizeMode)) {
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003023 throw new IllegalArgumentException("Drag resize mode not allow for stack stackId="
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003024 + getRootTaskId() + " dragResizeMode=" + dragResizeMode);
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003025 }
Jorim Jaggic662d8e2016-02-05 16:54:54 -08003026 mDragResizing = dragResizing;
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003027 mDragResizeMode = dragResizeMode;
Jorim Jaggic662d8e2016-02-05 16:54:54 -08003028 resetDragResizingChangeReported();
3029 }
3030 }
3031
Chong Zhang3005e752015-09-18 18:46:28 -07003032 boolean isDragResizing() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07003033 return mDragResizing;
Chong Zhang3005e752015-09-18 18:46:28 -07003034 }
3035
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003036 int getDragResizeMode() {
3037 return mDragResizeMode;
3038 }
3039
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003040 void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003041 if (displayContent == null) {
3042 return;
3043 }
Bryce Leef3c6a472017-11-14 14:53:06 -08003044 if (matchParentBounds()) {
Wale Ogunwale68278562017-09-23 17:13:55 -07003045 // TODO: Yeah...not sure if this works with WindowConfiguration, but shouldn't be a
3046 // problem once we move mBounds into WindowConfiguration.
Bryce Leef3c6a472017-11-14 14:53:06 -08003047 setBounds(null);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003048 return;
3049 }
Garfield Tandec96db2018-10-30 11:28:49 -07003050 final int displayId = displayContent.getDisplayId();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003051 final int newRotation = displayContent.getDisplayInfo().rotation;
Garfield Tandec96db2018-10-30 11:28:49 -07003052 if (displayId != mLastRotationDisplayId) {
3053 // This task is on a display that it wasn't on. There is no point to keep the relative
3054 // position if display rotations for old and new displays are different. Just keep these
3055 // values.
3056 mLastRotationDisplayId = displayId;
3057 mRotation = newRotation;
3058 return;
3059 }
3060
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003061 if (mRotation == newRotation) {
Garfield Tandec96db2018-10-30 11:28:49 -07003062 // Rotation didn't change. We don't need to adjust the bounds to keep the relative
3063 // position.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003064 return;
3065 }
3066
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003067 // Device rotation changed.
Chong Zhang2e2c81a2016-07-15 11:28:17 -07003068 // - We don't want the task to move around on the screen when this happens, so update the
3069 // task bounds so it stays in the same place.
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003070 // - Rotate the bounds and notify activity manager if the task can be resized independently
Chong Zhang2e2c81a2016-07-15 11:28:17 -07003071 // from its stack. The stack will take care of task rotation for the other case.
Bryce Leef3c6a472017-11-14 14:53:06 -08003072 mTmpRect2.set(getBounds());
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003073
Wale Ogunwale3382ab12017-07-27 08:55:03 -07003074 if (!getWindowConfiguration().canResizeTask()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08003075 setBounds(mTmpRect2);
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003076 return;
3077 }
3078
Wale Ogunwale94744212015-09-21 19:01:47 -07003079 displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
Bryce Leef3c6a472017-11-14 14:53:06 -08003080 if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003081 mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
Wale Ogunwale1ed0d892015-09-28 13:27:44 -07003082 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003083 }
3084
Wale Ogunwalef6192862016-09-10 13:42:30 -07003085 /** Cancels any running app transitions associated with the task. */
Winsonc28098f2015-10-30 14:50:19 -07003086 void cancelTaskWindowTransition() {
Wale Ogunwalef6192862016-09-10 13:42:30 -07003087 for (int i = mChildren.size() - 1; i >= 0; --i) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003088 mChildren.get(i).cancelAnimation();
Winsonc28098f2015-10-30 14:50:19 -07003089 }
3090 }
3091
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07003092 boolean showForAllUsers() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003093 if (mChildren.isEmpty()) return false;
3094 final ActivityRecord r = getTopNonFinishingActivity();
3095 return r != null && r.mShowForAllUsers;
Jorim Jaggiff71d202016-04-14 13:12:36 -07003096 }
3097
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08003098 @Override
3099 boolean showToCurrentUser() {
Louis Changedbda502020-04-27 15:51:42 +08003100 return mForceShowForAllUsers || showForAllUsers()
3101 || mWmService.isCurrentProfile(getTopMostTask().mUserId);
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08003102 }
3103
3104 void setForceShowForAllUsers(boolean forceShowForAllUsers) {
3105 mForceShowForAllUsers = forceShowForAllUsers;
3106 }
3107
Evan Rosky688c8382020-04-03 17:27:08 -07003108 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003109 public boolean isAttached() {
Andrii Kulian86d676c2020-03-27 19:34:54 -07003110 final TaskDisplayArea taskDisplayArea = getDisplayArea();
3111 return taskDisplayArea != null && !taskDisplayArea.isRemoved();
3112 }
3113
3114 @Override
3115 @Nullable
3116 TaskDisplayArea getDisplayArea() {
3117 return (TaskDisplayArea) super.getDisplayArea();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003118 }
3119
Robert Carr7e4c90e2017-02-15 19:52:38 -08003120 /**
3121 * When we are in a floating stack (Freeform, Pinned, ...) we calculate
3122 * insets differently. However if we are animating to the fullscreen stack
3123 * we need to begin calculating insets as if we were fullscreen, otherwise
3124 * we will have a jump at the end.
3125 */
Robert Carre6275582016-02-29 15:45:45 -08003126 boolean isFloating() {
Hongwei Wang85cf41f2020-01-15 15:14:47 -08003127 return getWindowConfiguration().tasksAreFloating() && !mPreserveNonFloatingState;
Robert Carre6275582016-02-29 15:45:45 -08003128 }
3129
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003130 /**
3131 * Returns true if the stack is translucent and can have other contents visible behind it if
3132 * needed. A stack is considered translucent if it don't contain a visible or
3133 * starting (about to be visible) activity that is fullscreen (opaque).
3134 * @param starting The currently starting activity or null if there is none.
3135 */
3136 @VisibleForTesting
3137 boolean isTranslucent(ActivityRecord starting) {
Robert Carrf6878a42019-12-18 02:13:12 -08003138 if (!isAttached() || isForceHidden()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003139 return true;
3140 }
3141 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isOpaqueActivity,
3142 PooledLambda.__(ActivityRecord.class), starting);
3143 final ActivityRecord opaque = getActivity(p);
3144 p.recycle();
3145 return opaque == null;
3146 }
3147
3148 private static boolean isOpaqueActivity(ActivityRecord r, ActivityRecord starting) {
3149 if (r.finishing) {
3150 // We don't factor in finishing activities when determining translucency since
3151 // they will be gone soon.
3152 return false;
3153 }
3154
3155 if (!r.visibleIgnoringKeyguard && r != starting) {
3156 // Also ignore invisible activities that are not the currently starting
3157 // activity (about to be visible).
3158 return false;
3159 }
3160
3161 if (r.occludesParent() || r.hasWallpaper) {
3162 // Stack isn't translucent if it has at least one fullscreen activity
3163 // that is visible.
3164 return true;
3165 }
3166 return false;
3167 }
3168
Winson Chungd41f71d2018-03-16 15:26:07 -07003169 @Override
3170 public SurfaceControl getAnimationLeashParent() {
Riddle Hsud8302832019-09-23 21:14:07 +08003171 if (WindowManagerService.sHierarchicalAnimations) {
Issei Suzuki71142152019-08-15 14:39:40 +02003172 return super.getAnimationLeashParent();
3173 }
Winson Chung732446a2018-09-19 13:15:17 -07003174 // Currently, only the recents animation will create animation leashes for tasks. In this
3175 // case, reparent the task to the home animation layer while it is being animated to allow
3176 // the home activity to reorder the app windows relative to its own.
3177 return getAppAnimationLayer(ANIMATION_LAYER_HOME);
Winson Chungd41f71d2018-03-16 15:26:07 -07003178 }
3179
lumark5341d1c2019-12-14 01:54:02 +08003180 @Override
3181 Rect getAnimationBounds(int appStackClipMode) {
3182 // TODO(b/131661052): we should remove appStackClipMode with hierarchical animations.
3183 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
3184 // Using the stack bounds here effectively applies the clipping before animation.
3185 return getStack().getBounds();
3186 }
3187 return super.getAnimationBounds(appStackClipMode);
3188 }
3189
lumark19a5d2e2019-10-11 16:19:30 +08003190 boolean shouldAnimate() {
Robert Carr8a2f9132019-11-11 15:03:15 -08003191 /**
3192 * Animations are handled by the TaskOrganizer implementation.
3193 */
Wale Ogunwaledec34082020-03-22 09:45:00 -07003194 if (isOrganized()) {
Robert Carr8a2f9132019-11-11 15:03:15 -08003195 return false;
3196 }
lumark19a5d2e2019-10-11 16:19:30 +08003197 // Don't animate while the task runs recents animation but only if we are in the mode
3198 // where we cancel with deferred screenshot, which means that the controller has
3199 // transformed the task.
3200 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
3201 if (controller != null && controller.isAnimatingTask(this)
3202 && controller.shouldDeferCancelUntilNextTransition()) {
3203 return false;
3204 }
3205 return true;
3206 }
3207
Evan Rosky9020c072018-12-06 14:11:12 -08003208 @Override
Vishnu Nairfd6fb672020-02-14 12:56:37 -08003209 void onSurfaceShown(SurfaceControl.Transaction t) {
3210 super.onSurfaceShown(t);
3211 t.unsetColor(mSurfaceControl);
3212 }
3213
3214 @Override
Evan Rosky9020c072018-12-06 14:11:12 -08003215 SurfaceControl.Builder makeSurface() {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08003216 return super.makeSurface().setColorLayer().setMetadata(METADATA_TASK_ID, mTaskId);
Evan Rosky9020c072018-12-06 14:11:12 -08003217 }
3218
Winson Chungd41f71d2018-03-16 15:26:07 -07003219 boolean isTaskAnimating() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003220 final RecentsAnimationController recentsAnim = mWmService.getRecentsAnimationController();
Winson Chungd41f71d2018-03-16 15:26:07 -07003221 if (recentsAnim != null) {
3222 if (recentsAnim.isAnimatingTask(this)) {
3223 return true;
3224 }
3225 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003226 return forAllTasks((t) -> { return t != this && t.isTaskAnimating(); });
Winson Chungd41f71d2018-03-16 15:26:07 -07003227 }
3228
lumark19a5d2e2019-10-11 16:19:30 +08003229 @Override
3230 RemoteAnimationTarget createRemoteAnimationTarget(
3231 RemoteAnimationController.RemoteAnimationRecord record) {
lumark5341d1c2019-12-14 01:54:02 +08003232 final ActivityRecord activity = getTopMostActivity();
lumark19a5d2e2019-10-11 16:19:30 +08003233 return activity != null ? activity.createRemoteAnimationTarget(record) : null;
3234 }
3235
Daichi Hirono8ecfc6b2020-02-18 16:28:03 +09003236 @Override
3237 boolean canCreateRemoteAnimationTarget() {
3238 return true;
3239 }
3240
Chong Zhangd8ceb852015-11-11 14:53:41 -08003241 WindowState getTopVisibleAppMainWindow() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003242 final ActivityRecord activity = getTopVisibleActivity();
3243 return activity != null ? activity.findMainWindow() : null;
Chong Zhang9184ec62015-09-24 12:32:21 -07003244 }
3245
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003246 ActivityRecord topRunningActivity() {
3247 return topRunningActivity(false /* focusableOnly */);
3248 }
3249
3250 ActivityRecord topRunningActivity(boolean focusableOnly) {
3251 // Split into 2 to avoid object creation due to variable capture.
3252 if (focusableOnly) {
3253 return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
3254 } else {
3255 return getActivity(ActivityRecord::canBeTopRunning);
3256 }
3257 }
3258
3259 ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
3260 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunningNonDelayed
3261 , PooledLambda.__(ActivityRecord.class), notTop);
3262 final ActivityRecord r = getActivity(p);
3263 p.recycle();
3264 return r;
3265 }
3266
3267 private static boolean isTopRunningNonDelayed(ActivityRecord r, ActivityRecord notTop) {
3268 return !r.delayedResume && r != notTop && r.canBeTopRunning();
3269 }
3270
3271 /**
3272 * This is a simplified version of topRunningActivity that provides a number of
3273 * optional skip-over modes. It is intended for use with the ActivityController hook only.
3274 *
3275 * @param token If non-null, any history records matching this token will be skipped.
3276 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
3277 *
3278 * @return Returns the HistoryRecord of the next activity on the stack.
3279 */
3280 ActivityRecord topRunningActivity(IBinder token, int taskId) {
3281 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunning,
3282 PooledLambda.__(ActivityRecord.class), taskId, token);
3283 final ActivityRecord r = getActivity(p);
3284 p.recycle();
3285 return r;
3286 }
3287
3288 private static boolean isTopRunning(ActivityRecord r, int taskId, IBinder notTop) {
3289 return r.getTask().mTaskId != taskId && r.appToken != notTop && r.canBeTopRunning();
3290 }
3291
Garfield Tane8d84ab2019-10-11 09:49:40 -07003292 ActivityRecord getTopFullscreenActivity() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003293 return getActivity((r) -> {
3294 final WindowState win = r.findMainWindow();
3295 return (win != null && win.mAttrs.isFullscreen());
3296 });
Jorim Jaggie6c6ecb2017-07-20 18:09:20 +02003297 }
3298
Garfield Tane8d84ab2019-10-11 09:49:40 -07003299 ActivityRecord getTopVisibleActivity() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003300 return getActivity((r) -> {
3301 // skip hidden (or about to hide) apps
3302 return !r.mIsExiting && r.isClientVisible() && r.mVisibleRequested;
3303 });
Chong Zhangbef461f2015-10-27 11:38:24 -07003304 }
3305
Winson Chungb5ce37c2020-04-22 10:08:28 -07003306 boolean isTopActivityFocusable() {
3307 final ActivityRecord r = topRunningActivity();
3308 return r != null ? r.isFocusable()
3309 : (isFocusable() && getWindowConfiguration().canReceiveKeys());
3310 }
3311
3312 boolean isFocusableAndVisible() {
3313 return isTopActivityFocusable() && shouldBeVisible(null /* starting */);
3314 }
3315
Wale Ogunwale3198da42019-10-10 14:45:03 +02003316 void positionChildAtTop(ActivityRecord child) {
3317 positionChildAt(child, POSITION_TOP);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003318 }
3319
Wale Ogunwale3198da42019-10-10 14:45:03 +02003320 void positionChildAt(ActivityRecord child, int position) {
3321 if (child == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003322 Slog.w(TAG_WM,
3323 "Attempted to position of non-existing app");
3324 return;
3325 }
3326
Wale Ogunwale3198da42019-10-10 14:45:03 +02003327 positionChildAt(position, child, false /* includeParents */);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003328 }
3329
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003330 void forceWindowsScaleable(boolean force) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003331 mWmService.openSurfaceTransaction();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003332 try {
Wale Ogunwalef6192862016-09-10 13:42:30 -07003333 for (int i = mChildren.size() - 1; i >= 0; i--) {
3334 mChildren.get(i).forceWindowsScaleableInTransaction(force);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003335 }
3336 } finally {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003337 mWmService.closeSurfaceTransaction("forceWindowsScaleable");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003338 }
3339 }
3340
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01003341 void setTaskDescription(TaskDescription taskDescription) {
3342 mTaskDescription = taskDescription;
3343 }
3344
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003345 void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003346 mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
3347 mTaskId, snapshot);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003348 }
3349
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01003350 TaskDescription getTaskDescription() {
3351 return mTaskDescription;
3352 }
3353
Wale Ogunwalef6192862016-09-10 13:42:30 -07003354 @Override
Riddle Hsu9a8e3ae2020-03-24 15:22:48 +08003355 int getOrientation(int candidate) {
3356 return canSpecifyOrientation() ? super.getOrientation(candidate) : SCREEN_ORIENTATION_UNSET;
3357 }
3358
3359 private boolean canSpecifyOrientation() {
3360 final int windowingMode = getWindowingMode();
3361 final int activityType = getActivityType();
3362 return windowingMode == WINDOWING_MODE_FULLSCREEN
3363 || activityType == ACTIVITY_TYPE_HOME
3364 || activityType == ACTIVITY_TYPE_RECENTS
3365 || activityType == ACTIVITY_TYPE_ASSISTANT;
3366 }
3367
3368 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07003369 boolean fillsParent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003370 return matchParentBounds();
3371 }
3372
Jeff Changdc9c1d42020-02-11 14:57:34 +08003373 @Override
Wale Ogunwale0d465192020-01-23 19:14:44 -08003374 void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
3375 final int count = mChildren.size();
3376 boolean isLeafTask = true;
3377 if (traverseTopToBottom) {
3378 for (int i = count - 1; i >= 0; --i) {
3379 final Task child = mChildren.get(i).asTask();
3380 if (child != null) {
3381 isLeafTask = false;
3382 child.forAllLeafTasks(callback, traverseTopToBottom);
3383 }
3384 }
3385 } else {
3386 for (int i = 0; i < count; i++) {
3387 final Task child = mChildren.get(i).asTask();
3388 if (child != null) {
3389 isLeafTask = false;
3390 child.forAllLeafTasks(callback, traverseTopToBottom);
3391 }
3392 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003393 }
Wale Ogunwale0d465192020-01-23 19:14:44 -08003394 if (isLeafTask) callback.accept(this);
Wale Ogunwale51362492016-09-08 17:49:17 -07003395 }
3396
Jorim Jaggi329a5832017-01-05 18:57:12 +01003397 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003398 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08003399 super.forAllTasks(callback, traverseTopToBottom);
3400 callback.accept(this);
Jorim Jaggi51304d72017-05-17 17:25:32 +02003401 }
3402
lumarkbc0032a2019-11-01 21:38:13 +08003403 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003404 boolean forAllTasks(Function<Task, Boolean> callback) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003405 if (super.forAllTasks(callback)) return true;
lumarkbc0032a2019-11-01 21:38:13 +08003406 return callback.apply(this);
3407 }
3408
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003409 @Override
3410 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003411 final Task t = super.getTask(callback, traverseTopToBottom);
3412 if (t != null) return t;
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003413 return callback.test(this) ? this : null;
3414 }
3415
Jorim Jaggi50bf59c2018-03-09 17:29:48 +01003416 /**
3417 * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
3418 * flags. See {@link WindowState#canAffectSystemUiFlags()}.
3419 */
3420 void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) {
3421 mCanAffectSystemUiFlags = canAffectSystemUiFlags;
3422 }
3423
3424 /**
3425 * @see #setCanAffectSystemUiFlags
3426 */
3427 boolean canAffectSystemUiFlags() {
3428 return mCanAffectSystemUiFlags;
3429 }
3430
chaviw87ca63a2018-03-26 14:06:17 -07003431 void dontAnimateDimExit() {
3432 mDimmer.dontAnimateExit();
3433 }
3434
Wale Ogunwale9adfe572016-09-08 20:43:58 -07003435 String getName() {
Louis Changcdec0802019-11-11 11:45:07 +08003436 return "Task=" + mTaskId;
Wale Ogunwale9adfe572016-09-08 20:43:58 -07003437 }
3438
Robert Carr18f622f2017-05-08 11:20:43 -07003439 void clearPreserveNonFloatingState() {
3440 mPreserveNonFloatingState = false;
3441 }
3442
chaviw2fb06bc2018-01-19 17:09:15 -08003443 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07003444 Dimmer getDimmer() {
chaviw51e4c2f2020-04-03 13:49:45 -07003445 // If the window is in multi-window mode, we want to dim at the Task level to ensure the dim
3446 // bounds match the area the app lives in
3447 if (inMultiWindowMode()) {
3448 return mDimmer;
3449 }
3450
3451 // If we're not at the root task level, we want to keep traversing through the parents to
3452 // find the root.
3453 // Once at the root task level, we want to check {@link #isTranslucent(ActivityRecord)}.
3454 // If true, we want to get the Dimmer from the level above since we don't want to animate
3455 // the dim with the Task.
3456 if (!isRootTask() || isTranslucent(null)) {
3457 return super.getDimmer();
3458 }
3459
Robert Carrf59b8dd2017-10-02 18:58:36 -07003460 return mDimmer;
3461 }
3462
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003463 void dim(float alpha) {
3464 mDimmer.dimAbove(getPendingTransaction(), alpha);
3465 scheduleAnimation();
3466 }
3467
3468 void stopDimming() {
3469 mDimmer.stopDim(getPendingTransaction());
3470 scheduleAnimation();
3471 }
3472
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003473 boolean isTaskForUser(int userId) {
3474 return mUserId == userId;
3475 }
3476
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07003477 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07003478 void prepareSurfaces() {
3479 mDimmer.resetDimStates();
3480 super.prepareSurfaces();
3481 getDimBounds(mTmpDimBoundsRect);
chaviwe07246a2017-12-12 16:18:29 -08003482
3483 // Bounds need to be relative, as the dim layer is a child.
HEO SEUNGe10f4192019-11-21 10:21:04 +09003484 if (inFreeformWindowingMode()) {
3485 getBounds(mTmpRect);
3486 mTmpDimBoundsRect.offsetTo(mTmpDimBoundsRect.left - mTmpRect.left,
3487 mTmpDimBoundsRect.top - mTmpRect.top);
3488 } else {
3489 mTmpDimBoundsRect.offsetTo(0, 0);
3490 }
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08003491
Vishnu Nairae3b0772020-03-19 16:55:25 -07003492 updateShadowsRadius(isFocused(), getPendingTransaction());
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08003493
Robert Carrf59b8dd2017-10-02 18:58:36 -07003494 if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
3495 scheduleAnimation();
3496 }
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07003497 }
3498
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003499 @Override
lumark04bceb92020-03-07 00:03:33 +08003500 protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
3501 int transit, boolean isVoiceInteraction,
3502 @Nullable OnAnimationFinishedCallback finishedCallback) {
3503 final RecentsAnimationController control = mWmService.getRecentsAnimationController();
3504 if (control != null && enter
3505 && getDisplayContent().mAppTransition.isNextAppTransitionCustomFromRecents()) {
3506 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
3507 "addTaskToRecentsAnimationIfNeeded, control: %s, task: %s, transit: %s",
3508 control, asTask(), AppTransition.appTransitionToString(transit));
3509 // We let the transition to be controlled by RecentsAnimation, and callback task's
3510 // RemoteAnimationTarget for remote runner to animate.
3511 control.addTaskToTargets(getRootTask(), finishedCallback);
3512 } else {
3513 super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, finishedCallback);
3514 }
3515 }
3516
3517 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003518 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003519 super.dump(pw, prefix, dumpAll);
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003520 final String doublePrefix = prefix + " ";
3521
3522 pw.println(prefix + "taskId=" + mTaskId);
Bryce Leef3c6a472017-11-14 14:53:06 -08003523 pw.println(doublePrefix + "mBounds=" + getBounds().toShortString());
Wale Ogunwalef6192862016-09-10 13:42:30 -07003524 pw.println(doublePrefix + "appTokens=" + mChildren);
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003525
3526 final String triplePrefix = doublePrefix + " ";
Jorim Jaggi153dc9d2018-02-23 13:28:15 +01003527 final String quadruplePrefix = triplePrefix + " ";
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003528
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003529 int[] index = { 0 };
3530 forAllActivities((r) -> {
3531 pw.println(triplePrefix + "Activity #" + index[0]++ + " " + r);
3532 r.dump(pw, quadruplePrefix, dumpAll);
3533 });
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003534 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07003535
Louis Changcdec0802019-11-11 11:45:07 +08003536 /**
Winson Chung66b08f02020-03-03 14:32:35 -08003537 * Fills in a {@link TaskInfo} with information from this task. Note that the base intent in the
3538 * task info will not include any extras or clip data.
Louis Changcdec0802019-11-11 11:45:07 +08003539 */
3540 void fillTaskInfo(TaskInfo info) {
3541 getNumRunningActivities(mReuseActivitiesReport);
3542 info.userId = mUserId;
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003543 info.stackId = getRootTaskId();
Louis Changcdec0802019-11-11 11:45:07 +08003544 info.taskId = mTaskId;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003545 info.displayId = getDisplayId();
Wale Ogunwale21e06482019-11-18 05:14:15 -08003546 info.isRunning = getTopNonFinishingActivity() != null;
Evan Rosky0037e5f2019-11-05 10:26:24 -08003547 final Intent baseIntent = getBaseIntent();
Riddle Hsuc5a1bd42020-02-02 19:32:17 +08003548 // Make a copy of base intent because this is like a snapshot info.
3549 // Besides, {@link RecentTasks#getRecentTasksImpl} may modify it.
Winson Chung661d8662020-04-14 14:47:32 -07003550 final int baseIntentFlags = baseIntent == null ? 0 : baseIntent.getFlags();
Winson Chung66b08f02020-03-03 14:32:35 -08003551 info.baseIntent = baseIntent == null ? new Intent() : baseIntent.cloneFilter();
Winson Chung661d8662020-04-14 14:47:32 -07003552 info.baseIntent.setFlags(baseIntentFlags);
Louis Changcdec0802019-11-11 11:45:07 +08003553 info.baseActivity = mReuseActivitiesReport.base != null
3554 ? mReuseActivitiesReport.base.intent.getComponent()
3555 : null;
3556 info.topActivity = mReuseActivitiesReport.top != null
3557 ? mReuseActivitiesReport.top.mActivityComponent
3558 : null;
3559 info.origActivity = origActivity;
3560 info.realActivity = realActivity;
3561 info.numActivities = mReuseActivitiesReport.numActivities;
3562 info.lastActiveTime = lastActiveTime;
3563 info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
3564 info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
Louis Changcdec0802019-11-11 11:45:07 +08003565 info.configuration.setTo(getConfiguration());
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07003566 info.token = mRemoteToken.toWindowContainerToken();
Evan Roskya8fde152020-01-07 19:09:13 -08003567
3568 //TODO (AM refactor): Just use local once updateEffectiveIntent is run during all child
3569 // order changes.
3570 final Task top = getTopMostTask();
3571 info.resizeMode = top != null ? top.mResizeMode : mResizeMode;
Louis Changa009c762020-02-26 11:21:31 +08003572 info.topActivityType = top.getActivityType();
Robert Carrf6690d12020-02-04 14:16:21 -08003573
Jorim Jaggi785edb42020-05-08 12:34:47 +00003574 if (mPictureInPictureParams.empty()) {
Robert Carrf6690d12020-02-04 14:16:21 -08003575 info.pictureInPictureParams = null;
3576 } else {
Jorim Jaggi785edb42020-05-08 12:34:47 +00003577 info.pictureInPictureParams = mPictureInPictureParams;
Robert Carrf6690d12020-02-04 14:16:21 -08003578 }
Hongwei Wang2e725be2020-03-10 11:01:28 -07003579 info.topActivityInfo = mReuseActivitiesReport.top != null
3580 ? mReuseActivitiesReport.top.info
3581 : null;
Louis Changcdec0802019-11-11 11:45:07 +08003582 }
3583
3584 /**
3585 * Returns a {@link TaskInfo} with information from this task.
3586 */
3587 ActivityManager.RunningTaskInfo getTaskInfo() {
3588 ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
3589 fillTaskInfo(info);
3590 return info;
3591 }
3592
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003593 boolean isTaskId(int taskId) {
3594 return mTaskId == taskId;
3595 }
3596
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003597 @Override
3598 Task asTask() {
3599 // I'm a task!
3600 return this;
3601 }
3602
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003603 /**
3604 * Returns true if the task should be visible.
3605 *
3606 * @param starting The currently starting activity or null if there is none.
3607 */
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003608 boolean shouldBeVisible(ActivityRecord starting) {
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003609 return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE;
3610 }
3611
3612 /**
3613 * Returns true if the task should be visible.
3614 *
3615 * @param starting The currently starting activity or null if there is none.
3616 */
3617 @ActivityStack.StackVisibility
3618 int getVisibility(ActivityRecord starting) {
3619 if (!isAttached() || isForceHidden()) {
3620 return STACK_VISIBILITY_INVISIBLE;
3621 }
3622
3623 boolean gotSplitScreenStack = false;
3624 boolean gotOpaqueSplitScreenPrimary = false;
3625 boolean gotOpaqueSplitScreenSecondary = false;
3626 boolean gotTranslucentFullscreen = false;
3627 boolean gotTranslucentSplitScreenPrimary = false;
3628 boolean gotTranslucentSplitScreenSecondary = false;
3629 boolean shouldBeVisible = true;
3630
3631 // This stack is only considered visible if all its parent stacks are considered visible,
3632 // so check the visibility of all ancestor stacks first.
3633 final WindowContainer parent = getParent();
3634 if (parent.asTask() != null) {
3635 final int parentVisibility = parent.asTask().getVisibility(starting);
3636 if (parentVisibility == STACK_VISIBILITY_INVISIBLE) {
3637 // Can't be visible if parent isn't visible
3638 return STACK_VISIBILITY_INVISIBLE;
3639 } else if (parentVisibility == STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT) {
3640 // Parent is behind a translucent container so the highest visibility this container
3641 // can get is that.
3642 gotTranslucentFullscreen = true;
3643 }
3644 }
3645
3646 final int windowingMode = getWindowingMode();
3647 final boolean isAssistantType = isActivityTypeAssistant();
3648 for (int i = parent.getChildCount() - 1; i >= 0; --i) {
3649 final WindowContainer wc = parent.getChildAt(i);
3650 final Task other = wc.asTask();
3651 if (other == null) continue;
3652
3653 final boolean hasRunningActivities = other.topRunningActivity() != null;
3654 if (other == this) {
3655 // Should be visible if there is no other stack occluding it, unless it doesn't
3656 // have any running activities, not starting one and not home stack.
3657 shouldBeVisible = hasRunningActivities || isInTask(starting) != null
3658 || isActivityTypeHome();
3659 break;
3660 }
3661
3662 if (!hasRunningActivities) {
3663 continue;
3664 }
3665
3666 final int otherWindowingMode = other.getWindowingMode();
3667
3668 if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) {
3669 // In this case the home stack isn't resizeable even though we are in split-screen
3670 // mode. We still want the primary splitscreen stack to be visible as there will be
3671 // a slight hint of it in the status bar area above the non-resizeable home
3672 // activity. In addition, if the fullscreen assistant is over primary splitscreen
3673 // stack, the stack should still be visible in the background as long as the recents
3674 // animation is running.
3675 final int activityType = other.getActivityType();
3676 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
3677 if (activityType == ACTIVITY_TYPE_HOME
3678 || (activityType == ACTIVITY_TYPE_ASSISTANT
3679 && mWmService.getRecentsAnimationController() != null)) {
3680 break;
3681 }
3682 }
3683 if (other.isTranslucent(starting)) {
3684 // Can be visible behind a translucent fullscreen stack.
3685 gotTranslucentFullscreen = true;
3686 continue;
3687 }
3688 return STACK_VISIBILITY_INVISIBLE;
3689 } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
3690 && !gotOpaqueSplitScreenPrimary) {
3691 gotSplitScreenStack = true;
3692 gotTranslucentSplitScreenPrimary = other.isTranslucent(starting);
3693 gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary;
3694 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
3695 && gotOpaqueSplitScreenPrimary) {
3696 // Can not be visible behind another opaque stack in split-screen-primary mode.
3697 return STACK_VISIBILITY_INVISIBLE;
3698 }
3699 } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
3700 && !gotOpaqueSplitScreenSecondary) {
3701 gotSplitScreenStack = true;
3702 gotTranslucentSplitScreenSecondary = other.isTranslucent(starting);
3703 gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary;
3704 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
3705 && gotOpaqueSplitScreenSecondary) {
3706 // Can not be visible behind another opaque stack in split-screen-secondary mode.
3707 return STACK_VISIBILITY_INVISIBLE;
3708 }
3709 }
3710 if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) {
3711 // Can not be visible if we are in split-screen windowing mode and both halves of
3712 // the screen are opaque.
3713 return STACK_VISIBILITY_INVISIBLE;
3714 }
3715 if (isAssistantType && gotSplitScreenStack) {
3716 // Assistant stack can't be visible behind split-screen. In addition to this not
3717 // making sense, it also works around an issue here we boost the z-order of the
3718 // assistant window surfaces in window manager whenever it is visible.
3719 return STACK_VISIBILITY_INVISIBLE;
3720 }
3721 }
3722
3723 if (!shouldBeVisible) {
3724 return STACK_VISIBILITY_INVISIBLE;
3725 }
3726
3727 // Handle cases when there can be a translucent split-screen stack on top.
3728 switch (windowingMode) {
3729 case WINDOWING_MODE_FULLSCREEN:
3730 if (gotTranslucentSplitScreenPrimary || gotTranslucentSplitScreenSecondary) {
3731 // At least one of the split-screen stacks that covers this one is translucent.
3732 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
3733 }
3734 break;
3735 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
3736 if (gotTranslucentSplitScreenPrimary) {
3737 // Covered by translucent primary split-screen on top.
3738 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
3739 }
3740 break;
3741 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
3742 if (gotTranslucentSplitScreenSecondary) {
3743 // Covered by translucent secondary split-screen on top.
3744 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
3745 }
3746 break;
3747 }
3748
3749 // Lastly - check if there is a translucent fullscreen stack on top.
3750 return gotTranslucentFullscreen ? STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
3751 : STACK_VISIBILITY_VISIBLE;
3752 }
3753
3754 ActivityRecord isInTask(ActivityRecord r) {
3755 if (r == null) {
3756 return null;
3757 }
3758 final Task task = r.getRootTask();
3759 if (task != null && r.isDescendantOf(task)) {
3760 if (task != this) Slog.w(TAG, "Illegal state! task does not point to stack it is in. "
3761 + "stack=" + this + " task=" + task + " r=" + r
3762 + " callers=" + Debug.getCallers(15, "\n"));
3763 return r;
3764 }
3765 return null;
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003766 }
3767
Louis Changcdec0802019-11-11 11:45:07 +08003768 void dump(PrintWriter pw, String prefix) {
3769 pw.print(prefix); pw.print("userId="); pw.print(mUserId);
3770 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
3771 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
3772 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Wale Ogunwale0d465192020-01-23 19:14:44 -08003773 pw.print(" mCallingPackage="); pw.print(mCallingPackage);
Philip P. Moltmannee295092020-02-10 08:46:26 -08003774 pw.print(" mCallingFeatureId="); pw.println(mCallingFeatureId);
Louis Changcdec0802019-11-11 11:45:07 +08003775 if (affinity != null || rootAffinity != null) {
3776 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
3777 if (affinity == null || !affinity.equals(rootAffinity)) {
3778 pw.print(" root="); pw.println(rootAffinity);
3779 } else {
3780 pw.println();
3781 }
3782 }
Garfield Tan5901e7c2020-02-07 17:12:22 -08003783 if (mWindowLayoutAffinity != null) {
3784 pw.print(prefix); pw.print("windowLayoutAffinity="); pw.println(mWindowLayoutAffinity);
3785 }
Louis Changcdec0802019-11-11 11:45:07 +08003786 if (voiceSession != null || voiceInteractor != null) {
3787 pw.print(prefix); pw.print("VOICE: session=0x");
3788 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
3789 pw.print(" interactor=0x");
3790 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
3791 }
3792 if (intent != null) {
3793 StringBuilder sb = new StringBuilder(128);
3794 sb.append(prefix); sb.append("intent={");
3795 intent.toShortString(sb, false, true, false, false);
3796 sb.append('}');
3797 pw.println(sb.toString());
3798 }
3799 if (affinityIntent != null) {
3800 StringBuilder sb = new StringBuilder(128);
3801 sb.append(prefix); sb.append("affinityIntent={");
3802 affinityIntent.toShortString(sb, false, true, false, false);
3803 sb.append('}');
3804 pw.println(sb.toString());
3805 }
3806 if (origActivity != null) {
3807 pw.print(prefix); pw.print("origActivity=");
3808 pw.println(origActivity.flattenToShortString());
3809 }
3810 if (realActivity != null) {
3811 pw.print(prefix); pw.print("mActivityComponent=");
3812 pw.println(realActivity.flattenToShortString());
3813 }
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08003814 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard()) {
Louis Changcdec0802019-11-11 11:45:07 +08003815 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
3816 pw.print(" isPersistable="); pw.print(isPersistable);
Louis Changcdec0802019-11-11 11:45:07 +08003817 pw.print(" activityType="); pw.println(getActivityType());
3818 }
3819 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
3820 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
3821 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
3822 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
3823 pw.print(" mReuseTask="); pw.print(mReuseTask);
3824 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
3825 }
3826 if (mAffiliatedTaskId != mTaskId || mPrevAffiliateTaskId != INVALID_TASK_ID
3827 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
3828 || mNextAffiliate != null) {
3829 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
3830 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
3831 pw.print(" (");
3832 if (mPrevAffiliate == null) {
3833 pw.print("null");
3834 } else {
3835 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
3836 }
3837 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
3838 pw.print(" (");
3839 if (mNextAffiliate == null) {
3840 pw.print("null");
3841 } else {
3842 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
3843 }
3844 pw.println(")");
3845 }
3846 pw.print(prefix); pw.print("Activities="); pw.println(mChildren);
3847 if (!askedCompatMode || !inRecents || !isAvailable) {
3848 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
3849 pw.print(" inRecents="); pw.print(inRecents);
3850 pw.print(" isAvailable="); pw.println(isAvailable);
3851 }
3852 if (lastDescription != null) {
3853 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
3854 }
3855 if (mRootProcess != null) {
3856 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
3857 }
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003858 pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId());
Dianne Hackborn9106f2a2020-04-30 16:23:20 -07003859 pw.print(prefix); pw.print("mHasBeenVisible="); pw.println(getHasBeenVisible());
3860 pw.print(prefix); pw.print("mResizeMode=");
3861 pw.print(ActivityInfo.resizeModeToString(mResizeMode));
3862 pw.print(" mSupportsPictureInPicture="); pw.print(mSupportsPictureInPicture);
3863 pw.print(" isResizeable="); pw.println(isResizeable());
3864 pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
Louis Changcdec0802019-11-11 11:45:07 +08003865 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
3866 }
3867
3868 @Override
3869 public String toString() {
3870 StringBuilder sb = new StringBuilder(128);
3871 if (stringName != null) {
3872 sb.append(stringName);
3873 sb.append(" U=");
3874 sb.append(mUserId);
3875 sb.append(" StackId=");
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003876 sb.append(getRootTaskId());
Louis Changcdec0802019-11-11 11:45:07 +08003877 sb.append(" sz=");
3878 sb.append(getChildCount());
3879 sb.append('}');
3880 return sb.toString();
3881 }
3882 sb.append("Task{");
3883 sb.append(Integer.toHexString(System.identityHashCode(this)));
3884 sb.append(" #");
3885 sb.append(mTaskId);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003886 sb.append(" visible=" + shouldBeVisible(null /* starting */));
3887 sb.append(" type=" + activityTypeToString(getActivityType()));
3888 sb.append(" mode=" + windowingModeToString(getWindowingMode()));
3889 sb.append(" translucent=" + isTranslucent(null /* starting */));
Louis Changcdec0802019-11-11 11:45:07 +08003890 if (affinity != null) {
3891 sb.append(" A=");
3892 sb.append(affinity);
Evan Rosky0037e5f2019-11-05 10:26:24 -08003893 } else if (intent != null && intent.getComponent() != null) {
Louis Changcdec0802019-11-11 11:45:07 +08003894 sb.append(" I=");
3895 sb.append(intent.getComponent().flattenToShortString());
3896 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
3897 sb.append(" aI=");
3898 sb.append(affinityIntent.getComponent().flattenToShortString());
3899 } else {
3900 sb.append(" ??");
3901 }
3902 stringName = sb.toString();
3903 return toString();
3904 }
3905
Louis Changcdec0802019-11-11 11:45:07 +08003906 /** @see #getNumRunningActivities(TaskActivitiesReport) */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003907 static class TaskActivitiesReport implements Consumer<ActivityRecord> {
Louis Changcdec0802019-11-11 11:45:07 +08003908 int numRunning;
3909 int numActivities;
3910 ActivityRecord top;
3911 ActivityRecord base;
3912
3913 void reset() {
3914 numRunning = numActivities = 0;
3915 top = base = null;
3916 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003917
3918 @Override
3919 public void accept(ActivityRecord r) {
3920 if (r.finishing) {
3921 return;
3922 }
3923
3924 base = r;
3925
3926 // Increment the total number of non-finishing activities
3927 numActivities++;
3928
3929 if (top == null || (top.isState(ActivityState.INITIALIZING))) {
3930 top = r;
3931 // Reset the number of running activities until we hit the first non-initializing
3932 // activity
3933 numRunning = 0;
3934 }
3935 if (r.attachedToProcess()) {
3936 // Increment the number of actually running activities
3937 numRunning++;
3938 }
3939 }
Louis Changcdec0802019-11-11 11:45:07 +08003940 }
3941
3942 /**
3943 * Saves this {@link Task} to XML using given serializer.
3944 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003945 void saveToXml(XmlSerializer out) throws Exception {
Louis Changcdec0802019-11-11 11:45:07 +08003946 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
3947
3948 out.attribute(null, ATTR_TASKID, String.valueOf(mTaskId));
3949 if (realActivity != null) {
3950 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
3951 }
3952 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
3953 if (origActivity != null) {
3954 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
3955 }
3956 // Write affinity, and root affinity if it is different from affinity.
3957 // We use the special string "@" for a null root affinity, so we can identify
3958 // later whether we were given a root affinity or should just make it the
3959 // same as the affinity.
3960 if (affinity != null) {
3961 out.attribute(null, ATTR_AFFINITY, affinity);
3962 if (!affinity.equals(rootAffinity)) {
3963 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3964 }
3965 } else if (rootAffinity != null) {
3966 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3967 }
Garfield Tan5901e7c2020-02-07 17:12:22 -08003968 if (mWindowLayoutAffinity != null) {
3969 out.attribute(null, ATTR_WINDOW_LAYOUT_AFFINITY, mWindowLayoutAffinity);
3970 }
Louis Changcdec0802019-11-11 11:45:07 +08003971 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
3972 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
3973 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
3974 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
3975 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
3976 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
3977 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
3978 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
3979 if (lastDescription != null) {
3980 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
3981 }
3982 if (getTaskDescription() != null) {
3983 getTaskDescription().saveToXml(out);
3984 }
3985 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
3986 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
3987 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
3988 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
3989 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
3990 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
Philip P. Moltmannee295092020-02-10 08:46:26 -08003991 out.attribute(null, ATTR_CALLING_FEATURE_ID,
3992 mCallingFeatureId == null ? "" : mCallingFeatureId);
Louis Changcdec0802019-11-11 11:45:07 +08003993 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
3994 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
3995 String.valueOf(mSupportsPictureInPicture));
3996 if (mLastNonFullscreenBounds != null) {
3997 out.attribute(
3998 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
3999 }
4000 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
4001 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
4002 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
4003
4004 if (affinityIntent != null) {
4005 out.startTag(null, TAG_AFFINITYINTENT);
4006 affinityIntent.saveToXml(out);
4007 out.endTag(null, TAG_AFFINITYINTENT);
4008 }
4009
4010 if (intent != null) {
4011 out.startTag(null, TAG_INTENT);
4012 intent.saveToXml(out);
4013 out.endTag(null, TAG_INTENT);
4014 }
4015
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004016 sTmpException = null;
4017 final PooledFunction f = PooledLambda.obtainFunction(Task::saveActivityToXml,
4018 PooledLambda.__(ActivityRecord.class), getBottomMostActivity(), out);
4019 forAllActivities(f);
4020 f.recycle();
4021 if (sTmpException != null) {
4022 throw sTmpException;
4023 }
4024 }
4025
4026 private static boolean saveActivityToXml(
4027 ActivityRecord r, ActivityRecord first, XmlSerializer out) {
4028 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable()
4029 || ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
4030 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT)
4031 && r != first) {
4032 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
4033 return true;
4034 }
4035 try {
Louis Changcdec0802019-11-11 11:45:07 +08004036 out.startTag(null, TAG_ACTIVITY);
4037 r.saveToXml(out);
4038 out.endTag(null, TAG_ACTIVITY);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004039 return false;
4040 } catch (Exception e) {
4041 sTmpException = e;
4042 return true;
Louis Changcdec0802019-11-11 11:45:07 +08004043 }
4044 }
4045
Louis Changcdec0802019-11-11 11:45:07 +08004046 static Task restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
4047 throws IOException, XmlPullParserException {
Garfield Tan5044a152020-05-01 14:13:35 -07004048 Intent intent = null;
4049 Intent affinityIntent = null;
4050 ArrayList<ActivityRecord> activities = new ArrayList<>();
4051 ComponentName realActivity = null;
4052 boolean realActivitySuspended = false;
4053 ComponentName origActivity = null;
4054 String affinity = null;
4055 String rootAffinity = null;
4056 boolean hasRootAffinity = false;
4057 String windowLayoutAffinity = null;
4058 boolean rootHasReset = false;
4059 boolean autoRemoveRecents = false;
4060 boolean askedCompatMode = false;
4061 int taskType = 0;
4062 int userId = 0;
4063 boolean userSetupComplete = true;
4064 int effectiveUid = -1;
4065 String lastDescription = null;
4066 long lastTimeOnTop = 0;
4067 boolean neverRelinquishIdentity = true;
4068 int taskId = INVALID_TASK_ID;
4069 final int outerDepth = in.getDepth();
4070 TaskDescription taskDescription = new TaskDescription();
4071 int taskAffiliation = INVALID_TASK_ID;
4072 int taskAffiliationColor = 0;
4073 int prevTaskId = INVALID_TASK_ID;
4074 int nextTaskId = INVALID_TASK_ID;
4075 int callingUid = -1;
4076 String callingPackage = "";
4077 String callingFeatureId = null;
4078 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4079 boolean supportsPictureInPicture = false;
4080 Rect lastNonFullscreenBounds = null;
4081 int minWidth = INVALID_MIN_SIZE;
4082 int minHeight = INVALID_MIN_SIZE;
4083 int persistTaskVersion = 0;
Louis Changcdec0802019-11-11 11:45:07 +08004084
Garfield Tan5044a152020-05-01 14:13:35 -07004085 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
4086 final String attrName = in.getAttributeName(attrNdx);
4087 final String attrValue = in.getAttributeValue(attrNdx);
4088 if (TaskPersister.DEBUG) {
4089 Slog.d(TaskPersister.TAG, "Task: attribute name=" + attrName + " value="
4090 + attrValue);
Louis Changcdec0802019-11-11 11:45:07 +08004091 }
Garfield Tan5044a152020-05-01 14:13:35 -07004092 switch (attrName) {
4093 case ATTR_TASKID:
4094 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
4095 break;
4096 case ATTR_REALACTIVITY:
4097 realActivity = ComponentName.unflattenFromString(attrValue);
4098 break;
4099 case ATTR_REALACTIVITY_SUSPENDED:
4100 realActivitySuspended = Boolean.valueOf(attrValue);
4101 break;
4102 case ATTR_ORIGACTIVITY:
4103 origActivity = ComponentName.unflattenFromString(attrValue);
4104 break;
4105 case ATTR_AFFINITY:
4106 affinity = attrValue;
4107 break;
4108 case ATTR_ROOT_AFFINITY:
4109 rootAffinity = attrValue;
4110 hasRootAffinity = true;
4111 break;
4112 case ATTR_WINDOW_LAYOUT_AFFINITY:
4113 windowLayoutAffinity = attrValue;
4114 break;
4115 case ATTR_ROOTHASRESET:
4116 rootHasReset = Boolean.parseBoolean(attrValue);
4117 break;
4118 case ATTR_AUTOREMOVERECENTS:
4119 autoRemoveRecents = Boolean.parseBoolean(attrValue);
4120 break;
4121 case ATTR_ASKEDCOMPATMODE:
4122 askedCompatMode = Boolean.parseBoolean(attrValue);
4123 break;
4124 case ATTR_USERID:
4125 userId = Integer.parseInt(attrValue);
4126 break;
4127 case ATTR_USER_SETUP_COMPLETE:
4128 userSetupComplete = Boolean.parseBoolean(attrValue);
4129 break;
4130 case ATTR_EFFECTIVE_UID:
4131 effectiveUid = Integer.parseInt(attrValue);
4132 break;
4133 case ATTR_TASKTYPE:
4134 taskType = Integer.parseInt(attrValue);
4135 break;
4136 case ATTR_LASTDESCRIPTION:
4137 lastDescription = attrValue;
4138 break;
4139 case ATTR_LASTTIMEMOVED:
4140 lastTimeOnTop = Long.parseLong(attrValue);
4141 break;
4142 case ATTR_NEVERRELINQUISH:
4143 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
4144 break;
4145 case ATTR_TASK_AFFILIATION:
4146 taskAffiliation = Integer.parseInt(attrValue);
4147 break;
4148 case ATTR_PREV_AFFILIATION:
4149 prevTaskId = Integer.parseInt(attrValue);
4150 break;
4151 case ATTR_NEXT_AFFILIATION:
4152 nextTaskId = Integer.parseInt(attrValue);
4153 break;
4154 case ATTR_TASK_AFFILIATION_COLOR:
4155 taskAffiliationColor = Integer.parseInt(attrValue);
4156 break;
4157 case ATTR_CALLING_UID:
4158 callingUid = Integer.parseInt(attrValue);
4159 break;
4160 case ATTR_CALLING_PACKAGE:
4161 callingPackage = attrValue;
4162 break;
4163 case ATTR_CALLING_FEATURE_ID:
4164 callingFeatureId = attrValue;
4165 break;
4166 case ATTR_RESIZE_MODE:
4167 resizeMode = Integer.parseInt(attrValue);
4168 break;
4169 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
4170 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
4171 break;
4172 case ATTR_NON_FULLSCREEN_BOUNDS:
4173 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
4174 break;
4175 case ATTR_MIN_WIDTH:
4176 minWidth = Integer.parseInt(attrValue);
4177 break;
4178 case ATTR_MIN_HEIGHT:
4179 minHeight = Integer.parseInt(attrValue);
4180 break;
4181 case ATTR_PERSIST_TASK_VERSION:
4182 persistTaskVersion = Integer.parseInt(attrValue);
4183 break;
4184 default:
4185 if (!attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
4186 Slog.w(TAG, "Task: Unknown attribute=" + attrName);
Louis Changcdec0802019-11-11 11:45:07 +08004187 }
Louis Changcdec0802019-11-11 11:45:07 +08004188 }
Garfield Tan5044a152020-05-01 14:13:35 -07004189 }
4190 taskDescription.restoreFromXml(in);
4191
4192 int event;
4193 while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
4194 && (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
4195 if (event == XmlPullParser.START_TAG) {
4196 final String name = in.getName();
4197 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: START_TAG name=" + name);
4198 if (TAG_AFFINITYINTENT.equals(name)) {
4199 affinityIntent = Intent.restoreFromXml(in);
4200 } else if (TAG_INTENT.equals(name)) {
4201 intent = Intent.restoreFromXml(in);
4202 } else if (TAG_ACTIVITY.equals(name)) {
4203 ActivityRecord activity =
4204 ActivityRecord.restoreFromXml(in, stackSupervisor);
4205 if (TaskPersister.DEBUG) {
4206 Slog.d(TaskPersister.TAG, "Task: activity=" + activity);
Louis Changcdec0802019-11-11 11:45:07 +08004207 }
Garfield Tan5044a152020-05-01 14:13:35 -07004208 if (activity != null) {
4209 activities.add(activity);
4210 }
4211 } else {
4212 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
4213 XmlUtils.skipCurrentTag(in);
Louis Changcdec0802019-11-11 11:45:07 +08004214 }
4215 }
Garfield Tan5044a152020-05-01 14:13:35 -07004216 }
4217 if (!hasRootAffinity) {
4218 rootAffinity = affinity;
4219 } else if ("@".equals(rootAffinity)) {
4220 rootAffinity = null;
4221 }
4222 if (effectiveUid <= 0) {
4223 Intent checkIntent = intent != null ? intent : affinityIntent;
4224 effectiveUid = 0;
4225 if (checkIntent != null) {
4226 IPackageManager pm = AppGlobals.getPackageManager();
4227 try {
4228 ApplicationInfo ai = pm.getApplicationInfo(
4229 checkIntent.getComponent().getPackageName(),
4230 PackageManager.MATCH_UNINSTALLED_PACKAGES
4231 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
4232 if (ai != null) {
4233 effectiveUid = ai.uid;
4234 }
4235 } catch (RemoteException e) {
4236 }
Louis Changcdec0802019-11-11 11:45:07 +08004237 }
Garfield Tan5044a152020-05-01 14:13:35 -07004238 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
4239 + ": effectiveUid=" + effectiveUid);
Louis Changcdec0802019-11-11 11:45:07 +08004240 }
4241
Garfield Tan5044a152020-05-01 14:13:35 -07004242 if (persistTaskVersion < 1) {
4243 // We need to convert the resize mode of home activities saved before version one if
4244 // they are marked as RESIZE_MODE_RESIZEABLE to
4245 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
4246 // before version 1 and the system didn't resize home activities before then.
4247 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
4248 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4249 }
4250 } else {
4251 // This activity has previously marked itself explicitly as both resizeable and
4252 // supporting picture-in-picture. Since there is no longer a requirement for
4253 // picture-in-picture activities to be resizeable, we can mark this simply as
4254 // resizeable and supporting picture-in-picture separately.
4255 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
4256 resizeMode = RESIZE_MODE_RESIZEABLE;
4257 supportsPictureInPicture = true;
4258 }
Louis Changcdec0802019-11-11 11:45:07 +08004259 }
Garfield Tan5044a152020-05-01 14:13:35 -07004260
4261 final Task task = new ActivityStack(stackSupervisor.mService, taskId, intent,
4262 affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
4263 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
4264 lastTimeOnTop, neverRelinquishIdentity, taskDescription, taskAffiliation,
4265 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
4266 callingFeatureId, resizeMode, supportsPictureInPicture, realActivitySuspended,
4267 userSetupComplete, minWidth, minHeight, null /*ActivityInfo*/,
4268 null /*_voiceSession*/, null /*_voiceInteractor*/, null /* stack */);
4269 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
4270 task.setBounds(lastNonFullscreenBounds);
4271 task.mWindowLayoutAffinity = windowLayoutAffinity;
4272
4273 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4274 task.addChild(activities.get(activityNdx));
4275 }
4276
4277 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
4278 return task;
Robert Carrf59b8dd2017-10-02 18:58:36 -07004279 }
Robert Carr8a2f9132019-11-11 15:03:15 -08004280
Wale Ogunwaledec34082020-03-22 09:45:00 -07004281 @Override
4282 boolean isOrganized() {
Wale Ogunwale465b1e12020-03-31 12:15:51 -07004283 return mTaskOrganizer != null;
Robert Carr8a2f9132019-11-11 15:03:15 -08004284 }
4285
4286 @Override
4287 protected void reparentSurfaceControl(SurfaceControl.Transaction t, SurfaceControl newParent) {
4288 /**
Louis Changa009c762020-02-26 11:21:31 +08004289 * Avoid reparenting SurfaceControl of the organized tasks that are always on top, since
4290 * the surfaces should be controlled by the organizer itself, like bubbles.
Robert Carr8a2f9132019-11-11 15:03:15 -08004291 */
Louis Changa009c762020-02-26 11:21:31 +08004292 if (isOrganized() && isAlwaysOnTop()) {
Robert Carr8a2f9132019-11-11 15:03:15 -08004293 return;
4294 }
4295 super.reparentSurfaceControl(t, newParent);
4296 }
4297
Robert Carrde96c8a2020-03-24 15:22:21 -07004298 void setHasBeenVisible(boolean hasBeenVisible) {
Winson Chung8b5d23a2020-04-06 19:23:23 -07004299 final boolean prevHasBeenVisible = mHasBeenVisible;
Robert Carrde96c8a2020-03-24 15:22:21 -07004300 mHasBeenVisible = hasBeenVisible;
4301 if (hasBeenVisible) {
Winson Chung8b5d23a2020-04-06 19:23:23 -07004302 // If the task is not yet visible when it is added to the task organizer, then we should
4303 // hide it to allow the task organizer to show it when it is properly reparented. We
4304 // skip this for tasks created by the organizer because they can synchronously update
4305 // the leash before new children are added to the task.
4306 if (!mCreatedByOrganizer && mTaskOrganizer != null && !prevHasBeenVisible) {
4307 getPendingTransaction().hide(getSurfaceControl());
4308 commitPendingTransaction();
4309 }
4310
Robert Carrde96c8a2020-03-24 15:22:21 -07004311 sendTaskAppeared();
4312 if (!isRootTask()) {
4313 getRootTask().setHasBeenVisible(true);
4314 }
4315 }
4316 }
4317
4318 boolean getHasBeenVisible() {
4319 return mHasBeenVisible;
4320 }
4321
chaviwda7b3c22020-04-24 11:25:08 -07004322 /** In the case that these conditions are true, we want to send the Task to the organizer:
4323 * 1. An organizer has been set
4324 * 2. The Task was created by the organizer
4325 * or
4326 * 2a. We have a SurfaceControl
4327 * 2b. We have finished drawing
Robert Carrde96c8a2020-03-24 15:22:21 -07004328 * Any time any of these conditions are updated, the updating code should call
4329 * sendTaskAppeared.
4330 */
Louis Chang9d35a3a2020-04-06 17:23:02 +08004331 boolean taskAppearedReady() {
chaviwda7b3c22020-04-24 11:25:08 -07004332 if (mTaskOrganizer == null) {
4333 return false;
4334 }
4335
4336 if (mCreatedByOrganizer) {
4337 return true;
4338 }
4339
4340 return mSurfaceControl != null && getHasBeenVisible();
Robert Carrde96c8a2020-03-24 15:22:21 -07004341 }
4342
Robert Carr8a2f9132019-11-11 15:03:15 -08004343 private void sendTaskAppeared() {
Louis Chang9d35a3a2020-04-06 17:23:02 +08004344 if (mTaskOrganizer != null) {
Robert Carr8a2f9132019-11-11 15:03:15 -08004345 mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this);
4346 }
4347 }
4348
chaviwda7b3c22020-04-24 11:25:08 -07004349 private void sendTaskVanished(ITaskOrganizer organizer) {
4350 if (organizer != null) {
4351 mAtmService.mTaskOrganizerController.onTaskVanished(organizer, this);
Robert Carr8a2f9132019-11-11 15:03:15 -08004352 }
4353 }
4354
Wale Ogunwale465b1e12020-03-31 12:15:51 -07004355 @VisibleForTesting
Evan Roskyf64f5da2020-03-16 13:47:48 -07004356 boolean setTaskOrganizer(ITaskOrganizer organizer) {
Evan Rosky0037e5f2019-11-05 10:26:24 -08004357 if (mTaskOrganizer == organizer) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07004358 return false;
Evan Rosky0037e5f2019-11-05 10:26:24 -08004359 }
chaviwda7b3c22020-04-24 11:25:08 -07004360
4361 ITaskOrganizer previousOrganizer = mTaskOrganizer;
4362 // Update the new task organizer before calling sendTaskVanished since it could result in
4363 // a new SurfaceControl getting created that would notify the old organizer about it.
Robert Carr8a2f9132019-11-11 15:03:15 -08004364 mTaskOrganizer = organizer;
chaviwda7b3c22020-04-24 11:25:08 -07004365 // Let the old organizer know it has lost control.
4366 sendTaskVanished(previousOrganizer);
Robert Carr8a2f9132019-11-11 15:03:15 -08004367
Wale Ogunwale20ab6d42020-04-13 07:30:59 -07004368 if (mTaskOrganizer != null) {
4369 sendTaskAppeared();
4370 } else {
4371 // No longer managed by any organizer.
4372 mTaskAppearedSent = false;
4373 mLastTaskOrganizerWindowingMode = -1;
4374 setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */);
4375 if (mCreatedByOrganizer) {
4376 removeImmediately();
4377 }
Louis Changa009c762020-02-26 11:21:31 +08004378 }
Wale Ogunwale20ab6d42020-04-13 07:30:59 -07004379
4380 return true;
Winson Chung77338ab2020-03-09 16:32:34 -07004381 }
4382
4383 /**
4384 * Called when the task state changes (ie. from windowing mode change) an the task organizer
4385 * state should also be updated.
4386 *
4387 * @param forceUpdate Updates the task organizer to the one currently specified in the task
4388 * org controller for the task's windowing mode, ignoring the cached
4389 * windowing mode checks.
Evan Roskyf64f5da2020-03-16 13:47:48 -07004390 * @return {@code true} if task organizer changed.
Winson Chung77338ab2020-03-09 16:32:34 -07004391 */
Evan Roskyf64f5da2020-03-16 13:47:48 -07004392 boolean updateTaskOrganizerState(boolean forceUpdate) {
Winson Chung77338ab2020-03-09 16:32:34 -07004393 if (!isRootTask()) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07004394 return false;
Winson Chung77338ab2020-03-09 16:32:34 -07004395 }
4396
4397 final int windowingMode = getWindowingMode();
4398 if (!forceUpdate && windowingMode == mLastTaskOrganizerWindowingMode) {
4399 // If our windowing mode hasn't actually changed, then just stick
4400 // with our old organizer. This lets us implement the semantic
4401 // where SysUI can continue to manage it's old tasks
4402 // while CTS temporarily takes over the registration.
Evan Roskyf64f5da2020-03-16 13:47:48 -07004403 return false;
Winson Chung77338ab2020-03-09 16:32:34 -07004404 }
4405 /*
4406 * Different windowing modes may be managed by different task organizers. If
4407 * getTaskOrganizer returns null, we still call setTaskOrganizer to
4408 * make sure we clear it.
4409 */
4410 final ITaskOrganizer org =
4411 mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
Evan Roskyf64f5da2020-03-16 13:47:48 -07004412 final boolean result = setTaskOrganizer(org);
Winson Chung77338ab2020-03-09 16:32:34 -07004413 mLastTaskOrganizerWindowingMode = windowingMode;
Evan Roskyf64f5da2020-03-16 13:47:48 -07004414 return result;
Robert Carr8a2f9132019-11-11 15:03:15 -08004415 }
4416
4417 @Override
4418 void setSurfaceControl(SurfaceControl sc) {
4419 super.setSurfaceControl(sc);
4420 // If the TaskOrganizer was set before we created the SurfaceControl, we need to
4421 // emit the callbacks now.
4422 sendTaskAppeared();
4423 }
4424
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004425 /**
4426 * @return true if the task is currently focused.
4427 */
4428 private boolean isFocused() {
4429 if (mDisplayContent == null || mDisplayContent.mCurrentFocus == null) {
4430 return false;
4431 }
4432 return mDisplayContent.mCurrentFocus.getTask() == this;
4433 }
4434
4435 /**
Vishnu Nairae3b0772020-03-19 16:55:25 -07004436 * @return true if the task is visible and has at least one visible child.
4437 */
4438 private boolean hasVisibleChildren() {
4439 if (!isAttached() || isForceHidden()) {
4440 return false;
4441 }
4442
4443 return getActivity(ActivityRecord::isVisible) != null;
4444 }
4445
4446 /**
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004447 * @return the desired shadow radius in pixels for the current task.
4448 */
4449 private float getShadowRadius(boolean taskIsFocused) {
Vishnu Nairae3b0772020-03-19 16:55:25 -07004450 int elevation = 0;
4451
4452 // Get elevation for a specific windowing mode.
4453 if (inPinnedWindowingMode()) {
4454 elevation = PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
Garfield Tan7e1cb5c2020-04-10 15:21:23 -07004455 } else if (inFreeformWindowingMode()) {
Vishnu Nairae3b0772020-03-19 16:55:25 -07004456 elevation = taskIsFocused
4457 ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
4458 } else {
4459 // For all other windowing modes, do not draw a shadow.
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004460 return 0;
4461 }
4462
Vishnu Nairae3b0772020-03-19 16:55:25 -07004463 // If the task has no visible children, do not draw a shadow.
4464 if (!hasVisibleChildren()) {
4465 return 0;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004466 }
4467
Vishnu Nairae3b0772020-03-19 16:55:25 -07004468 return dipToPixel(elevation, getDisplayContent().getDisplayMetrics());
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004469 }
4470
4471 /**
4472 * Update the length of the shadow if needed based on windowing mode and task focus state.
4473 */
4474 private void updateShadowsRadius(boolean taskIsFocused,
4475 SurfaceControl.Transaction pendingTransaction) {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08004476 if (!mWmService.mRenderShadowsInCompositor || !isRootTask()) return;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004477
4478 final float newShadowRadius = getShadowRadius(taskIsFocused);
4479 if (mShadowRadius != newShadowRadius) {
4480 mShadowRadius = newShadowRadius;
4481 pendingTransaction.setShadowRadius(getSurfaceControl(), mShadowRadius);
4482 }
4483 }
4484
4485 /**
4486 * Called on the task of a window which gained or lost focus.
4487 * @param hasFocus
4488 */
4489 void onWindowFocusChanged(boolean hasFocus) {
4490 updateShadowsRadius(hasFocus, getPendingTransaction());
4491 }
Robert Carrf6690d12020-02-04 14:16:21 -08004492
Jorim Jaggi785edb42020-05-08 12:34:47 +00004493 void setPictureInPictureParams(PictureInPictureParams p) {
4494 mPictureInPictureParams.copyOnlySet(p);
Winson Chung1df39e22020-04-09 14:30:55 -07004495 if (isOrganized()) {
4496 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
4497 }
Robert Carrf6690d12020-02-04 14:16:21 -08004498 }
Robert Carr711e7052020-02-19 11:14:33 -08004499
4500 /**
4501 * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this
4502 * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy
4503 * to resize, and it will defer the transaction until that resize frame completes.
4504 */
4505 void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t) {
4506 mMainWindowSizeChangeTransaction = t;
4507 }
4508
4509 SurfaceControl.Transaction getMainWindowSizeChangeTransaction() {
4510 return mMainWindowSizeChangeTransaction;
4511 }
Vishnu Nairdddc9f52020-03-09 09:37:27 -07004512
Robert Carr2bed6212020-02-20 16:55:07 -08004513 void setActivityWindowingMode(int windowingMode) {
4514 PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setWindowingMode,
chaviw6630d852020-04-15 19:06:56 -07004515 PooledLambda.__(ActivityRecord.class), windowingMode);
Robert Carr2bed6212020-02-20 16:55:07 -08004516 forAllActivities(c);
4517 c.recycle();
4518 }
4519
Robert Carrf6878a42019-12-18 02:13:12 -08004520 /**
4521 * Sets/unsets the forced-hidden state flag for this task depending on {@param set}.
4522 * @return Whether the force hidden state changed
4523 */
4524 boolean setForceHidden(int flags, boolean set) {
4525 int newFlags = mForceHiddenFlags;
4526 if (set) {
4527 newFlags |= flags;
4528 } else {
4529 newFlags &= ~flags;
4530 }
4531 if (mForceHiddenFlags == newFlags) {
4532 return false;
4533 }
Winson Chungb5ce37c2020-04-22 10:08:28 -07004534 final boolean wasHidden = isForceHidden();
Robert Carrf6878a42019-12-18 02:13:12 -08004535 mForceHiddenFlags = newFlags;
Winson Chungb5ce37c2020-04-22 10:08:28 -07004536 if (wasHidden && isFocusableAndVisible()) {
4537 // The change in force-hidden state will change visibility without triggering a stack
4538 // order change, so we should reset the preferred top focusable stack to ensure it's not
4539 // used if a new activity is started from this task.
4540 getDisplayArea().resetPreferredTopFocusableStackIfBelow(this);
4541 }
Robert Carrf6878a42019-12-18 02:13:12 -08004542 return true;
4543 }
4544
4545 /**
4546 * Returns whether this task is currently forced to be hidden for any reason.
4547 */
4548 protected boolean isForceHidden() {
4549 return mForceHiddenFlags != 0;
4550 }
4551
Vishnu Nairdddc9f52020-03-09 09:37:27 -07004552 @Override
4553 long getProtoFieldId() {
4554 return TASK;
4555 }
Robert Carr2bed6212020-02-20 16:55:07 -08004556
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08004557}