blob: 36cae1fb9b36c4f293b6a151febdedaed8084d6b [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;
Louis Changcdec0802019-11-11 11:45:07 +080023import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
24import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -080025import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
Louis Changcdec0802019-11-11 11:45:07 +080026import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
27import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
28import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
29import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
30import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
31import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
32import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080033import static android.app.WindowConfiguration.activityTypeToString;
34import static android.app.WindowConfiguration.windowingModeToString;
Louis Changcdec0802019-11-11 11:45:07 +080035import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
36import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
37import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
38import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
39import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
40import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
41import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
42import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
43import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080044import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
Jason Monkba53d8a2017-04-06 18:28:19 +000045import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020046import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Louis Changcdec0802019-11-11 11:45:07 +080047import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
48import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
49import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
50import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Bryce Lee61fbcbc2017-03-10 14:14:03 -080051import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Wale Ogunwale68278562017-09-23 17:13:55 -070052import static android.content.res.Configuration.EMPTY;
Louis Changcdec0802019-11-11 11:45:07 +080053import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
54import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
55import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
56import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
57import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
58import static android.view.Display.DEFAULT_DISPLAY;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -080059import static android.view.Display.INVALID_DISPLAY;
Evan Rosky9020c072018-12-06 14:11:12 -080060import static android.view.SurfaceControl.METADATA_TASK_ID;
chaviw8c9d1f52018-07-25 14:56:07 -070061
Vishnu Nairf6ef1c72020-01-23 16:28:33 -080062import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
63import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
Louis Changcdec0802019-11-11 11:45:07 +080064import static com.android.server.am.TaskRecordProto.ACTIVITIES;
65import static com.android.server.am.TaskRecordProto.ACTIVITY_TYPE;
Louis Changcdec0802019-11-11 11:45:07 +080066import static com.android.server.am.TaskRecordProto.FULLSCREEN;
Louis Changcdec0802019-11-11 11:45:07 +080067import static com.android.server.am.TaskRecordProto.LAST_NON_FULLSCREEN_BOUNDS;
68import static com.android.server.am.TaskRecordProto.MIN_HEIGHT;
69import static com.android.server.am.TaskRecordProto.MIN_WIDTH;
70import static com.android.server.am.TaskRecordProto.ORIG_ACTIVITY;
71import static com.android.server.am.TaskRecordProto.REAL_ACTIVITY;
72import static com.android.server.am.TaskRecordProto.RESIZE_MODE;
73import static com.android.server.am.TaskRecordProto.STACK_ID;
74import static com.android.server.am.TaskRecordProto.TASK;
Louis Changcdec0802019-11-11 11:45:07 +080075import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080076import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
Louis Changcdec0802019-11-11 11:45:07 +080077import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
78import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
79import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
80import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
81import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
82import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
83import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
84import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
85import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
86import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
87import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
88import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
89import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080090import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
Yunfan Chen0e7aff92018-12-05 16:35:32 -080091import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
Louis Changcdec0802019-11-11 11:45:07 +080092import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
Jeff Changacc340d2019-11-22 14:23:08 +080093import static com.android.server.wm.TaskProto.ACTIVITY;
Evan Roskyed6767f2018-10-26 17:21:06 -070094import static com.android.server.wm.TaskProto.DISPLAYED_BOUNDS;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070095import static com.android.server.wm.TaskProto.FILLS_PARENT;
Louis Chang7501e332018-08-20 13:08:39 +080096import static com.android.server.wm.TaskProto.SURFACE_HEIGHT;
97import static com.android.server.wm.TaskProto.SURFACE_WIDTH;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070098import static com.android.server.wm.TaskProto.WINDOW_CONTAINER;
lumark9bca6b42019-10-17 18:35:22 +080099import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
100import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
chaviw8c9d1f52018-07-25 14:56:07 -0700101import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800102import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
chaviw8c9d1f52018-07-25 14:56:07 -0700103import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -0800104import static com.android.server.wm.WindowManagerService.dipToPixel;
lumark5341d1c2019-12-14 01:54:02 +0800105import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Wale Ogunwale99db1862015-10-23 20:08:22 -0700106
Louis Changcdec0802019-11-11 11:45:07 +0800107import static java.lang.Integer.MAX_VALUE;
108
109import android.annotation.IntDef;
110import android.annotation.NonNull;
111import android.annotation.Nullable;
112import android.app.Activity;
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800113import android.app.ActivityManager;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100114import android.app.ActivityManager.TaskDescription;
Louis Changcdec0802019-11-11 11:45:07 +0800115import android.app.ActivityManager.TaskSnapshot;
116import android.app.ActivityOptions;
117import android.app.ActivityTaskManager;
118import android.app.AppGlobals;
119import android.app.TaskInfo;
120import android.app.WindowConfiguration;
121import android.content.ComponentName;
122import android.content.Intent;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800123import android.content.pm.ActivityInfo;
Louis Changcdec0802019-11-11 11:45:07 +0800124import android.content.pm.ApplicationInfo;
125import android.content.pm.IPackageManager;
126import android.content.pm.PackageManager;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700127import android.content.res.Configuration;
Robert Carr8a2f9132019-11-11 15:03:15 -0800128import android.graphics.Point;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700129import android.graphics.Rect;
Louis Changcdec0802019-11-11 11:45:07 +0800130import android.os.Debug;
Garfield Tan90b04282018-12-11 14:04:42 -0800131import android.os.IBinder;
Louis Changcdec0802019-11-11 11:45:07 +0800132import android.os.RemoteException;
133import android.os.SystemClock;
134import android.os.Trace;
135import android.os.UserHandle;
136import android.provider.Settings;
137import android.service.voice.IVoiceInteractionSession;
138import android.util.DisplayMetrics;
Craig Mautner42bf39e2014-02-21 16:46:22 -0800139import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -0700140import android.util.proto.ProtoOutputStream;
Louis Changcdec0802019-11-11 11:45:07 +0800141import android.view.DisplayInfo;
Robert Carr8a2f9132019-11-11 15:03:15 -0800142import android.view.ITaskOrganizer;
lumark19a5d2e2019-10-11 16:19:30 +0800143import android.view.RemoteAnimationTarget;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700144import android.view.Surface;
Winson Chungd41f71d2018-03-16 15:26:07 -0700145import android.view.SurfaceControl;
chaviw8c9d1f52018-07-25 14:56:07 -0700146
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800147import com.android.internal.annotations.VisibleForTesting;
Louis Changcdec0802019-11-11 11:45:07 +0800148import com.android.internal.app.IVoiceInteractor;
Louis Changcdec0802019-11-11 11:45:07 +0800149import com.android.internal.util.XmlUtils;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800150import com.android.internal.util.function.pooled.PooledConsumer;
151import com.android.internal.util.function.pooled.PooledFunction;
152import com.android.internal.util.function.pooled.PooledLambda;
153import com.android.internal.util.function.pooled.PooledPredicate;
Louis Changcdec0802019-11-11 11:45:07 +0800154import com.android.server.protolog.common.ProtoLog;
155import com.android.server.wm.ActivityStack.ActivityState;
Craig Mautner2c2549c2013-11-12 08:31:15 -0800156
Louis Changcdec0802019-11-11 11:45:07 +0800157import org.xmlpull.v1.XmlPullParser;
158import org.xmlpull.v1.XmlPullParserException;
159import org.xmlpull.v1.XmlSerializer;
160
161import java.io.IOException;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700162import java.io.PrintWriter;
Louis Changcdec0802019-11-11 11:45:07 +0800163import java.lang.annotation.Retention;
164import java.lang.annotation.RetentionPolicy;
165import java.util.ArrayList;
166import java.util.Objects;
Jorim Jaggi51304d72017-05-17 17:25:32 +0200167import java.util.function.Consumer;
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900168import java.util.function.Function;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800169import java.util.function.Predicate;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700170
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800171class Task extends WindowContainer<WindowContainer> {
Louis Changcdec0802019-11-11 11:45:07 +0800172 private static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_ATM;
173 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
174 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
175 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
176 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
177
178 private static final String ATTR_TASKID = "task_id";
179 private static final String TAG_INTENT = "intent";
180 private static final String TAG_AFFINITYINTENT = "affinity_intent";
181 private static final String ATTR_REALACTIVITY = "real_activity";
182 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
183 private static final String ATTR_ORIGACTIVITY = "orig_activity";
184 private static final String TAG_ACTIVITY = "activity";
185 private static final String ATTR_AFFINITY = "affinity";
186 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
187 private static final String ATTR_ROOTHASRESET = "root_has_reset";
188 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
189 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
190 private static final String ATTR_USERID = "user_id";
191 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
192 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
193 @Deprecated
194 private static final String ATTR_TASKTYPE = "task_type";
195 private static final String ATTR_LASTDESCRIPTION = "last_description";
196 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
197 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
198 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
199 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
200 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
201 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
202 private static final String ATTR_CALLING_UID = "calling_uid";
203 private static final String ATTR_CALLING_PACKAGE = "calling_package";
204 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
205 private static final String ATTR_RESIZE_MODE = "resize_mode";
206 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
207 private static final String ATTR_MIN_WIDTH = "min_width";
208 private static final String ATTR_MIN_HEIGHT = "min_height";
209 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
210
211 // Current version of the task record we persist. Used to check if we need to run any upgrade
212 // code.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800213 static final int PERSIST_TASK_VERSION = 1;
Louis Changcdec0802019-11-11 11:45:07 +0800214
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800215 static final int INVALID_MIN_SIZE = -1;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -0800216 private float mShadowRadius = 0;
217 private final Rect mLastSurfaceCrop = new Rect();
Louis Changcdec0802019-11-11 11:45:07 +0800218
219 /**
220 * The modes to control how the stack is moved to the front when calling {@link Task#reparent}.
221 */
222 @Retention(RetentionPolicy.SOURCE)
223 @IntDef({
224 REPARENT_MOVE_STACK_TO_FRONT,
225 REPARENT_KEEP_STACK_AT_FRONT,
226 REPARENT_LEAVE_STACK_IN_PLACE
227 })
228 @interface ReparentMoveStackMode {}
229 // Moves the stack to the front if it was not at the front
230 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
231 // Only moves the stack to the front if it was focused or front most already
232 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
233 // Do not move the stack as a part of reparenting
234 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
235
236 /**
237 * The factory used to create {@link Task}. This allows OEM subclass {@link Task}.
238 */
239 private static TaskFactory sTaskFactory;
240
241 String affinity; // The affinity name for this task, or null; may change identity.
242 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
243 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
244 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
245 Intent intent; // The original intent that started the task. Note that this value can
246 // be null.
247 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
248 int effectiveUid; // The current effective uid of the identity of this task.
249 ComponentName origActivity; // The non-alias activity component of the intent.
250 ComponentName realActivity; // The actual activity component that started the task.
251 boolean realActivitySuspended; // True if the actual activity component that started the
252 // task is suspended.
253 boolean inRecents; // Actually in the recents list?
254 long lastActiveTime; // Last time this task was active in the current device session,
255 // including sleep. This time is initialized to the elapsed time when
256 // restored from disk.
257 boolean isAvailable; // Is the activity available to be launched?
258 boolean rootWasReset; // True if the intent at the root of the task had
259 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
260 boolean autoRemoveRecents; // If true, we should automatically remove the task from
261 // recents when activity finishes
262 boolean askedCompatMode;// Have asked the user about compat mode for this task.
263 boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.
264
265 String stringName; // caching of toString() result.
266 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
267 // was changed.
268
Louis Changcdec0802019-11-11 11:45:07 +0800269 /** Can't be put in lockTask mode. */
270 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
271 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
272 final static int LOCK_TASK_AUTH_PINNABLE = 1;
273 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
274 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
275 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
276 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
277 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
278 * lockTask task. */
279 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
280 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
281
282 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
283
Louis Changcdec0802019-11-11 11:45:07 +0800284 /** The process that had previously hosted the root activity of this task.
285 * Used to know that we should try harder to keep this process around, in case the
286 * user wants to return to it. */
287 private WindowProcessController mRootProcess;
288
289 /** Takes on same value as first root activity */
290 boolean isPersistable = false;
291 int maxRecents;
292
293 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
294 * determining the order when restoring. Sign indicates whether last task movement was to front
295 * (positive) or back (negative). Absolute value indicates time. */
296 long mLastTimeMoved;
297
298 /** If original intent did not allow relinquishing task identity, save that information */
299 private boolean mNeverRelinquishIdentity = true;
300
301 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
302 // do not want to delete the stack when the task goes empty.
303 private boolean mReuseTask = false;
304
305 CharSequence lastDescription; // Last description captured for this item.
306
307 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
308 int mAffiliatedTaskColor; // color of the parent task affiliation.
309 Task mPrevAffiliate; // previous task in affiliated chain.
310 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
311 Task mNextAffiliate; // next task in affiliated chain.
312 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
313
314 // For relaunching the task from recents as though it was launched by the original launcher.
315 int mCallingUid;
316 String mCallingPackage;
317
318 private final Rect mTmpStableBounds = new Rect();
319 private final Rect mTmpNonDecorBounds = new Rect();
320 private final Rect mTmpBounds = new Rect();
321 private final Rect mTmpInsets = new Rect();
Evan Rosky70213702019-11-05 10:26:24 -0800322 private final Rect mTmpFullBounds = new Rect();
Louis Changcdec0802019-11-11 11:45:07 +0800323
324 // Last non-fullscreen bounds the task was launched in or resized to.
325 // The information is persisted and used to determine the appropriate stack to launch the
326 // task into on restore.
327 Rect mLastNonFullscreenBounds = null;
328 // Minimal width and height of this task when it's resizeable. -1 means it should use the
329 // default minimal width/height.
330 int mMinWidth;
331 int mMinHeight;
332
333 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
334 // This number will be assigned when we evaluate OOM scores for all visible tasks.
335 int mLayerRank = -1;
336
337 /** Helper object used for updating override configuration. */
338 private Configuration mTmpConfig = new Configuration();
339
340 /** Used by fillTaskInfo */
341 final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700342
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200343 final ActivityTaskManagerService mAtmService;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800344 final ActivityStackSupervisor mStackSupervisor;
345 final RootWindowContainer mRootWindowContainer;
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200346
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700347 /* Unique identifier for this task. */
Craig Mautner83162a92015-01-26 14:43:30 -0800348 final int mTaskId;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700349 /* User for which this task was created. */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200350 // TODO: Make final
351 int mUserId;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800352
Jorim Jaggi0429f352015-12-22 16:29:16 +0100353 final Rect mPreparedFrozenBounds = new Rect();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700354 final Configuration mPreparedFrozenMergedConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700355
Evan Roskyed6767f2018-10-26 17:21:06 -0700356 // If non-empty, bounds used to display the task during animations/interactions.
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200357 // TODO(b/119687367): This member is temporary.
Evan Roskyed6767f2018-10-26 17:21:06 -0700358 private final Rect mOverrideDisplayedBounds = new Rect();
Jorim Jaggidc249c42015-12-15 14:57:31 -0800359
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800360 // Id of the previous display the stack was on.
361 int mPrevDisplayId = INVALID_DISPLAY;
362
Garfield Tandec96db2018-10-30 11:28:49 -0700363 /** ID of the display which rotation {@link #mRotation} has. */
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800364 private int mLastRotationDisplayId = INVALID_DISPLAY;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800365
Garfield Tandec96db2018-10-30 11:28:49 -0700366 /**
367 * Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
368 * moved to a new display.
369 */
Vadim Caenfc14c662020-01-20 16:00:31 +0100370 @Surface.Rotation
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700371 private int mRotation;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700372
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700373 // For comparison with DisplayContent bounds.
374 private Rect mTmpRect = new Rect();
375 // For handling display rotations.
376 private Rect mTmpRect2 = new Rect();
377
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800378 // Resize mode of the task. See {@link ActivityInfo#resizeMode}
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200379 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
380 int mResizeMode;
Chong Zhangb15758a2015-11-17 12:12:03 -0800381
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200382 // Whether or not this task and its activities support PiP. Based on the
383 // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity.
384 boolean mSupportsPictureInPicture;
Winson Chungd3395382016-12-13 11:49:09 -0800385
Chong Zhang3005e752015-09-18 18:46:28 -0700386 // Whether the task is currently being drag-resized
387 private boolean mDragResizing;
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +0100388 private int mDragResizeMode;
Chong Zhang3005e752015-09-18 18:46:28 -0700389
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700390 // This represents the last resolved activity values for this task
391 // NOTE: This value needs to be persisted with each task
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100392 private TaskDescription mTaskDescription;
393
Robert Carr18f622f2017-05-08 11:20:43 -0700394 // If set to true, the task will report that it is not in the floating
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700395 // state regardless of it's stack affiliation. As the floating state drives
Robert Carr18f622f2017-05-08 11:20:43 -0700396 // production of content insets this can be used to preserve them across
397 // stack moves and we in fact do so when moving from full screen to pinned.
398 private boolean mPreserveNonFloatingState = false;
399
Robert Carrf59b8dd2017-10-02 18:58:36 -0700400 private Dimmer mDimmer = new Dimmer(this);
401 private final Rect mTmpDimBoundsRect = new Rect();
402
Jorim Jaggi50bf59c2018-03-09 17:29:48 +0100403 /** @see #setCanAffectSystemUiFlags */
404 private boolean mCanAffectSystemUiFlags = true;
405
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800406 private static Exception sTmpException;
407
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800408 /** ActivityRecords that are exiting, but still on screen for animations. */
409 final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
410
411 /**
412 * When we are in the process of pausing an activity, before starting the
413 * next one, this variable holds the activity that is currently being paused.
414 */
415 ActivityRecord mPausingActivity = null;
416
417 /**
418 * This is the last activity that we put into the paused state. This is
419 * used to determine if we need to do an activity transition while sleeping,
420 * when we normally hold the top activity paused.
421 */
422 ActivityRecord mLastPausedActivity = null;
423
424 /**
425 * Activities that specify No History must be removed once the user navigates away from them.
426 * If the device goes to sleep with such an activity in the paused state then we save it here
427 * and finish it later if another activity replaces it on wakeup.
428 */
429 ActivityRecord mLastNoHistoryActivity = null;
430
431 /** Current activity that is resumed, or null if there is none. */
432 ActivityRecord mResumedActivity = null;
433
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -0800434 private boolean mForceShowForAllUsers;
435
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800436 /** When set, will force the task to report as invisible. */
437 boolean mForceHidden = false;
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
477 * emit an IWindowContainer (allowing access to it's SurfaceControl leash) to the organizers
478 * taskAppeared callback, and emit a taskRemoved callback when the Task is vanished.
479 */
480 ITaskOrganizer mTaskOrganizer;
481
482
483 /**
Louis Changcdec0802019-11-11 11:45:07 +0800484 * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
485 * ActivityInfo, Intent, TaskDescription)} instead.
486 */
487 Task(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info, Intent _intent,
488 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
489 TaskDescription _taskDescription, ActivityStack stack) {
490 this(atmService, _taskId, _intent, null /*_affinityIntent*/, null /*_affinity*/,
491 null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
492 false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
493 UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
494 null /*_lastDescription*/, System.currentTimeMillis(),
495 true /*neverRelinquishIdentity*/,
496 _taskDescription != null ? _taskDescription : new TaskDescription(),
497 _taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
498 info.applicationInfo.uid, info.packageName, info.resizeMode,
499 info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
500 false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
501 _voiceSession, _voiceInteractor, stack);
502 }
503
Robert Carr8a2f9132019-11-11 15:03:15 -0800504 class TaskToken extends RemoteToken {
Evan Roskya80f11c2020-01-23 19:17:10 -0800505 TaskToken(WindowContainer container) {
Robert Carr8a2f9132019-11-11 15:03:15 -0800506 super(container);
507 }
508
509 @Override
510 public SurfaceControl getLeash() {
511 // We need to copy the SurfaceControl instead of returning the original
512 // because the Parcel FLAGS PARCELABLE_WRITE_RETURN_VALUE cause SurfaceControls
513 // to release themselves.
514 SurfaceControl sc = new SurfaceControl();
515 sc.copyFrom(getSurfaceControl());
516 return sc;
517 }
518 }
519
Louis Changcdec0802019-11-11 11:45:07 +0800520 /** Don't use constructor directly. This is only used by XML parser. */
521 Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
522 Intent _affinityIntent, String _affinity, String _rootAffinity,
523 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
524 boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId,
525 int _effectiveUid, String _lastDescription,
526 long lastTimeMoved, boolean neverRelinquishIdentity,
527 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
528 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
529 int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended,
530 boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info,
531 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
532 ActivityStack stack) {
533 super(atmService.mWindowManager);
534
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -0800535 EventLogTags.writeWmTaskCreated(_taskId, stack != null ? getRootTaskId() : INVALID_TASK_ID);
Louis Changcdec0802019-11-11 11:45:07 +0800536 mAtmService = atmService;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800537 mStackSupervisor = atmService.mStackSupervisor;
538 mRootWindowContainer = mAtmService.mRootWindowContainer;
Louis Changcdec0802019-11-11 11:45:07 +0800539 mTaskId = _taskId;
540 mUserId = _userId;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800541 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800542 mSupportsPictureInPicture = supportsPictureInPicture;
Louis Changcdec0802019-11-11 11:45:07 +0800543 mTaskDescription = _lastTaskDescription;
Riddle Hsu6b76cd32019-10-08 00:37:19 +0800544 // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
545 setOrientation(SCREEN_ORIENTATION_UNSET);
Robert Carr8a2f9132019-11-11 15:03:15 -0800546 mRemoteToken = new TaskToken(this);
Louis Changcdec0802019-11-11 11:45:07 +0800547 affinityIntent = _affinityIntent;
548 affinity = _affinity;
549 rootAffinity = _rootAffinity;
550 voiceSession = _voiceSession;
551 voiceInteractor = _voiceInteractor;
552 realActivity = _realActivity;
553 realActivitySuspended = _realActivitySuspended;
554 origActivity = _origActivity;
555 rootWasReset = _rootWasReset;
556 isAvailable = true;
557 autoRemoveRecents = _autoRemoveRecents;
558 askedCompatMode = _askedCompatMode;
559 mUserSetupComplete = userSetupComplete;
560 effectiveUid = _effectiveUid;
561 touchActiveTime();
562 lastDescription = _lastDescription;
563 mLastTimeMoved = lastTimeMoved;
564 mNeverRelinquishIdentity = neverRelinquishIdentity;
565 mAffiliatedTaskId = taskAffiliation;
566 mAffiliatedTaskColor = taskAffiliationColor;
567 mPrevAffiliateTaskId = prevTaskId;
568 mNextAffiliateTaskId = nextTaskId;
569 mCallingUid = callingUid;
570 mCallingPackage = callingPackage;
571 mResizeMode = resizeMode;
572 if (info != null) {
573 setIntent(_intent, info);
574 setMinDimensions(info);
575 } else {
576 intent = _intent;
577 mMinWidth = minWidth;
578 mMinHeight = minHeight;
579 }
580 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
581 }
582
Garfield Tan8b096b22020-01-07 14:55:20 -0800583 private void cleanUpResourcesForDestroy(ConfigurationContainer oldParent) {
Louis Changcdec0802019-11-11 11:45:07 +0800584 if (hasChild()) {
585 return;
586 }
587
Garfield Tan8b096b22020-01-07 14:55:20 -0800588 // TODO(xutan): Removed type check after stack and task is merged.
589 // Before the real merge of stack and task, we need to avoid saving state of stacks. Once
590 // the merge is finished we can just pass DisplayContent because both windowing mode and
591 // bounds are set in the merged task.
592 if (oldParent instanceof ActivityStack) {
593 // This task is going away, so save the last state if necessary.
594 saveLaunchingStateIfNeeded(((WindowContainer) oldParent).getDisplayContent());
595 }
Louis Changcdec0802019-11-11 11:45:07 +0800596
597 // TODO: VI what about activity?
598 final boolean isVoiceSession = voiceSession != null;
599 if (isVoiceSession) {
600 try {
601 voiceSession.taskFinished(intent, mTaskId);
602 } catch (RemoteException e) {
603 }
604 }
605 if (autoRemoveFromRecents() || isVoiceSession) {
606 // Task creator asked to remove this when done, or this task was a voice
607 // interaction, so it should not remain on the recent tasks list.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800608 mStackSupervisor.mRecentTasks.remove(this);
Louis Changcdec0802019-11-11 11:45:07 +0800609 }
610
611 removeIfPossible();
612 }
613
614 @VisibleForTesting
615 @Override
616 void removeIfPossible() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800617 final boolean isRootTask = isRootTask();
618 if (!isRootTask) {
619 mAtmService.getLockTaskController().clearLockedTask(this);
620 }
Louis Changcdec0802019-11-11 11:45:07 +0800621 if (shouldDeferRemoval()) {
622 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId);
623 return;
624 }
625 removeImmediately();
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800626 if (!isRootTask) {
627 mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
628 }
Louis Changcdec0802019-11-11 11:45:07 +0800629 }
630
631 void setResizeMode(int resizeMode) {
632 if (mResizeMode == resizeMode) {
633 return;
634 }
635 mResizeMode = resizeMode;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800636 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
637 mRootWindowContainer.resumeFocusedStacksTopActivities();
Louis Changcdec0802019-11-11 11:45:07 +0800638 updateTaskDescription();
639 }
640
641 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
642 mAtmService.deferWindowLayout();
643
644 try {
645 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
646
647 if (getParent() == null) {
648 // Task doesn't exist in window manager yet (e.g. was restored from recents).
649 // All we can do for now is update the bounds so it can be used when the task is
650 // added to window manager.
651 setBounds(bounds);
652 if (!inFreeformWindowingMode()) {
653 // re-restore the task so it can have the proper stack association.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800654 mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
Louis Changcdec0802019-11-11 11:45:07 +0800655 }
656 return true;
657 }
658
659 if (!canResizeToBounds(bounds)) {
660 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
661 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
662 }
663
664 // Do not move the task to another stack here.
665 // This method assumes that the task is already placed in the right stack.
666 // we do not mess with that decision and we only do the resize!
667
668 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeTask_" + mTaskId);
669
670 boolean updatedConfig = false;
671 mTmpConfig.setTo(getResolvedOverrideConfiguration());
672 if (setBounds(bounds) != BOUNDS_CHANGE_NONE) {
673 updatedConfig = !mTmpConfig.equals(getResolvedOverrideConfiguration());
674 }
675 // This variable holds information whether the configuration didn't change in a
676 // significant way and the activity was kept the way it was. If it's false, it means
677 // the activity had to be relaunched due to configuration change.
678 boolean kept = true;
679 if (updatedConfig) {
680 final ActivityRecord r = topRunningActivityLocked();
681 if (r != null && !deferResume) {
682 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
683 preserveWindow);
684 // Preserve other windows for resizing because if resizing happens when there
685 // is a dialog activity in the front, the activity that still shows some
686 // content to the user will become black and cause flickers. Note in most cases
687 // this won't cause tons of irrelevant windows being preserved because only
688 // activities in this task may experience a bounds change. Configs for other
689 // activities stay the same.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800690 mRootWindowContainer.ensureActivitiesVisible(r, 0, preserveWindow);
Louis Changcdec0802019-11-11 11:45:07 +0800691 if (!kept) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800692 mRootWindowContainer.resumeFocusedStacksTopActivities();
Louis Changcdec0802019-11-11 11:45:07 +0800693 }
694 }
695 }
696 resize(kept, forced);
697
698 saveLaunchingStateIfNeeded();
699
700 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
701 return kept;
702 } finally {
703 mAtmService.continueWindowLayout();
704 }
705 }
706
707 /** Convenience method to reparent a task to the top or bottom position of the stack. */
708 boolean reparent(ActivityStack preferredStack, boolean toTop,
709 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
710 String reason) {
711 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
712 true /* schedulePictureInPictureModeChange */, reason);
713 }
714
715 /**
716 * Convenience method to reparent a task to the top or bottom position of the stack, with
717 * an option to skip scheduling the picture-in-picture mode change.
718 */
719 boolean reparent(ActivityStack preferredStack, boolean toTop,
720 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
721 boolean schedulePictureInPictureModeChange, String reason) {
722 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
723 deferResume, schedulePictureInPictureModeChange, reason);
724 }
725
726 /** Convenience method to reparent a task to a specific position of the stack. */
727 boolean reparent(ActivityStack preferredStack, int position,
728 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
729 String reason) {
730 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
731 true /* schedulePictureInPictureModeChange */, reason);
732 }
733
734 /**
735 * Reparents the task into a preferred stack, creating it if necessary.
736 *
737 * @param preferredStack the target stack to move this task
738 * @param position the position to place this task in the new stack
739 * @param animate whether or not we should wait for the new window created as a part of the
740 * reparenting to be drawn and animated in
741 * @param moveStackMode whether or not to move the stack to the front always, only if it was
742 * previously focused & in front, or never
743 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
744 * have changed as a result of this reparenting
745 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
746 * change. Callers may set this to false if they are explicitly scheduling PiP mode
747 * changes themselves, like during the PiP animation
748 * @param reason the caller of this reparenting
749 * @return whether the task was reparented
750 */
751 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
752 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
753 boolean reparent(ActivityStack preferredStack, int position,
754 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
755 boolean schedulePictureInPictureModeChange, String reason) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800756 final ActivityStackSupervisor supervisor = mStackSupervisor;
757 final RootWindowContainer root = mRootWindowContainer;
Louis Changcdec0802019-11-11 11:45:07 +0800758 final WindowManagerService windowManager = mAtmService.mWindowManager;
759 final ActivityStack sourceStack = getStack();
760 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
761 position == MAX_VALUE);
762 if (toStack == sourceStack) {
763 return false;
764 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800765 if (!canBeLaunchedOnDisplay(toStack.getDisplayId())) {
Louis Changcdec0802019-11-11 11:45:07 +0800766 return false;
767 }
768
769 final boolean toTopOfStack = position == MAX_VALUE;
770 if (toTopOfStack && toStack.getResumedActivity() != null
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900771 && toStack.topRunningActivity() != null) {
Louis Changcdec0802019-11-11 11:45:07 +0800772 // Pause the resumed activity on the target stack while re-parenting task on top of it.
773 toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
774 null /* resuming */);
775 }
776
777 final int toStackWindowingMode = toStack.getWindowingMode();
Wale Ogunwale21e06482019-11-18 05:14:15 -0800778 final ActivityRecord topActivity = getTopNonFinishingActivity();
Louis Changcdec0802019-11-11 11:45:07 +0800779
780 final boolean mightReplaceWindow = topActivity != null
781 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
782 if (mightReplaceWindow) {
783 // We are about to relaunch the activity because its configuration changed due to
784 // being maximized, i.e. size change. The activity will first remove the old window
785 // and then add a new one. This call will tell window manager about this, so it can
786 // preserve the old window until the new one is drawn. This prevents having a gap
787 // between the removal and addition, in which no window is visible. We also want the
788 // entrance of the new window to be properly animated.
789 // Note here we always set the replacing window first, as the flags might be needed
790 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
791 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
792 }
793
794 mAtmService.deferWindowLayout();
795 boolean kept = true;
796 try {
797 final ActivityRecord r = topRunningActivityLocked();
Louis Changcdec0802019-11-11 11:45:07 +0800798 final boolean wasFocused = r != null && root.isTopDisplayFocusedStack(sourceStack)
799 && (topRunningActivityLocked() == r);
800 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
801 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
802
803 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
804 // Whenever we are moving the top activity from the front stack we want to make sure to
805 // move the stack to the front.
806 final boolean wasFront = r != null && sourceStack.isTopStackOnDisplay()
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900807 && (sourceStack.topRunningActivity() == r);
Louis Changcdec0802019-11-11 11:45:07 +0800808
809 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
810 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
811
812 reparent(toStack, position, moveStackToFront, reason);
813
814 if (schedulePictureInPictureModeChange) {
815 // Notify of picture-in-picture mode changes
816 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
817 }
818
819 // If the task had focus before (or we're requested to move focus), move focus to the
820 // new stack by moving the stack to the front.
821 if (r != null) {
822 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
823 wasPaused, reason);
824 }
825 if (!animate) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800826 mStackSupervisor.mNoAnimActivities.add(topActivity);
Louis Changcdec0802019-11-11 11:45:07 +0800827 }
828
829 // We might trigger a configuration change. Save the current task bounds for freezing.
830 // TODO: Should this call be moved inside the resize method in WM?
831 toStack.prepareFreezingTaskBounds();
832
833 // Make sure the task has the appropriate bounds/size for the stack it is in.
834 final boolean toStackSplitScreenPrimary =
835 toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
836 final Rect configBounds = getRequestedOverrideBounds();
837 if ((toStackWindowingMode == WINDOWING_MODE_FULLSCREEN
838 || toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
839 && !Objects.equals(configBounds, toStack.getRequestedOverrideBounds())) {
840 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
841 !mightReplaceWindow, deferResume);
842 } else if (toStackWindowingMode == WINDOWING_MODE_FREEFORM) {
843 Rect bounds = getLaunchBounds();
844 if (bounds == null) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800845 mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Louis Changcdec0802019-11-11 11:45:07 +0800846 bounds = configBounds;
847 }
848 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
849 } else if (toStackSplitScreenPrimary || toStackWindowingMode == WINDOWING_MODE_PINNED) {
850 if (toStackSplitScreenPrimary && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
851 // Move recents to front so it is not behind home stack when going into docked
852 // mode
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800853 mStackSupervisor.moveRecentsStackToFront(reason);
Louis Changcdec0802019-11-11 11:45:07 +0800854 }
855 kept = resize(toStack.getRequestedOverrideBounds(), RESIZE_MODE_SYSTEM,
856 !mightReplaceWindow, deferResume);
857 }
858 } finally {
859 mAtmService.continueWindowLayout();
860 }
861
862 if (mightReplaceWindow) {
863 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
864 // window), we need to clear the replace window settings. Otherwise, we schedule a
865 // timeout to remove the old window if the replacing window is not coming in time.
866 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
867 }
868
869 if (!deferResume) {
870 // The task might have already been running and its visibility needs to be synchronized
871 // with the visibility of the stack / windows.
872 root.ensureActivitiesVisible(null, 0, !mightReplaceWindow);
873 root.resumeFocusedStacksTopActivities();
874 }
875
876 // TODO: Handle incorrect request to move before the actual move, not after.
877 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
878 DEFAULT_DISPLAY, toStack);
879
880 return (preferredStack == toStack);
881 }
882
883 /**
884 * @return {@code true} if the windows of tasks being moved to the target stack from the
885 * source stack should be replaced, meaning that window manager will keep the old window
886 * around until the new is ready.
887 */
888 private static boolean replaceWindowsOnTaskMove(
889 int sourceWindowingMode, int targetWindowingMode) {
890 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
891 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
892 }
893
894 /**
895 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
896 */
897 TaskSnapshot getSnapshot(boolean reducedResolution, boolean restoreFromDisk) {
898
899 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
900 // synchronized between AM and WM.
901 return mAtmService.mWindowManager.getTaskSnapshot(mTaskId, mUserId, reducedResolution,
902 restoreFromDisk);
903 }
904
905 void touchActiveTime() {
906 lastActiveTime = SystemClock.elapsedRealtime();
907 }
908
909 long getInactiveDuration() {
910 return SystemClock.elapsedRealtime() - lastActiveTime;
911 }
912
913 /** Sets the original intent, and the calling uid and package. */
914 void setIntent(ActivityRecord r) {
915 mCallingUid = r.launchedFromUid;
916 mCallingPackage = r.launchedFromPackage;
917 setIntent(r.intent, r.info);
918 setLockTaskAuth(r);
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800919
920 final WindowContainer parent = getParent();
921 if (parent != null) {
922 final Task t = parent.asTask();
923 if (t != null) {
924 t.setIntent(r);
925 }
926 }
Louis Changcdec0802019-11-11 11:45:07 +0800927 }
928
929 /** Sets the original intent, _without_ updating the calling uid or package. */
930 private void setIntent(Intent _intent, ActivityInfo info) {
931 if (intent == null) {
932 mNeverRelinquishIdentity =
933 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
934 } else if (mNeverRelinquishIdentity) {
935 return;
936 }
937
938 affinity = info.taskAffinity;
939 if (intent == null) {
940 // If this task already has an intent associated with it, don't set the root
941 // affinity -- we don't want it changing after initially set, but the initially
942 // set value may be null.
943 rootAffinity = affinity;
944 }
945 effectiveUid = info.applicationInfo.uid;
946 stringName = null;
947
948 if (info.targetActivity == null) {
949 if (_intent != null) {
950 // If this Intent has a selector, we want to clear it for the
951 // recent task since it is not relevant if the user later wants
952 // to re-launch the app.
953 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
954 _intent = new Intent(_intent);
955 _intent.setSelector(null);
956 _intent.setSourceBounds(null);
957 }
958 }
959 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
960 intent = _intent;
961 realActivity = _intent != null ? _intent.getComponent() : null;
962 origActivity = null;
963 } else {
964 ComponentName targetComponent = new ComponentName(
965 info.packageName, info.targetActivity);
966 if (_intent != null) {
967 Intent targetIntent = new Intent(_intent);
968 targetIntent.setSelector(null);
969 targetIntent.setSourceBounds(null);
970 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
971 "Setting Intent of " + this + " to target " + targetIntent);
972 intent = targetIntent;
973 realActivity = targetComponent;
974 origActivity = _intent.getComponent();
975 } else {
976 intent = null;
977 realActivity = targetComponent;
978 origActivity = new ComponentName(info.packageName, info.name);
979 }
980 }
981
982 final int intentFlags = intent == null ? 0 : intent.getFlags();
983 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
984 // Once we are set to an Intent with this flag, we count this
985 // task as having a true root activity.
986 rootWasReset = true;
987 }
988 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
989 mUserSetupComplete = Settings.Secure.getIntForUser(
990 mAtmService.mContext.getContentResolver(), USER_SETUP_COMPLETE, 0, mUserId) != 0;
991 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
992 // If the activity itself has requested auto-remove, then just always do it.
993 autoRemoveRecents = true;
994 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
995 == FLAG_ACTIVITY_NEW_DOCUMENT) {
996 // If the caller has not asked for the document to be retained, then we may
997 // want to turn on auto-remove, depending on whether the target has set its
998 // own document launch mode.
999 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
1000 autoRemoveRecents = false;
1001 } else {
1002 autoRemoveRecents = true;
1003 }
1004 } else {
1005 autoRemoveRecents = false;
1006 }
1007 if (mResizeMode != info.resizeMode) {
1008 mResizeMode = info.resizeMode;
1009 updateTaskDescription();
1010 }
1011 mSupportsPictureInPicture = info.supportsPictureInPicture();
1012 }
1013
1014 /** Sets the original minimal width and height. */
1015 private void setMinDimensions(ActivityInfo info) {
1016 if (info != null && info.windowLayout != null) {
1017 mMinWidth = info.windowLayout.minWidth;
1018 mMinHeight = info.windowLayout.minHeight;
1019 } else {
1020 mMinWidth = INVALID_MIN_SIZE;
1021 mMinHeight = INVALID_MIN_SIZE;
1022 }
1023 }
1024
1025 /**
1026 * Return true if the input activity has the same intent filter as the intent this task
1027 * record is based on (normally the root activity intent).
1028 */
1029 boolean isSameIntentFilter(ActivityRecord r) {
1030 final Intent intent = new Intent(r.intent);
1031 // Make sure the component are the same if the input activity has the same real activity
1032 // as the one in the task because either one of them could be the alias activity.
1033 if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) {
1034 intent.setComponent(this.intent.getComponent());
1035 }
1036 return intent.filterEquals(this.intent);
1037 }
1038
1039 boolean returnsToHomeStack() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001040 if (inMultiWindowMode() || !hasChild()) return false;
1041 if (intent != null) {
1042 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
1043 return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
1044 }
1045 final Task bottomTask = getBottomMostTask();
1046 return bottomTask != this && bottomTask.returnsToHomeStack();
Louis Changcdec0802019-11-11 11:45:07 +08001047 }
1048
1049 void setPrevAffiliate(Task prevAffiliate) {
1050 mPrevAffiliate = prevAffiliate;
1051 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.mTaskId;
1052 }
1053
1054 void setNextAffiliate(Task nextAffiliate) {
1055 mNextAffiliate = nextAffiliate;
1056 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
1057 }
1058
Louis Changcdec0802019-11-11 11:45:07 +08001059 @Override
1060 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001061 final DisplayContent display = newParent != null
1062 ? ((WindowContainer) newParent).getDisplayContent() : null;
1063 final DisplayContent oldDisplay = oldParent != null
1064 ? ((WindowContainer) oldParent).getDisplayContent() : null;
1065
1066 mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
Louis Changcdec0802019-11-11 11:45:07 +08001067
Louis Chang8bda2322019-12-05 16:38:11 +08001068 if (oldParent != null && newParent == null) {
Garfield Tan8b096b22020-01-07 14:55:20 -08001069 cleanUpResourcesForDestroy(oldParent);
Louis Chang8bda2322019-12-05 16:38:11 +08001070 }
1071
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001072 if (display != null) {
1073 // TODO(NOW!): Chat with the erosky@ of this code to see if this really makes sense here...
1074 // Rotations are relative to the display. This means if there are 2 displays rotated
1075 // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
1076 // from one to the other could look like a rotation change. To prevent this
1077 // apparent rotation change (and corresponding bounds rotation), pretend like our
1078 // current rotation is already the same as the new display.
1079 // Note, if ActivityStack or related logic ever gets nested, this logic will need
1080 // to move to onConfigurationChanged.
1081 getConfiguration().windowConfiguration.setRotation(
1082 display.getWindowConfiguration().getRotation());
1083 }
1084
Louis Changcdec0802019-11-11 11:45:07 +08001085 super.onParentChanged(newParent, oldParent);
1086
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001087 // TODO(NOW): The check for null display content and setting it to null doesn't really
1088 // make sense here...
Louis Changcdec0802019-11-11 11:45:07 +08001089
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001090 // TODO(stack-merge): This is mostly taking care of the case where the stask is removing from
1091 // the display, so we should probably consolidate it there instead.
1092
1093 if (getParent() == null && mDisplayContent != null) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08001094 EventLogTags.writeWmStackRemoved(getRootTaskId());
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001095 mDisplayContent = null;
1096 mWmService.mWindowPlacerLocked.requestTraversal();
1097 }
1098
1099 if (oldParent != null) {
1100 final Task oldParentTask = ((WindowContainer) oldParent).asTask();
1101 if (oldParentTask != null) {
1102 final PooledConsumer c = PooledLambda.obtainConsumer(
1103 Task::cleanUpActivityReferences, oldParentTask,
1104 PooledLambda.__(ActivityRecord.class));
1105 forAllActivities(c);
1106 c.recycle();
1107 }
1108
1109 if (oldParent.inPinnedWindowingMode()
1110 && (newParent == null || !newParent.inPinnedWindowingMode())) {
Louis Changcdec0802019-11-11 11:45:07 +08001111 // Notify if a task from the pinned stack is being removed
1112 // (or moved depending on the mode).
1113 mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
1114 }
1115 }
1116
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001117 if (newParent != null) {
1118 final Task newParentTask = ((WindowContainer) newParent).asTask();
1119 if (newParentTask != null) {
1120 final ActivityRecord top = newParentTask.getTopNonFinishingActivity(
1121 false /* includeOverlays */);
1122 if (top != null && top.isState(RESUMED)) {
1123 newParentTask.setResumedActivity(top, "addedToTask");
1124 }
1125 }
Louis Changcdec0802019-11-11 11:45:07 +08001126
1127 // TODO: Ensure that this is actually necessary here
1128 // Notify the voice session if required
1129 if (voiceSession != null) {
1130 try {
1131 voiceSession.taskStarted(intent, mTaskId);
1132 } catch (RemoteException e) {
1133 }
1134 }
1135 }
1136
1137 // First time we are adding the task to the system.
1138 if (oldParent == null && newParent != null) {
1139
1140 // TODO: Super random place to be doing this, but aligns with what used to be done
1141 // before we unified Task level. Look into if this can be done in a better place.
1142 updateOverrideConfigurationFromLaunchBounds();
1143 }
1144
Louis Changcdec0802019-11-11 11:45:07 +08001145 // Update task bounds if needed.
1146 adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
1147
1148 if (getWindowConfiguration().windowsAreScaleable()) {
1149 // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
1150 // while a resize is pending.
1151 forceWindowsScaleable(true /* force */);
1152 } else {
1153 forceWindowsScaleable(false /* force */);
1154 }
1155
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001156 mRootWindowContainer.updateUIDsPresentOnDisplay();
1157 }
1158
1159 void cleanUpActivityReferences(ActivityRecord r) {
1160 final WindowContainer parent = getParent();
1161 if (parent != null && parent.asTask() != null) {
1162 parent.asTask().cleanUpActivityReferences(r);
1163 return;
1164 }
1165 r.removeTimeouts();
1166 mExitingActivities.remove(r);
1167
1168 if (mResumedActivity != null && mResumedActivity == r) {
1169 setResumedActivity(null, "cleanUpActivityReferences");
1170 }
1171 if (mPausingActivity != null && mPausingActivity == r) {
1172 mPausingActivity = null;
1173 }
1174 }
1175
1176 /** @return the currently resumed activity. */
1177 ActivityRecord getResumedActivity() {
1178 return mResumedActivity;
1179 }
1180
1181 void setResumedActivity(ActivityRecord r, String reason) {
1182 if (mResumedActivity == r) {
1183 return;
1184 }
1185
1186 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) Slog.d(TAG_STACK,
1187 "setResumedActivity stack:" + this + " + from: "
1188 + mResumedActivity + " to:" + r + " reason:" + reason);
1189 mResumedActivity = r;
1190 mStackSupervisor.updateTopResumedActivityIfNeeded();
Louis Changcdec0802019-11-11 11:45:07 +08001191 }
1192
1193 void updateTaskMovement(boolean toFront) {
1194 if (isPersistable) {
1195 mLastTimeMoved = System.currentTimeMillis();
1196 // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
1197 // recently will be most negative, tasks sent to the bottom before that will be less
1198 // negative. Similarly for recent tasks moved to the top which will be most positive.
1199 if (!toFront) {
1200 mLastTimeMoved *= -1;
1201 }
1202 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001203 mRootWindowContainer.invalidateTaskLayers();
Louis Changcdec0802019-11-11 11:45:07 +08001204 }
1205
Louis Changcdec0802019-11-11 11:45:07 +08001206 // Close up recents linked list.
1207 private void closeRecentsChain() {
1208 if (mPrevAffiliate != null) {
1209 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
1210 }
1211 if (mNextAffiliate != null) {
1212 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
1213 }
1214 setPrevAffiliate(null);
1215 setNextAffiliate(null);
1216 }
1217
1218 void removedFromRecents() {
1219 closeRecentsChain();
1220 if (inRecents) {
1221 inRecents = false;
1222 mAtmService.notifyTaskPersisterLocked(this, false);
1223 }
1224
1225 clearRootProcess();
1226
1227 mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
1228 mTaskId, mUserId);
1229 }
1230
1231 void setTaskToAffiliateWith(Task taskToAffiliateWith) {
1232 closeRecentsChain();
1233 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
1234 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
1235 // Find the end
1236 while (taskToAffiliateWith.mNextAffiliate != null) {
1237 final Task nextRecents = taskToAffiliateWith.mNextAffiliate;
1238 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1239 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1240 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1241 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1242 nextRecents.setPrevAffiliate(null);
1243 }
1244 taskToAffiliateWith.setNextAffiliate(null);
1245 break;
1246 }
1247 taskToAffiliateWith = nextRecents;
1248 }
1249 taskToAffiliateWith.setNextAffiliate(this);
1250 setPrevAffiliate(taskToAffiliateWith);
1251 setNextAffiliate(null);
1252 }
1253
1254 /** Returns the intent for the root activity for this task */
1255 Intent getBaseIntent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001256 if (intent != null) return intent;
1257 if (affinityIntent != null) return affinityIntent;
1258 // Probably a task that contains other tasks, so return the intent for the top task?
1259 final Task topTask = getTopMostTask();
1260 return topTask != null ? topTask.getBaseIntent() : null;
Louis Changcdec0802019-11-11 11:45:07 +08001261 }
1262
1263 /** Returns the first non-finishing activity from the bottom. */
1264 ActivityRecord getRootActivity() {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001265 // TODO: Figure out why we historical ignore relinquish identity for this case...
1266 return getRootActivity(true /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
1267 }
1268
1269 ActivityRecord getRootActivity(boolean setToBottomIfNone) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001270 return getRootActivity(false /*ignoreRelinquishIdentity*/, setToBottomIfNone);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001271 }
1272
1273 ActivityRecord getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001274 return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone);
Louis Changcdec0802019-11-11 11:45:07 +08001275 }
1276
Wale Ogunwale21e06482019-11-18 05:14:15 -08001277 ActivityRecord getTopNonFinishingActivity() {
1278 return getTopNonFinishingActivity(true /* includeOverlays */);
Louis Changcdec0802019-11-11 11:45:07 +08001279 }
1280
Wale Ogunwale21e06482019-11-18 05:14:15 -08001281 ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001282 return getTopActivity(false /*includeFinishing*/, includeOverlays);
Louis Changcdec0802019-11-11 11:45:07 +08001283 }
1284
1285 ActivityRecord topRunningActivityLocked() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001286 if (getParent() == null) {
1287 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001288 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001289 return getActivity(ActivityRecord::canBeTopRunning);
Louis Changcdec0802019-11-11 11:45:07 +08001290 }
1291
1292 /**
1293 * Return true if any activities in this task belongs to input uid.
1294 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001295 boolean isUidPresent(int uid) {
1296 final PooledPredicate p = PooledLambda.obtainPredicate(
1297 ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid);
1298 final boolean isUidPresent = getActivity(p) != null;
1299 p.recycle();
1300 return isUidPresent;
Louis Changcdec0802019-11-11 11:45:07 +08001301 }
1302
1303 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001304 if (getParent() == null) {
1305 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001306 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001307 return getActivity((r) -> r.mStartingWindowState == STARTING_WINDOW_SHOWN
1308 && r.canBeTopRunning());
Louis Changcdec0802019-11-11 11:45:07 +08001309 }
1310
1311 /**
1312 * Return the number of running activities, and the number of non-finishing/initializing
1313 * activities in the provided {@param reportOut} respectively.
1314 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001315 private void getNumRunningActivities(TaskActivitiesReport reportOut) {
Louis Changcdec0802019-11-11 11:45:07 +08001316 reportOut.reset();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001317 forAllActivities(reportOut);
Louis Changcdec0802019-11-11 11:45:07 +08001318 }
1319
1320 /**
1321 * Reorder the history stack so that the passed activity is brought to the front.
1322 */
1323 final void moveActivityToFrontLocked(ActivityRecord newTop) {
1324 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, "Removing and adding activity "
1325 + newTop + " to stack at top callers=" + Debug.getCallers(4));
1326
1327 positionChildAtTop(newTop);
1328 updateEffectiveIntent();
1329 }
1330
1331 @Override
1332 public int getActivityType() {
1333 final int applicationType = super.getActivityType();
1334 if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
1335 return applicationType;
1336 }
1337 return getChildAt(0).getActivityType();
1338 }
1339
1340 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001341 void addChild(WindowContainer child, int index) {
Louis Changcdec0802019-11-11 11:45:07 +08001342 // If this task had any child before we added this one.
1343 boolean hadChild = hasChild();
1344
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001345 index = getAdjustedChildPosition(child, index);
1346 super.addChild(child, index);
Louis Changcdec0802019-11-11 11:45:07 +08001347
1348 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001349
1350 // Make sure the list of display UID whitelists is updated
1351 // now that this record is in a new task.
1352 mRootWindowContainer.updateUIDsPresentOnDisplay();
1353
1354 final ActivityRecord r = child.asActivityRecord();
1355 if (r == null) return;
1356
Louis Changcdec0802019-11-11 11:45:07 +08001357 r.inHistory = true;
1358
Louis Changcdec0802019-11-11 11:45:07 +08001359 // Only set this based on the first activity
1360 if (!hadChild) {
1361 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1362 // Normally non-standard activity type for the activity record will be set when the
1363 // object is created, however we delay setting the standard application type until
1364 // this point so that the task can set the type for additional activities added in
1365 // the else condition below.
1366 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1367 }
1368 setActivityType(r.getActivityType());
1369 isPersistable = r.isPersistable();
1370 mCallingUid = r.launchedFromUid;
1371 mCallingPackage = r.launchedFromPackage;
1372 // Clamp to [1, max].
1373 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1374 ActivityTaskManager.getMaxAppRecentsLimitStatic());
1375 } else {
1376 // Otherwise make all added activities match this one.
1377 r.setActivityType(getActivityType());
1378 }
1379
1380 updateEffectiveIntent();
Louis Changcdec0802019-11-11 11:45:07 +08001381 }
1382
1383 void addChild(ActivityRecord r) {
1384 addChild(r, Integer.MAX_VALUE /* add on top */);
1385 }
1386
1387 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001388 void removeChild(WindowContainer child) {
1389 removeChild(child, "removeChild");
1390 }
1391
1392 void removeChild(WindowContainer r, String reason) {
Louis Changcdec0802019-11-11 11:45:07 +08001393 if (!mChildren.contains(r)) {
1394 Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
1395 return;
1396 }
1397
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001398 if (DEBUG_TASK_MOVEMENT) {
1399 Slog.d(TAG_WM, "removeChild: child=" + r + " reason=" + reason);
1400 }
Louis Changcdec0802019-11-11 11:45:07 +08001401 super.removeChild(r);
Louis Changcdec0802019-11-11 11:45:07 +08001402
1403 if (inPinnedWindowingMode()) {
1404 // We normally notify listeners of task stack changes on pause, however pinned stack
1405 // activities are normally in the paused state so no notification will be sent there
1406 // before the activity is removed. We send it here so instead.
1407 mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
1408 }
1409
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001410 final boolean isRootTask = isRootTask();
1411 if (isRootTask) {
1412 final DisplayContent display = getDisplayContent();
1413 if (display.isSingleTaskInstance()) {
1414 mAtmService.notifySingleTaskDisplayEmpty(display.mDisplayId);
1415 }
1416 display.mDisplayContent.setLayoutNeeded();
1417 }
1418
Louis Changcdec0802019-11-11 11:45:07 +08001419 if (hasChild()) {
1420 updateEffectiveIntent();
1421
1422 // The following block can be executed multiple times if there is more than one overlay.
1423 // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
1424 // of the task by id and exiting early if not found.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001425 if (onlyHasTaskOverlayActivities(true /*includeFinishing*/)) {
Louis Changcdec0802019-11-11 11:45:07 +08001426 // When destroying a task, tell the supervisor to remove it so that any activity it
1427 // has can be cleaned up correctly. This is currently the only place where we remove
1428 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
1429 // state into removeChild(), we just clear the task here before the other residual
1430 // work.
1431 // TODO: If the callers to removeChild() changes such that we have multiple places
1432 // where we are destroying the task, move this back into removeChild()
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001433 mStackSupervisor.removeTask(this, false /* killProcess */,
Louis Changcdec0802019-11-11 11:45:07 +08001434 !REMOVE_FROM_RECENTS, reason);
1435 }
1436 } else if (!mReuseTask) {
1437 // Remove entire task if it doesn't have any activity left and it isn't marked for reuse
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001438 if (!isRootTask) {
1439 getStack().removeChild(this, reason);
1440 }
Jeff Changd136e772019-11-05 20:33:52 +08001441 EventLogTags.writeWmTaskRemoved(mTaskId,
Louis Changcdec0802019-11-11 11:45:07 +08001442 "removeChild: last r=" + r + " in t=" + this);
1443 removeIfPossible();
1444 }
1445 }
1446
1447 /**
1448 * @return whether or not there are ONLY task overlay activities in the stack.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001449 * If {@param includeFinishing} is set, then don't ignore finishing activities in the
1450 * check. If there are no task overlay activities, this call returns false.
Louis Changcdec0802019-11-11 11:45:07 +08001451 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001452 boolean onlyHasTaskOverlayActivities(boolean includeFinishing) {
1453 if (getChildCount() == 0) {
1454 return false;
Louis Changcdec0802019-11-11 11:45:07 +08001455 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001456 if (includeFinishing) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001457 return getActivity((r) -> r.isTaskOverlay()) != null;
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001458 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001459 return getActivity((r) -> !r.finishing && r.isTaskOverlay()) != null;
Louis Changcdec0802019-11-11 11:45:07 +08001460 }
1461
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001462 private boolean autoRemoveFromRecents() {
Louis Changcdec0802019-11-11 11:45:07 +08001463 // We will automatically remove the task either if it has explicitly asked for
1464 // this, or it is empty and has never contained an activity that got shown to
1465 // the user.
1466 return autoRemoveRecents || (!hasChild() && !hasBeenVisible);
1467 }
1468
1469 /**
1470 * Completely remove all activities associated with an existing
1471 * task starting at a specified index.
1472 */
Wale Ogunwale21e06482019-11-18 05:14:15 -08001473 private void performClearTaskAtIndexLocked(String reason) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001474 // Broken down into to cases to avoid object create due to capturing mStack.
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001475 if (getStack() == null) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001476 forAllActivities((r) -> {
1477 if (r.finishing) return;
Louis Changcdec0802019-11-11 11:45:07 +08001478 // Task was restored from persistent storage.
1479 r.takeFromHistory();
1480 removeChild(r);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001481 });
1482 } else {
1483 forAllActivities((r) -> {
1484 if (r.finishing) return;
1485 // TODO: figure-out how to avoid object creation due to capture of reason variable.
1486 r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
1487 false /* oomAdj */);
1488 });
Louis Changcdec0802019-11-11 11:45:07 +08001489 }
1490 }
1491
1492 /**
1493 * Completely remove all activities associated with an existing task.
1494 */
1495 void performClearTaskLocked() {
1496 mReuseTask = true;
Wale Ogunwale21e06482019-11-18 05:14:15 -08001497 performClearTaskAtIndexLocked("clear-task-all");
Louis Changcdec0802019-11-11 11:45:07 +08001498 mReuseTask = false;
1499 }
1500
1501 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1502 mReuseTask = true;
1503 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1504 mReuseTask = false;
1505 return result;
1506 }
1507
1508 /**
1509 * Perform clear operation as requested by
1510 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1511 * stack to the given task, then look for
1512 * an instance of that activity in the stack and, if found, finish all
1513 * activities on top of it and return the instance.
1514 *
1515 * @param newR Description of the new activity being started.
1516 * @return Returns the old activity that should be continued to be used,
1517 * or {@code null} if none was found.
1518 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001519 private ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
1520 final ActivityRecord r = findActivityInHistory(newR.mActivityComponent);
1521 if (r == null) return null;
Louis Changcdec0802019-11-11 11:45:07 +08001522
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001523 final PooledFunction f = PooledLambda.obtainFunction(Task::finishActivityAbove,
1524 PooledLambda.__(ActivityRecord.class), r);
1525 forAllActivities(f);
1526 f.recycle();
Louis Changcdec0802019-11-11 11:45:07 +08001527
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001528 // Finally, if this is a normal launch mode (that is, not expecting onNewIntent()), then we
1529 // will finish the current instance of the activity so a new fresh one can be started.
1530 if (r.launchMode == ActivityInfo.LAUNCH_MULTIPLE
1531 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1532 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
1533 if (!r.finishing) {
1534 r.finishIfPossible("clear-task-top", false /* oomAdj */);
1535 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001536 }
1537 }
1538
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001539 return r;
1540 }
1541
1542 private static boolean finishActivityAbove(ActivityRecord r, ActivityRecord boundaryActivity) {
1543 // Stop operation once we reach the boundary activity.
1544 if (r == boundaryActivity) return true;
1545
1546 if (!r.finishing) {
1547 final ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
1548 if (opts != null) {
1549 // TODO: Why is this updating the boundary activity vs. the current activity???
1550 boundaryActivity.updateOptionsLocked(opts);
1551 }
1552 r.finishIfPossible("clear-task-stack", false /* oomAdj */);
1553 }
1554
1555 return false;
Louis Changcdec0802019-11-11 11:45:07 +08001556 }
1557
1558 void removeTaskActivitiesLocked(String reason) {
1559 // Just remove the entire task.
Wale Ogunwale21e06482019-11-18 05:14:15 -08001560 performClearTaskAtIndexLocked(reason);
Louis Changcdec0802019-11-11 11:45:07 +08001561 }
1562
1563 String lockTaskAuthToString() {
1564 switch (mLockTaskAuth) {
1565 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1566 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1567 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1568 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
1569 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
1570 default: return "unknown=" + mLockTaskAuth;
1571 }
1572 }
1573
1574 void setLockTaskAuth() {
1575 setLockTaskAuth(getRootActivity());
1576 }
1577
1578 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1579 if (r == null) {
1580 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1581 return;
1582 }
1583
1584 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
1585 final LockTaskController lockTaskController = mAtmService.getLockTaskController();
1586 switch (r.lockTaskLaunchMode) {
1587 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
1588 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
1589 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
1590 break;
1591
1592 case LOCK_TASK_LAUNCH_MODE_NEVER:
1593 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
1594 break;
1595
1596 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
1597 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
1598 break;
1599
1600 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
1601 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
1602 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
1603 break;
1604 }
1605 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this
1606 + " mLockTaskAuth=" + lockTaskAuthToString());
1607 }
1608
1609 @Override
1610 public boolean supportsSplitScreenWindowingMode() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001611 final Task topTask = getTopMostTask();
1612 return super.supportsSplitScreenWindowingMode()
1613 && (topTask == null || topTask.supportsSplitScreenWindowingModeInner());
1614 }
1615
1616 private boolean supportsSplitScreenWindowingModeInner() {
Louis Changcdec0802019-11-11 11:45:07 +08001617 // A task can not be docked even if it is considered resizeable because it only supports
1618 // picture-in-picture mode but has a non-resizeable resizeMode
1619 return super.supportsSplitScreenWindowingMode()
Louis Changcdec0802019-11-11 11:45:07 +08001620 && mAtmService.mSupportsSplitScreenMultiWindow
1621 && (mAtmService.mForceResizableActivities
1622 || (isResizeable(false /* checkSupportsPip */)
1623 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
1624 }
1625
1626 /**
1627 * Check whether this task can be launched on the specified display.
1628 *
1629 * @param displayId Target display id.
1630 * @return {@code true} if either it is the default display or this activity can be put on a
1631 * secondary display.
1632 */
1633 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001634 return mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Louis Changcdec0802019-11-11 11:45:07 +08001635 -1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
1636 }
1637
1638 /**
1639 * Check that a given bounds matches the application requested orientation.
1640 *
1641 * @param bounds The bounds to be tested.
1642 * @return True if the requested bounds are okay for a resizing request.
1643 */
1644 private boolean canResizeToBounds(Rect bounds) {
1645 if (bounds == null || !inFreeformWindowingMode()) {
1646 // Note: If not on the freeform workspace, we ignore the bounds.
1647 return true;
1648 }
1649 final boolean landscape = bounds.width() > bounds.height();
1650 final Rect configBounds = getRequestedOverrideBounds();
1651 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
1652 return configBounds.isEmpty()
1653 || landscape == (configBounds.width() > configBounds.height());
1654 }
1655 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1656 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1657 }
1658
1659 /**
1660 * @return {@code true} if the task is being cleared for the purposes of being reused.
1661 */
1662 boolean isClearingToReuseTask() {
1663 return mReuseTask;
1664 }
1665
1666 /**
1667 * Find the activity in the history stack within the given task. Returns
1668 * the index within the history at which it's found, or < 0 if not found.
1669 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001670 ActivityRecord findActivityInHistory(ComponentName component) {
1671 final PooledPredicate p = PooledLambda.obtainPredicate(Task::matchesActivityInHistory,
1672 PooledLambda.__(ActivityRecord.class), component);
1673 final ActivityRecord r = getActivity(p);
1674 p.recycle();
1675 return r;
1676 }
1677
1678 private static boolean matchesActivityInHistory(
1679 ActivityRecord r, ComponentName activityComponent) {
1680 return !r.finishing && r.mActivityComponent.equals(activityComponent);
Louis Changcdec0802019-11-11 11:45:07 +08001681 }
1682
1683 /** Updates the last task description values. */
1684 void updateTaskDescription() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001685 final ActivityRecord root = getRootActivity(true);
1686 if (root == null) return;
1687
1688 final TaskDescription taskDescription = new TaskDescription();
1689 final PooledFunction f = PooledLambda.obtainFunction(
1690 Task::setTaskDescriptionFromActivityAboveRoot,
1691 PooledLambda.__(ActivityRecord.class), root, taskDescription);
1692 forAllActivities(f);
1693 f.recycle();
1694 taskDescription.setResizeMode(mResizeMode);
1695 taskDescription.setMinWidth(mMinWidth);
1696 taskDescription.setMinHeight(mMinHeight);
1697 setTaskDescription(taskDescription);
1698 // Update the task affiliation color if we are the parent of the group
1699 if (mTaskId == mAffiliatedTaskId) {
1700 mAffiliatedTaskColor = taskDescription.getPrimaryColor();
Louis Changcdec0802019-11-11 11:45:07 +08001701 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001702 mAtmService.getTaskChangeNotificationController().notifyTaskDescriptionChanged(
1703 getTaskInfo());
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001704
1705 final WindowContainer parent = getParent();
1706 if (parent != null) {
1707 final Task t = parent.asTask();
1708 if (t != null) {
1709 t.updateTaskDescription();
1710 }
1711 }
Louis Changcdec0802019-11-11 11:45:07 +08001712 }
1713
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001714 private static boolean setTaskDescriptionFromActivityAboveRoot(
1715 ActivityRecord r, ActivityRecord root, TaskDescription td) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001716 if (!r.isTaskOverlay() && r.taskDescription != null) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001717 final TaskDescription atd = r.taskDescription;
1718 if (td.getLabel() == null) {
1719 td.setLabel(atd.getLabel());
Louis Changcdec0802019-11-11 11:45:07 +08001720 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001721 if (td.getIconResource() == 0) {
1722 td.setIcon(atd.getIconResource());
Louis Changcdec0802019-11-11 11:45:07 +08001723 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001724 if (td.getIconFilename() == null) {
1725 td.setIconFilename(atd.getIconFilename());
1726 }
1727 if (td.getPrimaryColor() == 0) {
1728 td.setPrimaryColor(atd.getPrimaryColor());
1729 }
1730 if (td.getBackgroundColor() == 0) {
1731 td.setBackgroundColor(atd.getBackgroundColor());
1732 }
1733 if (td.getStatusBarColor() == 0) {
1734 td.setStatusBarColor(atd.getStatusBarColor());
1735 td.setEnsureStatusBarContrastWhenTransparent(
1736 atd.getEnsureStatusBarContrastWhenTransparent());
1737 }
1738 if (td.getNavigationBarColor() == 0) {
1739 td.setNavigationBarColor(atd.getNavigationBarColor());
1740 td.setEnsureNavigationBarContrastWhenTransparent(
1741 atd.getEnsureNavigationBarContrastWhenTransparent());
1742 }
1743
Louis Changcdec0802019-11-11 11:45:07 +08001744 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001745
1746 // End search once we get to root.
1747 return r == root;
Louis Changcdec0802019-11-11 11:45:07 +08001748 }
1749
1750 // TODO (AM refactor): Invoke automatically when there is a change in children
1751 @VisibleForTesting
1752 void updateEffectiveIntent() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001753 final ActivityRecord root = getRootActivity(true /*setToBottomIfNone*/);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001754 if (root != null) {
1755 setIntent(root);
1756 // Update the task description when the activities change
1757 updateTaskDescription();
1758 }
Louis Changcdec0802019-11-11 11:45:07 +08001759 }
1760
1761 void adjustForMinimalTaskDimensions(Rect bounds, Rect previousBounds) {
Evan Rosky70213702019-11-05 10:26:24 -08001762 final Rect parentBounds = getParent() != null ? getParent().getBounds() : null;
1763 if (bounds == null
1764 || (bounds.isEmpty() && (parentBounds == null || parentBounds.isEmpty()))) {
Louis Changcdec0802019-11-11 11:45:07 +08001765 return;
1766 }
1767 int minWidth = mMinWidth;
1768 int minHeight = mMinHeight;
1769 // If the task has no requested minimal size, we'd like to enforce a minimal size
1770 // so that the user can not render the task too small to manipulate. We don't need
1771 // to do this for the pinned stack as the bounds are controlled by the system.
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001772 if (!inPinnedWindowingMode() && getStack() != null) {
1773 final int defaultMinSizeDp = mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001774 final DisplayContent display = getDisplayContent();
Louis Changcdec0802019-11-11 11:45:07 +08001775 final float density =
1776 (float) display.getConfiguration().densityDpi / DisplayMetrics.DENSITY_DEFAULT;
1777 final int defaultMinSize = (int) (defaultMinSizeDp * density);
1778
1779 if (minWidth == INVALID_MIN_SIZE) {
1780 minWidth = defaultMinSize;
1781 }
1782 if (minHeight == INVALID_MIN_SIZE) {
1783 minHeight = defaultMinSize;
1784 }
1785 }
Evan Rosky70213702019-11-05 10:26:24 -08001786 if (bounds.isEmpty()) {
1787 // If inheriting parent bounds, check if parent bounds adhere to minimum size. If they
1788 // do, we can just skip.
1789 if (parentBounds.width() >= minWidth && parentBounds.height() >= minHeight) {
1790 return;
1791 }
1792 bounds.set(parentBounds);
1793 }
Louis Changcdec0802019-11-11 11:45:07 +08001794 final boolean adjustWidth = minWidth > bounds.width();
1795 final boolean adjustHeight = minHeight > bounds.height();
1796 if (!(adjustWidth || adjustHeight)) {
1797 return;
1798 }
1799
1800 if (adjustWidth) {
1801 if (!previousBounds.isEmpty() && bounds.right == previousBounds.right) {
1802 bounds.left = bounds.right - minWidth;
1803 } else {
1804 // Either left bounds match, or neither match, or the previous bounds were
1805 // fullscreen and we default to keeping left.
1806 bounds.right = bounds.left + minWidth;
1807 }
1808 }
1809 if (adjustHeight) {
1810 if (!previousBounds.isEmpty() && bounds.bottom == previousBounds.bottom) {
1811 bounds.top = bounds.bottom - minHeight;
1812 } else {
1813 // Either top bounds match, or neither match, or the previous bounds were
1814 // fullscreen and we default to keeping top.
1815 bounds.bottom = bounds.top + minHeight;
1816 }
1817 }
1818 }
1819
1820 void setLastNonFullscreenBounds(Rect bounds) {
1821 if (mLastNonFullscreenBounds == null) {
1822 mLastNonFullscreenBounds = new Rect(bounds);
1823 } else {
1824 mLastNonFullscreenBounds.set(bounds);
1825 }
1826 }
1827
1828 /**
1829 * This should be called when an child activity changes state. This should only
1830 * be called from
1831 * {@link ActivityRecord#setState(ActivityState, String)} .
1832 * @param record The {@link ActivityRecord} whose state has changed.
1833 * @param state The new state.
1834 * @param reason The reason for the change.
1835 */
1836 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001837 final Task parentTask = getParent().asTask();
1838 if (parentTask != null) {
1839 parentTask.onActivityStateChanged(record, state, reason);
1840 return;
1841 }
Louis Changcdec0802019-11-11 11:45:07 +08001842
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001843 if (record == mResumedActivity && state != RESUMED) {
1844 setResumedActivity(null, reason + " - onActivityStateChanged");
1845 }
1846
1847 if (state == RESUMED) {
1848 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
1849 Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" + reason);
1850 }
1851 setResumedActivity(record, reason + " - onActivityStateChanged");
1852 if (record == mRootWindowContainer.getTopResumedActivity()) {
1853 mAtmService.setResumedActivityUncheckLocked(record, reason);
1854 }
1855 mStackSupervisor.mRecentTasks.add(record.getTask());
Louis Changcdec0802019-11-11 11:45:07 +08001856 }
1857 }
1858
1859 @Override
1860 public void onConfigurationChanged(Configuration newParentConfig) {
1861 // Check if the new configuration supports persistent bounds (eg. is Freeform) and if so
1862 // restore the last recorded non-fullscreen bounds.
1863 final boolean prevPersistTaskBounds = getWindowConfiguration().persistTaskBounds();
1864 final boolean nextPersistTaskBounds =
1865 getRequestedOverrideConfiguration().windowConfiguration.persistTaskBounds()
1866 || newParentConfig.windowConfiguration.persistTaskBounds();
1867 if (!prevPersistTaskBounds && nextPersistTaskBounds
1868 && mLastNonFullscreenBounds != null && !mLastNonFullscreenBounds.isEmpty()) {
1869 // Bypass onRequestedOverrideConfigurationChanged here to avoid infinite loop.
1870 getRequestedOverrideConfiguration().windowConfiguration
1871 .setBounds(mLastNonFullscreenBounds);
1872 }
1873
1874 final boolean wasInMultiWindowMode = inMultiWindowMode();
1875 super.onConfigurationChanged(newParentConfig);
1876 if (wasInMultiWindowMode != inMultiWindowMode()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001877 mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08001878 updateShadowsRadius(isFocused(), getPendingTransaction());
Louis Changcdec0802019-11-11 11:45:07 +08001879 }
1880
1881 // If the configuration supports persistent bounds (eg. Freeform), keep track of the
1882 // current (non-fullscreen) bounds for persistence.
1883 if (getWindowConfiguration().persistTaskBounds()) {
1884 final Rect currentBounds = getRequestedOverrideBounds();
1885 if (!currentBounds.isEmpty()) {
1886 setLastNonFullscreenBounds(currentBounds);
1887 }
1888 }
1889 // TODO: Should also take care of Pip mode changes here.
1890
1891 saveLaunchingStateIfNeeded();
1892 }
1893
1894 /**
1895 * Saves launching state if necessary so that we can launch the activity to its latest state.
1896 * It only saves state if this task has been shown to user and it's in fullscreen or freeform
1897 * mode on freeform displays.
1898 */
Garfield Tan8b096b22020-01-07 14:55:20 -08001899 private void saveLaunchingStateIfNeeded() {
1900 saveLaunchingStateIfNeeded(getDisplayContent());
1901 }
1902
1903 private void saveLaunchingStateIfNeeded(DisplayContent display) {
Louis Changcdec0802019-11-11 11:45:07 +08001904 if (!hasBeenVisible) {
1905 // Not ever visible to user.
1906 return;
1907 }
1908
1909 final int windowingMode = getWindowingMode();
1910 if (windowingMode != WINDOWING_MODE_FULLSCREEN
1911 && windowingMode != WINDOWING_MODE_FREEFORM) {
1912 return;
1913 }
1914
1915 // Don't persist state if display isn't in freeform mode. Then the task will be launched
1916 // back to its last state in a freeform display when it's launched in a freeform display
1917 // next time.
1918 if (getWindowConfiguration().getDisplayWindowingMode() != WINDOWING_MODE_FREEFORM) {
1919 return;
1920 }
1921
1922 // Saves the new state so that we can launch the activity at the same location.
Garfield Tan8b096b22020-01-07 14:55:20 -08001923 mStackSupervisor.mLaunchParamsPersister.saveTask(this, display);
Louis Changcdec0802019-11-11 11:45:07 +08001924 }
1925
1926 /**
1927 * Adjust bounds to stay within stack bounds.
1928 *
1929 * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
1930 * that keep them unchanged, but be contained within the stack bounds.
1931 *
1932 * @param bounds Bounds to be adjusted.
1933 * @param stackBounds Bounds within which the other bounds should remain.
1934 * @param overlapPxX The amount of px required to be visible in the X dimension.
1935 * @param overlapPxY The amount of px required to be visible in the Y dimension.
1936 */
1937 private static void fitWithinBounds(Rect bounds, Rect stackBounds, int overlapPxX,
1938 int overlapPxY) {
1939 if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
1940 return;
1941 }
1942
1943 // For each side of the parent (eg. left), check if the opposing side of the window (eg.
1944 // right) is at least overlap pixels away. If less, offset the window by that difference.
1945 int horizontalDiff = 0;
1946 // If window is smaller than overlap, use it's smallest dimension instead
1947 int overlapLR = Math.min(overlapPxX, bounds.width());
1948 if (bounds.right < (stackBounds.left + overlapLR)) {
1949 horizontalDiff = overlapLR - (bounds.right - stackBounds.left);
1950 } else if (bounds.left > (stackBounds.right - overlapLR)) {
1951 horizontalDiff = -(overlapLR - (stackBounds.right - bounds.left));
1952 }
1953 int verticalDiff = 0;
1954 int overlapTB = Math.min(overlapPxY, bounds.width());
1955 if (bounds.bottom < (stackBounds.top + overlapTB)) {
1956 verticalDiff = overlapTB - (bounds.bottom - stackBounds.top);
1957 } else if (bounds.top > (stackBounds.bottom - overlapTB)) {
1958 verticalDiff = -(overlapTB - (stackBounds.bottom - bounds.top));
1959 }
1960 bounds.offset(horizontalDiff, verticalDiff);
1961 }
1962
1963 /**
1964 * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
1965 * intersectBounds on a side, then the respective side will not be intersected.
1966 *
1967 * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
1968 * inset on that side is no-longer applicable. This scenario happens when a task's minimal
1969 * bounds are larger than the provided parent/display bounds.
1970 *
1971 * @param inOutBounds the bounds to intersect.
1972 * @param intersectBounds the bounds to intersect with.
1973 * @param intersectInsets insets to apply to intersectBounds before intersecting.
1974 */
1975 static void intersectWithInsetsIfFits(
1976 Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
1977 if (inOutBounds.right <= intersectBounds.right) {
1978 inOutBounds.right =
1979 Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
1980 }
1981 if (inOutBounds.bottom <= intersectBounds.bottom) {
1982 inOutBounds.bottom =
1983 Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
1984 }
1985 if (inOutBounds.left >= intersectBounds.left) {
1986 inOutBounds.left =
1987 Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
1988 }
1989 if (inOutBounds.top >= intersectBounds.top) {
1990 inOutBounds.top =
1991 Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
1992 }
1993 }
1994
1995 /**
1996 * Gets bounds with non-decor and stable insets applied respectively.
1997 *
1998 * If bounds overhangs the display, those edges will not get insets. See
1999 * {@link #intersectWithInsetsIfFits}
2000 *
2001 * @param outNonDecorBounds where to place bounds with non-decor insets applied.
2002 * @param outStableBounds where to place bounds with stable insets applied.
2003 * @param bounds the bounds to inset.
2004 */
2005 private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
2006 DisplayInfo displayInfo) {
2007 outNonDecorBounds.set(bounds);
2008 outStableBounds.set(bounds);
2009 if (getStack() == null || getStack().getDisplay() == null) {
2010 return;
2011 }
2012 DisplayPolicy policy = getStack().getDisplay().mDisplayContent.getDisplayPolicy();
2013 if (policy == null) {
2014 return;
2015 }
2016 mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
2017
2018 policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
2019 displayInfo.logicalHeight, displayInfo.displayCutout, mTmpInsets);
2020 intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);
2021
2022 policy.convertNonDecorInsetsToStableInsets(mTmpInsets, displayInfo.rotation);
2023 intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
2024 }
2025
2026 /**
2027 * Asks docked-divider controller for the smallestwidthdp given bounds.
2028 * @param bounds bounds to calculate smallestwidthdp for.
2029 */
2030 private int getSmallestScreenWidthDpForDockedBounds(Rect bounds) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002031 DisplayContent dc = getDisplayContent();
Louis Changcdec0802019-11-11 11:45:07 +08002032 if (dc != null) {
2033 return dc.getDockedDividerController().getSmallestWidthDpForBounds(bounds);
2034 }
2035 return Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED;
2036 }
2037
2038 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
2039 @NonNull Configuration parentConfig) {
2040 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* compatInsets */);
2041 }
2042
2043 /**
2044 * Calculates configuration values used by the client to get resources. This should be run
2045 * using app-facing bounds (bounds unmodified by animations or transient interactions).
2046 *
2047 * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
2048 * configuring an "inherit-bounds" window which means that all configuration settings would
2049 * just be inherited from the parent configuration.
2050 **/
2051 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
2052 @NonNull Configuration parentConfig,
2053 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
2054 int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
2055 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2056 windowingMode = parentConfig.windowConfiguration.getWindowingMode();
2057 }
2058
2059 float density = inOutConfig.densityDpi;
2060 if (density == Configuration.DENSITY_DPI_UNDEFINED) {
2061 density = parentConfig.densityDpi;
2062 }
2063 density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
2064
Evan Rosky70213702019-11-05 10:26:24 -08002065 final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds();
2066 if (resolvedBounds == null) {
2067 mTmpFullBounds.setEmpty();
2068 } else {
2069 mTmpFullBounds.set(resolvedBounds);
2070 }
2071 if (mTmpFullBounds.isEmpty()) {
2072 mTmpFullBounds.set(parentConfig.windowConfiguration.getBounds());
2073 }
2074
Louis Changcdec0802019-11-11 11:45:07 +08002075 Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2076 if (outAppBounds == null || outAppBounds.isEmpty()) {
Evan Rosky70213702019-11-05 10:26:24 -08002077 inOutConfig.windowConfiguration.setAppBounds(mTmpFullBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002078 outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2079 }
2080 // Non-null compatibility insets means the activity prefers to keep its original size, so
2081 // the out bounds doesn't need to be restricted by the parent.
2082 final boolean insideParentBounds = compatInsets == null;
2083 if (insideParentBounds && windowingMode != WINDOWING_MODE_FREEFORM) {
2084 final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
2085 if (parentAppBounds != null && !parentAppBounds.isEmpty()) {
2086 outAppBounds.intersect(parentAppBounds);
2087 }
2088 }
2089
2090 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
2091 || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
jaehoon.kim643293e2019-11-08 06:36:28 +09002092 if (insideParentBounds && WindowConfiguration.isFloating(windowingMode)) {
2093 mTmpNonDecorBounds.set(mTmpFullBounds);
2094 mTmpStableBounds.set(mTmpFullBounds);
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002095 } else if (insideParentBounds && getDisplayContent() != null) {
Louis Changcdec0802019-11-11 11:45:07 +08002096 final DisplayInfo di = new DisplayInfo();
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002097 getDisplayContent().mDisplay.getDisplayInfo(di);
Louis Changcdec0802019-11-11 11:45:07 +08002098
2099 // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
2100 // area, i.e. the screen area without the system bars.
2101 // The non decor inset are areas that could never be removed in Honeycomb. See
2102 // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
Evan Rosky70213702019-11-05 10:26:24 -08002103 calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di);
Louis Changcdec0802019-11-11 11:45:07 +08002104 } else {
2105 // Apply the given non-decor and stable insets to calculate the corresponding bounds
2106 // for screen size of configuration.
2107 int rotation = inOutConfig.windowConfiguration.getRotation();
2108 if (rotation == ROTATION_UNDEFINED) {
2109 rotation = parentConfig.windowConfiguration.getRotation();
2110 }
2111 if (rotation != ROTATION_UNDEFINED && compatInsets != null) {
Evan Rosky70213702019-11-05 10:26:24 -08002112 mTmpNonDecorBounds.set(mTmpFullBounds);
2113 mTmpStableBounds.set(mTmpFullBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002114 compatInsets.getDisplayBoundsByRotation(mTmpBounds, rotation);
2115 intersectWithInsetsIfFits(mTmpNonDecorBounds, mTmpBounds,
2116 compatInsets.mNonDecorInsets[rotation]);
2117 intersectWithInsetsIfFits(mTmpStableBounds, mTmpBounds,
2118 compatInsets.mStableInsets[rotation]);
2119 outAppBounds.set(mTmpNonDecorBounds);
2120 } else {
2121 // Set to app bounds because it excludes decor insets.
2122 mTmpNonDecorBounds.set(outAppBounds);
2123 mTmpStableBounds.set(outAppBounds);
2124 }
2125 }
2126
2127 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
2128 final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density);
2129 inOutConfig.screenWidthDp = insideParentBounds
2130 ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
2131 : overrideScreenWidthDp;
2132 }
2133 if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2134 final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
2135 inOutConfig.screenHeightDp = insideParentBounds
2136 ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
2137 : overrideScreenHeightDp;
2138 }
2139
2140 if (inOutConfig.smallestScreenWidthDp
2141 == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2142 if (WindowConfiguration.isFloating(windowingMode)) {
2143 // For floating tasks, calculate the smallest width from the bounds of the task
2144 inOutConfig.smallestScreenWidthDp = (int) (
Evan Rosky70213702019-11-05 10:26:24 -08002145 Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density);
Louis Changcdec0802019-11-11 11:45:07 +08002146 } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
2147 // Iterating across all screen orientations, and return the minimum of the task
2148 // width taking into account that the bounds might change because the snap
2149 // algorithm snaps to a different value
2150 inOutConfig.smallestScreenWidthDp =
Evan Rosky70213702019-11-05 10:26:24 -08002151 getSmallestScreenWidthDpForDockedBounds(mTmpFullBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002152 }
2153 // otherwise, it will just inherit
2154 }
2155 }
2156
2157 if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
2158 inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
2159 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
2160 }
2161 if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
2162 // For calculating screen layout, we need to use the non-decor inset screen area for the
2163 // calculation for compatibility reasons, i.e. screen area without system bars that
2164 // could never go away in Honeycomb.
2165 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
2166 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Louis Changcdec0802019-11-11 11:45:07 +08002167 // Reducing the screen layout starting from its parent config.
Riddle Hsuca928562019-11-22 01:04:14 +08002168 inOutConfig.screenLayout = computeScreenLayoutOverride(parentConfig.screenLayout,
2169 compatScreenWidthDp, compatScreenHeightDp);
Louis Changcdec0802019-11-11 11:45:07 +08002170 }
2171 }
2172
Riddle Hsuca928562019-11-22 01:04:14 +08002173 /** Computes LONG, SIZE and COMPAT parts of {@link Configuration#screenLayout}. */
2174 static int computeScreenLayoutOverride(int sourceScreenLayout, int screenWidthDp,
2175 int screenHeightDp) {
2176 sourceScreenLayout = sourceScreenLayout
2177 & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
2178 final int longSize = Math.max(screenWidthDp, screenHeightDp);
2179 final int shortSize = Math.min(screenWidthDp, screenHeightDp);
2180 return Configuration.reduceScreenLayout(sourceScreenLayout, longSize, shortSize);
2181 }
2182
Louis Changcdec0802019-11-11 11:45:07 +08002183 @Override
2184 void resolveOverrideConfiguration(Configuration newParentConfig) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002185 if (isRootTask()) {
2186 super.resolveOverrideConfiguration(newParentConfig);
2187 return;
2188 }
Louis Changcdec0802019-11-11 11:45:07 +08002189 mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
2190 super.resolveOverrideConfiguration(newParentConfig);
2191 int windowingMode =
2192 getRequestedOverrideConfiguration().windowConfiguration.getWindowingMode();
2193 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2194 windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
2195 }
2196 Rect outOverrideBounds =
2197 getResolvedOverrideConfiguration().windowConfiguration.getBounds();
2198
2199 if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
2200 computeFullscreenBounds(outOverrideBounds, null /* refActivity */,
2201 newParentConfig.windowConfiguration.getBounds(),
2202 newParentConfig.orientation);
2203 }
2204
Louis Changcdec0802019-11-11 11:45:07 +08002205 adjustForMinimalTaskDimensions(outOverrideBounds, mTmpBounds);
2206 if (windowingMode == WINDOWING_MODE_FREEFORM) {
2207 // by policy, make sure the window remains within parent somewhere
2208 final float density =
2209 ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;
2210 final Rect parentBounds =
2211 new Rect(newParentConfig.windowConfiguration.getBounds());
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002212 final DisplayContent display = getDisplayContent();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002213 if (display != null) {
Louis Changcdec0802019-11-11 11:45:07 +08002214 // If a freeform window moves below system bar, there is no way to move it again
2215 // by touch. Because its caption is covered by system bar. So we exclude them
2216 // from stack bounds. and then caption will be shown inside stable area.
2217 final Rect stableBounds = new Rect();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002218 display.getStableRect(stableBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002219 parentBounds.intersect(stableBounds);
2220 }
2221
2222 fitWithinBounds(outOverrideBounds, parentBounds,
2223 (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP),
2224 (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP));
2225
2226 // Prevent to overlap caption with stable insets.
2227 final int offsetTop = parentBounds.top - outOverrideBounds.top;
2228 if (offsetTop > 0) {
2229 outOverrideBounds.offset(0, offsetTop);
2230 }
2231 }
2232 computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
2233 }
2234
2235 /**
2236 * Compute bounds (letterbox or pillarbox) for
2237 * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the
2238 * orientation change and the requested orientation is different from the parent.
2239 */
2240 void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
2241 @NonNull Rect parentBounds, int parentOrientation) {
2242 // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
2243 outBounds.setEmpty();
2244 if (handlesOrientationChangeFromDescendant()) {
2245 return;
2246 }
2247 if (refActivity == null) {
2248 // Use the top activity as the reference of orientation. Don't include overlays because
2249 // it is usually not the actual content or just temporarily shown.
2250 // E.g. ForcedResizableInfoActivity.
Wale Ogunwale21e06482019-11-18 05:14:15 -08002251 refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
Louis Changcdec0802019-11-11 11:45:07 +08002252 }
2253
2254 // If the task or the reference activity requires a different orientation (either by
2255 // override or activityInfo), make it fit the available bounds by scaling down its bounds.
2256 final int overrideOrientation = getRequestedOverrideConfiguration().orientation;
2257 final int forcedOrientation =
2258 (overrideOrientation != ORIENTATION_UNDEFINED || refActivity == null)
2259 ? overrideOrientation : refActivity.getRequestedConfigurationOrientation();
2260 if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
2261 return;
2262 }
2263
2264 final int parentWidth = parentBounds.width();
2265 final int parentHeight = parentBounds.height();
2266 final float aspect = ((float) parentHeight) / parentWidth;
2267 if (forcedOrientation == ORIENTATION_LANDSCAPE) {
2268 final int height = (int) (parentWidth / aspect);
2269 final int top = parentBounds.centerY() - height / 2;
2270 outBounds.set(parentBounds.left, top, parentBounds.right, top + height);
2271 } else {
2272 final int width = (int) (parentHeight * aspect);
2273 final int left = parentBounds.centerX() - width / 2;
2274 outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
2275 }
2276 }
2277
2278 Rect updateOverrideConfigurationFromLaunchBounds() {
2279 final Rect bounds = getLaunchBounds();
2280 setBounds(bounds);
2281 if (bounds != null && !bounds.isEmpty()) {
2282 // TODO: Review if we actually want to do this - we are setting the launch bounds
2283 // directly here.
2284 bounds.set(getRequestedOverrideBounds());
2285 }
2286 return bounds;
2287 }
2288
2289 /** Updates the task's bounds and override configuration to match what is expected for the
2290 * input stack. */
2291 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002292 final ActivityStack stack = getStack();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002293
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002294 if (stack != null && stack == inStack) {
Louis Changcdec0802019-11-11 11:45:07 +08002295 return;
2296 }
2297
2298 if (inStack.inFreeformWindowingMode()) {
2299 if (!isResizeable()) {
2300 throw new IllegalArgumentException("Can not position non-resizeable task="
2301 + this + " in stack=" + inStack);
2302 }
2303 if (!matchParentBounds()) {
2304 return;
2305 }
2306 if (mLastNonFullscreenBounds != null) {
2307 setBounds(mLastNonFullscreenBounds);
2308 } else {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002309 mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Louis Changcdec0802019-11-11 11:45:07 +08002310 }
2311 } else {
2312 setBounds(inStack.getRequestedOverrideBounds());
2313 }
2314 }
2315
2316 /** Returns the bounds that should be used to launch this task. */
2317 Rect getLaunchBounds() {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002318 final ActivityStack stack = getStack();
2319 if (stack == null) {
Louis Changcdec0802019-11-11 11:45:07 +08002320 return null;
2321 }
2322
2323 final int windowingMode = getWindowingMode();
2324 if (!isActivityTypeStandardOrUndefined()
2325 || windowingMode == WINDOWING_MODE_FULLSCREEN
2326 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002327 return isResizeable() ? stack.getRequestedOverrideBounds() : null;
Louis Changcdec0802019-11-11 11:45:07 +08002328 } else if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002329 return stack.getRequestedOverrideBounds();
Louis Changcdec0802019-11-11 11:45:07 +08002330 }
2331 return mLastNonFullscreenBounds;
2332 }
2333
Louis Changcdec0802019-11-11 11:45:07 +08002334 void setRootProcess(WindowProcessController proc) {
2335 clearRootProcess();
2336 if (intent != null
2337 && (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
2338 mRootProcess = proc;
2339 mRootProcess.addRecentTask(this);
2340 }
2341 }
2342
2343 void clearRootProcess() {
2344 if (mRootProcess != null) {
2345 mRootProcess.removeRecentTask(this);
2346 mRootProcess = null;
2347 }
2348 }
2349
Tiger Huanged6794e2019-05-07 20:07:59 +08002350 @Override
Craig Mautnerc00204b2013-03-05 15:02:14 -08002351 DisplayContent getDisplayContent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002352 // TODO: Why aren't we just using our own display content vs. parent's???
2353 final ActivityStack stack = getStack();
2354 return stack != null && stack != this
2355 ? stack.getDisplayContent() : super.getDisplayContent();
Wale Ogunwale8577a052019-10-26 23:22:34 -07002356 }
2357
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002358 int getDisplayId() {
2359 final DisplayContent dc = getDisplayContent();
2360 return dc != null ? dc.mDisplayId : INVALID_DISPLAY;
2361 }
2362
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002363 // TODO: Migrate callers to getRootTask()
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002364 ActivityStack getStack() {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002365 return (ActivityStack) getRootTask();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002366 }
2367
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002368 /** @return Id of root task. */
2369 int getRootTaskId() {
2370 return getRootTask().mTaskId;
2371 }
2372
2373 Task getRootTask() {
2374 final WindowContainer parent = getParent();
2375 if (parent == null) return this;
2376
2377 final Task parentTask = parent.asTask();
2378 return parentTask == null ? this : parentTask.getRootTask();
2379 }
2380
2381 // TODO(task-merge): Figure out what's the right thing to do for places that used it.
2382 boolean isRootTask() {
2383 return getRootTask() == this;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002384 }
2385
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002386 int getDescendantTaskCount() {
2387 final int[] currentCount = {0};
2388 final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
2389 PooledLambda.__(Task.class), currentCount);
2390 forAllTasks(c, false /* traverseTopToBottom */, this);
2391 c.recycle();
2392 return currentCount[0];
2393 }
2394
2395 /** Calculate the minimum possible position for a task that can be shown to the user.
2396 * The minimum position will be above all other tasks that can't be shown.
2397 * @param minPosition The minimum position the caller is suggesting.
2398 * We will start adjusting up from here.
2399 * @param size The size of the current task list.
2400 */
2401 // TODO: Move user to their own window container.
2402 private int computeMinUserPosition(int minPosition, int size) {
2403 while (minPosition < size) {
2404 final WindowContainer child = mChildren.get(minPosition);
2405 final boolean canShow = child.showToCurrentUser();
2406 if (canShow) {
2407 break;
2408 }
2409 minPosition++;
2410 }
2411 return minPosition;
2412 }
2413
2414 /** Calculate the maximum possible position for a task that can't be shown to the user.
2415 * The maximum position will be below all other tasks that can be shown.
2416 * @param maxPosition The maximum position the caller is suggesting.
2417 * We will start adjusting down from here.
2418 */
2419 // TODO: Move user to their own window container.
2420 private int computeMaxUserPosition(int maxPosition) {
2421 while (maxPosition > 0) {
2422 final WindowContainer child = mChildren.get(maxPosition);
2423 final boolean canShow = child.showToCurrentUser();
2424 if (!canShow) {
2425 break;
2426 }
2427 maxPosition--;
2428 }
2429 return maxPosition;
2430 }
2431
2432 private int getAdjustedChildPosition(WindowContainer wc, int suggestedPosition) {
2433 final boolean canShowChild = wc.showToCurrentUser();
2434
2435 final int size = mChildren.size();
2436
2437 // Figure-out min/max possible position depending on if child can show for current user.
2438 int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0;
2439 int maxPosition = (canShowChild) ? size : computeMaxUserPosition(size - 1);
2440
2441 // Factor in always-on-top children in max possible position.
2442 if (!wc.isAlwaysOnTop()) {
2443
2444 // We want to place all non-always-on-top containers below always-on-top ones.
2445 while (maxPosition > minPosition) {
2446 if (!mChildren.get(maxPosition - 1).isAlwaysOnTop()) break;
2447 --maxPosition;
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002448 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002449 }
2450
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002451 // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
2452 if (suggestedPosition == POSITION_BOTTOM && minPosition == 0) {
2453 return POSITION_BOTTOM;
2454 } else if (suggestedPosition == POSITION_TOP && maxPosition == (size - 1)) {
2455 return POSITION_TOP;
2456 }
2457 // Reset position based on minimum/maximum possible positions.
2458 return Math.min(Math.max(suggestedPosition, minPosition), maxPosition);
Craig Mautnerc00204b2013-03-05 15:02:14 -08002459 }
2460
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002461 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002462 void positionChildAt(int position, WindowContainer child, boolean includingParents) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002463 position = getAdjustedChildPosition(child, position);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002464 super.positionChildAt(position, child, includingParents);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002465
2466 // Log positioning.
2467 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "positionChildAt: child=" + child
2468 + " position=" + position + " parent=" + this);
2469
2470 final int toTop = position >= (mChildren.size() - 1) ? 1 : 0;
2471 final Task task = child.asTask();
2472 if (task != null) {
2473 EventLogTags.writeWmTaskMoved(task.mTaskId, toTop, position);
2474 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002475 }
2476
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002477 @VisibleForTesting
2478 boolean hasWindowsAlive() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002479 return getActivity(ActivityRecord::hasWindowsAlive) != null;
Chong Zhang7e8eeb72016-01-06 19:14:47 -08002480 }
2481
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002482 @VisibleForTesting
2483 boolean shouldDeferRemoval() {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02002484 if (mChildren.isEmpty()) {
2485 // No reason to defer removal of a Task that doesn't have any child.
2486 return false;
2487 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002488 return hasWindowsAlive() && getStack().isAnimating(TRANSITION | CHILDREN);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002489 }
2490
Wale Ogunwalef6192862016-09-10 13:42:30 -07002491 @Override
Andrii Kulian45a61fe2017-01-05 16:53:19 -08002492 void removeImmediately() {
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08002493 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
Jeff Changd136e772019-11-05 20:33:52 +08002494 EventLogTags.writeWmTaskRemoved(mTaskId, "removeTask");
Robert Carr8a2f9132019-11-11 15:03:15 -08002495
2496 // If applicable let the TaskOrganizer know the Task is vanishing.
2497 setTaskOrganizer(null);
2498
Andrii Kulian45a61fe2017-01-05 16:53:19 -08002499 super.removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -08002500 }
2501
Louis Changcdec0802019-11-11 11:45:07 +08002502 // TODO: Consolidate this with Task.reparent()
Louis Changdc077272019-11-12 16:52:56 +08002503 void reparent(ActivityStack stack, int position, boolean moveParents, String reason) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -08002504 if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002505 + " from stack=" + getStack());
Louis Chang074cdf22019-12-13 13:15:13 +08002506 EventLogTags.writeWmTaskRemoved(mTaskId, "reParentTask:" + reason);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002507
2508 reparent(stack, position);
2509
Louis Changcdec0802019-11-11 11:45:07 +08002510 stack.positionChildAt(position, this, moveParents);
Andrii Kulian7cd7c2d2017-01-18 12:14:37 -08002511
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002512 // If we are moving from the fullscreen stack to the pinned stack then we want to preserve
2513 // our insets so that there will not be a jump in the area covered by system decorations.
2514 // We rely on the pinned animation to later unset this value.
2515 mPreserveNonFloatingState = stack.inPinnedWindowingMode();
Wale Ogunwale53a29a92015-02-23 15:42:52 -08002516 }
2517
Bryce Leef3c6a472017-11-14 14:53:06 -08002518 public int setBounds(Rect bounds, boolean forceResize) {
2519 final int boundsChanged = setBounds(bounds);
2520
2521 if (forceResize && (boundsChanged & BOUNDS_CHANGE_SIZE) != BOUNDS_CHANGE_SIZE) {
2522 onResize();
2523 return BOUNDS_CHANGE_SIZE | boundsChanged;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002524 }
Wale Ogunwale68278562017-09-23 17:13:55 -07002525
Bryce Leef3c6a472017-11-14 14:53:06 -08002526 return boundsChanged;
2527 }
2528
2529 /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
2530 @Override
2531 public int setBounds(Rect bounds) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002532 int rotation = Surface.ROTATION_0;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002533 final DisplayContent displayContent = getStack() != null
2534 ? getStack().getDisplayContent() : null;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002535 if (displayContent != null) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002536 rotation = displayContent.getDisplayInfo().rotation;
Wale Ogunwale2cc92f52015-09-09 13:12:10 -07002537 }
2538
Bryce Leef3c6a472017-11-14 14:53:06 -08002539 final int boundsChange = super.setBounds(bounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002540 mRotation = rotation;
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002541 updateSurfacePosition();
Wale Ogunwale2cc92f52015-09-09 13:12:10 -07002542 return boundsChange;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002543 }
2544
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08002545 private void updateSurfaceCrop() {
2546 // Only update the crop if we are drawing shadows on the task.
2547 if (mSurfaceControl == null || !mWmService.mRenderShadowsInCompositor) {
2548 return;
2549 }
2550
2551 if (inSplitScreenWindowingMode()) {
2552 // inherit crop from parent
2553 mTmpRect.setEmpty();
2554 } else {
2555 getBounds(mTmpRect);
2556 }
2557
2558 mTmpRect.offsetTo(0, 0);
2559 if (mLastSurfaceCrop.equals(mTmpRect)) {
2560 return;
2561 }
2562
2563 getPendingTransaction().setWindowCrop(mSurfaceControl, mTmpRect);
2564 mLastSurfaceCrop.set(mTmpRect);
2565 }
2566
Garfield Tan90b04282018-12-11 14:04:42 -08002567 @Override
2568 public boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
2569 ConfigurationContainer requestingContainer) {
2570 if (super.onDescendantOrientationChanged(freezeDisplayToken, requestingContainer)) {
2571 return true;
2572 }
2573
2574 // No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
2575 // it if possible.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002576 if (getParent() != null) {
2577 onConfigurationChanged(getParent().getConfiguration());
Garfield Tan90b04282018-12-11 14:04:42 -08002578 return true;
2579 }
2580 return false;
2581 }
2582
Yunfan Chen0e7aff92018-12-05 16:35:32 -08002583 void resize(boolean relayout, boolean forced) {
2584 if (setBounds(getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE && relayout) {
2585 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
2586 }
2587 }
2588
Louis Chang7501e332018-08-20 13:08:39 +08002589 @Override
2590 void onDisplayChanged(DisplayContent dc) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002591 final boolean isRootTask = isRootTask();
2592 if (!isRootTask) {
2593 adjustBoundsForDisplayChangeIfNeeded(dc);
2594 }
Louis Chang7501e332018-08-20 13:08:39 +08002595 super.onDisplayChanged(dc);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002596 if (!isRootTask) {
2597 final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY;
2598 mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged(
2599 mTaskId, displayId);
2600 }
Louis Chang7501e332018-08-20 13:08:39 +08002601 }
2602
Jorim Jaggidc249c42015-12-15 14:57:31 -08002603 /**
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002604 * Displayed bounds are used to set where the task is drawn at any given time. This is
2605 * separate from its actual bounds so that the app doesn't see any meaningful configuration
2606 * changes during transitionary periods.
Jorim Jaggidc249c42015-12-15 14:57:31 -08002607 */
Evan Roskyed6767f2018-10-26 17:21:06 -07002608 void setOverrideDisplayedBounds(Rect overrideDisplayedBounds) {
2609 if (overrideDisplayedBounds != null) {
2610 mOverrideDisplayedBounds.set(overrideDisplayedBounds);
Jorim Jaggidc249c42015-12-15 14:57:31 -08002611 } else {
Evan Roskyed6767f2018-10-26 17:21:06 -07002612 mOverrideDisplayedBounds.setEmpty();
Jorim Jaggidc249c42015-12-15 14:57:31 -08002613 }
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002614 updateSurfacePosition();
Jorim Jaggidc249c42015-12-15 14:57:31 -08002615 }
2616
2617 /**
Evan Roskyed6767f2018-10-26 17:21:06 -07002618 * Gets the bounds that override where the task is displayed. See
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002619 * {@link android.app.IActivityTaskManager#resizeDockedStack} why this is needed.
Jorim Jaggidc249c42015-12-15 14:57:31 -08002620 */
Evan Roskyed6767f2018-10-26 17:21:06 -07002621 Rect getOverrideDisplayedBounds() {
2622 return mOverrideDisplayedBounds;
Jorim Jaggidc249c42015-12-15 14:57:31 -08002623 }
2624
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002625 boolean isResizeable(boolean checkSupportsPip) {
2626 return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
2627 || (checkSupportsPip && mSupportsPictureInPicture));
Chong Zhangb15758a2015-11-17 12:12:03 -08002628 }
2629
2630 boolean isResizeable() {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002631 return isResizeable(true /* checkSupportsPip */);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002632 }
2633
skuhne@google.com322347b2016-12-02 12:54:03 -08002634 /**
2635 * Tests if the orientation should be preserved upon user interactive resizig operations.
2636
2637 * @return true if orientation should not get changed upon resizing operation.
2638 */
2639 boolean preserveOrientationOnResize() {
2640 return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
2641 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
2642 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
2643 }
2644
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002645 boolean cropWindowsToStackBounds() {
Wale Ogunwaledf241e92016-10-13 15:14:21 -07002646 return isResizeable();
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002647 }
2648
Jorim Jaggi0429f352015-12-22 16:29:16 +01002649 /**
2650 * Prepares the task bounds to be frozen with the current size. See
Garfield Tane8d84ab2019-10-11 09:49:40 -07002651 * {@link ActivityRecord#freezeBounds}.
Jorim Jaggi0429f352015-12-22 16:29:16 +01002652 */
2653 void prepareFreezingBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08002654 mPreparedFrozenBounds.set(getBounds());
Andrii Kulian441e4492016-09-29 15:25:00 -07002655 mPreparedFrozenMergedConfig.setTo(getConfiguration());
Jorim Jaggi0429f352015-12-22 16:29:16 +01002656 }
2657
Chong Zhang5117e272016-05-03 12:47:34 -07002658 /**
2659 * Align the task to the adjusted bounds.
2660 *
2661 * @param adjustedBounds Adjusted bounds to which the task should be aligned.
2662 * @param tempInsetBounds Insets bounds for the task.
2663 * @param alignBottom True if the task's bottom should be aligned to the adjusted
2664 * bounds's bottom; false if the task's top should be aligned
2665 * the adjusted bounds's top.
2666 */
Andrii Kulian441e4492016-09-29 15:25:00 -07002667 void alignToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds, boolean alignBottom) {
Evan Roskydfe3da72018-10-26 17:21:06 -07002668 if (!isResizeable() || EMPTY.equals(getRequestedOverrideConfiguration())) {
Chong Zhang5117e272016-05-03 12:47:34 -07002669 return;
2670 }
2671
2672 getBounds(mTmpRect2);
2673 if (alignBottom) {
2674 int offsetY = adjustedBounds.bottom - mTmpRect2.bottom;
2675 mTmpRect2.offset(0, offsetY);
2676 } else {
2677 mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
2678 }
Evan Roskyed6767f2018-10-26 17:21:06 -07002679 if (tempInsetBounds == null || tempInsetBounds.isEmpty()) {
2680 setOverrideDisplayedBounds(null);
2681 setBounds(mTmpRect2);
2682 } else {
2683 setOverrideDisplayedBounds(mTmpRect2);
2684 setBounds(tempInsetBounds);
2685 }
Chong Zhang5117e272016-05-03 12:47:34 -07002686 }
2687
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002688 /**
2689 * Gets the current overridden displayed bounds. These will be empty if the task is not
2690 * currently overriding where it is displayed.
2691 */
Evan Roskyed6767f2018-10-26 17:21:06 -07002692 @Override
2693 public Rect getDisplayedBounds() {
2694 if (mOverrideDisplayedBounds.isEmpty()) {
2695 return super.getDisplayedBounds();
2696 } else {
2697 return mOverrideDisplayedBounds;
2698 }
2699 }
2700
Issei Suzukiad287d02019-10-31 16:19:44 +01002701 @Override
2702 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2703 Rect outSurfaceInsets) {
2704 final WindowState windowState = getTopVisibleAppMainWindow();
2705 if (windowState != null) {
2706 windowState.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2707 } else {
2708 super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2709 }
2710 }
2711
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002712 /**
2713 * Calculate the maximum visible area of this task. If the task has only one app,
2714 * the result will be visible frame of that app. If the task has more than one apps,
2715 * we search from top down if the next app got different visible area.
2716 *
2717 * This effort is to handle the case where some task (eg. GMail composer) might pop up
2718 * a dialog that's different in size from the activity below, in which case we should
2719 * be dimming the entire task area behind the dialog.
2720 *
2721 * @param out Rect containing the max visible bounds.
2722 * @return true if the task has some visible app windows; false otherwise.
2723 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002724 private static void getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop) {
2725 // skip hidden (or about to hide) apps
2726 if (token.mIsExiting || !token.isClientVisible() || !token.mVisibleRequested) {
2727 return;
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002728 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002729 final WindowState win = token.findMainWindow();
2730 if (win == null) {
2731 return;
2732 }
2733 if (!foundTop[0]) {
2734 foundTop[0] = true;
2735 out.setEmpty();
2736 }
2737
2738 win.getMaxVisibleBounds(out);
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002739 }
2740
2741 /** Bounds of the task to be used for dimming, as well as touch related tests. */
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002742 void getDimBounds(Rect out) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002743 final DisplayContent displayContent = getStack().getDisplayContent();
Robert Carra86a6bf2016-04-08 17:34:16 -07002744 // It doesn't matter if we in particular are part of the resize, since we couldn't have
2745 // a DimLayer anyway if we weren't visible.
Wale Ogunwalef6192862016-09-10 13:42:30 -07002746 final boolean dockedResizing = displayContent != null
2747 && displayContent.mDividerControllerLocked.isResizing();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002748 if (inFreeformWindowingMode()) {
2749 boolean[] foundTop = { false };
2750 final PooledConsumer c = PooledLambda.obtainConsumer(Task::getMaxVisibleBounds,
2751 PooledLambda.__(ActivityRecord.class), out, foundTop);
Vishnu Nair4d7a6002020-01-23 14:34:40 -08002752 forAllActivities(c);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002753 c.recycle();
2754 if (foundTop[0]) {
2755 return;
2756 }
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002757 }
2758
Evan Rosky4fb1e912019-03-06 13:54:43 -08002759 if (!matchParentBounds()) {
2760 // When minimizing the docked stack when going home, we don't adjust the task bounds
2761 // so we need to intersect the task bounds with the stack bounds here.
2762 //
2763 // If we are Docked Resizing with snap points, the task bounds could be smaller than the
2764 // stack bounds and so we don't even want to use them. Even if the app should not be
2765 // resized the Dim should keep up with the divider.
2766 if (dockedResizing) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002767 getStack().getBounds(out);
Evan Rosky4fb1e912019-03-06 13:54:43 -08002768 } else {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002769 getStack().getBounds(mTmpRect);
Evan Rosky4fb1e912019-03-06 13:54:43 -08002770 mTmpRect.intersect(getBounds());
2771 out.set(mTmpRect);
2772 }
2773 } else {
2774 out.set(getBounds());
Wale Ogunwalef6192862016-09-10 13:42:30 -07002775 }
Evan Rosky4fb1e912019-03-06 13:54:43 -08002776 return;
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002777 }
2778
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01002779 void setDragResizing(boolean dragResizing, int dragResizeMode) {
Jorim Jaggic662d8e2016-02-05 16:54:54 -08002780 if (mDragResizing != dragResizing) {
chaviw8c9d1f52018-07-25 14:56:07 -07002781 // No need to check if the mode is allowed if it's leaving dragResize
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002782 if (dragResizing && !DragResizeMode.isModeAllowedForStack(getStack(), dragResizeMode)) {
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01002783 throw new IllegalArgumentException("Drag resize mode not allow for stack stackId="
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002784 + getRootTaskId() + " dragResizeMode=" + dragResizeMode);
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01002785 }
Jorim Jaggic662d8e2016-02-05 16:54:54 -08002786 mDragResizing = dragResizing;
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01002787 mDragResizeMode = dragResizeMode;
Jorim Jaggic662d8e2016-02-05 16:54:54 -08002788 resetDragResizingChangeReported();
2789 }
2790 }
2791
Chong Zhang3005e752015-09-18 18:46:28 -07002792 boolean isDragResizing() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07002793 return mDragResizing;
Chong Zhang3005e752015-09-18 18:46:28 -07002794 }
2795
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01002796 int getDragResizeMode() {
2797 return mDragResizeMode;
2798 }
2799
Yunfan Chen0e7aff92018-12-05 16:35:32 -08002800 /**
2801 * Puts this task into docked drag resizing mode. See {@link DragResizeMode}.
2802 *
2803 * @param resizing Whether to put the task into drag resize mode.
2804 */
2805 public void setTaskDockedResizing(boolean resizing) {
2806 setDragResizing(resizing, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
2807 }
2808
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002809 void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002810 if (displayContent == null) {
2811 return;
2812 }
Bryce Leef3c6a472017-11-14 14:53:06 -08002813 if (matchParentBounds()) {
Wale Ogunwale68278562017-09-23 17:13:55 -07002814 // TODO: Yeah...not sure if this works with WindowConfiguration, but shouldn't be a
2815 // problem once we move mBounds into WindowConfiguration.
Bryce Leef3c6a472017-11-14 14:53:06 -08002816 setBounds(null);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002817 return;
2818 }
Garfield Tandec96db2018-10-30 11:28:49 -07002819 final int displayId = displayContent.getDisplayId();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002820 final int newRotation = displayContent.getDisplayInfo().rotation;
Garfield Tandec96db2018-10-30 11:28:49 -07002821 if (displayId != mLastRotationDisplayId) {
2822 // This task is on a display that it wasn't on. There is no point to keep the relative
2823 // position if display rotations for old and new displays are different. Just keep these
2824 // values.
2825 mLastRotationDisplayId = displayId;
2826 mRotation = newRotation;
2827 return;
2828 }
2829
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002830 if (mRotation == newRotation) {
Garfield Tandec96db2018-10-30 11:28:49 -07002831 // Rotation didn't change. We don't need to adjust the bounds to keep the relative
2832 // position.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002833 return;
2834 }
2835
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08002836 // Device rotation changed.
Chong Zhang2e2c81a2016-07-15 11:28:17 -07002837 // - We don't want the task to move around on the screen when this happens, so update the
2838 // task bounds so it stays in the same place.
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08002839 // - Rotate the bounds and notify activity manager if the task can be resized independently
Chong Zhang2e2c81a2016-07-15 11:28:17 -07002840 // from its stack. The stack will take care of task rotation for the other case.
Bryce Leef3c6a472017-11-14 14:53:06 -08002841 mTmpRect2.set(getBounds());
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08002842
Wale Ogunwale3382ab12017-07-27 08:55:03 -07002843 if (!getWindowConfiguration().canResizeTask()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08002844 setBounds(mTmpRect2);
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08002845 return;
2846 }
2847
Wale Ogunwale94744212015-09-21 19:01:47 -07002848 displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
Bryce Leef3c6a472017-11-14 14:53:06 -08002849 if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002850 mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
Wale Ogunwale1ed0d892015-09-28 13:27:44 -07002851 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002852 }
2853
Wale Ogunwalef6192862016-09-10 13:42:30 -07002854 /** Cancels any running app transitions associated with the task. */
Winsonc28098f2015-10-30 14:50:19 -07002855 void cancelTaskWindowTransition() {
Wale Ogunwalef6192862016-09-10 13:42:30 -07002856 for (int i = mChildren.size() - 1; i >= 0; --i) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002857 mChildren.get(i).cancelAnimation();
Winsonc28098f2015-10-30 14:50:19 -07002858 }
2859 }
2860
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07002861 boolean showForAllUsers() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002862 if (mChildren.isEmpty()) return false;
2863 final ActivityRecord r = getTopNonFinishingActivity();
2864 return r != null && r.mShowForAllUsers;
Jorim Jaggiff71d202016-04-14 13:12:36 -07002865 }
2866
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08002867 @Override
2868 boolean showToCurrentUser() {
2869 return mForceShowForAllUsers || showForAllUsers() || mWmService.isCurrentProfile(mUserId);
2870 }
2871
2872 void setForceShowForAllUsers(boolean forceShowForAllUsers) {
2873 mForceShowForAllUsers = forceShowForAllUsers;
2874 }
2875
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002876 public boolean isAttached() {
2877 final DisplayContent display = getDisplayContent();
2878 return display != null && !display.isRemoved();
2879 }
2880
Robert Carr7e4c90e2017-02-15 19:52:38 -08002881 /**
2882 * When we are in a floating stack (Freeform, Pinned, ...) we calculate
2883 * insets differently. However if we are animating to the fullscreen stack
2884 * we need to begin calculating insets as if we were fullscreen, otherwise
2885 * we will have a jump at the end.
2886 */
Robert Carre6275582016-02-29 15:45:45 -08002887 boolean isFloating() {
Wale Ogunwale3382ab12017-07-27 08:55:03 -07002888 return getWindowConfiguration().tasksAreFloating()
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002889 && !getStack().isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState;
Robert Carre6275582016-02-29 15:45:45 -08002890 }
2891
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002892 /**
2893 * Returns true if the stack is translucent and can have other contents visible behind it if
2894 * needed. A stack is considered translucent if it don't contain a visible or
2895 * starting (about to be visible) activity that is fullscreen (opaque).
2896 * @param starting The currently starting activity or null if there is none.
2897 */
2898 @VisibleForTesting
2899 boolean isTranslucent(ActivityRecord starting) {
2900 if (!isAttached() || mForceHidden) {
2901 return true;
2902 }
2903 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isOpaqueActivity,
2904 PooledLambda.__(ActivityRecord.class), starting);
2905 final ActivityRecord opaque = getActivity(p);
2906 p.recycle();
2907 return opaque == null;
2908 }
2909
2910 private static boolean isOpaqueActivity(ActivityRecord r, ActivityRecord starting) {
2911 if (r.finishing) {
2912 // We don't factor in finishing activities when determining translucency since
2913 // they will be gone soon.
2914 return false;
2915 }
2916
2917 if (!r.visibleIgnoringKeyguard && r != starting) {
2918 // Also ignore invisible activities that are not the currently starting
2919 // activity (about to be visible).
2920 return false;
2921 }
2922
2923 if (r.occludesParent() || r.hasWallpaper) {
2924 // Stack isn't translucent if it has at least one fullscreen activity
2925 // that is visible.
2926 return true;
2927 }
2928 return false;
2929 }
2930
Winson Chungd41f71d2018-03-16 15:26:07 -07002931 @Override
2932 public SurfaceControl getAnimationLeashParent() {
Riddle Hsud8302832019-09-23 21:14:07 +08002933 if (WindowManagerService.sHierarchicalAnimations) {
Issei Suzuki71142152019-08-15 14:39:40 +02002934 return super.getAnimationLeashParent();
2935 }
Winson Chung732446a2018-09-19 13:15:17 -07002936 // Currently, only the recents animation will create animation leashes for tasks. In this
2937 // case, reparent the task to the home animation layer while it is being animated to allow
2938 // the home activity to reorder the app windows relative to its own.
2939 return getAppAnimationLayer(ANIMATION_LAYER_HOME);
Winson Chungd41f71d2018-03-16 15:26:07 -07002940 }
2941
lumark5341d1c2019-12-14 01:54:02 +08002942 @Override
2943 Rect getAnimationBounds(int appStackClipMode) {
2944 // TODO(b/131661052): we should remove appStackClipMode with hierarchical animations.
2945 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
2946 // Using the stack bounds here effectively applies the clipping before animation.
2947 return getStack().getBounds();
2948 }
2949 return super.getAnimationBounds(appStackClipMode);
2950 }
2951
lumark19a5d2e2019-10-11 16:19:30 +08002952 boolean shouldAnimate() {
Robert Carr8a2f9132019-11-11 15:03:15 -08002953 /**
2954 * Animations are handled by the TaskOrganizer implementation.
2955 */
2956 if (isControlledByTaskOrganizer()) {
2957 return false;
2958 }
lumark19a5d2e2019-10-11 16:19:30 +08002959 // Don't animate while the task runs recents animation but only if we are in the mode
2960 // where we cancel with deferred screenshot, which means that the controller has
2961 // transformed the task.
2962 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
2963 if (controller != null && controller.isAnimatingTask(this)
2964 && controller.shouldDeferCancelUntilNextTransition()) {
2965 return false;
2966 }
2967 return true;
2968 }
2969
Evan Rosky9020c072018-12-06 14:11:12 -08002970 @Override
2971 SurfaceControl.Builder makeSurface() {
2972 return super.makeSurface().setMetadata(METADATA_TASK_ID, mTaskId);
2973 }
2974
Winson Chungd41f71d2018-03-16 15:26:07 -07002975 boolean isTaskAnimating() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08002976 final RecentsAnimationController recentsAnim = mWmService.getRecentsAnimationController();
Winson Chungd41f71d2018-03-16 15:26:07 -07002977 if (recentsAnim != null) {
2978 if (recentsAnim.isAnimatingTask(this)) {
2979 return true;
2980 }
2981 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002982 return forAllTasks((t) -> { return t != this && t.isTaskAnimating(); });
Winson Chungd41f71d2018-03-16 15:26:07 -07002983 }
2984
lumark19a5d2e2019-10-11 16:19:30 +08002985 /**
2986 * @return {@code true} if changing app transition is running.
2987 */
2988 @Override
2989 boolean isChangingAppTransition() {
2990 final ActivityRecord activity = getTopVisibleActivity();
2991 return activity != null && getDisplayContent().mChangingApps.contains(activity);
2992 }
2993
2994 @Override
2995 RemoteAnimationTarget createRemoteAnimationTarget(
2996 RemoteAnimationController.RemoteAnimationRecord record) {
lumark5341d1c2019-12-14 01:54:02 +08002997 final ActivityRecord activity = getTopMostActivity();
lumark19a5d2e2019-10-11 16:19:30 +08002998 return activity != null ? activity.createRemoteAnimationTarget(record) : null;
2999 }
3000
Chong Zhangd8ceb852015-11-11 14:53:41 -08003001 WindowState getTopVisibleAppMainWindow() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003002 final ActivityRecord activity = getTopVisibleActivity();
3003 return activity != null ? activity.findMainWindow() : null;
Chong Zhang9184ec62015-09-24 12:32:21 -07003004 }
3005
Garfield Tane8d84ab2019-10-11 09:49:40 -07003006 ActivityRecord getTopFullscreenActivity() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003007 return getActivity((r) -> {
3008 final WindowState win = r.findMainWindow();
3009 return (win != null && win.mAttrs.isFullscreen());
3010 });
Jorim Jaggie6c6ecb2017-07-20 18:09:20 +02003011 }
3012
Garfield Tane8d84ab2019-10-11 09:49:40 -07003013 ActivityRecord getTopVisibleActivity() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003014 return getActivity((r) -> {
3015 // skip hidden (or about to hide) apps
3016 return !r.mIsExiting && r.isClientVisible() && r.mVisibleRequested;
3017 });
Chong Zhangbef461f2015-10-27 11:38:24 -07003018 }
3019
Wale Ogunwale3198da42019-10-10 14:45:03 +02003020 void positionChildAtTop(ActivityRecord child) {
3021 positionChildAt(child, POSITION_TOP);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003022 }
3023
Wale Ogunwale3198da42019-10-10 14:45:03 +02003024 void positionChildAt(ActivityRecord child, int position) {
3025 if (child == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003026 Slog.w(TAG_WM,
3027 "Attempted to position of non-existing app");
3028 return;
3029 }
3030
Wale Ogunwale3198da42019-10-10 14:45:03 +02003031 positionChildAt(position, child, false /* includeParents */);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003032 }
3033
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003034 void forceWindowsScaleable(boolean force) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003035 mWmService.openSurfaceTransaction();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003036 try {
Wale Ogunwalef6192862016-09-10 13:42:30 -07003037 for (int i = mChildren.size() - 1; i >= 0; i--) {
3038 mChildren.get(i).forceWindowsScaleableInTransaction(force);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003039 }
3040 } finally {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003041 mWmService.closeSurfaceTransaction("forceWindowsScaleable");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003042 }
3043 }
3044
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01003045 void setTaskDescription(TaskDescription taskDescription) {
3046 mTaskDescription = taskDescription;
3047 }
3048
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003049 void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003050 mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
3051 mTaskId, snapshot);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003052 }
3053
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01003054 TaskDescription getTaskDescription() {
3055 return mTaskDescription;
3056 }
3057
Wale Ogunwalef6192862016-09-10 13:42:30 -07003058 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07003059 boolean fillsParent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003060 return matchParentBounds();
3061 }
3062
3063 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom, Task excludedTask) {
3064 if (traverseTopToBottom) {
3065 super.forAllTasks(callback, traverseTopToBottom);
3066 if (excludedTask != this) {
3067 callback.accept(this);
3068 }
3069 } else {
3070 super.forAllTasks(callback, traverseTopToBottom);
3071 if (excludedTask != this) {
3072 callback.accept(this);
3073 }
3074 }
Wale Ogunwale51362492016-09-08 17:49:17 -07003075 }
3076
Jorim Jaggi329a5832017-01-05 18:57:12 +01003077 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003078 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003079 forAllTasks(callback, traverseTopToBottom, null /* excludedTask */);
Jorim Jaggi51304d72017-05-17 17:25:32 +02003080 }
3081
lumarkbc0032a2019-11-01 21:38:13 +08003082 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003083 boolean forAllTasks(Function<Task, Boolean> callback) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003084 if (super.forAllTasks(callback)) return true;
lumarkbc0032a2019-11-01 21:38:13 +08003085 return callback.apply(this);
3086 }
3087
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003088 @Override
3089 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003090 final Task t = super.getTask(callback, traverseTopToBottom);
3091 if (t != null) return t;
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003092 return callback.test(this) ? this : null;
3093 }
3094
Jorim Jaggi50bf59c2018-03-09 17:29:48 +01003095 /**
3096 * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
3097 * flags. See {@link WindowState#canAffectSystemUiFlags()}.
3098 */
3099 void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) {
3100 mCanAffectSystemUiFlags = canAffectSystemUiFlags;
3101 }
3102
3103 /**
3104 * @see #setCanAffectSystemUiFlags
3105 */
3106 boolean canAffectSystemUiFlags() {
3107 return mCanAffectSystemUiFlags;
3108 }
3109
chaviw87ca63a2018-03-26 14:06:17 -07003110 void dontAnimateDimExit() {
3111 mDimmer.dontAnimateExit();
3112 }
3113
Wale Ogunwale9adfe572016-09-08 20:43:58 -07003114 String getName() {
Louis Changcdec0802019-11-11 11:45:07 +08003115 return "Task=" + mTaskId;
Wale Ogunwale9adfe572016-09-08 20:43:58 -07003116 }
3117
Robert Carr18f622f2017-05-08 11:20:43 -07003118 void clearPreserveNonFloatingState() {
3119 mPreserveNonFloatingState = false;
3120 }
3121
chaviw2fb06bc2018-01-19 17:09:15 -08003122 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07003123 Dimmer getDimmer() {
3124 return mDimmer;
3125 }
3126
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003127 void dim(float alpha) {
3128 mDimmer.dimAbove(getPendingTransaction(), alpha);
3129 scheduleAnimation();
3130 }
3131
3132 void stopDimming() {
3133 mDimmer.stopDim(getPendingTransaction());
3134 scheduleAnimation();
3135 }
3136
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003137 boolean isTaskForUser(int userId) {
3138 return mUserId == userId;
3139 }
3140
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07003141 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07003142 void prepareSurfaces() {
3143 mDimmer.resetDimStates();
3144 super.prepareSurfaces();
3145 getDimBounds(mTmpDimBoundsRect);
chaviwe07246a2017-12-12 16:18:29 -08003146
3147 // Bounds need to be relative, as the dim layer is a child.
HEO SEUNGe10f4192019-11-21 10:21:04 +09003148 if (inFreeformWindowingMode()) {
3149 getBounds(mTmpRect);
3150 mTmpDimBoundsRect.offsetTo(mTmpDimBoundsRect.left - mTmpRect.left,
3151 mTmpDimBoundsRect.top - mTmpRect.top);
3152 } else {
3153 mTmpDimBoundsRect.offsetTo(0, 0);
3154 }
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08003155
3156 updateSurfaceCrop();
3157
Robert Carrf59b8dd2017-10-02 18:58:36 -07003158 if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
3159 scheduleAnimation();
3160 }
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07003161 }
3162
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003163 // TODO(proto-merge): Remove once protos for TaskRecord and Task are merged.
Jeffrey Huangcb782852019-12-05 11:28:11 -08003164 void dumpDebugInnerTaskOnly(ProtoOutputStream proto, long fieldId,
Nataniel Borges023ecb52019-01-16 14:15:43 -08003165 @WindowTraceLogLevel int logLevel) {
3166 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3167 return;
3168 }
3169
Steven Timotiusaf03df62017-07-18 16:56:43 -07003170 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08003171 super.dumpDebug(proto, WINDOW_CONTAINER, logLevel);
Louis Changcdec0802019-11-11 11:45:07 +08003172 proto.write(TaskProto.ID, mTaskId);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003173 forAllActivities((r) -> {
Jeff Changacc340d2019-11-22 14:23:08 +08003174 r.dumpDebug(proto, ACTIVITY);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003175 });
Bryce Leef3c6a472017-11-14 14:53:06 -08003176 proto.write(FILLS_PARENT, matchParentBounds());
Jeffrey Huangcb782852019-12-05 11:28:11 -08003177 getBounds().dumpDebug(proto, TaskProto.BOUNDS);
3178 mOverrideDisplayedBounds.dumpDebug(proto, DISPLAYED_BOUNDS);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003179 if (mSurfaceControl != null) {
3180 proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth());
3181 proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
3182 }
Steven Timotiusaf03df62017-07-18 16:56:43 -07003183 proto.end(token);
3184 }
3185
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003186 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003187 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003188 super.dump(pw, prefix, dumpAll);
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003189 final String doublePrefix = prefix + " ";
3190
3191 pw.println(prefix + "taskId=" + mTaskId);
Bryce Leef3c6a472017-11-14 14:53:06 -08003192 pw.println(doublePrefix + "mBounds=" + getBounds().toShortString());
Wale Ogunwalef6192862016-09-10 13:42:30 -07003193 pw.println(doublePrefix + "appTokens=" + mChildren);
Evan Roskyed6767f2018-10-26 17:21:06 -07003194 pw.println(doublePrefix + "mDisplayedBounds=" + mOverrideDisplayedBounds.toShortString());
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003195
3196 final String triplePrefix = doublePrefix + " ";
Jorim Jaggi153dc9d2018-02-23 13:28:15 +01003197 final String quadruplePrefix = triplePrefix + " ";
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003198
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003199 int[] index = { 0 };
3200 forAllActivities((r) -> {
3201 pw.println(triplePrefix + "Activity #" + index[0]++ + " " + r);
3202 r.dump(pw, quadruplePrefix, dumpAll);
3203 });
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003204 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07003205
Louis Changcdec0802019-11-11 11:45:07 +08003206 /**
3207 * Fills in a {@link TaskInfo} with information from this task.
3208 * @param info the {@link TaskInfo} to fill in
3209 */
3210 void fillTaskInfo(TaskInfo info) {
3211 getNumRunningActivities(mReuseActivitiesReport);
3212 info.userId = mUserId;
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003213 info.stackId = getRootTaskId();
Louis Changcdec0802019-11-11 11:45:07 +08003214 info.taskId = mTaskId;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003215 info.displayId = getDisplayId();
Wale Ogunwale21e06482019-11-18 05:14:15 -08003216 info.isRunning = getTopNonFinishingActivity() != null;
Louis Changcdec0802019-11-11 11:45:07 +08003217 info.baseIntent = new Intent(getBaseIntent());
3218 info.baseActivity = mReuseActivitiesReport.base != null
3219 ? mReuseActivitiesReport.base.intent.getComponent()
3220 : null;
3221 info.topActivity = mReuseActivitiesReport.top != null
3222 ? mReuseActivitiesReport.top.mActivityComponent
3223 : null;
3224 info.origActivity = origActivity;
3225 info.realActivity = realActivity;
3226 info.numActivities = mReuseActivitiesReport.numActivities;
3227 info.lastActiveTime = lastActiveTime;
3228 info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
3229 info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
3230 info.resizeMode = mResizeMode;
3231 info.configuration.setTo(getConfiguration());
3232 }
3233
3234 /**
3235 * Returns a {@link TaskInfo} with information from this task.
3236 */
3237 ActivityManager.RunningTaskInfo getTaskInfo() {
3238 ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
3239 fillTaskInfo(info);
3240 return info;
3241 }
3242
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003243 boolean isTaskId(int taskId) {
3244 return mTaskId == taskId;
3245 }
3246
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003247 @Override
3248 Task asTask() {
3249 // I'm a task!
3250 return this;
3251 }
3252
3253 // TODO(task-merge): Figure-out how this should work with hierarchy tasks.
3254 boolean shouldBeVisible(ActivityRecord starting) {
3255 return true;
3256 }
3257
Louis Changcdec0802019-11-11 11:45:07 +08003258 void dump(PrintWriter pw, String prefix) {
3259 pw.print(prefix); pw.print("userId="); pw.print(mUserId);
3260 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
3261 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
3262 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
3263 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
3264 if (affinity != null || rootAffinity != null) {
3265 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
3266 if (affinity == null || !affinity.equals(rootAffinity)) {
3267 pw.print(" root="); pw.println(rootAffinity);
3268 } else {
3269 pw.println();
3270 }
3271 }
3272 if (voiceSession != null || voiceInteractor != null) {
3273 pw.print(prefix); pw.print("VOICE: session=0x");
3274 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
3275 pw.print(" interactor=0x");
3276 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
3277 }
3278 if (intent != null) {
3279 StringBuilder sb = new StringBuilder(128);
3280 sb.append(prefix); sb.append("intent={");
3281 intent.toShortString(sb, false, true, false, false);
3282 sb.append('}');
3283 pw.println(sb.toString());
3284 }
3285 if (affinityIntent != null) {
3286 StringBuilder sb = new StringBuilder(128);
3287 sb.append(prefix); sb.append("affinityIntent={");
3288 affinityIntent.toShortString(sb, false, true, false, false);
3289 sb.append('}');
3290 pw.println(sb.toString());
3291 }
3292 if (origActivity != null) {
3293 pw.print(prefix); pw.print("origActivity=");
3294 pw.println(origActivity.flattenToShortString());
3295 }
3296 if (realActivity != null) {
3297 pw.print(prefix); pw.print("mActivityComponent=");
3298 pw.println(realActivity.flattenToShortString());
3299 }
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08003300 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard()) {
Louis Changcdec0802019-11-11 11:45:07 +08003301 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
3302 pw.print(" isPersistable="); pw.print(isPersistable);
Louis Changcdec0802019-11-11 11:45:07 +08003303 pw.print(" activityType="); pw.println(getActivityType());
3304 }
3305 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
3306 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
3307 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
3308 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
3309 pw.print(" mReuseTask="); pw.print(mReuseTask);
3310 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
3311 }
3312 if (mAffiliatedTaskId != mTaskId || mPrevAffiliateTaskId != INVALID_TASK_ID
3313 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
3314 || mNextAffiliate != null) {
3315 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
3316 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
3317 pw.print(" (");
3318 if (mPrevAffiliate == null) {
3319 pw.print("null");
3320 } else {
3321 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
3322 }
3323 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
3324 pw.print(" (");
3325 if (mNextAffiliate == null) {
3326 pw.print("null");
3327 } else {
3328 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
3329 }
3330 pw.println(")");
3331 }
3332 pw.print(prefix); pw.print("Activities="); pw.println(mChildren);
3333 if (!askedCompatMode || !inRecents || !isAvailable) {
3334 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
3335 pw.print(" inRecents="); pw.print(inRecents);
3336 pw.print(" isAvailable="); pw.println(isAvailable);
3337 }
3338 if (lastDescription != null) {
3339 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
3340 }
3341 if (mRootProcess != null) {
3342 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
3343 }
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003344 pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId());
Louis Changcdec0802019-11-11 11:45:07 +08003345 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
3346 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
3347 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
3348 pw.print(" isResizeable=" + isResizeable());
3349 pw.print(" lastActiveTime=" + lastActiveTime);
3350 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
3351 }
3352
3353 @Override
3354 public String toString() {
3355 StringBuilder sb = new StringBuilder(128);
3356 if (stringName != null) {
3357 sb.append(stringName);
3358 sb.append(" U=");
3359 sb.append(mUserId);
3360 sb.append(" StackId=");
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003361 sb.append(getRootTaskId());
Louis Changcdec0802019-11-11 11:45:07 +08003362 sb.append(" sz=");
3363 sb.append(getChildCount());
3364 sb.append('}');
3365 return sb.toString();
3366 }
3367 sb.append("Task{");
3368 sb.append(Integer.toHexString(System.identityHashCode(this)));
3369 sb.append(" #");
3370 sb.append(mTaskId);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003371 sb.append(" visible=" + shouldBeVisible(null /* starting */));
3372 sb.append(" type=" + activityTypeToString(getActivityType()));
3373 sb.append(" mode=" + windowingModeToString(getWindowingMode()));
3374 sb.append(" translucent=" + isTranslucent(null /* starting */));
Louis Changcdec0802019-11-11 11:45:07 +08003375 if (affinity != null) {
3376 sb.append(" A=");
3377 sb.append(affinity);
3378 } else if (intent != null) {
3379 sb.append(" I=");
3380 sb.append(intent.getComponent().flattenToShortString());
3381 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
3382 sb.append(" aI=");
3383 sb.append(affinityIntent.getComponent().flattenToShortString());
3384 } else {
3385 sb.append(" ??");
3386 }
3387 stringName = sb.toString();
3388 return toString();
3389 }
3390
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003391 void dumpDebugInner(ProtoOutputStream proto, long fieldId,
Louis Changcdec0802019-11-11 11:45:07 +08003392 @WindowTraceLogLevel int logLevel) {
3393 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
3394 return;
3395 }
3396
3397 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08003398 dumpDebugInnerTaskOnly(proto, TASK, logLevel);
Louis Changcdec0802019-11-11 11:45:07 +08003399 proto.write(com.android.server.am.TaskRecordProto.ID, mTaskId);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003400
3401 forAllActivities((r) -> {
Jeffrey Huangcb782852019-12-05 11:28:11 -08003402 r.dumpDebug(proto, ACTIVITIES);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003403 });
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003404 proto.write(STACK_ID, getRootTaskId());
Louis Changcdec0802019-11-11 11:45:07 +08003405 if (mLastNonFullscreenBounds != null) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08003406 mLastNonFullscreenBounds.dumpDebug(proto, LAST_NON_FULLSCREEN_BOUNDS);
Louis Changcdec0802019-11-11 11:45:07 +08003407 }
3408 if (realActivity != null) {
3409 proto.write(REAL_ACTIVITY, realActivity.flattenToShortString());
3410 }
3411 if (origActivity != null) {
3412 proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString());
3413 }
3414 proto.write(ACTIVITY_TYPE, getActivityType());
3415 proto.write(RESIZE_MODE, mResizeMode);
3416 // TODO: Remove, no longer needed with windowingMode.
3417 proto.write(FULLSCREEN, matchParentBounds());
3418
3419 if (!matchParentBounds()) {
3420 final Rect bounds = getRequestedOverrideBounds();
Jeffrey Huangcb782852019-12-05 11:28:11 -08003421 bounds.dumpDebug(proto, com.android.server.am.TaskRecordProto.BOUNDS);
Louis Changcdec0802019-11-11 11:45:07 +08003422 }
3423 proto.write(MIN_WIDTH, mMinWidth);
3424 proto.write(MIN_HEIGHT, mMinHeight);
3425 proto.end(token);
3426 }
3427
3428 /** @see #getNumRunningActivities(TaskActivitiesReport) */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003429 static class TaskActivitiesReport implements Consumer<ActivityRecord> {
Louis Changcdec0802019-11-11 11:45:07 +08003430 int numRunning;
3431 int numActivities;
3432 ActivityRecord top;
3433 ActivityRecord base;
3434
3435 void reset() {
3436 numRunning = numActivities = 0;
3437 top = base = null;
3438 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003439
3440 @Override
3441 public void accept(ActivityRecord r) {
3442 if (r.finishing) {
3443 return;
3444 }
3445
3446 base = r;
3447
3448 // Increment the total number of non-finishing activities
3449 numActivities++;
3450
3451 if (top == null || (top.isState(ActivityState.INITIALIZING))) {
3452 top = r;
3453 // Reset the number of running activities until we hit the first non-initializing
3454 // activity
3455 numRunning = 0;
3456 }
3457 if (r.attachedToProcess()) {
3458 // Increment the number of actually running activities
3459 numRunning++;
3460 }
3461 }
Louis Changcdec0802019-11-11 11:45:07 +08003462 }
3463
3464 /**
3465 * Saves this {@link Task} to XML using given serializer.
3466 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003467 void saveToXml(XmlSerializer out) throws Exception {
Louis Changcdec0802019-11-11 11:45:07 +08003468 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
3469
3470 out.attribute(null, ATTR_TASKID, String.valueOf(mTaskId));
3471 if (realActivity != null) {
3472 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
3473 }
3474 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
3475 if (origActivity != null) {
3476 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
3477 }
3478 // Write affinity, and root affinity if it is different from affinity.
3479 // We use the special string "@" for a null root affinity, so we can identify
3480 // later whether we were given a root affinity or should just make it the
3481 // same as the affinity.
3482 if (affinity != null) {
3483 out.attribute(null, ATTR_AFFINITY, affinity);
3484 if (!affinity.equals(rootAffinity)) {
3485 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3486 }
3487 } else if (rootAffinity != null) {
3488 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3489 }
3490 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
3491 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
3492 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
3493 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
3494 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
3495 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
3496 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
3497 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
3498 if (lastDescription != null) {
3499 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
3500 }
3501 if (getTaskDescription() != null) {
3502 getTaskDescription().saveToXml(out);
3503 }
3504 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
3505 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
3506 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
3507 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
3508 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
3509 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
3510 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
3511 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
3512 String.valueOf(mSupportsPictureInPicture));
3513 if (mLastNonFullscreenBounds != null) {
3514 out.attribute(
3515 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
3516 }
3517 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
3518 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
3519 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
3520
3521 if (affinityIntent != null) {
3522 out.startTag(null, TAG_AFFINITYINTENT);
3523 affinityIntent.saveToXml(out);
3524 out.endTag(null, TAG_AFFINITYINTENT);
3525 }
3526
3527 if (intent != null) {
3528 out.startTag(null, TAG_INTENT);
3529 intent.saveToXml(out);
3530 out.endTag(null, TAG_INTENT);
3531 }
3532
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003533 sTmpException = null;
3534 final PooledFunction f = PooledLambda.obtainFunction(Task::saveActivityToXml,
3535 PooledLambda.__(ActivityRecord.class), getBottomMostActivity(), out);
3536 forAllActivities(f);
3537 f.recycle();
3538 if (sTmpException != null) {
3539 throw sTmpException;
3540 }
3541 }
3542
3543 private static boolean saveActivityToXml(
3544 ActivityRecord r, ActivityRecord first, XmlSerializer out) {
3545 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable()
3546 || ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
3547 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT)
3548 && r != first) {
3549 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
3550 return true;
3551 }
3552 try {
Louis Changcdec0802019-11-11 11:45:07 +08003553 out.startTag(null, TAG_ACTIVITY);
3554 r.saveToXml(out);
3555 out.endTag(null, TAG_ACTIVITY);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003556 return false;
3557 } catch (Exception e) {
3558 sTmpException = e;
3559 return true;
Louis Changcdec0802019-11-11 11:45:07 +08003560 }
3561 }
3562
3563 @VisibleForTesting
3564 static TaskFactory getTaskFactory() {
3565 if (sTaskFactory == null) {
3566 setTaskFactory(new TaskFactory());
3567 }
3568 return sTaskFactory;
3569 }
3570
3571 static void setTaskFactory(TaskFactory factory) {
3572 sTaskFactory = factory;
3573 }
3574
3575 static Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
3576 Intent intent, IVoiceInteractionSession voiceSession,
3577 IVoiceInteractor voiceInteractor, ActivityStack stack) {
3578 return getTaskFactory().create(
3579 service, taskId, info, intent, voiceSession, voiceInteractor, stack);
3580 }
3581
3582 static Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
3583 Intent intent, TaskDescription taskDescription, ActivityStack stack) {
3584 return getTaskFactory().create(service, taskId, info, intent, taskDescription, stack);
3585 }
3586
3587 static Task restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
3588 throws IOException, XmlPullParserException {
3589 return getTaskFactory().restoreFromXml(in, stackSupervisor);
3590 }
3591
3592 /**
3593 * A factory class used to create {@link Task} or its subclass if any. This can be
3594 * specified when system boots by setting it with
3595 * {@link #setTaskFactory(TaskFactory)}.
3596 */
3597 static class TaskFactory {
3598
3599 Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
3600 Intent intent, IVoiceInteractionSession voiceSession,
3601 IVoiceInteractor voiceInteractor, ActivityStack stack) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003602 return new ActivityStack(service, taskId, info, intent, voiceSession, voiceInteractor,
Louis Changcdec0802019-11-11 11:45:07 +08003603 null /*taskDescription*/, stack);
3604 }
3605
3606 Task create(ActivityTaskManagerService service, int taskId, ActivityInfo info,
3607 Intent intent, TaskDescription taskDescription, ActivityStack stack) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003608 return new ActivityStack(service, taskId, info, intent, null /*voiceSession*/,
Louis Changcdec0802019-11-11 11:45:07 +08003609 null /*voiceInteractor*/, taskDescription, stack);
3610 }
3611
3612 /**
3613 * Should only be used when we're restoring {@link Task} from storage.
3614 */
3615 Task create(ActivityTaskManagerService service, int taskId, Intent intent,
3616 Intent affinityIntent, String affinity, String rootAffinity,
3617 ComponentName realActivity, ComponentName origActivity, boolean rootWasReset,
3618 boolean autoRemoveRecents, boolean askedCompatMode, int userId,
3619 int effectiveUid, String lastDescription,
3620 long lastTimeMoved, boolean neverRelinquishIdentity,
3621 TaskDescription lastTaskDescription, int taskAffiliation, int prevTaskId,
3622 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
3623 int resizeMode, boolean supportsPictureInPicture, boolean realActivitySuspended,
3624 boolean userSetupComplete, int minWidth, int minHeight, ActivityStack stack) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003625 return new ActivityStack(service, taskId, intent, affinityIntent, affinity,
Louis Changcdec0802019-11-11 11:45:07 +08003626 rootAffinity, realActivity, origActivity, rootWasReset, autoRemoveRecents,
3627 askedCompatMode, userId, effectiveUid, lastDescription,
3628 lastTimeMoved, neverRelinquishIdentity, lastTaskDescription, taskAffiliation,
3629 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
3630 resizeMode, supportsPictureInPicture, realActivitySuspended, userSetupComplete,
3631 minWidth, minHeight, null /*ActivityInfo*/, null /*_voiceSession*/,
3632 null /*_voiceInteractor*/, stack);
3633 }
3634
3635 Task restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
3636 throws IOException, XmlPullParserException {
3637 Intent intent = null;
3638 Intent affinityIntent = null;
3639 ArrayList<ActivityRecord> activities = new ArrayList<>();
3640 ComponentName realActivity = null;
3641 boolean realActivitySuspended = false;
3642 ComponentName origActivity = null;
3643 String affinity = null;
3644 String rootAffinity = null;
3645 boolean hasRootAffinity = false;
3646 boolean rootHasReset = false;
3647 boolean autoRemoveRecents = false;
3648 boolean askedCompatMode = false;
3649 int taskType = 0;
3650 int userId = 0;
3651 boolean userSetupComplete = true;
3652 int effectiveUid = -1;
3653 String lastDescription = null;
3654 long lastTimeOnTop = 0;
3655 boolean neverRelinquishIdentity = true;
3656 int taskId = INVALID_TASK_ID;
3657 final int outerDepth = in.getDepth();
3658 TaskDescription taskDescription = new TaskDescription();
3659 int taskAffiliation = INVALID_TASK_ID;
3660 int taskAffiliationColor = 0;
3661 int prevTaskId = INVALID_TASK_ID;
3662 int nextTaskId = INVALID_TASK_ID;
3663 int callingUid = -1;
3664 String callingPackage = "";
3665 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
3666 boolean supportsPictureInPicture = false;
3667 Rect lastNonFullscreenBounds = null;
3668 int minWidth = INVALID_MIN_SIZE;
3669 int minHeight = INVALID_MIN_SIZE;
3670 int persistTaskVersion = 0;
3671
3672 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
3673 final String attrName = in.getAttributeName(attrNdx);
3674 final String attrValue = in.getAttributeValue(attrNdx);
3675 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: attribute name="
3676 + attrName + " value=" + attrValue);
3677 switch (attrName) {
3678 case ATTR_TASKID:
3679 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
3680 break;
3681 case ATTR_REALACTIVITY:
3682 realActivity = ComponentName.unflattenFromString(attrValue);
3683 break;
3684 case ATTR_REALACTIVITY_SUSPENDED:
3685 realActivitySuspended = Boolean.valueOf(attrValue);
3686 break;
3687 case ATTR_ORIGACTIVITY:
3688 origActivity = ComponentName.unflattenFromString(attrValue);
3689 break;
3690 case ATTR_AFFINITY:
3691 affinity = attrValue;
3692 break;
3693 case ATTR_ROOT_AFFINITY:
3694 rootAffinity = attrValue;
3695 hasRootAffinity = true;
3696 break;
3697 case ATTR_ROOTHASRESET:
3698 rootHasReset = Boolean.parseBoolean(attrValue);
3699 break;
3700 case ATTR_AUTOREMOVERECENTS:
3701 autoRemoveRecents = Boolean.parseBoolean(attrValue);
3702 break;
3703 case ATTR_ASKEDCOMPATMODE:
3704 askedCompatMode = Boolean.parseBoolean(attrValue);
3705 break;
3706 case ATTR_USERID:
3707 userId = Integer.parseInt(attrValue);
3708 break;
3709 case ATTR_USER_SETUP_COMPLETE:
3710 userSetupComplete = Boolean.parseBoolean(attrValue);
3711 break;
3712 case ATTR_EFFECTIVE_UID:
3713 effectiveUid = Integer.parseInt(attrValue);
3714 break;
3715 case ATTR_TASKTYPE:
3716 taskType = Integer.parseInt(attrValue);
3717 break;
3718 case ATTR_LASTDESCRIPTION:
3719 lastDescription = attrValue;
3720 break;
3721 case ATTR_LASTTIMEMOVED:
3722 lastTimeOnTop = Long.parseLong(attrValue);
3723 break;
3724 case ATTR_NEVERRELINQUISH:
3725 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
3726 break;
3727 case ATTR_TASK_AFFILIATION:
3728 taskAffiliation = Integer.parseInt(attrValue);
3729 break;
3730 case ATTR_PREV_AFFILIATION:
3731 prevTaskId = Integer.parseInt(attrValue);
3732 break;
3733 case ATTR_NEXT_AFFILIATION:
3734 nextTaskId = Integer.parseInt(attrValue);
3735 break;
3736 case ATTR_TASK_AFFILIATION_COLOR:
3737 taskAffiliationColor = Integer.parseInt(attrValue);
3738 break;
3739 case ATTR_CALLING_UID:
3740 callingUid = Integer.parseInt(attrValue);
3741 break;
3742 case ATTR_CALLING_PACKAGE:
3743 callingPackage = attrValue;
3744 break;
3745 case ATTR_RESIZE_MODE:
3746 resizeMode = Integer.parseInt(attrValue);
3747 break;
3748 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
3749 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
3750 break;
3751 case ATTR_NON_FULLSCREEN_BOUNDS:
3752 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
3753 break;
3754 case ATTR_MIN_WIDTH:
3755 minWidth = Integer.parseInt(attrValue);
3756 break;
3757 case ATTR_MIN_HEIGHT:
3758 minHeight = Integer.parseInt(attrValue);
3759 break;
3760 case ATTR_PERSIST_TASK_VERSION:
3761 persistTaskVersion = Integer.parseInt(attrValue);
3762 break;
3763 default:
3764 if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
3765 taskDescription.restoreFromXml(attrName, attrValue);
3766 } else {
3767 Slog.w(TAG, "Task: Unknown attribute=" + attrName);
3768 }
3769 }
3770 }
3771
3772 int event;
3773 while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
3774 && (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
3775 if (event == XmlPullParser.START_TAG) {
3776 final String name = in.getName();
3777 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
3778 "Task: START_TAG name=" + name);
3779 if (TAG_AFFINITYINTENT.equals(name)) {
3780 affinityIntent = Intent.restoreFromXml(in);
3781 } else if (TAG_INTENT.equals(name)) {
3782 intent = Intent.restoreFromXml(in);
3783 } else if (TAG_ACTIVITY.equals(name)) {
3784 ActivityRecord activity =
3785 ActivityRecord.restoreFromXml(in, stackSupervisor);
3786 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: activity="
3787 + activity);
3788 if (activity != null) {
3789 activities.add(activity);
3790 }
3791 } else {
3792 handleUnknownTag(name, in);
3793 }
3794 }
3795 }
3796 if (!hasRootAffinity) {
3797 rootAffinity = affinity;
3798 } else if ("@".equals(rootAffinity)) {
3799 rootAffinity = null;
3800 }
3801 if (effectiveUid <= 0) {
3802 Intent checkIntent = intent != null ? intent : affinityIntent;
3803 effectiveUid = 0;
3804 if (checkIntent != null) {
3805 IPackageManager pm = AppGlobals.getPackageManager();
3806 try {
3807 ApplicationInfo ai = pm.getApplicationInfo(
3808 checkIntent.getComponent().getPackageName(),
3809 PackageManager.MATCH_UNINSTALLED_PACKAGES
3810 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
3811 if (ai != null) {
3812 effectiveUid = ai.uid;
3813 }
3814 } catch (RemoteException e) {
3815 }
3816 }
3817 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
3818 + ": effectiveUid=" + effectiveUid);
3819 }
3820
3821 if (persistTaskVersion < 1) {
3822 // We need to convert the resize mode of home activities saved before version one if
3823 // they are marked as RESIZE_MODE_RESIZEABLE to
3824 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
3825 // before version 1 and the system didn't resize home activities before then.
3826 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
3827 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
3828 }
3829 } else {
3830 // This activity has previously marked itself explicitly as both resizeable and
3831 // supporting picture-in-picture. Since there is no longer a requirement for
3832 // picture-in-picture activities to be resizeable, we can mark this simply as
3833 // resizeable and supporting picture-in-picture separately.
3834 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
3835 resizeMode = RESIZE_MODE_RESIZEABLE;
3836 supportsPictureInPicture = true;
3837 }
3838 }
3839
3840 final Task task = create(stackSupervisor.mService,
3841 taskId, intent, affinityIntent,
3842 affinity, rootAffinity, realActivity, origActivity, rootHasReset,
3843 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
3844 lastTimeOnTop, neverRelinquishIdentity, taskDescription,
3845 taskAffiliation, prevTaskId, nextTaskId, taskAffiliationColor, callingUid,
3846 callingPackage, resizeMode, supportsPictureInPicture, realActivitySuspended,
3847 userSetupComplete, minWidth, minHeight, null /*stack*/);
3848 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
3849 task.setBounds(lastNonFullscreenBounds);
3850
3851 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3852 task.addChild(activities.get(activityNdx));
3853 }
3854
3855 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
3856 return task;
3857 }
3858
3859 void handleUnknownTag(String name, XmlPullParser in)
3860 throws IOException, XmlPullParserException {
3861 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
3862 XmlUtils.skipCurrentTag(in);
3863 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07003864 }
Robert Carr8a2f9132019-11-11 15:03:15 -08003865
3866 boolean isControlledByTaskOrganizer() {
Robert Carr9fd095b2020-01-24 14:40:06 -08003867 final Task rootTask = getRootTask();
3868 return rootTask == this && rootTask.mTaskOrganizer != null;
Robert Carr8a2f9132019-11-11 15:03:15 -08003869 }
3870
3871 @Override
3872 protected void reparentSurfaceControl(SurfaceControl.Transaction t, SurfaceControl newParent) {
3873 /**
3874 * Avoid yanking back control from the TaskOrganizer, which has presumably reparented the
3875 * Surface in to its own hierarchy.
3876 */
3877 if (isControlledByTaskOrganizer()) {
3878 return;
3879 }
3880 super.reparentSurfaceControl(t, newParent);
3881 }
3882
3883 private void sendTaskAppeared() {
3884 if (mSurfaceControl != null && mTaskOrganizer != null) {
3885 mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this);
3886 }
3887 }
3888
3889 private void sendTaskVanished() {
3890 if (mTaskOrganizer != null) {
3891 mAtmService.mTaskOrganizerController.onTaskVanished(mTaskOrganizer, this);
3892 }
3893 }
3894
3895 void setTaskOrganizer(ITaskOrganizer organizer) {
3896 // Let the old organizer know it has lost control.
3897 if (mTaskOrganizer != null) {
3898 sendTaskVanished();
3899 }
3900 mTaskOrganizer = organizer;
3901 sendTaskAppeared();
3902 }
3903
3904 // Called on Binder death.
3905 void taskOrganizerDied() {
3906 mTaskOrganizer = null;
3907 }
3908
3909 @Override
3910 void setSurfaceControl(SurfaceControl sc) {
3911 super.setSurfaceControl(sc);
3912 // If the TaskOrganizer was set before we created the SurfaceControl, we need to
3913 // emit the callbacks now.
3914 sendTaskAppeared();
3915 }
3916
3917 @Override
3918 public void updateSurfacePosition() {
3919 // Avoid fighting with the TaskOrganizer over Surface position.
3920 if (isControlledByTaskOrganizer()) {
3921 getPendingTransaction().setPosition(mSurfaceControl, 0, 0);
3922 scheduleAnimation();
3923 return;
3924 } else {
3925 super.updateSurfacePosition();
3926 }
3927 }
3928
3929 @Override
3930 void getRelativeDisplayedPosition(Point outPos) {
3931 // In addition to updateSurfacePosition, we keep other code that sets
3932 // position from fighting with the TaskOrganizer
3933 if (isControlledByTaskOrganizer()) {
3934 outPos.set(0, 0);
3935 return;
3936 }
3937 super.getRelativeDisplayedPosition(outPos);
3938 }
3939
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08003940 /**
3941 * @return true if the task is currently focused.
3942 */
3943 private boolean isFocused() {
3944 if (mDisplayContent == null || mDisplayContent.mCurrentFocus == null) {
3945 return false;
3946 }
3947 return mDisplayContent.mCurrentFocus.getTask() == this;
3948 }
3949
3950 /**
3951 * @return the desired shadow radius in pixels for the current task.
3952 */
3953 private float getShadowRadius(boolean taskIsFocused) {
3954 if (mDisplayContent == null) {
3955 return 0;
3956 }
3957
3958 if (inPinnedWindowingMode()) {
3959 return dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP,
3960 mDisplayContent.getDisplayMetrics());
3961 }
3962 if (inFreeformWindowingMode()) {
3963 final int elevation = taskIsFocused
3964 ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
3965 return dipToPixel(elevation, mDisplayContent.getDisplayMetrics());
3966 }
3967
3968 // For all other windowing modes, do not draw a shadow.
3969 return 0;
3970 }
3971
3972 /**
3973 * Update the length of the shadow if needed based on windowing mode and task focus state.
3974 */
3975 private void updateShadowsRadius(boolean taskIsFocused,
3976 SurfaceControl.Transaction pendingTransaction) {
3977 if (!mWmService.mRenderShadowsInCompositor) return;
3978
3979 final float newShadowRadius = getShadowRadius(taskIsFocused);
3980 if (mShadowRadius != newShadowRadius) {
3981 mShadowRadius = newShadowRadius;
3982 pendingTransaction.setShadowRadius(getSurfaceControl(), mShadowRadius);
3983 }
3984 }
3985
3986 /**
3987 * Called on the task of a window which gained or lost focus.
3988 * @param hasFocus
3989 */
3990 void onWindowFocusChanged(boolean hasFocus) {
3991 updateShadowsRadius(hasFocus, getPendingTransaction());
3992 }
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08003993}