blob: 1ffa01c2bd66d3e5047be9b1740ae0167d4ebfdb [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;
21import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070022import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
Riddle Hsu9a8e3ae2020-03-24 15:22:48 +080023import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
24import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
25import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
Louis Changcdec0802019-11-11 11:45:07 +080026import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
27import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -080028import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
Louis Changcdec0802019-11-11 11:45:07 +080029import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
30import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
31import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
32import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
33import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
34import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
35import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080036import static android.app.WindowConfiguration.activityTypeToString;
37import static android.app.WindowConfiguration.windowingModeToString;
Louis Changcdec0802019-11-11 11:45:07 +080038import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
39import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
40import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
41import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
42import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
43import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
44import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
45import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
46import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080047import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
Jason Monkba53d8a2017-04-06 18:28:19 +000048import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020049import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Louis Changcdec0802019-11-11 11:45:07 +080050import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
51import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
52import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
53import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Bryce Lee61fbcbc2017-03-10 14:14:03 -080054import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Louis Changcdec0802019-11-11 11:45:07 +080055import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
56import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
57import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
58import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
59import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -080060import static android.view.Display.INVALID_DISPLAY;
Evan Rosky9020c072018-12-06 14:11:12 -080061import static android.view.SurfaceControl.METADATA_TASK_ID;
Evan Rosky55bddd82020-01-29 13:07:18 -080062import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
chaviw8c9d1f52018-07-25 14:56:07 -070063
Vishnu Nairf6ef1c72020-01-23 16:28:33 -080064import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
65import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
Louis Changcdec0802019-11-11 11:45:07 +080066import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080067import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
Louis Changcdec0802019-11-11 11:45:07 +080068import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
69import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
70import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
71import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
72import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
73import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
74import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
75import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
76import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
77import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
78import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
79import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
80import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080081import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
Yunfan Chen0e7aff92018-12-05 16:35:32 -080082import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
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;
Robert Carrf6690d12020-02-04 14:16:21 -0800110import android.app.PictureInPictureParams;
Louis Changcdec0802019-11-11 11:45:07 +0800111import android.app.TaskInfo;
112import android.app.WindowConfiguration;
113import android.content.ComponentName;
114import android.content.Intent;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800115import android.content.pm.ActivityInfo;
Louis Changcdec0802019-11-11 11:45:07 +0800116import android.content.pm.ApplicationInfo;
117import android.content.pm.IPackageManager;
118import android.content.pm.PackageManager;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700119import android.content.res.Configuration;
120import 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;
213 private final Rect mLastSurfaceCrop = new Rect();
Louis Changcdec0802019-11-11 11:45:07 +0800214
215 /**
216 * The modes to control how the stack is moved to the front when calling {@link Task#reparent}.
217 */
218 @Retention(RetentionPolicy.SOURCE)
219 @IntDef({
220 REPARENT_MOVE_STACK_TO_FRONT,
221 REPARENT_KEEP_STACK_AT_FRONT,
222 REPARENT_LEAVE_STACK_IN_PLACE
223 })
224 @interface ReparentMoveStackMode {}
225 // Moves the stack to the front if it was not at the front
226 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
227 // Only moves the stack to the front if it was focused or front most already
228 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
229 // Do not move the stack as a part of reparenting
230 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
231
232 /**
233 * The factory used to create {@link Task}. This allows OEM subclass {@link Task}.
234 */
235 private static TaskFactory sTaskFactory;
236
237 String affinity; // The affinity name for this task, or null; may change identity.
238 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Garfield Tan5901e7c2020-02-07 17:12:22 -0800239 String mWindowLayoutAffinity; // Launch param affinity of this task or null. Used when saving
240 // launch params of this task.
Wale Ogunwale0d465192020-01-23 19:14:44 -0800241 IVoiceInteractionSession voiceSession; // Voice interaction session driving task
242 IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Louis Changcdec0802019-11-11 11:45:07 +0800243 Intent intent; // The original intent that started the task. Note that this value can
244 // be null.
245 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
246 int effectiveUid; // The current effective uid of the identity of this task.
247 ComponentName origActivity; // The non-alias activity component of the intent.
248 ComponentName realActivity; // The actual activity component that started the task.
249 boolean realActivitySuspended; // True if the actual activity component that started the
250 // task is suspended.
251 boolean inRecents; // Actually in the recents list?
252 long lastActiveTime; // Last time this task was active in the current device session,
253 // including sleep. This time is initialized to the elapsed time when
254 // restored from disk.
255 boolean isAvailable; // Is the activity available to be launched?
256 boolean rootWasReset; // True if the intent at the root of the task had
257 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
258 boolean autoRemoveRecents; // If true, we should automatically remove the task from
259 // recents when activity finishes
260 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Robert Carrde96c8a2020-03-24 15:22:21 -0700261 private boolean mHasBeenVisible; // Set if any activities in the task have been visible
Louis Changcdec0802019-11-11 11:45:07 +0800262
263 String stringName; // caching of toString() result.
264 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
265 // was changed.
266
Louis Changcdec0802019-11-11 11:45:07 +0800267 /** Can't be put in lockTask mode. */
268 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
269 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
270 final static int LOCK_TASK_AUTH_PINNABLE = 1;
271 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
272 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
273 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
274 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
275 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
276 * lockTask task. */
277 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
278 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
279
280 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
281
Louis Changcdec0802019-11-11 11:45:07 +0800282 /** The process that had previously hosted the root activity of this task.
283 * Used to know that we should try harder to keep this process around, in case the
284 * user wants to return to it. */
285 private WindowProcessController mRootProcess;
286
287 /** Takes on same value as first root activity */
288 boolean isPersistable = false;
289 int maxRecents;
290
291 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
292 * determining the order when restoring. Sign indicates whether last task movement was to front
293 * (positive) or back (negative). Absolute value indicates time. */
294 long mLastTimeMoved;
295
296 /** If original intent did not allow relinquishing task identity, save that information */
297 private boolean mNeverRelinquishIdentity = true;
298
299 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
300 // do not want to delete the stack when the task goes empty.
301 private boolean mReuseTask = false;
302
303 CharSequence lastDescription; // Last description captured for this item.
304
305 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
306 int mAffiliatedTaskColor; // color of the parent task affiliation.
307 Task mPrevAffiliate; // previous task in affiliated chain.
308 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
309 Task mNextAffiliate; // next task in affiliated chain.
310 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
311
312 // For relaunching the task from recents as though it was launched by the original launcher.
313 int mCallingUid;
314 String mCallingPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800315 String mCallingFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +0800316
317 private final Rect mTmpStableBounds = new Rect();
318 private final Rect mTmpNonDecorBounds = new Rect();
319 private final Rect mTmpBounds = new Rect();
320 private final Rect mTmpInsets = new Rect();
Evan Rosky70213702019-11-05 10:26:24 -0800321 private final Rect mTmpFullBounds = new Rect();
Louis Changcdec0802019-11-11 11:45:07 +0800322
323 // Last non-fullscreen bounds the task was launched in or resized to.
324 // The information is persisted and used to determine the appropriate stack to launch the
325 // task into on restore.
326 Rect mLastNonFullscreenBounds = null;
327 // Minimal width and height of this task when it's resizeable. -1 means it should use the
328 // default minimal width/height.
329 int mMinWidth;
330 int mMinHeight;
331
332 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
333 // This number will be assigned when we evaluate OOM scores for all visible tasks.
334 int mLayerRank = -1;
335
336 /** Helper object used for updating override configuration. */
337 private Configuration mTmpConfig = new Configuration();
338
339 /** Used by fillTaskInfo */
340 final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700341
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200342 final ActivityTaskManagerService mAtmService;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800343 final ActivityStackSupervisor mStackSupervisor;
344 final RootWindowContainer mRootWindowContainer;
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200345
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700346 /* Unique identifier for this task. */
Craig Mautner83162a92015-01-26 14:43:30 -0800347 final int mTaskId;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700348 /* User for which this task was created. */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200349 // TODO: Make final
350 int mUserId;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800351
Jorim Jaggi0429f352015-12-22 16:29:16 +0100352 final Rect mPreparedFrozenBounds = new Rect();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700353 final Configuration mPreparedFrozenMergedConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700354
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800355 // Id of the previous display the stack was on.
356 int mPrevDisplayId = INVALID_DISPLAY;
357
Garfield Tandec96db2018-10-30 11:28:49 -0700358 /** ID of the display which rotation {@link #mRotation} has. */
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800359 private int mLastRotationDisplayId = INVALID_DISPLAY;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800360
Garfield Tandec96db2018-10-30 11:28:49 -0700361 /**
362 * Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
363 * moved to a new display.
364 */
Vadim Caenfc14c662020-01-20 16:00:31 +0100365 @Surface.Rotation
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700366 private int mRotation;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700367
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700368 // For comparison with DisplayContent bounds.
369 private Rect mTmpRect = new Rect();
370 // For handling display rotations.
371 private Rect mTmpRect2 = new Rect();
372
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800373 // Resize mode of the task. See {@link ActivityInfo#resizeMode}
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200374 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
375 int mResizeMode;
Chong Zhangb15758a2015-11-17 12:12:03 -0800376
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200377 // Whether or not this task and its activities support PiP. Based on the
378 // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity.
379 boolean mSupportsPictureInPicture;
Winson Chungd3395382016-12-13 11:49:09 -0800380
Chong Zhang3005e752015-09-18 18:46:28 -0700381 // Whether the task is currently being drag-resized
382 private boolean mDragResizing;
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +0100383 private int mDragResizeMode;
Chong Zhang3005e752015-09-18 18:46:28 -0700384
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700385 // This represents the last resolved activity values for this task
386 // NOTE: This value needs to be persisted with each task
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100387 private TaskDescription mTaskDescription;
388
Robert Carr18f622f2017-05-08 11:20:43 -0700389 // If set to true, the task will report that it is not in the floating
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700390 // state regardless of it's stack affiliation. As the floating state drives
Robert Carr18f622f2017-05-08 11:20:43 -0700391 // production of content insets this can be used to preserve them across
392 // stack moves and we in fact do so when moving from full screen to pinned.
393 private boolean mPreserveNonFloatingState = false;
394
Robert Carrf59b8dd2017-10-02 18:58:36 -0700395 private Dimmer mDimmer = new Dimmer(this);
396 private final Rect mTmpDimBoundsRect = new Rect();
397
Jorim Jaggi50bf59c2018-03-09 17:29:48 +0100398 /** @see #setCanAffectSystemUiFlags */
399 private boolean mCanAffectSystemUiFlags = true;
400
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800401 private static Exception sTmpException;
402
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800403 /** ActivityRecords that are exiting, but still on screen for animations. */
404 final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
405
406 /**
407 * When we are in the process of pausing an activity, before starting the
408 * next one, this variable holds the activity that is currently being paused.
409 */
410 ActivityRecord mPausingActivity = null;
411
412 /**
413 * This is the last activity that we put into the paused state. This is
414 * used to determine if we need to do an activity transition while sleeping,
415 * when we normally hold the top activity paused.
416 */
417 ActivityRecord mLastPausedActivity = null;
418
419 /**
420 * Activities that specify No History must be removed once the user navigates away from them.
421 * If the device goes to sleep with such an activity in the paused state then we save it here
422 * and finish it later if another activity replaces it on wakeup.
423 */
424 ActivityRecord mLastNoHistoryActivity = null;
425
426 /** Current activity that is resumed, or null if there is none. */
427 ActivityRecord mResumedActivity = null;
428
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -0800429 private boolean mForceShowForAllUsers;
430
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800431 /** When set, will force the task to report as invisible. */
Robert Carrf6878a42019-12-18 02:13:12 -0800432 static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1;
433 static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1;
434 private int mForceHiddenFlags = 0;
435
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800436
Robert Carr711e7052020-02-19 11:14:33 -0800437 SurfaceControl.Transaction mMainWindowSizeChangeTransaction;
438
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800439 private final FindRootHelper mFindRootHelper = new FindRootHelper();
440 private class FindRootHelper {
441 private ActivityRecord mRoot;
442
443 private void clear() {
444 mRoot = null;
445 }
446
447 ActivityRecord findRoot(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
448 final PooledFunction f = PooledLambda.obtainFunction(FindRootHelper::processActivity,
449 this, PooledLambda.__(ActivityRecord.class), ignoreRelinquishIdentity,
450 setToBottomIfNone);
451 clear();
452 forAllActivities(f, false /*traverseTopToBottom*/);
453 f.recycle();
454 return mRoot;
455 }
456
457 private boolean processActivity(ActivityRecord r,
458 boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
459 if (mRoot == null && setToBottomIfNone) {
460 // This is the first activity we are process. Set it as the candidate root in case
461 // we don't find a better one.
462 mRoot = r;
463 }
464
465 if (r.finishing) return false;
466
467 // Set this as the candidate root since it isn't finishing.
468 mRoot = r;
469
470 // Only end search if we are ignore relinquishing identity or we are not relinquishing.
471 return ignoreRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
472 }
473 }
474
Louis Changcdec0802019-11-11 11:45:07 +0800475 /**
Robert Carr8a2f9132019-11-11 15:03:15 -0800476 * The TaskOrganizer which is delegated presentation of this task. If set the Task will
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700477 * emit an WindowContainerToken (allowing access to it's SurfaceControl leash) to the organizers
Robert Carr8a2f9132019-11-11 15:03:15 -0800478 * taskAppeared callback, and emit a taskRemoved callback when the Task is vanished.
479 */
480 ITaskOrganizer mTaskOrganizer;
Winson Chung77338ab2020-03-09 16:32:34 -0700481 private int mLastTaskOrganizerWindowingMode = -1;
Robert Carrde96c8a2020-03-24 15:22:21 -0700482 /**
483 * Prevent duplicate calls to onTaskAppeared.
484 */
485 boolean mTaskAppearedSent;
Robert Carr8a2f9132019-11-11 15:03:15 -0800486
Robert Carrf6690d12020-02-04 14:16:21 -0800487 /**
488 * Last Picture-in-Picture params applicable to the task. Updated when the app
489 * enters Picture-in-Picture or when setPictureInPictureParams is called.
490 */
491 PictureInPictureParams mPictureInPictureParams = new PictureInPictureParams.Builder().build();
Robert Carr8a2f9132019-11-11 15:03:15 -0800492
493 /**
Louis Changa009c762020-02-26 11:21:31 +0800494 * This task was created by the task organizer which has the following implementations.
495 * <ul>
496 * <lis>The task won't be removed when it is empty. Removal has to be an explicit request
497 * from the task organizer.</li>
498 * <li>Unlike other non-root tasks, it's direct children are visible to the task
499 * organizer for ordering purposes.</li>
500 * </ul>
501 */
502 boolean mCreatedByOrganizer;
503
504 /**
Louis Changcdec0802019-11-11 11:45:07 +0800505 * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
506 * ActivityInfo, Intent, TaskDescription)} instead.
507 */
508 Task(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info, Intent _intent,
509 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
510 TaskDescription _taskDescription, ActivityStack stack) {
511 this(atmService, _taskId, _intent, null /*_affinityIntent*/, null /*_affinity*/,
512 null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
513 false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
514 UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
515 null /*_lastDescription*/, System.currentTimeMillis(),
516 true /*neverRelinquishIdentity*/,
517 _taskDescription != null ? _taskDescription : new TaskDescription(),
518 _taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
Philip P. Moltmannee295092020-02-10 08:46:26 -0800519 info.applicationInfo.uid, info.packageName, null /* default featureId */,
520 info.resizeMode, info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
Louis Changcdec0802019-11-11 11:45:07 +0800521 false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
522 _voiceSession, _voiceInteractor, stack);
523 }
524
525 /** Don't use constructor directly. This is only used by XML parser. */
Philip P. Moltmannee295092020-02-10 08:46:26 -0800526 Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent, Intent _affinityIntent,
527 String _affinity, String _rootAffinity, ComponentName _realActivity,
528 ComponentName _origActivity, boolean _rootWasReset, boolean _autoRemoveRecents,
529 boolean _askedCompatMode, int _userId, int _effectiveUid, String _lastDescription,
Louis Changcdec0802019-11-11 11:45:07 +0800530 long lastTimeMoved, boolean neverRelinquishIdentity,
531 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
532 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Philip P. Moltmannee295092020-02-10 08:46:26 -0800533 @Nullable String callingFeatureId, int resizeMode, boolean supportsPictureInPicture,
534 boolean _realActivitySuspended, boolean userSetupComplete, int minWidth, int minHeight,
535 ActivityInfo info, IVoiceInteractionSession _voiceSession,
536 IVoiceInteractor _voiceInteractor, ActivityStack stack) {
Louis Changcdec0802019-11-11 11:45:07 +0800537 super(atmService.mWindowManager);
538
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -0800539 EventLogTags.writeWmTaskCreated(_taskId, stack != null ? getRootTaskId() : INVALID_TASK_ID);
Louis Changcdec0802019-11-11 11:45:07 +0800540 mAtmService = atmService;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800541 mStackSupervisor = atmService.mStackSupervisor;
542 mRootWindowContainer = mAtmService.mRootWindowContainer;
Louis Changcdec0802019-11-11 11:45:07 +0800543 mTaskId = _taskId;
544 mUserId = _userId;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800545 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800546 mSupportsPictureInPicture = supportsPictureInPicture;
Louis Changcdec0802019-11-11 11:45:07 +0800547 mTaskDescription = _lastTaskDescription;
Riddle Hsu6b76cd32019-10-08 00:37:19 +0800548 // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
549 setOrientation(SCREEN_ORIENTATION_UNSET);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700550 mRemoteToken = new RemoteToken(this);
Louis Changcdec0802019-11-11 11:45:07 +0800551 affinityIntent = _affinityIntent;
552 affinity = _affinity;
553 rootAffinity = _rootAffinity;
554 voiceSession = _voiceSession;
555 voiceInteractor = _voiceInteractor;
556 realActivity = _realActivity;
557 realActivitySuspended = _realActivitySuspended;
558 origActivity = _origActivity;
559 rootWasReset = _rootWasReset;
560 isAvailable = true;
561 autoRemoveRecents = _autoRemoveRecents;
562 askedCompatMode = _askedCompatMode;
563 mUserSetupComplete = userSetupComplete;
564 effectiveUid = _effectiveUid;
565 touchActiveTime();
566 lastDescription = _lastDescription;
567 mLastTimeMoved = lastTimeMoved;
568 mNeverRelinquishIdentity = neverRelinquishIdentity;
569 mAffiliatedTaskId = taskAffiliation;
570 mAffiliatedTaskColor = taskAffiliationColor;
571 mPrevAffiliateTaskId = prevTaskId;
572 mNextAffiliateTaskId = nextTaskId;
573 mCallingUid = callingUid;
574 mCallingPackage = callingPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800575 mCallingFeatureId = callingFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +0800576 mResizeMode = resizeMode;
577 if (info != null) {
578 setIntent(_intent, info);
579 setMinDimensions(info);
580 } else {
581 intent = _intent;
582 mMinWidth = minWidth;
583 mMinHeight = minHeight;
584 }
585 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
586 }
587
Wale Ogunwale0d465192020-01-23 19:14:44 -0800588 Task reuseAsLeafTask(IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
Louis Changfbcf55f2020-03-02 12:27:15 +0800589 Intent intent, ActivityInfo info, ActivityRecord activity) {
Wale Ogunwale0d465192020-01-23 19:14:44 -0800590 voiceSession = _voiceSession;
591 voiceInteractor = _voiceInteractor;
Louis Changfbcf55f2020-03-02 12:27:15 +0800592 setIntent(activity, intent, info);
Wale Ogunwale0d465192020-01-23 19:14:44 -0800593 setMinDimensions(info);
Garfield Tana7c9f7c2020-03-13 15:56:51 -0700594 // Before we began to reuse a root task (old ActivityStack) as the leaf task, we used to
595 // create a leaf task in this case. Therefore now we won't send out the task created
596 // notification when we decide to reuse it here, so we send out the notification below.
597 // The reason why the created notification sent out when root task is created doesn't work
598 // is that realActivity isn't set until setIntent() method above is called for the first
599 // time. Eventually this notification will be removed when we can populate those information
600 // when root task is created.
601 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(mTaskId, realActivity);
Wale Ogunwale0d465192020-01-23 19:14:44 -0800602 return this;
603 }
604
Garfield Tan8b096b22020-01-07 14:55:20 -0800605 private void cleanUpResourcesForDestroy(ConfigurationContainer oldParent) {
Louis Changcdec0802019-11-11 11:45:07 +0800606 if (hasChild()) {
607 return;
608 }
609
Garfield Tan59a60fa2020-03-24 10:32:29 -0700610 if (isLeafTask()) {
Garfield Tan8b096b22020-01-07 14:55:20 -0800611 // This task is going away, so save the last state if necessary.
612 saveLaunchingStateIfNeeded(((WindowContainer) oldParent).getDisplayContent());
613 }
Louis Changcdec0802019-11-11 11:45:07 +0800614
615 // TODO: VI what about activity?
616 final boolean isVoiceSession = voiceSession != null;
617 if (isVoiceSession) {
618 try {
619 voiceSession.taskFinished(intent, mTaskId);
620 } catch (RemoteException e) {
621 }
622 }
623 if (autoRemoveFromRecents() || isVoiceSession) {
624 // Task creator asked to remove this when done, or this task was a voice
625 // interaction, so it should not remain on the recent tasks list.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800626 mStackSupervisor.mRecentTasks.remove(this);
Louis Changcdec0802019-11-11 11:45:07 +0800627 }
628
629 removeIfPossible();
630 }
631
632 @VisibleForTesting
633 @Override
634 void removeIfPossible() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800635 final boolean isRootTask = isRootTask();
636 if (!isRootTask) {
637 mAtmService.getLockTaskController().clearLockedTask(this);
638 }
Louis Changcdec0802019-11-11 11:45:07 +0800639 if (shouldDeferRemoval()) {
640 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId);
641 return;
642 }
643 removeImmediately();
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800644 if (!isRootTask) {
645 mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
646 }
Louis Changcdec0802019-11-11 11:45:07 +0800647 }
648
649 void setResizeMode(int resizeMode) {
650 if (mResizeMode == resizeMode) {
651 return;
652 }
653 mResizeMode = resizeMode;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800654 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
655 mRootWindowContainer.resumeFocusedStacksTopActivities();
Louis Changcdec0802019-11-11 11:45:07 +0800656 updateTaskDescription();
657 }
658
659 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
660 mAtmService.deferWindowLayout();
661
662 try {
663 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
664
665 if (getParent() == null) {
666 // Task doesn't exist in window manager yet (e.g. was restored from recents).
667 // All we can do for now is update the bounds so it can be used when the task is
668 // added to window manager.
669 setBounds(bounds);
670 if (!inFreeformWindowingMode()) {
671 // re-restore the task so it can have the proper stack association.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800672 mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
Louis Changcdec0802019-11-11 11:45:07 +0800673 }
674 return true;
675 }
676
677 if (!canResizeToBounds(bounds)) {
678 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
679 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
680 }
681
682 // Do not move the task to another stack here.
683 // This method assumes that the task is already placed in the right stack.
684 // we do not mess with that decision and we only do the resize!
685
686 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeTask_" + mTaskId);
687
688 boolean updatedConfig = false;
689 mTmpConfig.setTo(getResolvedOverrideConfiguration());
690 if (setBounds(bounds) != BOUNDS_CHANGE_NONE) {
691 updatedConfig = !mTmpConfig.equals(getResolvedOverrideConfiguration());
692 }
693 // This variable holds information whether the configuration didn't change in a
694 // significant way and the activity was kept the way it was. If it's false, it means
695 // the activity had to be relaunched due to configuration change.
696 boolean kept = true;
697 if (updatedConfig) {
698 final ActivityRecord r = topRunningActivityLocked();
699 if (r != null && !deferResume) {
700 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
701 preserveWindow);
702 // Preserve other windows for resizing because if resizing happens when there
703 // is a dialog activity in the front, the activity that still shows some
704 // content to the user will become black and cause flickers. Note in most cases
705 // this won't cause tons of irrelevant windows being preserved because only
706 // activities in this task may experience a bounds change. Configs for other
707 // activities stay the same.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800708 mRootWindowContainer.ensureActivitiesVisible(r, 0, preserveWindow);
Louis Changcdec0802019-11-11 11:45:07 +0800709 if (!kept) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800710 mRootWindowContainer.resumeFocusedStacksTopActivities();
Louis Changcdec0802019-11-11 11:45:07 +0800711 }
712 }
713 }
714 resize(kept, forced);
715
716 saveLaunchingStateIfNeeded();
717
718 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
719 return kept;
720 } finally {
721 mAtmService.continueWindowLayout();
722 }
723 }
724
725 /** Convenience method to reparent a task to the top or bottom position of the stack. */
726 boolean reparent(ActivityStack preferredStack, boolean toTop,
727 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
728 String reason) {
729 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
730 true /* schedulePictureInPictureModeChange */, reason);
731 }
732
733 /**
734 * Convenience method to reparent a task to the top or bottom position of the stack, with
735 * an option to skip scheduling the picture-in-picture mode change.
736 */
737 boolean reparent(ActivityStack preferredStack, boolean toTop,
738 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
739 boolean schedulePictureInPictureModeChange, String reason) {
740 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
741 deferResume, schedulePictureInPictureModeChange, reason);
742 }
743
744 /** Convenience method to reparent a task to a specific position of the stack. */
745 boolean reparent(ActivityStack preferredStack, int position,
746 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
747 String reason) {
748 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
749 true /* schedulePictureInPictureModeChange */, reason);
750 }
751
752 /**
753 * Reparents the task into a preferred stack, creating it if necessary.
754 *
755 * @param preferredStack the target stack to move this task
756 * @param position the position to place this task in the new stack
757 * @param animate whether or not we should wait for the new window created as a part of the
758 * reparenting to be drawn and animated in
759 * @param moveStackMode whether or not to move the stack to the front always, only if it was
760 * previously focused & in front, or never
761 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
762 * have changed as a result of this reparenting
763 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
764 * change. Callers may set this to false if they are explicitly scheduling PiP mode
765 * changes themselves, like during the PiP animation
766 * @param reason the caller of this reparenting
767 * @return whether the task was reparented
768 */
769 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
770 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
771 boolean reparent(ActivityStack preferredStack, int position,
772 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
773 boolean schedulePictureInPictureModeChange, String reason) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800774 final ActivityStackSupervisor supervisor = mStackSupervisor;
775 final RootWindowContainer root = mRootWindowContainer;
Louis Changcdec0802019-11-11 11:45:07 +0800776 final WindowManagerService windowManager = mAtmService.mWindowManager;
777 final ActivityStack sourceStack = getStack();
778 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
779 position == MAX_VALUE);
780 if (toStack == sourceStack) {
781 return false;
782 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800783 if (!canBeLaunchedOnDisplay(toStack.getDisplayId())) {
Louis Changcdec0802019-11-11 11:45:07 +0800784 return false;
785 }
786
787 final boolean toTopOfStack = position == MAX_VALUE;
788 if (toTopOfStack && toStack.getResumedActivity() != null
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900789 && toStack.topRunningActivity() != null) {
Louis Changcdec0802019-11-11 11:45:07 +0800790 // Pause the resumed activity on the target stack while re-parenting task on top of it.
791 toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
792 null /* resuming */);
793 }
794
795 final int toStackWindowingMode = toStack.getWindowingMode();
Wale Ogunwale21e06482019-11-18 05:14:15 -0800796 final ActivityRecord topActivity = getTopNonFinishingActivity();
Louis Changcdec0802019-11-11 11:45:07 +0800797
798 final boolean mightReplaceWindow = topActivity != null
799 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
800 if (mightReplaceWindow) {
801 // We are about to relaunch the activity because its configuration changed due to
802 // being maximized, i.e. size change. The activity will first remove the old window
803 // and then add a new one. This call will tell window manager about this, so it can
804 // preserve the old window until the new one is drawn. This prevents having a gap
805 // between the removal and addition, in which no window is visible. We also want the
806 // entrance of the new window to be properly animated.
807 // Note here we always set the replacing window first, as the flags might be needed
808 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
809 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
810 }
811
812 mAtmService.deferWindowLayout();
813 boolean kept = true;
814 try {
815 final ActivityRecord r = topRunningActivityLocked();
Louis Changcdec0802019-11-11 11:45:07 +0800816 final boolean wasFocused = r != null && root.isTopDisplayFocusedStack(sourceStack)
817 && (topRunningActivityLocked() == r);
818 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
819 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
820
821 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
822 // Whenever we are moving the top activity from the front stack we want to make sure to
823 // move the stack to the front.
Andrii Kulian86d676c2020-03-27 19:34:54 -0700824 final boolean wasFront = r != null && sourceStack.isTopStackInDisplayArea()
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900825 && (sourceStack.topRunningActivity() == r);
Louis Changcdec0802019-11-11 11:45:07 +0800826
827 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
828 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
829
830 reparent(toStack, position, moveStackToFront, reason);
831
832 if (schedulePictureInPictureModeChange) {
833 // Notify of picture-in-picture mode changes
834 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
835 }
836
837 // If the task had focus before (or we're requested to move focus), move focus to the
838 // new stack by moving the stack to the front.
839 if (r != null) {
840 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
841 wasPaused, reason);
842 }
843 if (!animate) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800844 mStackSupervisor.mNoAnimActivities.add(topActivity);
Louis Changcdec0802019-11-11 11:45:07 +0800845 }
846
847 // We might trigger a configuration change. Save the current task bounds for freezing.
848 // TODO: Should this call be moved inside the resize method in WM?
849 toStack.prepareFreezingTaskBounds();
850
851 // Make sure the task has the appropriate bounds/size for the stack it is in.
852 final boolean toStackSplitScreenPrimary =
853 toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
854 final Rect configBounds = getRequestedOverrideBounds();
855 if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
856 || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
857 && !Objects.equals(configBounds, toStack.getRequestedOverrideBounds())) {
858 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
859 !mightReplaceWindow, deferResume);
860 } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
861 Rect bounds = getLaunchBounds();
862 if (bounds == null) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800863 mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Louis Changcdec0802019-11-11 11:45:07 +0800864 bounds = configBounds;
865 }
866 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
867 } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
868 if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
869 // Move recents to front so it is not behind home stack when going into docked
870 // mode
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800871 mStackSupervisor.moveRecentsStackToFront(reason);
Louis Changcdec0802019-11-11 11:45:07 +0800872 }
873 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
874 !mightReplaceWindow, deferResume);
875 }
876 } finally {
877 mAtmService.continueWindowLayout();
878 }
879
880 if (mightReplaceWindow) {
881 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
882 // window), we need to clear the replace window settings. Otherwise, we schedule a
883 // timeout to remove the old window if the replacing window is not coming in time.
884 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
885 }
886
887 if (!deferResume) {
888 // The task might have already been running and its visibility needs to be synchronized
889 // with the visibility of the stack / windows.
890 root.ensureActivitiesVisible(null, 0, !mightReplaceWindow);
891 root.resumeFocusedStacksTopActivities();
892 }
893
894 // TODO: Handle incorrect request to move before the actual move, not after.
895 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Andrii Kulian1cb59dd2020-04-10 12:17:17 -0700896 mRootWindowContainer.getDefaultTaskDisplayArea(), toStack);
Louis Changcdec0802019-11-11 11:45:07 +0800897
898 return (preferredStack == toStack);
899 }
900
901 /**
902 * @return {@code true} if the windows of tasks being moved to the target stack from the
903 * source stack should be replaced, meaning that window manager will keep the old window
904 * around until the new is ready.
905 */
906 private static boolean replaceWindowsOnTaskMove(
907 int sourceWindowingMode, int targetWindowingMode) {
908 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
909 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
910 }
911
912 /**
913 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
914 */
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800915 TaskSnapshot getSnapshot(boolean isLowResolution, boolean restoreFromDisk) {
Louis Changcdec0802019-11-11 11:45:07 +0800916
917 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
918 // synchronized between AM and WM.
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800919 return mAtmService.mWindowManager.getTaskSnapshot(mTaskId, mUserId, isLowResolution,
Louis Changcdec0802019-11-11 11:45:07 +0800920 restoreFromDisk);
921 }
922
923 void touchActiveTime() {
924 lastActiveTime = SystemClock.elapsedRealtime();
925 }
926
927 long getInactiveDuration() {
928 return SystemClock.elapsedRealtime() - lastActiveTime;
929 }
930
Louis Changfbcf55f2020-03-02 12:27:15 +0800931 /** @see #setIntent(ActivityRecord, Intent, ActivityInfo) */
Louis Changcdec0802019-11-11 11:45:07 +0800932 void setIntent(ActivityRecord r) {
Louis Changfbcf55f2020-03-02 12:27:15 +0800933 setIntent(r, null /* intent */, null /* info */);
934 }
935
936 /**
937 * Sets the original intent, and the calling uid and package.
938 *
939 * @param r The activity that started the task
940 * @param intent The task info which could be different from {@code r.intent} if set.
941 * @param info The activity info which could be different from {@code r.info} if set.
942 */
943 void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) {
Louis Changcdec0802019-11-11 11:45:07 +0800944 mCallingUid = r.launchedFromUid;
945 mCallingPackage = r.launchedFromPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800946 mCallingFeatureId = r.launchedFromFeatureId;
Louis Changfbcf55f2020-03-02 12:27:15 +0800947 setIntent(intent != null ? intent : r.intent, info != null ? info : r.info);
Louis Changcdec0802019-11-11 11:45:07 +0800948 setLockTaskAuth(r);
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800949
950 final WindowContainer parent = getParent();
951 if (parent != null) {
952 final Task t = parent.asTask();
953 if (t != null) {
954 t.setIntent(r);
955 }
956 }
Louis Changcdec0802019-11-11 11:45:07 +0800957 }
958
959 /** Sets the original intent, _without_ updating the calling uid or package. */
960 private void setIntent(Intent _intent, ActivityInfo info) {
961 if (intent == null) {
962 mNeverRelinquishIdentity =
963 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
964 } else if (mNeverRelinquishIdentity) {
965 return;
966 }
967
968 affinity = info.taskAffinity;
969 if (intent == null) {
970 // If this task already has an intent associated with it, don't set the root
971 // affinity -- we don't want it changing after initially set, but the initially
972 // set value may be null.
973 rootAffinity = affinity;
974 }
975 effectiveUid = info.applicationInfo.uid;
976 stringName = null;
977
978 if (info.targetActivity == null) {
979 if (_intent != null) {
980 // If this Intent has a selector, we want to clear it for the
981 // recent task since it is not relevant if the user later wants
982 // to re-launch the app.
983 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
984 _intent = new Intent(_intent);
985 _intent.setSelector(null);
986 _intent.setSourceBounds(null);
987 }
988 }
989 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
990 intent = _intent;
991 realActivity = _intent != null ? _intent.getComponent() : null;
992 origActivity = null;
993 } else {
994 ComponentName targetComponent = new ComponentName(
995 info.packageName, info.targetActivity);
996 if (_intent != null) {
997 Intent targetIntent = new Intent(_intent);
998 targetIntent.setSelector(null);
999 targetIntent.setSourceBounds(null);
1000 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
1001 "Setting Intent of " + this + " to target " + targetIntent);
1002 intent = targetIntent;
1003 realActivity = targetComponent;
1004 origActivity = _intent.getComponent();
1005 } else {
1006 intent = null;
1007 realActivity = targetComponent;
1008 origActivity = new ComponentName(info.packageName, info.name);
1009 }
1010 }
Garfield Tan5901e7c2020-02-07 17:12:22 -08001011 mWindowLayoutAffinity =
1012 info.windowLayout == null ? null : info.windowLayout.windowLayoutAffinity;
Louis Changcdec0802019-11-11 11:45:07 +08001013
1014 final int intentFlags = intent == null ? 0 : intent.getFlags();
1015 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1016 // Once we are set to an Intent with this flag, we count this
1017 // task as having a true root activity.
1018 rootWasReset = true;
1019 }
1020 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
1021 mUserSetupComplete = Settings.Secure.getIntForUser(
1022 mAtmService.mContext.getContentResolver(), USER_SETUP_COMPLETE, 0, mUserId) != 0;
1023 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
1024 // If the activity itself has requested auto-remove, then just always do it.
1025 autoRemoveRecents = true;
1026 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
1027 == FLAG_ACTIVITY_NEW_DOCUMENT) {
1028 // If the caller has not asked for the document to be retained, then we may
1029 // want to turn on auto-remove, depending on whether the target has set its
1030 // own document launch mode.
1031 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
1032 autoRemoveRecents = false;
1033 } else {
1034 autoRemoveRecents = true;
1035 }
1036 } else {
1037 autoRemoveRecents = false;
1038 }
1039 if (mResizeMode != info.resizeMode) {
1040 mResizeMode = info.resizeMode;
1041 updateTaskDescription();
1042 }
1043 mSupportsPictureInPicture = info.supportsPictureInPicture();
1044 }
1045
1046 /** Sets the original minimal width and height. */
Wale Ogunwale0d465192020-01-23 19:14:44 -08001047 void setMinDimensions(ActivityInfo info) {
Louis Changcdec0802019-11-11 11:45:07 +08001048 if (info != null && info.windowLayout != null) {
1049 mMinWidth = info.windowLayout.minWidth;
1050 mMinHeight = info.windowLayout.minHeight;
1051 } else {
1052 mMinWidth = INVALID_MIN_SIZE;
1053 mMinHeight = INVALID_MIN_SIZE;
1054 }
1055 }
1056
1057 /**
1058 * Return true if the input activity has the same intent filter as the intent this task
1059 * record is based on (normally the root activity intent).
1060 */
1061 boolean isSameIntentFilter(ActivityRecord r) {
1062 final Intent intent = new Intent(r.intent);
1063 // Make sure the component are the same if the input activity has the same real activity
1064 // as the one in the task because either one of them could be the alias activity.
1065 if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) {
1066 intent.setComponent(this.intent.getComponent());
1067 }
1068 return intent.filterEquals(this.intent);
1069 }
1070
1071 boolean returnsToHomeStack() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001072 if (inMultiWindowMode() || !hasChild()) return false;
1073 if (intent != null) {
1074 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
1075 return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
1076 }
1077 final Task bottomTask = getBottomMostTask();
1078 return bottomTask != this && bottomTask.returnsToHomeStack();
Louis Changcdec0802019-11-11 11:45:07 +08001079 }
1080
1081 void setPrevAffiliate(Task prevAffiliate) {
1082 mPrevAffiliate = prevAffiliate;
1083 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.mTaskId;
1084 }
1085
1086 void setNextAffiliate(Task nextAffiliate) {
1087 mNextAffiliate = nextAffiliate;
1088 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
1089 }
1090
Louis Changcdec0802019-11-11 11:45:07 +08001091 @Override
1092 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001093 final DisplayContent display = newParent != null
1094 ? ((WindowContainer) newParent).getDisplayContent() : null;
1095 final DisplayContent oldDisplay = oldParent != null
1096 ? ((WindowContainer) oldParent).getDisplayContent() : null;
1097
1098 mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
Louis Changcdec0802019-11-11 11:45:07 +08001099
Louis Chang8bda2322019-12-05 16:38:11 +08001100 if (oldParent != null && newParent == null) {
Garfield Tan8b096b22020-01-07 14:55:20 -08001101 cleanUpResourcesForDestroy(oldParent);
Louis Chang8bda2322019-12-05 16:38:11 +08001102 }
1103
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001104 if (display != null) {
1105 // TODO(NOW!): Chat with the erosky@ of this code to see if this really makes sense here...
1106 // Rotations are relative to the display. This means if there are 2 displays rotated
1107 // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
1108 // from one to the other could look like a rotation change. To prevent this
1109 // apparent rotation change (and corresponding bounds rotation), pretend like our
1110 // current rotation is already the same as the new display.
1111 // Note, if ActivityStack or related logic ever gets nested, this logic will need
1112 // to move to onConfigurationChanged.
1113 getConfiguration().windowConfiguration.setRotation(
1114 display.getWindowConfiguration().getRotation());
1115 }
1116
Louis Changcdec0802019-11-11 11:45:07 +08001117 super.onParentChanged(newParent, oldParent);
1118
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001119 // TODO(NOW): The check for null display content and setting it to null doesn't really
1120 // make sense here...
Louis Changcdec0802019-11-11 11:45:07 +08001121
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001122 // TODO(stack-merge): This is mostly taking care of the case where the stask is removing from
1123 // the display, so we should probably consolidate it there instead.
1124
1125 if (getParent() == null && mDisplayContent != null) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08001126 EventLogTags.writeWmStackRemoved(getRootTaskId());
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001127 mDisplayContent = null;
1128 mWmService.mWindowPlacerLocked.requestTraversal();
1129 }
1130
1131 if (oldParent != null) {
1132 final Task oldParentTask = ((WindowContainer) oldParent).asTask();
1133 if (oldParentTask != null) {
1134 final PooledConsumer c = PooledLambda.obtainConsumer(
1135 Task::cleanUpActivityReferences, oldParentTask,
1136 PooledLambda.__(ActivityRecord.class));
1137 forAllActivities(c);
1138 c.recycle();
1139 }
1140
1141 if (oldParent.inPinnedWindowingMode()
1142 && (newParent == null || !newParent.inPinnedWindowingMode())) {
Louis Changcdec0802019-11-11 11:45:07 +08001143 // Notify if a task from the pinned stack is being removed
1144 // (or moved depending on the mode).
1145 mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
1146 }
1147 }
1148
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001149 if (newParent != null) {
1150 final Task newParentTask = ((WindowContainer) newParent).asTask();
1151 if (newParentTask != null) {
1152 final ActivityRecord top = newParentTask.getTopNonFinishingActivity(
1153 false /* includeOverlays */);
1154 if (top != null && top.isState(RESUMED)) {
1155 newParentTask.setResumedActivity(top, "addedToTask");
1156 }
1157 }
Louis Changcdec0802019-11-11 11:45:07 +08001158
1159 // TODO: Ensure that this is actually necessary here
1160 // Notify the voice session if required
1161 if (voiceSession != null) {
1162 try {
1163 voiceSession.taskStarted(intent, mTaskId);
1164 } catch (RemoteException e) {
1165 }
1166 }
1167 }
1168
1169 // First time we are adding the task to the system.
1170 if (oldParent == null && newParent != null) {
1171
1172 // TODO: Super random place to be doing this, but aligns with what used to be done
1173 // before we unified Task level. Look into if this can be done in a better place.
1174 updateOverrideConfigurationFromLaunchBounds();
1175 }
1176
Louis Changcdec0802019-11-11 11:45:07 +08001177 // Update task bounds if needed.
1178 adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
1179
1180 if (getWindowConfiguration().windowsAreScaleable()) {
1181 // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
1182 // while a resize is pending.
1183 forceWindowsScaleable(true /* force */);
1184 } else {
1185 forceWindowsScaleable(false /* force */);
1186 }
1187
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001188 mRootWindowContainer.updateUIDsPresentOnDisplay();
1189 }
1190
1191 void cleanUpActivityReferences(ActivityRecord r) {
1192 final WindowContainer parent = getParent();
1193 if (parent != null && parent.asTask() != null) {
1194 parent.asTask().cleanUpActivityReferences(r);
1195 return;
1196 }
1197 r.removeTimeouts();
1198 mExitingActivities.remove(r);
1199
1200 if (mResumedActivity != null && mResumedActivity == r) {
1201 setResumedActivity(null, "cleanUpActivityReferences");
1202 }
1203 if (mPausingActivity != null && mPausingActivity == r) {
1204 mPausingActivity = null;
1205 }
1206 }
1207
1208 /** @return the currently resumed activity. */
1209 ActivityRecord getResumedActivity() {
1210 return mResumedActivity;
1211 }
1212
1213 void setResumedActivity(ActivityRecord r, String reason) {
1214 if (mResumedActivity == r) {
1215 return;
1216 }
1217
1218 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) Slog.d(TAG_STACK,
1219 "setResumedActivity stack:" + this + " + from: "
1220 + mResumedActivity + " to:" + r + " reason:" + reason);
1221 mResumedActivity = r;
1222 mStackSupervisor.updateTopResumedActivityIfNeeded();
Louis Changcdec0802019-11-11 11:45:07 +08001223 }
1224
1225 void updateTaskMovement(boolean toFront) {
1226 if (isPersistable) {
1227 mLastTimeMoved = System.currentTimeMillis();
1228 // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
1229 // recently will be most negative, tasks sent to the bottom before that will be less
1230 // negative. Similarly for recent tasks moved to the top which will be most positive.
1231 if (!toFront) {
1232 mLastTimeMoved *= -1;
1233 }
1234 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001235 mRootWindowContainer.invalidateTaskLayers();
Louis Changcdec0802019-11-11 11:45:07 +08001236 }
1237
Louis Changcdec0802019-11-11 11:45:07 +08001238 // Close up recents linked list.
1239 private void closeRecentsChain() {
1240 if (mPrevAffiliate != null) {
1241 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
1242 }
1243 if (mNextAffiliate != null) {
1244 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
1245 }
1246 setPrevAffiliate(null);
1247 setNextAffiliate(null);
1248 }
1249
1250 void removedFromRecents() {
1251 closeRecentsChain();
1252 if (inRecents) {
1253 inRecents = false;
1254 mAtmService.notifyTaskPersisterLocked(this, false);
1255 }
1256
1257 clearRootProcess();
1258
1259 mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
1260 mTaskId, mUserId);
1261 }
1262
1263 void setTaskToAffiliateWith(Task taskToAffiliateWith) {
1264 closeRecentsChain();
1265 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
1266 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
1267 // Find the end
1268 while (taskToAffiliateWith.mNextAffiliate != null) {
1269 final Task nextRecents = taskToAffiliateWith.mNextAffiliate;
1270 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1271 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1272 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1273 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1274 nextRecents.setPrevAffiliate(null);
1275 }
1276 taskToAffiliateWith.setNextAffiliate(null);
1277 break;
1278 }
1279 taskToAffiliateWith = nextRecents;
1280 }
1281 taskToAffiliateWith.setNextAffiliate(this);
1282 setPrevAffiliate(taskToAffiliateWith);
1283 setNextAffiliate(null);
1284 }
1285
1286 /** Returns the intent for the root activity for this task */
1287 Intent getBaseIntent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001288 if (intent != null) return intent;
1289 if (affinityIntent != null) return affinityIntent;
1290 // Probably a task that contains other tasks, so return the intent for the top task?
1291 final Task topTask = getTopMostTask();
Evan Rosky0037e5f2019-11-05 10:26:24 -08001292 return (topTask != this && topTask != null) ? topTask.getBaseIntent() : null;
Louis Changcdec0802019-11-11 11:45:07 +08001293 }
1294
1295 /** Returns the first non-finishing activity from the bottom. */
1296 ActivityRecord getRootActivity() {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001297 // TODO: Figure out why we historical ignore relinquish identity for this case...
1298 return getRootActivity(true /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
1299 }
1300
1301 ActivityRecord getRootActivity(boolean setToBottomIfNone) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001302 return getRootActivity(false /*ignoreRelinquishIdentity*/, setToBottomIfNone);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001303 }
1304
1305 ActivityRecord getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001306 return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone);
Louis Changcdec0802019-11-11 11:45:07 +08001307 }
1308
Wale Ogunwale21e06482019-11-18 05:14:15 -08001309 ActivityRecord getTopNonFinishingActivity() {
1310 return getTopNonFinishingActivity(true /* includeOverlays */);
Louis Changcdec0802019-11-11 11:45:07 +08001311 }
1312
Wale Ogunwale21e06482019-11-18 05:14:15 -08001313 ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001314 return getTopActivity(false /*includeFinishing*/, includeOverlays);
Louis Changcdec0802019-11-11 11:45:07 +08001315 }
1316
1317 ActivityRecord topRunningActivityLocked() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001318 if (getParent() == null) {
1319 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001320 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001321 return getActivity(ActivityRecord::canBeTopRunning);
Louis Changcdec0802019-11-11 11:45:07 +08001322 }
1323
1324 /**
1325 * Return true if any activities in this task belongs to input uid.
1326 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001327 boolean isUidPresent(int uid) {
1328 final PooledPredicate p = PooledLambda.obtainPredicate(
1329 ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid);
1330 final boolean isUidPresent = getActivity(p) != null;
1331 p.recycle();
1332 return isUidPresent;
Louis Changcdec0802019-11-11 11:45:07 +08001333 }
1334
1335 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001336 if (getParent() == null) {
1337 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001338 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001339 return getActivity((r) -> r.mStartingWindowState == STARTING_WINDOW_SHOWN
1340 && r.canBeTopRunning());
Louis Changcdec0802019-11-11 11:45:07 +08001341 }
1342
1343 /**
1344 * Return the number of running activities, and the number of non-finishing/initializing
1345 * activities in the provided {@param reportOut} respectively.
1346 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001347 private void getNumRunningActivities(TaskActivitiesReport reportOut) {
Louis Changcdec0802019-11-11 11:45:07 +08001348 reportOut.reset();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001349 forAllActivities(reportOut);
Louis Changcdec0802019-11-11 11:45:07 +08001350 }
1351
1352 /**
1353 * Reorder the history stack so that the passed activity is brought to the front.
1354 */
1355 final void moveActivityToFrontLocked(ActivityRecord newTop) {
1356 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, "Removing and adding activity "
1357 + newTop + " to stack at top callers=" + Debug.getCallers(4));
1358
1359 positionChildAtTop(newTop);
1360 updateEffectiveIntent();
1361 }
1362
1363 @Override
1364 public int getActivityType() {
1365 final int applicationType = super.getActivityType();
1366 if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
1367 return applicationType;
1368 }
Louis Changa009c762020-02-26 11:21:31 +08001369 return getTopChild().getActivityType();
Louis Changcdec0802019-11-11 11:45:07 +08001370 }
1371
1372 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001373 void addChild(WindowContainer child, int index) {
Louis Changcdec0802019-11-11 11:45:07 +08001374 // If this task had any child before we added this one.
1375 boolean hadChild = hasChild();
1376
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001377 index = getAdjustedChildPosition(child, index);
1378 super.addChild(child, index);
Louis Changcdec0802019-11-11 11:45:07 +08001379
1380 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001381
Louis Changa009c762020-02-26 11:21:31 +08001382 // A rootable task that is now being added to be the child of an organized task. Making
1383 // sure the stack references is keep updated.
1384 if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001385 getDisplayArea().addStackReferenceIfNeeded((ActivityStack) child);
Louis Changa009c762020-02-26 11:21:31 +08001386 }
1387
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001388 // Make sure the list of display UID whitelists is updated
1389 // now that this record is in a new task.
1390 mRootWindowContainer.updateUIDsPresentOnDisplay();
1391
1392 final ActivityRecord r = child.asActivityRecord();
1393 if (r == null) return;
1394
Louis Changcdec0802019-11-11 11:45:07 +08001395 r.inHistory = true;
1396
Louis Changcdec0802019-11-11 11:45:07 +08001397 // Only set this based on the first activity
1398 if (!hadChild) {
1399 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1400 // Normally non-standard activity type for the activity record will be set when the
1401 // object is created, however we delay setting the standard application type until
1402 // this point so that the task can set the type for additional activities added in
1403 // the else condition below.
1404 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1405 }
1406 setActivityType(r.getActivityType());
1407 isPersistable = r.isPersistable();
1408 mCallingUid = r.launchedFromUid;
1409 mCallingPackage = r.launchedFromPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -08001410 mCallingFeatureId = r.launchedFromFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +08001411 // Clamp to [1, max].
1412 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1413 ActivityTaskManager.getMaxAppRecentsLimitStatic());
1414 } else {
1415 // Otherwise make all added activities match this one.
1416 r.setActivityType(getActivityType());
1417 }
1418
1419 updateEffectiveIntent();
Louis Changcdec0802019-11-11 11:45:07 +08001420 }
1421
1422 void addChild(ActivityRecord r) {
1423 addChild(r, Integer.MAX_VALUE /* add on top */);
1424 }
1425
1426 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001427 void removeChild(WindowContainer child) {
Louis Changa009c762020-02-26 11:21:31 +08001428 // A rootable child task that is now being removed from an organized task. Making sure
1429 // the stack references is keep updated.
1430 if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001431 getDisplayArea().removeStackReferenceIfNeeded((ActivityStack) child);
Louis Changa009c762020-02-26 11:21:31 +08001432 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001433 removeChild(child, "removeChild");
1434 }
1435
1436 void removeChild(WindowContainer r, String reason) {
Louis Changcdec0802019-11-11 11:45:07 +08001437 if (!mChildren.contains(r)) {
1438 Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
1439 return;
1440 }
1441
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001442 if (DEBUG_TASK_MOVEMENT) {
1443 Slog.d(TAG_WM, "removeChild: child=" + r + " reason=" + reason);
1444 }
Louis Changcdec0802019-11-11 11:45:07 +08001445 super.removeChild(r);
Louis Changcdec0802019-11-11 11:45:07 +08001446
1447 if (inPinnedWindowingMode()) {
1448 // We normally notify listeners of task stack changes on pause, however pinned stack
1449 // activities are normally in the paused state so no notification will be sent there
1450 // before the activity is removed. We send it here so instead.
1451 mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
1452 }
1453
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001454 final boolean isRootTask = isRootTask();
1455 if (isRootTask) {
1456 final DisplayContent display = getDisplayContent();
1457 if (display.isSingleTaskInstance()) {
1458 mAtmService.notifySingleTaskDisplayEmpty(display.mDisplayId);
1459 }
1460 display.mDisplayContent.setLayoutNeeded();
1461 }
1462
Louis Changcdec0802019-11-11 11:45:07 +08001463 if (hasChild()) {
1464 updateEffectiveIntent();
1465
1466 // The following block can be executed multiple times if there is more than one overlay.
1467 // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
1468 // of the task by id and exiting early if not found.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001469 if (onlyHasTaskOverlayActivities(true /*includeFinishing*/)) {
Louis Changcdec0802019-11-11 11:45:07 +08001470 // When destroying a task, tell the supervisor to remove it so that any activity it
1471 // has can be cleaned up correctly. This is currently the only place where we remove
1472 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
1473 // state into removeChild(), we just clear the task here before the other residual
1474 // work.
1475 // TODO: If the callers to removeChild() changes such that we have multiple places
1476 // where we are destroying the task, move this back into removeChild()
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001477 mStackSupervisor.removeTask(this, false /* killProcess */,
Louis Changcdec0802019-11-11 11:45:07 +08001478 !REMOVE_FROM_RECENTS, reason);
1479 }
Louis Changa009c762020-02-26 11:21:31 +08001480 } else if (!mReuseTask && !mCreatedByOrganizer) {
Louis Changcdec0802019-11-11 11:45:07 +08001481 // 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 +08001482 // or created by task organizer.
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001483 if (!isRootTask) {
1484 getStack().removeChild(this, reason);
1485 }
Jeff Changd136e772019-11-05 20:33:52 +08001486 EventLogTags.writeWmTaskRemoved(mTaskId,
Louis Changcdec0802019-11-11 11:45:07 +08001487 "removeChild: last r=" + r + " in t=" + this);
1488 removeIfPossible();
1489 }
1490 }
1491
1492 /**
Louis Changfd5539e2020-02-04 14:34:24 +08001493 * @return whether or not there are ONLY task overlay activities in the task.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001494 * If {@param includeFinishing} is set, then don't ignore finishing activities in the
1495 * check. If there are no task overlay activities, this call returns false.
Louis Changcdec0802019-11-11 11:45:07 +08001496 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001497 boolean onlyHasTaskOverlayActivities(boolean includeFinishing) {
Louis Changfd5539e2020-02-04 14:34:24 +08001498 int count = 0;
1499 for (int i = getChildCount() - 1; i >= 0; i--) {
1500 final ActivityRecord r = getChildAt(i).asActivityRecord();
1501 if (r == null) {
1502 // Has a child that is other than Activity.
1503 return false;
1504 }
1505 if (!includeFinishing && r.finishing) {
1506 continue;
1507 }
1508 if (!r.isTaskOverlay()) {
1509 return false;
1510 }
1511 count++;
Louis Changcdec0802019-11-11 11:45:07 +08001512 }
Louis Changfd5539e2020-02-04 14:34:24 +08001513 return count > 0;
Louis Changcdec0802019-11-11 11:45:07 +08001514 }
1515
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001516 private boolean autoRemoveFromRecents() {
Louis Changcdec0802019-11-11 11:45:07 +08001517 // We will automatically remove the task either if it has explicitly asked for
1518 // this, or it is empty and has never contained an activity that got shown to
1519 // the user.
Robert Carrde96c8a2020-03-24 15:22:21 -07001520 return autoRemoveRecents || (!hasChild() && !getHasBeenVisible());
Louis Changcdec0802019-11-11 11:45:07 +08001521 }
1522
1523 /**
1524 * Completely remove all activities associated with an existing
1525 * task starting at a specified index.
1526 */
Wale Ogunwale21e06482019-11-18 05:14:15 -08001527 private void performClearTaskAtIndexLocked(String reason) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001528 // Broken down into to cases to avoid object create due to capturing mStack.
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001529 if (getStack() == null) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001530 forAllActivities((r) -> {
1531 if (r.finishing) return;
Louis Changcdec0802019-11-11 11:45:07 +08001532 // Task was restored from persistent storage.
1533 r.takeFromHistory();
1534 removeChild(r);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001535 });
1536 } else {
1537 forAllActivities((r) -> {
1538 if (r.finishing) return;
1539 // TODO: figure-out how to avoid object creation due to capture of reason variable.
1540 r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
1541 false /* oomAdj */);
1542 });
Louis Changcdec0802019-11-11 11:45:07 +08001543 }
1544 }
1545
1546 /**
1547 * Completely remove all activities associated with an existing task.
1548 */
1549 void performClearTaskLocked() {
1550 mReuseTask = true;
Wale Ogunwale21e06482019-11-18 05:14:15 -08001551 performClearTaskAtIndexLocked("clear-task-all");
Louis Changcdec0802019-11-11 11:45:07 +08001552 mReuseTask = false;
1553 }
1554
1555 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1556 mReuseTask = true;
1557 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1558 mReuseTask = false;
1559 return result;
1560 }
1561
1562 /**
1563 * Perform clear operation as requested by
1564 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1565 * stack to the given task, then look for
1566 * an instance of that activity in the stack and, if found, finish all
1567 * activities on top of it and return the instance.
1568 *
1569 * @param newR Description of the new activity being started.
1570 * @return Returns the old activity that should be continued to be used,
1571 * or {@code null} if none was found.
1572 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001573 private ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
1574 final ActivityRecord r = findActivityInHistory(newR.mActivityComponent);
1575 if (r == null) return null;
Louis Changcdec0802019-11-11 11:45:07 +08001576
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001577 final PooledFunction f = PooledLambda.obtainFunction(Task::finishActivityAbove,
1578 PooledLambda.__(ActivityRecord.class), r);
1579 forAllActivities(f);
1580 f.recycle();
Louis Changcdec0802019-11-11 11:45:07 +08001581
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001582 // Finally, if this is a normal launch mode (that is, not expecting onNewIntent()), then we
1583 // will finish the current instance of the activity so a new fresh one can be started.
1584 if (r.launchMode == ActivityInfo.LAUNCH_MULTIPLE
1585 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1586 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
1587 if (!r.finishing) {
1588 r.finishIfPossible("clear-task-top", false /* oomAdj */);
1589 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001590 }
1591 }
1592
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001593 return r;
1594 }
1595
1596 private static boolean finishActivityAbove(ActivityRecord r, ActivityRecord boundaryActivity) {
1597 // Stop operation once we reach the boundary activity.
1598 if (r == boundaryActivity) return true;
1599
1600 if (!r.finishing) {
1601 final ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
1602 if (opts != null) {
1603 // TODO: Why is this updating the boundary activity vs. the current activity???
1604 boundaryActivity.updateOptionsLocked(opts);
1605 }
1606 r.finishIfPossible("clear-task-stack", false /* oomAdj */);
1607 }
1608
1609 return false;
Louis Changcdec0802019-11-11 11:45:07 +08001610 }
1611
1612 void removeTaskActivitiesLocked(String reason) {
1613 // Just remove the entire task.
Wale Ogunwale21e06482019-11-18 05:14:15 -08001614 performClearTaskAtIndexLocked(reason);
Louis Changcdec0802019-11-11 11:45:07 +08001615 }
1616
1617 String lockTaskAuthToString() {
1618 switch (mLockTaskAuth) {
1619 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1620 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1621 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1622 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
1623 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
1624 default: return "unknown=" + mLockTaskAuth;
1625 }
1626 }
1627
1628 void setLockTaskAuth() {
1629 setLockTaskAuth(getRootActivity());
1630 }
1631
1632 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1633 if (r == null) {
1634 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1635 return;
1636 }
1637
1638 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
1639 final LockTaskController lockTaskController = mAtmService.getLockTaskController();
1640 switch (r.lockTaskLaunchMode) {
1641 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
1642 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
1643 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
1644 break;
1645
1646 case LOCK_TASK_LAUNCH_MODE_NEVER:
1647 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
1648 break;
1649
1650 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
1651 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
1652 break;
1653
1654 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
1655 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
1656 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
1657 break;
1658 }
1659 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this
1660 + " mLockTaskAuth=" + lockTaskAuthToString());
1661 }
1662
1663 @Override
1664 public boolean supportsSplitScreenWindowingMode() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001665 final Task topTask = getTopMostTask();
1666 return super.supportsSplitScreenWindowingMode()
1667 && (topTask == null || topTask.supportsSplitScreenWindowingModeInner());
1668 }
1669
1670 private boolean supportsSplitScreenWindowingModeInner() {
Louis Changcdec0802019-11-11 11:45:07 +08001671 // A task can not be docked even if it is considered resizeable because it only supports
1672 // picture-in-picture mode but has a non-resizeable resizeMode
1673 return super.supportsSplitScreenWindowingMode()
Louis Changcdec0802019-11-11 11:45:07 +08001674 && mAtmService.mSupportsSplitScreenMultiWindow
1675 && (mAtmService.mForceResizableActivities
1676 || (isResizeable(false /* checkSupportsPip */)
1677 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
1678 }
1679
1680 /**
1681 * Check whether this task can be launched on the specified display.
1682 *
1683 * @param displayId Target display id.
1684 * @return {@code true} if either it is the default display or this activity can be put on a
1685 * secondary display.
1686 */
1687 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001688 return mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Louis Changcdec0802019-11-11 11:45:07 +08001689 -1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
1690 }
1691
1692 /**
1693 * Check that a given bounds matches the application requested orientation.
1694 *
1695 * @param bounds The bounds to be tested.
1696 * @return True if the requested bounds are okay for a resizing request.
1697 */
1698 private boolean canResizeToBounds(Rect bounds) {
1699 if (bounds == null || !inFreeformWindowingMode()) {
1700 // Note: If not on the freeform workspace, we ignore the bounds.
1701 return true;
1702 }
1703 final boolean landscape = bounds.width() > bounds.height();
1704 final Rect configBounds = getRequestedOverrideBounds();
1705 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
1706 return configBounds.isEmpty()
1707 || landscape == (configBounds.width() > configBounds.height());
1708 }
1709 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1710 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1711 }
1712
1713 /**
1714 * @return {@code true} if the task is being cleared for the purposes of being reused.
1715 */
1716 boolean isClearingToReuseTask() {
1717 return mReuseTask;
1718 }
1719
1720 /**
1721 * Find the activity in the history stack within the given task. Returns
1722 * the index within the history at which it's found, or < 0 if not found.
1723 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001724 ActivityRecord findActivityInHistory(ComponentName component) {
1725 final PooledPredicate p = PooledLambda.obtainPredicate(Task::matchesActivityInHistory,
1726 PooledLambda.__(ActivityRecord.class), component);
1727 final ActivityRecord r = getActivity(p);
1728 p.recycle();
1729 return r;
1730 }
1731
1732 private static boolean matchesActivityInHistory(
1733 ActivityRecord r, ComponentName activityComponent) {
1734 return !r.finishing && r.mActivityComponent.equals(activityComponent);
Louis Changcdec0802019-11-11 11:45:07 +08001735 }
1736
1737 /** Updates the last task description values. */
1738 void updateTaskDescription() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001739 final ActivityRecord root = getRootActivity(true);
1740 if (root == null) return;
1741
1742 final TaskDescription taskDescription = new TaskDescription();
1743 final PooledFunction f = PooledLambda.obtainFunction(
1744 Task::setTaskDescriptionFromActivityAboveRoot,
1745 PooledLambda.__(ActivityRecord.class), root, taskDescription);
1746 forAllActivities(f);
1747 f.recycle();
1748 taskDescription.setResizeMode(mResizeMode);
1749 taskDescription.setMinWidth(mMinWidth);
1750 taskDescription.setMinHeight(mMinHeight);
1751 setTaskDescription(taskDescription);
1752 // Update the task affiliation color if we are the parent of the group
1753 if (mTaskId == mAffiliatedTaskId) {
1754 mAffiliatedTaskColor = taskDescription.getPrimaryColor();
Louis Changcdec0802019-11-11 11:45:07 +08001755 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001756 mAtmService.getTaskChangeNotificationController().notifyTaskDescriptionChanged(
1757 getTaskInfo());
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001758
1759 final WindowContainer parent = getParent();
1760 if (parent != null) {
1761 final Task t = parent.asTask();
1762 if (t != null) {
1763 t.updateTaskDescription();
1764 }
1765 }
Winson Chung1df39e22020-04-09 14:30:55 -07001766
1767 if (isOrganized()) {
1768 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
1769 }
Louis Changcdec0802019-11-11 11:45:07 +08001770 }
1771
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001772 private static boolean setTaskDescriptionFromActivityAboveRoot(
1773 ActivityRecord r, ActivityRecord root, TaskDescription td) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001774 if (!r.isTaskOverlay() && r.taskDescription != null) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001775 final TaskDescription atd = r.taskDescription;
1776 if (td.getLabel() == null) {
1777 td.setLabel(atd.getLabel());
Louis Changcdec0802019-11-11 11:45:07 +08001778 }
Winson Chungd6722032020-02-18 15:16:08 -08001779 if (td.getRawIcon() == null) {
1780 td.setIcon(atd.getRawIcon());
Louis Changcdec0802019-11-11 11:45:07 +08001781 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001782 if (td.getIconFilename() == null) {
1783 td.setIconFilename(atd.getIconFilename());
1784 }
1785 if (td.getPrimaryColor() == 0) {
1786 td.setPrimaryColor(atd.getPrimaryColor());
1787 }
1788 if (td.getBackgroundColor() == 0) {
1789 td.setBackgroundColor(atd.getBackgroundColor());
1790 }
1791 if (td.getStatusBarColor() == 0) {
1792 td.setStatusBarColor(atd.getStatusBarColor());
1793 td.setEnsureStatusBarContrastWhenTransparent(
1794 atd.getEnsureStatusBarContrastWhenTransparent());
1795 }
1796 if (td.getNavigationBarColor() == 0) {
1797 td.setNavigationBarColor(atd.getNavigationBarColor());
1798 td.setEnsureNavigationBarContrastWhenTransparent(
1799 atd.getEnsureNavigationBarContrastWhenTransparent());
1800 }
1801
Louis Changcdec0802019-11-11 11:45:07 +08001802 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001803
1804 // End search once we get to root.
1805 return r == root;
Louis Changcdec0802019-11-11 11:45:07 +08001806 }
1807
1808 // TODO (AM refactor): Invoke automatically when there is a change in children
1809 @VisibleForTesting
1810 void updateEffectiveIntent() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001811 final ActivityRecord root = getRootActivity(true /*setToBottomIfNone*/);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001812 if (root != null) {
1813 setIntent(root);
1814 // Update the task description when the activities change
1815 updateTaskDescription();
1816 }
Louis Changcdec0802019-11-11 11:45:07 +08001817 }
1818
1819 void adjustForMinimalTaskDimensions(Rect bounds, Rect previousBounds) {
Evan Rosky70213702019-11-05 10:26:24 -08001820 final Rect parentBounds = getParent() != null ? getParent().getBounds() : null;
1821 if (bounds == null
1822 || (bounds.isEmpty() && (parentBounds == null || parentBounds.isEmpty()))) {
Louis Changcdec0802019-11-11 11:45:07 +08001823 return;
1824 }
1825 int minWidth = mMinWidth;
1826 int minHeight = mMinHeight;
1827 // If the task has no requested minimal size, we'd like to enforce a minimal size
1828 // so that the user can not render the task too small to manipulate. We don't need
1829 // to do this for the pinned stack as the bounds are controlled by the system.
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001830 if (!inPinnedWindowingMode() && getStack() != null) {
1831 final int defaultMinSizeDp = mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001832 final DisplayContent display = getDisplayContent();
Louis Changcdec0802019-11-11 11:45:07 +08001833 final float density =
1834 (float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
1835 final int defaultMinSize = (int) (defaultMinSizeDp * density);
1836
1837 if (minWidth == INVALID_MIN_SIZE) {
1838 minWidth = defaultMinSize;
1839 }
1840 if (minHeight == INVALID_MIN_SIZE) {
1841 minHeight = defaultMinSize;
1842 }
1843 }
Evan Rosky70213702019-11-05 10:26:24 -08001844 if (bounds.isEmpty()) {
1845 // If inheriting parent bounds, check if parent bounds adhere to minimum size. If they
1846 // do, we can just skip.
1847 if (parentBounds.width() >= minWidth && parentBounds.height() >= minHeight) {
1848 return;
1849 }
1850 bounds.set(parentBounds);
1851 }
Louis Changcdec0802019-11-11 11:45:07 +08001852 final boolean adjustWidth = minWidth > bounds.width();
1853 final boolean adjustHeight = minHeight > bounds.height();
1854 if (!(adjustWidth || adjustHeight)) {
1855 return;
1856 }
1857
1858 if (adjustWidth) {
1859 if (!previousBounds.isEmpty() && bounds.right == previousBounds.right) {
1860 bounds.left = bounds.right - minWidth;
1861 } else {
1862 // Either left bounds match, or neither match, or the previous bounds were
1863 // fullscreen and we default to keeping left.
1864 bounds.right = bounds.left + minWidth;
1865 }
1866 }
1867 if (adjustHeight) {
1868 if (!previousBounds.isEmpty() && bounds.bottom == previousBounds.bottom) {
1869 bounds.top = bounds.bottom - minHeight;
1870 } else {
1871 // Either top bounds match, or neither match, or the previous bounds were
1872 // fullscreen and we default to keeping top.
1873 bounds.bottom = bounds.top + minHeight;
1874 }
1875 }
1876 }
1877
1878 void setLastNonFullscreenBounds(Rect bounds) {
1879 if (mLastNonFullscreenBounds == null) {
1880 mLastNonFullscreenBounds = new Rect(bounds);
1881 } else {
1882 mLastNonFullscreenBounds.set(bounds);
1883 }
1884 }
1885
1886 /**
1887 * This should be called when an child activity changes state. This should only
1888 * be called from
1889 * {@link ActivityRecord#setState(ActivityState, String)} .
1890 * @param record The {@link ActivityRecord} whose state has changed.
1891 * @param state The new state.
1892 * @param reason The reason for the change.
1893 */
1894 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001895 final Task parentTask = getParent().asTask();
1896 if (parentTask != null) {
1897 parentTask.onActivityStateChanged(record, state, reason);
Louis Changa009c762020-02-26 11:21:31 +08001898 // We still want to update the resumed activity if the parent task is created by
1899 // organizer in order to keep the information synced once got reparented out from the
1900 // organized task.
1901 if (!parentTask.mCreatedByOrganizer) {
1902 return;
1903 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001904 }
Louis Changcdec0802019-11-11 11:45:07 +08001905
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001906 if (record == mResumedActivity && state != RESUMED) {
1907 setResumedActivity(null, reason + " - onActivityStateChanged");
1908 }
1909
1910 if (state == RESUMED) {
1911 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
1912 Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" + reason);
1913 }
1914 setResumedActivity(record, reason + " - onActivityStateChanged");
1915 if (record == mRootWindowContainer.getTopResumedActivity()) {
1916 mAtmService.setResumedActivityUncheckLocked(record, reason);
1917 }
1918 mStackSupervisor.mRecentTasks.add(record.getTask());
Louis Changcdec0802019-11-11 11:45:07 +08001919 }
1920 }
1921
1922 @Override
1923 public void onConfigurationChanged(Configuration newParentConfig) {
1924 // Check if the new configuration supports persistent bounds (eg. is Freeform) and if so
1925 // restore the last recorded non-fullscreen bounds.
1926 final boolean prevPersistTaskBounds = getWindowConfiguration().persistTaskBounds();
1927 final boolean nextPersistTaskBounds =
1928 getRequestedOverrideConfiguration().windowConfiguration.persistTaskBounds()
1929 || newParentConfig.windowConfiguration.persistTaskBounds();
1930 if (!prevPersistTaskBounds && nextPersistTaskBounds
1931 && mLastNonFullscreenBounds != null && !mLastNonFullscreenBounds.isEmpty()) {
1932 // Bypass onRequestedOverrideConfigurationChanged here to avoid infinite loop.
1933 getRequestedOverrideConfiguration().windowConfiguration
1934 .setBounds(mLastNonFullscreenBounds);
1935 }
1936
Evan Rosky55bddd82020-01-29 13:07:18 -08001937 final int prevWinMode = getWindowingMode();
1938 mTmpPrevBounds.set(getBounds());
Louis Changcdec0802019-11-11 11:45:07 +08001939 final boolean wasInMultiWindowMode = inMultiWindowMode();
1940 super.onConfigurationChanged(newParentConfig);
1941 if (wasInMultiWindowMode != inMultiWindowMode()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001942 mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Louis Changcdec0802019-11-11 11:45:07 +08001943 }
1944
Evan Rosky55bddd82020-01-29 13:07:18 -08001945 final int newWinMode = getWindowingMode();
1946 if ((prevWinMode != newWinMode) && (mDisplayContent != null)
1947 && shouldStartChangeTransition(prevWinMode, newWinMode)) {
1948 initializeChangeTransition(mTmpPrevBounds);
1949 }
1950
Louis Changcdec0802019-11-11 11:45:07 +08001951 // If the configuration supports persistent bounds (eg. Freeform), keep track of the
1952 // current (non-fullscreen) bounds for persistence.
1953 if (getWindowConfiguration().persistTaskBounds()) {
1954 final Rect currentBounds = getRequestedOverrideBounds();
1955 if (!currentBounds.isEmpty()) {
1956 setLastNonFullscreenBounds(currentBounds);
1957 }
1958 }
1959 // TODO: Should also take care of Pip mode changes here.
1960
1961 saveLaunchingStateIfNeeded();
Evan Roskyf64f5da2020-03-16 13:47:48 -07001962 final boolean taskOrgChanged = updateTaskOrganizerState(false /* forceUpdate */);
1963 // If the task organizer has changed, then it will already be receiving taskAppeared with
1964 // the latest task-info thus the task-info won't have changed.
Winson Chung1df39e22020-04-09 14:30:55 -07001965 if (!taskOrgChanged && isOrganized()) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07001966 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, false /* force */);
1967 }
Louis Changcdec0802019-11-11 11:45:07 +08001968 }
1969
1970 /**
Evan Rosky55bddd82020-01-29 13:07:18 -08001971 * Initializes a change transition. See {@link SurfaceFreezer} for more information.
1972 */
1973 private void initializeChangeTransition(Rect startBounds) {
1974 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1975 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1976 mDisplayContent.mChangingContainers.add(this);
1977
1978 mSurfaceFreezer.freeze(getPendingTransaction(), startBounds);
1979 }
1980
1981 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
1982 if (mWmService.mDisableTransitionAnimation
1983 || !isVisible()
1984 || getDisplayContent().mAppTransition.isTransitionSet()
1985 || getSurfaceControl() == null) {
1986 return false;
1987 }
1988 // Only do an animation into and out-of freeform mode for now. Other mode
1989 // transition animations are currently handled by system-ui.
1990 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1991 }
1992
1993 @VisibleForTesting
1994 boolean isInChangeTransition() {
1995 return mSurfaceFreezer.hasLeash() || AppTransition.isChangeTransit(mTransit);
1996 }
1997
1998 @Override
1999 public SurfaceControl getFreezeSnapshotTarget() {
2000 final int transit = mDisplayContent.mAppTransition.getAppTransition();
2001 if (!AppTransition.isChangeTransit(transit)) {
2002 return null;
2003 }
2004 // Skip creating snapshot if this transition is controlled by a remote animator which
2005 // doesn't need it.
2006 final ArraySet<Integer> activityTypes = new ArraySet<>();
2007 activityTypes.add(getActivityType());
2008 final RemoteAnimationAdapter adapter =
2009 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
2010 this, transit, activityTypes);
2011 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
2012 return null;
2013 }
2014 return getSurfaceControl();
2015 }
2016
2017 @Override
2018 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
2019 final long token = proto.start(fieldId);
2020 proto.write(HASH_CODE, System.identityHashCode(this));
2021 proto.write(USER_ID, mUserId);
2022 proto.write(TITLE, intent != null && intent.getComponent() != null
2023 ? intent.getComponent().flattenToShortString() : "Task");
2024 proto.end(token);
2025 }
2026
2027 /**
Louis Changcdec0802019-11-11 11:45:07 +08002028 * Saves launching state if necessary so that we can launch the activity to its latest state.
2029 * It only saves state if this task has been shown to user and it's in fullscreen or freeform
2030 * mode on freeform displays.
2031 */
Garfield Tan8b096b22020-01-07 14:55:20 -08002032 private void saveLaunchingStateIfNeeded() {
2033 saveLaunchingStateIfNeeded(getDisplayContent());
2034 }
2035
2036 private void saveLaunchingStateIfNeeded(DisplayContent display) {
Robert Carrde96c8a2020-03-24 15:22:21 -07002037 if (!getHasBeenVisible()) {
Louis Changcdec0802019-11-11 11:45:07 +08002038 // Not ever visible to user.
2039 return;
2040 }
2041
2042 final int windowingMode = getWindowingMode();
2043 if (windowingMode != WINDOWING_MODE_FULLSCREEN
2044 && windowingMode != WINDOWING_MODE_FREEFORM) {
2045 return;
2046 }
2047
2048 // Don't persist state if display isn't in freeform mode. Then the task will be launched
2049 // back to its last state in a freeform display when it's launched in a freeform display
2050 // next time.
2051 if (getWindowConfiguration().getDisplayWindowingMode() != WINDOWING_MODE_FREEFORM) {
2052 return;
2053 }
2054
2055 // Saves the new state so that we can launch the activity at the same location.
Garfield Tan8b096b22020-01-07 14:55:20 -08002056 mStackSupervisor.mLaunchParamsPersister.saveTask(this, display);
Louis Changcdec0802019-11-11 11:45:07 +08002057 }
2058
2059 /**
2060 * Adjust bounds to stay within stack bounds.
2061 *
2062 * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
2063 * that keep them unchanged, but be contained within the stack bounds.
2064 *
2065 * @param bounds Bounds to be adjusted.
2066 * @param stackBounds Bounds within which the other bounds should remain.
2067 * @param overlapPxX The amount of px required to be visible in the X dimension.
2068 * @param overlapPxY The amount of px required to be visible in the Y dimension.
2069 */
2070 private static void fitWithinBounds(Rect bounds, Rect stackBounds, int overlapPxX,
2071 int overlapPxY) {
2072 if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
2073 return;
2074 }
2075
2076 // For each side of the parent (eg. left), check if the opposing side of the window (eg.
2077 // right) is at least overlap pixels away. If less, offset the window by that difference.
2078 int horizontalDiff = 0;
2079 // If window is smaller than overlap, use it's smallest dimension instead
2080 int overlapLR = Math.min(overlapPxX, bounds.width());
2081 if (bounds.right < (stackBounds.left + overlapLR)) {
2082 horizontalDiff = overlapLR - (bounds.right - stackBounds.left);
2083 } else if (bounds.left > (stackBounds.right - overlapLR)) {
2084 horizontalDiff = -(overlapLR - (stackBounds.right - bounds.left));
2085 }
2086 int verticalDiff = 0;
2087 int overlapTB = Math.min(overlapPxY, bounds.width());
2088 if (bounds.bottom < (stackBounds.top + overlapTB)) {
2089 verticalDiff = overlapTB - (bounds.bottom - stackBounds.top);
2090 } else if (bounds.top > (stackBounds.bottom - overlapTB)) {
2091 verticalDiff = -(overlapTB - (stackBounds.bottom - bounds.top));
2092 }
2093 bounds.offset(horizontalDiff, verticalDiff);
2094 }
2095
2096 /**
2097 * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
2098 * intersectBounds on a side, then the respective side will not be intersected.
2099 *
2100 * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
2101 * inset on that side is no-longer applicable. This scenario happens when a task's minimal
2102 * bounds are larger than the provided parent/display bounds.
2103 *
2104 * @param inOutBounds the bounds to intersect.
2105 * @param intersectBounds the bounds to intersect with.
2106 * @param intersectInsets insets to apply to intersectBounds before intersecting.
2107 */
2108 static void intersectWithInsetsIfFits(
2109 Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
2110 if (inOutBounds.right <= intersectBounds.right) {
2111 inOutBounds.right =
2112 Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
2113 }
2114 if (inOutBounds.bottom <= intersectBounds.bottom) {
2115 inOutBounds.bottom =
2116 Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
2117 }
2118 if (inOutBounds.left >= intersectBounds.left) {
2119 inOutBounds.left =
2120 Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
2121 }
2122 if (inOutBounds.top >= intersectBounds.top) {
2123 inOutBounds.top =
2124 Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
2125 }
2126 }
2127
2128 /**
2129 * Gets bounds with non-decor and stable insets applied respectively.
2130 *
2131 * If bounds overhangs the display, those edges will not get insets. See
2132 * {@link #intersectWithInsetsIfFits}
2133 *
2134 * @param outNonDecorBounds where to place bounds with non-decor insets applied.
2135 * @param outStableBounds where to place bounds with stable insets applied.
2136 * @param bounds the bounds to inset.
2137 */
2138 private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
2139 DisplayInfo displayInfo) {
2140 outNonDecorBounds.set(bounds);
2141 outStableBounds.set(bounds);
2142 if (getStack() == null || getStack().getDisplay() == null) {
2143 return;
2144 }
2145 DisplayPolicy policy = getStack().getDisplay().mDisplayContent.getDisplayPolicy();
2146 if (policy == null) {
2147 return;
2148 }
2149 mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
2150
2151 policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
2152 displayInfo.logicalHeight, displayInfo.displayCutout, mTmpInsets);
2153 intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);
2154
2155 policy.convertNonDecorInsetsToStableInsets(mTmpInsets, displayInfo.rotation);
2156 intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
2157 }
2158
Riddle Hsu23e18a92020-03-10 00:26:51 +08002159 /**
2160 * Forces the app bounds related configuration can be computed by
2161 * {@link #computeConfigResourceOverrides(Configuration, Configuration, DisplayInfo,
2162 * ActivityRecord.CompatDisplayInsets)}.
2163 */
2164 private static void invalidateAppBoundsConfig(@NonNull Configuration inOutConfig) {
2165 final Rect appBounds = inOutConfig.windowConfiguration.getAppBounds();
2166 if (appBounds != null) {
2167 appBounds.setEmpty();
2168 }
2169 inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
2170 inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
2171 }
2172
Louis Changcdec0802019-11-11 11:45:07 +08002173 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Riddle Hsu9264a272020-03-04 23:10:41 +08002174 @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo) {
2175 if (overrideDisplayInfo != null) {
2176 // Make sure the screen related configs can be computed by the provided display info.
Riddle Hsu9264a272020-03-04 23:10:41 +08002177 inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
Riddle Hsu23e18a92020-03-10 00:26:51 +08002178 invalidateAppBoundsConfig(inOutConfig);
Riddle Hsu9264a272020-03-04 23:10:41 +08002179 }
2180 computeConfigResourceOverrides(inOutConfig, parentConfig, overrideDisplayInfo,
2181 null /* compatInsets */);
2182 }
2183
2184 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Louis Changcdec0802019-11-11 11:45:07 +08002185 @NonNull Configuration parentConfig) {
Riddle Hsu9264a272020-03-04 23:10:41 +08002186 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
2187 null /* compatInsets */);
2188 }
2189
2190 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
2191 @NonNull Configuration parentConfig,
2192 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
Riddle Hsu23e18a92020-03-10 00:26:51 +08002193 if (compatInsets != null) {
2194 // Make sure the app bounds can be computed by the compat insets.
2195 invalidateAppBoundsConfig(inOutConfig);
2196 }
Riddle Hsu9264a272020-03-04 23:10:41 +08002197 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
2198 compatInsets);
Louis Changcdec0802019-11-11 11:45:07 +08002199 }
2200
2201 /**
2202 * Calculates configuration values used by the client to get resources. This should be run
2203 * using app-facing bounds (bounds unmodified by animations or transient interactions).
2204 *
2205 * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
2206 * configuring an "inherit-bounds" window which means that all configuration settings would
2207 * just be inherited from the parent configuration.
2208 **/
2209 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Riddle Hsu9264a272020-03-04 23:10:41 +08002210 @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo,
Louis Changcdec0802019-11-11 11:45:07 +08002211 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
2212 int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
2213 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2214 windowingMode = parentConfig.windowConfiguration.getWindowingMode();
2215 }
2216
2217 float density = inOutConfig.densityDpi;
2218 if (density == Configuration.DENSITY_DPI_UNDEFINED) {
2219 density = parentConfig.densityDpi;
2220 }
2221 density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
2222
Evan Rosky70213702019-11-05 10:26:24 -08002223 final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds();
2224 if (resolvedBounds == null) {
2225 mTmpFullBounds.setEmpty();
2226 } else {
2227 mTmpFullBounds.set(resolvedBounds);
2228 }
2229 if (mTmpFullBounds.isEmpty()) {
2230 mTmpFullBounds.set(parentConfig.windowConfiguration.getBounds());
2231 }
2232
Louis Changcdec0802019-11-11 11:45:07 +08002233 Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2234 if (outAppBounds == null || outAppBounds.isEmpty()) {
Evan Rosky70213702019-11-05 10:26:24 -08002235 inOutConfig.windowConfiguration.setAppBounds(mTmpFullBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002236 outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2237 }
2238 // Non-null compatibility insets means the activity prefers to keep its original size, so
2239 // the out bounds doesn't need to be restricted by the parent.
2240 final boolean insideParentBounds = compatInsets == null;
2241 if (insideParentBounds && windowingMode != WINDOWING_MODE_FREEFORM) {
2242 final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
2243 if (parentAppBounds != null && !parentAppBounds.isEmpty()) {
2244 outAppBounds.intersect(parentAppBounds);
2245 }
2246 }
2247
2248 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
2249 || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
jaehoon.kim643293e2019-11-08 06:36:28 +09002250 if (insideParentBounds && WindowConfiguration.isFloating(windowingMode)) {
2251 mTmpNonDecorBounds.set(mTmpFullBounds);
2252 mTmpStableBounds.set(mTmpFullBounds);
Riddle Hsu9264a272020-03-04 23:10:41 +08002253 } else if (insideParentBounds
2254 && (overrideDisplayInfo != null || getDisplayContent() != null)) {
2255 final DisplayInfo di = overrideDisplayInfo != null
2256 ? overrideDisplayInfo
2257 : getDisplayContent().getDisplayInfo();
Louis Changcdec0802019-11-11 11:45:07 +08002258
2259 // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
2260 // area, i.e. the screen area without the system bars.
2261 // The non decor inset are areas that could never be removed in Honeycomb. See
2262 // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
Evan Rosky70213702019-11-05 10:26:24 -08002263 calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di);
Louis Changcdec0802019-11-11 11:45:07 +08002264 } else {
2265 // Apply the given non-decor and stable insets to calculate the corresponding bounds
2266 // for screen size of configuration.
2267 int rotation = inOutConfig.windowConfiguration.getRotation();
2268 if (rotation == ROTATION_UNDEFINED) {
2269 rotation = parentConfig.windowConfiguration.getRotation();
2270 }
2271 if (rotation != ROTATION_UNDEFINED && compatInsets != null) {
Evan Rosky70213702019-11-05 10:26:24 -08002272 mTmpNonDecorBounds.set(mTmpFullBounds);
2273 mTmpStableBounds.set(mTmpFullBounds);
Riddle Hsue47501b2020-02-18 12:45:41 +08002274 compatInsets.getBoundsByRotation(mTmpBounds, rotation);
Louis Changcdec0802019-11-11 11:45:07 +08002275 intersectWithInsetsIfFits(mTmpNonDecorBounds, mTmpBounds,
2276 compatInsets.mNonDecorInsets[rotation]);
2277 intersectWithInsetsIfFits(mTmpStableBounds, mTmpBounds,
2278 compatInsets.mStableInsets[rotation]);
2279 outAppBounds.set(mTmpNonDecorBounds);
2280 } else {
2281 // Set to app bounds because it excludes decor insets.
2282 mTmpNonDecorBounds.set(outAppBounds);
2283 mTmpStableBounds.set(outAppBounds);
2284 }
2285 }
2286
2287 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
2288 final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density);
2289 inOutConfig.screenWidthDp = insideParentBounds
2290 ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
2291 : overrideScreenWidthDp;
2292 }
2293 if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2294 final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
2295 inOutConfig.screenHeightDp = insideParentBounds
2296 ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
2297 : overrideScreenHeightDp;
2298 }
2299
2300 if (inOutConfig.smallestScreenWidthDp
2301 == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2302 if (WindowConfiguration.isFloating(windowingMode)) {
2303 // For floating tasks, calculate the smallest width from the bounds of the task
2304 inOutConfig.smallestScreenWidthDp = (int) (
Evan Rosky70213702019-11-05 10:26:24 -08002305 Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density);
Louis Changcdec0802019-11-11 11:45:07 +08002306 }
2307 // otherwise, it will just inherit
2308 }
2309 }
2310
2311 if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
2312 inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
2313 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
2314 }
2315 if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
2316 // For calculating screen layout, we need to use the non-decor inset screen area for the
2317 // calculation for compatibility reasons, i.e. screen area without system bars that
2318 // could never go away in Honeycomb.
2319 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
2320 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Louis Changcdec0802019-11-11 11:45:07 +08002321 // Reducing the screen layout starting from its parent config.
Riddle Hsuca928562019-11-22 01:04:14 +08002322 inOutConfig.screenLayout = computeScreenLayoutOverride(parentConfig.screenLayout,
2323 compatScreenWidthDp, compatScreenHeightDp);
Louis Changcdec0802019-11-11 11:45:07 +08002324 }
2325 }
2326
Riddle Hsuca928562019-11-22 01:04:14 +08002327 /** Computes LONG, SIZE and COMPAT parts of {@link Configuration#screenLayout}. */
2328 static int computeScreenLayoutOverride(int sourceScreenLayout, int screenWidthDp,
2329 int screenHeightDp) {
2330 sourceScreenLayout = sourceScreenLayout
2331 & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
2332 final int longSize = Math.max(screenWidthDp, screenHeightDp);
2333 final int shortSize = Math.min(screenWidthDp, screenHeightDp);
2334 return Configuration.reduceScreenLayout(sourceScreenLayout, longSize, shortSize);
2335 }
2336
Louis Changcdec0802019-11-11 11:45:07 +08002337 @Override
2338 void resolveOverrideConfiguration(Configuration newParentConfig) {
2339 mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
Louis Changdff902b2020-03-31 13:32:47 +08002340 super.resolveOverrideConfiguration(newParentConfig);
2341
2342 // Resolve override windowing mode to fullscreen for home task (even on freeform
2343 // display), or split-screen-secondary if in split-screen mode.
Louis Changcdec0802019-11-11 11:45:07 +08002344 int windowingMode =
Wale Ogunwale0d465192020-01-23 19:14:44 -08002345 getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
Louis Changdff902b2020-03-31 13:32:47 +08002346 if (getActivityType() == ACTIVITY_TYPE_HOME && windowingMode == WINDOWING_MODE_UNDEFINED) {
2347 windowingMode = inSplitScreenWindowingMode() ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
2348 : WINDOWING_MODE_FULLSCREEN;
2349 getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
2350 }
2351
2352 if (!isLeafTask()) {
2353 // Compute configuration overrides for tasks that created by organizer, so that
2354 // organizer can get the correct configuration from those tasks.
2355 if (mCreatedByOrganizer) {
2356 computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
2357 }
2358 return;
2359 }
2360
Louis Changcdec0802019-11-11 11:45:07 +08002361 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2362 windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
2363 }
2364 Rect outOverrideBounds =
2365 getResolvedOverrideConfiguration().windowConfiguration.getBounds();
2366
2367 if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
2368 computeFullscreenBounds(outOverrideBounds, null /* refActivity */,
2369 newParentConfig.windowConfiguration.getBounds(),
2370 newParentConfig.orientation);
2371 }
2372
Louis Changcdec0802019-11-11 11:45:07 +08002373 adjustForMinimalTaskDimensions(outOverrideBounds, mTmpBounds);
2374 if (windowingMode == WINDOWING_MODE_FREEFORM) {
2375 // by policy, make sure the window remains within parent somewhere
2376 final float density =
2377 ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;
2378 final Rect parentBounds =
2379 new Rect(newParentConfig.windowConfiguration.getBounds());
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002380 final DisplayContent display = getDisplayContent();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002381 if (display != null) {
Louis Changcdec0802019-11-11 11:45:07 +08002382 // If a freeform window moves below system bar, there is no way to move it again
2383 // by touch. Because its caption is covered by system bar. So we exclude them
2384 // from stack bounds. and then caption will be shown inside stable area.
2385 final Rect stableBounds = new Rect();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002386 display.getStableRect(stableBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002387 parentBounds.intersect(stableBounds);
2388 }
2389
2390 fitWithinBounds(outOverrideBounds, parentBounds,
2391 (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP),
2392 (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP));
2393
2394 // Prevent to overlap caption with stable insets.
2395 final int offsetTop = parentBounds.top - outOverrideBounds.top;
2396 if (offsetTop > 0) {
2397 outOverrideBounds.offset(0, offsetTop);
2398 }
2399 }
2400 computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
2401 }
2402
2403 /**
2404 * Compute bounds (letterbox or pillarbox) for
2405 * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the
2406 * orientation change and the requested orientation is different from the parent.
2407 */
2408 void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
2409 @NonNull Rect parentBounds, int parentOrientation) {
2410 // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
2411 outBounds.setEmpty();
2412 if (handlesOrientationChangeFromDescendant()) {
2413 return;
2414 }
2415 if (refActivity == null) {
2416 // Use the top activity as the reference of orientation. Don't include overlays because
2417 // it is usually not the actual content or just temporarily shown.
2418 // E.g. ForcedResizableInfoActivity.
Wale Ogunwale21e06482019-11-18 05:14:15 -08002419 refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
Louis Changcdec0802019-11-11 11:45:07 +08002420 }
2421
2422 // If the task or the reference activity requires a different orientation (either by
2423 // override or activityInfo), make it fit the available bounds by scaling down its bounds.
2424 final int overrideOrientation = getRequestedOverrideConfiguration().orientation;
2425 final int forcedOrientation =
2426 (overrideOrientation != ORIENTATION_UNDEFINED || refActivity == null)
2427 ? overrideOrientation : refActivity.getRequestedConfigurationOrientation();
2428 if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
2429 return;
2430 }
2431
2432 final int parentWidth = parentBounds.width();
2433 final int parentHeight = parentBounds.height();
2434 final float aspect = ((float) parentHeight) / parentWidth;
2435 if (forcedOrientation == ORIENTATION_LANDSCAPE) {
2436 final int height = (int) (parentWidth / aspect);
2437 final int top = parentBounds.centerY() - height / 2;
2438 outBounds.set(parentBounds.left, top, parentBounds.right, top + height);
2439 } else {
2440 final int width = (int) (parentHeight * aspect);
2441 final int left = parentBounds.centerX() - width / 2;
2442 outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
2443 }
2444 }
2445
2446 Rect updateOverrideConfigurationFromLaunchBounds() {
Louis Changa009c762020-02-26 11:21:31 +08002447 // If the task is controlled by another organized task, do not set override
2448 // configurations and let its parent (organized task) to control it;
Louis Chang06107a32020-04-06 11:55:46 +08002449 final Task rootTask = getRootTask();
2450 final Rect bounds = rootTask != this && rootTask.isOrganized() ? null : getLaunchBounds();
Louis Changcdec0802019-11-11 11:45:07 +08002451 setBounds(bounds);
2452 if (bounds != null && !bounds.isEmpty()) {
2453 // TODO: Review if we actually want to do this - we are setting the launch bounds
2454 // directly here.
2455 bounds.set(getRequestedOverrideBounds());
2456 }
2457 return bounds;
2458 }
2459
2460 /** Updates the task's bounds and override configuration to match what is expected for the
2461 * input stack. */
2462 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002463 final ActivityStack stack = getStack();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002464
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002465 if (stack != null && stack == inStack) {
Louis Changcdec0802019-11-11 11:45:07 +08002466 return;
2467 }
2468
2469 if (inStack.inFreeformWindowingMode()) {
2470 if (!isResizeable()) {
2471 throw new IllegalArgumentException("Can not position non-resizeable task="
2472 + this + " in stack=" + inStack);
2473 }
2474 if (!matchParentBounds()) {
2475 return;
2476 }
2477 if (mLastNonFullscreenBounds != null) {
2478 setBounds(mLastNonFullscreenBounds);
2479 } else {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002480 mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Louis Changcdec0802019-11-11 11:45:07 +08002481 }
2482 } else {
2483 setBounds(inStack.getRequestedOverrideBounds());
2484 }
2485 }
2486
2487 /** Returns the bounds that should be used to launch this task. */
2488 Rect getLaunchBounds() {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002489 final ActivityStack stack = getStack();
2490 if (stack == null) {
Louis Changcdec0802019-11-11 11:45:07 +08002491 return null;
2492 }
2493
2494 final int windowingMode = getWindowingMode();
2495 if (!isActivityTypeStandardOrUndefined()
2496 || windowingMode == WINDOWING_MODE_FULLSCREEN
2497 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002498 return isResizeable() ? stack.getRequestedOverrideBounds() : null;
Louis Changcdec0802019-11-11 11:45:07 +08002499 } else if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002500 return stack.getRequestedOverrideBounds();
Louis Changcdec0802019-11-11 11:45:07 +08002501 }
2502 return mLastNonFullscreenBounds;
2503 }
2504
Louis Changcdec0802019-11-11 11:45:07 +08002505 void setRootProcess(WindowProcessController proc) {
2506 clearRootProcess();
2507 if (intent != null
2508 && (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
2509 mRootProcess = proc;
2510 mRootProcess.addRecentTask(this);
2511 }
2512 }
2513
2514 void clearRootProcess() {
2515 if (mRootProcess != null) {
2516 mRootProcess.removeRecentTask(this);
2517 mRootProcess = null;
2518 }
2519 }
2520
Tiger Huanged6794e2019-05-07 20:07:59 +08002521 @Override
Craig Mautnerc00204b2013-03-05 15:02:14 -08002522 DisplayContent getDisplayContent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002523 // TODO: Why aren't we just using our own display content vs. parent's???
2524 final ActivityStack stack = getStack();
2525 return stack != null && stack != this
2526 ? stack.getDisplayContent() : super.getDisplayContent();
Wale Ogunwale8577a052019-10-26 23:22:34 -07002527 }
2528
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002529 int getDisplayId() {
2530 final DisplayContent dc = getDisplayContent();
2531 return dc != null ? dc.mDisplayId : INVALID_DISPLAY;
2532 }
2533
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002534 // TODO: Migrate callers to getRootTask()
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002535 ActivityStack getStack() {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002536 return (ActivityStack) getRootTask();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002537 }
2538
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002539 /** @return Id of root task. */
2540 int getRootTaskId() {
2541 return getRootTask().mTaskId;
2542 }
2543
2544 Task getRootTask() {
2545 final WindowContainer parent = getParent();
2546 if (parent == null) return this;
2547
2548 final Task parentTask = parent.asTask();
2549 return parentTask == null ? this : parentTask.getRootTask();
2550 }
2551
2552 // TODO(task-merge): Figure out what's the right thing to do for places that used it.
2553 boolean isRootTask() {
2554 return getRootTask() == this;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002555 }
2556
Louis Changfd5539e2020-02-04 14:34:24 +08002557 boolean isLeafTask() {
2558 for (int i = mChildren.size() - 1; i >= 0; --i) {
2559 if (mChildren.get(i).asTask() != null) {
2560 return false;
2561 }
2562 }
2563 return true;
2564 }
2565
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002566 int getDescendantTaskCount() {
2567 final int[] currentCount = {0};
2568 final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
2569 PooledLambda.__(Task.class), currentCount);
Wale Ogunwale0d465192020-01-23 19:14:44 -08002570 forAllLeafTasks(c, false /* traverseTopToBottom */);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002571 c.recycle();
2572 return currentCount[0];
2573 }
2574
2575 /** Calculate the minimum possible position for a task that can be shown to the user.
2576 * The minimum position will be above all other tasks that can't be shown.
2577 * @param minPosition The minimum position the caller is suggesting.
2578 * We will start adjusting up from here.
2579 * @param size The size of the current task list.
2580 */
2581 // TODO: Move user to their own window container.
2582 private int computeMinUserPosition(int minPosition, int size) {
2583 while (minPosition < size) {
2584 final WindowContainer child = mChildren.get(minPosition);
2585 final boolean canShow = child.showToCurrentUser();
2586 if (canShow) {
2587 break;
2588 }
2589 minPosition++;
2590 }
2591 return minPosition;
2592 }
2593
2594 /** Calculate the maximum possible position for a task that can't be shown to the user.
2595 * The maximum position will be below all other tasks that can be shown.
2596 * @param maxPosition The maximum position the caller is suggesting.
2597 * We will start adjusting down from here.
2598 */
2599 // TODO: Move user to their own window container.
2600 private int computeMaxUserPosition(int maxPosition) {
2601 while (maxPosition > 0) {
2602 final WindowContainer child = mChildren.get(maxPosition);
2603 final boolean canShow = child.showToCurrentUser();
2604 if (!canShow) {
2605 break;
2606 }
2607 maxPosition--;
2608 }
2609 return maxPosition;
2610 }
2611
2612 private int getAdjustedChildPosition(WindowContainer wc, int suggestedPosition) {
2613 final boolean canShowChild = wc.showToCurrentUser();
2614
2615 final int size = mChildren.size();
2616
2617 // Figure-out min/max possible position depending on if child can show for current user.
2618 int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0;
2619 int maxPosition = (canShowChild) ? size : computeMaxUserPosition(size - 1);
2620
2621 // Factor in always-on-top children in max possible position.
2622 if (!wc.isAlwaysOnTop()) {
2623
2624 // We want to place all non-always-on-top containers below always-on-top ones.
2625 while (maxPosition > minPosition) {
2626 if (!mChildren.get(maxPosition - 1).isAlwaysOnTop()) break;
2627 --maxPosition;
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002628 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002629 }
2630
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002631 // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
2632 if (suggestedPosition == POSITION_BOTTOM && minPosition == 0) {
2633 return POSITION_BOTTOM;
Louis Changa009c762020-02-26 11:21:31 +08002634 } else if (suggestedPosition == POSITION_TOP && maxPosition >= (size - 1)) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002635 return POSITION_TOP;
2636 }
2637 // Reset position based on minimum/maximum possible positions.
2638 return Math.min(Math.max(suggestedPosition, minPosition), maxPosition);
Craig Mautnerc00204b2013-03-05 15:02:14 -08002639 }
2640
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002641 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002642 void positionChildAt(int position, WindowContainer child, boolean includingParents) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002643 position = getAdjustedChildPosition(child, position);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002644 super.positionChildAt(position, child, includingParents);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002645
2646 // Log positioning.
2647 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "positionChildAt: child=" + child
2648 + " position=" + position + " parent=" + this);
2649
2650 final int toTop = position >= (mChildren.size() - 1) ? 1 : 0;
2651 final Task task = child.asTask();
2652 if (task != null) {
2653 EventLogTags.writeWmTaskMoved(task.mTaskId, toTop, position);
2654 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002655 }
2656
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002657 @VisibleForTesting
2658 boolean hasWindowsAlive() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002659 return getActivity(ActivityRecord::hasWindowsAlive) != null;
Chong Zhang7e8eeb72016-01-06 19:14:47 -08002660 }
2661
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002662 @VisibleForTesting
2663 boolean shouldDeferRemoval() {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02002664 if (mChildren.isEmpty()) {
2665 // No reason to defer removal of a Task that doesn't have any child.
2666 return false;
2667 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002668 return hasWindowsAlive() && getStack().isAnimating(TRANSITION | CHILDREN);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002669 }
2670
Wale Ogunwalef6192862016-09-10 13:42:30 -07002671 @Override
Andrii Kulian45a61fe2017-01-05 16:53:19 -08002672 void removeImmediately() {
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08002673 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
Jeff Changd136e772019-11-05 20:33:52 +08002674 EventLogTags.writeWmTaskRemoved(mTaskId, "removeTask");
Robert Carr8a2f9132019-11-11 15:03:15 -08002675
2676 // If applicable let the TaskOrganizer know the Task is vanishing.
2677 setTaskOrganizer(null);
2678
Andrii Kulian45a61fe2017-01-05 16:53:19 -08002679 super.removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -08002680 }
2681
Louis Changcdec0802019-11-11 11:45:07 +08002682 // TODO: Consolidate this with Task.reparent()
Louis Changdc077272019-11-12 16:52:56 +08002683 void reparent(ActivityStack stack, int position, boolean moveParents, String reason) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -08002684 if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002685 + " from stack=" + getStack());
Louis Chang074cdf22019-12-13 13:15:13 +08002686 EventLogTags.writeWmTaskRemoved(mTaskId, "reParentTask:" + reason);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002687
2688 reparent(stack, position);
2689
Louis Changcdec0802019-11-11 11:45:07 +08002690 stack.positionChildAt(position, this, moveParents);
Andrii Kulian7cd7c2d2017-01-18 12:14:37 -08002691
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002692 // If we are moving from the fullscreen stack to the pinned stack then we want to preserve
2693 // our insets so that there will not be a jump in the area covered by system decorations.
2694 // We rely on the pinned animation to later unset this value.
2695 mPreserveNonFloatingState = stack.inPinnedWindowingMode();
Wale Ogunwale53a29a92015-02-23 15:42:52 -08002696 }
2697
Bryce Leef3c6a472017-11-14 14:53:06 -08002698 public int setBounds(Rect bounds, boolean forceResize) {
2699 final int boundsChanged = setBounds(bounds);
2700
2701 if (forceResize && (boundsChanged & BOUNDS_CHANGE_SIZE) != BOUNDS_CHANGE_SIZE) {
2702 onResize();
2703 return BOUNDS_CHANGE_SIZE | boundsChanged;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002704 }
Wale Ogunwale68278562017-09-23 17:13:55 -07002705
Bryce Leef3c6a472017-11-14 14:53:06 -08002706 return boundsChanged;
2707 }
2708
2709 /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
2710 @Override
2711 public int setBounds(Rect bounds) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002712 int rotation = Surface.ROTATION_0;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002713 final DisplayContent displayContent = getStack() != null
2714 ? getStack().getDisplayContent() : null;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002715 if (displayContent != null) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002716 rotation = displayContent.getDisplayInfo().rotation;
Wale Ogunwale2cc92f52015-09-09 13:12:10 -07002717 }
2718
Bryce Leef3c6a472017-11-14 14:53:06 -08002719 final int boundsChange = super.setBounds(bounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002720 mRotation = rotation;
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002721 updateSurfacePosition();
Wale Ogunwale2cc92f52015-09-09 13:12:10 -07002722 return boundsChange;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002723 }
2724
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08002725 private void updateSurfaceCrop() {
2726 // Only update the crop if we are drawing shadows on the task.
Garfield Tan7e1cb5c2020-04-10 15:21:23 -07002727 if (mSurfaceControl == null || !mWmService.mRenderShadowsInCompositor || !isRootTask()) {
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08002728 return;
2729 }
2730
2731 if (inSplitScreenWindowingMode()) {
2732 // inherit crop from parent
2733 mTmpRect.setEmpty();
2734 } else {
2735 getBounds(mTmpRect);
2736 }
2737
2738 mTmpRect.offsetTo(0, 0);
2739 if (mLastSurfaceCrop.equals(mTmpRect)) {
2740 return;
2741 }
2742
2743 getPendingTransaction().setWindowCrop(mSurfaceControl, mTmpRect);
2744 mLastSurfaceCrop.set(mTmpRect);
2745 }
2746
Garfield Tan90b04282018-12-11 14:04:42 -08002747 @Override
2748 public boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
2749 ConfigurationContainer requestingContainer) {
2750 if (super.onDescendantOrientationChanged(freezeDisplayToken, requestingContainer)) {
2751 return true;
2752 }
2753
2754 // No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
2755 // it if possible.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002756 if (getParent() != null) {
2757 onConfigurationChanged(getParent().getConfiguration());
Garfield Tan90b04282018-12-11 14:04:42 -08002758 return true;
2759 }
2760 return false;
2761 }
2762
Yunfan Chen0e7aff92018-12-05 16:35:32 -08002763 void resize(boolean relayout, boolean forced) {
2764 if (setBounds(getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE && relayout) {
2765 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
2766 }
2767 }
2768
Louis Chang7501e332018-08-20 13:08:39 +08002769 @Override
2770 void onDisplayChanged(DisplayContent dc) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002771 final boolean isRootTask = isRootTask();
2772 if (!isRootTask) {
2773 adjustBoundsForDisplayChangeIfNeeded(dc);
2774 }
Evan Rosky55bddd82020-01-29 13:07:18 -08002775 final DisplayContent prevDc = mDisplayContent;
Louis Chang7501e332018-08-20 13:08:39 +08002776 super.onDisplayChanged(dc);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002777 if (!isRootTask) {
2778 final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY;
2779 mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged(
2780 mTaskId, displayId);
2781 }
Evan Rosky55bddd82020-01-29 13:07:18 -08002782 if (prevDc != null && prevDc.mChangingContainers.remove(this)) {
2783 // This gets called *after* this has been reparented to the new display.
2784 // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
2785 // so this token is now "frozen" while waiting for the animation to start on prevDc
2786 // (which will be cancelled since the window is no-longer a child). However, since this
2787 // is no longer a child of prevDc, this won't be notified of the cancelled animation,
2788 // so we need to cancel the change transition here.
2789 mSurfaceFreezer.unfreeze(getPendingTransaction());
2790 }
Louis Chang7501e332018-08-20 13:08:39 +08002791 }
2792
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002793 boolean isResizeable(boolean checkSupportsPip) {
2794 return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
2795 || (checkSupportsPip && mSupportsPictureInPicture));
Chong Zhangb15758a2015-11-17 12:12:03 -08002796 }
2797
2798 boolean isResizeable() {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002799 return isResizeable(true /* checkSupportsPip */);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002800 }
2801
skuhne@google.com322347b2016-12-02 12:54:03 -08002802 /**
2803 * Tests if the orientation should be preserved upon user interactive resizig operations.
2804
2805 * @return true if orientation should not get changed upon resizing operation.
2806 */
2807 boolean preserveOrientationOnResize() {
2808 return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
2809 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
2810 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
2811 }
2812
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002813 boolean cropWindowsToStackBounds() {
Wale Ogunwaledf241e92016-10-13 15:14:21 -07002814 return isResizeable();
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002815 }
2816
Jorim Jaggi0429f352015-12-22 16:29:16 +01002817 /**
2818 * Prepares the task bounds to be frozen with the current size. See
Garfield Tane8d84ab2019-10-11 09:49:40 -07002819 * {@link ActivityRecord#freezeBounds}.
Jorim Jaggi0429f352015-12-22 16:29:16 +01002820 */
2821 void prepareFreezingBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08002822 mPreparedFrozenBounds.set(getBounds());
Andrii Kulian441e4492016-09-29 15:25:00 -07002823 mPreparedFrozenMergedConfig.setTo(getConfiguration());
Jorim Jaggi0429f352015-12-22 16:29:16 +01002824 }
2825
Issei Suzukiad287d02019-10-31 16:19:44 +01002826 @Override
2827 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2828 Rect outSurfaceInsets) {
2829 final WindowState windowState = getTopVisibleAppMainWindow();
2830 if (windowState != null) {
2831 windowState.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2832 } else {
2833 super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2834 }
2835 }
2836
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002837 /**
2838 * Calculate the maximum visible area of this task. If the task has only one app,
2839 * the result will be visible frame of that app. If the task has more than one apps,
2840 * we search from top down if the next app got different visible area.
2841 *
2842 * This effort is to handle the case where some task (eg. GMail composer) might pop up
2843 * a dialog that's different in size from the activity below, in which case we should
2844 * be dimming the entire task area behind the dialog.
2845 *
2846 * @param out Rect containing the max visible bounds.
2847 * @return true if the task has some visible app windows; false otherwise.
2848 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002849 private static void getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop) {
2850 // skip hidden (or about to hide) apps
2851 if (token.mIsExiting || !token.isClientVisible() || !token.mVisibleRequested) {
2852 return;
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002853 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002854 final WindowState win = token.findMainWindow();
2855 if (win == null) {
2856 return;
2857 }
2858 if (!foundTop[0]) {
2859 foundTop[0] = true;
2860 out.setEmpty();
2861 }
2862
2863 win.getMaxVisibleBounds(out);
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002864 }
2865
2866 /** Bounds of the task to be used for dimming, as well as touch related tests. */
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002867 void getDimBounds(Rect out) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002868 final DisplayContent displayContent = getStack().getDisplayContent();
Robert Carra86a6bf2016-04-08 17:34:16 -07002869 // It doesn't matter if we in particular are part of the resize, since we couldn't have
2870 // a DimLayer anyway if we weren't visible.
Wale Ogunwalef6192862016-09-10 13:42:30 -07002871 final boolean dockedResizing = displayContent != null
2872 && displayContent.mDividerControllerLocked.isResizing();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002873 if (inFreeformWindowingMode()) {
2874 boolean[] foundTop = { false };
2875 final PooledConsumer c = PooledLambda.obtainConsumer(Task::getMaxVisibleBounds,
2876 PooledLambda.__(ActivityRecord.class), out, foundTop);
Vishnu Nair4d7a6002020-01-23 14:34:40 -08002877 forAllActivities(c);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002878 c.recycle();
2879 if (foundTop[0]) {
2880 return;
2881 }
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002882 }
2883
Evan Rosky4fb1e912019-03-06 13:54:43 -08002884 if (!matchParentBounds()) {
2885 // When minimizing the docked stack when going home, we don't adjust the task bounds
2886 // so we need to intersect the task bounds with the stack bounds here.
2887 //
2888 // If we are Docked Resizing with snap points, the task bounds could be smaller than the
2889 // stack bounds and so we don't even want to use them. Even if the app should not be
2890 // resized the Dim should keep up with the divider.
2891 if (dockedResizing) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002892 getStack().getBounds(out);
Evan Rosky4fb1e912019-03-06 13:54:43 -08002893 } else {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002894 getStack().getBounds(mTmpRect);
Evan Rosky4fb1e912019-03-06 13:54:43 -08002895 mTmpRect.intersect(getBounds());
2896 out.set(mTmpRect);
2897 }
2898 } else {
2899 out.set(getBounds());
Wale Ogunwalef6192862016-09-10 13:42:30 -07002900 }
Evan Rosky4fb1e912019-03-06 13:54:43 -08002901 return;
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002902 }
2903
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01002904 void setDragResizing(boolean dragResizing, int dragResizeMode) {
Jorim Jaggic662d8e2016-02-05 16:54:54 -08002905 if (mDragResizing != dragResizing) {
chaviw8c9d1f52018-07-25 14:56:07 -07002906 // No need to check if the mode is allowed if it's leaving dragResize
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002907 if (dragResizing && !DragResizeMode.isModeAllowedForStack(getStack(), dragResizeMode)) {
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01002908 throw new IllegalArgumentException("Drag resize mode not allow for stack stackId="
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002909 + getRootTaskId() + " dragResizeMode=" + dragResizeMode);
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01002910 }
Jorim Jaggic662d8e2016-02-05 16:54:54 -08002911 mDragResizing = dragResizing;
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01002912 mDragResizeMode = dragResizeMode;
Jorim Jaggic662d8e2016-02-05 16:54:54 -08002913 resetDragResizingChangeReported();
2914 }
2915 }
2916
Chong Zhang3005e752015-09-18 18:46:28 -07002917 boolean isDragResizing() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07002918 return mDragResizing;
Chong Zhang3005e752015-09-18 18:46:28 -07002919 }
2920
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01002921 int getDragResizeMode() {
2922 return mDragResizeMode;
2923 }
2924
Yunfan Chen0e7aff92018-12-05 16:35:32 -08002925 /**
2926 * Puts this task into docked drag resizing mode. See {@link DragResizeMode}.
2927 *
2928 * @param resizing Whether to put the task into drag resize mode.
2929 */
2930 public void setTaskDockedResizing(boolean resizing) {
2931 setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
2932 }
2933
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002934 void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002935 if (displayContent == null) {
2936 return;
2937 }
Bryce Leef3c6a472017-11-14 14:53:06 -08002938 if (matchParentBounds()) {
Wale Ogunwale68278562017-09-23 17:13:55 -07002939 // TODO: Yeah...not sure if this works with WindowConfiguration, but shouldn't be a
2940 // problem once we move mBounds into WindowConfiguration.
Bryce Leef3c6a472017-11-14 14:53:06 -08002941 setBounds(null);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002942 return;
2943 }
Garfield Tandec96db2018-10-30 11:28:49 -07002944 final int displayId = displayContent.getDisplayId();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002945 final int newRotation = displayContent.getDisplayInfo().rotation;
Garfield Tandec96db2018-10-30 11:28:49 -07002946 if (displayId != mLastRotationDisplayId) {
2947 // This task is on a display that it wasn't on. There is no point to keep the relative
2948 // position if display rotations for old and new displays are different. Just keep these
2949 // values.
2950 mLastRotationDisplayId = displayId;
2951 mRotation = newRotation;
2952 return;
2953 }
2954
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002955 if (mRotation == newRotation) {
Garfield Tandec96db2018-10-30 11:28:49 -07002956 // Rotation didn't change. We don't need to adjust the bounds to keep the relative
2957 // position.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002958 return;
2959 }
2960
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08002961 // Device rotation changed.
Chong Zhang2e2c81a2016-07-15 11:28:17 -07002962 // - We don't want the task to move around on the screen when this happens, so update the
2963 // task bounds so it stays in the same place.
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08002964 // - Rotate the bounds and notify activity manager if the task can be resized independently
Chong Zhang2e2c81a2016-07-15 11:28:17 -07002965 // from its stack. The stack will take care of task rotation for the other case.
Bryce Leef3c6a472017-11-14 14:53:06 -08002966 mTmpRect2.set(getBounds());
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08002967
Wale Ogunwale3382ab12017-07-27 08:55:03 -07002968 if (!getWindowConfiguration().canResizeTask()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08002969 setBounds(mTmpRect2);
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08002970 return;
2971 }
2972
Wale Ogunwale94744212015-09-21 19:01:47 -07002973 displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
Bryce Leef3c6a472017-11-14 14:53:06 -08002974 if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002975 mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
Wale Ogunwale1ed0d892015-09-28 13:27:44 -07002976 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002977 }
2978
Wale Ogunwalef6192862016-09-10 13:42:30 -07002979 /** Cancels any running app transitions associated with the task. */
Winsonc28098f2015-10-30 14:50:19 -07002980 void cancelTaskWindowTransition() {
Wale Ogunwalef6192862016-09-10 13:42:30 -07002981 for (int i = mChildren.size() - 1; i >= 0; --i) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002982 mChildren.get(i).cancelAnimation();
Winsonc28098f2015-10-30 14:50:19 -07002983 }
2984 }
2985
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07002986 boolean showForAllUsers() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002987 if (mChildren.isEmpty()) return false;
2988 final ActivityRecord r = getTopNonFinishingActivity();
2989 return r != null && r.mShowForAllUsers;
Jorim Jaggiff71d202016-04-14 13:12:36 -07002990 }
2991
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08002992 @Override
2993 boolean showToCurrentUser() {
2994 return mForceShowForAllUsers || showForAllUsers() || mWmService.isCurrentProfile(mUserId);
2995 }
2996
2997 void setForceShowForAllUsers(boolean forceShowForAllUsers) {
2998 mForceShowForAllUsers = forceShowForAllUsers;
2999 }
3000
Evan Rosky688c8382020-04-03 17:27:08 -07003001 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003002 public boolean isAttached() {
Andrii Kulian86d676c2020-03-27 19:34:54 -07003003 final TaskDisplayArea taskDisplayArea = getDisplayArea();
3004 return taskDisplayArea != null && !taskDisplayArea.isRemoved();
3005 }
3006
3007 @Override
3008 @Nullable
3009 TaskDisplayArea getDisplayArea() {
3010 return (TaskDisplayArea) super.getDisplayArea();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003011 }
3012
Robert Carr7e4c90e2017-02-15 19:52:38 -08003013 /**
3014 * When we are in a floating stack (Freeform, Pinned, ...) we calculate
3015 * insets differently. However if we are animating to the fullscreen stack
3016 * we need to begin calculating insets as if we were fullscreen, otherwise
3017 * we will have a jump at the end.
3018 */
Robert Carre6275582016-02-29 15:45:45 -08003019 boolean isFloating() {
Hongwei Wang85cf41f2020-01-15 15:14:47 -08003020 return getWindowConfiguration().tasksAreFloating() && !mPreserveNonFloatingState;
Robert Carre6275582016-02-29 15:45:45 -08003021 }
3022
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003023 /**
3024 * Returns true if the stack is translucent and can have other contents visible behind it if
3025 * needed. A stack is considered translucent if it don't contain a visible or
3026 * starting (about to be visible) activity that is fullscreen (opaque).
3027 * @param starting The currently starting activity or null if there is none.
3028 */
3029 @VisibleForTesting
3030 boolean isTranslucent(ActivityRecord starting) {
Robert Carrf6878a42019-12-18 02:13:12 -08003031 if (!isAttached() || isForceHidden()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003032 return true;
3033 }
3034 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isOpaqueActivity,
3035 PooledLambda.__(ActivityRecord.class), starting);
3036 final ActivityRecord opaque = getActivity(p);
3037 p.recycle();
3038 return opaque == null;
3039 }
3040
3041 private static boolean isOpaqueActivity(ActivityRecord r, ActivityRecord starting) {
3042 if (r.finishing) {
3043 // We don't factor in finishing activities when determining translucency since
3044 // they will be gone soon.
3045 return false;
3046 }
3047
3048 if (!r.visibleIgnoringKeyguard && r != starting) {
3049 // Also ignore invisible activities that are not the currently starting
3050 // activity (about to be visible).
3051 return false;
3052 }
3053
3054 if (r.occludesParent() || r.hasWallpaper) {
3055 // Stack isn't translucent if it has at least one fullscreen activity
3056 // that is visible.
3057 return true;
3058 }
3059 return false;
3060 }
3061
Winson Chungd41f71d2018-03-16 15:26:07 -07003062 @Override
3063 public SurfaceControl getAnimationLeashParent() {
Riddle Hsud8302832019-09-23 21:14:07 +08003064 if (WindowManagerService.sHierarchicalAnimations) {
Issei Suzuki71142152019-08-15 14:39:40 +02003065 return super.getAnimationLeashParent();
3066 }
Winson Chung732446a2018-09-19 13:15:17 -07003067 // Currently, only the recents animation will create animation leashes for tasks. In this
3068 // case, reparent the task to the home animation layer while it is being animated to allow
3069 // the home activity to reorder the app windows relative to its own.
3070 return getAppAnimationLayer(ANIMATION_LAYER_HOME);
Winson Chungd41f71d2018-03-16 15:26:07 -07003071 }
3072
lumark5341d1c2019-12-14 01:54:02 +08003073 @Override
3074 Rect getAnimationBounds(int appStackClipMode) {
3075 // TODO(b/131661052): we should remove appStackClipMode with hierarchical animations.
3076 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
3077 // Using the stack bounds here effectively applies the clipping before animation.
3078 return getStack().getBounds();
3079 }
3080 return super.getAnimationBounds(appStackClipMode);
3081 }
3082
lumark19a5d2e2019-10-11 16:19:30 +08003083 boolean shouldAnimate() {
Robert Carr8a2f9132019-11-11 15:03:15 -08003084 /**
3085 * Animations are handled by the TaskOrganizer implementation.
3086 */
Wale Ogunwaledec34082020-03-22 09:45:00 -07003087 if (isOrganized()) {
Robert Carr8a2f9132019-11-11 15:03:15 -08003088 return false;
3089 }
lumark19a5d2e2019-10-11 16:19:30 +08003090 // Don't animate while the task runs recents animation but only if we are in the mode
3091 // where we cancel with deferred screenshot, which means that the controller has
3092 // transformed the task.
3093 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
3094 if (controller != null && controller.isAnimatingTask(this)
3095 && controller.shouldDeferCancelUntilNextTransition()) {
3096 return false;
3097 }
3098 return true;
3099 }
3100
Evan Rosky9020c072018-12-06 14:11:12 -08003101 @Override
Vishnu Nairfd6fb672020-02-14 12:56:37 -08003102 void onSurfaceShown(SurfaceControl.Transaction t) {
3103 super.onSurfaceShown(t);
3104 t.unsetColor(mSurfaceControl);
3105 }
3106
3107 @Override
Evan Rosky9020c072018-12-06 14:11:12 -08003108 SurfaceControl.Builder makeSurface() {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08003109 return super.makeSurface().setColorLayer().setMetadata(METADATA_TASK_ID, mTaskId);
Evan Rosky9020c072018-12-06 14:11:12 -08003110 }
3111
Winson Chungd41f71d2018-03-16 15:26:07 -07003112 boolean isTaskAnimating() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003113 final RecentsAnimationController recentsAnim = mWmService.getRecentsAnimationController();
Winson Chungd41f71d2018-03-16 15:26:07 -07003114 if (recentsAnim != null) {
3115 if (recentsAnim.isAnimatingTask(this)) {
3116 return true;
3117 }
3118 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003119 return forAllTasks((t) -> { return t != this && t.isTaskAnimating(); });
Winson Chungd41f71d2018-03-16 15:26:07 -07003120 }
3121
lumark19a5d2e2019-10-11 16:19:30 +08003122 @Override
3123 RemoteAnimationTarget createRemoteAnimationTarget(
3124 RemoteAnimationController.RemoteAnimationRecord record) {
lumark5341d1c2019-12-14 01:54:02 +08003125 final ActivityRecord activity = getTopMostActivity();
lumark19a5d2e2019-10-11 16:19:30 +08003126 return activity != null ? activity.createRemoteAnimationTarget(record) : null;
3127 }
3128
Daichi Hirono8ecfc6b2020-02-18 16:28:03 +09003129 @Override
3130 boolean canCreateRemoteAnimationTarget() {
3131 return true;
3132 }
3133
Chong Zhangd8ceb852015-11-11 14:53:41 -08003134 WindowState getTopVisibleAppMainWindow() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003135 final ActivityRecord activity = getTopVisibleActivity();
3136 return activity != null ? activity.findMainWindow() : null;
Chong Zhang9184ec62015-09-24 12:32:21 -07003137 }
3138
Garfield Tane8d84ab2019-10-11 09:49:40 -07003139 ActivityRecord getTopFullscreenActivity() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003140 return getActivity((r) -> {
3141 final WindowState win = r.findMainWindow();
3142 return (win != null && win.mAttrs.isFullscreen());
3143 });
Jorim Jaggie6c6ecb2017-07-20 18:09:20 +02003144 }
3145
Garfield Tane8d84ab2019-10-11 09:49:40 -07003146 ActivityRecord getTopVisibleActivity() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003147 return getActivity((r) -> {
3148 // skip hidden (or about to hide) apps
3149 return !r.mIsExiting && r.isClientVisible() && r.mVisibleRequested;
3150 });
Chong Zhangbef461f2015-10-27 11:38:24 -07003151 }
3152
Wale Ogunwale3198da42019-10-10 14:45:03 +02003153 void positionChildAtTop(ActivityRecord child) {
3154 positionChildAt(child, POSITION_TOP);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003155 }
3156
Wale Ogunwale3198da42019-10-10 14:45:03 +02003157 void positionChildAt(ActivityRecord child, int position) {
3158 if (child == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003159 Slog.w(TAG_WM,
3160 "Attempted to position of non-existing app");
3161 return;
3162 }
3163
Wale Ogunwale3198da42019-10-10 14:45:03 +02003164 positionChildAt(position, child, false /* includeParents */);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003165 }
3166
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003167 void forceWindowsScaleable(boolean force) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003168 mWmService.openSurfaceTransaction();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003169 try {
Wale Ogunwalef6192862016-09-10 13:42:30 -07003170 for (int i = mChildren.size() - 1; i >= 0; i--) {
3171 mChildren.get(i).forceWindowsScaleableInTransaction(force);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003172 }
3173 } finally {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003174 mWmService.closeSurfaceTransaction("forceWindowsScaleable");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003175 }
3176 }
3177
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01003178 void setTaskDescription(TaskDescription taskDescription) {
3179 mTaskDescription = taskDescription;
3180 }
3181
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003182 void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003183 mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
3184 mTaskId, snapshot);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003185 }
3186
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01003187 TaskDescription getTaskDescription() {
3188 return mTaskDescription;
3189 }
3190
Wale Ogunwalef6192862016-09-10 13:42:30 -07003191 @Override
Riddle Hsu9a8e3ae2020-03-24 15:22:48 +08003192 int getOrientation(int candidate) {
3193 return canSpecifyOrientation() ? super.getOrientation(candidate) : SCREEN_ORIENTATION_UNSET;
3194 }
3195
3196 private boolean canSpecifyOrientation() {
3197 final int windowingMode = getWindowingMode();
3198 final int activityType = getActivityType();
3199 return windowingMode == WINDOWING_MODE_FULLSCREEN
3200 || activityType == ACTIVITY_TYPE_HOME
3201 || activityType == ACTIVITY_TYPE_RECENTS
3202 || activityType == ACTIVITY_TYPE_ASSISTANT;
3203 }
3204
3205 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07003206 boolean fillsParent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003207 return matchParentBounds();
3208 }
3209
Jeff Changdc9c1d42020-02-11 14:57:34 +08003210 @Override
Wale Ogunwale0d465192020-01-23 19:14:44 -08003211 void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
3212 final int count = mChildren.size();
3213 boolean isLeafTask = true;
3214 if (traverseTopToBottom) {
3215 for (int i = count - 1; i >= 0; --i) {
3216 final Task child = mChildren.get(i).asTask();
3217 if (child != null) {
3218 isLeafTask = false;
3219 child.forAllLeafTasks(callback, traverseTopToBottom);
3220 }
3221 }
3222 } else {
3223 for (int i = 0; i < count; i++) {
3224 final Task child = mChildren.get(i).asTask();
3225 if (child != null) {
3226 isLeafTask = false;
3227 child.forAllLeafTasks(callback, traverseTopToBottom);
3228 }
3229 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003230 }
Wale Ogunwale0d465192020-01-23 19:14:44 -08003231 if (isLeafTask) callback.accept(this);
Wale Ogunwale51362492016-09-08 17:49:17 -07003232 }
3233
Jorim Jaggi329a5832017-01-05 18:57:12 +01003234 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003235 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08003236 super.forAllTasks(callback, traverseTopToBottom);
3237 callback.accept(this);
Jorim Jaggi51304d72017-05-17 17:25:32 +02003238 }
3239
lumarkbc0032a2019-11-01 21:38:13 +08003240 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003241 boolean forAllTasks(Function<Task, Boolean> callback) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003242 if (super.forAllTasks(callback)) return true;
lumarkbc0032a2019-11-01 21:38:13 +08003243 return callback.apply(this);
3244 }
3245
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003246 @Override
3247 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003248 final Task t = super.getTask(callback, traverseTopToBottom);
3249 if (t != null) return t;
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003250 return callback.test(this) ? this : null;
3251 }
3252
Jorim Jaggi50bf59c2018-03-09 17:29:48 +01003253 /**
3254 * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
3255 * flags. See {@link WindowState#canAffectSystemUiFlags()}.
3256 */
3257 void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) {
3258 mCanAffectSystemUiFlags = canAffectSystemUiFlags;
3259 }
3260
3261 /**
3262 * @see #setCanAffectSystemUiFlags
3263 */
3264 boolean canAffectSystemUiFlags() {
3265 return mCanAffectSystemUiFlags;
3266 }
3267
chaviw87ca63a2018-03-26 14:06:17 -07003268 void dontAnimateDimExit() {
3269 mDimmer.dontAnimateExit();
3270 }
3271
Wale Ogunwale9adfe572016-09-08 20:43:58 -07003272 String getName() {
Louis Changcdec0802019-11-11 11:45:07 +08003273 return "Task=" + mTaskId;
Wale Ogunwale9adfe572016-09-08 20:43:58 -07003274 }
3275
Robert Carr18f622f2017-05-08 11:20:43 -07003276 void clearPreserveNonFloatingState() {
3277 mPreserveNonFloatingState = false;
3278 }
3279
chaviw2fb06bc2018-01-19 17:09:15 -08003280 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07003281 Dimmer getDimmer() {
chaviw51e4c2f2020-04-03 13:49:45 -07003282 // If the window is in multi-window mode, we want to dim at the Task level to ensure the dim
3283 // bounds match the area the app lives in
3284 if (inMultiWindowMode()) {
3285 return mDimmer;
3286 }
3287
3288 // If we're not at the root task level, we want to keep traversing through the parents to
3289 // find the root.
3290 // Once at the root task level, we want to check {@link #isTranslucent(ActivityRecord)}.
3291 // If true, we want to get the Dimmer from the level above since we don't want to animate
3292 // the dim with the Task.
3293 if (!isRootTask() || isTranslucent(null)) {
3294 return super.getDimmer();
3295 }
3296
Robert Carrf59b8dd2017-10-02 18:58:36 -07003297 return mDimmer;
3298 }
3299
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003300 void dim(float alpha) {
3301 mDimmer.dimAbove(getPendingTransaction(), alpha);
3302 scheduleAnimation();
3303 }
3304
3305 void stopDimming() {
3306 mDimmer.stopDim(getPendingTransaction());
3307 scheduleAnimation();
3308 }
3309
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003310 boolean isTaskForUser(int userId) {
3311 return mUserId == userId;
3312 }
3313
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07003314 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07003315 void prepareSurfaces() {
3316 mDimmer.resetDimStates();
3317 super.prepareSurfaces();
3318 getDimBounds(mTmpDimBoundsRect);
chaviwe07246a2017-12-12 16:18:29 -08003319
3320 // Bounds need to be relative, as the dim layer is a child.
HEO SEUNGe10f4192019-11-21 10:21:04 +09003321 if (inFreeformWindowingMode()) {
3322 getBounds(mTmpRect);
3323 mTmpDimBoundsRect.offsetTo(mTmpDimBoundsRect.left - mTmpRect.left,
3324 mTmpDimBoundsRect.top - mTmpRect.top);
3325 } else {
3326 mTmpDimBoundsRect.offsetTo(0, 0);
3327 }
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08003328
3329 updateSurfaceCrop();
Vishnu Nairae3b0772020-03-19 16:55:25 -07003330 updateShadowsRadius(isFocused(), getPendingTransaction());
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08003331
Robert Carrf59b8dd2017-10-02 18:58:36 -07003332 if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
3333 scheduleAnimation();
3334 }
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07003335 }
3336
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003337 @Override
lumark04bceb92020-03-07 00:03:33 +08003338 protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
3339 int transit, boolean isVoiceInteraction,
3340 @Nullable OnAnimationFinishedCallback finishedCallback) {
3341 final RecentsAnimationController control = mWmService.getRecentsAnimationController();
3342 if (control != null && enter
3343 && getDisplayContent().mAppTransition.isNextAppTransitionCustomFromRecents()) {
3344 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
3345 "addTaskToRecentsAnimationIfNeeded, control: %s, task: %s, transit: %s",
3346 control, asTask(), AppTransition.appTransitionToString(transit));
3347 // We let the transition to be controlled by RecentsAnimation, and callback task's
3348 // RemoteAnimationTarget for remote runner to animate.
3349 control.addTaskToTargets(getRootTask(), finishedCallback);
3350 } else {
3351 super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, finishedCallback);
3352 }
3353 }
3354
3355 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003356 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003357 super.dump(pw, prefix, dumpAll);
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003358 final String doublePrefix = prefix + " ";
3359
3360 pw.println(prefix + "taskId=" + mTaskId);
Bryce Leef3c6a472017-11-14 14:53:06 -08003361 pw.println(doublePrefix + "mBounds=" + getBounds().toShortString());
Wale Ogunwalef6192862016-09-10 13:42:30 -07003362 pw.println(doublePrefix + "appTokens=" + mChildren);
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003363
3364 final String triplePrefix = doublePrefix + " ";
Jorim Jaggi153dc9d2018-02-23 13:28:15 +01003365 final String quadruplePrefix = triplePrefix + " ";
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003366
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003367 int[] index = { 0 };
3368 forAllActivities((r) -> {
3369 pw.println(triplePrefix + "Activity #" + index[0]++ + " " + r);
3370 r.dump(pw, quadruplePrefix, dumpAll);
3371 });
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003372 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07003373
Louis Changcdec0802019-11-11 11:45:07 +08003374 /**
Winson Chung66b08f02020-03-03 14:32:35 -08003375 * Fills in a {@link TaskInfo} with information from this task. Note that the base intent in the
3376 * task info will not include any extras or clip data.
Louis Changcdec0802019-11-11 11:45:07 +08003377 */
3378 void fillTaskInfo(TaskInfo info) {
3379 getNumRunningActivities(mReuseActivitiesReport);
3380 info.userId = mUserId;
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003381 info.stackId = getRootTaskId();
Louis Changcdec0802019-11-11 11:45:07 +08003382 info.taskId = mTaskId;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003383 info.displayId = getDisplayId();
Wale Ogunwale21e06482019-11-18 05:14:15 -08003384 info.isRunning = getTopNonFinishingActivity() != null;
Evan Rosky0037e5f2019-11-05 10:26:24 -08003385 final Intent baseIntent = getBaseIntent();
Riddle Hsuc5a1bd42020-02-02 19:32:17 +08003386 // Make a copy of base intent because this is like a snapshot info.
3387 // Besides, {@link RecentTasks#getRecentTasksImpl} may modify it.
Winson Chung66b08f02020-03-03 14:32:35 -08003388 info.baseIntent = baseIntent == null ? new Intent() : baseIntent.cloneFilter();
Louis Changcdec0802019-11-11 11:45:07 +08003389 info.baseActivity = mReuseActivitiesReport.base != null
3390 ? mReuseActivitiesReport.base.intent.getComponent()
3391 : null;
3392 info.topActivity = mReuseActivitiesReport.top != null
3393 ? mReuseActivitiesReport.top.mActivityComponent
3394 : null;
3395 info.origActivity = origActivity;
3396 info.realActivity = realActivity;
3397 info.numActivities = mReuseActivitiesReport.numActivities;
3398 info.lastActiveTime = lastActiveTime;
3399 info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
3400 info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
Louis Changcdec0802019-11-11 11:45:07 +08003401 info.configuration.setTo(getConfiguration());
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07003402 info.token = mRemoteToken.toWindowContainerToken();
Evan Roskya8fde152020-01-07 19:09:13 -08003403
3404 //TODO (AM refactor): Just use local once updateEffectiveIntent is run during all child
3405 // order changes.
3406 final Task top = getTopMostTask();
3407 info.resizeMode = top != null ? top.mResizeMode : mResizeMode;
Louis Changa009c762020-02-26 11:21:31 +08003408 info.topActivityType = top.getActivityType();
Robert Carrf6690d12020-02-04 14:16:21 -08003409
3410 if (mPictureInPictureParams.empty()) {
3411 info.pictureInPictureParams = null;
3412 } else {
3413 info.pictureInPictureParams = mPictureInPictureParams;
3414 }
Hongwei Wang2e725be2020-03-10 11:01:28 -07003415 info.topActivityInfo = mReuseActivitiesReport.top != null
3416 ? mReuseActivitiesReport.top.info
3417 : null;
Louis Changcdec0802019-11-11 11:45:07 +08003418 }
3419
3420 /**
3421 * Returns a {@link TaskInfo} with information from this task.
3422 */
3423 ActivityManager.RunningTaskInfo getTaskInfo() {
3424 ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
3425 fillTaskInfo(info);
3426 return info;
3427 }
3428
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003429 boolean isTaskId(int taskId) {
3430 return mTaskId == taskId;
3431 }
3432
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003433 @Override
3434 Task asTask() {
3435 // I'm a task!
3436 return this;
3437 }
3438
3439 // TODO(task-merge): Figure-out how this should work with hierarchy tasks.
3440 boolean shouldBeVisible(ActivityRecord starting) {
3441 return true;
3442 }
3443
Louis Changcdec0802019-11-11 11:45:07 +08003444 void dump(PrintWriter pw, String prefix) {
3445 pw.print(prefix); pw.print("userId="); pw.print(mUserId);
3446 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
3447 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
3448 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Wale Ogunwale0d465192020-01-23 19:14:44 -08003449 pw.print(" mCallingPackage="); pw.print(mCallingPackage);
Philip P. Moltmannee295092020-02-10 08:46:26 -08003450 pw.print(" mCallingFeatureId="); pw.println(mCallingFeatureId);
Louis Changcdec0802019-11-11 11:45:07 +08003451 if (affinity != null || rootAffinity != null) {
3452 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
3453 if (affinity == null || !affinity.equals(rootAffinity)) {
3454 pw.print(" root="); pw.println(rootAffinity);
3455 } else {
3456 pw.println();
3457 }
3458 }
Garfield Tan5901e7c2020-02-07 17:12:22 -08003459 if (mWindowLayoutAffinity != null) {
3460 pw.print(prefix); pw.print("windowLayoutAffinity="); pw.println(mWindowLayoutAffinity);
3461 }
Louis Changcdec0802019-11-11 11:45:07 +08003462 if (voiceSession != null || voiceInteractor != null) {
3463 pw.print(prefix); pw.print("VOICE: session=0x");
3464 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
3465 pw.print(" interactor=0x");
3466 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
3467 }
3468 if (intent != null) {
3469 StringBuilder sb = new StringBuilder(128);
3470 sb.append(prefix); sb.append("intent={");
3471 intent.toShortString(sb, false, true, false, false);
3472 sb.append('}');
3473 pw.println(sb.toString());
3474 }
3475 if (affinityIntent != null) {
3476 StringBuilder sb = new StringBuilder(128);
3477 sb.append(prefix); sb.append("affinityIntent={");
3478 affinityIntent.toShortString(sb, false, true, false, false);
3479 sb.append('}');
3480 pw.println(sb.toString());
3481 }
3482 if (origActivity != null) {
3483 pw.print(prefix); pw.print("origActivity=");
3484 pw.println(origActivity.flattenToShortString());
3485 }
3486 if (realActivity != null) {
3487 pw.print(prefix); pw.print("mActivityComponent=");
3488 pw.println(realActivity.flattenToShortString());
3489 }
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08003490 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard()) {
Louis Changcdec0802019-11-11 11:45:07 +08003491 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
3492 pw.print(" isPersistable="); pw.print(isPersistable);
Louis Changcdec0802019-11-11 11:45:07 +08003493 pw.print(" activityType="); pw.println(getActivityType());
3494 }
3495 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
3496 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
3497 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
3498 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
3499 pw.print(" mReuseTask="); pw.print(mReuseTask);
3500 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
3501 }
3502 if (mAffiliatedTaskId != mTaskId || mPrevAffiliateTaskId != INVALID_TASK_ID
3503 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
3504 || mNextAffiliate != null) {
3505 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
3506 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
3507 pw.print(" (");
3508 if (mPrevAffiliate == null) {
3509 pw.print("null");
3510 } else {
3511 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
3512 }
3513 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
3514 pw.print(" (");
3515 if (mNextAffiliate == null) {
3516 pw.print("null");
3517 } else {
3518 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
3519 }
3520 pw.println(")");
3521 }
3522 pw.print(prefix); pw.print("Activities="); pw.println(mChildren);
3523 if (!askedCompatMode || !inRecents || !isAvailable) {
3524 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
3525 pw.print(" inRecents="); pw.print(inRecents);
3526 pw.print(" isAvailable="); pw.println(isAvailable);
3527 }
3528 if (lastDescription != null) {
3529 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
3530 }
3531 if (mRootProcess != null) {
3532 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
3533 }
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003534 pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId());
Robert Carrde96c8a2020-03-24 15:22:21 -07003535 pw.print(prefix + "mHasBeenVisible=" + getHasBeenVisible());
Louis Changcdec0802019-11-11 11:45:07 +08003536 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
3537 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
3538 pw.print(" isResizeable=" + isResizeable());
3539 pw.print(" lastActiveTime=" + lastActiveTime);
3540 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
3541 }
3542
3543 @Override
3544 public String toString() {
3545 StringBuilder sb = new StringBuilder(128);
3546 if (stringName != null) {
3547 sb.append(stringName);
3548 sb.append(" U=");
3549 sb.append(mUserId);
3550 sb.append(" StackId=");
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003551 sb.append(getRootTaskId());
Louis Changcdec0802019-11-11 11:45:07 +08003552 sb.append(" sz=");
3553 sb.append(getChildCount());
3554 sb.append('}');
3555 return sb.toString();
3556 }
3557 sb.append("Task{");
3558 sb.append(Integer.toHexString(System.identityHashCode(this)));
3559 sb.append(" #");
3560 sb.append(mTaskId);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003561 sb.append(" visible=" + shouldBeVisible(null /* starting */));
3562 sb.append(" type=" + activityTypeToString(getActivityType()));
3563 sb.append(" mode=" + windowingModeToString(getWindowingMode()));
3564 sb.append(" translucent=" + isTranslucent(null /* starting */));
Louis Changcdec0802019-11-11 11:45:07 +08003565 if (affinity != null) {
3566 sb.append(" A=");
3567 sb.append(affinity);
Evan Rosky0037e5f2019-11-05 10:26:24 -08003568 } else if (intent != null && intent.getComponent() != null) {
Louis Changcdec0802019-11-11 11:45:07 +08003569 sb.append(" I=");
3570 sb.append(intent.getComponent().flattenToShortString());
3571 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
3572 sb.append(" aI=");
3573 sb.append(affinityIntent.getComponent().flattenToShortString());
3574 } else {
3575 sb.append(" ??");
3576 }
3577 stringName = sb.toString();
3578 return toString();
3579 }
3580
Louis Changcdec0802019-11-11 11:45:07 +08003581 /** @see #getNumRunningActivities(TaskActivitiesReport) */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003582 static class TaskActivitiesReport implements Consumer<ActivityRecord> {
Louis Changcdec0802019-11-11 11:45:07 +08003583 int numRunning;
3584 int numActivities;
3585 ActivityRecord top;
3586 ActivityRecord base;
3587
3588 void reset() {
3589 numRunning = numActivities = 0;
3590 top = base = null;
3591 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003592
3593 @Override
3594 public void accept(ActivityRecord r) {
3595 if (r.finishing) {
3596 return;
3597 }
3598
3599 base = r;
3600
3601 // Increment the total number of non-finishing activities
3602 numActivities++;
3603
3604 if (top == null || (top.isState(ActivityState.INITIALIZING))) {
3605 top = r;
3606 // Reset the number of running activities until we hit the first non-initializing
3607 // activity
3608 numRunning = 0;
3609 }
3610 if (r.attachedToProcess()) {
3611 // Increment the number of actually running activities
3612 numRunning++;
3613 }
3614 }
Louis Changcdec0802019-11-11 11:45:07 +08003615 }
3616
3617 /**
3618 * Saves this {@link Task} to XML using given serializer.
3619 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003620 void saveToXml(XmlSerializer out) throws Exception {
Louis Changcdec0802019-11-11 11:45:07 +08003621 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
3622
3623 out.attribute(null, ATTR_TASKID, String.valueOf(mTaskId));
3624 if (realActivity != null) {
3625 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
3626 }
3627 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
3628 if (origActivity != null) {
3629 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
3630 }
3631 // Write affinity, and root affinity if it is different from affinity.
3632 // We use the special string "@" for a null root affinity, so we can identify
3633 // later whether we were given a root affinity or should just make it the
3634 // same as the affinity.
3635 if (affinity != null) {
3636 out.attribute(null, ATTR_AFFINITY, affinity);
3637 if (!affinity.equals(rootAffinity)) {
3638 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3639 }
3640 } else if (rootAffinity != null) {
3641 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3642 }
Garfield Tan5901e7c2020-02-07 17:12:22 -08003643 if (mWindowLayoutAffinity != null) {
3644 out.attribute(null, ATTR_WINDOW_LAYOUT_AFFINITY, mWindowLayoutAffinity);
3645 }
Louis Changcdec0802019-11-11 11:45:07 +08003646 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
3647 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
3648 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
3649 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
3650 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
3651 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
3652 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
3653 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
3654 if (lastDescription != null) {
3655 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
3656 }
3657 if (getTaskDescription() != null) {
3658 getTaskDescription().saveToXml(out);
3659 }
3660 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
3661 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
3662 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
3663 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
3664 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
3665 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
Philip P. Moltmannee295092020-02-10 08:46:26 -08003666 out.attribute(null, ATTR_CALLING_FEATURE_ID,
3667 mCallingFeatureId == null ? "" : mCallingFeatureId);
Louis Changcdec0802019-11-11 11:45:07 +08003668 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
3669 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
3670 String.valueOf(mSupportsPictureInPicture));
3671 if (mLastNonFullscreenBounds != null) {
3672 out.attribute(
3673 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
3674 }
3675 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
3676 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
3677 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
3678
3679 if (affinityIntent != null) {
3680 out.startTag(null, TAG_AFFINITYINTENT);
3681 affinityIntent.saveToXml(out);
3682 out.endTag(null, TAG_AFFINITYINTENT);
3683 }
3684
3685 if (intent != null) {
3686 out.startTag(null, TAG_INTENT);
3687 intent.saveToXml(out);
3688 out.endTag(null, TAG_INTENT);
3689 }
3690
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003691 sTmpException = null;
3692 final PooledFunction f = PooledLambda.obtainFunction(Task::saveActivityToXml,
3693 PooledLambda.__(ActivityRecord.class), getBottomMostActivity(), out);
3694 forAllActivities(f);
3695 f.recycle();
3696 if (sTmpException != null) {
3697 throw sTmpException;
3698 }
3699 }
3700
3701 private static boolean saveActivityToXml(
3702 ActivityRecord r, ActivityRecord first, XmlSerializer out) {
3703 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable()
3704 || ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
3705 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT)
3706 && r != first) {
3707 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
3708 return true;
3709 }
3710 try {
Louis Changcdec0802019-11-11 11:45:07 +08003711 out.startTag(null, TAG_ACTIVITY);
3712 r.saveToXml(out);
3713 out.endTag(null, TAG_ACTIVITY);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003714 return false;
3715 } catch (Exception e) {
3716 sTmpException = e;
3717 return true;
Louis Changcdec0802019-11-11 11:45:07 +08003718 }
3719 }
3720
3721 @VisibleForTesting
3722 static TaskFactory getTaskFactory() {
3723 if (sTaskFactory == null) {
3724 setTaskFactory(new TaskFactory());
3725 }
3726 return sTaskFactory;
3727 }
3728
3729 static void setTaskFactory(TaskFactory factory) {
3730 sTaskFactory = factory;
3731 }
3732
Garfield Tan9867b512020-02-28 09:48:15 -08003733 static Task create(ActivityTaskManagerService service, int taskId, int activityType,
Louis Changa009c762020-02-26 11:21:31 +08003734 ActivityInfo info, Intent intent, boolean createdByOrganizer) {
3735 return getTaskFactory().create(service, taskId, activityType, info, intent,
3736 createdByOrganizer);
Garfield Tan9867b512020-02-28 09:48:15 -08003737 }
3738
Louis Changcdec0802019-11-11 11:45:07 +08003739 static Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
3740 Intent intent, IVoiceInteractionSession voiceSession,
3741 IVoiceInteractor voiceInteractor, ActivityStack stack) {
3742 return getTaskFactory().create(
3743 service, taskId, info, intent, voiceSession, voiceInteractor, stack);
3744 }
3745
Louis Changcdec0802019-11-11 11:45:07 +08003746 static Task restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
3747 throws IOException, XmlPullParserException {
3748 return getTaskFactory().restoreFromXml(in, stackSupervisor);
3749 }
3750
3751 /**
3752 * A factory class used to create {@link Task} or its subclass if any. This can be
3753 * specified when system boots by setting it with
3754 * {@link #setTaskFactory(TaskFactory)}.
3755 */
3756 static class TaskFactory {
Garfield Tan9867b512020-02-28 09:48:15 -08003757 Task create(ActivityTaskManagerService service, int taskId, int activityType,
Louis Changa009c762020-02-26 11:21:31 +08003758 ActivityInfo info, Intent intent, boolean createdByOrganizer) {
3759 return new ActivityStack(service, taskId, activityType, info, intent,
3760 createdByOrganizer);
Garfield Tan9867b512020-02-28 09:48:15 -08003761 }
Louis Changcdec0802019-11-11 11:45:07 +08003762
3763 Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
3764 Intent intent, IVoiceInteractionSession voiceSession,
3765 IVoiceInteractor voiceInteractor, ActivityStack stack) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003766 return new ActivityStack(service, taskId, info, intent, voiceSession, voiceInteractor,
Louis Changcdec0802019-11-11 11:45:07 +08003767 null /*taskDescription*/, stack);
3768 }
3769
Louis Changcdec0802019-11-11 11:45:07 +08003770 /**
3771 * Should only be used when we're restoring {@link Task} from storage.
3772 */
3773 Task create(ActivityTaskManagerService service, int taskId, Intent intent,
3774 Intent affinityIntent, String affinity, String rootAffinity,
3775 ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
3776 boolean autoRemoveRecents, boolean askedCompatMode, int userId,
3777 int effectiveUid, String lastDescription,
3778 long lastTimeMoved, boolean neverRelinquishIdentity,
3779 TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
3780 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Philip P. Moltmannee295092020-02-10 08:46:26 -08003781 @Nullable String callingFeatureId, int resizeMode,
3782 boolean supportsPictureInPicture, boolean realActivitySuspended,
Louis Changcdec0802019-11-11 11:45:07 +08003783 boolean userSetupComplete, int minWidth, int minHeight, ActivityStack stack) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003784 return new ActivityStack(service, taskId, intent, affinityIntent, affinity,
Louis Changcdec0802019-11-11 11:45:07 +08003785 rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
3786 askedCompatMode, userId, effectiveUid, lastDescription,
3787 lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
3788 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
Philip P. Moltmannee295092020-02-10 08:46:26 -08003789 callingFeatureId, resizeMode, supportsPictureInPicture, realActivitySuspended,
3790 userSetupComplete, minWidth, minHeight, null /*ActivityInfo*/,
3791 null /*_voiceSession*/, null /*_voiceInteractor*/, stack);
Louis Changcdec0802019-11-11 11:45:07 +08003792 }
3793
3794 Task restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
3795 throws IOException, XmlPullParserException {
3796 Intent intent = null;
3797 Intent affinityIntent = null;
3798 ArrayList<ActivityRecord> activities = new ArrayList<>();
3799 ComponentName realActivity = null;
3800 boolean realActivitySuspended = false;
3801 ComponentName origActivity = null;
3802 String affinity = null;
3803 String rootAffinity = null;
3804 boolean hasRootAffinity = false;
Garfield Tan5901e7c2020-02-07 17:12:22 -08003805 String windowLayoutAffinity = null;
Louis Changcdec0802019-11-11 11:45:07 +08003806 boolean rootHasReset = false;
3807 boolean autoRemoveRecents = false;
3808 boolean askedCompatMode = false;
3809 int taskType = 0;
3810 int userId = 0;
3811 boolean userSetupComplete = true;
3812 int effectiveUid = -1;
3813 String lastDescription = null;
3814 long lastTimeOnTop = 0;
3815 boolean neverRelinquishIdentity = true;
3816 int taskId = INVALID_TASK_ID;
3817 final int outerDepth = in.getDepth();
3818 TaskDescription taskDescription = new TaskDescription();
3819 int taskAffiliation = INVALID_TASK_ID;
3820 int taskAffiliationColor = 0;
3821 int prevTaskId = INVALID_TASK_ID;
3822 int nextTaskId = INVALID_TASK_ID;
3823 int callingUid = -1;
3824 String callingPackage = "";
Philip P. Moltmannee295092020-02-10 08:46:26 -08003825 String callingFeatureId = null;
Louis Changcdec0802019-11-11 11:45:07 +08003826 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
3827 boolean supportsPictureInPicture = false;
3828 Rect lastNonFullscreenBounds = null;
3829 int minWidth = INVALID_MIN_SIZE;
3830 int minHeight = INVALID_MIN_SIZE;
3831 int persistTaskVersion = 0;
3832
3833 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
3834 final String attrName = in.getAttributeName(attrNdx);
3835 final String attrValue = in.getAttributeValue(attrNdx);
3836 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: attribute name="
3837 + attrName + " value=" + attrValue);
3838 switch (attrName) {
3839 case ATTR_TASKID:
3840 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
3841 break;
3842 case ATTR_REALACTIVITY:
3843 realActivity = ComponentName.unflattenFromString(attrValue);
3844 break;
3845 case ATTR_REALACTIVITY_SUSPENDED:
3846 realActivitySuspended = Boolean.valueOf(attrValue);
3847 break;
3848 case ATTR_ORIGACTIVITY:
3849 origActivity = ComponentName.unflattenFromString(attrValue);
3850 break;
3851 case ATTR_AFFINITY:
3852 affinity = attrValue;
3853 break;
3854 case ATTR_ROOT_AFFINITY:
3855 rootAffinity = attrValue;
3856 hasRootAffinity = true;
3857 break;
Garfield Tan5901e7c2020-02-07 17:12:22 -08003858 case ATTR_WINDOW_LAYOUT_AFFINITY:
3859 windowLayoutAffinity = attrValue;
3860 break;
Louis Changcdec0802019-11-11 11:45:07 +08003861 case ATTR_ROOTHASRESET:
3862 rootHasReset = Boolean.parseBoolean(attrValue);
3863 break;
3864 case ATTR_AUTOREMOVERECENTS:
3865 autoRemoveRecents = Boolean.parseBoolean(attrValue);
3866 break;
3867 case ATTR_ASKEDCOMPATMODE:
3868 askedCompatMode = Boolean.parseBoolean(attrValue);
3869 break;
3870 case ATTR_USERID:
3871 userId = Integer.parseInt(attrValue);
3872 break;
3873 case ATTR_USER_SETUP_COMPLETE:
3874 userSetupComplete = Boolean.parseBoolean(attrValue);
3875 break;
3876 case ATTR_EFFECTIVE_UID:
3877 effectiveUid = Integer.parseInt(attrValue);
3878 break;
3879 case ATTR_TASKTYPE:
3880 taskType = Integer.parseInt(attrValue);
3881 break;
3882 case ATTR_LASTDESCRIPTION:
3883 lastDescription = attrValue;
3884 break;
3885 case ATTR_LASTTIMEMOVED:
3886 lastTimeOnTop = Long.parseLong(attrValue);
3887 break;
3888 case ATTR_NEVERRELINQUISH:
3889 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
3890 break;
3891 case ATTR_TASK_AFFILIATION:
3892 taskAffiliation = Integer.parseInt(attrValue);
3893 break;
3894 case ATTR_PREV_AFFILIATION:
3895 prevTaskId = Integer.parseInt(attrValue);
3896 break;
3897 case ATTR_NEXT_AFFILIATION:
3898 nextTaskId = Integer.parseInt(attrValue);
3899 break;
3900 case ATTR_TASK_AFFILIATION_COLOR:
3901 taskAffiliationColor = Integer.parseInt(attrValue);
3902 break;
3903 case ATTR_CALLING_UID:
3904 callingUid = Integer.parseInt(attrValue);
3905 break;
3906 case ATTR_CALLING_PACKAGE:
3907 callingPackage = attrValue;
3908 break;
Philip P. Moltmannee295092020-02-10 08:46:26 -08003909 case ATTR_CALLING_FEATURE_ID:
3910 callingFeatureId = attrValue;
3911 break;
Louis Changcdec0802019-11-11 11:45:07 +08003912 case ATTR_RESIZE_MODE:
3913 resizeMode = Integer.parseInt(attrValue);
3914 break;
3915 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
3916 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
3917 break;
3918 case ATTR_NON_FULLSCREEN_BOUNDS:
3919 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
3920 break;
3921 case ATTR_MIN_WIDTH:
3922 minWidth = Integer.parseInt(attrValue);
3923 break;
3924 case ATTR_MIN_HEIGHT:
3925 minHeight = Integer.parseInt(attrValue);
3926 break;
3927 case ATTR_PERSIST_TASK_VERSION:
3928 persistTaskVersion = Integer.parseInt(attrValue);
3929 break;
3930 default:
Winson Chungd6722032020-02-18 15:16:08 -08003931 if (!attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
Louis Changcdec0802019-11-11 11:45:07 +08003932 Slog.w(TAG, "Task: Unknown attribute=" + attrName);
3933 }
3934 }
3935 }
Winson Chungd6722032020-02-18 15:16:08 -08003936 taskDescription.restoreFromXml(in);
Louis Changcdec0802019-11-11 11:45:07 +08003937
3938 int event;
3939 while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
3940 && (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
3941 if (event == XmlPullParser.START_TAG) {
3942 final String name = in.getName();
3943 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
3944 "Task: START_TAG name=" + name);
3945 if (TAG_AFFINITYINTENT.equals(name)) {
3946 affinityIntent = Intent.restoreFromXml(in);
3947 } else if (TAG_INTENT.equals(name)) {
3948 intent = Intent.restoreFromXml(in);
3949 } else if (TAG_ACTIVITY.equals(name)) {
3950 ActivityRecord activity =
3951 ActivityRecord.restoreFromXml(in, stackSupervisor);
3952 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: activity="
3953 + activity);
3954 if (activity != null) {
3955 activities.add(activity);
3956 }
3957 } else {
3958 handleUnknownTag(name, in);
3959 }
3960 }
3961 }
3962 if (!hasRootAffinity) {
3963 rootAffinity = affinity;
3964 } else if ("@".equals(rootAffinity)) {
3965 rootAffinity = null;
3966 }
3967 if (effectiveUid <= 0) {
3968 Intent checkIntent = intent != null ? intent : affinityIntent;
3969 effectiveUid = 0;
3970 if (checkIntent != null) {
3971 IPackageManager pm = AppGlobals.getPackageManager();
3972 try {
3973 ApplicationInfo ai = pm.getApplicationInfo(
3974 checkIntent.getComponent().getPackageName(),
3975 PackageManager.MATCH_UNINSTALLED_PACKAGES
3976 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
3977 if (ai != null) {
3978 effectiveUid = ai.uid;
3979 }
3980 } catch (RemoteException e) {
3981 }
3982 }
3983 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
3984 + ": effectiveUid=" + effectiveUid);
3985 }
3986
3987 if (persistTaskVersion < 1) {
3988 // We need to convert the resize mode of home activities saved before version one if
3989 // they are marked as RESIZE_MODE_RESIZEABLE to
3990 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
3991 // before version 1 and the system didn't resize home activities before then.
3992 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
3993 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
3994 }
3995 } else {
3996 // This activity has previously marked itself explicitly as both resizeable and
3997 // supporting picture-in-picture. Since there is no longer a requirement for
3998 // picture-in-picture activities to be resizeable, we can mark this simply as
3999 // resizeable and supporting picture-in-picture separately.
4000 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
4001 resizeMode = RESIZE_MODE_RESIZEABLE;
4002 supportsPictureInPicture = true;
4003 }
4004 }
4005
4006 final Task task = create(stackSupervisor.mService,
4007 taskId, intent, affinityIntent,
4008 affinity, rootAffinity, realActivity, origActivity, rootHasReset,
4009 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
4010 lastTimeOnTop, neverRelinquishIdentity, taskDescription,
4011 taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
Philip P. Moltmannee295092020-02-10 08:46:26 -08004012 callingPackage, callingFeatureId, resizeMode, supportsPictureInPicture,
4013 realActivitySuspended, userSetupComplete, minWidth, minHeight, null /*stack*/);
Louis Changcdec0802019-11-11 11:45:07 +08004014 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
4015 task.setBounds(lastNonFullscreenBounds);
Garfield Tan5901e7c2020-02-07 17:12:22 -08004016 task.mWindowLayoutAffinity = windowLayoutAffinity;
Louis Changcdec0802019-11-11 11:45:07 +08004017
4018 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4019 task.addChild(activities.get(activityNdx));
4020 }
4021
4022 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
4023 return task;
4024 }
4025
4026 void handleUnknownTag(String name, XmlPullParser in)
4027 throws IOException, XmlPullParserException {
4028 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
4029 XmlUtils.skipCurrentTag(in);
4030 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07004031 }
Robert Carr8a2f9132019-11-11 15:03:15 -08004032
Wale Ogunwaledec34082020-03-22 09:45:00 -07004033 @Override
4034 boolean isOrganized() {
Wale Ogunwale465b1e12020-03-31 12:15:51 -07004035 return mTaskOrganizer != null;
Robert Carr8a2f9132019-11-11 15:03:15 -08004036 }
4037
4038 @Override
4039 protected void reparentSurfaceControl(SurfaceControl.Transaction t, SurfaceControl newParent) {
4040 /**
Louis Changa009c762020-02-26 11:21:31 +08004041 * Avoid reparenting SurfaceControl of the organized tasks that are always on top, since
4042 * the surfaces should be controlled by the organizer itself, like bubbles.
Robert Carr8a2f9132019-11-11 15:03:15 -08004043 */
Louis Changa009c762020-02-26 11:21:31 +08004044 if (isOrganized() && isAlwaysOnTop()) {
Robert Carr8a2f9132019-11-11 15:03:15 -08004045 return;
4046 }
4047 super.reparentSurfaceControl(t, newParent);
4048 }
4049
Robert Carrde96c8a2020-03-24 15:22:21 -07004050 void setHasBeenVisible(boolean hasBeenVisible) {
Winson Chung8b5d23a2020-04-06 19:23:23 -07004051 final boolean prevHasBeenVisible = mHasBeenVisible;
Robert Carrde96c8a2020-03-24 15:22:21 -07004052 mHasBeenVisible = hasBeenVisible;
4053 if (hasBeenVisible) {
Winson Chung8b5d23a2020-04-06 19:23:23 -07004054 // If the task is not yet visible when it is added to the task organizer, then we should
4055 // hide it to allow the task organizer to show it when it is properly reparented. We
4056 // skip this for tasks created by the organizer because they can synchronously update
4057 // the leash before new children are added to the task.
4058 if (!mCreatedByOrganizer && mTaskOrganizer != null && !prevHasBeenVisible) {
4059 getPendingTransaction().hide(getSurfaceControl());
4060 commitPendingTransaction();
4061 }
4062
Robert Carrde96c8a2020-03-24 15:22:21 -07004063 sendTaskAppeared();
4064 if (!isRootTask()) {
4065 getRootTask().setHasBeenVisible(true);
4066 }
4067 }
4068 }
4069
4070 boolean getHasBeenVisible() {
4071 return mHasBeenVisible;
4072 }
4073
4074 /** In the case that these three conditions are true, we want to send the Task to
4075 * the organizer:
4076 * 1. We have a SurfaceControl
4077 * 2. An organizer has been set
4078 * 3. We have finished drawing
4079 * Any time any of these conditions are updated, the updating code should call
4080 * sendTaskAppeared.
4081 */
Louis Chang9d35a3a2020-04-06 17:23:02 +08004082 boolean taskAppearedReady() {
Robert Carrde96c8a2020-03-24 15:22:21 -07004083 return mSurfaceControl != null && mTaskOrganizer != null && getHasBeenVisible();
4084 }
4085
Robert Carr8a2f9132019-11-11 15:03:15 -08004086 private void sendTaskAppeared() {
Louis Chang9d35a3a2020-04-06 17:23:02 +08004087 if (mTaskOrganizer != null) {
Robert Carr8a2f9132019-11-11 15:03:15 -08004088 mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this);
4089 }
4090 }
4091
4092 private void sendTaskVanished() {
Louis Chang9d35a3a2020-04-06 17:23:02 +08004093 if (mTaskOrganizer != null) {
Robert Carr8a2f9132019-11-11 15:03:15 -08004094 mAtmService.mTaskOrganizerController.onTaskVanished(mTaskOrganizer, this);
4095 }
4096 }
4097
Wale Ogunwale465b1e12020-03-31 12:15:51 -07004098 @VisibleForTesting
Evan Roskyf64f5da2020-03-16 13:47:48 -07004099 boolean setTaskOrganizer(ITaskOrganizer organizer) {
Evan Rosky0037e5f2019-11-05 10:26:24 -08004100 if (mTaskOrganizer == organizer) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07004101 return false;
Evan Rosky0037e5f2019-11-05 10:26:24 -08004102 }
Robert Carr8a2f9132019-11-11 15:03:15 -08004103 // Let the old organizer know it has lost control.
Robert Carrf6878a42019-12-18 02:13:12 -08004104 sendTaskVanished();
Robert Carr8a2f9132019-11-11 15:03:15 -08004105 mTaskOrganizer = organizer;
4106 sendTaskAppeared();
Robert Carrf6878a42019-12-18 02:13:12 -08004107 onTaskOrganizerChanged();
Evan Roskyf64f5da2020-03-16 13:47:48 -07004108 return true;
Robert Carr8a2f9132019-11-11 15:03:15 -08004109 }
4110
Winson Chungaff506b2020-03-21 22:56:31 -07004111 void taskOrganizerUnregistered() {
Robert Carr8a2f9132019-11-11 15:03:15 -08004112 mTaskOrganizer = null;
Robert Carrde96c8a2020-03-24 15:22:21 -07004113 mTaskAppearedSent = false;
Winson Chung77338ab2020-03-09 16:32:34 -07004114 mLastTaskOrganizerWindowingMode = -1;
Robert Carrf6878a42019-12-18 02:13:12 -08004115 onTaskOrganizerChanged();
Louis Changa009c762020-02-26 11:21:31 +08004116 if (mCreatedByOrganizer) {
4117 removeImmediately();
4118 }
Winson Chung77338ab2020-03-09 16:32:34 -07004119 }
4120
4121 /**
4122 * Called when the task state changes (ie. from windowing mode change) an the task organizer
4123 * state should also be updated.
4124 *
4125 * @param forceUpdate Updates the task organizer to the one currently specified in the task
4126 * org controller for the task's windowing mode, ignoring the cached
4127 * windowing mode checks.
Evan Roskyf64f5da2020-03-16 13:47:48 -07004128 * @return {@code true} if task organizer changed.
Winson Chung77338ab2020-03-09 16:32:34 -07004129 */
Evan Roskyf64f5da2020-03-16 13:47:48 -07004130 boolean updateTaskOrganizerState(boolean forceUpdate) {
Winson Chung77338ab2020-03-09 16:32:34 -07004131 if (!isRootTask()) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07004132 return false;
Winson Chung77338ab2020-03-09 16:32:34 -07004133 }
4134
4135 final int windowingMode = getWindowingMode();
4136 if (!forceUpdate && windowingMode == mLastTaskOrganizerWindowingMode) {
4137 // If our windowing mode hasn't actually changed, then just stick
4138 // with our old organizer. This lets us implement the semantic
4139 // where SysUI can continue to manage it's old tasks
4140 // while CTS temporarily takes over the registration.
Evan Roskyf64f5da2020-03-16 13:47:48 -07004141 return false;
Winson Chung77338ab2020-03-09 16:32:34 -07004142 }
4143 /*
4144 * Different windowing modes may be managed by different task organizers. If
4145 * getTaskOrganizer returns null, we still call setTaskOrganizer to
4146 * make sure we clear it.
4147 */
4148 final ITaskOrganizer org =
4149 mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
Evan Roskyf64f5da2020-03-16 13:47:48 -07004150 final boolean result = setTaskOrganizer(org);
Winson Chung77338ab2020-03-09 16:32:34 -07004151 mLastTaskOrganizerWindowingMode = windowingMode;
Evan Roskyf64f5da2020-03-16 13:47:48 -07004152 return result;
Robert Carr8a2f9132019-11-11 15:03:15 -08004153 }
4154
Robert Carrf6878a42019-12-18 02:13:12 -08004155 private void onTaskOrganizerChanged() {
4156 if (mTaskOrganizer == null) {
4157 // If this task is no longer controlled by a task organizer, then reset the force hidden
4158 // state
4159 setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */);
4160 }
4161 }
4162
Robert Carr8a2f9132019-11-11 15:03:15 -08004163 @Override
4164 void setSurfaceControl(SurfaceControl sc) {
4165 super.setSurfaceControl(sc);
4166 // If the TaskOrganizer was set before we created the SurfaceControl, we need to
4167 // emit the callbacks now.
4168 sendTaskAppeared();
4169 }
4170
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004171 /**
4172 * @return true if the task is currently focused.
4173 */
4174 private boolean isFocused() {
4175 if (mDisplayContent == null || mDisplayContent.mCurrentFocus == null) {
4176 return false;
4177 }
4178 return mDisplayContent.mCurrentFocus.getTask() == this;
4179 }
4180
4181 /**
Vishnu Nairae3b0772020-03-19 16:55:25 -07004182 * @return true if the task is visible and has at least one visible child.
4183 */
4184 private boolean hasVisibleChildren() {
4185 if (!isAttached() || isForceHidden()) {
4186 return false;
4187 }
4188
4189 return getActivity(ActivityRecord::isVisible) != null;
4190 }
4191
4192 /**
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004193 * @return the desired shadow radius in pixels for the current task.
4194 */
4195 private float getShadowRadius(boolean taskIsFocused) {
Vishnu Nairae3b0772020-03-19 16:55:25 -07004196 int elevation = 0;
4197
4198 // Get elevation for a specific windowing mode.
4199 if (inPinnedWindowingMode()) {
4200 elevation = PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
Garfield Tan7e1cb5c2020-04-10 15:21:23 -07004201 } else if (inFreeformWindowingMode()) {
Vishnu Nairae3b0772020-03-19 16:55:25 -07004202 elevation = taskIsFocused
4203 ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
4204 } else {
4205 // For all other windowing modes, do not draw a shadow.
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004206 return 0;
4207 }
4208
Vishnu Nairae3b0772020-03-19 16:55:25 -07004209 // If the task has no visible children, do not draw a shadow.
4210 if (!hasVisibleChildren()) {
4211 return 0;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004212 }
4213
Vishnu Nairae3b0772020-03-19 16:55:25 -07004214 return dipToPixel(elevation, getDisplayContent().getDisplayMetrics());
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004215 }
4216
4217 /**
4218 * Update the length of the shadow if needed based on windowing mode and task focus state.
4219 */
4220 private void updateShadowsRadius(boolean taskIsFocused,
4221 SurfaceControl.Transaction pendingTransaction) {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08004222 if (!mWmService.mRenderShadowsInCompositor || !isRootTask()) return;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004223
4224 final float newShadowRadius = getShadowRadius(taskIsFocused);
4225 if (mShadowRadius != newShadowRadius) {
4226 mShadowRadius = newShadowRadius;
4227 pendingTransaction.setShadowRadius(getSurfaceControl(), mShadowRadius);
4228 }
4229 }
4230
4231 /**
4232 * Called on the task of a window which gained or lost focus.
4233 * @param hasFocus
4234 */
4235 void onWindowFocusChanged(boolean hasFocus) {
4236 updateShadowsRadius(hasFocus, getPendingTransaction());
4237 }
Robert Carrf6690d12020-02-04 14:16:21 -08004238
4239 void setPictureInPictureParams(PictureInPictureParams p) {
4240 mPictureInPictureParams.copyOnlySet(p);
Winson Chung1df39e22020-04-09 14:30:55 -07004241 if (isOrganized()) {
4242 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
4243 }
Robert Carrf6690d12020-02-04 14:16:21 -08004244 }
Robert Carr711e7052020-02-19 11:14:33 -08004245
4246 /**
4247 * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this
4248 * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy
4249 * to resize, and it will defer the transaction until that resize frame completes.
4250 */
4251 void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t) {
4252 mMainWindowSizeChangeTransaction = t;
4253 }
4254
4255 SurfaceControl.Transaction getMainWindowSizeChangeTransaction() {
4256 return mMainWindowSizeChangeTransaction;
4257 }
Vishnu Nairdddc9f52020-03-09 09:37:27 -07004258
Robert Carr2bed6212020-02-20 16:55:07 -08004259 void setActivityWindowingMode(int windowingMode) {
4260 PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setWindowingMode,
4261 PooledLambda.__(ActivityRecord.class), windowingMode);
4262 forAllActivities(c);
4263 c.recycle();
4264 }
4265
Robert Carrf6878a42019-12-18 02:13:12 -08004266 /**
4267 * Sets/unsets the forced-hidden state flag for this task depending on {@param set}.
4268 * @return Whether the force hidden state changed
4269 */
4270 boolean setForceHidden(int flags, boolean set) {
4271 int newFlags = mForceHiddenFlags;
4272 if (set) {
4273 newFlags |= flags;
4274 } else {
4275 newFlags &= ~flags;
4276 }
4277 if (mForceHiddenFlags == newFlags) {
4278 return false;
4279 }
4280 mForceHiddenFlags = newFlags;
4281 return true;
4282 }
4283
4284 /**
4285 * Returns whether this task is currently forced to be hidden for any reason.
4286 */
4287 protected boolean isForceHidden() {
4288 return mForceHiddenFlags != 0;
4289 }
4290
Vishnu Nairdddc9f52020-03-09 09:37:27 -07004291 @Override
4292 long getProtoFieldId() {
4293 return TASK;
4294 }
Robert Carr2bed6212020-02-20 16:55:07 -08004295
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08004296}