blob: d06e87511f77ec37b91e1cacf616244b8f12b031 [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;
110import android.app.TaskInfo;
111import android.app.WindowConfiguration;
112import android.content.ComponentName;
113import android.content.Intent;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800114import android.content.pm.ActivityInfo;
Louis Changcdec0802019-11-11 11:45:07 +0800115import android.content.pm.ApplicationInfo;
116import android.content.pm.IPackageManager;
117import android.content.pm.PackageManager;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700118import android.content.res.Configuration;
Louis Chang2570e332020-04-10 11:58:49 +0800119import android.graphics.Point;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700120import android.graphics.Rect;
Louis Changcdec0802019-11-11 11:45:07 +0800121import android.os.Debug;
Garfield Tan90b04282018-12-11 14:04:42 -0800122import android.os.IBinder;
Louis Changcdec0802019-11-11 11:45:07 +0800123import android.os.RemoteException;
124import android.os.SystemClock;
125import android.os.Trace;
126import android.os.UserHandle;
127import android.provider.Settings;
128import android.service.voice.IVoiceInteractionSession;
Evan Rosky55bddd82020-01-29 13:07:18 -0800129import android.util.ArraySet;
Louis Changcdec0802019-11-11 11:45:07 +0800130import android.util.DisplayMetrics;
Craig Mautner42bf39e2014-02-21 16:46:22 -0800131import android.util.Slog;
Evan Rosky55bddd82020-01-29 13:07:18 -0800132import android.util.proto.ProtoOutputStream;
Louis Changcdec0802019-11-11 11:45:07 +0800133import android.view.DisplayInfo;
Evan Rosky55bddd82020-01-29 13:07:18 -0800134import android.view.RemoteAnimationAdapter;
lumark19a5d2e2019-10-11 16:19:30 +0800135import android.view.RemoteAnimationTarget;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700136import android.view.Surface;
Winson Chungd41f71d2018-03-16 15:26:07 -0700137import android.view.SurfaceControl;
lumark04bceb92020-03-07 00:03:33 +0800138import android.view.WindowManager;
Garfield Tana7c9f7c2020-03-13 15:56:51 -0700139import android.window.ITaskOrganizer;
chaviw8c9d1f52018-07-25 14:56:07 -0700140
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800141import com.android.internal.annotations.VisibleForTesting;
Louis Changcdec0802019-11-11 11:45:07 +0800142import com.android.internal.app.IVoiceInteractor;
Louis Changcdec0802019-11-11 11:45:07 +0800143import com.android.internal.util.XmlUtils;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800144import com.android.internal.util.function.pooled.PooledConsumer;
145import com.android.internal.util.function.pooled.PooledFunction;
146import com.android.internal.util.function.pooled.PooledLambda;
147import com.android.internal.util.function.pooled.PooledPredicate;
Louis Changcdec0802019-11-11 11:45:07 +0800148import com.android.server.protolog.common.ProtoLog;
149import com.android.server.wm.ActivityStack.ActivityState;
Craig Mautner2c2549c2013-11-12 08:31:15 -0800150
Louis Changcdec0802019-11-11 11:45:07 +0800151import org.xmlpull.v1.XmlPullParser;
152import org.xmlpull.v1.XmlPullParserException;
153import org.xmlpull.v1.XmlSerializer;
154
155import java.io.IOException;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700156import java.io.PrintWriter;
Louis Changcdec0802019-11-11 11:45:07 +0800157import java.lang.annotation.Retention;
158import java.lang.annotation.RetentionPolicy;
159import java.util.ArrayList;
160import java.util.Objects;
Jorim Jaggi51304d72017-05-17 17:25:32 +0200161import java.util.function.Consumer;
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900162import java.util.function.Function;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800163import java.util.function.Predicate;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700164
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800165class Task extends WindowContainer<WindowContainer> {
Louis Changcdec0802019-11-11 11:45:07 +0800166 private static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_ATM;
167 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
168 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
169 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
170 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
171
172 private static final String ATTR_TASKID = "task_id";
173 private static final String TAG_INTENT = "intent";
174 private static final String TAG_AFFINITYINTENT = "affinity_intent";
175 private static final String ATTR_REALACTIVITY = "real_activity";
176 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
177 private static final String ATTR_ORIGACTIVITY = "orig_activity";
178 private static final String TAG_ACTIVITY = "activity";
179 private static final String ATTR_AFFINITY = "affinity";
180 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
181 private static final String ATTR_ROOTHASRESET = "root_has_reset";
182 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
183 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
184 private static final String ATTR_USERID = "user_id";
185 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
186 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
187 @Deprecated
188 private static final String ATTR_TASKTYPE = "task_type";
189 private static final String ATTR_LASTDESCRIPTION = "last_description";
190 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
191 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
192 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
193 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
194 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
195 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
196 private static final String ATTR_CALLING_UID = "calling_uid";
197 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Philip P. Moltmannee295092020-02-10 08:46:26 -0800198 private static final String ATTR_CALLING_FEATURE_ID = "calling_feature_id";
Louis Changcdec0802019-11-11 11:45:07 +0800199 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
200 private static final String ATTR_RESIZE_MODE = "resize_mode";
201 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
202 private static final String ATTR_MIN_WIDTH = "min_width";
203 private static final String ATTR_MIN_HEIGHT = "min_height";
204 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Garfield Tan5901e7c2020-02-07 17:12:22 -0800205 private static final String ATTR_WINDOW_LAYOUT_AFFINITY = "window_layout_affinity";
Louis Changcdec0802019-11-11 11:45:07 +0800206
207 // Current version of the task record we persist. Used to check if we need to run any upgrade
208 // code.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800209 static final int PERSIST_TASK_VERSION = 1;
Louis Changcdec0802019-11-11 11:45:07 +0800210
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800211 static final int INVALID_MIN_SIZE = -1;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -0800212 private float mShadowRadius = 0;
Louis Changcdec0802019-11-11 11:45:07 +0800213
214 /**
215 * The modes to control how the stack is moved to the front when calling {@link Task#reparent}.
216 */
217 @Retention(RetentionPolicy.SOURCE)
218 @IntDef({
219 REPARENT_MOVE_STACK_TO_FRONT,
220 REPARENT_KEEP_STACK_AT_FRONT,
221 REPARENT_LEAVE_STACK_IN_PLACE
222 })
223 @interface ReparentMoveStackMode {}
224 // Moves the stack to the front if it was not at the front
225 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
226 // Only moves the stack to the front if it was focused or front most already
227 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
228 // Do not move the stack as a part of reparenting
229 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
230
Louis Changcdec0802019-11-11 11:45:07 +0800231 String affinity; // The affinity name for this task, or null; may change identity.
232 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Garfield Tan5901e7c2020-02-07 17:12:22 -0800233 String mWindowLayoutAffinity; // Launch param affinity of this task or null. Used when saving
234 // launch params of this task.
Wale Ogunwale0d465192020-01-23 19:14:44 -0800235 IVoiceInteractionSession voiceSession; // Voice interaction session driving task
236 IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Louis Changcdec0802019-11-11 11:45:07 +0800237 Intent intent; // The original intent that started the task. Note that this value can
238 // be null.
239 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
240 int effectiveUid; // The current effective uid of the identity of this task.
241 ComponentName origActivity; // The non-alias activity component of the intent.
242 ComponentName realActivity; // The actual activity component that started the task.
243 boolean realActivitySuspended; // True if the actual activity component that started the
244 // task is suspended.
245 boolean inRecents; // Actually in the recents list?
246 long lastActiveTime; // Last time this task was active in the current device session,
247 // including sleep. This time is initialized to the elapsed time when
248 // restored from disk.
249 boolean isAvailable; // Is the activity available to be launched?
250 boolean rootWasReset; // True if the intent at the root of the task had
251 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
252 boolean autoRemoveRecents; // If true, we should automatically remove the task from
253 // recents when activity finishes
254 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Robert Carrde96c8a2020-03-24 15:22:21 -0700255 private boolean mHasBeenVisible; // Set if any activities in the task have been visible
Louis Changcdec0802019-11-11 11:45:07 +0800256
257 String stringName; // caching of toString() result.
258 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
259 // was changed.
260
Louis Changcdec0802019-11-11 11:45:07 +0800261 /** Can't be put in lockTask mode. */
262 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
263 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
264 final static int LOCK_TASK_AUTH_PINNABLE = 1;
265 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
266 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
267 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
268 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
269 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
270 * lockTask task. */
271 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
272 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
273
274 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
275
Louis Changcdec0802019-11-11 11:45:07 +0800276 /** The process that had previously hosted the root activity of this task.
277 * Used to know that we should try harder to keep this process around, in case the
278 * user wants to return to it. */
279 private WindowProcessController mRootProcess;
280
281 /** Takes on same value as first root activity */
282 boolean isPersistable = false;
283 int maxRecents;
284
285 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
286 * determining the order when restoring. Sign indicates whether last task movement was to front
287 * (positive) or back (negative). Absolute value indicates time. */
288 long mLastTimeMoved;
289
290 /** If original intent did not allow relinquishing task identity, save that information */
291 private boolean mNeverRelinquishIdentity = true;
292
293 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
294 // do not want to delete the stack when the task goes empty.
295 private boolean mReuseTask = false;
296
297 CharSequence lastDescription; // Last description captured for this item.
298
299 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
300 int mAffiliatedTaskColor; // color of the parent task affiliation.
301 Task mPrevAffiliate; // previous task in affiliated chain.
302 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
303 Task mNextAffiliate; // next task in affiliated chain.
304 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
305
306 // For relaunching the task from recents as though it was launched by the original launcher.
307 int mCallingUid;
308 String mCallingPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800309 String mCallingFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +0800310
311 private final Rect mTmpStableBounds = new Rect();
312 private final Rect mTmpNonDecorBounds = new Rect();
313 private final Rect mTmpBounds = new Rect();
314 private final Rect mTmpInsets = new Rect();
Evan Rosky70213702019-11-05 10:26:24 -0800315 private final Rect mTmpFullBounds = new Rect();
Louis Changcdec0802019-11-11 11:45:07 +0800316
317 // Last non-fullscreen bounds the task was launched in or resized to.
318 // The information is persisted and used to determine the appropriate stack to launch the
319 // task into on restore.
320 Rect mLastNonFullscreenBounds = null;
321 // Minimal width and height of this task when it's resizeable. -1 means it should use the
322 // default minimal width/height.
323 int mMinWidth;
324 int mMinHeight;
325
326 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
327 // This number will be assigned when we evaluate OOM scores for all visible tasks.
328 int mLayerRank = -1;
329
330 /** Helper object used for updating override configuration. */
331 private Configuration mTmpConfig = new Configuration();
332
333 /** Used by fillTaskInfo */
334 final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700335
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200336 final ActivityTaskManagerService mAtmService;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800337 final ActivityStackSupervisor mStackSupervisor;
338 final RootWindowContainer mRootWindowContainer;
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200339
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700340 /* Unique identifier for this task. */
Craig Mautner83162a92015-01-26 14:43:30 -0800341 final int mTaskId;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700342 /* User for which this task was created. */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200343 // TODO: Make final
344 int mUserId;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800345
Jorim Jaggi0429f352015-12-22 16:29:16 +0100346 final Rect mPreparedFrozenBounds = new Rect();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700347 final Configuration mPreparedFrozenMergedConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700348
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800349 // Id of the previous display the stack was on.
350 int mPrevDisplayId = INVALID_DISPLAY;
351
Garfield Tandec96db2018-10-30 11:28:49 -0700352 /** ID of the display which rotation {@link #mRotation} has. */
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800353 private int mLastRotationDisplayId = INVALID_DISPLAY;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800354
Garfield Tandec96db2018-10-30 11:28:49 -0700355 /**
356 * Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
357 * moved to a new display.
358 */
Vadim Caenfc14c662020-01-20 16:00:31 +0100359 @Surface.Rotation
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700360 private int mRotation;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700361
Garfield Tanafa0de82020-03-03 16:07:07 -0800362 /**
363 * Last requested orientation reported to DisplayContent. This is different from {@link
364 * #mOrientation} in the sense that this takes activities' requested orientation into
365 * account. Start with {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} so that we don't need
366 * to notify for activities that don't specify any orientation.
367 */
368 int mLastReportedRequestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
369
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700370 // For comparison with DisplayContent bounds.
371 private Rect mTmpRect = new Rect();
372 // For handling display rotations.
373 private Rect mTmpRect2 = new Rect();
374
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800375 // Resize mode of the task. See {@link ActivityInfo#resizeMode}
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200376 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
377 int mResizeMode;
Chong Zhangb15758a2015-11-17 12:12:03 -0800378
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200379 // Whether or not this task and its activities support PiP. Based on the
380 // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity.
381 boolean mSupportsPictureInPicture;
Winson Chungd3395382016-12-13 11:49:09 -0800382
Chong Zhang3005e752015-09-18 18:46:28 -0700383 // Whether the task is currently being drag-resized
384 private boolean mDragResizing;
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +0100385 private int mDragResizeMode;
Chong Zhang3005e752015-09-18 18:46:28 -0700386
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700387 // This represents the last resolved activity values for this task
388 // NOTE: This value needs to be persisted with each task
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100389 private TaskDescription mTaskDescription;
390
Robert Carr18f622f2017-05-08 11:20:43 -0700391 // If set to true, the task will report that it is not in the floating
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700392 // state regardless of it's stack affiliation. As the floating state drives
Robert Carr18f622f2017-05-08 11:20:43 -0700393 // production of content insets this can be used to preserve them across
394 // stack moves and we in fact do so when moving from full screen to pinned.
395 private boolean mPreserveNonFloatingState = false;
396
Robert Carrf59b8dd2017-10-02 18:58:36 -0700397 private Dimmer mDimmer = new Dimmer(this);
398 private final Rect mTmpDimBoundsRect = new Rect();
Louis Chang2570e332020-04-10 11:58:49 +0800399 private final Point mLastSurfaceSize = new Point();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700400
Jorim Jaggi50bf59c2018-03-09 17:29:48 +0100401 /** @see #setCanAffectSystemUiFlags */
402 private boolean mCanAffectSystemUiFlags = true;
403
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800404 private static Exception sTmpException;
405
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800406 /** ActivityRecords that are exiting, but still on screen for animations. */
407 final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
408
409 /**
410 * When we are in the process of pausing an activity, before starting the
411 * next one, this variable holds the activity that is currently being paused.
412 */
413 ActivityRecord mPausingActivity = null;
414
415 /**
416 * This is the last activity that we put into the paused state. This is
417 * used to determine if we need to do an activity transition while sleeping,
418 * when we normally hold the top activity paused.
419 */
420 ActivityRecord mLastPausedActivity = null;
421
422 /**
423 * Activities that specify No History must be removed once the user navigates away from them.
424 * If the device goes to sleep with such an activity in the paused state then we save it here
425 * and finish it later if another activity replaces it on wakeup.
426 */
427 ActivityRecord mLastNoHistoryActivity = null;
428
429 /** Current activity that is resumed, or null if there is none. */
430 ActivityRecord mResumedActivity = null;
431
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -0800432 private boolean mForceShowForAllUsers;
433
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800434 /** When set, will force the task to report as invisible. */
Robert Carrf6878a42019-12-18 02:13:12 -0800435 static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1;
436 static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1;
437 private int mForceHiddenFlags = 0;
438
Robert Carr711e7052020-02-19 11:14:33 -0800439 SurfaceControl.Transaction mMainWindowSizeChangeTransaction;
440
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800441 private final FindRootHelper mFindRootHelper = new FindRootHelper();
442 private class FindRootHelper {
443 private ActivityRecord mRoot;
444
445 private void clear() {
446 mRoot = null;
447 }
448
449 ActivityRecord findRoot(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
450 final PooledFunction f = PooledLambda.obtainFunction(FindRootHelper::processActivity,
451 this, PooledLambda.__(ActivityRecord.class), ignoreRelinquishIdentity,
452 setToBottomIfNone);
453 clear();
454 forAllActivities(f, false /*traverseTopToBottom*/);
455 f.recycle();
456 return mRoot;
457 }
458
459 private boolean processActivity(ActivityRecord r,
460 boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
461 if (mRoot == null && setToBottomIfNone) {
462 // This is the first activity we are process. Set it as the candidate root in case
463 // we don't find a better one.
464 mRoot = r;
465 }
466
467 if (r.finishing) return false;
468
469 // Set this as the candidate root since it isn't finishing.
470 mRoot = r;
471
472 // Only end search if we are ignore relinquishing identity or we are not relinquishing.
473 return ignoreRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
474 }
475 }
476
Louis Changcdec0802019-11-11 11:45:07 +0800477 /**
Robert Carr8a2f9132019-11-11 15:03:15 -0800478 * The TaskOrganizer which is delegated presentation of this task. If set the Task will
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700479 * emit an WindowContainerToken (allowing access to it's SurfaceControl leash) to the organizers
Robert Carr8a2f9132019-11-11 15:03:15 -0800480 * taskAppeared callback, and emit a taskRemoved callback when the Task is vanished.
481 */
482 ITaskOrganizer mTaskOrganizer;
Winson Chung77338ab2020-03-09 16:32:34 -0700483 private int mLastTaskOrganizerWindowingMode = -1;
Robert Carrde96c8a2020-03-24 15:22:21 -0700484 /**
485 * Prevent duplicate calls to onTaskAppeared.
486 */
487 boolean mTaskAppearedSent;
Robert Carr8a2f9132019-11-11 15:03:15 -0800488
Robert Carrf6690d12020-02-04 14:16:21 -0800489 /**
Louis Changa009c762020-02-26 11:21:31 +0800490 * This task was created by the task organizer which has the following implementations.
491 * <ul>
492 * <lis>The task won't be removed when it is empty. Removal has to be an explicit request
493 * from the task organizer.</li>
494 * <li>Unlike other non-root tasks, it's direct children are visible to the task
495 * organizer for ordering purposes.</li>
496 * </ul>
497 */
498 boolean mCreatedByOrganizer;
499
500 /**
Louis Changcdec0802019-11-11 11:45:07 +0800501 * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
502 * ActivityInfo, Intent, TaskDescription)} instead.
503 */
504 Task(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info, Intent _intent,
505 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
506 TaskDescription _taskDescription, ActivityStack stack) {
507 this(atmService, _taskId, _intent, null /*_affinityIntent*/, null /*_affinity*/,
508 null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
509 false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
510 UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
511 null /*_lastDescription*/, System.currentTimeMillis(),
512 true /*neverRelinquishIdentity*/,
513 _taskDescription != null ? _taskDescription : new TaskDescription(),
514 _taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
Philip P. Moltmannee295092020-02-10 08:46:26 -0800515 info.applicationInfo.uid, info.packageName, null /* default featureId */,
516 info.resizeMode, info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
Louis Changcdec0802019-11-11 11:45:07 +0800517 false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
518 _voiceSession, _voiceInteractor, stack);
519 }
520
521 /** Don't use constructor directly. This is only used by XML parser. */
Philip P. Moltmannee295092020-02-10 08:46:26 -0800522 Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent, Intent _affinityIntent,
523 String _affinity, String _rootAffinity, ComponentName _realActivity,
524 ComponentName _origActivity, boolean _rootWasReset, boolean _autoRemoveRecents,
525 boolean _askedCompatMode, int _userId, int _effectiveUid, String _lastDescription,
Louis Changcdec0802019-11-11 11:45:07 +0800526 long lastTimeMoved, boolean neverRelinquishIdentity,
527 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
528 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Philip P. Moltmannee295092020-02-10 08:46:26 -0800529 @Nullable String callingFeatureId, int resizeMode, boolean supportsPictureInPicture,
530 boolean _realActivitySuspended, boolean userSetupComplete, int minWidth, int minHeight,
531 ActivityInfo info, IVoiceInteractionSession _voiceSession,
532 IVoiceInteractor _voiceInteractor, ActivityStack stack) {
Louis Changcdec0802019-11-11 11:45:07 +0800533 super(atmService.mWindowManager);
534
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -0800535 EventLogTags.writeWmTaskCreated(_taskId, stack != null ? getRootTaskId() : INVALID_TASK_ID);
Louis Changcdec0802019-11-11 11:45:07 +0800536 mAtmService = atmService;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800537 mStackSupervisor = atmService.mStackSupervisor;
538 mRootWindowContainer = mAtmService.mRootWindowContainer;
Louis Changcdec0802019-11-11 11:45:07 +0800539 mTaskId = _taskId;
540 mUserId = _userId;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800541 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800542 mSupportsPictureInPicture = supportsPictureInPicture;
Louis Changcdec0802019-11-11 11:45:07 +0800543 mTaskDescription = _lastTaskDescription;
Riddle Hsu6b76cd32019-10-08 00:37:19 +0800544 // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
545 setOrientation(SCREEN_ORIENTATION_UNSET);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700546 mRemoteToken = new RemoteToken(this);
Louis Changcdec0802019-11-11 11:45:07 +0800547 affinityIntent = _affinityIntent;
548 affinity = _affinity;
549 rootAffinity = _rootAffinity;
550 voiceSession = _voiceSession;
551 voiceInteractor = _voiceInteractor;
552 realActivity = _realActivity;
553 realActivitySuspended = _realActivitySuspended;
554 origActivity = _origActivity;
555 rootWasReset = _rootWasReset;
556 isAvailable = true;
557 autoRemoveRecents = _autoRemoveRecents;
558 askedCompatMode = _askedCompatMode;
559 mUserSetupComplete = userSetupComplete;
560 effectiveUid = _effectiveUid;
561 touchActiveTime();
562 lastDescription = _lastDescription;
563 mLastTimeMoved = lastTimeMoved;
564 mNeverRelinquishIdentity = neverRelinquishIdentity;
565 mAffiliatedTaskId = taskAffiliation;
566 mAffiliatedTaskColor = taskAffiliationColor;
567 mPrevAffiliateTaskId = prevTaskId;
568 mNextAffiliateTaskId = nextTaskId;
569 mCallingUid = callingUid;
570 mCallingPackage = callingPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800571 mCallingFeatureId = callingFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +0800572 mResizeMode = resizeMode;
573 if (info != null) {
574 setIntent(_intent, info);
575 setMinDimensions(info);
576 } else {
577 intent = _intent;
578 mMinWidth = minWidth;
579 mMinHeight = minHeight;
580 }
581 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
582 }
583
Wale Ogunwale0d465192020-01-23 19:14:44 -0800584 Task reuseAsLeafTask(IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
Louis Changfbcf55f2020-03-02 12:27:15 +0800585 Intent intent, ActivityInfo info, ActivityRecord activity) {
Wale Ogunwale0d465192020-01-23 19:14:44 -0800586 voiceSession = _voiceSession;
587 voiceInteractor = _voiceInteractor;
Louis Changfbcf55f2020-03-02 12:27:15 +0800588 setIntent(activity, intent, info);
Wale Ogunwale0d465192020-01-23 19:14:44 -0800589 setMinDimensions(info);
Garfield Tana7c9f7c2020-03-13 15:56:51 -0700590 // Before we began to reuse a root task (old ActivityStack) as the leaf task, we used to
591 // create a leaf task in this case. Therefore now we won't send out the task created
592 // notification when we decide to reuse it here, so we send out the notification below.
593 // The reason why the created notification sent out when root task is created doesn't work
594 // is that realActivity isn't set until setIntent() method above is called for the first
595 // time. Eventually this notification will be removed when we can populate those information
596 // when root task is created.
597 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(mTaskId, realActivity);
Wale Ogunwale0d465192020-01-23 19:14:44 -0800598 return this;
599 }
600
Garfield Tan8b096b22020-01-07 14:55:20 -0800601 private void cleanUpResourcesForDestroy(ConfigurationContainer oldParent) {
Louis Changcdec0802019-11-11 11:45:07 +0800602 if (hasChild()) {
603 return;
604 }
605
Garfield Tan59a60fa2020-03-24 10:32:29 -0700606 if (isLeafTask()) {
Garfield Tan8b096b22020-01-07 14:55:20 -0800607 // This task is going away, so save the last state if necessary.
608 saveLaunchingStateIfNeeded(((WindowContainer) oldParent).getDisplayContent());
609 }
Louis Changcdec0802019-11-11 11:45:07 +0800610
611 // TODO: VI what about activity?
612 final boolean isVoiceSession = voiceSession != null;
613 if (isVoiceSession) {
614 try {
615 voiceSession.taskFinished(intent, mTaskId);
616 } catch (RemoteException e) {
617 }
618 }
619 if (autoRemoveFromRecents() || isVoiceSession) {
620 // Task creator asked to remove this when done, or this task was a voice
621 // interaction, so it should not remain on the recent tasks list.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800622 mStackSupervisor.mRecentTasks.remove(this);
Louis Changcdec0802019-11-11 11:45:07 +0800623 }
624
625 removeIfPossible();
626 }
627
628 @VisibleForTesting
629 @Override
630 void removeIfPossible() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800631 final boolean isRootTask = isRootTask();
632 if (!isRootTask) {
633 mAtmService.getLockTaskController().clearLockedTask(this);
634 }
Louis Changcdec0802019-11-11 11:45:07 +0800635 if (shouldDeferRemoval()) {
636 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId);
637 return;
638 }
639 removeImmediately();
Yuncheol Heo1c211c22020-04-20 13:08:43 -0700640 if (isLeafTask()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800641 mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
642 }
Louis Changcdec0802019-11-11 11:45:07 +0800643 }
644
645 void setResizeMode(int resizeMode) {
646 if (mResizeMode == resizeMode) {
647 return;
648 }
649 mResizeMode = resizeMode;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800650 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
651 mRootWindowContainer.resumeFocusedStacksTopActivities();
Louis Changcdec0802019-11-11 11:45:07 +0800652 updateTaskDescription();
653 }
654
Evan Rosky18e00a72020-05-08 09:36:27 -0700655 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow) {
Louis Changcdec0802019-11-11 11:45:07 +0800656 mAtmService.deferWindowLayout();
657
658 try {
659 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
660
661 if (getParent() == null) {
662 // Task doesn't exist in window manager yet (e.g. was restored from recents).
663 // All we can do for now is update the bounds so it can be used when the task is
664 // added to window manager.
665 setBounds(bounds);
666 if (!inFreeformWindowingMode()) {
667 // re-restore the task so it can have the proper stack association.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800668 mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
Louis Changcdec0802019-11-11 11:45:07 +0800669 }
670 return true;
671 }
672
673 if (!canResizeToBounds(bounds)) {
674 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
675 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
676 }
677
678 // Do not move the task to another stack here.
679 // This method assumes that the task is already placed in the right stack.
680 // we do not mess with that decision and we only do the resize!
681
682 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeTask_" + mTaskId);
683
684 boolean updatedConfig = false;
685 mTmpConfig.setTo(getResolvedOverrideConfiguration());
686 if (setBounds(bounds) != BOUNDS_CHANGE_NONE) {
687 updatedConfig = !mTmpConfig.equals(getResolvedOverrideConfiguration());
688 }
689 // This variable holds information whether the configuration didn't change in a
690 // significant way and the activity was kept the way it was. If it's false, it means
691 // the activity had to be relaunched due to configuration change.
692 boolean kept = true;
693 if (updatedConfig) {
694 final ActivityRecord r = topRunningActivityLocked();
Evan Rosky18e00a72020-05-08 09:36:27 -0700695 if (r != null) {
Louis Changcdec0802019-11-11 11:45:07 +0800696 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
697 preserveWindow);
698 // Preserve other windows for resizing because if resizing happens when there
699 // is a dialog activity in the front, the activity that still shows some
700 // content to the user will become black and cause flickers. Note in most cases
701 // this won't cause tons of irrelevant windows being preserved because only
702 // activities in this task may experience a bounds change. Configs for other
703 // activities stay the same.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800704 mRootWindowContainer.ensureActivitiesVisible(r, 0, preserveWindow);
Louis Changcdec0802019-11-11 11:45:07 +0800705 if (!kept) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800706 mRootWindowContainer.resumeFocusedStacksTopActivities();
Louis Changcdec0802019-11-11 11:45:07 +0800707 }
708 }
709 }
710 resize(kept, forced);
711
712 saveLaunchingStateIfNeeded();
713
714 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
715 return kept;
716 } finally {
717 mAtmService.continueWindowLayout();
718 }
719 }
720
721 /** Convenience method to reparent a task to the top or bottom position of the stack. */
722 boolean reparent(ActivityStack preferredStack, boolean toTop,
723 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
724 String reason) {
725 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
726 true /* schedulePictureInPictureModeChange */, reason);
727 }
728
729 /**
730 * Convenience method to reparent a task to the top or bottom position of the stack, with
731 * an option to skip scheduling the picture-in-picture mode change.
732 */
733 boolean reparent(ActivityStack preferredStack, boolean toTop,
734 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
735 boolean schedulePictureInPictureModeChange, String reason) {
736 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
737 deferResume, schedulePictureInPictureModeChange, reason);
738 }
739
740 /** Convenience method to reparent a task to a specific position of the stack. */
741 boolean reparent(ActivityStack preferredStack, int position,
742 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
743 String reason) {
744 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
745 true /* schedulePictureInPictureModeChange */, reason);
746 }
747
748 /**
749 * Reparents the task into a preferred stack, creating it if necessary.
750 *
751 * @param preferredStack the target stack to move this task
752 * @param position the position to place this task in the new stack
753 * @param animate whether or not we should wait for the new window created as a part of the
754 * reparenting to be drawn and animated in
755 * @param moveStackMode whether or not to move the stack to the front always, only if it was
756 * previously focused & in front, or never
757 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
758 * have changed as a result of this reparenting
759 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
760 * change. Callers may set this to false if they are explicitly scheduling PiP mode
761 * changes themselves, like during the PiP animation
762 * @param reason the caller of this reparenting
763 * @return whether the task was reparented
764 */
765 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
766 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
767 boolean reparent(ActivityStack preferredStack, int position,
768 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
769 boolean schedulePictureInPictureModeChange, String reason) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800770 final ActivityStackSupervisor supervisor = mStackSupervisor;
771 final RootWindowContainer root = mRootWindowContainer;
Louis Changcdec0802019-11-11 11:45:07 +0800772 final WindowManagerService windowManager = mAtmService.mWindowManager;
773 final ActivityStack sourceStack = getStack();
774 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
775 position == MAX_VALUE);
776 if (toStack == sourceStack) {
777 return false;
778 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800779 if (!canBeLaunchedOnDisplay(toStack.getDisplayId())) {
Louis Changcdec0802019-11-11 11:45:07 +0800780 return false;
781 }
782
783 final boolean toTopOfStack = position == MAX_VALUE;
784 if (toTopOfStack && toStack.getResumedActivity() != null
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900785 && toStack.topRunningActivity() != null) {
Louis Changcdec0802019-11-11 11:45:07 +0800786 // Pause the resumed activity on the target stack while re-parenting task on top of it.
787 toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
788 null /* resuming */);
789 }
790
791 final int toStackWindowingMode = toStack.getWindowingMode();
Wale Ogunwale21e06482019-11-18 05:14:15 -0800792 final ActivityRecord topActivity = getTopNonFinishingActivity();
Louis Changcdec0802019-11-11 11:45:07 +0800793
794 final boolean mightReplaceWindow = topActivity != null
795 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
796 if (mightReplaceWindow) {
797 // We are about to relaunch the activity because its configuration changed due to
798 // being maximized, i.e. size change. The activity will first remove the old window
799 // and then add a new one. This call will tell window manager about this, so it can
800 // preserve the old window until the new one is drawn. This prevents having a gap
801 // between the removal and addition, in which no window is visible. We also want the
802 // entrance of the new window to be properly animated.
803 // Note here we always set the replacing window first, as the flags might be needed
804 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
805 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
806 }
807
808 mAtmService.deferWindowLayout();
809 boolean kept = true;
810 try {
811 final ActivityRecord r = topRunningActivityLocked();
Louis Changcdec0802019-11-11 11:45:07 +0800812 final boolean wasFocused = r != null && root.isTopDisplayFocusedStack(sourceStack)
813 && (topRunningActivityLocked() == r);
814 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
815 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
816
817 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
818 // Whenever we are moving the top activity from the front stack we want to make sure to
819 // move the stack to the front.
Andrii Kulian86d676c2020-03-27 19:34:54 -0700820 final boolean wasFront = r != null && sourceStack.isTopStackInDisplayArea()
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900821 && (sourceStack.topRunningActivity() == r);
Louis Changcdec0802019-11-11 11:45:07 +0800822
823 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
824 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
825
826 reparent(toStack, position, moveStackToFront, reason);
827
828 if (schedulePictureInPictureModeChange) {
829 // Notify of picture-in-picture mode changes
830 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
831 }
832
833 // If the task had focus before (or we're requested to move focus), move focus to the
834 // new stack by moving the stack to the front.
835 if (r != null) {
836 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
837 wasPaused, reason);
838 }
839 if (!animate) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800840 mStackSupervisor.mNoAnimActivities.add(topActivity);
Louis Changcdec0802019-11-11 11:45:07 +0800841 }
842
843 // We might trigger a configuration change. Save the current task bounds for freezing.
844 // TODO: Should this call be moved inside the resize method in WM?
845 toStack.prepareFreezingTaskBounds();
846
Evan Rosky18e00a72020-05-08 09:36:27 -0700847 if (toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
848 && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
849 // Move recents to front so it is not behind home stack when going into docked
850 // mode
851 mStackSupervisor.moveRecentsStackToFront(reason);
Louis Changcdec0802019-11-11 11:45:07 +0800852 }
853 } finally {
854 mAtmService.continueWindowLayout();
855 }
856
857 if (mightReplaceWindow) {
858 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
859 // window), we need to clear the replace window settings. Otherwise, we schedule a
860 // timeout to remove the old window if the replacing window is not coming in time.
861 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
862 }
863
864 if (!deferResume) {
865 // The task might have already been running and its visibility needs to be synchronized
866 // with the visibility of the stack / windows.
867 root.ensureActivitiesVisible(null, 0, !mightReplaceWindow);
868 root.resumeFocusedStacksTopActivities();
869 }
870
871 // TODO: Handle incorrect request to move before the actual move, not after.
872 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Andrii Kulian1cb59dd2020-04-10 12:17:17 -0700873 mRootWindowContainer.getDefaultTaskDisplayArea(), toStack);
Louis Changcdec0802019-11-11 11:45:07 +0800874
875 return (preferredStack == toStack);
876 }
877
878 /**
879 * @return {@code true} if the windows of tasks being moved to the target stack from the
880 * source stack should be replaced, meaning that window manager will keep the old window
881 * around until the new is ready.
882 */
883 private static boolean replaceWindowsOnTaskMove(
884 int sourceWindowingMode, int targetWindowingMode) {
885 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
886 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
887 }
888
889 /**
890 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
891 */
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800892 TaskSnapshot getSnapshot(boolean isLowResolution, boolean restoreFromDisk) {
Louis Changcdec0802019-11-11 11:45:07 +0800893
894 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
895 // synchronized between AM and WM.
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800896 return mAtmService.mWindowManager.getTaskSnapshot(mTaskId, mUserId, isLowResolution,
Louis Changcdec0802019-11-11 11:45:07 +0800897 restoreFromDisk);
898 }
899
900 void touchActiveTime() {
901 lastActiveTime = SystemClock.elapsedRealtime();
902 }
903
904 long getInactiveDuration() {
905 return SystemClock.elapsedRealtime() - lastActiveTime;
906 }
907
Louis Changfbcf55f2020-03-02 12:27:15 +0800908 /** @see #setIntent(ActivityRecord, Intent, ActivityInfo) */
Louis Changcdec0802019-11-11 11:45:07 +0800909 void setIntent(ActivityRecord r) {
Louis Changfbcf55f2020-03-02 12:27:15 +0800910 setIntent(r, null /* intent */, null /* info */);
911 }
912
913 /**
914 * Sets the original intent, and the calling uid and package.
915 *
916 * @param r The activity that started the task
917 * @param intent The task info which could be different from {@code r.intent} if set.
918 * @param info The activity info which could be different from {@code r.info} if set.
919 */
920 void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) {
Louis Changcdec0802019-11-11 11:45:07 +0800921 mCallingUid = r.launchedFromUid;
922 mCallingPackage = r.launchedFromPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800923 mCallingFeatureId = r.launchedFromFeatureId;
Louis Changfbcf55f2020-03-02 12:27:15 +0800924 setIntent(intent != null ? intent : r.intent, info != null ? info : r.info);
Louis Changcdec0802019-11-11 11:45:07 +0800925 setLockTaskAuth(r);
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800926
927 final WindowContainer parent = getParent();
928 if (parent != null) {
929 final Task t = parent.asTask();
930 if (t != null) {
931 t.setIntent(r);
932 }
933 }
Louis Changcdec0802019-11-11 11:45:07 +0800934 }
935
936 /** Sets the original intent, _without_ updating the calling uid or package. */
937 private void setIntent(Intent _intent, ActivityInfo info) {
938 if (intent == null) {
939 mNeverRelinquishIdentity =
940 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
941 } else if (mNeverRelinquishIdentity) {
942 return;
943 }
944
945 affinity = info.taskAffinity;
946 if (intent == null) {
947 // If this task already has an intent associated with it, don't set the root
948 // affinity -- we don't want it changing after initially set, but the initially
949 // set value may be null.
950 rootAffinity = affinity;
951 }
952 effectiveUid = info.applicationInfo.uid;
953 stringName = null;
954
955 if (info.targetActivity == null) {
956 if (_intent != null) {
957 // If this Intent has a selector, we want to clear it for the
958 // recent task since it is not relevant if the user later wants
959 // to re-launch the app.
960 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
961 _intent = new Intent(_intent);
962 _intent.setSelector(null);
963 _intent.setSourceBounds(null);
964 }
965 }
966 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
967 intent = _intent;
968 realActivity = _intent != null ? _intent.getComponent() : null;
969 origActivity = null;
970 } else {
971 ComponentName targetComponent = new ComponentName(
972 info.packageName, info.targetActivity);
973 if (_intent != null) {
974 Intent targetIntent = new Intent(_intent);
975 targetIntent.setSelector(null);
976 targetIntent.setSourceBounds(null);
977 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
978 "Setting Intent of " + this + " to target " + targetIntent);
979 intent = targetIntent;
980 realActivity = targetComponent;
981 origActivity = _intent.getComponent();
982 } else {
983 intent = null;
984 realActivity = targetComponent;
985 origActivity = new ComponentName(info.packageName, info.name);
986 }
987 }
Garfield Tan5901e7c2020-02-07 17:12:22 -0800988 mWindowLayoutAffinity =
989 info.windowLayout == null ? null : info.windowLayout.windowLayoutAffinity;
Louis Changcdec0802019-11-11 11:45:07 +0800990
991 final int intentFlags = intent == null ? 0 : intent.getFlags();
992 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
993 // Once we are set to an Intent with this flag, we count this
994 // task as having a true root activity.
995 rootWasReset = true;
996 }
997 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
998 mUserSetupComplete = Settings.Secure.getIntForUser(
999 mAtmService.mContext.getContentResolver(), USER_SETUP_COMPLETE, 0, mUserId) != 0;
1000 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
1001 // If the activity itself has requested auto-remove, then just always do it.
1002 autoRemoveRecents = true;
1003 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
1004 == FLAG_ACTIVITY_NEW_DOCUMENT) {
1005 // If the caller has not asked for the document to be retained, then we may
1006 // want to turn on auto-remove, depending on whether the target has set its
1007 // own document launch mode.
1008 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
1009 autoRemoveRecents = false;
1010 } else {
1011 autoRemoveRecents = true;
1012 }
1013 } else {
1014 autoRemoveRecents = false;
1015 }
1016 if (mResizeMode != info.resizeMode) {
1017 mResizeMode = info.resizeMode;
1018 updateTaskDescription();
1019 }
1020 mSupportsPictureInPicture = info.supportsPictureInPicture();
1021 }
1022
1023 /** Sets the original minimal width and height. */
Wale Ogunwale0d465192020-01-23 19:14:44 -08001024 void setMinDimensions(ActivityInfo info) {
Louis Changcdec0802019-11-11 11:45:07 +08001025 if (info != null && info.windowLayout != null) {
1026 mMinWidth = info.windowLayout.minWidth;
1027 mMinHeight = info.windowLayout.minHeight;
1028 } else {
1029 mMinWidth = INVALID_MIN_SIZE;
1030 mMinHeight = INVALID_MIN_SIZE;
1031 }
1032 }
1033
1034 /**
1035 * Return true if the input activity has the same intent filter as the intent this task
1036 * record is based on (normally the root activity intent).
1037 */
1038 boolean isSameIntentFilter(ActivityRecord r) {
1039 final Intent intent = new Intent(r.intent);
1040 // Make sure the component are the same if the input activity has the same real activity
1041 // as the one in the task because either one of them could be the alias activity.
1042 if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) {
1043 intent.setComponent(this.intent.getComponent());
1044 }
1045 return intent.filterEquals(this.intent);
1046 }
1047
1048 boolean returnsToHomeStack() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001049 if (inMultiWindowMode() || !hasChild()) return false;
1050 if (intent != null) {
1051 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
1052 return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
1053 }
1054 final Task bottomTask = getBottomMostTask();
1055 return bottomTask != this && bottomTask.returnsToHomeStack();
Louis Changcdec0802019-11-11 11:45:07 +08001056 }
1057
1058 void setPrevAffiliate(Task prevAffiliate) {
1059 mPrevAffiliate = prevAffiliate;
1060 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.mTaskId;
1061 }
1062
1063 void setNextAffiliate(Task nextAffiliate) {
1064 mNextAffiliate = nextAffiliate;
1065 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
1066 }
1067
Louis Changcdec0802019-11-11 11:45:07 +08001068 @Override
1069 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001070 final DisplayContent display = newParent != null
1071 ? ((WindowContainer) newParent).getDisplayContent() : null;
1072 final DisplayContent oldDisplay = oldParent != null
1073 ? ((WindowContainer) oldParent).getDisplayContent() : null;
1074
1075 mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
Louis Changcdec0802019-11-11 11:45:07 +08001076
Louis Chang8bda2322019-12-05 16:38:11 +08001077 if (oldParent != null && newParent == null) {
Garfield Tan8b096b22020-01-07 14:55:20 -08001078 cleanUpResourcesForDestroy(oldParent);
Louis Chang8bda2322019-12-05 16:38:11 +08001079 }
1080
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001081 if (display != null) {
1082 // TODO(NOW!): Chat with the erosky@ of this code to see if this really makes sense here...
1083 // Rotations are relative to the display. This means if there are 2 displays rotated
1084 // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
1085 // from one to the other could look like a rotation change. To prevent this
1086 // apparent rotation change (and corresponding bounds rotation), pretend like our
1087 // current rotation is already the same as the new display.
1088 // Note, if ActivityStack or related logic ever gets nested, this logic will need
1089 // to move to onConfigurationChanged.
1090 getConfiguration().windowConfiguration.setRotation(
1091 display.getWindowConfiguration().getRotation());
1092 }
1093
Louis Changcdec0802019-11-11 11:45:07 +08001094 super.onParentChanged(newParent, oldParent);
1095
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001096 // TODO(NOW): The check for null display content and setting it to null doesn't really
1097 // make sense here...
Louis Changcdec0802019-11-11 11:45:07 +08001098
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001099 // TODO(stack-merge): This is mostly taking care of the case where the stask is removing from
1100 // the display, so we should probably consolidate it there instead.
1101
1102 if (getParent() == null && mDisplayContent != null) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08001103 EventLogTags.writeWmStackRemoved(getRootTaskId());
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001104 mDisplayContent = null;
1105 mWmService.mWindowPlacerLocked.requestTraversal();
1106 }
1107
1108 if (oldParent != null) {
1109 final Task oldParentTask = ((WindowContainer) oldParent).asTask();
1110 if (oldParentTask != null) {
1111 final PooledConsumer c = PooledLambda.obtainConsumer(
1112 Task::cleanUpActivityReferences, oldParentTask,
1113 PooledLambda.__(ActivityRecord.class));
1114 forAllActivities(c);
1115 c.recycle();
1116 }
1117
1118 if (oldParent.inPinnedWindowingMode()
1119 && (newParent == null || !newParent.inPinnedWindowingMode())) {
Louis Changcdec0802019-11-11 11:45:07 +08001120 // Notify if a task from the pinned stack is being removed
1121 // (or moved depending on the mode).
1122 mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
1123 }
1124 }
1125
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001126 if (newParent != null) {
1127 final Task newParentTask = ((WindowContainer) newParent).asTask();
1128 if (newParentTask != null) {
1129 final ActivityRecord top = newParentTask.getTopNonFinishingActivity(
1130 false /* includeOverlays */);
1131 if (top != null && top.isState(RESUMED)) {
1132 newParentTask.setResumedActivity(top, "addedToTask");
1133 }
1134 }
Louis Changcdec0802019-11-11 11:45:07 +08001135
1136 // TODO: Ensure that this is actually necessary here
1137 // Notify the voice session if required
1138 if (voiceSession != null) {
1139 try {
1140 voiceSession.taskStarted(intent, mTaskId);
1141 } catch (RemoteException e) {
1142 }
1143 }
1144 }
1145
1146 // First time we are adding the task to the system.
1147 if (oldParent == null && newParent != null) {
1148
1149 // TODO: Super random place to be doing this, but aligns with what used to be done
1150 // before we unified Task level. Look into if this can be done in a better place.
1151 updateOverrideConfigurationFromLaunchBounds();
1152 }
1153
Louis Changcdec0802019-11-11 11:45:07 +08001154 // Update task bounds if needed.
1155 adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
1156
1157 if (getWindowConfiguration().windowsAreScaleable()) {
1158 // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
1159 // while a resize is pending.
1160 forceWindowsScaleable(true /* force */);
1161 } else {
1162 forceWindowsScaleable(false /* force */);
1163 }
1164
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001165 mRootWindowContainer.updateUIDsPresentOnDisplay();
1166 }
1167
1168 void cleanUpActivityReferences(ActivityRecord r) {
1169 final WindowContainer parent = getParent();
1170 if (parent != null && parent.asTask() != null) {
1171 parent.asTask().cleanUpActivityReferences(r);
1172 return;
1173 }
1174 r.removeTimeouts();
1175 mExitingActivities.remove(r);
1176
1177 if (mResumedActivity != null && mResumedActivity == r) {
1178 setResumedActivity(null, "cleanUpActivityReferences");
1179 }
1180 if (mPausingActivity != null && mPausingActivity == r) {
1181 mPausingActivity = null;
1182 }
1183 }
1184
1185 /** @return the currently resumed activity. */
1186 ActivityRecord getResumedActivity() {
1187 return mResumedActivity;
1188 }
1189
1190 void setResumedActivity(ActivityRecord r, String reason) {
1191 if (mResumedActivity == r) {
1192 return;
1193 }
1194
1195 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) Slog.d(TAG_STACK,
1196 "setResumedActivity stack:" + this + " + from: "
1197 + mResumedActivity + " to:" + r + " reason:" + reason);
1198 mResumedActivity = r;
1199 mStackSupervisor.updateTopResumedActivityIfNeeded();
Louis Changcdec0802019-11-11 11:45:07 +08001200 }
1201
1202 void updateTaskMovement(boolean toFront) {
1203 if (isPersistable) {
1204 mLastTimeMoved = System.currentTimeMillis();
1205 // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
1206 // recently will be most negative, tasks sent to the bottom before that will be less
1207 // negative. Similarly for recent tasks moved to the top which will be most positive.
1208 if (!toFront) {
1209 mLastTimeMoved *= -1;
1210 }
1211 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001212 mRootWindowContainer.invalidateTaskLayers();
Louis Changcdec0802019-11-11 11:45:07 +08001213 }
1214
Louis Changcdec0802019-11-11 11:45:07 +08001215 // Close up recents linked list.
1216 private void closeRecentsChain() {
1217 if (mPrevAffiliate != null) {
1218 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
1219 }
1220 if (mNextAffiliate != null) {
1221 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
1222 }
1223 setPrevAffiliate(null);
1224 setNextAffiliate(null);
1225 }
1226
1227 void removedFromRecents() {
1228 closeRecentsChain();
1229 if (inRecents) {
1230 inRecents = false;
1231 mAtmService.notifyTaskPersisterLocked(this, false);
1232 }
1233
1234 clearRootProcess();
1235
1236 mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
1237 mTaskId, mUserId);
1238 }
1239
1240 void setTaskToAffiliateWith(Task taskToAffiliateWith) {
1241 closeRecentsChain();
1242 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
1243 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
1244 // Find the end
1245 while (taskToAffiliateWith.mNextAffiliate != null) {
1246 final Task nextRecents = taskToAffiliateWith.mNextAffiliate;
1247 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1248 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1249 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1250 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1251 nextRecents.setPrevAffiliate(null);
1252 }
1253 taskToAffiliateWith.setNextAffiliate(null);
1254 break;
1255 }
1256 taskToAffiliateWith = nextRecents;
1257 }
1258 taskToAffiliateWith.setNextAffiliate(this);
1259 setPrevAffiliate(taskToAffiliateWith);
1260 setNextAffiliate(null);
1261 }
1262
1263 /** Returns the intent for the root activity for this task */
1264 Intent getBaseIntent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001265 if (intent != null) return intent;
1266 if (affinityIntent != null) return affinityIntent;
1267 // Probably a task that contains other tasks, so return the intent for the top task?
1268 final Task topTask = getTopMostTask();
Evan Rosky0037e5f2019-11-05 10:26:24 -08001269 return (topTask != this && topTask != null) ? topTask.getBaseIntent() : null;
Louis Changcdec0802019-11-11 11:45:07 +08001270 }
1271
1272 /** Returns the first non-finishing activity from the bottom. */
1273 ActivityRecord getRootActivity() {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001274 // TODO: Figure out why we historical ignore relinquish identity for this case...
1275 return getRootActivity(true /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
1276 }
1277
1278 ActivityRecord getRootActivity(boolean setToBottomIfNone) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001279 return getRootActivity(false /*ignoreRelinquishIdentity*/, setToBottomIfNone);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001280 }
1281
1282 ActivityRecord getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001283 return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone);
Louis Changcdec0802019-11-11 11:45:07 +08001284 }
1285
Wale Ogunwale21e06482019-11-18 05:14:15 -08001286 ActivityRecord getTopNonFinishingActivity() {
1287 return getTopNonFinishingActivity(true /* includeOverlays */);
Louis Changcdec0802019-11-11 11:45:07 +08001288 }
1289
Wale Ogunwale21e06482019-11-18 05:14:15 -08001290 ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001291 return getTopActivity(false /*includeFinishing*/, includeOverlays);
Louis Changcdec0802019-11-11 11:45:07 +08001292 }
1293
1294 ActivityRecord topRunningActivityLocked() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001295 if (getParent() == null) {
1296 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001297 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001298 return getActivity(ActivityRecord::canBeTopRunning);
Louis Changcdec0802019-11-11 11:45:07 +08001299 }
1300
1301 /**
1302 * Return true if any activities in this task belongs to input uid.
1303 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001304 boolean isUidPresent(int uid) {
1305 final PooledPredicate p = PooledLambda.obtainPredicate(
1306 ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid);
1307 final boolean isUidPresent = getActivity(p) != null;
1308 p.recycle();
1309 return isUidPresent;
Louis Changcdec0802019-11-11 11:45:07 +08001310 }
1311
1312 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001313 if (getParent() == null) {
1314 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001315 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001316 return getActivity((r) -> r.mStartingWindowState == STARTING_WINDOW_SHOWN
1317 && r.canBeTopRunning());
Louis Changcdec0802019-11-11 11:45:07 +08001318 }
1319
1320 /**
1321 * Return the number of running activities, and the number of non-finishing/initializing
1322 * activities in the provided {@param reportOut} respectively.
1323 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001324 private void getNumRunningActivities(TaskActivitiesReport reportOut) {
Louis Changcdec0802019-11-11 11:45:07 +08001325 reportOut.reset();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001326 forAllActivities(reportOut);
Louis Changcdec0802019-11-11 11:45:07 +08001327 }
1328
1329 /**
1330 * Reorder the history stack so that the passed activity is brought to the front.
1331 */
1332 final void moveActivityToFrontLocked(ActivityRecord newTop) {
1333 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, "Removing and adding activity "
1334 + newTop + " to stack at top callers=" + Debug.getCallers(4));
1335
1336 positionChildAtTop(newTop);
1337 updateEffectiveIntent();
1338 }
1339
1340 @Override
1341 public int getActivityType() {
1342 final int applicationType = super.getActivityType();
1343 if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
1344 return applicationType;
1345 }
Louis Changa009c762020-02-26 11:21:31 +08001346 return getTopChild().getActivityType();
Louis Changcdec0802019-11-11 11:45:07 +08001347 }
1348
1349 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001350 void addChild(WindowContainer child, int index) {
Louis Changcdec0802019-11-11 11:45:07 +08001351 // If this task had any child before we added this one.
1352 boolean hadChild = hasChild();
Evan Rosky660b1752020-04-15 18:07:15 -07001353 // getActivityType() looks at the top child, so we need to read the type before adding
1354 // a new child in case the new child is on top and UNDEFINED.
1355 final int activityType = getActivityType();
Louis Changcdec0802019-11-11 11:45:07 +08001356
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001357 index = getAdjustedChildPosition(child, index);
1358 super.addChild(child, index);
Louis Changcdec0802019-11-11 11:45:07 +08001359
1360 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001361
Louis Changa009c762020-02-26 11:21:31 +08001362 // A rootable task that is now being added to be the child of an organized task. Making
1363 // sure the stack references is keep updated.
1364 if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001365 getDisplayArea().addStackReferenceIfNeeded((ActivityStack) child);
Louis Changa009c762020-02-26 11:21:31 +08001366 }
1367
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001368 // Make sure the list of display UID whitelists is updated
1369 // now that this record is in a new task.
1370 mRootWindowContainer.updateUIDsPresentOnDisplay();
1371
1372 final ActivityRecord r = child.asActivityRecord();
1373 if (r == null) return;
1374
Louis Changcdec0802019-11-11 11:45:07 +08001375 r.inHistory = true;
1376
Louis Changcdec0802019-11-11 11:45:07 +08001377 // Only set this based on the first activity
1378 if (!hadChild) {
1379 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1380 // Normally non-standard activity type for the activity record will be set when the
1381 // object is created, however we delay setting the standard application type until
1382 // this point so that the task can set the type for additional activities added in
1383 // the else condition below.
1384 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1385 }
1386 setActivityType(r.getActivityType());
1387 isPersistable = r.isPersistable();
1388 mCallingUid = r.launchedFromUid;
1389 mCallingPackage = r.launchedFromPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -08001390 mCallingFeatureId = r.launchedFromFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +08001391 // Clamp to [1, max].
1392 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1393 ActivityTaskManager.getMaxAppRecentsLimitStatic());
1394 } else {
1395 // Otherwise make all added activities match this one.
Evan Rosky660b1752020-04-15 18:07:15 -07001396 r.setActivityType(activityType);
Louis Changcdec0802019-11-11 11:45:07 +08001397 }
1398
1399 updateEffectiveIntent();
Louis Changcdec0802019-11-11 11:45:07 +08001400 }
1401
1402 void addChild(ActivityRecord r) {
1403 addChild(r, Integer.MAX_VALUE /* add on top */);
1404 }
1405
1406 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001407 void removeChild(WindowContainer child) {
1408 removeChild(child, "removeChild");
1409 }
1410
1411 void removeChild(WindowContainer r, String reason) {
Riddle Hsu9adc55f2020-04-28 17:07:33 +08001412 // A rootable child task that is now being removed from an organized task. Making sure
1413 // the stack references is keep updated.
1414 if (mTaskOrganizer != null && mCreatedByOrganizer && r.asTask() != null) {
1415 getDisplayArea().removeStackReferenceIfNeeded((ActivityStack) r);
1416 }
Louis Changcdec0802019-11-11 11:45:07 +08001417 if (!mChildren.contains(r)) {
1418 Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
1419 return;
1420 }
1421
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001422 if (DEBUG_TASK_MOVEMENT) {
1423 Slog.d(TAG_WM, "removeChild: child=" + r + " reason=" + reason);
1424 }
Louis Changcdec0802019-11-11 11:45:07 +08001425 super.removeChild(r);
Louis Changcdec0802019-11-11 11:45:07 +08001426
1427 if (inPinnedWindowingMode()) {
1428 // We normally notify listeners of task stack changes on pause, however pinned stack
1429 // activities are normally in the paused state so no notification will be sent there
1430 // before the activity is removed. We send it here so instead.
1431 mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
1432 }
1433
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001434 final boolean isRootTask = isRootTask();
1435 if (isRootTask) {
1436 final DisplayContent display = getDisplayContent();
1437 if (display.isSingleTaskInstance()) {
1438 mAtmService.notifySingleTaskDisplayEmpty(display.mDisplayId);
1439 }
1440 display.mDisplayContent.setLayoutNeeded();
1441 }
1442
Louis Changcdec0802019-11-11 11:45:07 +08001443 if (hasChild()) {
1444 updateEffectiveIntent();
1445
1446 // The following block can be executed multiple times if there is more than one overlay.
1447 // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
1448 // of the task by id and exiting early if not found.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001449 if (onlyHasTaskOverlayActivities(true /*includeFinishing*/)) {
Louis Changcdec0802019-11-11 11:45:07 +08001450 // When destroying a task, tell the supervisor to remove it so that any activity it
1451 // has can be cleaned up correctly. This is currently the only place where we remove
1452 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
1453 // state into removeChild(), we just clear the task here before the other residual
1454 // work.
1455 // TODO: If the callers to removeChild() changes such that we have multiple places
1456 // where we are destroying the task, move this back into removeChild()
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001457 mStackSupervisor.removeTask(this, false /* killProcess */,
Louis Changcdec0802019-11-11 11:45:07 +08001458 !REMOVE_FROM_RECENTS, reason);
1459 }
Louis Changa009c762020-02-26 11:21:31 +08001460 } else if (!mReuseTask && !mCreatedByOrganizer) {
Louis Changcdec0802019-11-11 11:45:07 +08001461 // 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 +08001462 // or created by task organizer.
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001463 if (!isRootTask) {
1464 getStack().removeChild(this, reason);
1465 }
Jeff Changd136e772019-11-05 20:33:52 +08001466 EventLogTags.writeWmTaskRemoved(mTaskId,
Louis Changcdec0802019-11-11 11:45:07 +08001467 "removeChild: last r=" + r + " in t=" + this);
1468 removeIfPossible();
1469 }
1470 }
1471
1472 /**
Louis Changfd5539e2020-02-04 14:34:24 +08001473 * @return whether or not there are ONLY task overlay activities in the task.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001474 * If {@param includeFinishing} is set, then don't ignore finishing activities in the
1475 * check. If there are no task overlay activities, this call returns false.
Louis Changcdec0802019-11-11 11:45:07 +08001476 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001477 boolean onlyHasTaskOverlayActivities(boolean includeFinishing) {
Louis Changfd5539e2020-02-04 14:34:24 +08001478 int count = 0;
1479 for (int i = getChildCount() - 1; i >= 0; i--) {
1480 final ActivityRecord r = getChildAt(i).asActivityRecord();
1481 if (r == null) {
1482 // Has a child that is other than Activity.
1483 return false;
1484 }
1485 if (!includeFinishing && r.finishing) {
1486 continue;
1487 }
1488 if (!r.isTaskOverlay()) {
1489 return false;
1490 }
1491 count++;
Louis Changcdec0802019-11-11 11:45:07 +08001492 }
Louis Changfd5539e2020-02-04 14:34:24 +08001493 return count > 0;
Louis Changcdec0802019-11-11 11:45:07 +08001494 }
1495
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001496 private boolean autoRemoveFromRecents() {
Louis Changcdec0802019-11-11 11:45:07 +08001497 // We will automatically remove the task either if it has explicitly asked for
1498 // this, or it is empty and has never contained an activity that got shown to
1499 // the user.
Robert Carrde96c8a2020-03-24 15:22:21 -07001500 return autoRemoveRecents || (!hasChild() && !getHasBeenVisible());
Louis Changcdec0802019-11-11 11:45:07 +08001501 }
1502
1503 /**
1504 * Completely remove all activities associated with an existing
1505 * task starting at a specified index.
1506 */
Wale Ogunwale21e06482019-11-18 05:14:15 -08001507 private void performClearTaskAtIndexLocked(String reason) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001508 // Broken down into to cases to avoid object create due to capturing mStack.
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001509 if (getStack() == null) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001510 forAllActivities((r) -> {
1511 if (r.finishing) return;
Louis Changcdec0802019-11-11 11:45:07 +08001512 // Task was restored from persistent storage.
1513 r.takeFromHistory();
1514 removeChild(r);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001515 });
1516 } else {
1517 forAllActivities((r) -> {
1518 if (r.finishing) return;
1519 // TODO: figure-out how to avoid object creation due to capture of reason variable.
1520 r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
1521 false /* oomAdj */);
1522 });
Louis Changcdec0802019-11-11 11:45:07 +08001523 }
1524 }
1525
1526 /**
1527 * Completely remove all activities associated with an existing task.
1528 */
1529 void performClearTaskLocked() {
1530 mReuseTask = true;
Wale Ogunwale21e06482019-11-18 05:14:15 -08001531 performClearTaskAtIndexLocked("clear-task-all");
Louis Changcdec0802019-11-11 11:45:07 +08001532 mReuseTask = false;
1533 }
1534
1535 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1536 mReuseTask = true;
1537 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1538 mReuseTask = false;
1539 return result;
1540 }
1541
1542 /**
1543 * Perform clear operation as requested by
1544 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1545 * stack to the given task, then look for
1546 * an instance of that activity in the stack and, if found, finish all
1547 * activities on top of it and return the instance.
1548 *
1549 * @param newR Description of the new activity being started.
1550 * @return Returns the old activity that should be continued to be used,
1551 * or {@code null} if none was found.
1552 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001553 private ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
1554 final ActivityRecord r = findActivityInHistory(newR.mActivityComponent);
1555 if (r == null) return null;
Louis Changcdec0802019-11-11 11:45:07 +08001556
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001557 final PooledFunction f = PooledLambda.obtainFunction(Task::finishActivityAbove,
1558 PooledLambda.__(ActivityRecord.class), r);
1559 forAllActivities(f);
1560 f.recycle();
Louis Changcdec0802019-11-11 11:45:07 +08001561
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001562 // Finally, if this is a normal launch mode (that is, not expecting onNewIntent()), then we
1563 // will finish the current instance of the activity so a new fresh one can be started.
1564 if (r.launchMode == ActivityInfo.LAUNCH_MULTIPLE
1565 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1566 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
1567 if (!r.finishing) {
1568 r.finishIfPossible("clear-task-top", false /* oomAdj */);
1569 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001570 }
1571 }
1572
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001573 return r;
1574 }
1575
1576 private static boolean finishActivityAbove(ActivityRecord r, ActivityRecord boundaryActivity) {
1577 // Stop operation once we reach the boundary activity.
1578 if (r == boundaryActivity) return true;
1579
1580 if (!r.finishing) {
1581 final ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
1582 if (opts != null) {
1583 // TODO: Why is this updating the boundary activity vs. the current activity???
1584 boundaryActivity.updateOptionsLocked(opts);
1585 }
1586 r.finishIfPossible("clear-task-stack", false /* oomAdj */);
1587 }
1588
1589 return false;
Louis Changcdec0802019-11-11 11:45:07 +08001590 }
1591
1592 void removeTaskActivitiesLocked(String reason) {
1593 // Just remove the entire task.
Wale Ogunwale21e06482019-11-18 05:14:15 -08001594 performClearTaskAtIndexLocked(reason);
Louis Changcdec0802019-11-11 11:45:07 +08001595 }
1596
1597 String lockTaskAuthToString() {
1598 switch (mLockTaskAuth) {
1599 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1600 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1601 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1602 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
1603 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
1604 default: return "unknown=" + mLockTaskAuth;
1605 }
1606 }
1607
1608 void setLockTaskAuth() {
1609 setLockTaskAuth(getRootActivity());
1610 }
1611
1612 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1613 if (r == null) {
1614 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1615 return;
1616 }
1617
1618 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
1619 final LockTaskController lockTaskController = mAtmService.getLockTaskController();
1620 switch (r.lockTaskLaunchMode) {
1621 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
1622 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
1623 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
1624 break;
1625
1626 case LOCK_TASK_LAUNCH_MODE_NEVER:
1627 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
1628 break;
1629
1630 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
1631 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
1632 break;
1633
1634 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
1635 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
1636 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
1637 break;
1638 }
1639 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this
1640 + " mLockTaskAuth=" + lockTaskAuthToString());
1641 }
1642
1643 @Override
1644 public boolean supportsSplitScreenWindowingMode() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001645 final Task topTask = getTopMostTask();
1646 return super.supportsSplitScreenWindowingMode()
1647 && (topTask == null || topTask.supportsSplitScreenWindowingModeInner());
1648 }
1649
1650 private boolean supportsSplitScreenWindowingModeInner() {
Louis Changcdec0802019-11-11 11:45:07 +08001651 // A task can not be docked even if it is considered resizeable because it only supports
1652 // picture-in-picture mode but has a non-resizeable resizeMode
1653 return super.supportsSplitScreenWindowingMode()
Louis Changcdec0802019-11-11 11:45:07 +08001654 && mAtmService.mSupportsSplitScreenMultiWindow
1655 && (mAtmService.mForceResizableActivities
1656 || (isResizeable(false /* checkSupportsPip */)
1657 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
1658 }
1659
1660 /**
1661 * Check whether this task can be launched on the specified display.
1662 *
1663 * @param displayId Target display id.
1664 * @return {@code true} if either it is the default display or this activity can be put on a
1665 * secondary display.
1666 */
1667 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001668 return mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Louis Changcdec0802019-11-11 11:45:07 +08001669 -1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
1670 }
1671
1672 /**
1673 * Check that a given bounds matches the application requested orientation.
1674 *
1675 * @param bounds The bounds to be tested.
1676 * @return True if the requested bounds are okay for a resizing request.
1677 */
1678 private boolean canResizeToBounds(Rect bounds) {
1679 if (bounds == null || !inFreeformWindowingMode()) {
1680 // Note: If not on the freeform workspace, we ignore the bounds.
1681 return true;
1682 }
1683 final boolean landscape = bounds.width() > bounds.height();
1684 final Rect configBounds = getRequestedOverrideBounds();
1685 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
1686 return configBounds.isEmpty()
1687 || landscape == (configBounds.width() > configBounds.height());
1688 }
1689 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1690 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1691 }
1692
1693 /**
1694 * @return {@code true} if the task is being cleared for the purposes of being reused.
1695 */
1696 boolean isClearingToReuseTask() {
1697 return mReuseTask;
1698 }
1699
1700 /**
1701 * Find the activity in the history stack within the given task. Returns
1702 * the index within the history at which it's found, or < 0 if not found.
1703 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001704 ActivityRecord findActivityInHistory(ComponentName component) {
1705 final PooledPredicate p = PooledLambda.obtainPredicate(Task::matchesActivityInHistory,
1706 PooledLambda.__(ActivityRecord.class), component);
1707 final ActivityRecord r = getActivity(p);
1708 p.recycle();
1709 return r;
1710 }
1711
1712 private static boolean matchesActivityInHistory(
1713 ActivityRecord r, ComponentName activityComponent) {
1714 return !r.finishing && r.mActivityComponent.equals(activityComponent);
Louis Changcdec0802019-11-11 11:45:07 +08001715 }
1716
1717 /** Updates the last task description values. */
1718 void updateTaskDescription() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001719 final ActivityRecord root = getRootActivity(true);
1720 if (root == null) return;
1721
1722 final TaskDescription taskDescription = new TaskDescription();
1723 final PooledFunction f = PooledLambda.obtainFunction(
1724 Task::setTaskDescriptionFromActivityAboveRoot,
1725 PooledLambda.__(ActivityRecord.class), root, taskDescription);
1726 forAllActivities(f);
1727 f.recycle();
1728 taskDescription.setResizeMode(mResizeMode);
1729 taskDescription.setMinWidth(mMinWidth);
1730 taskDescription.setMinHeight(mMinHeight);
1731 setTaskDescription(taskDescription);
1732 // Update the task affiliation color if we are the parent of the group
1733 if (mTaskId == mAffiliatedTaskId) {
1734 mAffiliatedTaskColor = taskDescription.getPrimaryColor();
Louis Changcdec0802019-11-11 11:45:07 +08001735 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001736 mAtmService.getTaskChangeNotificationController().notifyTaskDescriptionChanged(
1737 getTaskInfo());
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001738
1739 final WindowContainer parent = getParent();
1740 if (parent != null) {
1741 final Task t = parent.asTask();
1742 if (t != null) {
1743 t.updateTaskDescription();
1744 }
1745 }
Winson Chung1df39e22020-04-09 14:30:55 -07001746
1747 if (isOrganized()) {
1748 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
1749 }
Louis Changcdec0802019-11-11 11:45:07 +08001750 }
1751
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001752 private static boolean setTaskDescriptionFromActivityAboveRoot(
1753 ActivityRecord r, ActivityRecord root, TaskDescription td) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001754 if (!r.isTaskOverlay() && r.taskDescription != null) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001755 final TaskDescription atd = r.taskDescription;
1756 if (td.getLabel() == null) {
1757 td.setLabel(atd.getLabel());
Louis Changcdec0802019-11-11 11:45:07 +08001758 }
Winson Chungd6722032020-02-18 15:16:08 -08001759 if (td.getRawIcon() == null) {
1760 td.setIcon(atd.getRawIcon());
Louis Changcdec0802019-11-11 11:45:07 +08001761 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001762 if (td.getIconFilename() == null) {
1763 td.setIconFilename(atd.getIconFilename());
1764 }
1765 if (td.getPrimaryColor() == 0) {
1766 td.setPrimaryColor(atd.getPrimaryColor());
1767 }
1768 if (td.getBackgroundColor() == 0) {
1769 td.setBackgroundColor(atd.getBackgroundColor());
1770 }
1771 if (td.getStatusBarColor() == 0) {
1772 td.setStatusBarColor(atd.getStatusBarColor());
1773 td.setEnsureStatusBarContrastWhenTransparent(
1774 atd.getEnsureStatusBarContrastWhenTransparent());
1775 }
1776 if (td.getNavigationBarColor() == 0) {
1777 td.setNavigationBarColor(atd.getNavigationBarColor());
1778 td.setEnsureNavigationBarContrastWhenTransparent(
1779 atd.getEnsureNavigationBarContrastWhenTransparent());
1780 }
1781
Louis Changcdec0802019-11-11 11:45:07 +08001782 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001783
1784 // End search once we get to root.
1785 return r == root;
Louis Changcdec0802019-11-11 11:45:07 +08001786 }
1787
1788 // TODO (AM refactor): Invoke automatically when there is a change in children
1789 @VisibleForTesting
1790 void updateEffectiveIntent() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001791 final ActivityRecord root = getRootActivity(true /*setToBottomIfNone*/);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001792 if (root != null) {
1793 setIntent(root);
1794 // Update the task description when the activities change
1795 updateTaskDescription();
1796 }
Louis Changcdec0802019-11-11 11:45:07 +08001797 }
1798
Riddle Hsudd49c632020-04-30 22:39:51 +08001799 void adjustForMinimalTaskDimensions(@NonNull Rect bounds, @NonNull Rect previousBounds,
1800 @NonNull Configuration parentConfig) {
Louis Changcdec0802019-11-11 11:45:07 +08001801 int minWidth = mMinWidth;
1802 int minHeight = mMinHeight;
1803 // If the task has no requested minimal size, we'd like to enforce a minimal size
1804 // so that the user can not render the task too small to manipulate. We don't need
1805 // to do this for the pinned stack as the bounds are controlled by the system.
Riddle Hsudd49c632020-04-30 22:39:51 +08001806 if (!inPinnedWindowingMode()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001807 final int defaultMinSizeDp = mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp;
Riddle Hsudd49c632020-04-30 22:39:51 +08001808 final float density = (float) parentConfig.densityDpi / DisplayMetrics.DENSITY_DEFAULT;
Louis Changcdec0802019-11-11 11:45:07 +08001809 final int defaultMinSize = (int) (defaultMinSizeDp * density);
1810
1811 if (minWidth == INVALID_MIN_SIZE) {
1812 minWidth = defaultMinSize;
1813 }
1814 if (minHeight == INVALID_MIN_SIZE) {
1815 minHeight = defaultMinSize;
1816 }
1817 }
Evan Rosky70213702019-11-05 10:26:24 -08001818 if (bounds.isEmpty()) {
1819 // If inheriting parent bounds, check if parent bounds adhere to minimum size. If they
1820 // do, we can just skip.
Riddle Hsudd49c632020-04-30 22:39:51 +08001821 final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
Evan Rosky70213702019-11-05 10:26:24 -08001822 if (parentBounds.width() >= minWidth && parentBounds.height() >= minHeight) {
1823 return;
1824 }
1825 bounds.set(parentBounds);
1826 }
Louis Changcdec0802019-11-11 11:45:07 +08001827 final boolean adjustWidth = minWidth > bounds.width();
1828 final boolean adjustHeight = minHeight > bounds.height();
1829 if (!(adjustWidth || adjustHeight)) {
1830 return;
1831 }
1832
1833 if (adjustWidth) {
1834 if (!previousBounds.isEmpty() && bounds.right == previousBounds.right) {
1835 bounds.left = bounds.right - minWidth;
1836 } else {
1837 // Either left bounds match, or neither match, or the previous bounds were
1838 // fullscreen and we default to keeping left.
1839 bounds.right = bounds.left + minWidth;
1840 }
1841 }
1842 if (adjustHeight) {
1843 if (!previousBounds.isEmpty() && bounds.bottom == previousBounds.bottom) {
1844 bounds.top = bounds.bottom - minHeight;
1845 } else {
1846 // Either top bounds match, or neither match, or the previous bounds were
1847 // fullscreen and we default to keeping top.
1848 bounds.bottom = bounds.top + minHeight;
1849 }
1850 }
1851 }
1852
1853 void setLastNonFullscreenBounds(Rect bounds) {
1854 if (mLastNonFullscreenBounds == null) {
1855 mLastNonFullscreenBounds = new Rect(bounds);
1856 } else {
1857 mLastNonFullscreenBounds.set(bounds);
1858 }
1859 }
1860
1861 /**
1862 * This should be called when an child activity changes state. This should only
1863 * be called from
1864 * {@link ActivityRecord#setState(ActivityState, String)} .
1865 * @param record The {@link ActivityRecord} whose state has changed.
1866 * @param state The new state.
1867 * @param reason The reason for the change.
1868 */
1869 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001870 final Task parentTask = getParent().asTask();
1871 if (parentTask != null) {
1872 parentTask.onActivityStateChanged(record, state, reason);
Louis Changa009c762020-02-26 11:21:31 +08001873 // We still want to update the resumed activity if the parent task is created by
1874 // organizer in order to keep the information synced once got reparented out from the
1875 // organized task.
1876 if (!parentTask.mCreatedByOrganizer) {
1877 return;
1878 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001879 }
Louis Changcdec0802019-11-11 11:45:07 +08001880
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001881 if (record == mResumedActivity && state != RESUMED) {
1882 setResumedActivity(null, reason + " - onActivityStateChanged");
1883 }
1884
1885 if (state == RESUMED) {
1886 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
1887 Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" + reason);
1888 }
1889 setResumedActivity(record, reason + " - onActivityStateChanged");
1890 if (record == mRootWindowContainer.getTopResumedActivity()) {
1891 mAtmService.setResumedActivityUncheckLocked(record, reason);
1892 }
1893 mStackSupervisor.mRecentTasks.add(record.getTask());
Louis Changcdec0802019-11-11 11:45:07 +08001894 }
1895 }
1896
1897 @Override
1898 public void onConfigurationChanged(Configuration newParentConfig) {
1899 // Check if the new configuration supports persistent bounds (eg. is Freeform) and if so
1900 // restore the last recorded non-fullscreen bounds.
1901 final boolean prevPersistTaskBounds = getWindowConfiguration().persistTaskBounds();
Ben Lin50038ee2020-04-24 17:09:12 -07001902 boolean nextPersistTaskBounds =
1903 getRequestedOverrideConfiguration().windowConfiguration.persistTaskBounds();
1904 if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_UNDEFINED) {
1905 nextPersistTaskBounds = newParentConfig.windowConfiguration.persistTaskBounds();
1906 }
Louis Changcdec0802019-11-11 11:45:07 +08001907 if (!prevPersistTaskBounds && nextPersistTaskBounds
1908 && mLastNonFullscreenBounds != null && !mLastNonFullscreenBounds.isEmpty()) {
1909 // Bypass onRequestedOverrideConfigurationChanged here to avoid infinite loop.
1910 getRequestedOverrideConfiguration().windowConfiguration
1911 .setBounds(mLastNonFullscreenBounds);
1912 }
1913
Evan Rosky55bddd82020-01-29 13:07:18 -08001914 final int prevWinMode = getWindowingMode();
1915 mTmpPrevBounds.set(getBounds());
Louis Changcdec0802019-11-11 11:45:07 +08001916 final boolean wasInMultiWindowMode = inMultiWindowMode();
Hongwei Wang5c52ff82020-04-20 16:02:30 -07001917 final boolean wasInPictureInPicture = inPinnedWindowingMode();
Louis Changcdec0802019-11-11 11:45:07 +08001918 super.onConfigurationChanged(newParentConfig);
Louis Chang2570e332020-04-10 11:58:49 +08001919 // Only need to update surface size here since the super method will handle updating
1920 // surface position.
1921 updateSurfaceSize(getPendingTransaction());
1922
Hongwei Wang5c52ff82020-04-20 16:02:30 -07001923 if (wasInPictureInPicture != inPinnedWindowingMode()) {
1924 mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, getStack());
1925 } else if (wasInMultiWindowMode != inMultiWindowMode()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001926 mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Louis Changcdec0802019-11-11 11:45:07 +08001927 }
1928
Evan Rosky55bddd82020-01-29 13:07:18 -08001929 final int newWinMode = getWindowingMode();
1930 if ((prevWinMode != newWinMode) && (mDisplayContent != null)
1931 && shouldStartChangeTransition(prevWinMode, newWinMode)) {
1932 initializeChangeTransition(mTmpPrevBounds);
1933 }
1934
Louis Changcdec0802019-11-11 11:45:07 +08001935 // If the configuration supports persistent bounds (eg. Freeform), keep track of the
1936 // current (non-fullscreen) bounds for persistence.
1937 if (getWindowConfiguration().persistTaskBounds()) {
1938 final Rect currentBounds = getRequestedOverrideBounds();
1939 if (!currentBounds.isEmpty()) {
1940 setLastNonFullscreenBounds(currentBounds);
1941 }
1942 }
Louis Changcdec0802019-11-11 11:45:07 +08001943
1944 saveLaunchingStateIfNeeded();
Evan Roskyf64f5da2020-03-16 13:47:48 -07001945 final boolean taskOrgChanged = updateTaskOrganizerState(false /* forceUpdate */);
1946 // If the task organizer has changed, then it will already be receiving taskAppeared with
1947 // the latest task-info thus the task-info won't have changed.
Winson Chung1df39e22020-04-09 14:30:55 -07001948 if (!taskOrgChanged && isOrganized()) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07001949 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, false /* force */);
1950 }
Louis Changcdec0802019-11-11 11:45:07 +08001951 }
1952
1953 /**
Evan Rosky55bddd82020-01-29 13:07:18 -08001954 * Initializes a change transition. See {@link SurfaceFreezer} for more information.
1955 */
1956 private void initializeChangeTransition(Rect startBounds) {
1957 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1958 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1959 mDisplayContent.mChangingContainers.add(this);
1960
1961 mSurfaceFreezer.freeze(getPendingTransaction(), startBounds);
1962 }
1963
1964 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
1965 if (mWmService.mDisableTransitionAnimation
1966 || !isVisible()
1967 || getDisplayContent().mAppTransition.isTransitionSet()
Evan Rosky8d4ee722020-04-21 17:28:31 -07001968 || getSurfaceControl() == null
1969 || !isLeafTask()) {
Evan Rosky55bddd82020-01-29 13:07:18 -08001970 return false;
1971 }
1972 // Only do an animation into and out-of freeform mode for now. Other mode
1973 // transition animations are currently handled by system-ui.
1974 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1975 }
1976
chaviwda7b3c22020-04-24 11:25:08 -07001977 @Override
1978 void migrateToNewSurfaceControl() {
1979 super.migrateToNewSurfaceControl();
1980 mLastSurfaceSize.x = 0;
1981 mLastSurfaceSize.y = 0;
1982 updateSurfaceSize(getPendingTransaction());
1983 }
1984
Louis Chang2570e332020-04-10 11:58:49 +08001985 void updateSurfaceSize(SurfaceControl.Transaction transaction) {
Robert Carr1530eee2020-05-05 15:15:01 -07001986 if (mSurfaceControl == null || isOrganized()) {
Louis Chang2570e332020-04-10 11:58:49 +08001987 return;
1988 }
1989
1990 // Apply crop to root tasks only and clear the crops of the descendant tasks.
1991 int width = 0;
1992 int height = 0;
1993 if (isRootTask()) {
1994 final Rect taskBounds = getBounds();
1995 width = taskBounds.width();
1996 height = taskBounds.height();
1997
1998 final int outset = getTaskOutset();
1999 width += 2 * outset;
2000 height += 2 * outset;
2001 }
2002 if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
2003 return;
2004 }
2005 transaction.setWindowCrop(mSurfaceControl, width, height);
2006 mLastSurfaceSize.set(width, height);
2007 }
2008
2009 /**
2010 * Calculate an amount by which to expand the task bounds in each direction.
2011 * Used to make room for shadows in the pinned windowing mode.
2012 */
2013 int getTaskOutset() {
2014 // If we are drawing shadows on the task then don't outset the stack.
2015 if (mWmService.mRenderShadowsInCompositor) {
2016 return 0;
2017 }
2018 DisplayContent displayContent = getDisplayContent();
2019 if (inPinnedWindowingMode() && displayContent != null) {
2020 final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
2021
2022 // We multiply by two to match the client logic for converting view elevation
2023 // to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets}
2024 return (int) Math.ceil(
2025 mWmService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP, displayMetrics)
2026 * 2);
2027 }
2028 return 0;
2029 }
2030
2031 @VisibleForTesting
2032 Point getLastSurfaceSize() {
2033 return mLastSurfaceSize;
2034 }
2035
Evan Rosky55bddd82020-01-29 13:07:18 -08002036 @VisibleForTesting
2037 boolean isInChangeTransition() {
2038 return mSurfaceFreezer.hasLeash() || AppTransition.isChangeTransit(mTransit);
2039 }
2040
2041 @Override
2042 public SurfaceControl getFreezeSnapshotTarget() {
2043 final int transit = mDisplayContent.mAppTransition.getAppTransition();
2044 if (!AppTransition.isChangeTransit(transit)) {
2045 return null;
2046 }
2047 // Skip creating snapshot if this transition is controlled by a remote animator which
2048 // doesn't need it.
2049 final ArraySet<Integer> activityTypes = new ArraySet<>();
2050 activityTypes.add(getActivityType());
2051 final RemoteAnimationAdapter adapter =
2052 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
2053 this, transit, activityTypes);
2054 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
2055 return null;
2056 }
2057 return getSurfaceControl();
2058 }
2059
2060 @Override
2061 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
2062 final long token = proto.start(fieldId);
2063 proto.write(HASH_CODE, System.identityHashCode(this));
2064 proto.write(USER_ID, mUserId);
2065 proto.write(TITLE, intent != null && intent.getComponent() != null
2066 ? intent.getComponent().flattenToShortString() : "Task");
2067 proto.end(token);
2068 }
2069
2070 /**
Louis Changcdec0802019-11-11 11:45:07 +08002071 * Saves launching state if necessary so that we can launch the activity to its latest state.
2072 * It only saves state if this task has been shown to user and it's in fullscreen or freeform
2073 * mode on freeform displays.
2074 */
Garfield Tan8b096b22020-01-07 14:55:20 -08002075 private void saveLaunchingStateIfNeeded() {
2076 saveLaunchingStateIfNeeded(getDisplayContent());
2077 }
2078
2079 private void saveLaunchingStateIfNeeded(DisplayContent display) {
Robert Carrde96c8a2020-03-24 15:22:21 -07002080 if (!getHasBeenVisible()) {
Louis Changcdec0802019-11-11 11:45:07 +08002081 // Not ever visible to user.
2082 return;
2083 }
2084
2085 final int windowingMode = getWindowingMode();
2086 if (windowingMode != WINDOWING_MODE_FULLSCREEN
2087 && windowingMode != WINDOWING_MODE_FREEFORM) {
2088 return;
2089 }
2090
2091 // Don't persist state if display isn't in freeform mode. Then the task will be launched
2092 // back to its last state in a freeform display when it's launched in a freeform display
2093 // next time.
2094 if (getWindowConfiguration().getDisplayWindowingMode() != WINDOWING_MODE_FREEFORM) {
2095 return;
2096 }
2097
2098 // Saves the new state so that we can launch the activity at the same location.
Garfield Tan8b096b22020-01-07 14:55:20 -08002099 mStackSupervisor.mLaunchParamsPersister.saveTask(this, display);
Louis Changcdec0802019-11-11 11:45:07 +08002100 }
2101
2102 /**
2103 * Adjust bounds to stay within stack bounds.
2104 *
2105 * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
2106 * that keep them unchanged, but be contained within the stack bounds.
2107 *
2108 * @param bounds Bounds to be adjusted.
2109 * @param stackBounds Bounds within which the other bounds should remain.
2110 * @param overlapPxX The amount of px required to be visible in the X dimension.
2111 * @param overlapPxY The amount of px required to be visible in the Y dimension.
2112 */
2113 private static void fitWithinBounds(Rect bounds, Rect stackBounds, int overlapPxX,
2114 int overlapPxY) {
2115 if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
2116 return;
2117 }
2118
2119 // For each side of the parent (eg. left), check if the opposing side of the window (eg.
2120 // right) is at least overlap pixels away. If less, offset the window by that difference.
2121 int horizontalDiff = 0;
2122 // If window is smaller than overlap, use it's smallest dimension instead
2123 int overlapLR = Math.min(overlapPxX, bounds.width());
2124 if (bounds.right < (stackBounds.left + overlapLR)) {
2125 horizontalDiff = overlapLR - (bounds.right - stackBounds.left);
2126 } else if (bounds.left > (stackBounds.right - overlapLR)) {
2127 horizontalDiff = -(overlapLR - (stackBounds.right - bounds.left));
2128 }
2129 int verticalDiff = 0;
2130 int overlapTB = Math.min(overlapPxY, bounds.width());
2131 if (bounds.bottom < (stackBounds.top + overlapTB)) {
2132 verticalDiff = overlapTB - (bounds.bottom - stackBounds.top);
2133 } else if (bounds.top > (stackBounds.bottom - overlapTB)) {
2134 verticalDiff = -(overlapTB - (stackBounds.bottom - bounds.top));
2135 }
2136 bounds.offset(horizontalDiff, verticalDiff);
2137 }
2138
2139 /**
2140 * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
2141 * intersectBounds on a side, then the respective side will not be intersected.
2142 *
2143 * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
2144 * inset on that side is no-longer applicable. This scenario happens when a task's minimal
2145 * bounds are larger than the provided parent/display bounds.
2146 *
2147 * @param inOutBounds the bounds to intersect.
2148 * @param intersectBounds the bounds to intersect with.
2149 * @param intersectInsets insets to apply to intersectBounds before intersecting.
2150 */
2151 static void intersectWithInsetsIfFits(
2152 Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
2153 if (inOutBounds.right <= intersectBounds.right) {
2154 inOutBounds.right =
2155 Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
2156 }
2157 if (inOutBounds.bottom <= intersectBounds.bottom) {
2158 inOutBounds.bottom =
2159 Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
2160 }
2161 if (inOutBounds.left >= intersectBounds.left) {
2162 inOutBounds.left =
2163 Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
2164 }
2165 if (inOutBounds.top >= intersectBounds.top) {
2166 inOutBounds.top =
2167 Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
2168 }
2169 }
2170
2171 /**
2172 * Gets bounds with non-decor and stable insets applied respectively.
2173 *
2174 * If bounds overhangs the display, those edges will not get insets. See
2175 * {@link #intersectWithInsetsIfFits}
2176 *
2177 * @param outNonDecorBounds where to place bounds with non-decor insets applied.
2178 * @param outStableBounds where to place bounds with stable insets applied.
2179 * @param bounds the bounds to inset.
2180 */
2181 private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
2182 DisplayInfo displayInfo) {
2183 outNonDecorBounds.set(bounds);
2184 outStableBounds.set(bounds);
2185 if (getStack() == null || getStack().getDisplay() == null) {
2186 return;
2187 }
2188 DisplayPolicy policy = getStack().getDisplay().mDisplayContent.getDisplayPolicy();
2189 if (policy == null) {
2190 return;
2191 }
2192 mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
2193
2194 policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
2195 displayInfo.logicalHeight, displayInfo.displayCutout, mTmpInsets);
2196 intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);
2197
2198 policy.convertNonDecorInsetsToStableInsets(mTmpInsets, displayInfo.rotation);
2199 intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
2200 }
2201
Riddle Hsu23e18a92020-03-10 00:26:51 +08002202 /**
2203 * Forces the app bounds related configuration can be computed by
2204 * {@link #computeConfigResourceOverrides(Configuration, Configuration, DisplayInfo,
2205 * ActivityRecord.CompatDisplayInsets)}.
2206 */
2207 private static void invalidateAppBoundsConfig(@NonNull Configuration inOutConfig) {
2208 final Rect appBounds = inOutConfig.windowConfiguration.getAppBounds();
2209 if (appBounds != null) {
2210 appBounds.setEmpty();
2211 }
2212 inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
2213 inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
2214 }
2215
Louis Changcdec0802019-11-11 11:45:07 +08002216 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Riddle Hsu9264a272020-03-04 23:10:41 +08002217 @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo) {
2218 if (overrideDisplayInfo != null) {
2219 // Make sure the screen related configs can be computed by the provided display info.
Riddle Hsu9264a272020-03-04 23:10:41 +08002220 inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
Riddle Hsu23e18a92020-03-10 00:26:51 +08002221 invalidateAppBoundsConfig(inOutConfig);
Riddle Hsu9264a272020-03-04 23:10:41 +08002222 }
2223 computeConfigResourceOverrides(inOutConfig, parentConfig, overrideDisplayInfo,
2224 null /* compatInsets */);
2225 }
2226
2227 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Louis Changcdec0802019-11-11 11:45:07 +08002228 @NonNull Configuration parentConfig) {
Riddle Hsu9264a272020-03-04 23:10:41 +08002229 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
2230 null /* compatInsets */);
2231 }
2232
2233 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
2234 @NonNull Configuration parentConfig,
2235 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
Riddle Hsu23e18a92020-03-10 00:26:51 +08002236 if (compatInsets != null) {
2237 // Make sure the app bounds can be computed by the compat insets.
2238 invalidateAppBoundsConfig(inOutConfig);
2239 }
Riddle Hsu9264a272020-03-04 23:10:41 +08002240 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
2241 compatInsets);
Louis Changcdec0802019-11-11 11:45:07 +08002242 }
2243
2244 /**
2245 * Calculates configuration values used by the client to get resources. This should be run
2246 * using app-facing bounds (bounds unmodified by animations or transient interactions).
2247 *
2248 * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
2249 * configuring an "inherit-bounds" window which means that all configuration settings would
2250 * just be inherited from the parent configuration.
2251 **/
2252 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Riddle Hsu9264a272020-03-04 23:10:41 +08002253 @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo,
Louis Changcdec0802019-11-11 11:45:07 +08002254 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
2255 int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
2256 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2257 windowingMode = parentConfig.windowConfiguration.getWindowingMode();
2258 }
2259
2260 float density = inOutConfig.densityDpi;
2261 if (density == Configuration.DENSITY_DPI_UNDEFINED) {
2262 density = parentConfig.densityDpi;
2263 }
2264 density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
2265
Riddle Hsu1f931a592020-04-22 21:15:38 +08002266 // The bounds may have been overridden at this level. If the parent cannot cover these
2267 // bounds, the configuration is still computed according to the override bounds.
2268 final boolean insideParentBounds;
Evan Roskyc440b4e2020-04-17 15:11:22 -07002269
Riddle Hsu1f931a592020-04-22 21:15:38 +08002270 final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
Evan Rosky70213702019-11-05 10:26:24 -08002271 final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds();
Evan Roskyc440b4e2020-04-17 15:11:22 -07002272 if (resolvedBounds == null || resolvedBounds.isEmpty()) {
Riddle Hsu1f931a592020-04-22 21:15:38 +08002273 mTmpFullBounds.set(parentBounds);
2274 insideParentBounds = true;
Evan Rosky70213702019-11-05 10:26:24 -08002275 } else {
2276 mTmpFullBounds.set(resolvedBounds);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002277 insideParentBounds = parentBounds.contains(resolvedBounds);
Evan Rosky70213702019-11-05 10:26:24 -08002278 }
2279
Evan Roskye067ddf2020-04-24 18:28:25 -07002280 // Non-null compatibility insets means the activity prefers to keep its original size, so
2281 // out bounds doesn't need to be restricted by the parent or current display
2282 final boolean customContainerPolicy = compatInsets != null;
2283
Louis Changcdec0802019-11-11 11:45:07 +08002284 Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2285 if (outAppBounds == null || outAppBounds.isEmpty()) {
Evan Roskye067ddf2020-04-24 18:28:25 -07002286 // App-bounds hasn't been overridden, so calculate a value for it.
Evan Rosky70213702019-11-05 10:26:24 -08002287 inOutConfig.windowConfiguration.setAppBounds(mTmpFullBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002288 outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
Evan Roskye067ddf2020-04-24 18:28:25 -07002289
2290 if (!customContainerPolicy && windowingMode != WINDOWING_MODE_FREEFORM) {
2291 final Rect containingAppBounds;
2292 if (insideParentBounds) {
2293 containingAppBounds = parentConfig.windowConfiguration.getAppBounds();
2294 } else {
2295 // Restrict appBounds to display non-decor rather than parent because the
2296 // override bounds are beyond the parent. Otherwise, it won't match the
2297 // overridden bounds.
2298 final TaskDisplayArea displayArea = getDisplayArea();
2299 containingAppBounds = displayArea != null
2300 ? displayArea.getWindowConfiguration().getAppBounds() : null;
2301 }
2302 if (containingAppBounds != null && !containingAppBounds.isEmpty()) {
2303 outAppBounds.intersect(containingAppBounds);
2304 }
Louis Changcdec0802019-11-11 11:45:07 +08002305 }
2306 }
2307
2308 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
2309 || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
Riddle Hsu1f931a592020-04-22 21:15:38 +08002310 if (!customContainerPolicy && WindowConfiguration.isFloating(windowingMode)) {
jaehoon.kim643293e2019-11-08 06:36:28 +09002311 mTmpNonDecorBounds.set(mTmpFullBounds);
2312 mTmpStableBounds.set(mTmpFullBounds);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002313 } else if (!customContainerPolicy
Riddle Hsu9264a272020-03-04 23:10:41 +08002314 && (overrideDisplayInfo != null || getDisplayContent() != null)) {
2315 final DisplayInfo di = overrideDisplayInfo != null
2316 ? overrideDisplayInfo
2317 : getDisplayContent().getDisplayInfo();
Louis Changcdec0802019-11-11 11:45:07 +08002318
2319 // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
2320 // area, i.e. the screen area without the system bars.
2321 // The non decor inset are areas that could never be removed in Honeycomb. See
2322 // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
Evan Rosky70213702019-11-05 10:26:24 -08002323 calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di);
Louis Changcdec0802019-11-11 11:45:07 +08002324 } else {
2325 // Apply the given non-decor and stable insets to calculate the corresponding bounds
2326 // for screen size of configuration.
2327 int rotation = inOutConfig.windowConfiguration.getRotation();
2328 if (rotation == ROTATION_UNDEFINED) {
2329 rotation = parentConfig.windowConfiguration.getRotation();
2330 }
Riddle Hsu1f931a592020-04-22 21:15:38 +08002331 if (rotation != ROTATION_UNDEFINED && customContainerPolicy) {
Evan Rosky70213702019-11-05 10:26:24 -08002332 mTmpNonDecorBounds.set(mTmpFullBounds);
2333 mTmpStableBounds.set(mTmpFullBounds);
Riddle Hsue47501b2020-02-18 12:45:41 +08002334 compatInsets.getBoundsByRotation(mTmpBounds, rotation);
Louis Changcdec0802019-11-11 11:45:07 +08002335 intersectWithInsetsIfFits(mTmpNonDecorBounds, mTmpBounds,
2336 compatInsets.mNonDecorInsets[rotation]);
2337 intersectWithInsetsIfFits(mTmpStableBounds, mTmpBounds,
2338 compatInsets.mStableInsets[rotation]);
2339 outAppBounds.set(mTmpNonDecorBounds);
2340 } else {
2341 // Set to app bounds because it excludes decor insets.
2342 mTmpNonDecorBounds.set(outAppBounds);
2343 mTmpStableBounds.set(outAppBounds);
2344 }
2345 }
2346
2347 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
2348 final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002349 inOutConfig.screenWidthDp = (insideParentBounds && !customContainerPolicy)
Louis Changcdec0802019-11-11 11:45:07 +08002350 ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
2351 : overrideScreenWidthDp;
2352 }
2353 if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2354 final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002355 inOutConfig.screenHeightDp = (insideParentBounds && !customContainerPolicy)
Louis Changcdec0802019-11-11 11:45:07 +08002356 ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
2357 : overrideScreenHeightDp;
2358 }
2359
2360 if (inOutConfig.smallestScreenWidthDp
2361 == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2362 if (WindowConfiguration.isFloating(windowingMode)) {
2363 // For floating tasks, calculate the smallest width from the bounds of the task
2364 inOutConfig.smallestScreenWidthDp = (int) (
Evan Rosky70213702019-11-05 10:26:24 -08002365 Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density);
Louis Changcdec0802019-11-11 11:45:07 +08002366 }
2367 // otherwise, it will just inherit
2368 }
2369 }
2370
2371 if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
2372 inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
2373 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
2374 }
2375 if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
2376 // For calculating screen layout, we need to use the non-decor inset screen area for the
2377 // calculation for compatibility reasons, i.e. screen area without system bars that
2378 // could never go away in Honeycomb.
2379 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
2380 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Louis Changcdec0802019-11-11 11:45:07 +08002381 // Reducing the screen layout starting from its parent config.
Riddle Hsuca928562019-11-22 01:04:14 +08002382 inOutConfig.screenLayout = computeScreenLayoutOverride(parentConfig.screenLayout,
2383 compatScreenWidthDp, compatScreenHeightDp);
Louis Changcdec0802019-11-11 11:45:07 +08002384 }
2385 }
2386
Riddle Hsuca928562019-11-22 01:04:14 +08002387 /** Computes LONG, SIZE and COMPAT parts of {@link Configuration#screenLayout}. */
2388 static int computeScreenLayoutOverride(int sourceScreenLayout, int screenWidthDp,
2389 int screenHeightDp) {
2390 sourceScreenLayout = sourceScreenLayout
2391 & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
2392 final int longSize = Math.max(screenWidthDp, screenHeightDp);
2393 final int shortSize = Math.min(screenWidthDp, screenHeightDp);
2394 return Configuration.reduceScreenLayout(sourceScreenLayout, longSize, shortSize);
2395 }
2396
Louis Changcdec0802019-11-11 11:45:07 +08002397 @Override
2398 void resolveOverrideConfiguration(Configuration newParentConfig) {
2399 mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
Louis Changdff902b2020-03-31 13:32:47 +08002400 super.resolveOverrideConfiguration(newParentConfig);
2401
Louis Changcdec0802019-11-11 11:45:07 +08002402 int windowingMode =
Wale Ogunwale0d465192020-01-23 19:14:44 -08002403 getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
Evan Roskyc440b4e2020-04-17 15:11:22 -07002404
2405 // Resolve override windowing mode to fullscreen for home task (even on freeform
2406 // display), or split-screen if in split-screen mode.
Louis Changdff902b2020-03-31 13:32:47 +08002407 if (getActivityType() == ACTIVITY_TYPE_HOME && windowingMode == WINDOWING_MODE_UNDEFINED) {
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07002408 final int parentWindowingMode = newParentConfig.windowConfiguration.getWindowingMode();
Evan Roskyc440b4e2020-04-17 15:11:22 -07002409 windowingMode = WindowConfiguration.isSplitScreenWindowingMode(parentWindowingMode)
2410 ? parentWindowingMode : WINDOWING_MODE_FULLSCREEN;
Louis Changdff902b2020-03-31 13:32:47 +08002411 getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
2412 }
2413
Evan Roskyc440b4e2020-04-17 15:11:22 -07002414 if (isLeafTask()) {
Riddle Hsudd49c632020-04-30 22:39:51 +08002415 resolveLeafOnlyOverrideConfigs(newParentConfig, mTmpBounds /* previousBounds */);
Louis Changdff902b2020-03-31 13:32:47 +08002416 }
Evan Roskyc440b4e2020-04-17 15:11:22 -07002417 computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
2418 }
Louis Changdff902b2020-03-31 13:32:47 +08002419
Riddle Hsudd49c632020-04-30 22:39:51 +08002420 private void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig,
2421 Rect previousBounds) {
Evan Roskyc440b4e2020-04-17 15:11:22 -07002422 int windowingMode =
2423 getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
Louis Changcdec0802019-11-11 11:45:07 +08002424 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2425 windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
2426 }
2427 Rect outOverrideBounds =
2428 getResolvedOverrideConfiguration().windowConfiguration.getBounds();
2429
2430 if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
2431 computeFullscreenBounds(outOverrideBounds, null /* refActivity */,
2432 newParentConfig.windowConfiguration.getBounds(),
2433 newParentConfig.orientation);
Riddle Hsudd49c632020-04-30 22:39:51 +08002434 // The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
2435 // the parent or display is smaller than the size, the content may be cropped.
2436 return;
Louis Changcdec0802019-11-11 11:45:07 +08002437 }
2438
Riddle Hsudd49c632020-04-30 22:39:51 +08002439 adjustForMinimalTaskDimensions(outOverrideBounds, previousBounds, newParentConfig);
Louis Changcdec0802019-11-11 11:45:07 +08002440 if (windowingMode == WINDOWING_MODE_FREEFORM) {
2441 // by policy, make sure the window remains within parent somewhere
2442 final float density =
2443 ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;
2444 final Rect parentBounds =
2445 new Rect(newParentConfig.windowConfiguration.getBounds());
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002446 final DisplayContent display = getDisplayContent();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002447 if (display != null) {
Louis Changcdec0802019-11-11 11:45:07 +08002448 // If a freeform window moves below system bar, there is no way to move it again
2449 // by touch. Because its caption is covered by system bar. So we exclude them
2450 // from stack bounds. and then caption will be shown inside stable area.
2451 final Rect stableBounds = new Rect();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002452 display.getStableRect(stableBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002453 parentBounds.intersect(stableBounds);
2454 }
2455
2456 fitWithinBounds(outOverrideBounds, parentBounds,
2457 (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP),
2458 (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP));
2459
2460 // Prevent to overlap caption with stable insets.
2461 final int offsetTop = parentBounds.top - outOverrideBounds.top;
2462 if (offsetTop > 0) {
2463 outOverrideBounds.offset(0, offsetTop);
2464 }
2465 }
Louis Changcdec0802019-11-11 11:45:07 +08002466 }
2467
2468 /**
2469 * Compute bounds (letterbox or pillarbox) for
2470 * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the
2471 * orientation change and the requested orientation is different from the parent.
2472 */
2473 void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
2474 @NonNull Rect parentBounds, int parentOrientation) {
2475 // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
2476 outBounds.setEmpty();
2477 if (handlesOrientationChangeFromDescendant()) {
2478 return;
2479 }
2480 if (refActivity == null) {
2481 // Use the top activity as the reference of orientation. Don't include overlays because
2482 // it is usually not the actual content or just temporarily shown.
2483 // E.g. ForcedResizableInfoActivity.
Wale Ogunwale21e06482019-11-18 05:14:15 -08002484 refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
Louis Changcdec0802019-11-11 11:45:07 +08002485 }
2486
2487 // If the task or the reference activity requires a different orientation (either by
2488 // override or activityInfo), make it fit the available bounds by scaling down its bounds.
2489 final int overrideOrientation = getRequestedOverrideConfiguration().orientation;
2490 final int forcedOrientation =
2491 (overrideOrientation != ORIENTATION_UNDEFINED || refActivity == null)
2492 ? overrideOrientation : refActivity.getRequestedConfigurationOrientation();
2493 if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
2494 return;
2495 }
2496
2497 final int parentWidth = parentBounds.width();
2498 final int parentHeight = parentBounds.height();
2499 final float aspect = ((float) parentHeight) / parentWidth;
2500 if (forcedOrientation == ORIENTATION_LANDSCAPE) {
2501 final int height = (int) (parentWidth / aspect);
2502 final int top = parentBounds.centerY() - height / 2;
2503 outBounds.set(parentBounds.left, top, parentBounds.right, top + height);
2504 } else {
2505 final int width = (int) (parentHeight * aspect);
2506 final int left = parentBounds.centerX() - width / 2;
2507 outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
2508 }
2509 }
2510
2511 Rect updateOverrideConfigurationFromLaunchBounds() {
Louis Changa009c762020-02-26 11:21:31 +08002512 // If the task is controlled by another organized task, do not set override
2513 // configurations and let its parent (organized task) to control it;
Louis Chang06107a32020-04-06 11:55:46 +08002514 final Task rootTask = getRootTask();
2515 final Rect bounds = rootTask != this && rootTask.isOrganized() ? null : getLaunchBounds();
Louis Changcdec0802019-11-11 11:45:07 +08002516 setBounds(bounds);
2517 if (bounds != null && !bounds.isEmpty()) {
2518 // TODO: Review if we actually want to do this - we are setting the launch bounds
2519 // directly here.
2520 bounds.set(getRequestedOverrideBounds());
2521 }
2522 return bounds;
2523 }
2524
2525 /** Updates the task's bounds and override configuration to match what is expected for the
2526 * input stack. */
2527 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002528 final ActivityStack stack = getStack();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002529
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002530 if (stack != null && stack == inStack) {
Louis Changcdec0802019-11-11 11:45:07 +08002531 return;
2532 }
2533
2534 if (inStack.inFreeformWindowingMode()) {
2535 if (!isResizeable()) {
2536 throw new IllegalArgumentException("Can not position non-resizeable task="
2537 + this + " in stack=" + inStack);
2538 }
2539 if (!matchParentBounds()) {
2540 return;
2541 }
2542 if (mLastNonFullscreenBounds != null) {
2543 setBounds(mLastNonFullscreenBounds);
2544 } else {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002545 mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Louis Changcdec0802019-11-11 11:45:07 +08002546 }
2547 } else {
2548 setBounds(inStack.getRequestedOverrideBounds());
2549 }
2550 }
2551
2552 /** Returns the bounds that should be used to launch this task. */
2553 Rect getLaunchBounds() {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002554 final ActivityStack stack = getStack();
2555 if (stack == null) {
Louis Changcdec0802019-11-11 11:45:07 +08002556 return null;
2557 }
2558
2559 final int windowingMode = getWindowingMode();
2560 if (!isActivityTypeStandardOrUndefined()
2561 || windowingMode == WINDOWING_MODE_FULLSCREEN
2562 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002563 return isResizeable() ? stack.getRequestedOverrideBounds() : null;
Louis Changcdec0802019-11-11 11:45:07 +08002564 } else if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002565 return stack.getRequestedOverrideBounds();
Louis Changcdec0802019-11-11 11:45:07 +08002566 }
2567 return mLastNonFullscreenBounds;
2568 }
2569
Louis Changcdec0802019-11-11 11:45:07 +08002570 void setRootProcess(WindowProcessController proc) {
2571 clearRootProcess();
2572 if (intent != null
2573 && (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
2574 mRootProcess = proc;
2575 mRootProcess.addRecentTask(this);
2576 }
2577 }
2578
2579 void clearRootProcess() {
2580 if (mRootProcess != null) {
2581 mRootProcess.removeRecentTask(this);
2582 mRootProcess = null;
2583 }
2584 }
2585
Tiger Huanged6794e2019-05-07 20:07:59 +08002586 @Override
Craig Mautnerc00204b2013-03-05 15:02:14 -08002587 DisplayContent getDisplayContent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002588 // TODO: Why aren't we just using our own display content vs. parent's???
2589 final ActivityStack stack = getStack();
2590 return stack != null && stack != this
2591 ? stack.getDisplayContent() : super.getDisplayContent();
Wale Ogunwale8577a052019-10-26 23:22:34 -07002592 }
2593
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002594 int getDisplayId() {
2595 final DisplayContent dc = getDisplayContent();
2596 return dc != null ? dc.mDisplayId : INVALID_DISPLAY;
2597 }
2598
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002599 // TODO: Migrate callers to getRootTask()
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002600 ActivityStack getStack() {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002601 return (ActivityStack) getRootTask();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002602 }
2603
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002604 /** @return Id of root task. */
2605 int getRootTaskId() {
2606 return getRootTask().mTaskId;
2607 }
2608
2609 Task getRootTask() {
2610 final WindowContainer parent = getParent();
2611 if (parent == null) return this;
2612
2613 final Task parentTask = parent.asTask();
2614 return parentTask == null ? this : parentTask.getRootTask();
2615 }
2616
2617 // TODO(task-merge): Figure out what's the right thing to do for places that used it.
2618 boolean isRootTask() {
2619 return getRootTask() == this;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002620 }
2621
Louis Changfd5539e2020-02-04 14:34:24 +08002622 boolean isLeafTask() {
2623 for (int i = mChildren.size() - 1; i >= 0; --i) {
2624 if (mChildren.get(i).asTask() != null) {
2625 return false;
2626 }
2627 }
2628 return true;
2629 }
2630
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002631 int getDescendantTaskCount() {
2632 final int[] currentCount = {0};
2633 final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
2634 PooledLambda.__(Task.class), currentCount);
Wale Ogunwale0d465192020-01-23 19:14:44 -08002635 forAllLeafTasks(c, false /* traverseTopToBottom */);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002636 c.recycle();
2637 return currentCount[0];
2638 }
2639
Louis Chang6434be42020-04-10 17:39:35 +08002640 /**
2641 * Find next proper focusable stack and make it focused.
2642 * @return The stack that now got the focus, {@code null} if none found.
2643 */
2644 ActivityStack adjustFocusToNextFocusableTask(String reason) {
2645 return adjustFocusToNextFocusableTask(reason, false /* allowFocusSelf */,
2646 true /* moveParentsToTop */);
2647 }
2648
2649 /** Return the next focusable task by looking from the siblings and parent tasks */
2650 private Task getNextFocusableTask(boolean allowFocusSelf) {
2651 final WindowContainer parent = getParent();
2652 if (parent == null) {
2653 return null;
2654 }
2655
2656 final Task focusableTask = parent.getTask((task) -> (allowFocusSelf || task != this)
2657 && ((ActivityStack) task).isFocusableAndVisible());
2658 if (focusableTask == null && parent.asTask() != null) {
2659 return parent.asTask().getNextFocusableTask(allowFocusSelf);
2660 } else {
2661 return focusableTask;
2662 }
2663 }
2664
2665 /**
2666 * Find next proper focusable task and make it focused.
2667 * @param reason The reason of making the adjustment.
2668 * @param allowFocusSelf Is the focus allowed to remain on the same task.
2669 * @param moveParentsToTop Whether to move parents to top while making the task focused.
2670 * @return The root task that now got the focus, {@code null} if none found.
2671 */
2672 ActivityStack adjustFocusToNextFocusableTask(String reason, boolean allowFocusSelf,
2673 boolean moveParentsToTop) {
2674 ActivityStack focusableTask = (ActivityStack) getNextFocusableTask(allowFocusSelf);
2675 if (focusableTask == null) {
2676 focusableTask = mRootWindowContainer.getNextFocusableStack((ActivityStack) this,
2677 !allowFocusSelf);
2678 }
2679 if (focusableTask == null) {
2680 return null;
2681 }
2682
Louis Chang6434be42020-04-10 17:39:35 +08002683 final ActivityStack rootTask = (ActivityStack) focusableTask.getRootTask();
Louis Chang6434be42020-04-10 17:39:35 +08002684 if (!moveParentsToTop) {
2685 // Only move the next stack to top in its task container.
2686 WindowContainer parent = focusableTask.getParent();
2687 parent.positionChildAt(POSITION_TOP, focusableTask, false /* includingParents */);
2688 return rootTask;
2689 }
2690
wilsonshiha31e01f2020-04-24 11:41:29 +08002691 final String myReason = reason + " adjustFocusToNextFocusableStack";
2692 final ActivityRecord top = focusableTask.topRunningActivity();
2693 if (focusableTask.isActivityTypeHome() && (top == null || !top.mVisibleRequested)) {
2694 // If we will be focusing on the home stack next and its current top activity isn't
2695 // visible, then use the move the home stack task to top to make the activity visible.
2696 focusableTask.getDisplayArea().moveHomeActivityToTop(myReason);
2697 return rootTask;
2698 }
2699
Louis Chang6434be42020-04-10 17:39:35 +08002700 // Move the entire hierarchy to top with updating global top resumed activity
2701 // and focused application if needed.
2702 focusableTask.moveToFront(myReason);
2703 // Top display focused stack is changed, update top resumed activity if needed.
2704 if (rootTask.mResumedActivity != null) {
2705 mStackSupervisor.updateTopResumedActivityIfNeeded();
2706 // Set focused app directly because if the next focused activity is already resumed
2707 // (e.g. the next top activity is on a different display), there won't have activity
2708 // state change to update it.
2709 mAtmService.setResumedActivityUncheckLocked(rootTask.mResumedActivity, reason);
2710 }
2711 return rootTask;
2712 }
2713
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002714 /** Calculate the minimum possible position for a task that can be shown to the user.
2715 * The minimum position will be above all other tasks that can't be shown.
2716 * @param minPosition The minimum position the caller is suggesting.
2717 * We will start adjusting up from here.
2718 * @param size The size of the current task list.
2719 */
2720 // TODO: Move user to their own window container.
2721 private int computeMinUserPosition(int minPosition, int size) {
2722 while (minPosition < size) {
2723 final WindowContainer child = mChildren.get(minPosition);
2724 final boolean canShow = child.showToCurrentUser();
2725 if (canShow) {
2726 break;
2727 }
2728 minPosition++;
2729 }
2730 return minPosition;
2731 }
2732
2733 /** Calculate the maximum possible position for a task that can't be shown to the user.
2734 * The maximum position will be below all other tasks that can be shown.
2735 * @param maxPosition The maximum position the caller is suggesting.
2736 * We will start adjusting down from here.
2737 */
2738 // TODO: Move user to their own window container.
2739 private int computeMaxUserPosition(int maxPosition) {
2740 while (maxPosition > 0) {
2741 final WindowContainer child = mChildren.get(maxPosition);
2742 final boolean canShow = child.showToCurrentUser();
2743 if (!canShow) {
2744 break;
2745 }
2746 maxPosition--;
2747 }
2748 return maxPosition;
2749 }
2750
2751 private int getAdjustedChildPosition(WindowContainer wc, int suggestedPosition) {
2752 final boolean canShowChild = wc.showToCurrentUser();
2753
2754 final int size = mChildren.size();
2755
2756 // Figure-out min/max possible position depending on if child can show for current user.
2757 int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0;
2758 int maxPosition = (canShowChild) ? size : computeMaxUserPosition(size - 1);
2759
2760 // Factor in always-on-top children in max possible position.
2761 if (!wc.isAlwaysOnTop()) {
2762
2763 // We want to place all non-always-on-top containers below always-on-top ones.
2764 while (maxPosition > minPosition) {
2765 if (!mChildren.get(maxPosition - 1).isAlwaysOnTop()) break;
2766 --maxPosition;
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002767 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002768 }
2769
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002770 // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
2771 if (suggestedPosition == POSITION_BOTTOM && minPosition == 0) {
2772 return POSITION_BOTTOM;
Louis Changa009c762020-02-26 11:21:31 +08002773 } else if (suggestedPosition == POSITION_TOP && maxPosition >= (size - 1)) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002774 return POSITION_TOP;
2775 }
2776 // Reset position based on minimum/maximum possible positions.
2777 return Math.min(Math.max(suggestedPosition, minPosition), maxPosition);
Craig Mautnerc00204b2013-03-05 15:02:14 -08002778 }
2779
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002780 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002781 void positionChildAt(int position, WindowContainer child, boolean includingParents) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002782 position = getAdjustedChildPosition(child, position);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002783 super.positionChildAt(position, child, includingParents);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002784
2785 // Log positioning.
2786 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "positionChildAt: child=" + child
2787 + " position=" + position + " parent=" + this);
2788
2789 final int toTop = position >= (mChildren.size() - 1) ? 1 : 0;
2790 final Task task = child.asTask();
2791 if (task != null) {
2792 EventLogTags.writeWmTaskMoved(task.mTaskId, toTop, position);
2793 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002794 }
2795
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002796 @VisibleForTesting
2797 boolean hasWindowsAlive() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002798 return getActivity(ActivityRecord::hasWindowsAlive) != null;
Chong Zhang7e8eeb72016-01-06 19:14:47 -08002799 }
2800
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002801 @VisibleForTesting
2802 boolean shouldDeferRemoval() {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02002803 if (mChildren.isEmpty()) {
2804 // No reason to defer removal of a Task that doesn't have any child.
2805 return false;
2806 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002807 return hasWindowsAlive() && getStack().isAnimating(TRANSITION | CHILDREN);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002808 }
2809
Wale Ogunwalef6192862016-09-10 13:42:30 -07002810 @Override
Andrii Kulian45a61fe2017-01-05 16:53:19 -08002811 void removeImmediately() {
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08002812 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
Jeff Changd136e772019-11-05 20:33:52 +08002813 EventLogTags.writeWmTaskRemoved(mTaskId, "removeTask");
Robert Carr8a2f9132019-11-11 15:03:15 -08002814
2815 // If applicable let the TaskOrganizer know the Task is vanishing.
2816 setTaskOrganizer(null);
2817
Andrii Kulian45a61fe2017-01-05 16:53:19 -08002818 super.removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -08002819 }
2820
Louis Changcdec0802019-11-11 11:45:07 +08002821 // TODO: Consolidate this with Task.reparent()
Louis Changdc077272019-11-12 16:52:56 +08002822 void reparent(ActivityStack stack, int position, boolean moveParents, String reason) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -08002823 if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002824 + " from stack=" + getStack());
Louis Chang074cdf22019-12-13 13:15:13 +08002825 EventLogTags.writeWmTaskRemoved(mTaskId, "reParentTask:" + reason);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002826
2827 reparent(stack, position);
2828
Louis Changcdec0802019-11-11 11:45:07 +08002829 stack.positionChildAt(position, this, moveParents);
Andrii Kulian7cd7c2d2017-01-18 12:14:37 -08002830
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002831 // If we are moving from the fullscreen stack to the pinned stack then we want to preserve
2832 // our insets so that there will not be a jump in the area covered by system decorations.
2833 // We rely on the pinned animation to later unset this value.
2834 mPreserveNonFloatingState = stack.inPinnedWindowingMode();
Wale Ogunwale53a29a92015-02-23 15:42:52 -08002835 }
2836
Bryce Leef3c6a472017-11-14 14:53:06 -08002837 public int setBounds(Rect bounds, boolean forceResize) {
2838 final int boundsChanged = setBounds(bounds);
2839
2840 if (forceResize && (boundsChanged & BOUNDS_CHANGE_SIZE) != BOUNDS_CHANGE_SIZE) {
2841 onResize();
2842 return BOUNDS_CHANGE_SIZE | boundsChanged;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002843 }
Wale Ogunwale68278562017-09-23 17:13:55 -07002844
Bryce Leef3c6a472017-11-14 14:53:06 -08002845 return boundsChanged;
2846 }
2847
2848 /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
2849 @Override
2850 public int setBounds(Rect bounds) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002851 int rotation = Surface.ROTATION_0;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002852 final DisplayContent displayContent = getStack() != null
2853 ? getStack().getDisplayContent() : null;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002854 if (displayContent != null) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002855 rotation = displayContent.getDisplayInfo().rotation;
Wale Ogunwale2cc92f52015-09-09 13:12:10 -07002856 }
2857
Bryce Leef3c6a472017-11-14 14:53:06 -08002858 final int boundsChange = super.setBounds(bounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002859 mRotation = rotation;
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002860 updateSurfacePosition();
Wale Ogunwale2cc92f52015-09-09 13:12:10 -07002861 return boundsChange;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002862 }
2863
Garfield Tan90b04282018-12-11 14:04:42 -08002864 @Override
2865 public boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
2866 ConfigurationContainer requestingContainer) {
2867 if (super.onDescendantOrientationChanged(freezeDisplayToken, requestingContainer)) {
2868 return true;
2869 }
2870
2871 // No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
2872 // it if possible.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002873 if (getParent() != null) {
2874 onConfigurationChanged(getParent().getConfiguration());
Garfield Tan90b04282018-12-11 14:04:42 -08002875 return true;
2876 }
2877 return false;
2878 }
2879
Yunfan Chen0e7aff92018-12-05 16:35:32 -08002880 void resize(boolean relayout, boolean forced) {
2881 if (setBounds(getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE && relayout) {
2882 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
2883 }
2884 }
2885
Louis Chang7501e332018-08-20 13:08:39 +08002886 @Override
2887 void onDisplayChanged(DisplayContent dc) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002888 final boolean isRootTask = isRootTask();
2889 if (!isRootTask) {
2890 adjustBoundsForDisplayChangeIfNeeded(dc);
2891 }
Louis Chang7501e332018-08-20 13:08:39 +08002892 super.onDisplayChanged(dc);
Yuncheol Heo1c211c22020-04-20 13:08:43 -07002893 if (isLeafTask()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002894 final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY;
2895 mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged(
2896 mTaskId, displayId);
2897 }
Louis Chang7501e332018-08-20 13:08:39 +08002898 }
2899
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002900 boolean isResizeable(boolean checkSupportsPip) {
2901 return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
2902 || (checkSupportsPip && mSupportsPictureInPicture));
Chong Zhangb15758a2015-11-17 12:12:03 -08002903 }
2904
2905 boolean isResizeable() {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002906 return isResizeable(true /* checkSupportsPip */);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002907 }
2908
skuhne@google.com322347b2016-12-02 12:54:03 -08002909 /**
2910 * Tests if the orientation should be preserved upon user interactive resizig operations.
2911
2912 * @return true if orientation should not get changed upon resizing operation.
2913 */
2914 boolean preserveOrientationOnResize() {
2915 return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
2916 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
2917 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
2918 }
2919
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002920 boolean cropWindowsToStackBounds() {
Wale Ogunwaledf241e92016-10-13 15:14:21 -07002921 return isResizeable();
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002922 }
2923
Jorim Jaggi0429f352015-12-22 16:29:16 +01002924 /**
2925 * Prepares the task bounds to be frozen with the current size. See
Garfield Tane8d84ab2019-10-11 09:49:40 -07002926 * {@link ActivityRecord#freezeBounds}.
Jorim Jaggi0429f352015-12-22 16:29:16 +01002927 */
2928 void prepareFreezingBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08002929 mPreparedFrozenBounds.set(getBounds());
Andrii Kulian441e4492016-09-29 15:25:00 -07002930 mPreparedFrozenMergedConfig.setTo(getConfiguration());
Jorim Jaggi0429f352015-12-22 16:29:16 +01002931 }
2932
Issei Suzukiad287d02019-10-31 16:19:44 +01002933 @Override
2934 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2935 Rect outSurfaceInsets) {
2936 final WindowState windowState = getTopVisibleAppMainWindow();
2937 if (windowState != null) {
2938 windowState.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2939 } else {
2940 super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2941 }
2942 }
2943
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002944 /**
2945 * Calculate the maximum visible area of this task. If the task has only one app,
2946 * the result will be visible frame of that app. If the task has more than one apps,
2947 * we search from top down if the next app got different visible area.
2948 *
2949 * This effort is to handle the case where some task (eg. GMail composer) might pop up
2950 * a dialog that's different in size from the activity below, in which case we should
2951 * be dimming the entire task area behind the dialog.
2952 *
2953 * @param out Rect containing the max visible bounds.
2954 * @return true if the task has some visible app windows; false otherwise.
2955 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002956 private static void getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop) {
2957 // skip hidden (or about to hide) apps
2958 if (token.mIsExiting || !token.isClientVisible() || !token.mVisibleRequested) {
2959 return;
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002960 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002961 final WindowState win = token.findMainWindow();
2962 if (win == null) {
2963 return;
2964 }
2965 if (!foundTop[0]) {
2966 foundTop[0] = true;
2967 out.setEmpty();
2968 }
2969
2970 win.getMaxVisibleBounds(out);
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002971 }
2972
2973 /** Bounds of the task to be used for dimming, as well as touch related tests. */
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002974 void getDimBounds(Rect out) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002975 final DisplayContent displayContent = getStack().getDisplayContent();
Robert Carra86a6bf2016-04-08 17:34:16 -07002976 // It doesn't matter if we in particular are part of the resize, since we couldn't have
2977 // a DimLayer anyway if we weren't visible.
Wale Ogunwalef6192862016-09-10 13:42:30 -07002978 final boolean dockedResizing = displayContent != null
2979 && displayContent.mDividerControllerLocked.isResizing();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002980 if (inFreeformWindowingMode()) {
2981 boolean[] foundTop = { false };
2982 final PooledConsumer c = PooledLambda.obtainConsumer(Task::getMaxVisibleBounds,
2983 PooledLambda.__(ActivityRecord.class), out, foundTop);
Vishnu Nair4d7a6002020-01-23 14:34:40 -08002984 forAllActivities(c);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002985 c.recycle();
2986 if (foundTop[0]) {
2987 return;
2988 }
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002989 }
2990
Evan Rosky4fb1e912019-03-06 13:54:43 -08002991 if (!matchParentBounds()) {
2992 // When minimizing the docked stack when going home, we don't adjust the task bounds
2993 // so we need to intersect the task bounds with the stack bounds here.
2994 //
2995 // If we are Docked Resizing with snap points, the task bounds could be smaller than the
2996 // stack bounds and so we don't even want to use them. Even if the app should not be
2997 // resized the Dim should keep up with the divider.
2998 if (dockedResizing) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002999 getStack().getBounds(out);
Evan Rosky4fb1e912019-03-06 13:54:43 -08003000 } else {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003001 getStack().getBounds(mTmpRect);
Evan Rosky4fb1e912019-03-06 13:54:43 -08003002 mTmpRect.intersect(getBounds());
3003 out.set(mTmpRect);
3004 }
3005 } else {
3006 out.set(getBounds());
Wale Ogunwalef6192862016-09-10 13:42:30 -07003007 }
Evan Rosky4fb1e912019-03-06 13:54:43 -08003008 return;
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08003009 }
3010
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003011 void setDragResizing(boolean dragResizing, int dragResizeMode) {
Jorim Jaggic662d8e2016-02-05 16:54:54 -08003012 if (mDragResizing != dragResizing) {
chaviw8c9d1f52018-07-25 14:56:07 -07003013 // No need to check if the mode is allowed if it's leaving dragResize
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003014 if (dragResizing && !DragResizeMode.isModeAllowedForStack(getStack(), dragResizeMode)) {
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003015 throw new IllegalArgumentException("Drag resize mode not allow for stack stackId="
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003016 + getRootTaskId() + " dragResizeMode=" + dragResizeMode);
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003017 }
Jorim Jaggic662d8e2016-02-05 16:54:54 -08003018 mDragResizing = dragResizing;
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003019 mDragResizeMode = dragResizeMode;
Jorim Jaggic662d8e2016-02-05 16:54:54 -08003020 resetDragResizingChangeReported();
3021 }
3022 }
3023
Chong Zhang3005e752015-09-18 18:46:28 -07003024 boolean isDragResizing() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07003025 return mDragResizing;
Chong Zhang3005e752015-09-18 18:46:28 -07003026 }
3027
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003028 int getDragResizeMode() {
3029 return mDragResizeMode;
3030 }
3031
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003032 void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003033 if (displayContent == null) {
3034 return;
3035 }
Bryce Leef3c6a472017-11-14 14:53:06 -08003036 if (matchParentBounds()) {
Wale Ogunwale68278562017-09-23 17:13:55 -07003037 // TODO: Yeah...not sure if this works with WindowConfiguration, but shouldn't be a
3038 // problem once we move mBounds into WindowConfiguration.
Bryce Leef3c6a472017-11-14 14:53:06 -08003039 setBounds(null);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003040 return;
3041 }
Garfield Tandec96db2018-10-30 11:28:49 -07003042 final int displayId = displayContent.getDisplayId();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003043 final int newRotation = displayContent.getDisplayInfo().rotation;
Garfield Tandec96db2018-10-30 11:28:49 -07003044 if (displayId != mLastRotationDisplayId) {
3045 // This task is on a display that it wasn't on. There is no point to keep the relative
3046 // position if display rotations for old and new displays are different. Just keep these
3047 // values.
3048 mLastRotationDisplayId = displayId;
3049 mRotation = newRotation;
3050 return;
3051 }
3052
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003053 if (mRotation == newRotation) {
Garfield Tandec96db2018-10-30 11:28:49 -07003054 // Rotation didn't change. We don't need to adjust the bounds to keep the relative
3055 // position.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003056 return;
3057 }
3058
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003059 // Device rotation changed.
Chong Zhang2e2c81a2016-07-15 11:28:17 -07003060 // - We don't want the task to move around on the screen when this happens, so update the
3061 // task bounds so it stays in the same place.
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003062 // - Rotate the bounds and notify activity manager if the task can be resized independently
Chong Zhang2e2c81a2016-07-15 11:28:17 -07003063 // from its stack. The stack will take care of task rotation for the other case.
Bryce Leef3c6a472017-11-14 14:53:06 -08003064 mTmpRect2.set(getBounds());
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003065
Wale Ogunwale3382ab12017-07-27 08:55:03 -07003066 if (!getWindowConfiguration().canResizeTask()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08003067 setBounds(mTmpRect2);
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003068 return;
3069 }
3070
Wale Ogunwale94744212015-09-21 19:01:47 -07003071 displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
Bryce Leef3c6a472017-11-14 14:53:06 -08003072 if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003073 mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
Wale Ogunwale1ed0d892015-09-28 13:27:44 -07003074 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003075 }
3076
Wale Ogunwalef6192862016-09-10 13:42:30 -07003077 /** Cancels any running app transitions associated with the task. */
Winsonc28098f2015-10-30 14:50:19 -07003078 void cancelTaskWindowTransition() {
Wale Ogunwalef6192862016-09-10 13:42:30 -07003079 for (int i = mChildren.size() - 1; i >= 0; --i) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003080 mChildren.get(i).cancelAnimation();
Winsonc28098f2015-10-30 14:50:19 -07003081 }
3082 }
3083
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07003084 boolean showForAllUsers() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003085 if (mChildren.isEmpty()) return false;
3086 final ActivityRecord r = getTopNonFinishingActivity();
3087 return r != null && r.mShowForAllUsers;
Jorim Jaggiff71d202016-04-14 13:12:36 -07003088 }
3089
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08003090 @Override
3091 boolean showToCurrentUser() {
Louis Changedbda502020-04-27 15:51:42 +08003092 return mForceShowForAllUsers || showForAllUsers()
3093 || mWmService.isCurrentProfile(getTopMostTask().mUserId);
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08003094 }
3095
3096 void setForceShowForAllUsers(boolean forceShowForAllUsers) {
3097 mForceShowForAllUsers = forceShowForAllUsers;
3098 }
3099
Evan Rosky688c8382020-04-03 17:27:08 -07003100 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003101 public boolean isAttached() {
Andrii Kulian86d676c2020-03-27 19:34:54 -07003102 final TaskDisplayArea taskDisplayArea = getDisplayArea();
3103 return taskDisplayArea != null && !taskDisplayArea.isRemoved();
3104 }
3105
3106 @Override
3107 @Nullable
3108 TaskDisplayArea getDisplayArea() {
3109 return (TaskDisplayArea) super.getDisplayArea();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003110 }
3111
Robert Carr7e4c90e2017-02-15 19:52:38 -08003112 /**
3113 * When we are in a floating stack (Freeform, Pinned, ...) we calculate
3114 * insets differently. However if we are animating to the fullscreen stack
3115 * we need to begin calculating insets as if we were fullscreen, otherwise
3116 * we will have a jump at the end.
3117 */
Robert Carre6275582016-02-29 15:45:45 -08003118 boolean isFloating() {
Hongwei Wang85cf41f2020-01-15 15:14:47 -08003119 return getWindowConfiguration().tasksAreFloating() && !mPreserveNonFloatingState;
Robert Carre6275582016-02-29 15:45:45 -08003120 }
3121
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003122 /**
3123 * Returns true if the stack is translucent and can have other contents visible behind it if
3124 * needed. A stack is considered translucent if it don't contain a visible or
3125 * starting (about to be visible) activity that is fullscreen (opaque).
3126 * @param starting The currently starting activity or null if there is none.
3127 */
3128 @VisibleForTesting
3129 boolean isTranslucent(ActivityRecord starting) {
Robert Carrf6878a42019-12-18 02:13:12 -08003130 if (!isAttached() || isForceHidden()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003131 return true;
3132 }
3133 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isOpaqueActivity,
3134 PooledLambda.__(ActivityRecord.class), starting);
3135 final ActivityRecord opaque = getActivity(p);
3136 p.recycle();
3137 return opaque == null;
3138 }
3139
3140 private static boolean isOpaqueActivity(ActivityRecord r, ActivityRecord starting) {
3141 if (r.finishing) {
3142 // We don't factor in finishing activities when determining translucency since
3143 // they will be gone soon.
3144 return false;
3145 }
3146
3147 if (!r.visibleIgnoringKeyguard && r != starting) {
3148 // Also ignore invisible activities that are not the currently starting
3149 // activity (about to be visible).
3150 return false;
3151 }
3152
3153 if (r.occludesParent() || r.hasWallpaper) {
3154 // Stack isn't translucent if it has at least one fullscreen activity
3155 // that is visible.
3156 return true;
3157 }
3158 return false;
3159 }
3160
Winson Chungd41f71d2018-03-16 15:26:07 -07003161 @Override
3162 public SurfaceControl getAnimationLeashParent() {
Riddle Hsud8302832019-09-23 21:14:07 +08003163 if (WindowManagerService.sHierarchicalAnimations) {
Issei Suzuki71142152019-08-15 14:39:40 +02003164 return super.getAnimationLeashParent();
3165 }
Winson Chung732446a2018-09-19 13:15:17 -07003166 // Currently, only the recents animation will create animation leashes for tasks. In this
3167 // case, reparent the task to the home animation layer while it is being animated to allow
3168 // the home activity to reorder the app windows relative to its own.
3169 return getAppAnimationLayer(ANIMATION_LAYER_HOME);
Winson Chungd41f71d2018-03-16 15:26:07 -07003170 }
3171
lumark5341d1c2019-12-14 01:54:02 +08003172 @Override
3173 Rect getAnimationBounds(int appStackClipMode) {
3174 // TODO(b/131661052): we should remove appStackClipMode with hierarchical animations.
3175 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
3176 // Using the stack bounds here effectively applies the clipping before animation.
3177 return getStack().getBounds();
3178 }
3179 return super.getAnimationBounds(appStackClipMode);
3180 }
3181
lumark19a5d2e2019-10-11 16:19:30 +08003182 boolean shouldAnimate() {
Robert Carr8a2f9132019-11-11 15:03:15 -08003183 /**
3184 * Animations are handled by the TaskOrganizer implementation.
3185 */
Wale Ogunwaledec34082020-03-22 09:45:00 -07003186 if (isOrganized()) {
Robert Carr8a2f9132019-11-11 15:03:15 -08003187 return false;
3188 }
lumark19a5d2e2019-10-11 16:19:30 +08003189 // Don't animate while the task runs recents animation but only if we are in the mode
3190 // where we cancel with deferred screenshot, which means that the controller has
3191 // transformed the task.
3192 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
3193 if (controller != null && controller.isAnimatingTask(this)
3194 && controller.shouldDeferCancelUntilNextTransition()) {
3195 return false;
3196 }
3197 return true;
3198 }
3199
Evan Rosky9020c072018-12-06 14:11:12 -08003200 @Override
Vishnu Nairfd6fb672020-02-14 12:56:37 -08003201 void onSurfaceShown(SurfaceControl.Transaction t) {
3202 super.onSurfaceShown(t);
3203 t.unsetColor(mSurfaceControl);
3204 }
3205
3206 @Override
Evan Rosky9020c072018-12-06 14:11:12 -08003207 SurfaceControl.Builder makeSurface() {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08003208 return super.makeSurface().setColorLayer().setMetadata(METADATA_TASK_ID, mTaskId);
Evan Rosky9020c072018-12-06 14:11:12 -08003209 }
3210
Winson Chungd41f71d2018-03-16 15:26:07 -07003211 boolean isTaskAnimating() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003212 final RecentsAnimationController recentsAnim = mWmService.getRecentsAnimationController();
Winson Chungd41f71d2018-03-16 15:26:07 -07003213 if (recentsAnim != null) {
3214 if (recentsAnim.isAnimatingTask(this)) {
3215 return true;
3216 }
3217 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003218 return forAllTasks((t) -> { return t != this && t.isTaskAnimating(); });
Winson Chungd41f71d2018-03-16 15:26:07 -07003219 }
3220
lumark19a5d2e2019-10-11 16:19:30 +08003221 @Override
3222 RemoteAnimationTarget createRemoteAnimationTarget(
3223 RemoteAnimationController.RemoteAnimationRecord record) {
lumark5341d1c2019-12-14 01:54:02 +08003224 final ActivityRecord activity = getTopMostActivity();
lumark19a5d2e2019-10-11 16:19:30 +08003225 return activity != null ? activity.createRemoteAnimationTarget(record) : null;
3226 }
3227
Daichi Hirono8ecfc6b2020-02-18 16:28:03 +09003228 @Override
3229 boolean canCreateRemoteAnimationTarget() {
3230 return true;
3231 }
3232
Chong Zhangd8ceb852015-11-11 14:53:41 -08003233 WindowState getTopVisibleAppMainWindow() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003234 final ActivityRecord activity = getTopVisibleActivity();
3235 return activity != null ? activity.findMainWindow() : null;
Chong Zhang9184ec62015-09-24 12:32:21 -07003236 }
3237
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003238 ActivityRecord topRunningActivity() {
3239 return topRunningActivity(false /* focusableOnly */);
3240 }
3241
3242 ActivityRecord topRunningActivity(boolean focusableOnly) {
3243 // Split into 2 to avoid object creation due to variable capture.
3244 if (focusableOnly) {
3245 return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
3246 } else {
3247 return getActivity(ActivityRecord::canBeTopRunning);
3248 }
3249 }
3250
3251 ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
3252 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunningNonDelayed
3253 , PooledLambda.__(ActivityRecord.class), notTop);
3254 final ActivityRecord r = getActivity(p);
3255 p.recycle();
3256 return r;
3257 }
3258
3259 private static boolean isTopRunningNonDelayed(ActivityRecord r, ActivityRecord notTop) {
3260 return !r.delayedResume && r != notTop && r.canBeTopRunning();
3261 }
3262
3263 /**
3264 * This is a simplified version of topRunningActivity that provides a number of
3265 * optional skip-over modes. It is intended for use with the ActivityController hook only.
3266 *
3267 * @param token If non-null, any history records matching this token will be skipped.
3268 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
3269 *
3270 * @return Returns the HistoryRecord of the next activity on the stack.
3271 */
3272 ActivityRecord topRunningActivity(IBinder token, int taskId) {
3273 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunning,
3274 PooledLambda.__(ActivityRecord.class), taskId, token);
3275 final ActivityRecord r = getActivity(p);
3276 p.recycle();
3277 return r;
3278 }
3279
3280 private static boolean isTopRunning(ActivityRecord r, int taskId, IBinder notTop) {
3281 return r.getTask().mTaskId != taskId && r.appToken != notTop && r.canBeTopRunning();
3282 }
3283
Garfield Tane8d84ab2019-10-11 09:49:40 -07003284 ActivityRecord getTopFullscreenActivity() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003285 return getActivity((r) -> {
3286 final WindowState win = r.findMainWindow();
3287 return (win != null && win.mAttrs.isFullscreen());
3288 });
Jorim Jaggie6c6ecb2017-07-20 18:09:20 +02003289 }
3290
Garfield Tane8d84ab2019-10-11 09:49:40 -07003291 ActivityRecord getTopVisibleActivity() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003292 return getActivity((r) -> {
3293 // skip hidden (or about to hide) apps
3294 return !r.mIsExiting && r.isClientVisible() && r.mVisibleRequested;
3295 });
Chong Zhangbef461f2015-10-27 11:38:24 -07003296 }
3297
Winson Chungb5ce37c2020-04-22 10:08:28 -07003298 boolean isTopActivityFocusable() {
3299 final ActivityRecord r = topRunningActivity();
3300 return r != null ? r.isFocusable()
3301 : (isFocusable() && getWindowConfiguration().canReceiveKeys());
3302 }
3303
3304 boolean isFocusableAndVisible() {
3305 return isTopActivityFocusable() && shouldBeVisible(null /* starting */);
3306 }
3307
Wale Ogunwale3198da42019-10-10 14:45:03 +02003308 void positionChildAtTop(ActivityRecord child) {
3309 positionChildAt(child, POSITION_TOP);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003310 }
3311
Wale Ogunwale3198da42019-10-10 14:45:03 +02003312 void positionChildAt(ActivityRecord child, int position) {
3313 if (child == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003314 Slog.w(TAG_WM,
3315 "Attempted to position of non-existing app");
3316 return;
3317 }
3318
Wale Ogunwale3198da42019-10-10 14:45:03 +02003319 positionChildAt(position, child, false /* includeParents */);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003320 }
3321
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003322 void forceWindowsScaleable(boolean force) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003323 mWmService.openSurfaceTransaction();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003324 try {
Wale Ogunwalef6192862016-09-10 13:42:30 -07003325 for (int i = mChildren.size() - 1; i >= 0; i--) {
3326 mChildren.get(i).forceWindowsScaleableInTransaction(force);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003327 }
3328 } finally {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003329 mWmService.closeSurfaceTransaction("forceWindowsScaleable");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003330 }
3331 }
3332
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01003333 void setTaskDescription(TaskDescription taskDescription) {
3334 mTaskDescription = taskDescription;
3335 }
3336
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003337 void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003338 mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
3339 mTaskId, snapshot);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003340 }
3341
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01003342 TaskDescription getTaskDescription() {
3343 return mTaskDescription;
3344 }
3345
Wale Ogunwalef6192862016-09-10 13:42:30 -07003346 @Override
Riddle Hsu9a8e3ae2020-03-24 15:22:48 +08003347 int getOrientation(int candidate) {
3348 return canSpecifyOrientation() ? super.getOrientation(candidate) : SCREEN_ORIENTATION_UNSET;
3349 }
3350
3351 private boolean canSpecifyOrientation() {
3352 final int windowingMode = getWindowingMode();
3353 final int activityType = getActivityType();
3354 return windowingMode == WINDOWING_MODE_FULLSCREEN
3355 || activityType == ACTIVITY_TYPE_HOME
3356 || activityType == ACTIVITY_TYPE_RECENTS
3357 || activityType == ACTIVITY_TYPE_ASSISTANT;
3358 }
3359
3360 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07003361 boolean fillsParent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003362 return matchParentBounds();
3363 }
3364
Jeff Changdc9c1d42020-02-11 14:57:34 +08003365 @Override
Wale Ogunwale0d465192020-01-23 19:14:44 -08003366 void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
3367 final int count = mChildren.size();
3368 boolean isLeafTask = true;
3369 if (traverseTopToBottom) {
3370 for (int i = count - 1; i >= 0; --i) {
3371 final Task child = mChildren.get(i).asTask();
3372 if (child != null) {
3373 isLeafTask = false;
3374 child.forAllLeafTasks(callback, traverseTopToBottom);
3375 }
3376 }
3377 } else {
3378 for (int i = 0; i < count; i++) {
3379 final Task child = mChildren.get(i).asTask();
3380 if (child != null) {
3381 isLeafTask = false;
3382 child.forAllLeafTasks(callback, traverseTopToBottom);
3383 }
3384 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003385 }
Wale Ogunwale0d465192020-01-23 19:14:44 -08003386 if (isLeafTask) callback.accept(this);
Wale Ogunwale51362492016-09-08 17:49:17 -07003387 }
3388
Jorim Jaggi329a5832017-01-05 18:57:12 +01003389 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003390 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08003391 super.forAllTasks(callback, traverseTopToBottom);
3392 callback.accept(this);
Jorim Jaggi51304d72017-05-17 17:25:32 +02003393 }
3394
lumarkbc0032a2019-11-01 21:38:13 +08003395 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003396 boolean forAllTasks(Function<Task, Boolean> callback) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003397 if (super.forAllTasks(callback)) return true;
lumarkbc0032a2019-11-01 21:38:13 +08003398 return callback.apply(this);
3399 }
3400
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003401 @Override
3402 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003403 final Task t = super.getTask(callback, traverseTopToBottom);
3404 if (t != null) return t;
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003405 return callback.test(this) ? this : null;
3406 }
3407
Jorim Jaggi50bf59c2018-03-09 17:29:48 +01003408 /**
3409 * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
3410 * flags. See {@link WindowState#canAffectSystemUiFlags()}.
3411 */
3412 void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) {
3413 mCanAffectSystemUiFlags = canAffectSystemUiFlags;
3414 }
3415
3416 /**
3417 * @see #setCanAffectSystemUiFlags
3418 */
3419 boolean canAffectSystemUiFlags() {
3420 return mCanAffectSystemUiFlags;
3421 }
3422
chaviw87ca63a2018-03-26 14:06:17 -07003423 void dontAnimateDimExit() {
3424 mDimmer.dontAnimateExit();
3425 }
3426
Wale Ogunwale9adfe572016-09-08 20:43:58 -07003427 String getName() {
Louis Changcdec0802019-11-11 11:45:07 +08003428 return "Task=" + mTaskId;
Wale Ogunwale9adfe572016-09-08 20:43:58 -07003429 }
3430
Robert Carr18f622f2017-05-08 11:20:43 -07003431 void clearPreserveNonFloatingState() {
3432 mPreserveNonFloatingState = false;
3433 }
3434
chaviw2fb06bc2018-01-19 17:09:15 -08003435 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07003436 Dimmer getDimmer() {
chaviw51e4c2f2020-04-03 13:49:45 -07003437 // If the window is in multi-window mode, we want to dim at the Task level to ensure the dim
3438 // bounds match the area the app lives in
3439 if (inMultiWindowMode()) {
3440 return mDimmer;
3441 }
3442
3443 // If we're not at the root task level, we want to keep traversing through the parents to
3444 // find the root.
3445 // Once at the root task level, we want to check {@link #isTranslucent(ActivityRecord)}.
3446 // If true, we want to get the Dimmer from the level above since we don't want to animate
3447 // the dim with the Task.
3448 if (!isRootTask() || isTranslucent(null)) {
3449 return super.getDimmer();
3450 }
3451
Robert Carrf59b8dd2017-10-02 18:58:36 -07003452 return mDimmer;
3453 }
3454
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003455 void dim(float alpha) {
3456 mDimmer.dimAbove(getPendingTransaction(), alpha);
3457 scheduleAnimation();
3458 }
3459
3460 void stopDimming() {
3461 mDimmer.stopDim(getPendingTransaction());
3462 scheduleAnimation();
3463 }
3464
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003465 boolean isTaskForUser(int userId) {
3466 return mUserId == userId;
3467 }
3468
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07003469 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07003470 void prepareSurfaces() {
3471 mDimmer.resetDimStates();
3472 super.prepareSurfaces();
3473 getDimBounds(mTmpDimBoundsRect);
chaviwe07246a2017-12-12 16:18:29 -08003474
3475 // Bounds need to be relative, as the dim layer is a child.
HEO SEUNGe10f4192019-11-21 10:21:04 +09003476 if (inFreeformWindowingMode()) {
3477 getBounds(mTmpRect);
3478 mTmpDimBoundsRect.offsetTo(mTmpDimBoundsRect.left - mTmpRect.left,
3479 mTmpDimBoundsRect.top - mTmpRect.top);
3480 } else {
3481 mTmpDimBoundsRect.offsetTo(0, 0);
3482 }
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08003483
Vishnu Nairae3b0772020-03-19 16:55:25 -07003484 updateShadowsRadius(isFocused(), getPendingTransaction());
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08003485
Robert Carrf59b8dd2017-10-02 18:58:36 -07003486 if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
3487 scheduleAnimation();
3488 }
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07003489 }
3490
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003491 @Override
lumark04bceb92020-03-07 00:03:33 +08003492 protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
3493 int transit, boolean isVoiceInteraction,
3494 @Nullable OnAnimationFinishedCallback finishedCallback) {
3495 final RecentsAnimationController control = mWmService.getRecentsAnimationController();
3496 if (control != null && enter
3497 && getDisplayContent().mAppTransition.isNextAppTransitionCustomFromRecents()) {
3498 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
3499 "addTaskToRecentsAnimationIfNeeded, control: %s, task: %s, transit: %s",
3500 control, asTask(), AppTransition.appTransitionToString(transit));
3501 // We let the transition to be controlled by RecentsAnimation, and callback task's
3502 // RemoteAnimationTarget for remote runner to animate.
3503 control.addTaskToTargets(getRootTask(), finishedCallback);
3504 } else {
3505 super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, finishedCallback);
3506 }
3507 }
3508
3509 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003510 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003511 super.dump(pw, prefix, dumpAll);
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003512 final String doublePrefix = prefix + " ";
3513
3514 pw.println(prefix + "taskId=" + mTaskId);
Bryce Leef3c6a472017-11-14 14:53:06 -08003515 pw.println(doublePrefix + "mBounds=" + getBounds().toShortString());
Wale Ogunwalef6192862016-09-10 13:42:30 -07003516 pw.println(doublePrefix + "appTokens=" + mChildren);
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003517
3518 final String triplePrefix = doublePrefix + " ";
Jorim Jaggi153dc9d2018-02-23 13:28:15 +01003519 final String quadruplePrefix = triplePrefix + " ";
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003520
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003521 int[] index = { 0 };
3522 forAllActivities((r) -> {
3523 pw.println(triplePrefix + "Activity #" + index[0]++ + " " + r);
3524 r.dump(pw, quadruplePrefix, dumpAll);
3525 });
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003526 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07003527
Louis Changcdec0802019-11-11 11:45:07 +08003528 /**
Winson Chung66b08f02020-03-03 14:32:35 -08003529 * Fills in a {@link TaskInfo} with information from this task. Note that the base intent in the
3530 * task info will not include any extras or clip data.
Louis Changcdec0802019-11-11 11:45:07 +08003531 */
3532 void fillTaskInfo(TaskInfo info) {
3533 getNumRunningActivities(mReuseActivitiesReport);
3534 info.userId = mUserId;
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003535 info.stackId = getRootTaskId();
Louis Changcdec0802019-11-11 11:45:07 +08003536 info.taskId = mTaskId;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003537 info.displayId = getDisplayId();
Wale Ogunwale21e06482019-11-18 05:14:15 -08003538 info.isRunning = getTopNonFinishingActivity() != null;
Evan Rosky0037e5f2019-11-05 10:26:24 -08003539 final Intent baseIntent = getBaseIntent();
Riddle Hsuc5a1bd42020-02-02 19:32:17 +08003540 // Make a copy of base intent because this is like a snapshot info.
3541 // Besides, {@link RecentTasks#getRecentTasksImpl} may modify it.
Winson Chung661d8662020-04-14 14:47:32 -07003542 final int baseIntentFlags = baseIntent == null ? 0 : baseIntent.getFlags();
Winson Chung66b08f02020-03-03 14:32:35 -08003543 info.baseIntent = baseIntent == null ? new Intent() : baseIntent.cloneFilter();
Winson Chung661d8662020-04-14 14:47:32 -07003544 info.baseIntent.setFlags(baseIntentFlags);
Louis Changcdec0802019-11-11 11:45:07 +08003545 info.baseActivity = mReuseActivitiesReport.base != null
3546 ? mReuseActivitiesReport.base.intent.getComponent()
3547 : null;
3548 info.topActivity = mReuseActivitiesReport.top != null
3549 ? mReuseActivitiesReport.top.mActivityComponent
3550 : null;
3551 info.origActivity = origActivity;
3552 info.realActivity = realActivity;
3553 info.numActivities = mReuseActivitiesReport.numActivities;
3554 info.lastActiveTime = lastActiveTime;
3555 info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
3556 info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
Louis Changcdec0802019-11-11 11:45:07 +08003557 info.configuration.setTo(getConfiguration());
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07003558 info.token = mRemoteToken.toWindowContainerToken();
Evan Roskya8fde152020-01-07 19:09:13 -08003559
3560 //TODO (AM refactor): Just use local once updateEffectiveIntent is run during all child
3561 // order changes.
3562 final Task top = getTopMostTask();
3563 info.resizeMode = top != null ? top.mResizeMode : mResizeMode;
Louis Changa009c762020-02-26 11:21:31 +08003564 info.topActivityType = top.getActivityType();
Robert Carrf6690d12020-02-04 14:16:21 -08003565
Evan Rosky2af969c2020-05-08 16:26:31 +00003566 ActivityRecord rootActivity = top.getRootActivity();
3567 if (rootActivity == null || rootActivity.pictureInPictureArgs.empty()) {
Robert Carrf6690d12020-02-04 14:16:21 -08003568 info.pictureInPictureParams = null;
3569 } else {
Evan Rosky2af969c2020-05-08 16:26:31 +00003570 info.pictureInPictureParams = rootActivity.pictureInPictureArgs;
Robert Carrf6690d12020-02-04 14:16:21 -08003571 }
Hongwei Wang2e725be2020-03-10 11:01:28 -07003572 info.topActivityInfo = mReuseActivitiesReport.top != null
3573 ? mReuseActivitiesReport.top.info
3574 : null;
Louis Changcdec0802019-11-11 11:45:07 +08003575 }
3576
3577 /**
3578 * Returns a {@link TaskInfo} with information from this task.
3579 */
3580 ActivityManager.RunningTaskInfo getTaskInfo() {
3581 ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
3582 fillTaskInfo(info);
3583 return info;
3584 }
3585
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003586 boolean isTaskId(int taskId) {
3587 return mTaskId == taskId;
3588 }
3589
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003590 @Override
3591 Task asTask() {
3592 // I'm a task!
3593 return this;
3594 }
3595
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003596 /**
3597 * Returns true if the task should be visible.
3598 *
3599 * @param starting The currently starting activity or null if there is none.
3600 */
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003601 boolean shouldBeVisible(ActivityRecord starting) {
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003602 return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE;
3603 }
3604
3605 /**
3606 * Returns true if the task should be visible.
3607 *
3608 * @param starting The currently starting activity or null if there is none.
3609 */
3610 @ActivityStack.StackVisibility
3611 int getVisibility(ActivityRecord starting) {
3612 if (!isAttached() || isForceHidden()) {
3613 return STACK_VISIBILITY_INVISIBLE;
3614 }
3615
3616 boolean gotSplitScreenStack = false;
3617 boolean gotOpaqueSplitScreenPrimary = false;
3618 boolean gotOpaqueSplitScreenSecondary = false;
3619 boolean gotTranslucentFullscreen = false;
3620 boolean gotTranslucentSplitScreenPrimary = false;
3621 boolean gotTranslucentSplitScreenSecondary = false;
3622 boolean shouldBeVisible = true;
3623
3624 // This stack is only considered visible if all its parent stacks are considered visible,
3625 // so check the visibility of all ancestor stacks first.
3626 final WindowContainer parent = getParent();
3627 if (parent.asTask() != null) {
3628 final int parentVisibility = parent.asTask().getVisibility(starting);
3629 if (parentVisibility == STACK_VISIBILITY_INVISIBLE) {
3630 // Can't be visible if parent isn't visible
3631 return STACK_VISIBILITY_INVISIBLE;
3632 } else if (parentVisibility == STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT) {
3633 // Parent is behind a translucent container so the highest visibility this container
3634 // can get is that.
3635 gotTranslucentFullscreen = true;
3636 }
3637 }
3638
3639 final int windowingMode = getWindowingMode();
3640 final boolean isAssistantType = isActivityTypeAssistant();
3641 for (int i = parent.getChildCount() - 1; i >= 0; --i) {
3642 final WindowContainer wc = parent.getChildAt(i);
3643 final Task other = wc.asTask();
3644 if (other == null) continue;
3645
3646 final boolean hasRunningActivities = other.topRunningActivity() != null;
3647 if (other == this) {
3648 // Should be visible if there is no other stack occluding it, unless it doesn't
3649 // have any running activities, not starting one and not home stack.
3650 shouldBeVisible = hasRunningActivities || isInTask(starting) != null
3651 || isActivityTypeHome();
3652 break;
3653 }
3654
3655 if (!hasRunningActivities) {
3656 continue;
3657 }
3658
3659 final int otherWindowingMode = other.getWindowingMode();
3660
3661 if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) {
3662 // In this case the home stack isn't resizeable even though we are in split-screen
3663 // mode. We still want the primary splitscreen stack to be visible as there will be
3664 // a slight hint of it in the status bar area above the non-resizeable home
3665 // activity. In addition, if the fullscreen assistant is over primary splitscreen
3666 // stack, the stack should still be visible in the background as long as the recents
3667 // animation is running.
3668 final int activityType = other.getActivityType();
3669 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
3670 if (activityType == ACTIVITY_TYPE_HOME
3671 || (activityType == ACTIVITY_TYPE_ASSISTANT
3672 && mWmService.getRecentsAnimationController() != null)) {
3673 break;
3674 }
3675 }
3676 if (other.isTranslucent(starting)) {
3677 // Can be visible behind a translucent fullscreen stack.
3678 gotTranslucentFullscreen = true;
3679 continue;
3680 }
3681 return STACK_VISIBILITY_INVISIBLE;
3682 } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
3683 && !gotOpaqueSplitScreenPrimary) {
3684 gotSplitScreenStack = true;
3685 gotTranslucentSplitScreenPrimary = other.isTranslucent(starting);
3686 gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary;
3687 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
3688 && gotOpaqueSplitScreenPrimary) {
3689 // Can not be visible behind another opaque stack in split-screen-primary mode.
3690 return STACK_VISIBILITY_INVISIBLE;
3691 }
3692 } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
3693 && !gotOpaqueSplitScreenSecondary) {
3694 gotSplitScreenStack = true;
3695 gotTranslucentSplitScreenSecondary = other.isTranslucent(starting);
3696 gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary;
3697 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
3698 && gotOpaqueSplitScreenSecondary) {
3699 // Can not be visible behind another opaque stack in split-screen-secondary mode.
3700 return STACK_VISIBILITY_INVISIBLE;
3701 }
3702 }
3703 if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) {
3704 // Can not be visible if we are in split-screen windowing mode and both halves of
3705 // the screen are opaque.
3706 return STACK_VISIBILITY_INVISIBLE;
3707 }
3708 if (isAssistantType && gotSplitScreenStack) {
3709 // Assistant stack can't be visible behind split-screen. In addition to this not
3710 // making sense, it also works around an issue here we boost the z-order of the
3711 // assistant window surfaces in window manager whenever it is visible.
3712 return STACK_VISIBILITY_INVISIBLE;
3713 }
3714 }
3715
3716 if (!shouldBeVisible) {
3717 return STACK_VISIBILITY_INVISIBLE;
3718 }
3719
3720 // Handle cases when there can be a translucent split-screen stack on top.
3721 switch (windowingMode) {
3722 case WINDOWING_MODE_FULLSCREEN:
3723 if (gotTranslucentSplitScreenPrimary || gotTranslucentSplitScreenSecondary) {
3724 // At least one of the split-screen stacks that covers this one is translucent.
3725 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
3726 }
3727 break;
3728 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
3729 if (gotTranslucentSplitScreenPrimary) {
3730 // Covered by translucent primary split-screen on top.
3731 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
3732 }
3733 break;
3734 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
3735 if (gotTranslucentSplitScreenSecondary) {
3736 // Covered by translucent secondary split-screen on top.
3737 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
3738 }
3739 break;
3740 }
3741
3742 // Lastly - check if there is a translucent fullscreen stack on top.
3743 return gotTranslucentFullscreen ? STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
3744 : STACK_VISIBILITY_VISIBLE;
3745 }
3746
3747 ActivityRecord isInTask(ActivityRecord r) {
3748 if (r == null) {
3749 return null;
3750 }
3751 final Task task = r.getRootTask();
3752 if (task != null && r.isDescendantOf(task)) {
3753 if (task != this) Slog.w(TAG, "Illegal state! task does not point to stack it is in. "
3754 + "stack=" + this + " task=" + task + " r=" + r
3755 + " callers=" + Debug.getCallers(15, "\n"));
3756 return r;
3757 }
3758 return null;
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003759 }
3760
Louis Changcdec0802019-11-11 11:45:07 +08003761 void dump(PrintWriter pw, String prefix) {
3762 pw.print(prefix); pw.print("userId="); pw.print(mUserId);
3763 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
3764 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
3765 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Wale Ogunwale0d465192020-01-23 19:14:44 -08003766 pw.print(" mCallingPackage="); pw.print(mCallingPackage);
Philip P. Moltmannee295092020-02-10 08:46:26 -08003767 pw.print(" mCallingFeatureId="); pw.println(mCallingFeatureId);
Louis Changcdec0802019-11-11 11:45:07 +08003768 if (affinity != null || rootAffinity != null) {
3769 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
3770 if (affinity == null || !affinity.equals(rootAffinity)) {
3771 pw.print(" root="); pw.println(rootAffinity);
3772 } else {
3773 pw.println();
3774 }
3775 }
Garfield Tan5901e7c2020-02-07 17:12:22 -08003776 if (mWindowLayoutAffinity != null) {
3777 pw.print(prefix); pw.print("windowLayoutAffinity="); pw.println(mWindowLayoutAffinity);
3778 }
Louis Changcdec0802019-11-11 11:45:07 +08003779 if (voiceSession != null || voiceInteractor != null) {
3780 pw.print(prefix); pw.print("VOICE: session=0x");
3781 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
3782 pw.print(" interactor=0x");
3783 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
3784 }
3785 if (intent != null) {
3786 StringBuilder sb = new StringBuilder(128);
3787 sb.append(prefix); sb.append("intent={");
3788 intent.toShortString(sb, false, true, false, false);
3789 sb.append('}');
3790 pw.println(sb.toString());
3791 }
3792 if (affinityIntent != null) {
3793 StringBuilder sb = new StringBuilder(128);
3794 sb.append(prefix); sb.append("affinityIntent={");
3795 affinityIntent.toShortString(sb, false, true, false, false);
3796 sb.append('}');
3797 pw.println(sb.toString());
3798 }
3799 if (origActivity != null) {
3800 pw.print(prefix); pw.print("origActivity=");
3801 pw.println(origActivity.flattenToShortString());
3802 }
3803 if (realActivity != null) {
3804 pw.print(prefix); pw.print("mActivityComponent=");
3805 pw.println(realActivity.flattenToShortString());
3806 }
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08003807 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard()) {
Louis Changcdec0802019-11-11 11:45:07 +08003808 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
3809 pw.print(" isPersistable="); pw.print(isPersistable);
Louis Changcdec0802019-11-11 11:45:07 +08003810 pw.print(" activityType="); pw.println(getActivityType());
3811 }
3812 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
3813 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
3814 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
3815 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
3816 pw.print(" mReuseTask="); pw.print(mReuseTask);
3817 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
3818 }
3819 if (mAffiliatedTaskId != mTaskId || mPrevAffiliateTaskId != INVALID_TASK_ID
3820 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
3821 || mNextAffiliate != null) {
3822 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
3823 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
3824 pw.print(" (");
3825 if (mPrevAffiliate == null) {
3826 pw.print("null");
3827 } else {
3828 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
3829 }
3830 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
3831 pw.print(" (");
3832 if (mNextAffiliate == null) {
3833 pw.print("null");
3834 } else {
3835 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
3836 }
3837 pw.println(")");
3838 }
3839 pw.print(prefix); pw.print("Activities="); pw.println(mChildren);
3840 if (!askedCompatMode || !inRecents || !isAvailable) {
3841 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
3842 pw.print(" inRecents="); pw.print(inRecents);
3843 pw.print(" isAvailable="); pw.println(isAvailable);
3844 }
3845 if (lastDescription != null) {
3846 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
3847 }
3848 if (mRootProcess != null) {
3849 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
3850 }
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003851 pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId());
Dianne Hackborn9106f2a2020-04-30 16:23:20 -07003852 pw.print(prefix); pw.print("mHasBeenVisible="); pw.println(getHasBeenVisible());
3853 pw.print(prefix); pw.print("mResizeMode=");
3854 pw.print(ActivityInfo.resizeModeToString(mResizeMode));
3855 pw.print(" mSupportsPictureInPicture="); pw.print(mSupportsPictureInPicture);
3856 pw.print(" isResizeable="); pw.println(isResizeable());
3857 pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
Louis Changcdec0802019-11-11 11:45:07 +08003858 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
3859 }
3860
3861 @Override
3862 public String toString() {
3863 StringBuilder sb = new StringBuilder(128);
3864 if (stringName != null) {
3865 sb.append(stringName);
3866 sb.append(" U=");
3867 sb.append(mUserId);
3868 sb.append(" StackId=");
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003869 sb.append(getRootTaskId());
Louis Changcdec0802019-11-11 11:45:07 +08003870 sb.append(" sz=");
3871 sb.append(getChildCount());
3872 sb.append('}');
3873 return sb.toString();
3874 }
3875 sb.append("Task{");
3876 sb.append(Integer.toHexString(System.identityHashCode(this)));
3877 sb.append(" #");
3878 sb.append(mTaskId);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003879 sb.append(" visible=" + shouldBeVisible(null /* starting */));
3880 sb.append(" type=" + activityTypeToString(getActivityType()));
3881 sb.append(" mode=" + windowingModeToString(getWindowingMode()));
3882 sb.append(" translucent=" + isTranslucent(null /* starting */));
Louis Changcdec0802019-11-11 11:45:07 +08003883 if (affinity != null) {
3884 sb.append(" A=");
3885 sb.append(affinity);
Evan Rosky0037e5f2019-11-05 10:26:24 -08003886 } else if (intent != null && intent.getComponent() != null) {
Louis Changcdec0802019-11-11 11:45:07 +08003887 sb.append(" I=");
3888 sb.append(intent.getComponent().flattenToShortString());
3889 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
3890 sb.append(" aI=");
3891 sb.append(affinityIntent.getComponent().flattenToShortString());
3892 } else {
3893 sb.append(" ??");
3894 }
3895 stringName = sb.toString();
3896 return toString();
3897 }
3898
Louis Changcdec0802019-11-11 11:45:07 +08003899 /** @see #getNumRunningActivities(TaskActivitiesReport) */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003900 static class TaskActivitiesReport implements Consumer<ActivityRecord> {
Louis Changcdec0802019-11-11 11:45:07 +08003901 int numRunning;
3902 int numActivities;
3903 ActivityRecord top;
3904 ActivityRecord base;
3905
3906 void reset() {
3907 numRunning = numActivities = 0;
3908 top = base = null;
3909 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003910
3911 @Override
3912 public void accept(ActivityRecord r) {
3913 if (r.finishing) {
3914 return;
3915 }
3916
3917 base = r;
3918
3919 // Increment the total number of non-finishing activities
3920 numActivities++;
3921
3922 if (top == null || (top.isState(ActivityState.INITIALIZING))) {
3923 top = r;
3924 // Reset the number of running activities until we hit the first non-initializing
3925 // activity
3926 numRunning = 0;
3927 }
3928 if (r.attachedToProcess()) {
3929 // Increment the number of actually running activities
3930 numRunning++;
3931 }
3932 }
Louis Changcdec0802019-11-11 11:45:07 +08003933 }
3934
3935 /**
3936 * Saves this {@link Task} to XML using given serializer.
3937 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003938 void saveToXml(XmlSerializer out) throws Exception {
Louis Changcdec0802019-11-11 11:45:07 +08003939 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
3940
3941 out.attribute(null, ATTR_TASKID, String.valueOf(mTaskId));
3942 if (realActivity != null) {
3943 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
3944 }
3945 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
3946 if (origActivity != null) {
3947 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
3948 }
3949 // Write affinity, and root affinity if it is different from affinity.
3950 // We use the special string "@" for a null root affinity, so we can identify
3951 // later whether we were given a root affinity or should just make it the
3952 // same as the affinity.
3953 if (affinity != null) {
3954 out.attribute(null, ATTR_AFFINITY, affinity);
3955 if (!affinity.equals(rootAffinity)) {
3956 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3957 }
3958 } else if (rootAffinity != null) {
3959 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3960 }
Garfield Tan5901e7c2020-02-07 17:12:22 -08003961 if (mWindowLayoutAffinity != null) {
3962 out.attribute(null, ATTR_WINDOW_LAYOUT_AFFINITY, mWindowLayoutAffinity);
3963 }
Louis Changcdec0802019-11-11 11:45:07 +08003964 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
3965 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
3966 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
3967 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
3968 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
3969 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
3970 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
3971 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
3972 if (lastDescription != null) {
3973 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
3974 }
3975 if (getTaskDescription() != null) {
3976 getTaskDescription().saveToXml(out);
3977 }
3978 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
3979 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
3980 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
3981 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
3982 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
3983 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
Philip P. Moltmannee295092020-02-10 08:46:26 -08003984 out.attribute(null, ATTR_CALLING_FEATURE_ID,
3985 mCallingFeatureId == null ? "" : mCallingFeatureId);
Louis Changcdec0802019-11-11 11:45:07 +08003986 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
3987 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
3988 String.valueOf(mSupportsPictureInPicture));
3989 if (mLastNonFullscreenBounds != null) {
3990 out.attribute(
3991 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
3992 }
3993 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
3994 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
3995 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
3996
3997 if (affinityIntent != null) {
3998 out.startTag(null, TAG_AFFINITYINTENT);
3999 affinityIntent.saveToXml(out);
4000 out.endTag(null, TAG_AFFINITYINTENT);
4001 }
4002
4003 if (intent != null) {
4004 out.startTag(null, TAG_INTENT);
4005 intent.saveToXml(out);
4006 out.endTag(null, TAG_INTENT);
4007 }
4008
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004009 sTmpException = null;
4010 final PooledFunction f = PooledLambda.obtainFunction(Task::saveActivityToXml,
4011 PooledLambda.__(ActivityRecord.class), getBottomMostActivity(), out);
4012 forAllActivities(f);
4013 f.recycle();
4014 if (sTmpException != null) {
4015 throw sTmpException;
4016 }
4017 }
4018
4019 private static boolean saveActivityToXml(
4020 ActivityRecord r, ActivityRecord first, XmlSerializer out) {
4021 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable()
4022 || ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
4023 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT)
4024 && r != first) {
4025 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
4026 return true;
4027 }
4028 try {
Louis Changcdec0802019-11-11 11:45:07 +08004029 out.startTag(null, TAG_ACTIVITY);
4030 r.saveToXml(out);
4031 out.endTag(null, TAG_ACTIVITY);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004032 return false;
4033 } catch (Exception e) {
4034 sTmpException = e;
4035 return true;
Louis Changcdec0802019-11-11 11:45:07 +08004036 }
4037 }
4038
Louis Changcdec0802019-11-11 11:45:07 +08004039 static Task restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
4040 throws IOException, XmlPullParserException {
Garfield Tan5044a152020-05-01 14:13:35 -07004041 Intent intent = null;
4042 Intent affinityIntent = null;
4043 ArrayList<ActivityRecord> activities = new ArrayList<>();
4044 ComponentName realActivity = null;
4045 boolean realActivitySuspended = false;
4046 ComponentName origActivity = null;
4047 String affinity = null;
4048 String rootAffinity = null;
4049 boolean hasRootAffinity = false;
4050 String windowLayoutAffinity = null;
4051 boolean rootHasReset = false;
4052 boolean autoRemoveRecents = false;
4053 boolean askedCompatMode = false;
4054 int taskType = 0;
4055 int userId = 0;
4056 boolean userSetupComplete = true;
4057 int effectiveUid = -1;
4058 String lastDescription = null;
4059 long lastTimeOnTop = 0;
4060 boolean neverRelinquishIdentity = true;
4061 int taskId = INVALID_TASK_ID;
4062 final int outerDepth = in.getDepth();
4063 TaskDescription taskDescription = new TaskDescription();
4064 int taskAffiliation = INVALID_TASK_ID;
4065 int taskAffiliationColor = 0;
4066 int prevTaskId = INVALID_TASK_ID;
4067 int nextTaskId = INVALID_TASK_ID;
4068 int callingUid = -1;
4069 String callingPackage = "";
4070 String callingFeatureId = null;
4071 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4072 boolean supportsPictureInPicture = false;
4073 Rect lastNonFullscreenBounds = null;
4074 int minWidth = INVALID_MIN_SIZE;
4075 int minHeight = INVALID_MIN_SIZE;
4076 int persistTaskVersion = 0;
Louis Changcdec0802019-11-11 11:45:07 +08004077
Garfield Tan5044a152020-05-01 14:13:35 -07004078 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
4079 final String attrName = in.getAttributeName(attrNdx);
4080 final String attrValue = in.getAttributeValue(attrNdx);
4081 if (TaskPersister.DEBUG) {
4082 Slog.d(TaskPersister.TAG, "Task: attribute name=" + attrName + " value="
4083 + attrValue);
Louis Changcdec0802019-11-11 11:45:07 +08004084 }
Garfield Tan5044a152020-05-01 14:13:35 -07004085 switch (attrName) {
4086 case ATTR_TASKID:
4087 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
4088 break;
4089 case ATTR_REALACTIVITY:
4090 realActivity = ComponentName.unflattenFromString(attrValue);
4091 break;
4092 case ATTR_REALACTIVITY_SUSPENDED:
4093 realActivitySuspended = Boolean.valueOf(attrValue);
4094 break;
4095 case ATTR_ORIGACTIVITY:
4096 origActivity = ComponentName.unflattenFromString(attrValue);
4097 break;
4098 case ATTR_AFFINITY:
4099 affinity = attrValue;
4100 break;
4101 case ATTR_ROOT_AFFINITY:
4102 rootAffinity = attrValue;
4103 hasRootAffinity = true;
4104 break;
4105 case ATTR_WINDOW_LAYOUT_AFFINITY:
4106 windowLayoutAffinity = attrValue;
4107 break;
4108 case ATTR_ROOTHASRESET:
4109 rootHasReset = Boolean.parseBoolean(attrValue);
4110 break;
4111 case ATTR_AUTOREMOVERECENTS:
4112 autoRemoveRecents = Boolean.parseBoolean(attrValue);
4113 break;
4114 case ATTR_ASKEDCOMPATMODE:
4115 askedCompatMode = Boolean.parseBoolean(attrValue);
4116 break;
4117 case ATTR_USERID:
4118 userId = Integer.parseInt(attrValue);
4119 break;
4120 case ATTR_USER_SETUP_COMPLETE:
4121 userSetupComplete = Boolean.parseBoolean(attrValue);
4122 break;
4123 case ATTR_EFFECTIVE_UID:
4124 effectiveUid = Integer.parseInt(attrValue);
4125 break;
4126 case ATTR_TASKTYPE:
4127 taskType = Integer.parseInt(attrValue);
4128 break;
4129 case ATTR_LASTDESCRIPTION:
4130 lastDescription = attrValue;
4131 break;
4132 case ATTR_LASTTIMEMOVED:
4133 lastTimeOnTop = Long.parseLong(attrValue);
4134 break;
4135 case ATTR_NEVERRELINQUISH:
4136 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
4137 break;
4138 case ATTR_TASK_AFFILIATION:
4139 taskAffiliation = Integer.parseInt(attrValue);
4140 break;
4141 case ATTR_PREV_AFFILIATION:
4142 prevTaskId = Integer.parseInt(attrValue);
4143 break;
4144 case ATTR_NEXT_AFFILIATION:
4145 nextTaskId = Integer.parseInt(attrValue);
4146 break;
4147 case ATTR_TASK_AFFILIATION_COLOR:
4148 taskAffiliationColor = Integer.parseInt(attrValue);
4149 break;
4150 case ATTR_CALLING_UID:
4151 callingUid = Integer.parseInt(attrValue);
4152 break;
4153 case ATTR_CALLING_PACKAGE:
4154 callingPackage = attrValue;
4155 break;
4156 case ATTR_CALLING_FEATURE_ID:
4157 callingFeatureId = attrValue;
4158 break;
4159 case ATTR_RESIZE_MODE:
4160 resizeMode = Integer.parseInt(attrValue);
4161 break;
4162 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
4163 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
4164 break;
4165 case ATTR_NON_FULLSCREEN_BOUNDS:
4166 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
4167 break;
4168 case ATTR_MIN_WIDTH:
4169 minWidth = Integer.parseInt(attrValue);
4170 break;
4171 case ATTR_MIN_HEIGHT:
4172 minHeight = Integer.parseInt(attrValue);
4173 break;
4174 case ATTR_PERSIST_TASK_VERSION:
4175 persistTaskVersion = Integer.parseInt(attrValue);
4176 break;
4177 default:
4178 if (!attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
4179 Slog.w(TAG, "Task: Unknown attribute=" + attrName);
Louis Changcdec0802019-11-11 11:45:07 +08004180 }
Louis Changcdec0802019-11-11 11:45:07 +08004181 }
Garfield Tan5044a152020-05-01 14:13:35 -07004182 }
4183 taskDescription.restoreFromXml(in);
4184
4185 int event;
4186 while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
4187 && (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
4188 if (event == XmlPullParser.START_TAG) {
4189 final String name = in.getName();
4190 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: START_TAG name=" + name);
4191 if (TAG_AFFINITYINTENT.equals(name)) {
4192 affinityIntent = Intent.restoreFromXml(in);
4193 } else if (TAG_INTENT.equals(name)) {
4194 intent = Intent.restoreFromXml(in);
4195 } else if (TAG_ACTIVITY.equals(name)) {
4196 ActivityRecord activity =
4197 ActivityRecord.restoreFromXml(in, stackSupervisor);
4198 if (TaskPersister.DEBUG) {
4199 Slog.d(TaskPersister.TAG, "Task: activity=" + activity);
Louis Changcdec0802019-11-11 11:45:07 +08004200 }
Garfield Tan5044a152020-05-01 14:13:35 -07004201 if (activity != null) {
4202 activities.add(activity);
4203 }
4204 } else {
4205 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
4206 XmlUtils.skipCurrentTag(in);
Louis Changcdec0802019-11-11 11:45:07 +08004207 }
4208 }
Garfield Tan5044a152020-05-01 14:13:35 -07004209 }
4210 if (!hasRootAffinity) {
4211 rootAffinity = affinity;
4212 } else if ("@".equals(rootAffinity)) {
4213 rootAffinity = null;
4214 }
4215 if (effectiveUid <= 0) {
4216 Intent checkIntent = intent != null ? intent : affinityIntent;
4217 effectiveUid = 0;
4218 if (checkIntent != null) {
4219 IPackageManager pm = AppGlobals.getPackageManager();
4220 try {
4221 ApplicationInfo ai = pm.getApplicationInfo(
4222 checkIntent.getComponent().getPackageName(),
4223 PackageManager.MATCH_UNINSTALLED_PACKAGES
4224 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
4225 if (ai != null) {
4226 effectiveUid = ai.uid;
4227 }
4228 } catch (RemoteException e) {
4229 }
Louis Changcdec0802019-11-11 11:45:07 +08004230 }
Garfield Tan5044a152020-05-01 14:13:35 -07004231 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
4232 + ": effectiveUid=" + effectiveUid);
Louis Changcdec0802019-11-11 11:45:07 +08004233 }
4234
Garfield Tan5044a152020-05-01 14:13:35 -07004235 if (persistTaskVersion < 1) {
4236 // We need to convert the resize mode of home activities saved before version one if
4237 // they are marked as RESIZE_MODE_RESIZEABLE to
4238 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
4239 // before version 1 and the system didn't resize home activities before then.
4240 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
4241 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4242 }
4243 } else {
4244 // This activity has previously marked itself explicitly as both resizeable and
4245 // supporting picture-in-picture. Since there is no longer a requirement for
4246 // picture-in-picture activities to be resizeable, we can mark this simply as
4247 // resizeable and supporting picture-in-picture separately.
4248 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
4249 resizeMode = RESIZE_MODE_RESIZEABLE;
4250 supportsPictureInPicture = true;
4251 }
Louis Changcdec0802019-11-11 11:45:07 +08004252 }
Garfield Tan5044a152020-05-01 14:13:35 -07004253
4254 final Task task = new ActivityStack(stackSupervisor.mService, taskId, intent,
4255 affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
4256 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
4257 lastTimeOnTop, neverRelinquishIdentity, taskDescription, taskAffiliation,
4258 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
4259 callingFeatureId, resizeMode, supportsPictureInPicture, realActivitySuspended,
4260 userSetupComplete, minWidth, minHeight, null /*ActivityInfo*/,
4261 null /*_voiceSession*/, null /*_voiceInteractor*/, null /* stack */);
4262 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
4263 task.setBounds(lastNonFullscreenBounds);
4264 task.mWindowLayoutAffinity = windowLayoutAffinity;
4265
4266 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4267 task.addChild(activities.get(activityNdx));
4268 }
4269
4270 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
4271 return task;
Robert Carrf59b8dd2017-10-02 18:58:36 -07004272 }
Robert Carr8a2f9132019-11-11 15:03:15 -08004273
Wale Ogunwaledec34082020-03-22 09:45:00 -07004274 @Override
4275 boolean isOrganized() {
Wale Ogunwale465b1e12020-03-31 12:15:51 -07004276 return mTaskOrganizer != null;
Robert Carr8a2f9132019-11-11 15:03:15 -08004277 }
4278
4279 @Override
4280 protected void reparentSurfaceControl(SurfaceControl.Transaction t, SurfaceControl newParent) {
4281 /**
Louis Changa009c762020-02-26 11:21:31 +08004282 * Avoid reparenting SurfaceControl of the organized tasks that are always on top, since
4283 * the surfaces should be controlled by the organizer itself, like bubbles.
Robert Carr8a2f9132019-11-11 15:03:15 -08004284 */
Louis Changa009c762020-02-26 11:21:31 +08004285 if (isOrganized() && isAlwaysOnTop()) {
Robert Carr8a2f9132019-11-11 15:03:15 -08004286 return;
4287 }
4288 super.reparentSurfaceControl(t, newParent);
4289 }
4290
Robert Carrde96c8a2020-03-24 15:22:21 -07004291 void setHasBeenVisible(boolean hasBeenVisible) {
Winson Chung8b5d23a2020-04-06 19:23:23 -07004292 final boolean prevHasBeenVisible = mHasBeenVisible;
Robert Carrde96c8a2020-03-24 15:22:21 -07004293 mHasBeenVisible = hasBeenVisible;
4294 if (hasBeenVisible) {
Winson Chung8b5d23a2020-04-06 19:23:23 -07004295 // If the task is not yet visible when it is added to the task organizer, then we should
4296 // hide it to allow the task organizer to show it when it is properly reparented. We
4297 // skip this for tasks created by the organizer because they can synchronously update
4298 // the leash before new children are added to the task.
4299 if (!mCreatedByOrganizer && mTaskOrganizer != null && !prevHasBeenVisible) {
4300 getPendingTransaction().hide(getSurfaceControl());
4301 commitPendingTransaction();
4302 }
4303
Robert Carrde96c8a2020-03-24 15:22:21 -07004304 sendTaskAppeared();
4305 if (!isRootTask()) {
4306 getRootTask().setHasBeenVisible(true);
4307 }
4308 }
4309 }
4310
4311 boolean getHasBeenVisible() {
4312 return mHasBeenVisible;
4313 }
4314
chaviwda7b3c22020-04-24 11:25:08 -07004315 /** In the case that these conditions are true, we want to send the Task to the organizer:
4316 * 1. An organizer has been set
4317 * 2. The Task was created by the organizer
4318 * or
4319 * 2a. We have a SurfaceControl
4320 * 2b. We have finished drawing
Robert Carrde96c8a2020-03-24 15:22:21 -07004321 * Any time any of these conditions are updated, the updating code should call
4322 * sendTaskAppeared.
4323 */
Louis Chang9d35a3a2020-04-06 17:23:02 +08004324 boolean taskAppearedReady() {
chaviwda7b3c22020-04-24 11:25:08 -07004325 if (mTaskOrganizer == null) {
4326 return false;
4327 }
4328
4329 if (mCreatedByOrganizer) {
4330 return true;
4331 }
4332
4333 return mSurfaceControl != null && getHasBeenVisible();
Robert Carrde96c8a2020-03-24 15:22:21 -07004334 }
4335
Robert Carr8a2f9132019-11-11 15:03:15 -08004336 private void sendTaskAppeared() {
Louis Chang9d35a3a2020-04-06 17:23:02 +08004337 if (mTaskOrganizer != null) {
Robert Carr8a2f9132019-11-11 15:03:15 -08004338 mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this);
4339 }
4340 }
4341
chaviwda7b3c22020-04-24 11:25:08 -07004342 private void sendTaskVanished(ITaskOrganizer organizer) {
4343 if (organizer != null) {
4344 mAtmService.mTaskOrganizerController.onTaskVanished(organizer, this);
Robert Carr8a2f9132019-11-11 15:03:15 -08004345 }
4346 }
4347
Wale Ogunwale465b1e12020-03-31 12:15:51 -07004348 @VisibleForTesting
Evan Roskyf64f5da2020-03-16 13:47:48 -07004349 boolean setTaskOrganizer(ITaskOrganizer organizer) {
Evan Rosky0037e5f2019-11-05 10:26:24 -08004350 if (mTaskOrganizer == organizer) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07004351 return false;
Evan Rosky0037e5f2019-11-05 10:26:24 -08004352 }
chaviwda7b3c22020-04-24 11:25:08 -07004353
4354 ITaskOrganizer previousOrganizer = mTaskOrganizer;
4355 // Update the new task organizer before calling sendTaskVanished since it could result in
4356 // a new SurfaceControl getting created that would notify the old organizer about it.
Robert Carr8a2f9132019-11-11 15:03:15 -08004357 mTaskOrganizer = organizer;
chaviwda7b3c22020-04-24 11:25:08 -07004358 // Let the old organizer know it has lost control.
4359 sendTaskVanished(previousOrganizer);
Robert Carr8a2f9132019-11-11 15:03:15 -08004360
Wale Ogunwale20ab6d42020-04-13 07:30:59 -07004361 if (mTaskOrganizer != null) {
4362 sendTaskAppeared();
4363 } else {
4364 // No longer managed by any organizer.
4365 mTaskAppearedSent = false;
4366 mLastTaskOrganizerWindowingMode = -1;
4367 setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */);
4368 if (mCreatedByOrganizer) {
4369 removeImmediately();
4370 }
Louis Changa009c762020-02-26 11:21:31 +08004371 }
Wale Ogunwale20ab6d42020-04-13 07:30:59 -07004372
4373 return true;
Winson Chung77338ab2020-03-09 16:32:34 -07004374 }
4375
4376 /**
4377 * Called when the task state changes (ie. from windowing mode change) an the task organizer
4378 * state should also be updated.
4379 *
4380 * @param forceUpdate Updates the task organizer to the one currently specified in the task
4381 * org controller for the task's windowing mode, ignoring the cached
4382 * windowing mode checks.
Evan Roskyf64f5da2020-03-16 13:47:48 -07004383 * @return {@code true} if task organizer changed.
Winson Chung77338ab2020-03-09 16:32:34 -07004384 */
Evan Roskyf64f5da2020-03-16 13:47:48 -07004385 boolean updateTaskOrganizerState(boolean forceUpdate) {
Winson Chung77338ab2020-03-09 16:32:34 -07004386 if (!isRootTask()) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07004387 return false;
Winson Chung77338ab2020-03-09 16:32:34 -07004388 }
4389
4390 final int windowingMode = getWindowingMode();
4391 if (!forceUpdate && windowingMode == mLastTaskOrganizerWindowingMode) {
4392 // If our windowing mode hasn't actually changed, then just stick
4393 // with our old organizer. This lets us implement the semantic
4394 // where SysUI can continue to manage it's old tasks
4395 // while CTS temporarily takes over the registration.
Evan Roskyf64f5da2020-03-16 13:47:48 -07004396 return false;
Winson Chung77338ab2020-03-09 16:32:34 -07004397 }
4398 /*
4399 * Different windowing modes may be managed by different task organizers. If
4400 * getTaskOrganizer returns null, we still call setTaskOrganizer to
4401 * make sure we clear it.
4402 */
4403 final ITaskOrganizer org =
4404 mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
Evan Roskyf64f5da2020-03-16 13:47:48 -07004405 final boolean result = setTaskOrganizer(org);
Winson Chung77338ab2020-03-09 16:32:34 -07004406 mLastTaskOrganizerWindowingMode = windowingMode;
Evan Roskyf64f5da2020-03-16 13:47:48 -07004407 return result;
Robert Carr8a2f9132019-11-11 15:03:15 -08004408 }
4409
4410 @Override
4411 void setSurfaceControl(SurfaceControl sc) {
4412 super.setSurfaceControl(sc);
4413 // If the TaskOrganizer was set before we created the SurfaceControl, we need to
4414 // emit the callbacks now.
4415 sendTaskAppeared();
4416 }
4417
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004418 /**
4419 * @return true if the task is currently focused.
4420 */
4421 private boolean isFocused() {
4422 if (mDisplayContent == null || mDisplayContent.mCurrentFocus == null) {
4423 return false;
4424 }
4425 return mDisplayContent.mCurrentFocus.getTask() == this;
4426 }
4427
4428 /**
Vishnu Nairae3b0772020-03-19 16:55:25 -07004429 * @return true if the task is visible and has at least one visible child.
4430 */
4431 private boolean hasVisibleChildren() {
4432 if (!isAttached() || isForceHidden()) {
4433 return false;
4434 }
4435
4436 return getActivity(ActivityRecord::isVisible) != null;
4437 }
4438
4439 /**
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004440 * @return the desired shadow radius in pixels for the current task.
4441 */
4442 private float getShadowRadius(boolean taskIsFocused) {
Vishnu Nairae3b0772020-03-19 16:55:25 -07004443 int elevation = 0;
4444
4445 // Get elevation for a specific windowing mode.
4446 if (inPinnedWindowingMode()) {
4447 elevation = PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
Garfield Tan7e1cb5c2020-04-10 15:21:23 -07004448 } else if (inFreeformWindowingMode()) {
Vishnu Nairae3b0772020-03-19 16:55:25 -07004449 elevation = taskIsFocused
4450 ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
4451 } else {
4452 // For all other windowing modes, do not draw a shadow.
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004453 return 0;
4454 }
4455
Vishnu Nairae3b0772020-03-19 16:55:25 -07004456 // If the task has no visible children, do not draw a shadow.
4457 if (!hasVisibleChildren()) {
4458 return 0;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004459 }
4460
Vishnu Nairae3b0772020-03-19 16:55:25 -07004461 return dipToPixel(elevation, getDisplayContent().getDisplayMetrics());
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004462 }
4463
4464 /**
4465 * Update the length of the shadow if needed based on windowing mode and task focus state.
4466 */
4467 private void updateShadowsRadius(boolean taskIsFocused,
4468 SurfaceControl.Transaction pendingTransaction) {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08004469 if (!mWmService.mRenderShadowsInCompositor || !isRootTask()) return;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004470
4471 final float newShadowRadius = getShadowRadius(taskIsFocused);
4472 if (mShadowRadius != newShadowRadius) {
4473 mShadowRadius = newShadowRadius;
4474 pendingTransaction.setShadowRadius(getSurfaceControl(), mShadowRadius);
4475 }
4476 }
4477
4478 /**
4479 * Called on the task of a window which gained or lost focus.
4480 * @param hasFocus
4481 */
4482 void onWindowFocusChanged(boolean hasFocus) {
4483 updateShadowsRadius(hasFocus, getPendingTransaction());
4484 }
Robert Carrf6690d12020-02-04 14:16:21 -08004485
Evan Rosky2af969c2020-05-08 16:26:31 +00004486 void onPictureInPictureParamsChanged() {
Winson Chung1df39e22020-04-09 14:30:55 -07004487 if (isOrganized()) {
4488 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
4489 }
Robert Carrf6690d12020-02-04 14:16:21 -08004490 }
Robert Carr711e7052020-02-19 11:14:33 -08004491
4492 /**
4493 * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this
4494 * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy
4495 * to resize, and it will defer the transaction until that resize frame completes.
4496 */
4497 void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t) {
4498 mMainWindowSizeChangeTransaction = t;
4499 }
4500
4501 SurfaceControl.Transaction getMainWindowSizeChangeTransaction() {
4502 return mMainWindowSizeChangeTransaction;
4503 }
Vishnu Nairdddc9f52020-03-09 09:37:27 -07004504
Robert Carr2bed6212020-02-20 16:55:07 -08004505 void setActivityWindowingMode(int windowingMode) {
4506 PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setWindowingMode,
chaviw6630d852020-04-15 19:06:56 -07004507 PooledLambda.__(ActivityRecord.class), windowingMode);
Robert Carr2bed6212020-02-20 16:55:07 -08004508 forAllActivities(c);
4509 c.recycle();
4510 }
4511
Robert Carrf6878a42019-12-18 02:13:12 -08004512 /**
4513 * Sets/unsets the forced-hidden state flag for this task depending on {@param set}.
4514 * @return Whether the force hidden state changed
4515 */
4516 boolean setForceHidden(int flags, boolean set) {
4517 int newFlags = mForceHiddenFlags;
4518 if (set) {
4519 newFlags |= flags;
4520 } else {
4521 newFlags &= ~flags;
4522 }
4523 if (mForceHiddenFlags == newFlags) {
4524 return false;
4525 }
Winson Chungb5ce37c2020-04-22 10:08:28 -07004526 final boolean wasHidden = isForceHidden();
Robert Carrf6878a42019-12-18 02:13:12 -08004527 mForceHiddenFlags = newFlags;
Winson Chungb5ce37c2020-04-22 10:08:28 -07004528 if (wasHidden && isFocusableAndVisible()) {
4529 // The change in force-hidden state will change visibility without triggering a stack
4530 // order change, so we should reset the preferred top focusable stack to ensure it's not
4531 // used if a new activity is started from this task.
4532 getDisplayArea().resetPreferredTopFocusableStackIfBelow(this);
4533 }
Robert Carrf6878a42019-12-18 02:13:12 -08004534 return true;
4535 }
4536
4537 /**
4538 * Returns whether this task is currently forced to be hidden for any reason.
4539 */
4540 protected boolean isForceHidden() {
4541 return mForceHiddenFlags != 0;
4542 }
4543
Vishnu Nairdddc9f52020-03-09 09:37:27 -07004544 @Override
4545 long getProtoFieldId() {
4546 return TASK;
4547 }
Robert Carr2bed6212020-02-20 16:55:07 -08004548
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08004549}