1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.app.ActivityManager.isStartResultSuccessful;
20 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
21 import static android.app.ActivityTaskManager.INVALID_WINDOWING_MODE;
22 import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED;
23 import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
24 import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN;
25 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
26 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
27 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
28 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
29 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
30 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
31 import static android.app.WindowConfiguration.activityTypeToString;
32 import static android.app.WindowConfiguration.windowingModeToString;
33 import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
34 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
35 import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
36 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
37 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
38 import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
39 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
40 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
41 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
42 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
43 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
44 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
45 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
46 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
47 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
48 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
49 import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
50 import static android.view.Display.DEFAULT_DISPLAY;
51 import static android.view.Display.INVALID_DISPLAY;
52 import static android.view.InsetsSource.FLAG_INSETS_ROUNDED_CORNER;
53 import static android.view.SurfaceControl.METADATA_TASK_ID;
54 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
55 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
56 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
57 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
58 import static android.view.WindowManager.TRANSIT_CHANGE;
59 import static android.view.WindowManager.TRANSIT_CLOSE;
60 import static android.view.WindowManager.TRANSIT_FLAG_APP_CRASHED;
61 import static android.view.WindowManager.TRANSIT_NONE;
62 import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
63 import static android.view.WindowManager.TRANSIT_OPEN;
64 import static android.view.WindowManager.TRANSIT_TO_BACK;
65 import static android.view.WindowManager.TRANSIT_TO_FRONT;
66 import static android.window.DisplayAreaOrganizer.FEATURE_UNDEFINED;
67 
68 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
69 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_LOCKTASK;
70 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
71 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
72 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_TASKS;
73 import static com.android.server.wm.ActivityRecord.State.PAUSED;
74 import static com.android.server.wm.ActivityRecord.State.PAUSING;
75 import static com.android.server.wm.ActivityRecord.State.RESUMED;
76 import static com.android.server.wm.ActivityRecord.State.STARTED;
77 import static com.android.server.wm.ActivityRecord.TRANSFER_SPLASH_SCREEN_COPYING;
78 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
79 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
80 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
81 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
82 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CLEANUP;
83 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
84 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
85 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
86 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
87 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING;
88 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
89 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
90 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
91 import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_TASK_MSG;
92 import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
93 import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
94 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
95 import static com.android.server.wm.ActivityTaskSupervisor.REMOVE_FROM_RECENTS;
96 import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity;
97 import static com.android.server.wm.IdentifierProto.HASH_CODE;
98 import static com.android.server.wm.IdentifierProto.TITLE;
99 import static com.android.server.wm.IdentifierProto.USER_ID;
100 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_ALLOWLISTED;
101 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_DONT_LOCK;
102 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE;
103 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
104 import static com.android.server.wm.LockTaskController.LOCK_TASK_AUTH_PINNABLE;
105 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
106 import static com.android.server.wm.TaskProto.AFFINITY;
107 import static com.android.server.wm.TaskProto.BOUNDS;
108 import static com.android.server.wm.TaskProto.CREATED_BY_ORGANIZER;
109 import static com.android.server.wm.TaskProto.FILLS_PARENT;
110 import static com.android.server.wm.TaskProto.HAS_CHILD_PIP_ACTIVITY;
111 import static com.android.server.wm.TaskProto.LAST_NON_FULLSCREEN_BOUNDS;
112 import static com.android.server.wm.TaskProto.ORIG_ACTIVITY;
113 import static com.android.server.wm.TaskProto.REAL_ACTIVITY;
114 import static com.android.server.wm.TaskProto.RESIZE_MODE;
115 import static com.android.server.wm.TaskProto.RESUMED_ACTIVITY;
116 import static com.android.server.wm.TaskProto.ROOT_TASK_ID;
117 import static com.android.server.wm.TaskProto.SURFACE_HEIGHT;
118 import static com.android.server.wm.TaskProto.SURFACE_WIDTH;
119 import static com.android.server.wm.TaskProto.TASK_FRAGMENT;
120 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
121 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
122 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
123 import static com.android.server.wm.WindowContainerChildProto.TASK;
124 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
125 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
126 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
127 
128 import static java.lang.Integer.MAX_VALUE;
129 
130 import android.annotation.IntDef;
131 import android.annotation.NonNull;
132 import android.annotation.Nullable;
133 import android.annotation.UserIdInt;
134 import android.app.Activity;
135 import android.app.ActivityManager;
136 import android.app.ActivityManager.RecentTaskInfo.PersistedTaskSnapshotData;
137 import android.app.ActivityManager.TaskDescription;
138 import android.app.ActivityOptions;
139 import android.app.ActivityTaskManager;
140 import android.app.AppGlobals;
141 import android.app.IActivityController;
142 import android.app.PictureInPictureParams;
143 import android.app.TaskInfo;
144 import android.app.WindowConfiguration;
145 import android.content.ComponentName;
146 import android.content.Intent;
147 import android.content.pm.ActivityInfo;
148 import android.content.pm.ActivityInfo.ScreenOrientation;
149 import android.content.pm.ApplicationInfo;
150 import android.content.pm.IPackageManager;
151 import android.content.pm.PackageManager;
152 import android.content.res.Configuration;
153 import android.graphics.Matrix;
154 import android.graphics.Point;
155 import android.graphics.Rect;
156 import android.os.Binder;
157 import android.os.Debug;
158 import android.os.Handler;
159 import android.os.IBinder;
160 import android.os.Looper;
161 import android.os.Message;
162 import android.os.Process;
163 import android.os.RemoteException;
164 import android.os.SystemClock;
165 import android.os.Trace;
166 import android.os.UserHandle;
167 import android.provider.Settings;
168 import android.service.voice.IVoiceInteractionSession;
169 import android.util.ArraySet;
170 import android.util.DisplayMetrics;
171 import android.util.Slog;
172 import android.util.proto.ProtoOutputStream;
173 import android.view.DisplayInfo;
174 import android.view.InsetsSource;
175 import android.view.InsetsState;
176 import android.view.RemoteAnimationAdapter;
177 import android.view.Surface;
178 import android.view.SurfaceControl;
179 import android.view.TaskTransitionSpec;
180 import android.view.WindowManager;
181 import android.view.WindowManager.TransitionOldType;
182 import android.window.ITaskOrganizer;
183 import android.window.PictureInPictureSurfaceTransaction;
184 import android.window.StartingWindowInfo;
185 import android.window.TaskFragmentParentInfo;
186 import android.window.TaskSnapshot;
187 import android.window.WindowContainerToken;
188 
189 import com.android.internal.annotations.GuardedBy;
190 import com.android.internal.annotations.VisibleForTesting;
191 import com.android.internal.app.IVoiceInteractor;
192 import com.android.internal.protolog.common.ProtoLog;
193 import com.android.internal.util.XmlUtils;
194 import com.android.internal.util.function.pooled.PooledLambda;
195 import com.android.internal.util.function.pooled.PooledPredicate;
196 import com.android.modules.utils.TypedXmlPullParser;
197 import com.android.modules.utils.TypedXmlSerializer;
198 import com.android.server.Watchdog;
199 import com.android.server.am.ActivityManagerService;
200 import com.android.server.am.AppTimeTracker;
201 import com.android.server.uri.NeededUriGrants;
202 
203 import org.xmlpull.v1.XmlPullParser;
204 import org.xmlpull.v1.XmlPullParserException;
205 
206 import java.io.FileDescriptor;
207 import java.io.IOException;
208 import java.io.PrintWriter;
209 import java.lang.annotation.Retention;
210 import java.lang.annotation.RetentionPolicy;
211 import java.util.ArrayList;
212 import java.util.Objects;
213 import java.util.function.Consumer;
214 import java.util.function.Predicate;
215 
216 /**
217  * {@link Task} is a TaskFragment that can contain a group of activities to perform a certain job.
218  * Activities of the same task affinities usually group in the same {@link Task}. A {@link Task}
219  * can also be an entity that showing in the Recents Screen for a job that user interacted with.
220  * A {@link Task} can also contain other {@link Task}s.
221  */
222 class Task extends TaskFragment {
223     private static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_ATM;
224     private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
225     static final String TAG_TASKS = TAG + POSTFIX_TASKS;
226     static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP;
227     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
228     private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
229     private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
230     static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
231 
232     private static final String ATTR_TASKID = "task_id";
233     private static final String TAG_INTENT = "intent";
234     private static final String TAG_AFFINITYINTENT = "affinity_intent";
235     private static final String ATTR_REALACTIVITY = "real_activity";
236     private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
237     private static final String ATTR_ORIGACTIVITY = "orig_activity";
238     private static final String TAG_ACTIVITY = "activity";
239     private static final String ATTR_AFFINITY = "affinity";
240     private static final String ATTR_ROOT_AFFINITY = "root_affinity";
241     private static final String ATTR_ROOTHASRESET = "root_has_reset";
242     private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
243     private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
244     private static final String ATTR_USERID = "user_id";
245     private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
246     private static final String ATTR_EFFECTIVE_UID = "effective_uid";
247     @Deprecated
248     private static final String ATTR_TASKTYPE = "task_type";
249     private static final String ATTR_LASTDESCRIPTION = "last_description";
250     private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
251     private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
252     private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
253     private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
254     private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
255     private static final String ATTR_CALLING_UID = "calling_uid";
256     private static final String ATTR_CALLING_PACKAGE = "calling_package";
257     private static final String ATTR_CALLING_FEATURE_ID = "calling_feature_id";
258     private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
259     private static final String ATTR_RESIZE_MODE = "resize_mode";
260     private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
261     private static final String ATTR_MIN_WIDTH = "min_width";
262     private static final String ATTR_MIN_HEIGHT = "min_height";
263     private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
264     private static final String ATTR_WINDOW_LAYOUT_AFFINITY = "window_layout_affinity";
265     private static final String ATTR_LAST_SNAPSHOT_TASK_SIZE = "last_snapshot_task_size";
266     private static final String ATTR_LAST_SNAPSHOT_CONTENT_INSETS = "last_snapshot_content_insets";
267     private static final String ATTR_LAST_SNAPSHOT_BUFFER_SIZE = "last_snapshot_buffer_size";
268 
269     // How long to wait for all background Activities to redraw following a call to
270     // convertToTranslucent().
271     private static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000;
272 
273     // Current version of the task record we persist. Used to check if we need to run any upgrade
274     // code.
275     static final int PERSIST_TASK_VERSION = 1;
276 
277     private static final int DEFAULT_MIN_TASK_SIZE_DP = 220;
278 
279     /**
280      * The modes to control how root task is moved to the front when calling {@link Task#reparent}.
281      */
282     @Retention(RetentionPolicy.SOURCE)
283     @IntDef({
284             REPARENT_MOVE_ROOT_TASK_TO_FRONT,
285             REPARENT_KEEP_ROOT_TASK_AT_FRONT,
286             REPARENT_LEAVE_ROOT_TASK_IN_PLACE
287     })
288     @interface ReparentMoveRootTaskMode {}
289     // Moves the root task to the front if it was not at the front
290     static final int REPARENT_MOVE_ROOT_TASK_TO_FRONT = 0;
291     // Only moves the root task to the front if it was focused or front most already
292     static final int REPARENT_KEEP_ROOT_TASK_AT_FRONT = 1;
293     // Do not move the root task as a part of reparenting
294     static final int REPARENT_LEAVE_ROOT_TASK_IN_PLACE = 2;
295 
296     // The topmost Activity passed to convertToTranslucent(). When non-null it means we are
297     // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they
298     // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the
299     // Activity in mTranslucentActivityWaiting is notified via
300     // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last
301     // background activity being drawn then the same call will be made with a true value.
302     ActivityRecord mTranslucentActivityWaiting = null;
303     ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = new ArrayList<>();
304 
305     /**
306      * Set when we know we are going to be calling updateConfiguration()
307      * soon, so want to skip intermediate config checks.
308      */
309     boolean mConfigWillChange;
310 
311     /**
312      * Used to keep resumeTopActivityUncheckedLocked() from being entered recursively
313      */
314     boolean mInResumeTopActivity = false;
315 
316     /**
317      * Used to identify if the activity that is installed from device's system image.
318      */
319     boolean mIsEffectivelySystemApp;
320 
321     int mCurrentUser;
322 
323     String affinity;        // The affinity name for this task, or null; may change identity.
324     String rootAffinity;    // Initial base affinity, or null; does not change from initial root.
325     String mWindowLayoutAffinity; // Launch param affinity of this task or null. Used when saving
326                                 // launch params of this task.
327     IVoiceInteractionSession voiceSession;    // Voice interaction session driving task
328     IVoiceInteractor voiceInteractor;         // Associated interactor to provide to app
329     Intent intent;          // The original intent that started the task. Note that this value can
330                             // be null.
331     Intent affinityIntent;  // Intent of affinity-moved activity that started this task.
332     int effectiveUid;       // The current effective uid of the identity of this task.
333     ComponentName origActivity; // The non-alias activity component of the intent.
334     ComponentName realActivity; // The actual activity component that started the task.
335     boolean realActivitySuspended; // True if the actual activity component that started the
336                                    // task is suspended.
337     boolean inRecents;      // Actually in the recents list?
338     long lastActiveTime;    // Last time this task was active in the current device session,
339                             // including sleep. This time is initialized to the elapsed time when
340                             // restored from disk.
341     boolean isAvailable;    // Is the activity available to be launched?
342     boolean rootWasReset;   // True if the intent at the root of the task had
343                             // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
344     boolean autoRemoveRecents;  // If true, we should automatically remove the task from
345                                 // recents when activity finishes
346     boolean askedCompatMode;// Have asked the user about compat mode for this task.
347     private boolean mHasBeenVisible; // Set if any activities in the task have been visible
348 
349     String stringName;      // caching of toString() result.
350     boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
351                                 // was changed.
352 
353     int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
354 
355     int mLockTaskUid = -1;  // The uid of the application that called startLockTask().
356 
357     /**
358      * If non-null, the starting window should cover the associated task. It is assigned when the
359      * parent activity of starting window is put in a partial area of the task. This field will be
360      * cleared when all visible activities in this task are drawn.
361      */
362     StartingData mSharedStartingData;
363 
364     /** The process that had previously hosted the root activity of this task.
365      * Used to know that we should try harder to keep this process around, in case the
366      * user wants to return to it. */
367     private WindowProcessController mRootProcess;
368 
369     /** Takes on same value as first root activity */
370     boolean isPersistable = false;
371     int maxRecents;
372 
373     /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
374      *  determining the order when restoring. */
375     long mLastTimeMoved;
376 
377     /**
378      * If it is set, the processes belong to the task will be killed when one of its activity
379      * reports that Activity#onDestroy is done and the task no longer contains perceptible
380      * components. This should only be set on a leaf task.
381      */
382     boolean mKillProcessesOnDestroyed;
383 
384     /** If original intent did not allow relinquishing task identity, save that information */
385     private boolean mNeverRelinquishIdentity = true;
386 
387     /** Avoid reentrant of {@link #removeImmediately(String)}. */
388     private boolean mRemoving;
389 
390     // Used in the unique case where we are clearing the task in order to reuse it. In that case we
391     // do not want to delete the root task when the task goes empty.
392     private boolean mReuseTask = false;
393 
394     CharSequence lastDescription; // Last description captured for this item.
395 
396     int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
397     Task mPrevAffiliate; // previous task in affiliated chain.
398     int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
399     Task mNextAffiliate; // next task in affiliated chain.
400     int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
401 
402     // For relaunching the task from recents as though it was launched by the original launcher.
403     int mCallingUid;
404     String mCallingPackage;
405     String mCallingFeatureId;
406 
407     private static final Rect sTmpBounds = new Rect();
408 
409     // Last non-fullscreen bounds the task was launched in or resized to.
410     // The information is persisted and used to determine the appropriate root task to launch the
411     // task into on restore.
412     Rect mLastNonFullscreenBounds = null;
413 
414     // The surface transition of the target when recents animation is finished.
415     // This is originally introduced to carry out the current surface control position and window
416     // crop when a multi-activity task enters pip with autoEnterPip enabled. In such case,
417     // the surface control of the task will be animated in Launcher and then the top activity is
418     // reparented to pinned root task.
419     // Do not forget to reset this after reparenting.
420     // TODO: remove this once the recents animation is moved to the Shell
421     PictureInPictureSurfaceTransaction mLastRecentsAnimationTransaction;
422     // The content overlay to be applied with mLastRecentsAnimationTransaction
423     // TODO: remove this once the recents animation is moved to the Shell
424     SurfaceControl mLastRecentsAnimationOverlay;
425 
426     static final int LAYER_RANK_INVISIBLE = -1;
427     // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
428     // This number will be assigned when we evaluate OOM scores for all visible tasks.
429     int mLayerRank = LAYER_RANK_INVISIBLE;
430 
431     /* Unique identifier for this task. */
432     final int mTaskId;
433     /* User for which this task was created. */
434     // TODO: Make final
435     int mUserId;
436 
437     // Id of the previous display the root task was on.
438     int mPrevDisplayId = INVALID_DISPLAY;
439 
440     /** ID of the display which rotation {@link #mRotation} has. */
441     private int mLastRotationDisplayId = INVALID_DISPLAY;
442 
443     /**
444      * Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
445      * moved to a new display.
446      */
447     @Surface.Rotation
448     private int mRotation;
449 
450     int mMultiWindowRestoreWindowingMode = INVALID_WINDOWING_MODE;
451 
452     /**
453      * Last requested orientation reported to DisplayContent. This is different from {@link
454      * #mOrientation} in the sense that this takes activities' requested orientation into
455      * account. Start with {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} so that we don't need
456      * to notify for activities that don't specify any orientation.
457      */
458     int mLastReportedRequestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
459 
460     // For comparison with DisplayContent bounds.
461     private Rect mTmpRect = new Rect();
462     // For handling display rotations.
463     private Rect mTmpRect2 = new Rect();
464 
465     // Resize mode of the task. See {@link ActivityInfo#resizeMode}
466     // Based on the {@link ActivityInfo#resizeMode} of the root activity.
467     int mResizeMode;
468 
469     // Whether or not this task and its activities support PiP. Based on the
470     // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity.
471     boolean mSupportsPictureInPicture;
472 
473     // Whether the task is currently being drag-resized
474     private boolean mDragResizing;
475 
476     // This represents the last resolved activity values for this task
477     // NOTE: This value needs to be persisted with each task
478     private TaskDescription mTaskDescription;
479 
480     // Information about the last snapshot that should be persisted with the task to allow SystemUI
481     // to layout without loading all the task snapshots
482     final PersistedTaskSnapshotData mLastTaskSnapshotData;
483 
484     /** @see #setCanAffectSystemUiFlags */
485     private boolean mCanAffectSystemUiFlags = true;
486 
487     private static Exception sTmpException;
488 
489     private boolean mForceShowForAllUsers;
490 
491     /** When set, will force the task to report as invisible. */
492     static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1;
493     static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1;
494     private int mForceHiddenFlags = 0;
495     private boolean mForceTranslucent = false;
496 
497     // The display category name for this task.
498     String mRequiredDisplayCategory;
499 
500     // TODO(b/160201781): Revisit double invocation issue in Task#removeChild.
501     /**
502      * Skip {@link ActivityTaskSupervisor#removeTask(Task, boolean, boolean, String)} execution if
503      * {@code true} to prevent double traversal of {@link #mChildren} in a loop.
504      */
505     boolean mInRemoveTask;
506 
507     /**
508      * When set, disassociate the leaf task if relaunched and reparented it to TDA as root task if
509      * possible.
510      */
511     boolean mReparentLeafTaskIfRelaunch;
512 
513     private final AnimatingActivityRegistry mAnimatingActivityRegistry =
514             new AnimatingActivityRegistry();
515 
516     private static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_TASK_MSG + 1;
517 
518     private final Handler mHandler;
519 
520     private class ActivityTaskHandler extends Handler {
521 
ActivityTaskHandler(Looper looper)522         ActivityTaskHandler(Looper looper) {
523             super(looper);
524         }
525 
526         @Override
handleMessage(Message msg)527         public void handleMessage(Message msg) {
528             switch (msg.what) {
529                 case TRANSLUCENT_TIMEOUT_MSG: {
530                     synchronized (mAtmService.mGlobalLock) {
531                         notifyActivityDrawnLocked(null);
532                     }
533                 } break;
534             }
535         }
536     }
537 
538     private static final ResetTargetTaskHelper sResetTargetTaskHelper = new ResetTargetTaskHelper();
539 
540     private final FindRootHelper mFindRootHelper = new FindRootHelper();
541     private class FindRootHelper implements Predicate<ActivityRecord> {
542         private ActivityRecord mRoot;
543         private boolean mIgnoreRelinquishIdentity;
544         private boolean mSetToBottomIfNone;
545 
findRoot(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone)546         ActivityRecord findRoot(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
547             mIgnoreRelinquishIdentity = ignoreRelinquishIdentity;
548             mSetToBottomIfNone = setToBottomIfNone;
549             forAllActivities(this, false /* traverseTopToBottom */);
550             final ActivityRecord root = mRoot;
551             mRoot = null;
552             return root;
553         }
554 
555         @Override
test(ActivityRecord r)556         public boolean test(ActivityRecord r) {
557             if (mRoot == null && mSetToBottomIfNone) {
558                 // This is the first activity we are process. Set it as the candidate root in case
559                 // we don't find a better one.
560                 mRoot = r;
561             }
562 
563             if (r.finishing) return false;
564 
565             if (mRoot == null || mRoot.finishing) {
566                 // Set this as the candidate root since it isn't finishing.
567                 mRoot = r;
568             }
569 
570             final int uid = mRoot == r ? effectiveUid : r.info.applicationInfo.uid;
571             if (mIgnoreRelinquishIdentity
572                     || (mRoot.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0
573                     || (mRoot.info.applicationInfo.uid != Process.SYSTEM_UID
574                     && !mRoot.info.applicationInfo.isSystemApp()
575                     && mRoot.info.applicationInfo.uid != uid)) {
576                 // No need to relinquish identity, end search.
577                 return true;
578             }
579 
580             // Relinquish to next activity
581             mRoot = r;
582             return false;
583         }
584     }
585 
586     /**
587      * The TaskOrganizer which is delegated presentation of this task. If set the Task will
588      * emit an WindowContainerToken (allowing access to it's SurfaceControl leash) to the organizers
589      * taskAppeared callback, and emit a taskRemoved callback when the Task is vanished.
590      */
591     ITaskOrganizer mTaskOrganizer;
592 
593     /**
594      * Prevent duplicate calls to onTaskAppeared.
595      */
596     boolean mTaskAppearedSent;
597 
598     // If the sending of the task appear signal should be deferred until this flag is set back to
599     // false.
600     private boolean mDeferTaskAppear;
601 
602     // Tracking cookie for the creation of this task.
603     IBinder mLaunchCookie;
604 
605     // The task will be removed when TaskOrganizer, which is managing the task, is destroyed.
606     boolean mRemoveWithTaskOrganizer;
607 
608     /**
609      * Reference to the pinned activity that is logically parented to this task, ie.
610      * the previous top activity within this task is put into pinned mode.
611      * This always gets cleared in pair with the ActivityRecord-to-Task link as seen in
612      * {@link ActivityRecord#clearLastParentBeforePip()}.
613      */
614     ActivityRecord mChildPipActivity;
615 
616     boolean mLastSurfaceShowing;
617 
618     boolean mAlignActivityLocaleWithTask = false;
619 
Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent, Intent _affinityIntent, String _affinity, String _rootAffinity, ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset, boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId, int _effectiveUid, String _lastDescription, long lastTimeMoved, boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription, PersistedTaskSnapshotData _lastSnapshotData, int taskAffiliation, int prevTaskId, int nextTaskId, int callingUid, String callingPackage, @Nullable String callingFeatureId, int resizeMode, boolean supportsPictureInPicture, boolean _realActivitySuspended, boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info, IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, boolean _createdByOrganizer, IBinder _launchCookie, boolean _deferTaskAppear, boolean _removeWithTaskOrganizer)620     private Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent,
621             Intent _affinityIntent, String _affinity, String _rootAffinity,
622             ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
623             boolean _autoRemoveRecents, boolean _askedCompatMode, int _userId, int _effectiveUid,
624             String _lastDescription, long lastTimeMoved, boolean neverRelinquishIdentity,
625             TaskDescription _lastTaskDescription, PersistedTaskSnapshotData _lastSnapshotData,
626             int taskAffiliation, int prevTaskId, int nextTaskId, int callingUid,
627             String callingPackage, @Nullable String callingFeatureId, int resizeMode,
628             boolean supportsPictureInPicture, boolean _realActivitySuspended,
629             boolean userSetupComplete, int minWidth, int minHeight, ActivityInfo info,
630             IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
631             boolean _createdByOrganizer, IBinder _launchCookie, boolean _deferTaskAppear,
632             boolean _removeWithTaskOrganizer) {
633         super(atmService, null /* fragmentToken */, _createdByOrganizer, false /* isEmbedded */);
634 
635         mTaskId = _taskId;
636         mUserId = _userId;
637         mResizeMode = resizeMode;
638         mSupportsPictureInPicture = supportsPictureInPicture;
639         mTaskDescription = _lastTaskDescription != null
640                 ? _lastTaskDescription
641                 : new TaskDescription();
642         mLastTaskSnapshotData = _lastSnapshotData != null
643                 ? _lastSnapshotData
644                 : new PersistedTaskSnapshotData();
645         // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
646         setOrientation(SCREEN_ORIENTATION_UNSET);
647         affinityIntent = _affinityIntent;
648         affinity = _affinity;
649         rootAffinity = _rootAffinity;
650         voiceSession = _voiceSession;
651         voiceInteractor = _voiceInteractor;
652         realActivity = _realActivity;
653         realActivitySuspended = _realActivitySuspended;
654         origActivity = _origActivity;
655         rootWasReset = _rootWasReset;
656         isAvailable = true;
657         autoRemoveRecents = _autoRemoveRecents;
658         askedCompatMode = _askedCompatMode;
659         mUserSetupComplete = userSetupComplete;
660         effectiveUid = _effectiveUid;
661         touchActiveTime();
662         lastDescription = _lastDescription;
663         mLastTimeMoved = lastTimeMoved;
664         mNeverRelinquishIdentity = neverRelinquishIdentity;
665         mAffiliatedTaskId = taskAffiliation;
666         mPrevAffiliateTaskId = prevTaskId;
667         mNextAffiliateTaskId = nextTaskId;
668         mCallingUid = callingUid;
669         mCallingPackage = callingPackage;
670         mCallingFeatureId = callingFeatureId;
671         mResizeMode = resizeMode;
672         if (info != null) {
673             setIntent(_intent, info);
674             setMinDimensions(info);
675         } else {
676             intent = _intent;
677             mMinWidth = minWidth;
678             mMinHeight = minHeight;
679         }
680         mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
681         mHandler = new ActivityTaskHandler(mTaskSupervisor.mLooper);
682         mCurrentUser = mAtmService.mAmInternal.getCurrentUserId();
683 
684         mLaunchCookie = _launchCookie;
685         mDeferTaskAppear = _deferTaskAppear;
686         mRemoveWithTaskOrganizer = _removeWithTaskOrganizer;
687         EventLogTags.writeWmTaskCreated(mTaskId);
688     }
689 
fromWindowContainerToken(WindowContainerToken token)690     static Task fromWindowContainerToken(WindowContainerToken token) {
691         if (token == null) return null;
692         return fromBinder(token.asBinder()).asTask();
693     }
694 
reuseAsLeafTask(IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, Intent intent, ActivityInfo info, ActivityRecord activity)695     Task reuseAsLeafTask(IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
696             Intent intent, ActivityInfo info, ActivityRecord activity) {
697         voiceSession = _voiceSession;
698         voiceInteractor = _voiceInteractor;
699         setIntent(activity, intent, info);
700         setMinDimensions(info);
701         // Before we began to reuse a root task as the leaf task, we used to
702         // create a leaf task in this case. Therefore now we won't send out the task created
703         // notification when we decide to reuse it here, so we send out the notification below.
704         // The reason why the created notification sent out when root task is created doesn't work
705         // is that realActivity isn't set until setIntent() method above is called for the first
706         // time. Eventually this notification will be removed when we can populate those information
707         // when root task is created.
708         mAtmService.getTaskChangeNotificationController().notifyTaskCreated(mTaskId, realActivity);
709         return this;
710     }
711 
cleanUpResourcesForDestroy(WindowContainer<?> oldParent)712     private void cleanUpResourcesForDestroy(WindowContainer<?> oldParent) {
713         if (hasChild()) {
714             return;
715         }
716 
717         // This task is going away, so save the last state if necessary.
718         saveLaunchingStateIfNeeded(oldParent.getDisplayContent());
719 
720         // TODO: VI what about activity?
721         final boolean isVoiceSession = voiceSession != null;
722         if (isVoiceSession) {
723             try {
724                 voiceSession.taskFinished(intent, mTaskId);
725             } catch (RemoteException e) {
726             }
727         }
728         if (autoRemoveFromRecents(oldParent.asTaskFragment()) || isVoiceSession) {
729             // Task creator asked to remove this when done, or this task was a voice
730             // interaction, so it should not remain on the recent tasks list.
731             mTaskSupervisor.mRecentTasks.remove(this);
732         }
733 
734         removeIfPossible("cleanUpResourcesForDestroy");
735     }
736 
737     @VisibleForTesting
738     @Override
removeIfPossible()739     void removeIfPossible() {
740         removeIfPossible("removeTaskIfPossible");
741     }
742 
removeIfPossible(String reason)743     void removeIfPossible(String reason) {
744         mAtmService.getLockTaskController().clearLockedTask(this);
745         if (shouldDeferRemoval()) {
746             if (DEBUG_ROOT_TASK) Slog.i(TAG,
747                     "removeTask:" + reason + " deferring removing taskId=" + mTaskId);
748             return;
749         }
750         final boolean isLeafTask = isLeafTask();
751         removeImmediately(reason);
752         if (isLeafTask) {
753             mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
754 
755             final TaskDisplayArea taskDisplayArea = getDisplayArea();
756             if (taskDisplayArea != null) {
757                 taskDisplayArea.onLeafTaskRemoved(mTaskId);
758             }
759         }
760     }
761 
setResizeMode(int resizeMode)762     void setResizeMode(int resizeMode) {
763         if (mResizeMode == resizeMode) {
764             return;
765         }
766         mResizeMode = resizeMode;
767         mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
768         mRootWindowContainer.resumeFocusedTasksTopActivities();
769         updateTaskDescription();
770     }
771 
resize(Rect bounds, int resizeMode, boolean preserveWindow)772     boolean resize(Rect bounds, int resizeMode, boolean preserveWindow) {
773         mAtmService.deferWindowLayout();
774 
775         try {
776             final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
777 
778             if (getParent() == null) {
779                 // Task doesn't exist in window manager yet (e.g. was restored from recents).
780                 // All we can do for now is update the bounds so it can be used when the task is
781                 // added to window manager.
782                 setBounds(bounds);
783                 if (!inFreeformWindowingMode()) {
784                     // re-restore the task so it can have the proper root task association.
785                     mTaskSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
786                 }
787                 return true;
788             }
789 
790             if (!canResizeToBounds(bounds)) {
791                 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
792                         + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
793             }
794 
795             // Do not move the task to another root task here.
796             // This method assumes that the task is already placed in the right root task.
797             // we do not mess with that decision and we only do the resize!
798 
799             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeTask_" + mTaskId);
800 
801             // This variable holds information whether the configuration didn't change in a
802             // significant way and the activity was kept the way it was. If it's false, it means
803             // the activity had to be relaunched due to configuration change.
804             boolean kept = true;
805             if (setBounds(bounds, forced) != BOUNDS_CHANGE_NONE) {
806                 final ActivityRecord r = topRunningActivityLocked();
807                 if (r != null) {
808                     kept = r.ensureActivityConfiguration(0 /* globalChanges */,
809                             preserveWindow);
810                     // Preserve other windows for resizing because if resizing happens when there
811                     // is a dialog activity in the front, the activity that still shows some
812                     // content to the user will become black and cause flickers. Note in most cases
813                     // this won't cause tons of irrelevant windows being preserved because only
814                     // activities in this task may experience a bounds change. Configs for other
815                     // activities stay the same.
816                     mRootWindowContainer.ensureActivitiesVisible(r, 0, preserveWindow);
817                     if (!kept) {
818                         mRootWindowContainer.resumeFocusedTasksTopActivities();
819                     }
820                 }
821             }
822             saveLaunchingStateIfNeeded();
823 
824             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
825             return kept;
826         } finally {
827             mAtmService.continueWindowLayout();
828         }
829     }
830 
831     /** Convenience method to reparent a task to the top or bottom position of the root task. */
reparent(Task preferredRootTask, boolean toTop, @ReparentMoveRootTaskMode int moveRootTaskMode, boolean animate, boolean deferResume, String reason)832     boolean reparent(Task preferredRootTask, boolean toTop,
833             @ReparentMoveRootTaskMode int moveRootTaskMode, boolean animate, boolean deferResume,
834             String reason) {
835         return reparent(preferredRootTask, toTop ? MAX_VALUE : 0, moveRootTaskMode, animate,
836                 deferResume, true /* schedulePictureInPictureModeChange */, reason);
837     }
838 
839     /**
840      * Reparents the task into a preferred root task, creating it if necessary.
841      *
842      * @param preferredRootTask the target root task to move this task
843      * @param position the position to place this task in the new root task
844      * @param animate whether or not we should wait for the new window created as a part of the
845      *            reparenting to be drawn and animated in
846      * @param moveRootTaskMode whether or not to move the root task to the front always, only if
847      *            it was previously focused & in front, or never
848      * @param deferResume whether or not to update the visibility of other tasks and root tasks
849      *            that may have changed as a result of this reparenting
850      * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
851      *            change. Callers may set this to false if they are explicitly scheduling PiP mode
852      *            changes themselves, like during the PiP animation
853      * @param reason the caller of this reparenting
854      * @return whether the task was reparented
855      */
856     // TODO: Inspect all call sites and change to just changing windowing mode of the root task vs.
857     // re-parenting the task. Can only be done when we are no longer using static root task Ids.
reparent(Task preferredRootTask, int position, @ReparentMoveRootTaskMode int moveRootTaskMode, boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange, String reason)858     boolean reparent(Task preferredRootTask, int position,
859             @ReparentMoveRootTaskMode int moveRootTaskMode, boolean animate, boolean deferResume,
860             boolean schedulePictureInPictureModeChange, String reason) {
861         final ActivityTaskSupervisor supervisor = mTaskSupervisor;
862         final RootWindowContainer root = mRootWindowContainer;
863         final WindowManagerService windowManager = mAtmService.mWindowManager;
864         final Task sourceRootTask = getRootTask();
865         final Task toRootTask = supervisor.getReparentTargetRootTask(this, preferredRootTask,
866                 position == MAX_VALUE);
867         if (toRootTask == sourceRootTask) {
868             return false;
869         }
870         if (!canBeLaunchedOnDisplay(toRootTask.getDisplayId())) {
871             return false;
872         }
873 
874         final ActivityRecord topActivity = getTopNonFinishingActivity();
875 
876         mAtmService.deferWindowLayout();
877         boolean kept = true;
878         try {
879             final ActivityRecord r = topRunningActivityLocked();
880             final boolean wasFocused = r != null && root.isTopDisplayFocusedRootTask(sourceRootTask)
881                     && (topRunningActivityLocked() == r);
882 
883             // In some cases the focused root task isn't the front root task. E.g. root pinned task.
884             // Whenever we are moving the top activity from the front root task we want to make
885             // sure to move the root task to the front.
886             final boolean wasFront = r != null && sourceRootTask.isTopRootTaskInDisplayArea()
887                     && (sourceRootTask.topRunningActivity() == r);
888 
889             final boolean moveRootTaskToFront = moveRootTaskMode == REPARENT_MOVE_ROOT_TASK_TO_FRONT
890                     || (moveRootTaskMode == REPARENT_KEEP_ROOT_TASK_AT_FRONT
891                             && (wasFocused || wasFront));
892 
893             reparent(toRootTask, position, moveRootTaskToFront, reason);
894 
895             if (schedulePictureInPictureModeChange) {
896                 // Notify of picture-in-picture mode changes
897                 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceRootTask);
898             }
899 
900             // If the task had focus before (or we're requested to move focus), move focus to the
901             // new root task by moving the root task to the front.
902             if (r != null && moveRootTaskToFront) {
903                 // Move the root task in which we are placing the activity to the front.
904                 toRootTask.moveToFront(reason);
905 
906                 // If the original state is resumed, there is no state change to update focused app.
907                 // So here makes sure the activity focus is set if it is the top.
908                 if (r.isState(RESUMED) && r == mRootWindowContainer.getTopResumedActivity()) {
909                     mAtmService.setLastResumedActivityUncheckLocked(r, reason);
910                 }
911             }
912             if (!animate) {
913                 mTaskSupervisor.mNoAnimActivities.add(topActivity);
914             }
915         } finally {
916             mAtmService.continueWindowLayout();
917         }
918 
919         if (!deferResume) {
920             // The task might have already been running and its visibility needs to be synchronized
921             // with the visibility of the root task / windows.
922             root.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
923             root.resumeFocusedTasksTopActivities();
924         }
925 
926         // TODO: Handle incorrect request to move before the actual move, not after.
927         supervisor.handleNonResizableTaskIfNeeded(this, preferredRootTask.getWindowingMode(),
928                 mRootWindowContainer.getDefaultTaskDisplayArea(), toRootTask);
929 
930         return (preferredRootTask == toRootTask);
931     }
932 
touchActiveTime()933     void touchActiveTime() {
934         lastActiveTime = SystemClock.elapsedRealtime();
935     }
936 
getInactiveDuration()937     long getInactiveDuration() {
938         return SystemClock.elapsedRealtime() - lastActiveTime;
939     }
940 
941     /** @see #setIntent(ActivityRecord, Intent, ActivityInfo) */
setIntent(ActivityRecord r)942     void setIntent(ActivityRecord r) {
943         setIntent(r, null /* intent */, null /* info */);
944     }
945 
946     /**
947      * Sets the original intent, and the calling uid and package.
948      *
949      * @param r The activity that started the task
950      * @param intent The task info which could be different from {@code r.intent} if set.
951      * @param info The activity info which could be different from {@code r.info} if set.
952      */
setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info)953     void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) {
954         boolean updateIdentity = false;
955         if (this.intent == null) {
956             updateIdentity = true;
957         } else if (!mNeverRelinquishIdentity) {
958             final ActivityInfo activityInfo = info != null ? info : r.info;
959             updateIdentity = (effectiveUid == Process.SYSTEM_UID || mIsEffectivelySystemApp
960                     || effectiveUid == activityInfo.applicationInfo.uid);
961         }
962         if (updateIdentity) {
963             mCallingUid = r.launchedFromUid;
964             mCallingPackage = r.launchedFromPackage;
965             mCallingFeatureId = r.launchedFromFeatureId;
966             setIntent(intent != null ? intent : r.intent, info != null ? info : r.info);
967         }
968         setLockTaskAuth(r);
969     }
970 
971     /** Sets the original intent, _without_ updating the calling uid or package. */
setIntent(Intent _intent, ActivityInfo info)972     private void setIntent(Intent _intent, ActivityInfo info) {
973         if (!isLeafTask()) return;
974 
975         mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
976         affinity = info.taskAffinity;
977         if (intent == null) {
978             // If this task already has an intent associated with it, don't set the root
979             // affinity -- we don't want it changing after initially set, but the initially
980             // set value may be null.
981             rootAffinity = affinity;
982             mRequiredDisplayCategory = info.requiredDisplayCategory;
983         }
984         effectiveUid = info.applicationInfo.uid;
985         mIsEffectivelySystemApp = info.applicationInfo.isSystemApp();
986         stringName = null;
987 
988         if (info.targetActivity == null) {
989             if (_intent != null) {
990                 // If this Intent has a selector, we want to clear it for the
991                 // recent task since it is not relevant if the user later wants
992                 // to re-launch the app.
993                 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
994                     _intent = new Intent(_intent);
995                     _intent.setSelector(null);
996                     _intent.setSourceBounds(null);
997                 }
998             }
999             ProtoLog.v(WM_DEBUG_TASKS, "Setting Intent of %s to %s", this, _intent);
1000             intent = _intent;
1001             realActivity = _intent != null ? _intent.getComponent() : null;
1002             origActivity = null;
1003         } else {
1004             ComponentName targetComponent = new ComponentName(
1005                     info.packageName, info.targetActivity);
1006             if (_intent != null) {
1007                 Intent targetIntent = new Intent(_intent);
1008                 targetIntent.setSelector(null);
1009                 targetIntent.setSourceBounds(null);
1010                 ProtoLog.v(WM_DEBUG_TASKS, "Setting Intent of %s to target %s", this, targetIntent);
1011                 intent = targetIntent;
1012                 realActivity = targetComponent;
1013                 origActivity = _intent.getComponent();
1014             } else {
1015                 intent = null;
1016                 realActivity = targetComponent;
1017                 origActivity = new ComponentName(info.packageName, info.name);
1018             }
1019         }
1020         mWindowLayoutAffinity =
1021                 info.windowLayout == null ? null : info.windowLayout.windowLayoutAffinity;
1022 
1023         final int intentFlags = intent == null ? 0 : intent.getFlags();
1024         if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1025             // Once we are set to an Intent with this flag, we count this
1026             // task as having a true root activity.
1027             rootWasReset = true;
1028         }
1029         mUserId = UserHandle.getUserId(info.applicationInfo.uid);
1030         mUserSetupComplete = Settings.Secure.getIntForUser(
1031                 mAtmService.mContext.getContentResolver(), USER_SETUP_COMPLETE, 0, mUserId) != 0;
1032         if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
1033             // If the activity itself has requested auto-remove, then just always do it.
1034             autoRemoveRecents = true;
1035         } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
1036                 == FLAG_ACTIVITY_NEW_DOCUMENT) {
1037             // If the caller has not asked for the document to be retained, then we may
1038             // want to turn on auto-remove, depending on whether the target has set its
1039             // own document launch mode.
1040             if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
1041                 autoRemoveRecents = false;
1042             } else {
1043                 autoRemoveRecents = true;
1044             }
1045         } else {
1046             autoRemoveRecents = false;
1047         }
1048         if (mResizeMode != info.resizeMode) {
1049             mResizeMode = info.resizeMode;
1050             updateTaskDescription();
1051         }
1052         mSupportsPictureInPicture = info.supportsPictureInPicture();
1053 
1054         // Re-adding the task to Recents once updated
1055         if (inRecents) {
1056             mTaskSupervisor.mRecentTasks.remove(this);
1057             mTaskSupervisor.mRecentTasks.add(this);
1058         }
1059     }
1060 
1061     /** Sets the original minimal width and height. */
setMinDimensions(ActivityInfo info)1062     void setMinDimensions(ActivityInfo info) {
1063         if (info != null && info.windowLayout != null) {
1064             mMinWidth = info.windowLayout.minWidth;
1065             mMinHeight = info.windowLayout.minHeight;
1066         } else {
1067             mMinWidth = INVALID_MIN_SIZE;
1068             mMinHeight = INVALID_MIN_SIZE;
1069         }
1070     }
1071 
1072     /**
1073      * Return true if the input activity has the same intent filter as the intent this task
1074      * record is based on (normally the root activity intent).
1075      */
isSameIntentFilter(ActivityRecord r)1076     boolean isSameIntentFilter(ActivityRecord r) {
1077         final Intent intent = new Intent(r.intent);
1078         // Make sure the component are the same if the input activity has the same real activity
1079         // as the one in the task because either one of them could be the alias activity.
1080         if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) {
1081             intent.setComponent(this.intent.getComponent());
1082             // Make sure the package name the same to prevent one of the intent is set while the
1083             // other one is not.
1084             intent.setPackage(this.intent.getPackage());
1085         }
1086         return intent.filterEquals(this.intent);
1087     }
1088 
returnsToHomeRootTask()1089     boolean returnsToHomeRootTask() {
1090         if (inMultiWindowMode() || !hasChild()) return false;
1091         if (intent != null) {
1092             final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
1093             if ((intent.getFlags() & returnHomeFlags) != returnHomeFlags) {
1094                 return false;
1095             }
1096             final Task task = getDisplayArea() != null ? getDisplayArea().getRootHomeTask() : null;
1097             return !(task != null
1098                     && mAtmService.getLockTaskController().isLockTaskModeViolation(task));
1099         }
1100         final Task bottomTask = getBottomMostTask();
1101         return bottomTask != this && bottomTask.returnsToHomeRootTask();
1102     }
1103 
setPrevAffiliate(Task prevAffiliate)1104     void setPrevAffiliate(Task prevAffiliate) {
1105         mPrevAffiliate = prevAffiliate;
1106         mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.mTaskId;
1107     }
1108 
setNextAffiliate(Task nextAffiliate)1109     void setNextAffiliate(Task nextAffiliate) {
1110         mNextAffiliate = nextAffiliate;
1111         mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
1112     }
1113 
1114     @Override
onParentChanged(ConfigurationContainer rawNewParent, ConfigurationContainer rawOldParent)1115     void onParentChanged(ConfigurationContainer rawNewParent, ConfigurationContainer rawOldParent) {
1116         final WindowContainer<?> newParent = (WindowContainer<?>) rawNewParent;
1117         final WindowContainer<?> oldParent = (WindowContainer<?>) rawOldParent;
1118         final DisplayContent display = newParent != null ? newParent.getDisplayContent() : null;
1119         final DisplayContent oldDisplay = oldParent != null ? oldParent.getDisplayContent() : null;
1120 
1121         mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
1122 
1123         if (oldParent != null && newParent == null) {
1124             cleanUpResourcesForDestroy(oldParent);
1125         }
1126 
1127         if (display != null) {
1128             // TODO(b/168037178): Chat with the erosky@ of this code to see if this really makes
1129             //                    sense here...
1130             // Rotations are relative to the display. This means if there are 2 displays rotated
1131             // differently (eg. 2 monitors with one landscape and one portrait), moving a root task
1132             // from one to the other could look like a rotation change. To prevent this
1133             // apparent rotation change (and corresponding bounds rotation), pretend like our
1134             // current rotation is already the same as the new display.
1135             // Note, if Task or related logic ever gets nested, this logic will need
1136             // to move to onConfigurationChanged.
1137             getConfiguration().windowConfiguration.setRotation(
1138                     display.getWindowConfiguration().getRotation());
1139         }
1140 
1141         super.onParentChanged(newParent, oldParent);
1142 
1143         // Call this again after super onParentChanged in-case the surface wasn't created yet
1144         // (happens when the task is first inserted into the hierarchy). It's a no-op if it
1145         // already ran fully within super.onParentChanged
1146         updateTaskOrganizerState();
1147 
1148         // TODO(b/168037178): The check for null display content and setting it to null doesn't
1149         //                    really make sense here...
1150 
1151         // TODO(b/168037178): This is mostly taking care of the case where the stask is removing
1152         //                    from the display, so we should probably consolidate it there instead.
1153 
1154         if (getParent() == null && mDisplayContent != null) {
1155             mDisplayContent = null;
1156             mWmService.mWindowPlacerLocked.requestTraversal();
1157         }
1158 
1159         if (oldParent != null) {
1160             final Task oldParentTask = oldParent.asTask();
1161             if (oldParentTask != null) {
1162                 forAllActivities(oldParentTask::cleanUpActivityReferences);
1163             }
1164 
1165             if (oldParent.inPinnedWindowingMode()
1166                     && (newParent == null || !newParent.inPinnedWindowingMode())) {
1167                 // Notify if a task from the root pinned task is being removed
1168                 // (or moved depending on the mode).
1169                 mRootWindowContainer.notifyActivityPipModeChanged(this, null);
1170             }
1171         }
1172 
1173         if (newParent != null) {
1174             // Surface of Task that will not be organized should be shown by default.
1175             // See Task#showSurfaceOnCreation
1176             if (!mCreatedByOrganizer && !canBeOrganized()) {
1177                 getSyncTransaction().show(mSurfaceControl);
1178             }
1179 
1180             // TODO: Ensure that this is actually necessary here
1181             // Notify the voice session if required
1182             if (voiceSession != null) {
1183                 try {
1184                     voiceSession.taskStarted(intent, mTaskId);
1185                 } catch (RemoteException e) {
1186                 }
1187             }
1188         }
1189 
1190         // First time we are adding the task to the system.
1191         if (oldParent == null && newParent != null) {
1192 
1193             // TODO: Super random place to be doing this, but aligns with what used to be done
1194             // before we unified Task level. Look into if this can be done in a better place.
1195             updateOverrideConfigurationFromLaunchBounds();
1196         }
1197 
1198         // Update task bounds if needed.
1199         adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
1200 
1201         mRootWindowContainer.updateUIDsPresentOnDisplay();
1202 
1203         // Ensure all animations are finished at same time in split-screen mode.
1204         forAllActivities(ActivityRecord::updateAnimatingActivityRegistry);
1205     }
1206 
1207     @Override
1208     @Nullable
getTopResumedActivity()1209     ActivityRecord getTopResumedActivity() {
1210         if (!isLeafTask()) {
1211             for (int i = mChildren.size() - 1; i >= 0; --i) {
1212                 ActivityRecord resumedActivity = mChildren.get(i).asTask().getTopResumedActivity();
1213                 if (resumedActivity != null) {
1214                     return resumedActivity;
1215                 }
1216             }
1217         }
1218 
1219         final ActivityRecord taskResumedActivity = getResumedActivity();
1220         ActivityRecord topResumedActivity = null;
1221         for (int i = mChildren.size() - 1; i >= 0; --i) {
1222             final WindowContainer child = mChildren.get(i);
1223             if (child.asTaskFragment() != null) {
1224                 topResumedActivity = child.asTaskFragment().getTopResumedActivity();
1225             } else if (taskResumedActivity != null
1226                     && child.asActivityRecord() == taskResumedActivity) {
1227                 topResumedActivity = taskResumedActivity;
1228             }
1229             if (topResumedActivity != null) {
1230                 return topResumedActivity;
1231             }
1232         }
1233         return null;
1234     }
1235 
1236     @Override
1237     @Nullable
getTopPausingActivity()1238     ActivityRecord getTopPausingActivity() {
1239         if (!isLeafTask()) {
1240             for (int i = mChildren.size() - 1; i >= 0; --i) {
1241                 ActivityRecord pausingActivity = mChildren.get(i).asTask().getTopPausingActivity();
1242                 if (pausingActivity != null) {
1243                     return pausingActivity;
1244                 }
1245             }
1246         }
1247 
1248         final ActivityRecord taskPausingActivity = getPausingActivity();
1249         ActivityRecord topPausingActivity = null;
1250         for (int i = mChildren.size() - 1; i >= 0; --i) {
1251             final WindowContainer child = mChildren.get(i);
1252             if (child.asTaskFragment() != null) {
1253                 topPausingActivity = child.asTaskFragment().getTopPausingActivity();
1254             } else if (taskPausingActivity != null
1255                     && child.asActivityRecord() == taskPausingActivity) {
1256                 topPausingActivity = taskPausingActivity;
1257             }
1258             if (topPausingActivity != null) {
1259                 return topPausingActivity;
1260             }
1261         }
1262         return null;
1263     }
1264 
updateTaskMovement(boolean toTop, boolean toBottom, int position)1265     void updateTaskMovement(boolean toTop, boolean toBottom, int position) {
1266         EventLogTags.writeWmTaskMoved(mTaskId, getRootTaskId(), getDisplayId(), toTop ? 1 : 0,
1267                 position);
1268         final TaskDisplayArea taskDisplayArea = getDisplayArea();
1269         if (taskDisplayArea != null && isLeafTask()) {
1270             taskDisplayArea.onLeafTaskMoved(this, toTop, toBottom);
1271         }
1272         if (isPersistable) {
1273             mLastTimeMoved = System.currentTimeMillis();
1274         }
1275         if (toTop && inRecents) {
1276             // If task is in recents, ensure it is at the top
1277             mTaskSupervisor.mRecentTasks.add(this);
1278         }
1279     }
1280 
1281     // Close up recents linked list.
closeRecentsChain()1282     private void closeRecentsChain() {
1283         if (mPrevAffiliate != null) {
1284             mPrevAffiliate.setNextAffiliate(mNextAffiliate);
1285         }
1286         if (mNextAffiliate != null) {
1287             mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
1288         }
1289         setPrevAffiliate(null);
1290         setNextAffiliate(null);
1291     }
1292 
removedFromRecents()1293     void removedFromRecents() {
1294         closeRecentsChain();
1295         if (inRecents) {
1296             inRecents = false;
1297             mAtmService.notifyTaskPersisterLocked(this, false);
1298         }
1299 
1300         clearRootProcess();
1301 
1302         mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
1303                 mTaskId, mUserId);
1304     }
1305 
setTaskToAffiliateWith(Task taskToAffiliateWith)1306     void setTaskToAffiliateWith(Task taskToAffiliateWith) {
1307         closeRecentsChain();
1308         mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
1309         // Find the end
1310         while (taskToAffiliateWith.mNextAffiliate != null) {
1311             final Task nextRecents = taskToAffiliateWith.mNextAffiliate;
1312             if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1313                 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1314                         + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1315                 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1316                     nextRecents.setPrevAffiliate(null);
1317                 }
1318                 taskToAffiliateWith.setNextAffiliate(null);
1319                 break;
1320             }
1321             taskToAffiliateWith = nextRecents;
1322         }
1323         taskToAffiliateWith.setNextAffiliate(this);
1324         setPrevAffiliate(taskToAffiliateWith);
1325         setNextAffiliate(null);
1326     }
1327 
1328     /** Returns the intent for the root activity for this task */
getBaseIntent()1329     Intent getBaseIntent() {
1330         if (intent != null) return intent;
1331         if (affinityIntent != null) return affinityIntent;
1332         // Probably a task that contains other tasks, so return the intent for the top task?
1333         final Task topTask = getTopMostTask();
1334         return (topTask != this && topTask != null) ? topTask.getBaseIntent() : null;
1335     }
1336 
1337     /**
1338      * Returns the package name which stands for this task. It is empty string if no activities
1339      * have been added to this task.
1340      */
1341     @NonNull
getBasePackageName()1342     String getBasePackageName() {
1343         final Intent intent = getBaseIntent();
1344         if (intent == null) {
1345             return "";
1346         }
1347         final ComponentName componentName = intent.getComponent();
1348         return componentName != null ? componentName.getPackageName() : "";
1349     }
1350 
1351     /** Returns the first non-finishing activity from the bottom. */
getRootActivity()1352     ActivityRecord getRootActivity() {
1353         // TODO: Figure out why we historical ignore relinquish identity for this case...
1354         return getRootActivity(true /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
1355     }
1356 
getRootActivity(boolean setToBottomIfNone)1357     ActivityRecord getRootActivity(boolean setToBottomIfNone) {
1358         return getRootActivity(false /*ignoreRelinquishIdentity*/, setToBottomIfNone);
1359     }
1360 
getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone)1361     ActivityRecord getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
1362         return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone);
1363     }
1364 
topRunningActivityLocked()1365     ActivityRecord topRunningActivityLocked() {
1366         if (getParent() == null) {
1367             return null;
1368         }
1369         return getActivity(ActivityRecord::canBeTopRunning);
1370     }
1371 
1372     /**
1373      * Return true if any activities in this task belongs to input uid.
1374      */
isUidPresent(int uid)1375     boolean isUidPresent(int uid) {
1376         final PooledPredicate p = PooledLambda.obtainPredicate(
1377                 ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid);
1378         final boolean isUidPresent = getActivity(p) != null;
1379         p.recycle();
1380         return isUidPresent;
1381     }
1382 
topActivityContainsStartingWindow()1383     ActivityRecord topActivityContainsStartingWindow() {
1384         if (getParent() == null) {
1385             return null;
1386         }
1387         return getActivity((r) -> r.getWindow(window ->
1388                 window.getBaseType() == TYPE_APPLICATION_STARTING) != null);
1389     }
1390 
1391     /**
1392      * Reorder the history task so that the passed activity is brought to the front.
1393      * @return whether it was actually moved (vs already being top).
1394      */
moveActivityToFront(ActivityRecord newTop)1395     final boolean moveActivityToFront(ActivityRecord newTop) {
1396         ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Removing and adding activity %s to root task at top "
1397                 + "callers=%s", newTop, Debug.getCallers(4));
1398         final TaskFragment taskFragment = newTop.getTaskFragment();
1399         boolean moved;
1400         if (taskFragment != this) {
1401             if (taskFragment.isEmbedded() && taskFragment.getNonFinishingActivityCount() == 1) {
1402                 taskFragment.mClearedForReorderActivityToFront = true;
1403             }
1404             newTop.reparent(this, POSITION_TOP);
1405             moved = true;
1406             if (taskFragment.isEmbedded()) {
1407                 mAtmService.mWindowOrganizerController.mTaskFragmentOrganizerController
1408                         .onActivityReparentedToTask(newTop);
1409             }
1410         } else {
1411             moved = moveChildToFront(newTop);
1412         }
1413         updateEffectiveIntent();
1414         return moved;
1415     }
1416 
1417     @Override
addChild(WindowContainer child, int index)1418     void addChild(WindowContainer child, int index) {
1419         index = getAdjustedChildPosition(child, index);
1420         super.addChild(child, index);
1421 
1422         ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
1423 
1424         // A rootable task that is now being added to be the child of an organized task. Making
1425         // sure the root task references is keep updated.
1426         if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) {
1427             getDisplayArea().addRootTaskReferenceIfNeeded((Task) child);
1428         }
1429 
1430         // Make sure the list of display UID allowlists is updated
1431         // now that this record is in a new task.
1432         mRootWindowContainer.updateUIDsPresentOnDisplay();
1433 
1434         // Only pass minimum dimensions for pure TaskFragment. Task's minimum dimensions must be
1435         // passed from Task constructor.
1436         final TaskFragment childTaskFrag = child.asTaskFragment();
1437         if (childTaskFrag != null && childTaskFrag.asTask() == null) {
1438             childTaskFrag.setMinDimensions(mMinWidth, mMinHeight);
1439 
1440             // The starting window should keep covering its task when a pure TaskFragment is added
1441             // because its bounds may not fill the task.
1442             final ActivityRecord top = getTopMostActivity();
1443             if (top != null) {
1444                 top.associateStartingWindowWithTaskIfNeeded();
1445             }
1446         }
1447     }
1448 
1449     /** Called when an {@link ActivityRecord} is added as a descendant */
onDescendantActivityAdded(boolean hadActivity, int activityType, ActivityRecord r)1450     void onDescendantActivityAdded(boolean hadActivity, int activityType, ActivityRecord r) {
1451         warnForNonLeafTask("onDescendantActivityAdded");
1452 
1453         // Only set this based on the first activity
1454         if (!hadActivity) {
1455             int activityOverrideType =
1456                     r.getRequestedOverrideConfiguration().windowConfiguration.getActivityType();
1457             if (activityOverrideType == ACTIVITY_TYPE_UNDEFINED) {
1458                 // Normally non-standard activity type for the activity record will be set when the
1459                 // object is created, however we delay setting the standard application type until
1460                 // this point so that the task can set the type for additional activities added in
1461                 // the else condition below.
1462                 activityOverrideType = activityType != ACTIVITY_TYPE_UNDEFINED ? activityType
1463                         : ACTIVITY_TYPE_STANDARD;
1464                 // Set the Activity's requestedOverrideConfiguration directly to reduce
1465                 // WC#onConfigurationChanged calls since it will be called while setting the
1466                 // Task's activity type below.
1467                 r.getRequestedOverrideConfiguration().windowConfiguration.setActivityType(
1468                         activityOverrideType);
1469             }
1470             setActivityType(activityOverrideType);
1471             isPersistable = r.isPersistable();
1472             mCallingUid = r.launchedFromUid;
1473             mCallingPackage = r.launchedFromPackage;
1474             mCallingFeatureId = r.launchedFromFeatureId;
1475             // Clamp to [1, max].
1476             maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1477                     ActivityTaskManager.getMaxAppRecentsLimitStatic());
1478         } else {
1479             // Otherwise make all added activities match this one.
1480             r.setActivityType(activityType);
1481         }
1482 
1483         updateEffectiveIntent();
1484     }
1485 
1486     @Override
removeChild(WindowContainer child)1487     void removeChild(WindowContainer child) {
1488         removeChild(child, "removeChild");
1489     }
1490 
removeChild(WindowContainer r, String reason)1491     void removeChild(WindowContainer r, String reason) {
1492         // A rootable child task that is now being removed from an organized task. Making sure
1493         // the root task references is keep updated.
1494         if (mCreatedByOrganizer && r.asTask() != null) {
1495             getDisplayArea().removeRootTaskReferenceIfNeeded((Task) r);
1496         }
1497         if (!mChildren.contains(r)) {
1498             Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
1499             return;
1500         }
1501 
1502         if (DEBUG_TASK_MOVEMENT) {
1503             Slog.d(TAG_WM, "removeChild: child=" + r + " reason=" + reason);
1504         }
1505         super.removeChild(r, false /* removeSelfIfPossible */);
1506 
1507         if (inPinnedWindowingMode()) {
1508             // We normally notify listeners of task stack changes on pause, however root pinned task
1509             // activities are normally in the paused state so no notification will be sent there
1510             // before the activity is removed. We send it here so instead.
1511             mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
1512         }
1513 
1514         if (hasChild()) {
1515             updateEffectiveIntent();
1516 
1517             // The following block can be executed multiple times if there is more than one overlay.
1518             // {@link ActivityTaskSupervisor#removeTaskByIdLocked} handles this by reverse lookup
1519             // of the task by id and exiting early if not found.
1520             if (onlyHasTaskOverlayActivities(true /*includeFinishing*/)) {
1521                 // When destroying a task, tell the supervisor to remove it so that any activity it
1522                 // has can be cleaned up correctly. This is currently the only place where we remove
1523                 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
1524                 // state into removeChild(), we just clear the task here before the other residual
1525                 // work.
1526                 // TODO: If the callers to removeChild() changes such that we have multiple places
1527                 //       where we are destroying the task, move this back into removeChild()
1528                 mTaskSupervisor.removeTask(this, false /* killProcess */,
1529                         !REMOVE_FROM_RECENTS, reason);
1530             }
1531         } else if (!mReuseTask && shouldRemoveSelfOnLastChildRemoval()) {
1532             reason += ", last child = " + r + " in " + this;
1533             removeIfPossible(reason);
1534         }
1535     }
1536 
1537     /**
1538      * @return whether or not there are ONLY task overlay activities in the task.
1539      *         If {@param includeFinishing} is set, then don't ignore finishing activities in the
1540      *         check. If there are no task overlay activities, this call returns false.
1541      */
onlyHasTaskOverlayActivities(boolean includeFinishing)1542     boolean onlyHasTaskOverlayActivities(boolean includeFinishing) {
1543         int count = 0;
1544         for (int i = getChildCount() - 1; i >= 0; i--) {
1545             final ActivityRecord r = getChildAt(i).asActivityRecord();
1546             if (r == null) {
1547                 // Has a child that is other than Activity.
1548                 return false;
1549             }
1550             if (!includeFinishing && r.finishing) {
1551                 continue;
1552             }
1553             if (!r.isTaskOverlay()) {
1554                 return false;
1555             }
1556             count++;
1557         }
1558         return count > 0;
1559     }
1560 
autoRemoveFromRecents(TaskFragment oldParentFragment)1561     private boolean autoRemoveFromRecents(TaskFragment oldParentFragment) {
1562         // We will automatically remove the task either if it has explicitly asked for
1563         // this, or it is empty and has never contained an activity that got shown to
1564         // the user, or it was being embedded in another Task.
1565         return autoRemoveRecents || (!hasChild() && !getHasBeenVisible()
1566                 || (oldParentFragment != null && oldParentFragment.isEmbedded()));
1567     }
1568 
clearPinnedTaskIfNeed()1569     private void clearPinnedTaskIfNeed() {
1570         // The original task is to be removed, try remove also the pinned task.
1571         if (mChildPipActivity != null && mChildPipActivity.getTask() != null) {
1572             mTaskSupervisor.removeRootTask(mChildPipActivity.getTask());
1573         }
1574     }
1575 
1576     /** Completely remove all activities associated with an existing task. */
removeActivities(String reason, boolean excludingTaskOverlay)1577     void removeActivities(String reason, boolean excludingTaskOverlay) {
1578         clearPinnedTaskIfNeed();
1579         // Broken down into to cases to avoid object create due to capturing mStack.
1580         if (getRootTask() == null) {
1581             forAllActivities((r) -> {
1582                 if (r.finishing || (excludingTaskOverlay && r.isTaskOverlay())) {
1583                     return;
1584                 }
1585                 // Task was restored from persistent storage.
1586                 r.takeFromHistory();
1587                 removeChild(r, reason);
1588             });
1589         } else {
1590             final ArrayList<ActivityRecord> finishingActivities = new ArrayList<>();
1591             forAllActivities(r -> {
1592                 if (r.finishing || (excludingTaskOverlay && r.isTaskOverlay())) {
1593                     return;
1594                 }
1595                 finishingActivities.add(r);
1596             });
1597 
1598             // Finish or destroy apps from the bottom to ensure that all the other activity have
1599             // been finished and the top task in another task gets resumed when a top activity is
1600             // removed. Otherwise, the next top activity could be started while the top activity
1601             // is removed, which is not necessary since the next top activity is on the same Task
1602             // and should also be removed.
1603             for (int i = finishingActivities.size() - 1; i >= 0; i--) {
1604                 final ActivityRecord r = finishingActivities.get(i);
1605 
1606                 // Prevent the transition from being executed too early if the top activity is
1607                 // resumed but the mVisibleRequested of any other activity is true, the transition
1608                 // should wait until next activity resumed.
1609                 if (r.isState(RESUMED) || (r.isVisible()
1610                         && !mDisplayContent.mAppTransition.containsTransitRequest(TRANSIT_CLOSE))) {
1611                     r.finishIfPossible(reason, false /* oomAdj */);
1612                 } else {
1613                     r.destroyIfPossible(reason);
1614                 }
1615             }
1616         }
1617     }
1618 
1619     /**
1620      * Completely remove all activities associated with an existing task.
1621      */
performClearTaskForReuse(boolean excludingTaskOverlay)1622     void performClearTaskForReuse(boolean excludingTaskOverlay) {
1623         mReuseTask = true;
1624         mTaskSupervisor.beginDeferResume();
1625         try {
1626             removeActivities("clear-task-all", excludingTaskOverlay);
1627         } finally {
1628             mTaskSupervisor.endDeferResume();
1629             mReuseTask = false;
1630         }
1631     }
1632 
performClearTop(ActivityRecord newR, int launchFlags, int[] finishCount)1633     ActivityRecord performClearTop(ActivityRecord newR, int launchFlags, int[] finishCount) {
1634         // The task should be preserved for putting new activity in case the last activity is
1635         // finished if it is normal launch mode and not single top ("clear-task-top").
1636         mReuseTask = true;
1637         mTaskSupervisor.beginDeferResume();
1638         final ActivityRecord result;
1639         try {
1640             result = clearTopActivities(newR, launchFlags, finishCount);
1641         } finally {
1642             mTaskSupervisor.endDeferResume();
1643             mReuseTask = false;
1644         }
1645         return result;
1646     }
1647 
1648     /**
1649      * Perform clear operation as requested by
1650      * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1651      * root task to the given task, then look for
1652      * an instance of that activity in the root task and, if found, finish all
1653      * activities on top of it and return the instance.
1654      *
1655      * @param newR Description of the new activity being started.
1656      * @param finishCount 1-element array that will be populated with the number of activities
1657      *                    that have been finished.
1658      * @return Returns the existing activity in the task that performs the clear-top operation,
1659      * or {@code null} if none was found.
1660      */
clearTopActivities(ActivityRecord newR, int launchFlags, int[] finishCount)1661     private ActivityRecord clearTopActivities(ActivityRecord newR, int launchFlags,
1662             int[] finishCount) {
1663         final ActivityRecord r = findActivityInHistory(newR.mActivityComponent, newR.mUserId);
1664         if (r == null) return null;
1665 
1666         final PooledPredicate f = PooledLambda.obtainPredicate(
1667                 (ActivityRecord ar, ActivityRecord boundaryActivity) ->
1668                         finishActivityAbove(ar, boundaryActivity, finishCount),
1669                 PooledLambda.__(ActivityRecord.class), r);
1670         forAllActivities(f);
1671         f.recycle();
1672 
1673         // Finally, if this is a normal launch mode (that is, not expecting onNewIntent()), then we
1674         // will finish the current instance of the activity so a new fresh one can be started.
1675         if (r.launchMode == ActivityInfo.LAUNCH_MULTIPLE
1676                 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1677                 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
1678             if (!r.finishing) {
1679                 r.finishIfPossible("clear-task-top", false /* oomAdj */);
1680             }
1681         }
1682 
1683         return r;
1684     }
1685 
finishActivityAbove(ActivityRecord r, ActivityRecord boundaryActivity, @NonNull int[] finishCount)1686     private static boolean finishActivityAbove(ActivityRecord r, ActivityRecord boundaryActivity,
1687             @NonNull int[] finishCount) {
1688         // Stop operation once we reach the boundary activity.
1689         if (r == boundaryActivity) return true;
1690 
1691         if (!r.finishing && !r.isTaskOverlay()) {
1692             final ActivityOptions opts = r.getOptions();
1693             if (opts != null) {
1694                 r.clearOptionsAnimation();
1695                 // TODO: Why is this updating the boundary activity vs. the current activity???
1696                 boundaryActivity.updateOptionsLocked(opts);
1697             }
1698             finishCount[0] += 1;
1699             r.finishIfPossible("clear-task-stack", false /* oomAdj */);
1700         }
1701 
1702         return false;
1703     }
1704 
lockTaskAuthToString()1705     String lockTaskAuthToString() {
1706         switch (mLockTaskAuth) {
1707             case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1708             case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1709             case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1710             case LOCK_TASK_AUTH_ALLOWLISTED: return "LOCK_TASK_AUTH_ALLOWLISTED";
1711             case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
1712             default: return "unknown=" + mLockTaskAuth;
1713         }
1714     }
1715 
setLockTaskAuth()1716     void setLockTaskAuth() {
1717         setLockTaskAuth(getRootActivity());
1718     }
1719 
setLockTaskAuth(@ullable ActivityRecord r)1720     private void setLockTaskAuth(@Nullable ActivityRecord r) {
1721         mLockTaskAuth = mAtmService.getLockTaskController().getLockTaskAuth(r, this);
1722         ProtoLog.d(WM_DEBUG_LOCKTASK, "setLockTaskAuth: task=%s mLockTaskAuth=%s", this,
1723                 lockTaskAuthToString());
1724     }
1725 
supportsFreeform()1726     boolean supportsFreeform() {
1727         return supportsFreeformInDisplayArea(getDisplayArea());
1728     }
1729 
1730     /**
1731      * @return whether this task supports freeform multi-window if it is in the given
1732      *         {@link TaskDisplayArea}.
1733      */
supportsFreeformInDisplayArea(@ullable TaskDisplayArea tda)1734     boolean supportsFreeformInDisplayArea(@Nullable TaskDisplayArea tda) {
1735         return mAtmService.mSupportsFreeformWindowManagement
1736                 && supportsMultiWindowInDisplayArea(tda);
1737     }
1738 
1739     /**
1740      * Check whether this task can be launched on the specified display.
1741      *
1742      * @param displayId Target display id.
1743      * @return {@code true} if either it is the default display or this activity can be put on a
1744      *         secondary display.
1745      */
canBeLaunchedOnDisplay(int displayId)1746     boolean canBeLaunchedOnDisplay(int displayId) {
1747         return mTaskSupervisor.canPlaceEntityOnDisplay(displayId,
1748                 -1 /* don't check PID */, -1 /* don't check UID */, this);
1749     }
1750 
1751     /**
1752      * Check that a given bounds matches the application requested orientation.
1753      *
1754      * @param bounds The bounds to be tested.
1755      * @return True if the requested bounds are okay for a resizing request.
1756      */
canResizeToBounds(Rect bounds)1757     private boolean canResizeToBounds(Rect bounds) {
1758         if (bounds == null || !inFreeformWindowingMode()) {
1759             // Note: If not on the freeform workspace, we ignore the bounds.
1760             return true;
1761         }
1762         final boolean landscape = bounds.width() > bounds.height();
1763         final Rect configBounds = getRequestedOverrideBounds();
1764         if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
1765             return configBounds.isEmpty()
1766                     || landscape == (configBounds.width() > configBounds.height());
1767         }
1768         return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1769                 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1770     }
1771 
1772     /**
1773      * @return {@code true} if the task is being cleared for the purposes of being reused.
1774      */
isClearingToReuseTask()1775     boolean isClearingToReuseTask() {
1776         return mReuseTask;
1777     }
1778 
1779     /**
1780      * Find the activity in the history task within the given task.  Returns
1781      * the index within the history at which it's found, or < 0 if not found.
1782      */
findActivityInHistory(ComponentName component, int userId)1783     ActivityRecord findActivityInHistory(ComponentName component, int userId) {
1784         final PooledPredicate p = PooledLambda.obtainPredicate(Task::matchesActivityInHistory,
1785                 PooledLambda.__(ActivityRecord.class), component, userId);
1786         final ActivityRecord r = getActivity(p);
1787         p.recycle();
1788         return r;
1789     }
1790 
matchesActivityInHistory( ActivityRecord r, ComponentName activityComponent, int userId)1791     private static boolean matchesActivityInHistory(
1792             ActivityRecord r, ComponentName activityComponent, int userId) {
1793         return !r.finishing && r.mActivityComponent.equals(activityComponent)
1794                 && r.mUserId == userId;
1795     }
1796 
1797     /** Updates the last task description values. */
updateTaskDescription()1798     void updateTaskDescription() {
1799         final ActivityRecord root = getRootActivity(true);
1800         if (root == null) return;
1801 
1802         final TaskDescription taskDescription = new TaskDescription();
1803         final PooledPredicate f = PooledLambda.obtainPredicate(
1804                 Task::setTaskDescriptionFromActivityAboveRoot,
1805                 PooledLambda.__(ActivityRecord.class), root, taskDescription);
1806         forAllActivities(f);
1807         f.recycle();
1808         taskDescription.setResizeMode(mResizeMode);
1809         taskDescription.setMinWidth(mMinWidth);
1810         taskDescription.setMinHeight(mMinHeight);
1811         setTaskDescription(taskDescription);
1812         mAtmService.getTaskChangeNotificationController().notifyTaskDescriptionChanged(
1813                 getTaskInfo());
1814 
1815         final WindowContainer parent = getParent();
1816         if (parent != null) {
1817             final Task t = parent.asTask();
1818             if (t != null) {
1819                 t.updateTaskDescription();
1820             }
1821         }
1822 
1823         dispatchTaskInfoChangedIfNeeded(false /* force */);
1824     }
1825 
setTaskDescriptionFromActivityAboveRoot( ActivityRecord r, ActivityRecord root, TaskDescription td)1826     private static boolean setTaskDescriptionFromActivityAboveRoot(
1827             ActivityRecord r, ActivityRecord root, TaskDescription td) {
1828         if (!r.isTaskOverlay() && r.taskDescription != null) {
1829             final TaskDescription atd = r.taskDescription;
1830             if (td.getLabel() == null) {
1831                 td.setLabel(atd.getLabel());
1832             }
1833             if (td.getRawIcon() == null) {
1834                 td.setIcon(atd.getRawIcon());
1835             }
1836             if (td.getIconFilename() == null) {
1837                 td.setIconFilename(atd.getIconFilename());
1838             }
1839             if (td.getPrimaryColor() == 0) {
1840                 td.setPrimaryColor(atd.getPrimaryColor());
1841             }
1842             if (td.getBackgroundColor() == 0) {
1843                 td.setBackgroundColor(atd.getBackgroundColor());
1844             }
1845             if (td.getStatusBarColor() == 0) {
1846                 td.setStatusBarColor(atd.getStatusBarColor());
1847                 td.setEnsureStatusBarContrastWhenTransparent(
1848                         atd.getEnsureStatusBarContrastWhenTransparent());
1849             }
1850             if (td.getStatusBarAppearance() == 0) {
1851                 td.setStatusBarAppearance(atd.getStatusBarAppearance());
1852             }
1853             if (td.getNavigationBarColor() == 0) {
1854                 td.setNavigationBarColor(atd.getNavigationBarColor());
1855                 td.setEnsureNavigationBarContrastWhenTransparent(
1856                         atd.getEnsureNavigationBarContrastWhenTransparent());
1857             }
1858             if (td.getBackgroundColorFloating() == 0) {
1859                 td.setBackgroundColorFloating(atd.getBackgroundColorFloating());
1860             }
1861         }
1862 
1863         // End search once we get to root.
1864         return r == root;
1865     }
1866 
1867     // TODO (AM refactor): Invoke automatically when there is a change in children
1868     @VisibleForTesting
updateEffectiveIntent()1869     void updateEffectiveIntent() {
1870         final ActivityRecord root = getRootActivity(true /*setToBottomIfNone*/);
1871         if (root != null) {
1872             setIntent(root);
1873             // Update the task description when the activities change
1874             updateTaskDescription();
1875         }
1876     }
1877 
setLastNonFullscreenBounds(Rect bounds)1878     void setLastNonFullscreenBounds(Rect bounds) {
1879         if (mLastNonFullscreenBounds == null) {
1880             mLastNonFullscreenBounds = new Rect(bounds);
1881         } else {
1882             mLastNonFullscreenBounds.set(bounds);
1883         }
1884     }
1885 
onConfigurationChangedInner(Configuration newParentConfig)1886     private void onConfigurationChangedInner(Configuration newParentConfig) {
1887         // Check if the new configuration supports persistent bounds (eg. is Freeform) and if so
1888         // restore the last recorded non-fullscreen bounds.
1889         final boolean prevPersistTaskBounds = getWindowConfiguration().persistTaskBounds();
1890         boolean nextPersistTaskBounds =
1891                 getRequestedOverrideConfiguration().windowConfiguration.persistTaskBounds();
1892         if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_UNDEFINED) {
1893             nextPersistTaskBounds = newParentConfig.windowConfiguration.persistTaskBounds();
1894         }
1895         // Only restore to the last non-fullscreen bounds when the requested override bounds
1896         // have not been explicitly set already.
1897         nextPersistTaskBounds &=
1898                 (getRequestedOverrideConfiguration().windowConfiguration.getBounds() == null
1899                 || getRequestedOverrideConfiguration().windowConfiguration.getBounds().isEmpty());
1900         if (!prevPersistTaskBounds && nextPersistTaskBounds
1901                 && mLastNonFullscreenBounds != null && !mLastNonFullscreenBounds.isEmpty()) {
1902             // Bypass onRequestedOverrideConfigurationChanged here to avoid infinite loop.
1903             getRequestedOverrideConfiguration().windowConfiguration
1904                     .setBounds(mLastNonFullscreenBounds);
1905         }
1906 
1907         final int prevWinMode = getWindowingMode();
1908         mTmpPrevBounds.set(getBounds());
1909         final boolean wasInMultiWindowMode = inMultiWindowMode();
1910         final boolean wasInPictureInPicture = inPinnedWindowingMode();
1911         super.onConfigurationChanged(newParentConfig);
1912         // Only need to update surface size here since the super method will handle updating
1913         // surface position.
1914         updateSurfaceSize(getSyncTransaction());
1915 
1916         final boolean pipChanging = wasInPictureInPicture != inPinnedWindowingMode();
1917         if (pipChanging) {
1918             mTaskSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, getRootTask());
1919         } else if (wasInMultiWindowMode != inMultiWindowMode()) {
1920             mTaskSupervisor.scheduleUpdateMultiWindowMode(this);
1921         }
1922 
1923         if (shouldStartChangeTransition(prevWinMode, mTmpPrevBounds)) {
1924             initializeChangeTransition(mTmpPrevBounds);
1925         }
1926 
1927         // If the configuration supports persistent bounds (eg. Freeform), keep track of the
1928         // current (non-fullscreen) bounds for persistence.
1929         if (getWindowConfiguration().persistTaskBounds()) {
1930             final Rect currentBounds = getRequestedOverrideBounds();
1931             if (!currentBounds.isEmpty()) {
1932                 setLastNonFullscreenBounds(currentBounds);
1933             }
1934         }
1935 
1936         if (pipChanging && wasInPictureInPicture
1937                 && !mTransitionController.isShellTransitionsEnabled()) {
1938             // If the top activity is changing from PiP to fullscreen with fixed rotation,
1939             // clear the crop and rotation matrix of task because fixed rotation will handle
1940             // the transformation on activity level. This also avoids flickering caused by the
1941             // latency of fullscreen task organizer configuring the surface.
1942             final ActivityRecord r = topRunningActivity();
1943             if (r != null && mDisplayContent.isFixedRotationLaunchingApp(r)) {
1944                 resetSurfaceControlTransforms();
1945             }
1946         }
1947 
1948         saveLaunchingStateIfNeeded();
1949         final boolean taskOrgChanged = updateTaskOrganizerState();
1950         if (taskOrgChanged) {
1951             updateSurfacePosition(getSyncTransaction());
1952             if (!isOrganized()) {
1953                 // Surface-size update was skipped before (since internally it no-ops if
1954                 // isOrganized() is true); however, now that this is not organized, the surface
1955                 // size needs to be updated by WM.
1956                 updateSurfaceSize(getSyncTransaction());
1957             }
1958         }
1959         // If the task organizer has changed, then it will already be receiving taskAppeared with
1960         // the latest task-info thus the task-info won't have changed.
1961         if (!taskOrgChanged) {
1962             dispatchTaskInfoChangedIfNeeded(false /* force */);
1963         }
1964     }
1965 
1966     @Override
onConfigurationChanged(Configuration newParentConfig)1967     public void onConfigurationChanged(Configuration newParentConfig) {
1968         if (mDisplayContent != null
1969                 && mDisplayContent.mPinnedTaskController.isFreezingTaskConfig(this)) {
1970             // It happens when animating from fullscreen to PiP with orientation change. Because
1971             // the activity in this pinned task is in fullscreen windowing mode (see
1972             // RootWindowContainer#moveActivityToPinnedRootTask) and the activity will be set to
1973             // pinned mode after the animation is done, the configuration change by orientation
1974             // change is just an intermediate state that should be ignored to avoid flickering.
1975             return;
1976         }
1977         // Calling Task#onConfigurationChanged() for leaf task since the ops in this method are
1978         // particularly for root tasks, like preventing bounds changes when inheriting certain
1979         // windowing mode.
1980         if (!isRootTask()) {
1981             onConfigurationChangedInner(newParentConfig);
1982             return;
1983         }
1984 
1985         final int prevWindowingMode = getWindowingMode();
1986         final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
1987         final int prevRotation = getWindowConfiguration().getRotation();
1988         final Rect newBounds = mTmpRect;
1989         // Initialize the new bounds by previous bounds as the input and output for calculating
1990         // override bounds in pinned (pip) or split-screen mode.
1991         getBounds(newBounds);
1992 
1993         onConfigurationChangedInner(newParentConfig);
1994 
1995         final TaskDisplayArea taskDisplayArea = getDisplayArea();
1996         if (taskDisplayArea == null) {
1997             return;
1998         }
1999 
2000         if (prevWindowingMode != getWindowingMode()) {
2001             taskDisplayArea.onRootTaskWindowingModeChanged(this);
2002         }
2003 
2004         if (!isOrganized() && !getRequestedOverrideBounds().isEmpty() && mDisplayContent != null) {
2005             // If the parent (display) has rotated, rotate our bounds to best-fit where their
2006             // bounds were on the pre-rotated display.
2007             final int newRotation = getWindowConfiguration().getRotation();
2008             final boolean rotationChanged = prevRotation != newRotation;
2009             if (rotationChanged) {
2010                 mDisplayContent.rotateBounds(prevRotation, newRotation, newBounds);
2011                 setBounds(newBounds);
2012             }
2013         }
2014 
2015         if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
2016             // Since always on top is only on when the root task is freeform or pinned, the state
2017             // can be toggled when the windowing mode changes. We must make sure the root task is
2018             // placed properly when always on top state changes.
2019             taskDisplayArea.positionChildAt(POSITION_TOP, this, false /* includingParents */);
2020         }
2021     }
2022 
resolveLeafTaskOnlyOverrideConfigs(Configuration newParentConfig, Rect previousBounds)2023     void resolveLeafTaskOnlyOverrideConfigs(Configuration newParentConfig, Rect previousBounds) {
2024         if (!isLeafTask()) {
2025             return;
2026         }
2027 
2028         int windowingMode =
2029                 getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
2030         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2031             windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
2032         }
2033         // Commit the resolved windowing mode so the canSpecifyOrientation won't get the old
2034         // mode that may cause the bounds to be miscalculated, e.g. letterboxed.
2035         getConfiguration().windowConfiguration.setWindowingMode(windowingMode);
2036         Rect outOverrideBounds = getResolvedOverrideConfiguration().windowConfiguration.getBounds();
2037 
2038         if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
2039             if (!mCreatedByOrganizer) {
2040                 // Use empty bounds to indicate "fill parent".
2041                 outOverrideBounds.setEmpty();
2042             }
2043             // The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
2044             // the parent or display is smaller than the size, the content may be cropped.
2045             return;
2046         }
2047 
2048         adjustForMinimalTaskDimensions(outOverrideBounds, previousBounds, newParentConfig);
2049         if (windowingMode == WINDOWING_MODE_FREEFORM) {
2050             computeFreeformBounds(outOverrideBounds, newParentConfig);
2051             return;
2052         }
2053     }
2054 
adjustForMinimalTaskDimensions(@onNull Rect bounds, @NonNull Rect previousBounds, @NonNull Configuration parentConfig)2055     void adjustForMinimalTaskDimensions(@NonNull Rect bounds, @NonNull Rect previousBounds,
2056             @NonNull Configuration parentConfig) {
2057         int minWidth = mMinWidth;
2058         int minHeight = mMinHeight;
2059         // If the task has no requested minimal size, we'd like to enforce a minimal size
2060         // so that the user can not render the task fragment too small to manipulate. We don't need
2061         // to do this for the root pinned task as the bounds are controlled by the system.
2062         if (!inPinnedWindowingMode()) {
2063             // Use Display specific min sizes when there is one associated with this Task.
2064             final int defaultMinSizeDp = mDisplayContent == null
2065                     ? DEFAULT_MIN_TASK_SIZE_DP : mDisplayContent.mMinSizeOfResizeableTaskDp;
2066             final float density = (float) parentConfig.densityDpi / DisplayMetrics.DENSITY_DEFAULT;
2067             final int defaultMinSize = (int) (defaultMinSizeDp * density);
2068 
2069             if (minWidth == INVALID_MIN_SIZE) {
2070                 minWidth = defaultMinSize;
2071             }
2072             if (minHeight == INVALID_MIN_SIZE) {
2073                 minHeight = defaultMinSize;
2074             }
2075         }
2076         if (bounds.isEmpty()) {
2077             // If inheriting parent bounds, check if parent bounds adhere to minimum size. If they
2078             // do, we can just skip.
2079             final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
2080             if (parentBounds.width() >= minWidth && parentBounds.height() >= minHeight) {
2081                 return;
2082             }
2083             bounds.set(parentBounds);
2084         }
2085         final boolean adjustWidth = minWidth > bounds.width();
2086         final boolean adjustHeight = minHeight > bounds.height();
2087         if (!(adjustWidth || adjustHeight)) {
2088             return;
2089         }
2090 
2091         if (adjustWidth) {
2092             if (!previousBounds.isEmpty() && bounds.right == previousBounds.right) {
2093                 bounds.left = bounds.right - minWidth;
2094             } else {
2095                 // Either left bounds match, or neither match, or the previous bounds were
2096                 // fullscreen and we default to keeping left.
2097                 bounds.right = bounds.left + minWidth;
2098             }
2099         }
2100         if (adjustHeight) {
2101             if (!previousBounds.isEmpty() && bounds.bottom == previousBounds.bottom) {
2102                 bounds.top = bounds.bottom - minHeight;
2103             } else {
2104                 // Either top bounds match, or neither match, or the previous bounds were
2105                 // fullscreen and we default to keeping top.
2106                 bounds.bottom = bounds.top + minHeight;
2107             }
2108         }
2109     }
2110 
2111     /** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FREEFORM}. */
computeFreeformBounds(@onNull Rect outBounds, @NonNull Configuration newParentConfig)2112     private void computeFreeformBounds(@NonNull Rect outBounds,
2113             @NonNull Configuration newParentConfig) {
2114         // by policy, make sure the window remains within parent somewhere
2115         final float density =
2116                 ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;
2117         final Rect parentBounds =
2118                 new Rect(newParentConfig.windowConfiguration.getBounds());
2119         final DisplayContent display = getDisplayContent();
2120         if (display != null) {
2121             // If a freeform window moves below system bar, there is no way to move it again
2122             // by touch. Because its caption is covered by system bar. So we exclude them
2123             // from root task bounds. and then caption will be shown inside stable area.
2124             final Rect stableBounds = new Rect();
2125             display.getStableRect(stableBounds);
2126             parentBounds.intersect(stableBounds);
2127         }
2128 
2129         fitWithinBounds(outBounds, parentBounds,
2130                 (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP),
2131                 (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP));
2132 
2133         // Prevent to overlap caption with stable insets.
2134         final int offsetTop = parentBounds.top - outBounds.top;
2135         if (offsetTop > 0) {
2136             outBounds.offset(0, offsetTop);
2137         }
2138     }
2139 
2140     /**
2141      * Adjusts bounds to stay within root task bounds.
2142      *
2143      * Since bounds might be outside of root task bounds, this method tries to move the bounds in
2144      * a way that keep them unchanged, but be contained within the root task bounds.
2145      *
2146      * @param bounds Bounds to be adjusted.
2147      * @param rootTaskBounds Bounds within which the other bounds should remain.
2148      * @param overlapPxX The amount of px required to be visible in the X dimension.
2149      * @param overlapPxY The amount of px required to be visible in the Y dimension.
2150      */
fitWithinBounds(Rect bounds, Rect rootTaskBounds, int overlapPxX, int overlapPxY)2151     private static void fitWithinBounds(Rect bounds, Rect rootTaskBounds, int overlapPxX,
2152             int overlapPxY) {
2153         if (rootTaskBounds == null || rootTaskBounds.isEmpty() || rootTaskBounds.contains(bounds)) {
2154             return;
2155         }
2156 
2157         // For each side of the parent (eg. left), check if the opposing side of the window (eg.
2158         // right) is at least overlap pixels away. If less, offset the window by that difference.
2159         int horizontalDiff = 0;
2160         // If window is smaller than overlap, use it's smallest dimension instead
2161         int overlapLR = Math.min(overlapPxX, bounds.width());
2162         if (bounds.right < (rootTaskBounds.left + overlapLR)) {
2163             horizontalDiff = overlapLR - (bounds.right - rootTaskBounds.left);
2164         } else if (bounds.left > (rootTaskBounds.right - overlapLR)) {
2165             horizontalDiff = -(overlapLR - (rootTaskBounds.right - bounds.left));
2166         }
2167         int verticalDiff = 0;
2168         int overlapTB = Math.min(overlapPxY, bounds.width());
2169         if (bounds.bottom < (rootTaskBounds.top + overlapTB)) {
2170             verticalDiff = overlapTB - (bounds.bottom - rootTaskBounds.top);
2171         } else if (bounds.top > (rootTaskBounds.bottom - overlapTB)) {
2172             verticalDiff = -(overlapTB - (rootTaskBounds.bottom - bounds.top));
2173         }
2174         bounds.offset(horizontalDiff, verticalDiff);
2175     }
2176 
shouldStartChangeTransition(int prevWinMode, @NonNull Rect prevBounds)2177     private boolean shouldStartChangeTransition(int prevWinMode, @NonNull Rect prevBounds) {
2178         if (!(isLeafTask() || mCreatedByOrganizer) || !canStartChangeTransition()) {
2179             return false;
2180         }
2181         final int newWinMode = getWindowingMode();
2182         if (mTransitionController.inTransition(this)) {
2183             final Rect newBounds = getConfiguration().windowConfiguration.getBounds();
2184             return prevWinMode != newWinMode || prevBounds.width() != newBounds.width()
2185                     || prevBounds.height() != newBounds.height();
2186         }
2187         // Only do an animation into and out-of freeform mode for now. Other mode
2188         // transition animations are currently handled by system-ui.
2189         return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
2190     }
2191 
2192     @Override
migrateToNewSurfaceControl(SurfaceControl.Transaction t)2193     void migrateToNewSurfaceControl(SurfaceControl.Transaction t) {
2194         super.migrateToNewSurfaceControl(t);
2195         mLastSurfaceSize.x = 0;
2196         mLastSurfaceSize.y = 0;
2197         updateSurfaceSize(t);
2198     }
2199 
updateSurfaceSize(SurfaceControl.Transaction transaction)2200     void updateSurfaceSize(SurfaceControl.Transaction transaction) {
2201         if (mSurfaceControl == null || isOrganized()) {
2202             return;
2203         }
2204 
2205         // Apply crop to root tasks only and clear the crops of the descendant tasks.
2206         int width = 0;
2207         int height = 0;
2208         if (isRootTask()) {
2209             final Rect taskBounds = getBounds();
2210             width = taskBounds.width();
2211             height = taskBounds.height();
2212         }
2213         if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
2214             return;
2215         }
2216         transaction.setWindowCrop(mSurfaceControl, width, height);
2217         mLastSurfaceSize.set(width, height);
2218     }
2219 
2220     @VisibleForTesting
getLastSurfaceSize()2221     Point getLastSurfaceSize() {
2222         return mLastSurfaceSize;
2223     }
2224 
2225     @VisibleForTesting
isInChangeTransition()2226     boolean isInChangeTransition() {
2227         return mSurfaceFreezer.hasLeash() || AppTransition.isChangeTransitOld(mTransit);
2228     }
2229 
2230     @Override
getFreezeSnapshotTarget()2231     public SurfaceControl getFreezeSnapshotTarget() {
2232         if (!mDisplayContent.mAppTransition.containsTransitRequest(TRANSIT_CHANGE)) {
2233             return null;
2234         }
2235         // Skip creating snapshot if this transition is controlled by a remote animator which
2236         // doesn't need it.
2237         final ArraySet<Integer> activityTypes = new ArraySet<>();
2238         activityTypes.add(getActivityType());
2239         final RemoteAnimationAdapter adapter =
2240                 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
2241                         this, TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE, activityTypes);
2242         if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
2243             return null;
2244         }
2245         return getSurfaceControl();
2246     }
2247 
2248     @Override
writeIdentifierToProto(ProtoOutputStream proto, long fieldId)2249     void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
2250         final long token = proto.start(fieldId);
2251         proto.write(HASH_CODE, System.identityHashCode(this));
2252         proto.write(USER_ID, mUserId);
2253         proto.write(TITLE, intent != null && intent.getComponent() != null
2254                 ? intent.getComponent().flattenToShortString() : "Task");
2255         proto.end(token);
2256     }
2257 
2258     /**
2259      * Saves launching state if necessary so that we can launch the activity to its latest state.
2260      */
saveLaunchingStateIfNeeded()2261     private void saveLaunchingStateIfNeeded() {
2262         saveLaunchingStateIfNeeded(getDisplayContent());
2263     }
2264 
saveLaunchingStateIfNeeded(DisplayContent display)2265     private void saveLaunchingStateIfNeeded(DisplayContent display) {
2266         if (!isLeafTask()) {
2267             return;
2268         }
2269 
2270         if (!getHasBeenVisible()) {
2271             // Not ever visible to user.
2272             return;
2273         }
2274 
2275         final int windowingMode = getWindowingMode();
2276         if (windowingMode != WINDOWING_MODE_FULLSCREEN
2277                 && windowingMode != WINDOWING_MODE_FREEFORM) {
2278             return;
2279         }
2280 
2281         // Don't persist state if Task Display Area isn't in freeform mode. Then the task will be
2282         // launched back to its last state in a freeform Task Display Area when it's launched in a
2283         // freeform Task Display Area next time.
2284         if (getTaskDisplayArea() == null
2285                 || getTaskDisplayArea().getWindowingMode() != WINDOWING_MODE_FREEFORM) {
2286             return;
2287         }
2288 
2289         // Saves the new state so that we can launch the activity at the same location.
2290         mTaskSupervisor.mLaunchParamsPersister.saveTask(this, display);
2291     }
2292 
updateOverrideConfigurationFromLaunchBounds()2293     Rect updateOverrideConfigurationFromLaunchBounds() {
2294         // If the task is controlled by another organized task, do not set override
2295         // configurations and let its parent (organized task) to control it;
2296         final Task rootTask = getRootTask();
2297         final Rect bounds = rootTask != this && rootTask.isOrganized() ? null : getLaunchBounds();
2298         setBounds(bounds);
2299         if (bounds != null && !bounds.isEmpty()) {
2300             // TODO: Review if we actually want to do this - we are setting the launch bounds
2301             // directly here.
2302             bounds.set(getRequestedOverrideBounds());
2303         }
2304         return bounds;
2305     }
2306 
2307     /** Returns the bounds that should be used to launch this task. */
getLaunchBounds()2308     Rect getLaunchBounds() {
2309         final Task rootTask = getRootTask();
2310         if (rootTask == null) {
2311             return null;
2312         }
2313 
2314         final int windowingMode = getWindowingMode();
2315         if (!isActivityTypeStandardOrUndefined()
2316                 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
2317             return isResizeable() ? rootTask.getRequestedOverrideBounds() : null;
2318         } else if (!getWindowConfiguration().persistTaskBounds()) {
2319             return rootTask.getRequestedOverrideBounds();
2320         }
2321         return mLastNonFullscreenBounds;
2322     }
2323 
setRootProcess(WindowProcessController proc)2324     void setRootProcess(WindowProcessController proc) {
2325         clearRootProcess();
2326         if (intent != null
2327                 && (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
2328             mRootProcess = proc;
2329             mRootProcess.addRecentTask(this);
2330         }
2331     }
2332 
clearRootProcess()2333     void clearRootProcess() {
2334         if (mRootProcess != null) {
2335             mRootProcess.removeRecentTask(this);
2336             mRootProcess = null;
2337         }
2338     }
2339 
2340     /** @return Id of root task. */
getRootTaskId()2341     int getRootTaskId() {
2342         return getRootTask().mTaskId;
2343     }
2344 
2345     /** @return the first organized task. */
2346     @Nullable
getOrganizedTask()2347     Task getOrganizedTask() {
2348         if (isOrganized()) {
2349             return this;
2350         }
2351         final WindowContainer parent = getParent();
2352         if (parent == null) {
2353             return null;
2354         }
2355         final Task parentTask = parent.asTask();
2356         return parentTask == null ? null : parentTask.getOrganizedTask();
2357     }
2358 
2359     /** @return the first create-by-organizer task. */
2360     @Nullable
getCreatedByOrganizerTask()2361     Task getCreatedByOrganizerTask() {
2362         if (mCreatedByOrganizer) {
2363             return this;
2364         }
2365         final WindowContainer parent = getParent();
2366         if (parent == null) {
2367             return null;
2368         }
2369         final Task parentTask = parent.asTask();
2370         return parentTask == null ? null : parentTask.getCreatedByOrganizerTask();
2371     }
2372 
2373     /** @return the first adjacent task of this task or its parent. */
2374     @Nullable
getAdjacentTask()2375     Task getAdjacentTask() {
2376         final TaskFragment adjacentTaskFragment = getAdjacentTaskFragment();
2377         if (adjacentTaskFragment != null && adjacentTaskFragment.asTask() != null) {
2378             return adjacentTaskFragment.asTask();
2379         }
2380 
2381         final WindowContainer parent = getParent();
2382         if (parent == null || parent.asTask() == null) {
2383             return null;
2384         }
2385 
2386         return parent.asTask().getAdjacentTask();
2387     }
2388 
2389     // TODO(task-merge): Figure out what's the right thing to do for places that used it.
isRootTask()2390     boolean isRootTask() {
2391         return getRootTask() == this;
2392     }
2393 
isLeafTask()2394     boolean isLeafTask() {
2395         for (int i = mChildren.size() - 1; i >= 0; --i) {
2396             if (mChildren.get(i).asTask() != null) {
2397                 return false;
2398             }
2399         }
2400         return true;
2401     }
2402 
2403     /** Return the top-most leaf-task under this one, or this task if it is a leaf. */
getTopLeafTask()2404     public Task getTopLeafTask() {
2405         for (int i = mChildren.size() - 1; i >= 0; --i) {
2406             final Task child = mChildren.get(i).asTask();
2407             if (child == null) continue;
2408             return child.getTopLeafTask();
2409         }
2410         return this;
2411     }
2412 
getDescendantTaskCount()2413     int getDescendantTaskCount() {
2414         final int[] currentCount = {0};
2415         forAllLeafTasks(t -> currentCount[0]++, false /* traverseTopToBottom */);
2416         return currentCount[0];
2417     }
2418 
2419     /**
2420      * Find next proper focusable root task and make it focused.
2421      * @return The root task that now got the focus, {@code null} if none found.
2422      */
adjustFocusToNextFocusableTask(String reason)2423     Task adjustFocusToNextFocusableTask(String reason) {
2424         return adjustFocusToNextFocusableTask(reason, false /* allowFocusSelf */,
2425                 true /* moveDisplayToTop */);
2426     }
2427 
2428     /** Return the next focusable task by looking from the siblings and parent tasks */
getNextFocusableTask(boolean allowFocusSelf)2429     private Task getNextFocusableTask(boolean allowFocusSelf) {
2430         final WindowContainer parent = getParent();
2431         if (parent == null) {
2432             return null;
2433         }
2434 
2435         final Task focusableTask = parent.getTask((task) -> (allowFocusSelf || task != this)
2436                 && ((Task) task).isFocusableAndVisible());
2437         if (focusableTask == null && parent.asTask() != null) {
2438             return parent.asTask().getNextFocusableTask(allowFocusSelf);
2439         } else {
2440             return focusableTask;
2441         }
2442     }
2443 
2444     /**
2445      * Find next proper focusable task and make it focused.
2446      * @param reason The reason of making the adjustment.
2447      * @param allowFocusSelf Is the focus allowed to remain on the same task.
2448      * @param moveDisplayToTop Whether to move display to top while making the task focused.
2449      * @return The root task that now got the focus, {@code null} if none found.
2450      */
adjustFocusToNextFocusableTask(String reason, boolean allowFocusSelf, boolean moveDisplayToTop)2451     Task adjustFocusToNextFocusableTask(String reason, boolean allowFocusSelf,
2452             boolean moveDisplayToTop) {
2453         Task focusableTask = getNextFocusableTask(allowFocusSelf);
2454         if (focusableTask == null) {
2455             focusableTask = mRootWindowContainer.getNextFocusableRootTask(this, !allowFocusSelf);
2456         }
2457         if (focusableTask == null) {
2458             final TaskDisplayArea taskDisplayArea = getDisplayArea();
2459             if (taskDisplayArea != null) {
2460                 // Clear the recorded task since there is no next focusable task.
2461                 taskDisplayArea.clearPreferredTopFocusableRootTask();
2462             }
2463             return null;
2464         }
2465 
2466         final Task rootTask = focusableTask.getRootTask();
2467         if (!moveDisplayToTop) {
2468             // There may be multiple task layers above this task, so when relocating the task to the
2469             // top, we should move this task and each of its parent task that below display area to
2470             // the top of each layer.
2471             WindowContainer parent = focusableTask.getParent();
2472             WindowContainer next = focusableTask;
2473             do {
2474                 parent.positionChildAt(POSITION_TOP, next, false /* includingParents */);
2475                 next = parent;
2476                 parent = next.getParent();
2477             } while (next.asTask() != null && parent != null);
2478             return rootTask;
2479         }
2480 
2481         final String myReason = reason + " adjustFocusToNextFocusableTask";
2482         final ActivityRecord top = focusableTask.topRunningActivity();
2483         if (focusableTask.isActivityTypeHome() && (top == null || !top.isVisibleRequested())) {
2484             // If we will be focusing on the root home task next and its current top activity isn't
2485             // visible, then use the move the root home task to top to make the activity visible.
2486             focusableTask.getDisplayArea().moveHomeActivityToTop(myReason);
2487             return rootTask;
2488         }
2489 
2490         // Move the entire hierarchy to top with updating global top resumed activity
2491         // and focused application if needed.
2492         focusableTask.moveToFront(myReason);
2493         // Top display focused root task is changed, update top resumed activity if needed.
2494         if (rootTask.getTopResumedActivity() != null) {
2495             mTaskSupervisor.updateTopResumedActivityIfNeeded(reason);
2496         }
2497         return rootTask;
2498     }
2499 
2500     /** Calculate the minimum possible position for a task that can be shown to the user.
2501      *  The minimum position will be above all other tasks that can't be shown.
2502      *  @param minPosition The minimum position the caller is suggesting.
2503      *                  We will start adjusting up from here.
2504      *  @param size The size of the current task list.
2505      */
2506     // TODO: Move user to their own window container.
computeMinUserPosition(int minPosition, int size)2507     private int computeMinUserPosition(int minPosition, int size) {
2508         while (minPosition < size) {
2509             final WindowContainer child = mChildren.get(minPosition);
2510             final boolean canShow = child.showToCurrentUser();
2511             if (canShow) {
2512                 break;
2513             }
2514             minPosition++;
2515         }
2516         return minPosition;
2517     }
2518 
2519     /** Calculate the maximum possible position for a task that can't be shown to the user.
2520      *  The maximum position will be below all other tasks that can be shown.
2521      *  @param maxPosition The maximum position the caller is suggesting.
2522      *                  We will start adjusting down from here.
2523      */
2524     // TODO: Move user to their own window container.
computeMaxUserPosition(int maxPosition)2525     private int computeMaxUserPosition(int maxPosition) {
2526         while (maxPosition > 0) {
2527             final WindowContainer child = mChildren.get(maxPosition);
2528             final boolean canShow = child.showToCurrentUser();
2529             if (!canShow) {
2530                 break;
2531             }
2532             maxPosition--;
2533         }
2534         return maxPosition;
2535     }
2536 
getAdjustedChildPosition(WindowContainer wc, int suggestedPosition)2537     private int getAdjustedChildPosition(WindowContainer wc, int suggestedPosition) {
2538         final boolean canShowChild = wc.showToCurrentUser();
2539 
2540         final int size = mChildren.size();
2541 
2542         // Figure-out min/max possible position depending on if child can show for current user.
2543         int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0;
2544         int maxPosition = minPosition;
2545         if (size > 0) {
2546             maxPosition = (canShowChild) ? size - 1 : computeMaxUserPosition(size - 1);
2547         }
2548 
2549         // Factor in always-on-top children in max possible position.
2550         if (!wc.isAlwaysOnTop()) {
2551             // We want to place all non-always-on-top containers below always-on-top ones.
2552             while (maxPosition > minPosition) {
2553                 if (!mChildren.get(maxPosition).isAlwaysOnTop()) break;
2554                 --maxPosition;
2555             }
2556         }
2557 
2558         // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
2559         if (suggestedPosition == POSITION_BOTTOM && minPosition == 0) {
2560             return POSITION_BOTTOM;
2561         } else if (suggestedPosition == POSITION_TOP && maxPosition >= (size - 1)) {
2562             return POSITION_TOP;
2563         }
2564 
2565         // Increase the maxPosition because children size will grow once wc is added.
2566         if (!hasChild(wc)) {
2567             ++maxPosition;
2568         }
2569 
2570         // Reset position based on minimum/maximum possible positions.
2571         return Math.min(Math.max(suggestedPosition, minPosition), maxPosition);
2572     }
2573 
2574     @Override
positionChildAt(int position, WindowContainer child, boolean includingParents)2575     void positionChildAt(int position, WindowContainer child, boolean includingParents) {
2576         final boolean toTop = position >= (mChildren.size() - 1);
2577         position = getAdjustedChildPosition(child, position);
2578         super.positionChildAt(position, child, includingParents);
2579 
2580         // Log positioning.
2581         if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "positionChildAt: child=" + child
2582                 + " position=" + position + " parent=" + this);
2583 
2584         final Task task = child.asTask();
2585         if (task != null) {
2586             task.updateTaskMovement(toTop, position == POSITION_BOTTOM, position);
2587         }
2588     }
2589 
2590     @Override
removeImmediately()2591     void removeImmediately() {
2592         removeImmediately("removeTask");
2593     }
2594 
2595     @Override
removeImmediately(String reason)2596     void removeImmediately(String reason) {
2597         if (DEBUG_ROOT_TASK) Slog.i(TAG, "removeTask:" + reason + " removing taskId=" + mTaskId);
2598         if (mRemoving) {
2599             return;
2600         }
2601         mRemoving = true;
2602 
2603         EventLogTags.writeWmTaskRemoved(mTaskId, getRootTaskId(), getDisplayId(), reason);
2604         clearPinnedTaskIfNeed();
2605         if (mChildPipActivity != null) {
2606             mChildPipActivity.clearLastParentBeforePip();
2607         }
2608         // If applicable let the TaskOrganizer know the Task is vanishing.
2609         setTaskOrganizer(null);
2610 
2611         super.removeImmediately();
2612         mRemoving = false;
2613     }
2614 
2615     // TODO: Consolidate this with Task.reparent()
reparent(Task rootTask, int position, boolean moveParents, String reason)2616     void reparent(Task rootTask, int position, boolean moveParents, String reason) {
2617         if (DEBUG_ROOT_TASK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
2618                 + " from rootTask=" + getRootTask());
2619         EventLogTags.writeWmTaskRemoved(mTaskId, getRootTaskId(), getDisplayId(),
2620                 "reParentTask:" + reason);
2621 
2622         reparent(rootTask, position);
2623 
2624         rootTask.positionChildAt(position, this, moveParents);
2625     }
2626 
setBounds(Rect bounds, boolean forceResize)2627     public int setBounds(Rect bounds, boolean forceResize) {
2628         final int boundsChanged = setBounds(bounds);
2629 
2630         if (forceResize && (boundsChanged & BOUNDS_CHANGE_SIZE) != BOUNDS_CHANGE_SIZE) {
2631             onResize();
2632             return BOUNDS_CHANGE_SIZE | boundsChanged;
2633         }
2634 
2635         return boundsChanged;
2636     }
2637 
2638     /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
2639     @Override
setBounds(Rect bounds)2640     public int setBounds(Rect bounds) {
2641         if (isRootTask()) {
2642             return setBounds(getRequestedOverrideBounds(), bounds);
2643         }
2644 
2645         int rotation = Surface.ROTATION_0;
2646         final DisplayContent displayContent = getRootTask() != null
2647                 ? getRootTask().getDisplayContent() : null;
2648         if (displayContent != null) {
2649             rotation = displayContent.getDisplayInfo().rotation;
2650         }
2651 
2652         final int boundsChange = super.setBounds(bounds);
2653         mRotation = rotation;
2654         updateSurfacePositionNonOrganized();
2655         return boundsChange;
2656     }
2657 
2658     /** Sets the requested bounds regardless of the windowing mode. */
setBoundsUnchecked(@onNull Rect bounds)2659     int setBoundsUnchecked(@NonNull Rect bounds) {
2660         final int boundsChange = super.setBounds(bounds);
2661         updateSurfaceBounds();
2662         return boundsChange;
2663     }
2664 
2665     @Override
isCompatible(int windowingMode, int activityType)2666     public boolean isCompatible(int windowingMode, int activityType) {
2667         // TODO: Should we just move this to ConfigurationContainer?
2668         if (activityType == ACTIVITY_TYPE_UNDEFINED) {
2669             // Undefined activity types end up in a standard root task once the root task is
2670             // created on a display, so they should be considered compatible.
2671             activityType = ACTIVITY_TYPE_STANDARD;
2672         }
2673         return super.isCompatible(windowingMode, activityType);
2674     }
2675 
2676     @Override
onDescendantOrientationChanged(WindowContainer requestingContainer)2677     public boolean onDescendantOrientationChanged(WindowContainer requestingContainer) {
2678         if (super.onDescendantOrientationChanged(requestingContainer)) {
2679             return true;
2680         }
2681 
2682         // No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
2683         // it if possible.
2684         if (getParent() != null) {
2685             onConfigurationChanged(getParent().getConfiguration());
2686             return true;
2687         }
2688         return false;
2689     }
2690 
2691     @Override
handlesOrientationChangeFromDescendant(@creenOrientation int orientation)2692     boolean handlesOrientationChangeFromDescendant(@ScreenOrientation int orientation) {
2693         if (!super.handlesOrientationChangeFromDescendant(orientation)) {
2694             return false;
2695         }
2696 
2697         // At task level, we want to check canSpecifyOrientation() based on the top activity type.
2698         // Do this only on leaf Task, so that the result is not affecting by the sibling leaf Task.
2699         // Otherwise, root Task will use the result from the top leaf Task, and all its child
2700         // leaf Tasks will rely on that from super.handlesOrientationChangeFromDescendant().
2701         if (!isLeafTask()) {
2702             return true;
2703         }
2704 
2705         // Check for leaf Task.
2706         // Display won't rotate for the orientation request if the Task/TaskDisplayArea
2707         // can't specify orientation.
2708         return canSpecifyOrientation() && getDisplayArea().canSpecifyOrientation(orientation);
2709     }
2710 
2711     @Override
onDisplayChanged(DisplayContent dc)2712     void onDisplayChanged(DisplayContent dc) {
2713         final boolean isRootTask = isRootTask();
2714         if (!isRootTask && !mCreatedByOrganizer) {
2715             adjustBoundsForDisplayChangeIfNeeded(dc);
2716         }
2717         super.onDisplayChanged(dc);
2718         if (isLeafTask()) {
2719             final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY;
2720             mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged(
2721                     mTaskId, displayId);
2722         }
2723         if (isRootTask()) {
2724             updateSurfaceBounds();
2725         }
2726         sendTaskFragmentParentInfoChangedIfNeeded();
2727     }
2728 
isResizeable()2729     boolean isResizeable() {
2730         return isResizeable(/* checkPictureInPictureSupport */ true);
2731     }
2732 
isResizeable(boolean checkPictureInPictureSupport)2733     boolean isResizeable(boolean checkPictureInPictureSupport) {
2734         final boolean forceResizable = mAtmService.mForceResizableActivities
2735                 && getActivityType() == ACTIVITY_TYPE_STANDARD;
2736         return forceResizable || ActivityInfo.isResizeableMode(mResizeMode)
2737                 || (mSupportsPictureInPicture && checkPictureInPictureSupport);
2738     }
2739 
2740     /**
2741      * Tests if the orientation should be preserved upon user interactive resizig operations.
2742 
2743      * @return true if orientation should not get changed upon resizing operation.
2744      */
preserveOrientationOnResize()2745     boolean preserveOrientationOnResize() {
2746         return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
2747                 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
2748                 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
2749     }
2750 
cropWindowsToRootTaskBounds()2751     boolean cropWindowsToRootTaskBounds() {
2752         // Don't crop HOME/RECENTS windows to root task bounds. This is because in split-screen
2753         // they extend past their root task and sysui uses the root task surface to control
2754         // cropping.
2755         // TODO(b/158242495): get rid of this when drag/drop can use surface bounds.
2756         if (isActivityTypeHomeOrRecents()) {
2757             // Make sure this is the top-most non-organizer root task (if not top-most, it means
2758             // another translucent task could be above this, so this needs to stay cropped.
2759             final Task rootTask = getRootTask();
2760             final Task topNonOrgTask =
2761                     rootTask.mCreatedByOrganizer ? rootTask.getTopMostTask() : rootTask;
2762             if (this == topNonOrgTask || isDescendantOf(topNonOrgTask)) {
2763                 return false;
2764             }
2765         }
2766         return isResizeable();
2767     }
2768 
2769     @Override
getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, Rect outSurfaceInsets)2770     void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2771             Rect outSurfaceInsets) {
2772         // If this task has its adjacent task, it means they should animate together. Use display
2773         // bounds for them could move same as full screen task.
2774         if (getAdjacentTask() != null) {
2775             super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2776             return;
2777         }
2778 
2779         final WindowState windowState = getTopVisibleAppMainWindow();
2780         if (windowState != null) {
2781             windowState.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2782         } else {
2783             super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2784         }
2785     }
2786 
2787     /**
2788      * Calculate the maximum visible area of this task. If the task has only one app,
2789      * the result will be visible frame of that app. If the task has more than one apps,
2790      * we search from top down if the next app got different visible area.
2791      *
2792      * This effort is to handle the case where some task (eg. GMail composer) might pop up
2793      * a dialog that's different in size from the activity below, in which case we should
2794      * be dimming the entire task area behind the dialog.
2795      *
2796      * @param out the union of visible bounds.
2797      */
getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop)2798     private static void getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop) {
2799         // skip hidden (or about to hide) apps
2800         if (token.mIsExiting || !token.isClientVisible() || !token.isVisibleRequested()) {
2801             return;
2802         }
2803         final WindowState win = token.findMainWindow();
2804         if (win == null) {
2805             return;
2806         }
2807         if (!foundTop[0]) {
2808             foundTop[0] = true;
2809             out.setEmpty();
2810         }
2811 
2812         final Rect visibleFrame = sTmpBounds;
2813         final WindowManager.LayoutParams attrs = win.mAttrs;
2814         visibleFrame.set(win.getFrame());
2815         visibleFrame.inset(win.getInsetsStateWithVisibilityOverride().calculateVisibleInsets(
2816                 visibleFrame, attrs.type, win.getActivityType(), attrs.softInputMode,
2817                 attrs.flags));
2818         out.union(visibleFrame);
2819     }
2820 
2821     /** Bounds of the task to be used for dimming, as well as touch related tests. */
getDimBounds(Rect out)2822     void getDimBounds(Rect out) {
2823         if (isRootTask()) {
2824             getBounds(out);
2825             return;
2826         }
2827 
2828         final Task rootTask = getRootTask();
2829         if (inFreeformWindowingMode()) {
2830             boolean[] foundTop = { false };
2831             forAllActivities(a -> { getMaxVisibleBounds(a, out, foundTop); });
2832             if (foundTop[0]) {
2833                 return;
2834             }
2835         }
2836 
2837         if (!matchParentBounds()) {
2838             // When minimizing the root docked task when going home, we don't adjust the task bounds
2839             // so we need to intersect the task bounds with the root task bounds here..
2840             rootTask.getBounds(mTmpRect);
2841             mTmpRect.intersect(getBounds());
2842             out.set(mTmpRect);
2843         } else {
2844             out.set(getBounds());
2845         }
2846         return;
2847     }
2848 
2849     /**
2850      * Account for specified insets to crop the animation bounds by to avoid the animation
2851      * occurring over "out of bounds" regions
2852      *
2853      * For example this is used to make sure the tasks are cropped to be fully above the expanded
2854      * taskbar when animating.
2855      *
2856      * TEMPORARY FIELD (b/202383002)
2857      * TODO: Remove once we use surfaceflinger rounded corners on tasks rather than taskbar overlays
2858      *       or when shell transitions are fully enabled
2859      *
2860      * @param animationBounds The animation bounds to adjust to account for the custom spec insets.
2861      */
adjustAnimationBoundsForTransition(Rect animationBounds)2862     void adjustAnimationBoundsForTransition(Rect animationBounds) {
2863         TaskTransitionSpec spec = mWmService.mTaskTransitionSpec;
2864         if (spec != null) {
2865             final InsetsState state =
2866                     getDisplayContent().getInsetsStateController().getRawInsetsState();
2867             for (int i = state.sourceSize() - 1; i >= 0; i--) {
2868                 final InsetsSource source = state.sourceAt(i);
2869                 if (source.hasFlags(FLAG_INSETS_ROUNDED_CORNER)) {
2870                     animationBounds.inset(source.calculateVisibleInsets(animationBounds));
2871                 }
2872             }
2873         }
2874     }
2875 
setDragResizing(boolean dragResizing)2876     void setDragResizing(boolean dragResizing) {
2877         if (mDragResizing != dragResizing) {
2878             // No need to check if allowed if it's leaving dragResize
2879             if (dragResizing
2880                     && !(getRootTask().getWindowingMode() == WINDOWING_MODE_FREEFORM)) {
2881                 Slog.e(TAG, "Drag resize isn't allowed for root task id=" + getRootTaskId());
2882                 return;
2883             }
2884             mDragResizing = dragResizing;
2885             resetDragResizingChangeReported();
2886         }
2887     }
2888 
isDragResizing()2889     boolean isDragResizing() {
2890         return mDragResizing;
2891     }
2892 
adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent)2893     void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
2894         if (displayContent == null) {
2895             return;
2896         }
2897         if (getRequestedOverrideBounds().isEmpty()) {
2898             return;
2899         }
2900         final int displayId = displayContent.getDisplayId();
2901         final int newRotation = displayContent.getDisplayInfo().rotation;
2902         if (displayId != mLastRotationDisplayId) {
2903             // This task is on a display that it wasn't on. There is no point to keep the relative
2904             // position if display rotations for old and new displays are different. Just keep these
2905             // values.
2906             mLastRotationDisplayId = displayId;
2907             mRotation = newRotation;
2908             return;
2909         }
2910 
2911         if (mRotation == newRotation) {
2912             // Rotation didn't change. We don't need to adjust the bounds to keep the relative
2913             // position.
2914             return;
2915         }
2916 
2917         // Device rotation changed.
2918         // - We don't want the task to move around on the screen when this happens, so update the
2919         //   task bounds so it stays in the same place.
2920         // - Rotate the bounds and notify activity manager if the task can be resized independently
2921         //   from its root task. The root task will take care of task rotation for the other case.
2922         mTmpRect2.set(getBounds());
2923 
2924         if (!getWindowConfiguration().canResizeTask()) {
2925             setBounds(mTmpRect2);
2926             return;
2927         }
2928 
2929         displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
2930         if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
2931             mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
2932         }
2933     }
2934 
2935     /** Cancels any running app transitions associated with the task. */
cancelTaskWindowTransition()2936     void cancelTaskWindowTransition() {
2937         for (int i = mChildren.size() - 1; i >= 0; --i) {
2938             mChildren.get(i).cancelAnimation();
2939         }
2940     }
2941 
showForAllUsers()2942     boolean showForAllUsers() {
2943         if (mChildren.isEmpty()) return false;
2944         final ActivityRecord r = getTopNonFinishingActivity();
2945         return r != null && r.mShowForAllUsers;
2946     }
2947 
2948     @Override
showToCurrentUser()2949     boolean showToCurrentUser() {
2950         return mForceShowForAllUsers || showForAllUsers()
2951                 || mWmService.isUserVisible(getTopMostTask().mUserId);
2952     }
2953 
setForceShowForAllUsers(boolean forceShowForAllUsers)2954     void setForceShowForAllUsers(boolean forceShowForAllUsers) {
2955         mForceShowForAllUsers = forceShowForAllUsers;
2956     }
2957 
2958     /** Returns the top-most activity that occludes the given one, or {@code null} if none. */
2959     @Nullable
getOccludingActivityAbove(ActivityRecord activity)2960     ActivityRecord getOccludingActivityAbove(ActivityRecord activity) {
2961         final ActivityRecord top = getActivity(r -> {
2962             if (r == activity) {
2963                 // Reached the given activity, return the activity to stop searching.
2964                 return true;
2965             }
2966 
2967             if (!r.occludesParent()) {
2968                 return false;
2969             }
2970 
2971             TaskFragment parent = r.getTaskFragment();
2972             if (parent == activity.getTaskFragment()) {
2973                 // Found it. This activity on top of the given activity on the same TaskFragment.
2974                 return true;
2975             }
2976             if (parent != null && parent.asTask() != null) {
2977                 // Found it. This activity is the direct child of a leaf Task.
2978                 return true;
2979             }
2980             // The candidate activity is being embedded. Checking if the bounds of the containing
2981             // TaskFragment equals to the outer TaskFragment.
2982             TaskFragment grandParent = parent.getParent().asTaskFragment();
2983             while (grandParent != null) {
2984                 if (!parent.getBounds().equals(grandParent.getBounds())) {
2985                     // Not occluding the grandparent.
2986                     break;
2987                 }
2988                 if (grandParent.asTask() != null) {
2989                     // Found it. The activity occludes its parent TaskFragment and the parent
2990                     // TaskFragment also occludes its parent all the way up.
2991                     return true;
2992                 }
2993                 parent = grandParent;
2994                 grandParent = parent.getParent().asTaskFragment();
2995             }
2996             return false;
2997         });
2998         return top != activity ? top : null;
2999     }
3000 
3001     @Override
makeAnimationLeash()3002     public SurfaceControl.Builder makeAnimationLeash() {
3003         return super.makeAnimationLeash().setMetadata(METADATA_TASK_ID, mTaskId);
3004     }
3005 
shouldAnimate()3006     boolean shouldAnimate() {
3007         /**
3008          * Animations are handled by the TaskOrganizer implementation.
3009          */
3010         if (isOrganized()) {
3011             return false;
3012         }
3013         // Don't animate while the task runs recents animation but only if we are in the mode
3014         // where we cancel with deferred screenshot, which means that the controller has
3015         // transformed the task.
3016         final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
3017         if (controller != null && controller.isAnimatingTask(this)
3018                 && controller.shouldDeferCancelUntilNextTransition()) {
3019             return false;
3020         }
3021         return true;
3022     }
3023 
3024     @Override
setInitialSurfaceControlProperties(SurfaceControl.Builder b)3025     void setInitialSurfaceControlProperties(SurfaceControl.Builder b) {
3026         b.setEffectLayer().setMetadata(METADATA_TASK_ID, mTaskId);
3027         super.setInitialSurfaceControlProperties(b);
3028     }
3029 
3030     /** Checking if self or its child tasks are animated by recents animation. */
isAnimatingByRecents()3031     boolean isAnimatingByRecents() {
3032         return isAnimating(CHILDREN, ANIMATION_TYPE_RECENTS)
3033                 || mTransitionController.isTransientHide(this);
3034     }
3035 
getTopVisibleAppMainWindow()3036     WindowState getTopVisibleAppMainWindow() {
3037         final ActivityRecord activity = getTopVisibleActivity();
3038         return activity != null ? activity.findMainWindow() : null;
3039     }
3040 
topRunningNonDelayedActivityLocked(ActivityRecord notTop)3041     ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
3042         final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunningNonDelayed
3043                 , PooledLambda.__(ActivityRecord.class), notTop);
3044         final ActivityRecord r = getActivity(p);
3045         p.recycle();
3046         return r;
3047     }
3048 
isTopRunningNonDelayed(ActivityRecord r, ActivityRecord notTop)3049     private static boolean isTopRunningNonDelayed(ActivityRecord r, ActivityRecord notTop) {
3050         return !r.delayedResume && r != notTop && r.canBeTopRunning();
3051     }
3052 
3053     /**
3054      * This is a simplified version of topRunningActivity that provides a number of
3055      * optional skip-over modes.  It is intended for use with the ActivityController hook only.
3056      *
3057      * @param token If non-null, any history records matching this token will be skipped.
3058      * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
3059      *
3060      * @return Returns the HistoryRecord of the next activity on the root task.
3061      */
topRunningActivity(IBinder token, int taskId)3062     ActivityRecord topRunningActivity(IBinder token, int taskId) {
3063         final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunning,
3064                 PooledLambda.__(ActivityRecord.class), taskId, token);
3065         final ActivityRecord r = getActivity(p);
3066         p.recycle();
3067         return r;
3068     }
3069 
isTopRunning(ActivityRecord r, int taskId, IBinder notTop)3070     private static boolean isTopRunning(ActivityRecord r, int taskId, IBinder notTop) {
3071         return r.getTask().mTaskId != taskId && r.token != notTop && r.canBeTopRunning();
3072     }
3073 
getTopFullscreenActivity()3074     ActivityRecord getTopFullscreenActivity() {
3075         return getActivity((r) -> {
3076             final WindowState win = r.findMainWindow();
3077             return (win != null && win.mAttrs.isFullscreen());
3078         });
3079     }
3080 
3081     /**
3082      * Return the top visible requested activity. The activity has been requested to be visible,
3083      * but it's possible that the activity has just been created, so no window is yet attached to
3084      * this activity.
3085      */
getTopVisibleActivity()3086     ActivityRecord getTopVisibleActivity() {
3087         return getActivity((r) -> !r.mIsExiting && r.isClientVisible() && r.isVisibleRequested());
3088     }
3089 
3090     /**
3091      * Return the top visible activity. The activity has a window on which contents are drawn.
3092      * However it's possible that the activity has already been requested to be invisible, but the
3093      * visibility is not yet committed.
3094      */
getTopRealVisibleActivity()3095     ActivityRecord getTopRealVisibleActivity() {
3096         return getActivity((r) -> !r.mIsExiting && r.isClientVisible() && r.isVisible());
3097     }
3098 
getTopWaitSplashScreenActivity()3099     ActivityRecord getTopWaitSplashScreenActivity() {
3100         return getActivity((r) -> {
3101             return r.mHandleExitSplashScreen
3102                     && r.mTransferringSplashScreenState == TRANSFER_SPLASH_SCREEN_COPYING;
3103         });
3104     }
3105 
3106     void setTaskDescription(TaskDescription taskDescription) {
3107         mTaskDescription = taskDescription;
3108     }
3109 
3110     void onSnapshotChanged(TaskSnapshot snapshot) {
3111         mLastTaskSnapshotData.set(snapshot);
3112         mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
3113                 mTaskId, snapshot);
3114     }
3115 
3116     TaskDescription getTaskDescription() {
3117         return mTaskDescription;
3118     }
3119 
3120     @Override
3121     void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
3122         final int count = mChildren.size();
3123         boolean isLeafTask = true;
3124         if (traverseTopToBottom) {
3125             for (int i = count - 1; i >= 0; --i) {
3126                 final Task child = mChildren.get(i).asTask();
3127                 if (child != null) {
3128                     isLeafTask = false;
3129                     child.forAllLeafTasks(callback, traverseTopToBottom);
3130                 }
3131             }
3132         } else {
3133             for (int i = 0; i < count; i++) {
3134                 final Task child = mChildren.get(i).asTask();
3135                 if (child != null) {
3136                     isLeafTask = false;
3137                     child.forAllLeafTasks(callback, traverseTopToBottom);
3138                 }
3139             }
3140         }
3141         if (isLeafTask) callback.accept(this);
3142     }
3143 
3144     @Override
3145     void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
3146         super.forAllTasks(callback, traverseTopToBottom);
3147         callback.accept(this);
3148     }
3149 
3150     @Override
3151     void forAllRootTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
3152         if (isRootTask()) {
3153             callback.accept(this);
3154         }
3155     }
3156 
3157     @Override
3158     boolean forAllTasks(Predicate<Task> callback) {
3159         if (super.forAllTasks(callback)) return true;
3160         return callback.test(this);
3161     }
3162 
3163     @Override
3164     boolean forAllLeafTasks(Predicate<Task> callback) {
3165         boolean isLeafTask = true;
3166         for (int i = mChildren.size() - 1; i >= 0; --i) {
3167             final Task child = mChildren.get(i).asTask();
3168             if (child != null) {
3169                 isLeafTask = false;
3170                 if (child.forAllLeafTasks(callback)) {
3171                     return true;
3172                 }
3173             }
3174         }
3175         if (isLeafTask) {
3176             return callback.test(this);
3177         }
3178         return false;
3179     }
3180 
3181     /** Iterates through all leaf task fragments and the leaf tasks. */
3182     void forAllLeafTasksAndLeafTaskFragments(final Consumer<TaskFragment> callback,
3183             boolean traverseTopToBottom) {
3184         forAllLeafTasks(task -> {
3185             if (task.isLeafTaskFragment()) {
3186                 callback.accept(task);
3187                 return;
3188             }
3189 
3190             // A leaf task that may contains both activities and task fragments.
3191             boolean consumed = false;
3192             if (traverseTopToBottom) {
3193                 for (int i = task.mChildren.size() - 1; i >= 0; --i) {
3194                     final WindowContainer child = task.mChildren.get(i);
3195                     if (child.asTaskFragment() != null) {
3196                         child.forAllLeafTaskFragments(callback, traverseTopToBottom);
3197                     } else if (child.asActivityRecord() != null && !consumed) {
3198                         callback.accept(task);
3199                         consumed = true;
3200                     }
3201                 }
3202             } else {
3203                 for (int i = 0; i < task.mChildren.size(); i++) {
3204                     final WindowContainer child = task.mChildren.get(i);
3205                     if (child.asTaskFragment() != null) {
3206                         child.forAllLeafTaskFragments(callback, traverseTopToBottom);
3207                     } else if (child.asActivityRecord() != null && !consumed) {
3208                         callback.accept(task);
3209                         consumed = true;
3210                     }
3211                 }
3212             }
3213         }, traverseTopToBottom);
3214     }
3215 
3216     @Override
3217     boolean forAllRootTasks(Predicate<Task> callback, boolean traverseTopToBottom) {
3218         return isRootTask() ? callback.test(this) : false;
3219     }
3220 
3221     @Override
3222     Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
3223         final Task t = super.getTask(callback, traverseTopToBottom);
3224         if (t != null) return t;
3225         return callback.test(this) ? this : null;
3226     }
3227 
3228     @Nullable
3229     @Override
3230     Task getRootTask(Predicate<Task> callback, boolean traverseTopToBottom) {
3231         return isRootTask() && callback.test(this) ? this : null;
3232     }
3233 
3234     /**
3235      * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
3236      *                               flags. See {@link WindowState#canAffectSystemUiFlags()}.
3237      */
3238     void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) {
3239         mCanAffectSystemUiFlags = canAffectSystemUiFlags;
3240     }
3241 
3242     /**
3243      * @see #setCanAffectSystemUiFlags
3244      */
3245     boolean canAffectSystemUiFlags() {
3246         return mCanAffectSystemUiFlags;
3247     }
3248 
3249     void dontAnimateDimExit() {
3250         mDimmer.dontAnimateExit();
3251     }
3252 
3253     String getName() {
3254         return "Task=" + mTaskId;
3255     }
3256 
3257     @Override
3258     Dimmer getDimmer() {
3259         // If the window is in multi-window mode, we want to dim at the Task level to ensure the dim
3260         // bounds match the area the app lives in
3261         if (inMultiWindowMode()) {
3262             return mDimmer;
3263         }
3264 
3265         // If we're not at the root task level, we want to keep traversing through the parents to
3266         // find the root.
3267         // Once at the root task level, we want to check {@link #isTranslucent(ActivityRecord)}.
3268         // If true, we want to get the Dimmer from the level above since we don't want to animate
3269         // the dim with the Task.
3270         if (!isRootTask() || isTranslucent(null)) {
3271             return super.getDimmer();
3272         }
3273 
3274         return mDimmer;
3275     }
3276 
3277     @Override
3278     void prepareSurfaces() {
3279         mDimmer.resetDimStates();
3280         super.prepareSurfaces();
3281 
3282         final Rect dimBounds = mDimmer.getDimBounds();
3283         if (dimBounds != null) {
3284             getDimBounds(dimBounds);
3285 
3286             // Bounds need to be relative, as the dim layer is a child.
3287             if (inFreeformWindowingMode()) {
3288                 getBounds(mTmpRect);
3289                 dimBounds.offsetTo(dimBounds.left - mTmpRect.left, dimBounds.top - mTmpRect.top);
3290             } else {
3291                 dimBounds.offsetTo(0, 0);
3292             }
3293         }
3294 
3295         final SurfaceControl.Transaction t = getSyncTransaction();
3296 
3297         if (dimBounds != null && mDimmer.updateDims(t)) {
3298             scheduleAnimation();
3299         }
3300 
3301         // Let organizer manage task visibility for shell transition. So don't change it's
3302         // visibility during collecting.
3303         if (mTransitionController.isCollecting() && mCreatedByOrganizer) {
3304             return;
3305         }
3306 
3307         // We intend to let organizer manage task visibility but it doesn't
3308         // have enough information until we finish shell transitions.
3309         // In the mean time we do an easy fix here.
3310         final boolean visible = isVisible();
3311         final boolean show = visible || isAnimating(TRANSITION | PARENTS | CHILDREN);
3312         if (mSurfaceControl != null) {
3313             if (show != mLastSurfaceShowing) {
3314                 t.setVisibility(mSurfaceControl, show);
3315             }
3316         }
3317         // Only show the overlay if the task has other visible children
3318         if (mOverlayHost != null) {
3319             mOverlayHost.setVisibility(t, visible);
3320         }
3321         mLastSurfaceShowing = show;
3322     }
3323 
3324     @Override
3325     protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
3326             @TransitionOldType int transit, boolean isVoiceInteraction,
3327             @Nullable ArrayList<WindowContainer> sources) {
3328         final RecentsAnimationController control = mWmService.getRecentsAnimationController();
3329         if (control != null) {
3330             // We let the transition to be controlled by RecentsAnimation, and callback task's
3331             // RemoteAnimationTarget for remote runner to animate.
3332             if (enter && !isActivityTypeHomeOrRecents()) {
3333                 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
3334                         "applyAnimationUnchecked, control: %s, task: %s, transit: %s",
3335                         control, asTask(), AppTransition.appTransitionOldToString(transit));
3336                 final int size = sources != null ? sources.size() : 0;
3337                 control.addTaskToTargets(this, (type, anim) -> {
3338                     for (int i = 0; i < size; ++i) {
3339                         sources.get(i).onAnimationFinished(type, anim);
3340                     }
3341                 });
3342             }
3343         } else {
3344             super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
3345         }
3346     }
3347 
3348     @Override
3349     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
3350         super.dump(pw, prefix, dumpAll);
3351         mAnimatingActivityRegistry.dump(pw, "AnimatingApps:", prefix);
3352     }
3353 
3354 
3355     /**
3356      * Fills in a {@link TaskInfo} with information from this task. Note that the base intent in the
3357      * task info will not include any extras or clip data.
3358      */
3359     void fillTaskInfo(TaskInfo info) {
3360         fillTaskInfo(info, true /* stripExtras */);
3361     }
3362 
3363     void fillTaskInfo(TaskInfo info, boolean stripExtras) {
3364         fillTaskInfo(info, stripExtras, getDisplayArea());
3365     }
3366 
3367     /**
3368      * Fills in a {@link TaskInfo} with information from this task.
3369      *
3370      * @param tda consider whether this Task can be put in multi window as it will be attached to
3371      *            the give {@link TaskDisplayArea}.
3372      */
3373     void fillTaskInfo(TaskInfo info, boolean stripExtras, @Nullable TaskDisplayArea tda) {
3374         info.launchCookies.clear();
3375         info.addLaunchCookie(mLaunchCookie);
3376         final ActivityRecord top = mTaskSupervisor.mTaskInfoHelper.fillAndReturnTop(this, info);
3377 
3378         info.userId = isLeafTask() ? mUserId : mCurrentUser;
3379         info.taskId = mTaskId;
3380         info.displayId = getDisplayId();
3381         info.displayAreaFeatureId = tda != null ? tda.mFeatureId : FEATURE_UNDEFINED;
3382         final Intent baseIntent = getBaseIntent();
3383         // Make a copy of base intent because this is like a snapshot info.
3384         // Besides, {@link RecentTasks#getRecentTasksImpl} may modify it.
3385         final int baseIntentFlags = baseIntent == null ? 0 : baseIntent.getFlags();
3386         info.baseIntent = baseIntent == null
3387                 ? new Intent()
3388                 : stripExtras ? baseIntent.cloneFilter() : new Intent(baseIntent);
3389         info.baseIntent.setFlags(baseIntentFlags);
3390 
3391         info.isRunning = top != null;
3392         info.topActivity = top != null ? top.mActivityComponent : null;
3393         info.origActivity = origActivity;
3394         info.realActivity = realActivity;
3395         info.lastActiveTime = lastActiveTime;
3396         info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
3397         info.supportsMultiWindow = supportsMultiWindowInDisplayArea(tda);
3398         info.configuration.setTo(getConfiguration());
3399         // Update to the task's current activity type and windowing mode which may differ from the
3400         // window configuration
3401         info.configuration.windowConfiguration.setActivityType(getActivityType());
3402         info.configuration.windowConfiguration.setWindowingMode(getWindowingMode());
3403         info.token = mRemoteToken.toWindowContainerToken();
3404 
3405         //TODO (AM refactor): Just use local once updateEffectiveIntent is run during all child
3406         //                    order changes.
3407         final Task topTask = top != null ? top.getTask() : this;
3408         info.resizeMode = topTask.mResizeMode;
3409         info.topActivityType = topTask.getActivityType();
3410         info.displayCutoutInsets = topTask.getDisplayCutoutInsets();
3411         info.isResizeable = isResizeable();
3412         info.minWidth = mMinWidth;
3413         info.minHeight = mMinHeight;
3414         info.defaultMinSize = mDisplayContent == null
3415                 ? DEFAULT_MIN_TASK_SIZE_DP : mDisplayContent.mMinSizeOfResizeableTaskDp;
3416         info.positionInParent = getRelativePosition();
3417 
3418         info.topActivityInfo = top != null ? top.info : null;
3419         info.pictureInPictureParams = getPictureInPictureParams(top);
3420         info.launchIntoPipHostTaskId = (info.pictureInPictureParams != null
3421                 && info.pictureInPictureParams.isLaunchIntoPip()
3422                 && top.getLastParentBeforePip() != null)
3423                         ? top.getLastParentBeforePip().mTaskId : INVALID_TASK_ID;
3424         info.lastParentTaskIdBeforePip = top != null && top.getLastParentBeforePip() != null
3425                 ? top.getLastParentBeforePip().mTaskId : INVALID_TASK_ID;
3426         info.shouldDockBigOverlays = top != null && top.shouldDockBigOverlays;
3427         info.mTopActivityLocusId = top != null ? top.getLocusId() : null;
3428 
3429         final boolean isTopActivityResumed = top != null
3430                 && top.getOrganizedTask() == this && top.isState(RESUMED);
3431         final boolean isTopActivityVisible = top != null
3432                 && top.getOrganizedTask() == this && top.isVisible();
3433         // Whether the direct top activity is in size compat mode
3434         info.topActivityInSizeCompat = isTopActivityVisible && top.inSizeCompatMode();
3435         if (info.topActivityInSizeCompat
3436                 && mWmService.mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) {
3437             // We hide the restart button in case of transparent activities.
3438             info.topActivityInSizeCompat = top.fillsParent();
3439         }
3440         // Whether the direct top activity is eligible for letterbox education.
3441         info.topActivityEligibleForLetterboxEducation = isTopActivityResumed
3442                 && top.isEligibleForLetterboxEducation();
3443         // Whether the direct top activity requested showing camera compat control.
3444         info.cameraCompatControlState = isTopActivityResumed
3445                 ? top.getCameraCompatControlState()
3446                 : TaskInfo.CAMERA_COMPAT_CONTROL_HIDDEN;
3447 
3448         final Task parentTask = getParent() != null ? getParent().asTask() : null;
3449         info.parentTaskId = parentTask != null && parentTask.mCreatedByOrganizer
3450                 ? parentTask.mTaskId
3451                 : INVALID_TASK_ID;
3452         info.isFocused = isFocused();
3453         info.isVisible = hasVisibleChildren();
3454         info.isVisibleRequested = isVisibleRequested();
3455         info.isSleeping = shouldSleepActivities();
3456         info.isLetterboxDoubleTapEnabled = top != null
3457                 && top.mLetterboxUiController.isLetterboxDoubleTapEducationEnabled();
3458         info.topActivityLetterboxVerticalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
3459         info.topActivityLetterboxHorizontalPosition = TaskInfo.PROPERTY_VALUE_UNSET;
3460         info.topActivityLetterboxWidth = TaskInfo.PROPERTY_VALUE_UNSET;
3461         info.topActivityLetterboxHeight = TaskInfo.PROPERTY_VALUE_UNSET;
3462         info.isUserFullscreenOverrideEnabled = top != null
3463                 && top.mLetterboxUiController.shouldApplyUserFullscreenOverride();
3464         info.isTopActivityTransparent = top != null && !top.fillsParent();
3465         info.isFromLetterboxDoubleTap = top != null && top.mLetterboxUiController.isFromDoubleTap();
3466         if (info.isLetterboxDoubleTapEnabled) {
3467             info.topActivityLetterboxWidth = top.getBounds().width();
3468             info.topActivityLetterboxHeight = top.getBounds().height();
3469             if (info.topActivityLetterboxWidth < info.topActivityLetterboxHeight) {
3470                 // Pillarboxed
3471                 info.topActivityLetterboxHorizontalPosition =
3472                         top.mLetterboxUiController.getLetterboxPositionForHorizontalReachability();
3473             } else {
3474                 // Letterboxed
3475                 info.topActivityLetterboxVerticalPosition =
3476                         top.mLetterboxUiController.getLetterboxPositionForVerticalReachability();
3477             }
3478         }
3479         // User Aspect Ratio Settings is enabled if the app is not in SCM
3480         info.topActivityEligibleForUserAspectRatioButton = top != null
3481                 && !info.topActivityInSizeCompat
3482                 && top.mLetterboxUiController.shouldEnableUserAspectRatioSettings();
3483         info.topActivityBoundsLetterboxed = top != null && top.areBoundsLetterboxed();
3484     }
3485 
3486     /**
3487      * Removes the activity info if the activity belongs to a different uid, which is
3488      * different from the app that hosts the task.
3489      */
3490     static void trimIneffectiveInfo(Task task, TaskInfo info) {
3491         final ActivityRecord baseActivity = task.getActivity(r -> !r.finishing,
3492                 false /* traverseTopToBottom */);
3493         final int baseActivityUid =
3494                 baseActivity != null ? baseActivity.getUid() : task.effectiveUid;
3495 
3496         if (info.topActivityInfo != null
3497                 && task.effectiveUid != info.topActivityInfo.applicationInfo.uid) {
3498             // Making a copy to prevent eliminating the info in the original ActivityRecord.
3499             info.topActivityInfo = new ActivityInfo(info.topActivityInfo);
3500             info.topActivityInfo.applicationInfo =
3501                     new ApplicationInfo(info.topActivityInfo.applicationInfo);
3502 
3503             // Strip the sensitive info.
3504             info.topActivity = new ComponentName("", "");
3505             info.topActivityInfo.packageName = "";
3506             info.topActivityInfo.taskAffinity = "";
3507             info.topActivityInfo.processName = "";
3508             info.topActivityInfo.name = "";
3509             info.topActivityInfo.parentActivityName = "";
3510             info.topActivityInfo.targetActivity = "";
3511             info.topActivityInfo.splitName = "";
3512             info.topActivityInfo.applicationInfo.className = "";
3513             info.topActivityInfo.applicationInfo.credentialProtectedDataDir = "";
3514             info.topActivityInfo.applicationInfo.dataDir = "";
3515             info.topActivityInfo.applicationInfo.deviceProtectedDataDir = "";
3516             info.topActivityInfo.applicationInfo.manageSpaceActivityName = "";
3517             info.topActivityInfo.applicationInfo.nativeLibraryDir = "";
3518             info.topActivityInfo.applicationInfo.nativeLibraryRootDir = "";
3519             info.topActivityInfo.applicationInfo.processName = "";
3520             info.topActivityInfo.applicationInfo.publicSourceDir = "";
3521             info.topActivityInfo.applicationInfo.scanPublicSourceDir = "";
3522             info.topActivityInfo.applicationInfo.scanSourceDir = "";
3523             info.topActivityInfo.applicationInfo.sourceDir = "";
3524             info.topActivityInfo.applicationInfo.taskAffinity = "";
3525             info.topActivityInfo.applicationInfo.name = "";
3526             info.topActivityInfo.applicationInfo.packageName = "";
3527         }
3528 
3529         if (task.effectiveUid != baseActivityUid) {
3530             info.baseActivity = new ComponentName("", "");
3531         }
3532     }
3533 
3534     @Nullable PictureInPictureParams getPictureInPictureParams() {
3535         final Task topTask = getTopMostTask();
3536         if (topTask == null) return null;
3537         return getPictureInPictureParams(topTask.getTopMostActivity());
3538     }
3539 
3540     private static @Nullable PictureInPictureParams getPictureInPictureParams(ActivityRecord top) {
3541         return (top == null || top.pictureInPictureArgs.empty())
3542                 ? null : new PictureInPictureParams(top.pictureInPictureArgs);
3543     }
3544 
3545     private boolean shouldDockBigOverlays() {
3546         final ActivityRecord topMostActivity = getTopMostActivity();
3547         return topMostActivity != null && topMostActivity.shouldDockBigOverlays;
3548     }
3549 
3550     Rect getDisplayCutoutInsets() {
3551         if (mDisplayContent == null || getDisplayInfo().displayCutout == null) return null;
3552         final WindowState w = getTopVisibleAppMainWindow();
3553         final int displayCutoutMode = w == null
3554                 ? WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
3555                 : w.getAttrs().layoutInDisplayCutoutMode;
3556         return (displayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
3557                 || displayCutoutMode == LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES)
3558                 ? null : getDisplayInfo().displayCutout.getSafeInsets();
3559     }
3560 
3561     /**
3562      * Returns a {@link TaskInfo} with information from this task.
3563      */
3564     ActivityManager.RunningTaskInfo getTaskInfo() {
3565         ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
3566         fillTaskInfo(info);
3567         return info;
3568     }
3569 
3570     /**
3571      * Returns a {@link StartingWindowInfo} with information from this task and the target activity.
3572      * @param activity Target activity which to show the starting window.
3573      */
3574     StartingWindowInfo getStartingWindowInfo(ActivityRecord activity) {
3575         final StartingWindowInfo info = new StartingWindowInfo();
3576         info.taskInfo = getTaskInfo();
3577         info.targetActivityInfo = info.taskInfo.topActivityInfo != null
3578                 && activity.info != info.taskInfo.topActivityInfo
3579                 ? activity.info : null;
3580         info.isKeyguardOccluded =
3581             mAtmService.mKeyguardController.isDisplayOccluded(DEFAULT_DISPLAY);
3582 
3583         info.startingWindowTypeParameter = activity.mStartingData != null
3584                 ? activity.mStartingData.mTypeParams
3585                 : (StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED
3586                         | StartingWindowInfo.TYPE_PARAMETER_WINDOWLESS);
3587         if ((info.startingWindowTypeParameter
3588                 & StartingWindowInfo.TYPE_PARAMETER_ACTIVITY_CREATED) != 0) {
3589             final WindowState topMainWin = getWindow(w -> w.mAttrs.type == TYPE_BASE_APPLICATION);
3590             if (topMainWin != null) {
3591                 info.mainWindowLayoutParams = topMainWin.getAttrs();
3592                 info.requestedVisibleTypes = topMainWin.getRequestedVisibleTypes();
3593             }
3594         }
3595         // If the developer has persist a different configuration, we need to override it to the
3596         // starting window because persisted configuration does not effect to Task.
3597         info.taskInfo.configuration.setTo(activity.getConfiguration());
3598         final ActivityRecord topFullscreenActivity = getTopFullscreenActivity();
3599         if (topFullscreenActivity != null) {
3600             final WindowState topFullscreenOpaqueWindow =
3601                     topFullscreenActivity.getTopFullscreenOpaqueWindow();
3602             if (topFullscreenOpaqueWindow != null) {
3603                 info.topOpaqueWindowInsetsState =
3604                         topFullscreenOpaqueWindow.getInsetsStateWithVisibilityOverride();
3605                 info.topOpaqueWindowLayoutParams = topFullscreenOpaqueWindow.getAttrs();
3606             }
3607         }
3608         return info;
3609     }
3610 
3611     /**
3612      * Returns the {@link TaskFragmentParentInfo} which will send to the client
3613      * {@link android.window.TaskFragmentOrganizer}
3614      */
3615     TaskFragmentParentInfo getTaskFragmentParentInfo() {
3616         return new TaskFragmentParentInfo(getConfiguration(), getDisplayId(),
3617                 shouldBeVisible(null /* starting */));
3618     }
3619 
3620     @Override
3621     protected boolean onChildVisibleRequestedChanged(@Nullable WindowContainer child) {
3622         if (!super.onChildVisibleRequestedChanged(child)) return false;
3623         sendTaskFragmentParentInfoChangedIfNeeded();
3624         return true;
3625     }
3626 
3627     void sendTaskFragmentParentInfoChangedIfNeeded() {
3628         if (!isLeafTask()) {
3629             // Only send parent info changed event for leaf task.
3630             return;
3631         }
3632         final TaskFragment childOrganizedTf =
3633                 getTaskFragment(TaskFragment::isOrganizedTaskFragment);
3634         if (childOrganizedTf != null) {
3635             childOrganizedTf.sendTaskFragmentParentInfoChanged();
3636         }
3637     }
3638 
3639     boolean isTaskId(int taskId) {
3640         return mTaskId == taskId;
3641     }
3642 
3643     @Override
3644     Task asTask() {
3645         // I'm a task!
3646         return this;
3647     }
3648 
3649     ActivityRecord isInTask(ActivityRecord r) {
3650         if (r == null) {
3651             return null;
3652         }
3653         if (r.isDescendantOf(this)) {
3654             return r;
3655         }
3656         return null;
3657     }
3658 
3659     void dump(PrintWriter pw, String prefix) {
3660         pw.print(prefix); pw.print("userId="); pw.print(mUserId);
3661         pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
3662         pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
3663         pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
3664         pw.print(" mCallingPackage="); pw.print(mCallingPackage);
3665         pw.print(" mCallingFeatureId="); pw.println(mCallingFeatureId);
3666         if (affinity != null || rootAffinity != null) {
3667             pw.print(prefix); pw.print("affinity="); pw.print(affinity);
3668             if (affinity == null || !affinity.equals(rootAffinity)) {
3669                 pw.print(" root="); pw.println(rootAffinity);
3670             } else {
3671                 pw.println();
3672             }
3673         }
3674         if (mWindowLayoutAffinity != null) {
3675             pw.print(prefix); pw.print("windowLayoutAffinity="); pw.println(mWindowLayoutAffinity);
3676         }
3677         if (voiceSession != null || voiceInteractor != null) {
3678             pw.print(prefix); pw.print("VOICE: session=0x");
3679             pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
3680             pw.print(" interactor=0x");
3681             pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
3682         }
3683         if (intent != null) {
3684             StringBuilder sb = new StringBuilder(128);
3685             sb.append(prefix); sb.append("intent={");
3686             intent.toShortString(sb, false, true, false, false);
3687             sb.append('}');
3688             pw.println(sb.toString());
3689         }
3690         if (affinityIntent != null) {
3691             StringBuilder sb = new StringBuilder(128);
3692             sb.append(prefix); sb.append("affinityIntent={");
3693             affinityIntent.toShortString(sb, false, true, false, false);
3694             sb.append('}');
3695             pw.println(sb.toString());
3696         }
3697         if (origActivity != null) {
3698             pw.print(prefix); pw.print("origActivity=");
3699             pw.println(origActivity.flattenToShortString());
3700         }
3701         if (realActivity != null) {
3702             pw.print(prefix); pw.print("mActivityComponent=");
3703             pw.println(realActivity.flattenToShortString());
3704         }
3705         if (autoRemoveRecents || isPersistable || !isActivityTypeStandard()) {
3706             pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
3707             pw.print(" isPersistable="); pw.print(isPersistable);
3708             pw.print(" activityType="); pw.println(getActivityType());
3709         }
3710         if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
3711                 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
3712             pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
3713             pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
3714             pw.print(" mReuseTask="); pw.print(mReuseTask);
3715             pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
3716         }
3717         if (mAffiliatedTaskId != mTaskId || mPrevAffiliateTaskId != INVALID_TASK_ID
3718                 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
3719                 || mNextAffiliate != null) {
3720             pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
3721             pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
3722             pw.print(" (");
3723             if (mPrevAffiliate == null) {
3724                 pw.print("null");
3725             } else {
3726                 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
3727             }
3728             pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
3729             pw.print(" (");
3730             if (mNextAffiliate == null) {
3731                 pw.print("null");
3732             } else {
3733                 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
3734             }
3735             pw.println(")");
3736         }
3737         pw.print(prefix); pw.print("Activities="); pw.println(mChildren);
3738         if (!askedCompatMode || !inRecents || !isAvailable) {
3739             pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
3740             pw.print(" inRecents="); pw.print(inRecents);
3741             pw.print(" isAvailable="); pw.println(isAvailable);
3742         }
3743         if (lastDescription != null) {
3744             pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
3745         }
3746         if (mRootProcess != null) {
3747             pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
3748         }
3749         if (mSharedStartingData != null) {
3750             pw.println(prefix + "mSharedStartingData=" + mSharedStartingData);
3751         }
3752         if (mKillProcessesOnDestroyed) {
3753             pw.println(prefix + "mKillProcessesOnDestroyed=true");
3754         }
3755         pw.print(prefix); pw.print("taskId=" + mTaskId);
3756         pw.println(" rootTaskId=" + getRootTaskId());
3757         pw.print(prefix); pw.println("hasChildPipActivity=" + (mChildPipActivity != null));
3758         pw.print(prefix); pw.print("mHasBeenVisible="); pw.println(getHasBeenVisible());
3759         pw.print(prefix); pw.print("mResizeMode=");
3760         pw.print(ActivityInfo.resizeModeToString(mResizeMode));
3761         pw.print(" mSupportsPictureInPicture="); pw.print(mSupportsPictureInPicture);
3762         pw.print(" isResizeable="); pw.println(isResizeable());
3763         pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
3764         pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
3765     }
3766 
3767     @Override
3768     String toFullString() {
3769         final StringBuilder sb = new StringBuilder(192);
3770         sb.append(this);
3771         sb.setLength(sb.length() - 1); // Remove tail '}'.
3772         sb.append(" U=");
3773         sb.append(mUserId);
3774         final Task rootTask = getRootTask();
3775         if (rootTask != this) {
3776             sb.append(" rootTaskId=");
3777             sb.append(rootTask.mTaskId);
3778         }
3779         sb.append(" visible=");
3780         sb.append(shouldBeVisible(null /* starting */));
3781         sb.append(" visibleRequested=");
3782         sb.append(isVisibleRequested());
3783         sb.append(" mode=");
3784         sb.append(windowingModeToString(getWindowingMode()));
3785         sb.append(" translucent=");
3786         sb.append(isTranslucent(null /* starting */));
3787         sb.append(" sz=");
3788         sb.append(getChildCount());
3789         sb.append('}');
3790         return sb.toString();
3791     }
3792 
3793     @Override
3794     public String toString() {
3795         if (stringName != null) return stringName;
3796         StringBuilder sb = new StringBuilder(128);
3797         sb.append("Task{");
3798         sb.append(Integer.toHexString(System.identityHashCode(this)));
3799         sb.append(" #");
3800         sb.append(mTaskId);
3801         sb.append(" type=" + activityTypeToString(getActivityType()));
3802         if (affinity != null) {
3803             sb.append(" A=");
3804             sb.append(affinity);
3805         } else if (intent != null && intent.getComponent() != null) {
3806             sb.append(" I=");
3807             sb.append(intent.getComponent().flattenToShortString());
3808         } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
3809             sb.append(" aI=");
3810             sb.append(affinityIntent.getComponent().flattenToShortString());
3811         }
3812         sb.append('}');
3813         return stringName = sb.toString();
3814     }
3815 
3816     /**
3817      * Saves this {@link Task} to XML using given serializer.
3818      */
3819     void saveToXml(TypedXmlSerializer out) throws Exception {
3820         if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
3821 
3822         out.attributeInt(null, ATTR_TASKID, mTaskId);
3823         if (realActivity != null) {
3824             out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
3825         }
3826         out.attributeBoolean(null, ATTR_REALACTIVITY_SUSPENDED, realActivitySuspended);
3827         if (origActivity != null) {
3828             out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
3829         }
3830         // Write affinity, and root affinity if it is different from affinity.
3831         // We use the special string "@" for a null root affinity, so we can identify
3832         // later whether we were given a root affinity or should just make it the
3833         // same as the affinity.
3834         if (affinity != null) {
3835             out.attribute(null, ATTR_AFFINITY, affinity);
3836             if (!affinity.equals(rootAffinity)) {
3837                 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3838             }
3839         } else if (rootAffinity != null) {
3840             out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3841         }
3842         if (mWindowLayoutAffinity != null) {
3843             out.attribute(null, ATTR_WINDOW_LAYOUT_AFFINITY, mWindowLayoutAffinity);
3844         }
3845         out.attributeBoolean(null, ATTR_ROOTHASRESET, rootWasReset);
3846         out.attributeBoolean(null, ATTR_AUTOREMOVERECENTS, autoRemoveRecents);
3847         out.attributeBoolean(null, ATTR_ASKEDCOMPATMODE, askedCompatMode);
3848         out.attributeInt(null, ATTR_USERID, mUserId);
3849         out.attributeBoolean(null, ATTR_USER_SETUP_COMPLETE, mUserSetupComplete);
3850         out.attributeInt(null, ATTR_EFFECTIVE_UID, effectiveUid);
3851         out.attributeLong(null, ATTR_LASTTIMEMOVED, mLastTimeMoved);
3852         out.attributeBoolean(null, ATTR_NEVERRELINQUISH, mNeverRelinquishIdentity);
3853         if (lastDescription != null) {
3854             out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
3855         }
3856         if (getTaskDescription() != null) {
3857             getTaskDescription().saveToXml(out);
3858         }
3859         out.attributeInt(null, ATTR_TASK_AFFILIATION, mAffiliatedTaskId);
3860         out.attributeInt(null, ATTR_PREV_AFFILIATION, mPrevAffiliateTaskId);
3861         out.attributeInt(null, ATTR_NEXT_AFFILIATION, mNextAffiliateTaskId);
3862         out.attributeInt(null, ATTR_CALLING_UID, mCallingUid);
3863         out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
3864         out.attribute(null, ATTR_CALLING_FEATURE_ID,
3865                 mCallingFeatureId == null ? "" : mCallingFeatureId);
3866         out.attributeInt(null, ATTR_RESIZE_MODE, mResizeMode);
3867         out.attributeBoolean(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE, mSupportsPictureInPicture);
3868         if (mLastNonFullscreenBounds != null) {
3869             out.attribute(
3870                     null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
3871         }
3872         out.attributeInt(null, ATTR_MIN_WIDTH, mMinWidth);
3873         out.attributeInt(null, ATTR_MIN_HEIGHT, mMinHeight);
3874         out.attributeInt(null, ATTR_PERSIST_TASK_VERSION, PERSIST_TASK_VERSION);
3875 
3876         if (mLastTaskSnapshotData.taskSize != null) {
3877             out.attribute(null, ATTR_LAST_SNAPSHOT_TASK_SIZE,
3878                     mLastTaskSnapshotData.taskSize.flattenToString());
3879         }
3880         if (mLastTaskSnapshotData.contentInsets != null) {
3881             out.attribute(null, ATTR_LAST_SNAPSHOT_CONTENT_INSETS,
3882                     mLastTaskSnapshotData.contentInsets.flattenToString());
3883         }
3884         if (mLastTaskSnapshotData.bufferSize != null) {
3885             out.attribute(null, ATTR_LAST_SNAPSHOT_BUFFER_SIZE,
3886                     mLastTaskSnapshotData.bufferSize.flattenToString());
3887         }
3888 
3889         if (affinityIntent != null) {
3890             out.startTag(null, TAG_AFFINITYINTENT);
3891             affinityIntent.saveToXml(out);
3892             out.endTag(null, TAG_AFFINITYINTENT);
3893         }
3894 
3895         if (intent != null) {
3896             out.startTag(null, TAG_INTENT);
3897             intent.saveToXml(out);
3898             out.endTag(null, TAG_INTENT);
3899         }
3900 
3901         sTmpException = null;
3902         final PooledPredicate f = PooledLambda.obtainPredicate(Task::saveActivityToXml,
3903                 PooledLambda.__(ActivityRecord.class), getBottomMostActivity(), out);
3904         forAllActivities(f);
3905         f.recycle();
3906         if (sTmpException != null) {
3907             throw sTmpException;
3908         }
3909     }
3910 
3911     private static boolean saveActivityToXml(
3912             ActivityRecord r, ActivityRecord first, TypedXmlSerializer out) {
3913         if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable()
3914                 || ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
3915                 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT)
3916                 && r != first) {
3917             // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
3918             return true;
3919         }
3920         try {
3921             out.startTag(null, TAG_ACTIVITY);
3922             r.saveToXml(out);
3923             out.endTag(null, TAG_ACTIVITY);
3924             return false;
3925         } catch (Exception e) {
3926             sTmpException = e;
3927             return true;
3928         }
3929     }
3930 
3931     static Task restoreFromXml(TypedXmlPullParser in, ActivityTaskSupervisor taskSupervisor)
3932             throws IOException, XmlPullParserException {
3933         Intent intent = null;
3934         Intent affinityIntent = null;
3935         ArrayList<ActivityRecord> activities = new ArrayList<>();
3936         ComponentName realActivity = null;
3937         boolean realActivitySuspended = false;
3938         ComponentName origActivity = null;
3939         String affinity = null;
3940         String rootAffinity = null;
3941         boolean hasRootAffinity = false;
3942         String windowLayoutAffinity = null;
3943         boolean rootHasReset = false;
3944         boolean autoRemoveRecents = false;
3945         boolean askedCompatMode = false;
3946         int taskType = 0;
3947         int userId = 0;
3948         boolean userSetupComplete = true;
3949         int effectiveUid = -1;
3950         String lastDescription = null;
3951         long lastTimeOnTop = 0;
3952         boolean neverRelinquishIdentity = true;
3953         int taskId = INVALID_TASK_ID;
3954         final int outerDepth = in.getDepth();
3955         TaskDescription taskDescription = new TaskDescription();
3956         PersistedTaskSnapshotData lastSnapshotData = new PersistedTaskSnapshotData();
3957         int taskAffiliation = INVALID_TASK_ID;
3958         int prevTaskId = INVALID_TASK_ID;
3959         int nextTaskId = INVALID_TASK_ID;
3960         int callingUid = -1;
3961         String callingPackage = "";
3962         String callingFeatureId = null;
3963         int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
3964         boolean supportsPictureInPicture = false;
3965         Rect lastNonFullscreenBounds = null;
3966         int minWidth = INVALID_MIN_SIZE;
3967         int minHeight = INVALID_MIN_SIZE;
3968         int persistTaskVersion = 0;
3969 
3970         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
3971             final String attrName = in.getAttributeName(attrNdx);
3972             final String attrValue = in.getAttributeValue(attrNdx);
3973             if (TaskPersister.DEBUG) {
3974                 Slog.d(TaskPersister.TAG, "Task: attribute name=" + attrName + " value="
3975                         + attrValue);
3976             }
3977             switch (attrName) {
3978                 case ATTR_TASKID:
3979                     if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
3980                     break;
3981                 case ATTR_REALACTIVITY:
3982                     realActivity = ComponentName.unflattenFromString(attrValue);
3983                     break;
3984                 case ATTR_REALACTIVITY_SUSPENDED:
3985                     realActivitySuspended = Boolean.valueOf(attrValue);
3986                     break;
3987                 case ATTR_ORIGACTIVITY:
3988                     origActivity = ComponentName.unflattenFromString(attrValue);
3989                     break;
3990                 case ATTR_AFFINITY:
3991                     affinity = attrValue;
3992                     break;
3993                 case ATTR_ROOT_AFFINITY:
3994                     rootAffinity = attrValue;
3995                     hasRootAffinity = true;
3996                     break;
3997                 case ATTR_WINDOW_LAYOUT_AFFINITY:
3998                     windowLayoutAffinity = attrValue;
3999                     break;
4000                 case ATTR_ROOTHASRESET:
4001                     rootHasReset = Boolean.parseBoolean(attrValue);
4002                     break;
4003                 case ATTR_AUTOREMOVERECENTS:
4004                     autoRemoveRecents = Boolean.parseBoolean(attrValue);
4005                     break;
4006                 case ATTR_ASKEDCOMPATMODE:
4007                     askedCompatMode = Boolean.parseBoolean(attrValue);
4008                     break;
4009                 case ATTR_USERID:
4010                     userId = Integer.parseInt(attrValue);
4011                     break;
4012                 case ATTR_USER_SETUP_COMPLETE:
4013                     userSetupComplete = Boolean.parseBoolean(attrValue);
4014                     break;
4015                 case ATTR_EFFECTIVE_UID:
4016                     effectiveUid = Integer.parseInt(attrValue);
4017                     break;
4018                 case ATTR_TASKTYPE:
4019                     taskType = Integer.parseInt(attrValue);
4020                     break;
4021                 case ATTR_LASTDESCRIPTION:
4022                     lastDescription = attrValue;
4023                     break;
4024                 case ATTR_LASTTIMEMOVED:
4025                     lastTimeOnTop = Long.parseLong(attrValue);
4026                     break;
4027                 case ATTR_NEVERRELINQUISH:
4028                     neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
4029                     break;
4030                 case ATTR_TASK_AFFILIATION:
4031                     taskAffiliation = Integer.parseInt(attrValue);
4032                     break;
4033                 case ATTR_PREV_AFFILIATION:
4034                     prevTaskId = Integer.parseInt(attrValue);
4035                     break;
4036                 case ATTR_NEXT_AFFILIATION:
4037                     nextTaskId = Integer.parseInt(attrValue);
4038                     break;
4039                 case ATTR_CALLING_UID:
4040                     callingUid = Integer.parseInt(attrValue);
4041                     break;
4042                 case ATTR_CALLING_PACKAGE:
4043                     callingPackage = attrValue;
4044                     break;
4045                 case ATTR_CALLING_FEATURE_ID:
4046                     callingFeatureId = attrValue;
4047                     break;
4048                 case ATTR_RESIZE_MODE:
4049                     resizeMode = Integer.parseInt(attrValue);
4050                     break;
4051                 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
4052                     supportsPictureInPicture = Boolean.parseBoolean(attrValue);
4053                     break;
4054                 case ATTR_NON_FULLSCREEN_BOUNDS:
4055                     lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
4056                     break;
4057                 case ATTR_MIN_WIDTH:
4058                     minWidth = Integer.parseInt(attrValue);
4059                     break;
4060                 case ATTR_MIN_HEIGHT:
4061                     minHeight = Integer.parseInt(attrValue);
4062                     break;
4063                 case ATTR_PERSIST_TASK_VERSION:
4064                     persistTaskVersion = Integer.parseInt(attrValue);
4065                     break;
4066                 case ATTR_LAST_SNAPSHOT_TASK_SIZE:
4067                     lastSnapshotData.taskSize = Point.unflattenFromString(attrValue);
4068                     break;
4069                 case ATTR_LAST_SNAPSHOT_CONTENT_INSETS:
4070                     lastSnapshotData.contentInsets = Rect.unflattenFromString(attrValue);
4071                     break;
4072                 case ATTR_LAST_SNAPSHOT_BUFFER_SIZE:
4073                     lastSnapshotData.bufferSize = Point.unflattenFromString(attrValue);
4074                     break;
4075                 default:
4076                     if (!attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
4077                         Slog.w(TAG, "Task: Unknown attribute=" + attrName);
4078                     }
4079             }
4080         }
4081         taskDescription.restoreFromXml(in);
4082 
4083         int event;
4084         while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
4085                 && (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
4086             if (event == XmlPullParser.START_TAG) {
4087                 final String name = in.getName();
4088                 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: START_TAG name=" + name);
4089                 if (TAG_AFFINITYINTENT.equals(name)) {
4090                     affinityIntent = Intent.restoreFromXml(in);
4091                 } else if (TAG_INTENT.equals(name)) {
4092                     intent = Intent.restoreFromXml(in);
4093                 } else if (TAG_ACTIVITY.equals(name)) {
4094                     ActivityRecord activity =
4095                             ActivityRecord.restoreFromXml(in, taskSupervisor);
4096                     if (TaskPersister.DEBUG) {
4097                         Slog.d(TaskPersister.TAG, "Task: activity=" + activity);
4098                     }
4099                     if (activity != null) {
4100                         activities.add(activity);
4101                     }
4102                 } else {
4103                     Slog.e(TAG, "restoreTask: Unexpected name=" + name);
4104                     XmlUtils.skipCurrentTag(in);
4105                 }
4106             }
4107         }
4108         if (!hasRootAffinity) {
4109             rootAffinity = affinity;
4110         } else if ("@".equals(rootAffinity)) {
4111             rootAffinity = null;
4112         }
4113         if (effectiveUid <= 0) {
4114             Intent checkIntent = intent != null ? intent : affinityIntent;
4115             effectiveUid = 0;
4116             if (checkIntent != null) {
4117                 IPackageManager pm = AppGlobals.getPackageManager();
4118                 try {
4119                     ApplicationInfo ai = pm.getApplicationInfo(
4120                             checkIntent.getComponent().getPackageName(),
4121                             PackageManager.MATCH_UNINSTALLED_PACKAGES
4122                                     | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
4123                     if (ai != null) {
4124                         effectiveUid = ai.uid;
4125                     }
4126                 } catch (RemoteException e) {
4127                 }
4128             }
4129             Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
4130                     + ": effectiveUid=" + effectiveUid);
4131         }
4132 
4133         if (persistTaskVersion < 1) {
4134             // We need to convert the resize mode of home activities saved before version one if
4135             // they are marked as RESIZE_MODE_RESIZEABLE to
4136             // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
4137             // before version 1 and the system didn't resize home activities before then.
4138             if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
4139                 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4140             }
4141         } else {
4142             // This activity has previously marked itself explicitly as both resizeable and
4143             // supporting picture-in-picture.  Since there is no longer a requirement for
4144             // picture-in-picture activities to be resizeable, we can mark this simply as
4145             // resizeable and supporting picture-in-picture separately.
4146             if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
4147                 resizeMode = RESIZE_MODE_RESIZEABLE;
4148                 supportsPictureInPicture = true;
4149             }
4150         }
4151 
4152         final Task task = new Task.Builder(taskSupervisor.mService)
4153                 .setTaskId(taskId)
4154                 .setIntent(intent)
4155                 .setAffinityIntent(affinityIntent)
4156                 .setAffinity(affinity)
4157                 .setRootAffinity(rootAffinity)
4158                 .setRealActivity(realActivity)
4159                 .setOrigActivity(origActivity)
4160                 .setRootWasReset(rootHasReset)
4161                 .setAutoRemoveRecents(autoRemoveRecents)
4162                 .setAskedCompatMode(askedCompatMode)
4163                 .setUserId(userId)
4164                 .setEffectiveUid(effectiveUid)
4165                 .setLastDescription(lastDescription)
4166                 .setLastTimeMoved(lastTimeOnTop)
4167                 .setNeverRelinquishIdentity(neverRelinquishIdentity)
4168                 .setLastTaskDescription(taskDescription)
4169                 .setLastSnapshotData(lastSnapshotData)
4170                 .setTaskAffiliation(taskAffiliation)
4171                 .setPrevAffiliateTaskId(prevTaskId)
4172                 .setNextAffiliateTaskId(nextTaskId)
4173                 .setCallingUid(callingUid)
4174                 .setCallingPackage(callingPackage)
4175                 .setCallingFeatureId(callingFeatureId)
4176                 .setResizeMode(resizeMode)
4177                 .setSupportsPictureInPicture(supportsPictureInPicture)
4178                 .setRealActivitySuspended(realActivitySuspended)
4179                 .setUserSetupComplete(userSetupComplete)
4180                 .setMinWidth(minWidth)
4181                 .setMinHeight(minHeight)
4182                 .buildInner();
4183         task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
4184         task.setBounds(lastNonFullscreenBounds);
4185         task.mWindowLayoutAffinity = windowLayoutAffinity;
4186         if (activities.size() > 0) {
4187             // We need to add the task into hierarchy before adding child to it.
4188             final DisplayContent dc =
4189                     taskSupervisor.mRootWindowContainer.getDisplayContent(DEFAULT_DISPLAY);
4190             dc.getDefaultTaskDisplayArea().addChild(task, POSITION_BOTTOM);
4191 
4192             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4193                 task.addChild(activities.get(activityNdx));
4194             }
4195         }
4196 
4197         if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
4198         return task;
4199     }
4200 
4201     @Override
4202     boolean isOrganized() {
4203         return mTaskOrganizer != null;
4204     }
4205 
4206     private boolean canBeOrganized() {
4207         // All root tasks can be organized
4208         if (isRootTask() || mCreatedByOrganizer) {
4209             return true;
4210         }
4211 
4212         // Task could be organized if it's the direct child of a task created by organizer.
4213         final Task parentTask = getParent().asTask();
4214         return parentTask != null && parentTask.mCreatedByOrganizer;
4215     }
4216 
4217     @Override
4218     boolean showSurfaceOnCreation() {
4219         return false;
4220     }
4221 
4222     @Override
4223     protected void reparentSurfaceControl(SurfaceControl.Transaction t, SurfaceControl newParent) {
4224         /**
4225          * Avoid reparenting SurfaceControl of the organized tasks that are always on top, since
4226          * the surfaces should be controlled by the organizer itself, like bubbles.
4227          */
4228         if (isOrganized() && isAlwaysOnTop()) {
4229             return;
4230         }
4231         super.reparentSurfaceControl(t, newParent);
4232     }
4233 
4234     void setHasBeenVisible(boolean hasBeenVisible) {
4235         mHasBeenVisible = hasBeenVisible;
4236         if (!hasBeenVisible || mDeferTaskAppear) {
4237             return;
4238         }
4239         sendTaskAppeared();
4240         for (WindowContainer<?> parent = getParent(); parent != null; parent = parent.getParent()) {
4241             final Task parentTask = parent.asTask();
4242             if (parentTask == null) {
4243                 break;
4244             }
4245             parentTask.setHasBeenVisible(true);
4246         }
4247     }
4248 
4249 
4250     boolean getHasBeenVisible() {
4251         return mHasBeenVisible;
4252     }
4253 
4254     void setDeferTaskAppear(boolean deferTaskAppear) {
4255         final boolean wasDeferred = mDeferTaskAppear;
4256         mDeferTaskAppear = deferTaskAppear;
4257         if (wasDeferred && !deferTaskAppear) {
4258             sendTaskAppeared();
4259         }
4260     }
4261 
4262     /** In the case that these conditions are true, we want to send the Task to the organizer:
4263      *     1. An organizer has been set
4264      *     2. The Task was created by the organizer
4265      *     or
4266      *     2a. We have a SurfaceControl
4267      *     2b. We have finished drawing
4268      * Any time any of these conditions are updated, the updating code should call
4269      * sendTaskAppeared.
4270      */
4271     boolean taskAppearedReady() {
4272         if (mTaskOrganizer == null) {
4273             return false;
4274         }
4275 
4276         if (mDeferTaskAppear) {
4277             return false;
4278         }
4279 
4280         if (mCreatedByOrganizer) {
4281             return true;
4282         }
4283 
4284         return mSurfaceControl != null && getHasBeenVisible();
4285     }
4286 
4287     private void sendTaskAppeared() {
4288         if (mTaskOrganizer != null) {
4289             mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this);
4290         }
4291     }
4292 
4293     private void sendTaskVanished(ITaskOrganizer organizer) {
4294         if (organizer != null) {
4295             mAtmService.mTaskOrganizerController.onTaskVanished(organizer, this);
4296         }
4297    }
4298 
4299     @VisibleForTesting
4300     boolean setTaskOrganizer(ITaskOrganizer organizer) {
4301         return setTaskOrganizer(organizer, false /* skipTaskAppeared */);
4302     }
4303 
4304     @VisibleForTesting
4305     boolean setTaskOrganizer(ITaskOrganizer organizer, boolean skipTaskAppeared) {
4306         if (mTaskOrganizer == organizer) {
4307             return false;
4308         }
4309 
4310         ITaskOrganizer prevOrganizer = mTaskOrganizer;
4311         // Update the new task organizer before calling sendTaskVanished since it could result in
4312         // a new SurfaceControl getting created that would notify the old organizer about it.
4313         mTaskOrganizer = organizer;
4314         // Let the old organizer know it has lost control.
4315         sendTaskVanished(prevOrganizer);
4316 
4317         if (mTaskOrganizer != null) {
4318             if (!skipTaskAppeared) {
4319                 sendTaskAppeared();
4320             }
4321         } else {
4322             // No longer managed by any organizer.
4323             final TaskDisplayArea taskDisplayArea = getDisplayArea();
4324             if (taskDisplayArea != null) {
4325                 taskDisplayArea.removeLaunchRootTask(this);
4326             }
4327             setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */);
4328             if (mCreatedByOrganizer) {
4329                 removeImmediately("setTaskOrganizer");
4330             }
4331         }
4332 
4333         return true;
4334     }
4335 
4336     boolean updateTaskOrganizerState() {
4337         return updateTaskOrganizerState(false /* skipTaskAppeared */);
4338     }
4339 
4340     /**
4341      * Called when the task state changes (ie. from windowing mode change) an the task organizer
4342      * state should also be updated.
4343      *
4344      * @param skipTaskAppeared Skips calling taskAppeared for the new organizer if it has changed
4345      * @return {@code true} if task organizer changed.
4346      */
4347     boolean updateTaskOrganizerState(boolean skipTaskAppeared) {
4348         if (getSurfaceControl() == null) {
4349             // Can't call onTaskAppeared without a surfacecontrol, so defer this until next one
4350             // is created.
4351             return false;
4352         }
4353         if (!canBeOrganized()) {
4354             return setTaskOrganizer(null);
4355         }
4356 
4357         final TaskOrganizerController controller = mWmService.mAtmService.mTaskOrganizerController;
4358         final ITaskOrganizer organizer = controller.getTaskOrganizer();
4359         // Do not change to different organizer if the task is created by organizer because only
4360         // the creator knows how to manage it.
4361         if (mCreatedByOrganizer && mTaskOrganizer != null && organizer != null
4362                 && mTaskOrganizer != organizer) {
4363             return false;
4364         }
4365         return setTaskOrganizer(organizer, skipTaskAppeared);
4366     }
4367 
4368     @Override
4369     void setSurfaceControl(SurfaceControl sc) {
4370         super.setSurfaceControl(sc);
4371         // If the TaskOrganizer was set before we created the SurfaceControl, we need to
4372         // emit the callbacks now.
4373         sendTaskAppeared();
4374     }
4375 
4376     /**
4377      * @return {@code true} if the task is currently focused or one of its children is focused.
4378      */
4379     boolean isFocused() {
4380         if (mDisplayContent == null || mDisplayContent.mFocusedApp == null) {
4381             return false;
4382         }
4383         final Task focusedTask = mDisplayContent.mFocusedApp.getTask();
4384         return focusedTask == this || (focusedTask != null && focusedTask.getParent() == this);
4385     }
4386 
4387     /**
4388      * @return true if the task is visible and has at least one visible child.
4389      */
4390     private boolean hasVisibleChildren() {
4391         if (!isAttached() || isForceHidden()) {
4392             return false;
4393         }
4394 
4395         return getActivity(ActivityRecord::isVisible) != null;
4396     }
4397 
4398     /**
4399      * Called on the task when it gained or lost focus.
4400      * @param hasFocus
4401      */
4402     void onAppFocusChanged(boolean hasFocus) {
4403         dispatchTaskInfoChangedIfNeeded(false /* force */);
4404         final Task parentTask = getParent().asTask();
4405         if (parentTask != null) parentTask.dispatchTaskInfoChangedIfNeeded(false /* force */);
4406 
4407         mAtmService.getTaskChangeNotificationController().notifyTaskFocusChanged(mTaskId, hasFocus);
4408     }
4409 
4410     void onPictureInPictureParamsChanged() {
4411         if (inPinnedWindowingMode()) {
4412             dispatchTaskInfoChangedIfNeeded(true /* force */);
4413         }
4414     }
4415 
4416     void onShouldDockBigOverlaysChanged() {
4417         dispatchTaskInfoChangedIfNeeded(true /* force */);
4418     }
4419 
4420     /** Called when the top activity in the Root Task enters or exits size compat mode. */
4421     void onSizeCompatActivityChanged() {
4422         // Trigger TaskInfoChanged to update the size compat restart button.
4423         dispatchTaskInfoChangedIfNeeded(true /* force */);
4424     }
4425 
4426     /**
4427      * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this
4428      * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy
4429      * to resize, and it will defer the transaction until that resize frame completes.
4430      */
4431     void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t) {
4432         setMainWindowSizeChangeTransaction(t, this);
4433         forAllWindows(WindowState::requestRedrawForSync, true);
4434     }
4435 
4436     private void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t, Task origin) {
4437         // This is only meaningful on an activity's task, so put it on the top one.
4438         ActivityRecord topActivity = getTopNonFinishingActivity();
4439         Task leaf = topActivity != null ? topActivity.getTask() : null;
4440         if (leaf == null) {
4441             return;
4442         }
4443         if (leaf != this) {
4444             leaf.setMainWindowSizeChangeTransaction(t, origin);
4445             return;
4446         }
4447         final WindowState w = getTopVisibleAppMainWindow();
4448         if (w != null) {
4449             w.applyWithNextDraw((d) -> {
4450                 d.merge(t);
4451             });
4452         } else {
4453             t.apply();
4454         }
4455     }
4456 
4457     /**
4458      * Sets/unsets the forced-hidden state flag for this task depending on {@param set}.
4459      * @return Whether the force hidden state changed
4460      */
4461     boolean setForceHidden(int flags, boolean set) {
4462         int newFlags = mForceHiddenFlags;
4463         if (set) {
4464             newFlags |= flags;
4465         } else {
4466             newFlags &= ~flags;
4467         }
4468         if (mForceHiddenFlags == newFlags) {
4469             return false;
4470         }
4471 
4472         final boolean wasHidden = isForceHidden();
4473         final boolean wasVisible = isVisible();
4474         mForceHiddenFlags = newFlags;
4475         final boolean nowHidden = isForceHidden();
4476         if (wasHidden != nowHidden) {
4477             final String reason = "setForceHidden";
4478             if (wasVisible && nowHidden) {
4479                 // Move this visible task to back when the task is forced hidden
4480                 moveToBack(reason, null);
4481             } else if (isAlwaysOnTop()) {
4482                 // Move this always-on-top task to front when no longer hidden
4483                 moveToFront(reason);
4484             }
4485         }
4486         return true;
4487     }
4488 
4489     void setForceTranslucent(boolean set) {
4490         mForceTranslucent = set;
4491     }
4492 
4493     @Override
4494     public boolean isAlwaysOnTop() {
4495         return !isForceHidden() && super.isAlwaysOnTop();
4496     }
4497 
4498     /**
4499      * @return whether this task is always on top without taking visibility into account.
4500      */
4501     public boolean isAlwaysOnTopWhenVisible() {
4502         return super.isAlwaysOnTop();
4503     }
4504 
4505     @Override
4506     protected boolean isForceHidden() {
4507         return mForceHiddenFlags != 0;
4508     }
4509 
4510     boolean isForceHiddenForPinnedTask() {
4511         return (mForceHiddenFlags & FLAG_FORCE_HIDDEN_FOR_PINNED_TASK) != 0;
4512     }
4513 
4514     @Override
4515     protected boolean isForceTranslucent() {
4516         return mForceTranslucent;
4517     }
4518 
4519     @Override
4520     long getProtoFieldId() {
4521         return TASK;
4522     }
4523 
4524     @Override
4525     public void setWindowingMode(int windowingMode) {
4526         // Calling Task#setWindowingMode() for leaf task since this is the a specialization of
4527         // {@link #setWindowingMode(int)} for root task.
4528         if (!isRootTask()) {
4529             super.setWindowingMode(windowingMode);
4530             return;
4531         }
4532 
4533         setWindowingMode(windowingMode, false /* creating */);
4534     }
4535 
4536     /**
4537      * Specialization of {@link #setWindowingMode(int)} for this subclass.
4538      *
4539      * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending
4540      *         on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the
4541      *         previous non-transient mode if this root task is currently in a transient mode.
4542      * @param creating {@code true} if this is being run during task construction.
4543      */
4544     void setWindowingMode(int preferredWindowingMode, boolean creating) {
4545         mWmService.inSurfaceTransaction(() -> setWindowingModeInSurfaceTransaction(
4546                 preferredWindowingMode, creating));
4547     }
4548 
4549     private void setWindowingModeInSurfaceTransaction(int preferredWindowingMode,
4550             boolean creating) {
4551         final TaskDisplayArea taskDisplayArea = getDisplayArea();
4552         if (taskDisplayArea == null) {
4553             Slog.d(TAG, "taskDisplayArea is null, bail early");
4554             return;
4555         }
4556         final int currentMode = getWindowingMode();
4557         final Task topTask = getTopMostTask();
4558         int windowingMode = preferredWindowingMode;
4559 
4560         // Need to make sure windowing mode is supported. If we in the process of creating the
4561         // root task no need to resolve the windowing mode again as it is already resolved to the
4562         // right mode.
4563         if (!creating) {
4564             if (!taskDisplayArea.isValidWindowingMode(windowingMode, null /* ActivityRecord */,
4565                     topTask)) {
4566                 windowingMode = WINDOWING_MODE_UNDEFINED;
4567             }
4568         }
4569 
4570         if (currentMode == windowingMode) {
4571             // You are already in the window mode, so we can skip most of the work below. However,
4572             // it's possible that we have inherited the current windowing mode from a parent. So,
4573             // fulfill this method's contract by setting the override mode directly.
4574             getRequestedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
4575             return;
4576         }
4577 
4578         final ActivityRecord topActivity = getTopNonFinishingActivity();
4579 
4580         // For now, assume that the root task's windowing mode is what will actually be used
4581         // by it's activities. In the future, there may be situations where this doesn't
4582         // happen; so at that point, this message will need to handle that.
4583         int likelyResolvedMode = windowingMode;
4584         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
4585             final ConfigurationContainer parent = getParent();
4586             likelyResolvedMode = parent != null ? parent.getWindowingMode()
4587                     : WINDOWING_MODE_FULLSCREEN;
4588         }
4589         if (currentMode == WINDOWING_MODE_PINNED) {
4590             // In the case that we've disabled affecting the SysUI flags as a part of seamlessly
4591             // transferring the transform on the leash to the task, reset this state once we're
4592             // moving out of pip
4593             setCanAffectSystemUiFlags(true);
4594             // Turn on userLeaveHint so other app can enter PiP mode.
4595             mTaskSupervisor.mUserLeaving = true;
4596             // Allow entering PiP from current top most activity when we are leaving PiP.
4597             final Task topFocused = mRootWindowContainer.getTopDisplayFocusedRootTask();
4598             if (topFocused != null) {
4599                 final ActivityRecord ar = topFocused.getTopResumedActivity();
4600                 enableEnterPipOnTaskSwitch(ar, null /* toFrontTask */, ar, null /* opts */);
4601             }
4602             mRootWindowContainer.notifyActivityPipModeChanged(this, null);
4603         }
4604         if (likelyResolvedMode == WINDOWING_MODE_PINNED) {
4605             if (taskDisplayArea.getRootPinnedTask() != null) {
4606                 // Can only have 1 pip at a time, so replace an existing pip
4607                 taskDisplayArea.getRootPinnedTask().dismissPip();
4608             }
4609         }
4610         if (likelyResolvedMode != WINDOWING_MODE_FULLSCREEN
4611                 && topActivity != null && !topActivity.noDisplay
4612                 && topActivity.canForceResizeNonResizable(likelyResolvedMode)) {
4613             // Inform the user that they are starting an app that may not work correctly in
4614             // multi-window mode.
4615             final String packageName = topActivity.info.applicationInfo.packageName;
4616             mAtmService.getTaskChangeNotificationController().notifyActivityForcedResizable(
4617                     topTask.mTaskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName);
4618         }
4619 
4620         mAtmService.deferWindowLayout();
4621         try {
4622             if (topActivity != null) {
4623                 mTaskSupervisor.mNoAnimActivities.add(topActivity);
4624             }
4625             super.setWindowingMode(windowingMode);
4626 
4627             if (currentMode == WINDOWING_MODE_PINNED && topActivity != null) {
4628                 // Try reparent pinned activity back to its original task after
4629                 // onConfigurationChanged cascade finishes. This is done on Task level instead of
4630                 // {@link ActivityRecord#onConfigurationChanged(Configuration)} since when we exit
4631                 // PiP, we set final windowing mode on the ActivityRecord first and then on its
4632                 // Task when the exit PiP transition finishes. Meanwhile, the exit transition is
4633                 // always performed on its original task, reparent immediately in ActivityRecord
4634                 // breaks it.
4635                 if (topActivity.getLastParentBeforePip() != null) {
4636                     // Do not reparent if the pinned task is in removal, indicated by the
4637                     // force hidden flag.
4638                     if (!isForceHidden()) {
4639                         final Task lastParentBeforePip = topActivity.getLastParentBeforePip();
4640                         if (lastParentBeforePip.isAttached()) {
4641                             topActivity.reparent(lastParentBeforePip,
4642                                     lastParentBeforePip.getChildCount() /* top */,
4643                                     "movePinnedActivityToOriginalTask");
4644                             final DisplayContent dc = topActivity.getDisplayContent();
4645                             if (dc != null && dc.isFixedRotationLaunchingApp(topActivity)) {
4646                                 // Expanding pip into new rotation, so create a rotation leash
4647                                 // until the display is rotated.
4648                                 topActivity.getOrCreateFixedRotationLeash(
4649                                         topActivity.getSyncTransaction());
4650                             }
4651                             lastParentBeforePip.moveToFront("movePinnedActivityToOriginalTask");
4652                         }
4653                     }
4654                 }
4655                 // Resume app-switches-allowed flag when exiting from pinned mode since
4656                 // it does not follow the ActivityStarter path.
4657                 if (topActivity.shouldBeVisible()) {
4658                     mAtmService.resumeAppSwitches();
4659                 }
4660             }
4661 
4662             if (creating) {
4663                 // Nothing else to do if we don't have a window container yet. E.g. call from ctor.
4664                 return;
4665             }
4666 
4667             // From fullscreen to PiP.
4668             if (topActivity != null && currentMode == WINDOWING_MODE_FULLSCREEN
4669                     && windowingMode == WINDOWING_MODE_PINNED
4670                     && !mTransitionController.isShellTransitionsEnabled()) {
4671                 mDisplayContent.mPinnedTaskController
4672                         .deferOrientationChangeForEnteringPipFromFullScreenIfNeeded();
4673             }
4674         } finally {
4675             mAtmService.continueWindowLayout();
4676         }
4677 
4678         if (!mTaskSupervisor.isRootVisibilityUpdateDeferred()) {
4679             mRootWindowContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS);
4680             mRootWindowContainer.resumeFocusedTasksTopActivities();
4681         }
4682     }
4683 
4684     /**
4685      * Abort an incomplete pip-entry. If left in this state, it will cover everything but remain
4686      * paused. If this is needed, there is a bug -- this should only be used for recovery.
4687      */
4688     void abortPipEnter(ActivityRecord top) {
4689         // an incomplete state has the task PINNED but the activity not.
4690         if (!inPinnedWindowingMode() || top.inPinnedWindowingMode() || !canMoveTaskToBack(this)) {
4691             return;
4692         }
4693         final Transition transition = new Transition(TRANSIT_TO_BACK, 0 /* flags */,
4694                 mTransitionController, mWmService.mSyncEngine);
4695         mTransitionController.moveToCollecting(transition);
4696         mTransitionController.requestStartTransition(transition, this, null /* remoteTransition */,
4697                 null /* displayChange */);
4698         if (top.getLastParentBeforePip() != null) {
4699             final Task lastParentBeforePip = top.getLastParentBeforePip();
4700             if (lastParentBeforePip.isAttached()) {
4701                 top.reparent(lastParentBeforePip, lastParentBeforePip.getChildCount() /* top */,
4702                         "movePinnedActivityToOriginalTask");
4703             }
4704         }
4705         if (isAttached()) {
4706             setWindowingMode(WINDOWING_MODE_UNDEFINED);
4707             moveTaskToBackInner(this);
4708         }
4709         if (top.isAttached()) {
4710             top.setWindowingMode(WINDOWING_MODE_UNDEFINED);
4711         }
4712     }
4713 
4714     void resumeNextFocusAfterReparent() {
4715         adjustFocusToNextFocusableTask("reparent", true /* allowFocusSelf */,
4716                 true /* moveDisplayToTop */);
4717         mRootWindowContainer.resumeFocusedTasksTopActivities();
4718         // Update visibility of activities before notifying WM. This way it won't try to resize
4719         // windows that are no longer visible.
4720         mRootWindowContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
4721                 !PRESERVE_WINDOWS);
4722     }
4723 
4724     final boolean isOnHomeDisplay() {
4725         return getDisplayId() == DEFAULT_DISPLAY;
4726     }
4727 
4728     void moveToFront(String reason) {
4729         moveToFront(reason, null);
4730     }
4731 
4732     /**
4733      * @param reason The reason for moving the root task to the front.
4734      * @param task If non-null, the task will be moved to the top of the root task.
4735      */
4736     @VisibleForTesting
4737     void moveToFront(String reason, Task task) {
4738         if (!isAttached()) {
4739             return;
4740         }
4741         mTransitionController.recordTaskOrder(this);
4742 
4743         final TaskDisplayArea taskDisplayArea = getDisplayArea();
4744 
4745         if (!isActivityTypeHome() && returnsToHomeRootTask()) {
4746             // Make sure the root home task is behind this root task since that is where we
4747             // should return to when this root task is no longer visible.
4748             taskDisplayArea.moveHomeRootTaskToFront(reason + " returnToHome");
4749         }
4750 
4751         final Task lastFocusedTask = isRootTask() ? taskDisplayArea.getFocusedRootTask() : null;
4752         if (task == null) {
4753             task = this;
4754         }
4755         task.getParent().positionChildAt(POSITION_TOP, task, true /* includingParents */);
4756         taskDisplayArea.updateLastFocusedRootTask(lastFocusedTask, reason);
4757     }
4758 
4759     /**
4760      * This moves 'task' to the back of this task and also recursively moves this task to the back
4761      * of its parents (if applicable).
4762      *
4763      * @param reason The reason for moving the root task to the back.
4764      * @param task If non-null, the task will be moved to the bottom of the root task.
4765      **/
4766     void moveToBack(String reason, Task task) {
4767         if (!isAttached()) {
4768             return;
4769         }
4770         final TaskDisplayArea displayArea = getDisplayArea();
4771         if (!mCreatedByOrganizer) {
4772             // If this is just a normal task, so move to back of parent and then move 'task' to
4773             // back of this.
4774             final WindowContainer parent = getParent();
4775             final Task parentTask = parent != null ? parent.asTask() : null;
4776             if (parentTask != null) {
4777                 parentTask.moveToBack(reason, this);
4778             } else {
4779                 final Task lastFocusedTask = displayArea.getFocusedRootTask();
4780                 displayArea.positionChildAt(POSITION_BOTTOM, this, false /*includingParents*/);
4781                 displayArea.updateLastFocusedRootTask(lastFocusedTask, reason);
4782             }
4783             if (task != null && task != this) {
4784                 positionChildAtBottom(task);
4785             }
4786             return;
4787         }
4788         if (task == null || task == this) {
4789             return;
4790         }
4791         // This is a created-by-organizer task. In this case, let the organizer deal with this
4792         // task's ordering. However, we still need to move 'task' to back. The intention is that
4793         // this ends up behind the home-task so that it is made invisible; so, if the home task
4794         // is not a child of this, reparent 'task' to the back of the home task's actual parent.
4795         displayArea.positionTaskBehindHome(task);
4796     }
4797 
4798     // TODO: Should each user have there own root tasks?
4799     @Override
4800     void switchUser(int userId) {
4801         if (mCurrentUser == userId) {
4802             return;
4803         }
4804         mCurrentUser = userId;
4805 
4806         super.switchUser(userId);
4807         if (!isRootTask() && showToCurrentUser()) {
4808             getParent().positionChildAt(POSITION_TOP, this, false /*includeParents*/);
4809         }
4810     }
4811 
4812     void minimalResumeActivityLocked(ActivityRecord r) {
4813         ProtoLog.v(WM_DEBUG_STATES, "Moving to RESUMED: %s (starting new instance) "
4814                 + "callers=%s", r, Debug.getCallers(5));
4815         r.setState(RESUMED, "minimalResumeActivityLocked");
4816         r.completeResumeLocked();
4817     }
4818 
4819     void checkReadyForSleep() {
4820         if (shouldSleepActivities() && goToSleepIfPossible(false /* shuttingDown */)) {
4821             mTaskSupervisor.checkReadyForSleepLocked(true /* allowDelay */);
4822         }
4823     }
4824 
4825     /**
4826      * Tries to put the activities in the root task to sleep.
4827      *
4828      * If the root task is not in a state where its activities can be put to sleep, this function
4829      * will start any necessary actions to move the root task into such a state. It is expected
4830      * that this function get called again when those actions complete.
4831      *
4832      * @param shuttingDown true when the called because the device is shutting down.
4833      * @return true if the root task finished going to sleep, false if the root task only started
4834      * the process of going to sleep (checkReadyForSleep will be called when that process finishes).
4835      */
4836     boolean goToSleepIfPossible(boolean shuttingDown) {
4837         final int[] sleepInProgress = {0};
4838         forAllLeafTasksAndLeafTaskFragments(taskFragment -> {
4839             if (!taskFragment.sleepIfPossible(shuttingDown)) {
4840                 sleepInProgress[0]++;
4841             }
4842         }, true /* traverseTopToBottom */);
4843         return sleepInProgress[0] == 0;
4844     }
4845 
4846     boolean isTopRootTaskInDisplayArea() {
4847         final TaskDisplayArea taskDisplayArea = getDisplayArea();
4848         return taskDisplayArea != null && taskDisplayArea.isTopRootTask(this);
4849     }
4850 
4851     /**
4852      * @return {@code true} if this is the focused root task on its current display, {@code false}
4853      * otherwise.
4854      */
4855     boolean isFocusedRootTaskOnDisplay() {
4856         return mDisplayContent != null && this == mDisplayContent.getFocusedRootTask();
4857     }
4858 
4859     /**
4860      * Make sure that all activities that need to be visible in the root task (that is, they
4861      * currently can be seen by the user) actually are and update their configuration.
4862      * @param starting The top most activity in the task.
4863      *                 The activity is either starting or resuming.
4864      *                 Caller should ensure starting activity is visible.
4865      * @param preserveWindows Flag indicating whether windows should be preserved when updating
4866      *                        configuration in {@link EnsureActivitiesVisibleHelper}.
4867      * @param configChanges Parts of the configuration that changed for this activity for evaluating
4868      *                      if the screen should be frozen as part of
4869      *                      {@link EnsureActivitiesVisibleHelper}.
4870      *
4871      */
4872     void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges,
4873             boolean preserveWindows) {
4874         ensureActivitiesVisible(starting, configChanges, preserveWindows, true /* notifyClients */);
4875     }
4876 
4877     /**
4878      * Ensure visibility with an option to also update the configuration of visible activities.
4879      * @see #ensureActivitiesVisible(ActivityRecord, int, boolean)
4880      * @see RootWindowContainer#ensureActivitiesVisible(ActivityRecord, int, boolean)
4881      * @param starting The top most activity in the task.
4882      *                 The activity is either starting or resuming.
4883      *                 Caller should ensure starting activity is visible.
4884      * @param notifyClients Flag indicating whether the visibility updates should be sent to the
4885      *                      clients in {@link EnsureActivitiesVisibleHelper}.
4886      * @param preserveWindows Flag indicating whether windows should be preserved when updating
4887      *                        configuration in {@link EnsureActivitiesVisibleHelper}.
4888      * @param configChanges Parts of the configuration that changed for this activity for evaluating
4889      *                      if the screen should be frozen as part of
4890      *                      {@link EnsureActivitiesVisibleHelper}.
4891      */
4892     // TODO: Should be re-worked based on the fact that each task as a root task in most cases.
4893     void ensureActivitiesVisible(@Nullable ActivityRecord starting, int configChanges,
4894             boolean preserveWindows, boolean notifyClients) {
4895         mTaskSupervisor.beginActivityVisibilityUpdate();
4896         try {
4897             forAllLeafTasks(task -> {
4898                 task.updateActivityVisibilities(starting, configChanges, preserveWindows,
4899                         notifyClients);
4900             }, true /* traverseTopToBottom */);
4901 
4902             if (mTranslucentActivityWaiting != null &&
4903                     mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
4904                 // Nothing is getting drawn or everything was already visible, don't wait for
4905                 // timeout.
4906                 notifyActivityDrawnLocked(null);
4907             }
4908         } finally {
4909             mTaskSupervisor.endActivityVisibilityUpdate();
4910         }
4911     }
4912 
4913     void checkTranslucentActivityWaiting(ActivityRecord top) {
4914         if (mTranslucentActivityWaiting != top) {
4915             mUndrawnActivitiesBelowTopTranslucent.clear();
4916             if (mTranslucentActivityWaiting != null) {
4917                 // Call the callback with a timeout indication.
4918                 notifyActivityDrawnLocked(null);
4919                 mTranslucentActivityWaiting = null;
4920             }
4921             mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
4922         }
4923     }
4924 
4925     void convertActivityToTranslucent(ActivityRecord r) {
4926         mTranslucentActivityWaiting = r;
4927         mUndrawnActivitiesBelowTopTranslucent.clear();
4928         mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
4929     }
4930 
4931     /**
4932      * Called as activities below the top translucent activity are redrawn. When the last one is
4933      * redrawn notify the top activity by calling
4934      * {@link Activity#onTranslucentConversionComplete}.
4935      *
4936      * @param r The most recent background activity to be drawn. Or, if r is null then a timeout
4937      * occurred and the activity will be notified immediately.
4938      */
4939     void notifyActivityDrawnLocked(ActivityRecord r) {
4940         if ((r == null)
4941                 || (mUndrawnActivitiesBelowTopTranslucent.remove(r) &&
4942                 mUndrawnActivitiesBelowTopTranslucent.isEmpty())) {
4943             // The last undrawn activity below the top has just been drawn. If there is an
4944             // opaque activity at the top, notify it that it can become translucent safely now.
4945             final ActivityRecord waitingActivity = mTranslucentActivityWaiting;
4946             mTranslucentActivityWaiting = null;
4947             mUndrawnActivitiesBelowTopTranslucent.clear();
4948             mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
4949 
4950             if (waitingActivity != null) {
4951                 mWmService.setWindowOpaqueLocked(waitingActivity.token, false);
4952                 if (waitingActivity.attachedToProcess()) {
4953                     try {
4954                         waitingActivity.app.getThread().scheduleTranslucentConversionComplete(
4955                                 waitingActivity.token, r != null);
4956                     } catch (RemoteException e) {
4957                     }
4958                 }
4959             }
4960         }
4961     }
4962 
4963     /**
4964      * Ensure that the top activity in the root task is resumed.
4965      *
4966      * @param prev The previously resumed activity, for when in the process
4967      * of pausing; can be null to call from elsewhere.
4968      * @param options Activity options.
4969      * @param deferPause When {@code true}, this will not pause back tasks.
4970      *
4971      * @return Returns true if something is being resumed, or false if
4972      * nothing happened.
4973      *
4974      * NOTE: It is not safe to call this method directly as it can cause an activity in a
4975      *       non-focused root task to be resumed.
4976      *       Use {@link RootWindowContainer#resumeFocusedTasksTopActivities} to resume the
4977      *       right activity for the current system state.
4978      */
4979     @GuardedBy("mService")
4980     boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,
4981             boolean deferPause) {
4982         if (mInResumeTopActivity) {
4983             // Don't even start recursing.
4984             return false;
4985         }
4986 
4987         boolean someActivityResumed = false;
4988         try {
4989             // Protect against recursion.
4990             mInResumeTopActivity = true;
4991 
4992             if (isLeafTask()) {
4993                 if (isFocusableAndVisible()) {
4994                     someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);
4995                 }
4996             } else {
4997                 int idx = mChildren.size() - 1;
4998                 while (idx >= 0) {
4999                     final Task child = (Task) getChildAt(idx--);
5000                     if (!child.isTopActivityFocusable()) {
5001                         continue;
5002                     }
5003                     if (child.getVisibility(null /* starting */)
5004                             != TASK_FRAGMENT_VISIBILITY_VISIBLE) {
5005                         if (child.topRunningActivity() == null) {
5006                             // Skip the task if no running activity and continue resuming next task.
5007                             continue;
5008                         }
5009                         // Otherwise, assuming everything behind this task should also be invisible.
5010                         break;
5011                     }
5012 
5013                     someActivityResumed |= child.resumeTopActivityUncheckedLocked(prev, options,
5014                             deferPause);
5015                     // Doing so in order to prevent IndexOOB since hierarchy might changes while
5016                     // resuming activities, for example dismissing split-screen while starting
5017                     // non-resizeable activity.
5018                     if (idx >= mChildren.size()) {
5019                         idx = mChildren.size() - 1;
5020                     }
5021                 }
5022             }
5023 
5024             // When resuming the top activity, it may be necessary to pause the top activity (for
5025             // example, returning to the lock screen. We suppress the normal pause logic in
5026             // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the
5027             // end. We call the {@link ActivityTaskSupervisor#checkReadyForSleepLocked} again here
5028             // to ensure any necessary pause logic occurs. In the case where the Activity will be
5029             // shown regardless of the lock screen, the call to
5030             // {@link ActivityTaskSupervisor#checkReadyForSleepLocked} is skipped.
5031             final ActivityRecord next = topRunningActivity(true /* focusableOnly */);
5032             if (next == null || !next.canTurnScreenOn()) {
5033                 checkReadyForSleep();
5034             }
5035         } finally {
5036             mInResumeTopActivity = false;
5037         }
5038 
5039         return someActivityResumed;
5040     }
5041 
5042     /** @see #resumeTopActivityUncheckedLocked(ActivityRecord, ActivityOptions, boolean) */
5043     @GuardedBy("mService")
5044     boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
5045         return resumeTopActivityUncheckedLocked(prev, options, false /* skipPause */);
5046     }
5047 
5048     @GuardedBy("mService")
5049     private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,
5050             boolean deferPause) {
5051         if (!mAtmService.isBooting() && !mAtmService.isBooted()) {
5052             // Not ready yet!
5053             return false;
5054         }
5055 
5056         final ActivityRecord topActivity = topRunningActivity(true /* focusableOnly */);
5057         if (topActivity == null) {
5058             // There are no activities left in this task, let's look somewhere else.
5059             return resumeNextFocusableActivityWhenRootTaskIsEmpty(prev, options);
5060         }
5061 
5062         final boolean[] resumed = new boolean[1];
5063         final TaskFragment topFragment = topActivity.getTaskFragment();
5064         resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
5065         forAllLeafTaskFragments(f -> {
5066             if (topFragment == f) {
5067                 return;
5068             }
5069             if (!f.canBeResumed(null /* starting */)) {
5070                 return;
5071             }
5072             resumed[0] |= f.resumeTopActivity(prev, options, deferPause);
5073         }, true);
5074         return resumed[0];
5075     }
5076 
5077     /**
5078      * Resume the next eligible activity in a focusable root task when this one does not have any
5079      * running activities left. The focus will be adjusted to the next focusable root task and
5080      * top running activities will be resumed in all focusable root tasks. However, if the
5081      * current root task is a root home task - we have to keep it focused, start and resume a
5082      * home activity on the current display instead to make sure that the display is not empty.
5083      */
5084     private boolean resumeNextFocusableActivityWhenRootTaskIsEmpty(ActivityRecord prev,
5085             ActivityOptions options) {
5086         final String reason = "noMoreActivities";
5087 
5088         if (!isActivityTypeHome()) {
5089             final Task nextFocusedTask = adjustFocusToNextFocusableTask(reason);
5090             if (nextFocusedTask != null) {
5091                 // Try to move focus to the next visible root task with a running activity if this
5092                 // root task is not covering the entire screen or is on a secondary display with
5093                 // no home root task.
5094                 return mRootWindowContainer.resumeFocusedTasksTopActivities(nextFocusedTask,
5095                         prev, null /* targetOptions */);
5096             }
5097         }
5098 
5099         // If the current root task is a root home task, or if focus didn't switch to a different
5100         // root task - just start up the Launcher...
5101         ActivityOptions.abort(options);
5102         ProtoLog.d(WM_DEBUG_STATES, "resumeNextFocusableActivityWhenRootTaskIsEmpty: %s, "
5103                 + "go home", reason);
5104         return mRootWindowContainer.resumeHomeActivity(prev, reason, getDisplayArea());
5105     }
5106 
5107     void startActivityLocked(ActivityRecord r, @Nullable Task topTask, boolean newTask,
5108             boolean isTaskSwitch, ActivityOptions options, @Nullable ActivityRecord sourceRecord) {
5109         final ActivityRecord pipCandidate = findEnterPipOnTaskSwitchCandidate(topTask);
5110         Task rTask = r.getTask();
5111         final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
5112         final boolean isOrhasTask = rTask == this || hasChild(rTask);
5113         // mLaunchTaskBehind tasks get placed at the back of the task stack.
5114         if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) {
5115             // Last activity in task had been removed or ActivityManagerService is reusing task.
5116             // Insert or replace.
5117             // Might not even be in.
5118             positionChildAtTop(rTask);
5119         }
5120         Task task = null;
5121         if (!newTask && isOrhasTask && !r.shouldBeVisible()) {
5122             ActivityOptions.abort(options);
5123             return;
5124         }
5125 
5126         // Place a new activity at top of root task, so it is next to interact with the user.
5127 
5128         // If we are not placing the new activity frontmost, we do not want to deliver the
5129         // onUserLeaving callback to the actual frontmost activity
5130         final Task activityTask = r.getTask();
5131         if (task == activityTask && mChildren.indexOf(task) != (getChildCount() - 1)) {
5132             mTaskSupervisor.mUserLeaving = false;
5133             if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
5134                     "startActivity() behind front, mUserLeaving=false");
5135         }
5136 
5137         task = activityTask;
5138 
5139         // Slot the activity into the history root task and proceed
5140         ProtoLog.i(WM_DEBUG_ADD_REMOVE, "Adding activity %s to task %s "
5141                         + "callers: %s", r, task, new RuntimeException("here").fillInStackTrace());
5142 
5143         if (isActivityTypeHomeOrRecents() && getActivityBelow(r) == null) {
5144             // If this is the first activity, don't do any fancy animations,
5145             // because there is nothing for it to animate on top of.
5146             ActivityOptions.abort(options);
5147             return;
5148         }
5149 
5150         if (!allowMoveToFront) {
5151             // The transition animation and starting window are not needed if
5152             // {@code allowMoveToFront} is false, because the activity won't be visible.
5153             ActivityOptions.abort(options);
5154             return;
5155         }
5156 
5157         final DisplayContent dc = mDisplayContent;
5158         if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
5159                 "Prepare open transition: starting " + r);
5160         if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
5161             dc.prepareAppTransition(TRANSIT_NONE);
5162             mTaskSupervisor.mNoAnimActivities.add(r);
5163             mTransitionController.setNoAnimation(r);
5164         } else {
5165             dc.prepareAppTransition(TRANSIT_OPEN);
5166             mTaskSupervisor.mNoAnimActivities.remove(r);
5167         }
5168         if (newTask && !r.mLaunchTaskBehind) {
5169             // If a new task is being launched, then mark the existing top activity as
5170             // supporting picture-in-picture while pausing only if the starting activity
5171             // would not be considered an overlay on top of the current activity
5172             // (eg. not fullscreen, or the assistant)
5173             enableEnterPipOnTaskSwitch(pipCandidate,
5174                     null /* toFrontTask */, r, options);
5175         }
5176         boolean doShow = true;
5177         if (newTask) {
5178             // Even though this activity is starting fresh, we still need
5179             // to reset it to make sure we apply affinities to move any
5180             // existing activities from other tasks in to it.
5181             // If the caller has requested that the target task be
5182             // reset, then do so.
5183             if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
5184                 resetTaskIfNeeded(r, r);
5185                 doShow = topRunningNonDelayedActivityLocked(null) == r;
5186             }
5187         } else if (options != null && options.getAnimationType()
5188                 == ActivityOptions.ANIM_SCENE_TRANSITION) {
5189             doShow = false;
5190         }
5191         if (options != null && options.getDisableStartingWindow()) {
5192             doShow = false;
5193         }
5194         if (r.mLaunchTaskBehind) {
5195             // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
5196             // tell WindowManager that r is visible even though it is at the back of the root
5197             // task.
5198             r.setVisibility(true);
5199             ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
5200             // If launching behind, the app will start regardless of what's above it, so mark it
5201             // as unknown even before prior `pause`. This also prevents a race between set-ready
5202             // and activityPause. Launch-behind is basically only used for dream now.
5203             if (!r.isVisibleRequested()) {
5204                 r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
5205             }
5206             // Go ahead to execute app transition for this activity since the app transition
5207             // will not be triggered through the resume channel.
5208             mDisplayContent.executeAppTransition();
5209         } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
5210             // Figure out if we are transitioning from another activity that is
5211             // "has the same starting icon" as the next one.  This allows the
5212             // window manager to keep the previous window it had previously
5213             // created, if it still had one.
5214             Task baseTask = r.getTask();
5215             final ActivityRecord prev = baseTask.getActivity(
5216                     a -> a.mStartingData != null && a.showToCurrentUser());
5217             mWmService.mStartingSurfaceController.showStartingWindow(r, prev, newTask,
5218                     isTaskSwitch, sourceRecord);
5219         }
5220     }
5221 
5222     /** On Task switch, finds the top activity that supports PiP. */
5223     @Nullable
5224     static ActivityRecord findEnterPipOnTaskSwitchCandidate(@Nullable Task topTask) {
5225         if (topTask == null) {
5226             return null;
5227         }
5228         final ActivityRecord[] candidate = new ActivityRecord[1];
5229         topTask.forAllLeafTaskFragments(tf -> {
5230             // Find the top activity that may enter Pip while pausing.
5231             final ActivityRecord topActivity = tf.getTopNonFinishingActivity();
5232             if (topActivity != null && topActivity.isState(RESUMED, PAUSING)
5233                     && topActivity.supportsPictureInPicture()) {
5234                 candidate[0] = topActivity;
5235                 return true;
5236             }
5237             return false;
5238         });
5239         return candidate[0];
5240     }
5241 
5242     /**
5243      * When switching to another Task, marks the currently PiP candidate activity as supporting to
5244      * enter PiP while it is pausing (if supported). Only one of {@param toFrontTask} or
5245      * {@param toFrontActivity} should be set.
5246      */
5247     private static void enableEnterPipOnTaskSwitch(@Nullable ActivityRecord pipCandidate,
5248             @Nullable Task toFrontTask, @Nullable ActivityRecord toFrontActivity,
5249             @Nullable ActivityOptions opts) {
5250         if (pipCandidate == null) {
5251             return;
5252         }
5253         if (opts != null && opts.disallowEnterPictureInPictureWhileLaunching()) {
5254             // Ensure the caller has requested not to trigger auto-enter PiP
5255             return;
5256         }
5257         if (pipCandidate.inPinnedWindowingMode()) {
5258             // Ensure that we do not trigger entering PiP an activity on the root pinned task.
5259             return;
5260         }
5261         final Task targetRootTask = toFrontTask != null ? toFrontTask.getRootTask()
5262                 : toFrontActivity != null ? toFrontActivity.getRootTask() : null;
5263         if (targetRootTask == null) {
5264             Slog.e(TAG, "No root task for enter pip, both to front task and activity are null?");
5265             return;
5266         }
5267         final boolean isTransient = opts != null && opts.getTransientLaunch()
5268                 || (targetRootTask.mTransitionController.isTransientHide(targetRootTask));
5269 
5270         // Ensure the task/activity being brought forward is not the assistant and is not transient
5271         // nor transient hide target. In the case of transient-launch, we want to wait until the end
5272         // of the transition and only allow to enter pip on task switch after the transient launch
5273         // was committed.
5274         pipCandidate.supportsEnterPipOnTaskSwitch = !targetRootTask.isActivityTypeAssistant()
5275                 && !isTransient;
5276     }
5277 
5278     /**
5279      * Reset the task by reparenting the activities that have same affinity to the task or
5280      * reparenting the activities that have different affinityies out of the task, while these
5281      * activities allow task reparenting.
5282      *
5283      * @param taskTop     Top activity of the task might be reset.
5284      * @param newActivity The activity that going to be started.
5285      * @return The non-finishing top activity of the task after reset or the original task top
5286      *         activity if all activities within the task are finishing.
5287      */
5288     ActivityRecord resetTaskIfNeeded(ActivityRecord taskTop, ActivityRecord newActivity) {
5289         final boolean forceReset =
5290                 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
5291         final Task task = taskTop.getTask();
5292 
5293         // If ActivityOptions are moved out and need to be aborted or moved to taskTop.
5294         final ActivityOptions topOptions;
5295 
5296         // Set the task to be reused, so the TaskFragment#mClearedTaskForReuse can be set if the
5297         // embedded activities are finished while reset task.
5298         mReuseTask = true;
5299         try {
5300             topOptions = sResetTargetTaskHelper.process(task, forceReset);
5301         } finally {
5302             mReuseTask = false;
5303         }
5304 
5305         if (mChildren.contains(task)) {
5306             final ActivityRecord newTop = task.getTopNonFinishingActivity();
5307             if (newTop != null) {
5308                 taskTop = newTop;
5309             }
5310         }
5311 
5312         if (topOptions != null) {
5313             // If we got some ActivityOptions from an activity on top that
5314             // was removed from the task, propagate them to the new real top.
5315             taskTop.updateOptionsLocked(topOptions);
5316         }
5317 
5318         return taskTop;
5319     }
5320 
5321     /**
5322      * Finish the topmost activity that belongs to the crashed app. We may also finish the activity
5323      * that requested launch of the crashed one to prevent launch-crash loop.
5324      * @param app The app that crashed.
5325      * @param reason Reason to perform this action.
5326      * @return The task that was finished in this root task, {@code null} if top running activity
5327      *         does not belong to the crashed app.
5328      */
5329     final Task finishTopCrashedActivityLocked(WindowProcessController app, String reason) {
5330         final ActivityRecord r = topRunningActivity();
5331         if (r == null || r.app != app) {
5332             return null;
5333         }
5334         if (r.isActivityTypeHome() && mAtmService.mHomeProcess == app) {
5335             // Home activities should not be force-finished as we have nothing else to go
5336             // back to. AppErrors will get to it after two crashes in MIN_CRASH_INTERVAL.
5337             Slog.w(TAG, "  Not force finishing home activity "
5338                     + r.intent.getComponent().flattenToShortString());
5339             return null;
5340         }
5341         Slog.w(TAG, "  Force finishing activity "
5342                 + r.intent.getComponent().flattenToShortString());
5343         Task finishedTask = r.getTask();
5344         mDisplayContent.requestTransitionAndLegacyPrepare(TRANSIT_CLOSE, TRANSIT_FLAG_APP_CRASHED);
5345         r.finishIfPossible(reason, false /* oomAdj */);
5346 
5347         // Also terminate any activities below it that aren't yet stopped, to avoid a situation
5348         // where one will get re-start our crashing activity once it gets resumed again.
5349         final ActivityRecord activityBelow = getActivityBelow(r);
5350         if (activityBelow != null) {
5351             if (activityBelow.isState(STARTED, RESUMED, PAUSING, PAUSED)) {
5352                 if (!activityBelow.isActivityTypeHome()
5353                         || mAtmService.mHomeProcess != activityBelow.app) {
5354                     Slog.w(TAG, "  Force finishing activity "
5355                             + activityBelow.intent.getComponent().flattenToShortString());
5356                     activityBelow.finishIfPossible(reason, false /* oomAdj */);
5357                 }
5358             }
5359         }
5360 
5361         return finishedTask;
5362     }
5363 
5364     void finishIfVoiceTask(IBinder binder) {
5365         if (voiceSession != null && voiceSession.asBinder() == binder) {
5366             forAllActivities((r) -> {
5367                 if (r.finishing) return;
5368                 r.finishIfPossible("finish-voice", false /* oomAdj */);
5369                 mAtmService.updateOomAdj();
5370             });
5371         } else {
5372             // Check if any of the activities are using voice
5373             final PooledPredicate f = PooledLambda.obtainPredicate(
5374                     Task::finishIfVoiceActivity, PooledLambda.__(ActivityRecord.class),
5375                     binder);
5376             forAllActivities(f);
5377             f.recycle();
5378         }
5379     }
5380 
5381     private static boolean finishIfVoiceActivity(ActivityRecord r, IBinder binder) {
5382         if (r.voiceSession == null || r.voiceSession.asBinder() != binder) return false;
5383         // Inform of cancellation
5384         r.clearVoiceSessionLocked();
5385         try {
5386             r.app.getThread().scheduleLocalVoiceInteractionStarted(r.token, null);
5387         } catch (RemoteException re) {
5388             // Ok Boomer...
5389         }
5390         r.mAtmService.finishRunningVoiceLocked();
5391         return true;
5392     }
5393 
5394     /** @return true if the root task behind this one is a standard activity type. */
5395     private boolean inFrontOfStandardRootTask() {
5396         final TaskDisplayArea taskDisplayArea = getDisplayArea();
5397         if (taskDisplayArea == null) {
5398             return false;
5399         }
5400         final boolean[] hasFound = new boolean[1];
5401         final Task rootTaskBehind = taskDisplayArea.getRootTask(
5402                 // From top to bottom, find the one behind this Task.
5403                 task -> {
5404                     if (hasFound[0]) {
5405                         return true;
5406                     }
5407                     if (task == this) {
5408                         // The next one is our target.
5409                         hasFound[0] = true;
5410                     }
5411                     return false;
5412                 });
5413         return rootTaskBehind != null && rootTaskBehind.isActivityTypeStandard();
5414     }
5415 
5416     boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
5417         // Basic case: for simple app-centric recents, we need to recreate
5418         // the task if the affinity has changed.
5419 
5420         final String affinity = ActivityRecord.computeTaskAffinity(destAffinity, srec.getUid());
5421         if (srec == null || srec.getTask().affinity == null
5422                 || !srec.getTask().affinity.equals(affinity)) {
5423             return true;
5424         }
5425         // Document-centric case: an app may be split in to multiple documents;
5426         // they need to re-create their task if this current activity is the root
5427         // of a document, unless simply finishing it will return them to the
5428         // correct app behind.
5429         final Task task = srec.getTask();
5430         if (srec.isRootOfTask() && task.getBaseIntent() != null
5431                 && task.getBaseIntent().isDocument()) {
5432             // Okay, this activity is at the root of its task.  What to do, what to do...
5433             if (!inFrontOfStandardRootTask()) {
5434                 // Finishing won't return to an application, so we need to recreate.
5435                 return true;
5436             }
5437             // We now need to get the task below it to determine what to do.
5438             final Task prevTask = getTaskBelow(task);
5439             if (prevTask == null) {
5440                 Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec);
5441                 return false;
5442             }
5443             if (!task.affinity.equals(prevTask.affinity)) {
5444                 // These are different apps, so need to recreate.
5445                 return true;
5446             }
5447         }
5448         return false;
5449     }
5450 
5451     boolean navigateUpTo(ActivityRecord srec, Intent destIntent, String resolvedType,
5452             NeededUriGrants destGrants, int resultCode, Intent resultData,
5453             NeededUriGrants resultGrants) {
5454         if (!srec.attachedToProcess()) {
5455             // Nothing to do if the caller is not attached, because this method should be called
5456             // from an alive activity.
5457             return false;
5458         }
5459         final Task task = srec.getTask();
5460         if (!srec.isDescendantOf(this)) {
5461             return false;
5462         }
5463 
5464         ActivityRecord parent = task.getActivityBelow(srec);
5465         boolean foundParentInTask = false;
5466         final ComponentName dest = destIntent.getComponent();
5467         if (task.getBottomMostActivity() != srec && dest != null) {
5468             final ActivityRecord candidate = task.getActivity(
5469                     (ar) -> ar.info.packageName.equals(dest.getPackageName())
5470                             && ar.info.name.equals(dest.getClassName()), srec,
5471                     false /*includeBoundary*/, true /*traverseTopToBottom*/);
5472             if (candidate != null) {
5473                 parent = candidate;
5474                 foundParentInTask = true;
5475             }
5476         }
5477 
5478         // TODO: There is a dup. of this block of code in ActivityTaskManagerService.finishActivity
5479         // We should consolidate.
5480         IActivityController controller = mAtmService.mController;
5481         if (controller != null) {
5482             ActivityRecord next = topRunningActivity(srec.token, INVALID_TASK_ID);
5483             if (next != null) {
5484                 // ask watcher if this is allowed
5485                 boolean resumeOK = true;
5486                 try {
5487                     resumeOK = controller.activityResuming(next.packageName);
5488                 } catch (RemoteException e) {
5489                     mAtmService.mController = null;
5490                     Watchdog.getInstance().setActivityController(null);
5491                 }
5492 
5493                 if (!resumeOK) {
5494                     return false;
5495                 }
5496             }
5497         }
5498         final long origId = Binder.clearCallingIdentity();
5499 
5500         final int[] resultCodeHolder = new int[1];
5501         resultCodeHolder[0] = resultCode;
5502         final Intent[] resultDataHolder = new Intent[1];
5503         resultDataHolder[0] = resultData;
5504         final NeededUriGrants[] resultGrantsHolder = new NeededUriGrants[1];
5505         resultGrantsHolder[0] = resultGrants;
5506         final ActivityRecord finalParent = parent;
5507         task.forAllActivities((ar) -> {
5508             if (ar == finalParent) return true;
5509 
5510             ar.finishIfPossible(resultCodeHolder[0], resultDataHolder[0], resultGrantsHolder[0],
5511                     "navigate-up", true /* oomAdj */);
5512             // Only return the supplied result for the first activity finished
5513             resultCodeHolder[0] = Activity.RESULT_CANCELED;
5514             resultDataHolder[0] = null;
5515             return false;
5516         }, srec, true, true);
5517         resultCode = resultCodeHolder[0];
5518         resultData = resultDataHolder[0];
5519 
5520         if (parent != null && foundParentInTask) {
5521             final int callingUid = srec.info.applicationInfo.uid;
5522             // TODO(b/64750076): Check if calling pid should really be -1.
5523             final int res = mAtmService.getActivityStartController()
5524                     .obtainStarter(destIntent, "navigateUpTo")
5525                     .setResolvedType(resolvedType)
5526                     .setUserId(srec.mUserId)
5527                     .setCaller(srec.app.getThread())
5528                     .setResultTo(parent.token)
5529                     .setIntentGrants(destGrants)
5530                     .setCallingPid(-1)
5531                     .setCallingUid(callingUid)
5532                     .setCallingPackage(srec.packageName)
5533                     .setCallingFeatureId(parent.launchedFromFeatureId)
5534                     .setRealCallingPid(-1)
5535                     .setRealCallingUid(callingUid)
5536                     .setComponentSpecified(true)
5537                     .execute();
5538             foundParentInTask = isStartResultSuccessful(res);
5539             if (res == ActivityManager.START_SUCCESS) {
5540                 parent.finishIfPossible(resultCode, resultData, resultGrants,
5541                         "navigate-top", true /* oomAdj */);
5542             }
5543         }
5544         Binder.restoreCallingIdentity(origId);
5545         return foundParentInTask;
5546     }
5547 
5548     void removeLaunchTickMessages() {
5549         forAllActivities(ActivityRecord::removeLaunchTickRunnable);
5550     }
5551 
5552     private void updateTransitLocked(@WindowManager.TransitionType int transit,
5553             ActivityOptions options) {
5554         if (options != null) {
5555             ActivityRecord r = topRunningActivity();
5556             if (r != null && !r.isState(RESUMED)) {
5557                 r.updateOptionsLocked(options);
5558             } else {
5559                 ActivityOptions.abort(options);
5560             }
5561         }
5562         mDisplayContent.prepareAppTransition(transit);
5563     }
5564 
5565     final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options,
5566             AppTimeTracker timeTracker, String reason) {
5567         moveTaskToFront(tr, noAnimation, options, timeTracker, !DEFER_RESUME, reason);
5568     }
5569 
5570     final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options,
5571             AppTimeTracker timeTracker, boolean deferResume, String reason) {
5572         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
5573 
5574         final ActivityRecord pipCandidate = findEnterPipOnTaskSwitchCandidate(
5575                 getDisplayArea().getTopRootTask());
5576 
5577         if (tr != this && !tr.isDescendantOf(this)) {
5578             // nothing to do!
5579             if (noAnimation) {
5580                 ActivityOptions.abort(options);
5581             } else {
5582                 updateTransitLocked(TRANSIT_TO_FRONT, options);
5583             }
5584             return;
5585         }
5586 
5587         if (timeTracker != null) {
5588             // The caller wants a time tracker associated with this task.
5589             tr.forAllActivities(a -> { a.appTimeTracker = timeTracker; });
5590         }
5591 
5592         try {
5593             // Defer updating the IME target since the new IME target will try to get computed
5594             // before updating all closing and opening apps, which can cause the ime target to
5595             // get calculated incorrectly.
5596             mDisplayContent.deferUpdateImeTarget();
5597 
5598             // Don't refocus if invisible to current user
5599             final ActivityRecord top = tr.getTopNonFinishingActivity();
5600             if (top == null || !top.showToCurrentUser()) {
5601                 positionChildAtTop(tr);
5602                 if (top != null) {
5603                     mTaskSupervisor.mRecentTasks.add(top.getTask());
5604                 }
5605                 ActivityOptions.abort(options);
5606                 return;
5607             }
5608 
5609             // Set focus to the top running activity of this task and move all its parents to top.
5610             top.moveFocusableActivityToTop(reason);
5611 
5612             if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr);
5613             if (noAnimation) {
5614                 mDisplayContent.prepareAppTransition(TRANSIT_NONE);
5615                 mTaskSupervisor.mNoAnimActivities.add(top);
5616                 ActivityOptions.abort(options);
5617             } else {
5618                 updateTransitLocked(TRANSIT_TO_FRONT, options);
5619             }
5620 
5621             // If a new task is moved to the front, then mark the existing top activity as
5622             // supporting
5623 
5624             // picture-in-picture while paused only if the task would not be considered an oerlay
5625             // on top
5626             // of the current activity (eg. not fullscreen, or the assistant)
5627             enableEnterPipOnTaskSwitch(pipCandidate, tr, null /* toFrontActivity */, options);
5628 
5629             if (!deferResume) {
5630                 mRootWindowContainer.resumeFocusedTasksTopActivities();
5631             }
5632         } finally {
5633             mDisplayContent.continueUpdateImeTarget();
5634         }
5635     }
5636 
5637     private boolean canMoveTaskToBack(Task task) {
5638         // In LockTask mode, moving a locked task to the back of the root task may expose unlocked
5639         // ones. Therefore we need to check if this operation is allowed.
5640         if (!mAtmService.getLockTaskController().canMoveTaskToBack(task)) {
5641             return false;
5642         }
5643 
5644         // If we have a watcher, preflight the move before committing to it.  First check
5645         // for *other* available tasks, but if none are available, then try again allowing the
5646         // current task to be selected.
5647         if (isTopRootTaskInDisplayArea() && mAtmService.mController != null) {
5648             ActivityRecord next = topRunningActivity(null, task.mTaskId);
5649             if (next == null) {
5650                 next = topRunningActivity(null, INVALID_TASK_ID);
5651             }
5652             if (next != null) {
5653                 // ask watcher if this is allowed
5654                 boolean moveOK = true;
5655                 try {
5656                     moveOK = mAtmService.mController.activityResuming(next.packageName);
5657                 } catch (RemoteException e) {
5658                     mAtmService.mController = null;
5659                     Watchdog.getInstance().setActivityController(null);
5660                 }
5661                 if (!moveOK) {
5662                     return false;
5663                 }
5664             }
5665         }
5666         return true;
5667     }
5668 
5669     /**
5670      * Worker method for rearranging history task. Implements the function of moving all
5671      * activities for a specific task (gathering them if disjoint) into a single group at the
5672      * bottom of the root task.
5673      *
5674      * If a watcher is installed, the action is preflighted and the watcher has an opportunity
5675      * to premeptively cancel the move.
5676      *
5677      * If this is a pinned task, it will be removed instead of rearranged.
5678      *
5679      * @param tr The task to collect and move to the bottom.
5680      * @return Returns true if the move completed, false if not.
5681      */
5682     boolean moveTaskToBack(Task tr) {
5683         Slog.i(TAG, "moveTaskToBack: " + tr);
5684 
5685         if (!canMoveTaskToBack(tr)) return false;
5686 
5687         if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task="
5688                 + tr.mTaskId);
5689 
5690         if (mTransitionController.isShellTransitionsEnabled()) {
5691             final Transition transition = new Transition(TRANSIT_TO_BACK, 0 /* flags */,
5692                     mTransitionController, mWmService.mSyncEngine);
5693             // Guarantee that this gets its own transition by queueing on SyncEngine
5694             mTransitionController.startCollectOrQueue(transition,
5695                     (deferred) -> {
5696                         // Need to check again if deferred since the system might
5697                         // be in a different state.
5698                         if (!isAttached() || (deferred && !canMoveTaskToBack(tr))) {
5699                             Slog.e(TAG, "Failed to move task to back after saying we could: "
5700                                     + tr.mTaskId);
5701                             transition.abort();
5702                             return;
5703                         }
5704                         mTransitionController.requestStartTransition(transition, tr,
5705                                 null /* remoteTransition */, null /* displayChange */);
5706                         mTransitionController.collect(tr);
5707                         moveTaskToBackInner(tr);
5708                     });
5709         } else {
5710             // Skip the transition for pinned task.
5711             if (!inPinnedWindowingMode()) {
5712                 mDisplayContent.prepareAppTransition(TRANSIT_TO_BACK);
5713             }
5714             moveTaskToBackInner(tr);
5715         }
5716         return true;
5717     }
5718 
5719     private boolean moveTaskToBackInner(@NonNull Task task) {
5720         if (mTransitionController.isShellTransitionsEnabled()) {
5721             // Preventing from update surface position for WindowState if configuration changed,
5722             // because the position is depends on WindowFrame, so update the position before
5723             // relayout will only update it to "old" position.
5724             mAtmService.deferWindowLayout();
5725         }
5726         try {
5727             moveToBack("moveTaskToBackInner", task);
5728 
5729             if (inPinnedWindowingMode()) {
5730                 mTaskSupervisor.removeRootTask(this);
5731                 return true;
5732             }
5733 
5734             mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */,
5735                     mDisplayContent.mDisplayId, false /* markFrozenIfConfigChanged */,
5736                     false /* deferResume */);
5737         } finally {
5738             if (mTransitionController.isShellTransitionsEnabled()) {
5739                 mAtmService.continueWindowLayout();
5740             }
5741         }
5742         ActivityRecord topActivity = getDisplayArea().topRunningActivity();
5743         Task topRootTask = topActivity.getRootTask();
5744         if (topRootTask != null && topRootTask != this && topActivity.isState(RESUMED)) {
5745             // Usually resuming a top activity triggers the next app transition, but nothing's got
5746             // resumed in this case, so we need to execute it explicitly.
5747             mDisplayContent.executeAppTransition();
5748             mDisplayContent.setFocusedApp(topActivity);
5749         } else {
5750             mRootWindowContainer.resumeFocusedTasksTopActivities();
5751         }
5752         return true;
5753     }
5754 
5755     boolean willActivityBeVisible(IBinder token) {
5756         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
5757         if (r == null) {
5758             return false;
5759         }
5760 
5761         if (!r.shouldBeVisible()) return false;
5762 
5763         if (r.finishing) Slog.e(TAG, "willActivityBeVisible: Returning false,"
5764                 + " would have returned true for r=" + r);
5765         return !r.finishing;
5766     }
5767 
5768     void unhandledBackLocked() {
5769         final ActivityRecord topActivity = getTopMostActivity();
5770         if (DEBUG_SWITCH) Slog.d(TAG_SWITCH,
5771                 "Performing unhandledBack(): top activity: " + topActivity);
5772         if (topActivity != null) {
5773             topActivity.finishIfPossible("unhandled-back", true /* oomAdj */);
5774         }
5775     }
5776 
5777     boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient,
5778             String dumpPackage, final boolean needSep) {
5779         return dump("  ", fd, pw, dumpAll, dumpClient, dumpPackage, needSep, null /* header */);
5780     }
5781 
5782     @Override
5783     void dumpInner(String prefix, PrintWriter pw, boolean dumpAll, String dumpPackage) {
5784         super.dumpInner(prefix, pw, dumpAll, dumpPackage);
5785         if (mCreatedByOrganizer) {
5786             pw.println(prefix + "  mCreatedByOrganizer=true");
5787         }
5788         if (mLastNonFullscreenBounds != null) {
5789             pw.print(prefix); pw.print("  mLastNonFullscreenBounds=");
5790             pw.println(mLastNonFullscreenBounds);
5791         }
5792         if (isLeafTask()) {
5793             pw.println(prefix + "  isSleeping=" + shouldSleepActivities());
5794             printThisActivity(pw, getTopPausingActivity(), dumpPackage, false,
5795                     prefix + "  topPausingActivity=", null);
5796             printThisActivity(pw, getTopResumedActivity(), dumpPackage, false,
5797                     prefix + "  topResumedActivity=", null);
5798             if (mMinWidth != INVALID_MIN_SIZE || mMinHeight != INVALID_MIN_SIZE) {
5799                 pw.print(prefix); pw.print("  mMinWidth="); pw.print(mMinWidth);
5800                 pw.print(" mMinHeight="); pw.println(mMinHeight);
5801             }
5802         }
5803     }
5804 
5805     ArrayList<ActivityRecord> getDumpActivitiesLocked(String name, @UserIdInt int userId) {
5806         ArrayList<ActivityRecord> activities = new ArrayList<>();
5807 
5808         if ("all".equals(name)) {
5809             forAllActivities((Consumer<ActivityRecord>) activities::add);
5810         } else if ("top".equals(name)) {
5811             final ActivityRecord topActivity = getTopMostActivity();
5812             if (topActivity != null) {
5813                 activities.add(topActivity);
5814             }
5815         } else {
5816             ActivityManagerService.ItemMatcher matcher = new ActivityManagerService.ItemMatcher();
5817             matcher.build(name);
5818 
5819             forAllActivities((r) -> {
5820                 if (matcher.match(r, r.intent.getComponent())) {
5821                     activities.add(r);
5822                 }
5823             });
5824         }
5825         if (userId != UserHandle.USER_ALL) {
5826             for (int i = activities.size() - 1; i >= 0; --i) {
5827                 if (activities.get(i).mUserId != userId) {
5828                     activities.remove(i);
5829                 }
5830             }
5831         }
5832         return activities;
5833     }
5834 
5835     ActivityRecord restartPackage(String packageName) {
5836         ActivityRecord starting = topRunningActivity();
5837 
5838         // All activities that came from the package must be
5839         // restarted as if there was a config change.
5840         forAllActivities(r -> {
5841             if (!r.info.packageName.equals(packageName)) return;
5842             r.forceNewConfig = true;
5843             if (starting != null && r == starting && r.isVisibleRequested()) {
5844                 r.startFreezingScreenLocked(CONFIG_SCREEN_LAYOUT);
5845             }
5846         });
5847 
5848         return starting;
5849     }
5850 
5851     Task reuseOrCreateTask(ActivityInfo info, Intent intent, boolean toTop) {
5852         return reuseOrCreateTask(info, intent, null /*voiceSession*/, null /*voiceInteractor*/,
5853                 toTop, null /*activity*/, null /*source*/, null /*options*/);
5854     }
5855 
5856     // TODO: Can be removed once we change callpoints creating root tasks to be creating tasks.
5857     /** Either returns this current task to be re-used or creates a new child task. */
5858     Task reuseOrCreateTask(ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession,
5859             IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity,
5860             ActivityRecord source, ActivityOptions options) {
5861 
5862         Task task;
5863         if (canReuseAsLeafTask()) {
5864             // This root task will only contain one task, so just return itself since all root
5865             // tasks ara now tasks and all tasks are now root tasks.
5866             task = reuseAsLeafTask(voiceSession, voiceInteractor, intent, info, activity);
5867         } else {
5868             // Create child task since this root task can contain multiple tasks.
5869             final int taskId = activity != null
5870                     ? mTaskSupervisor.getNextTaskIdForUser(activity.mUserId)
5871                     : mTaskSupervisor.getNextTaskIdForUser();
5872             final int activityType = getActivityType();
5873             task = new Task.Builder(mAtmService)
5874                     .setTaskId(taskId)
5875                     .setActivityInfo(info)
5876                     .setActivityOptions(options)
5877                     .setIntent(intent)
5878                     .setVoiceSession(voiceSession)
5879                     .setVoiceInteractor(voiceInteractor)
5880                     .setOnTop(toTop)
5881                     .setParent(this)
5882                     .build();
5883         }
5884 
5885         int displayId = getDisplayId();
5886         if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY;
5887         final boolean isLockscreenShown = mAtmService.mTaskSupervisor.getKeyguardController()
5888                 .isKeyguardOrAodShowing(displayId);
5889         if (!mTaskSupervisor.getLaunchParamsController()
5890                 .layoutTask(task, info.windowLayout, activity, source, options)
5891                 && !getRequestedOverrideBounds().isEmpty()
5892                 && task.isResizeable() && !isLockscreenShown) {
5893             task.setBounds(getRequestedOverrideBounds());
5894         }
5895 
5896         return task;
5897     }
5898 
5899     /** Return {@code true} if this task can be reused as leaf task. */
5900     private boolean canReuseAsLeafTask() {
5901         // Cannot be reused as leaf task if this task is created by organizer or having child tasks.
5902         if (mCreatedByOrganizer || !isLeafTask()) {
5903             return false;
5904         }
5905 
5906         // Existing Tasks can be reused if a new root task will be created anyway.
5907         final int windowingMode = getWindowingMode();
5908         final int activityType = getActivityType();
5909         return DisplayContent.alwaysCreateRootTask(windowingMode, activityType);
5910     }
5911 
5912     void addChild(WindowContainer child, final boolean toTop, boolean showForAllUsers) {
5913         Task task = child.asTask();
5914         try {
5915             if (task != null) {
5916                 task.setForceShowForAllUsers(showForAllUsers);
5917             }
5918             // We only want to move the parents to the parents if we are creating this task at the
5919             // top of its root task.
5920             addChild(child, toTop ? MAX_VALUE : 0, toTop /*moveParents*/);
5921         } finally {
5922             if (task != null) {
5923                 task.setForceShowForAllUsers(false);
5924             }
5925         }
5926     }
5927 
5928     public void setAlwaysOnTop(boolean alwaysOnTop) {
5929         // {@link #isAwaysonTop} overrides the original behavior which also evaluates if this
5930         // task is force hidden, so super.isAlwaysOnTop() is used here to see whether the
5931         // alwaysOnTop attributes should be updated.
5932         if (super.isAlwaysOnTop() == alwaysOnTop) {
5933             return;
5934         }
5935         super.setAlwaysOnTop(alwaysOnTop);
5936         // positionChildAtTop() must be called even when always on top gets turned off because we
5937         // need to make sure that the root task is moved from among always on top windows to
5938         // below other always on top windows. Since the position the root task should be inserted
5939         // into is calculated properly in {@link DisplayContent#getTopInsertPosition()} in both
5940         // cases, we can just request that the root task is put at top here.
5941         // Don't bother moving task to top if this task is force hidden and invisible to user.
5942         if (!isForceHidden()) {
5943             getDisplayArea().positionChildAt(POSITION_TOP, this, false /* includingParents */);
5944         }
5945     }
5946 
5947     void dismissPip() {
5948         if (!isActivityTypeStandardOrUndefined()) {
5949             throw new IllegalArgumentException(
5950                     "You can't move tasks from non-standard root tasks.");
5951         }
5952         if (getWindowingMode() != WINDOWING_MODE_PINNED) {
5953             throw new IllegalArgumentException(
5954                     "Can't exit pinned mode if it's not pinned already.");
5955         }
5956 
5957         mWmService.inSurfaceTransaction(() -> {
5958             final Task task = getBottomMostTask();
5959             setWindowingMode(WINDOWING_MODE_UNDEFINED);
5960 
5961             // Task could have been removed from the hierarchy due to windowing mode change
5962             // where its only child is reparented back to their original parent task.
5963             if (isAttached()) {
5964                 getDisplayArea().positionChildAt(POSITION_TOP, this, false /* includingParents */);
5965             }
5966 
5967             mTaskSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, this);
5968         });
5969     }
5970 
5971     private int setBounds(Rect existing, Rect bounds) {
5972         if (equivalentBounds(existing, bounds)) {
5973             return BOUNDS_CHANGE_NONE;
5974         }
5975 
5976         return setBoundsUnchecked(!inMultiWindowMode() ? null : bounds);
5977     }
5978 
5979     @Override
5980     public void getBounds(Rect bounds) {
5981         bounds.set(getBounds());
5982     }
5983 
5984     /**
5985      * Put a Task in this root task. Used for adding only.
5986      * When task is added to top of the root task, the entire branch of the hierarchy (including
5987      * root task and display) will be brought to top.
5988      * @param child The child to add.
5989      * @param position Target position to add the task to.
5990      */
5991     private void addChild(WindowContainer child, int position, boolean moveParents) {
5992         // Add child task.
5993         addChild(child, null);
5994 
5995         // Move child to a proper position, as some restriction for position might apply.
5996         positionChildAt(position, child, moveParents /* includingParents */);
5997     }
5998 
5999     void positionChildAtTop(Task child) {
6000         if (child == null) {
6001             // TODO: Fix the call-points that cause this to happen.
6002             return;
6003         }
6004 
6005         if (child == this) {
6006             // TODO: Fix call-points
6007             moveToFront("positionChildAtTop");
6008             return;
6009         }
6010 
6011         positionChildAt(POSITION_TOP, child, true /* includingParents */);
6012     }
6013 
6014     void positionChildAtBottom(Task child) {
6015         // If there are other focusable root tasks on the display, the z-order of the display
6016         // should not be changed just because a task was placed at the bottom. E.g. if it is
6017         // moving the topmost task to bottom, the next focusable root task on the same display
6018         // should be focused.
6019         final Task nextFocusableRootTask = getDisplayArea().getNextFocusableRootTask(
6020                 child.getRootTask(), true /* ignoreCurrent */);
6021         positionChildAtBottom(child, nextFocusableRootTask == null /* includingParents */);
6022     }
6023 
6024     @VisibleForTesting
6025     void positionChildAtBottom(Task child, boolean includingParents) {
6026         if (child == null) {
6027             // TODO: Fix the call-points that cause this to happen.
6028             return;
6029         }
6030 
6031         positionChildAt(POSITION_BOTTOM, child, includingParents);
6032     }
6033 
6034     @Override
6035     void onChildPositionChanged(WindowContainer child) {
6036         dispatchTaskInfoChangedIfNeeded(false /* force */);
6037 
6038         if (!mChildren.contains(child)) {
6039             return;
6040         }
6041         if (child.asTask() != null) {
6042             // Non-root task position changed.
6043             mRootWindowContainer.invalidateTaskLayers();
6044         }
6045     }
6046 
6047     void reparent(TaskDisplayArea newParent, boolean onTop) {
6048         if (newParent == null) {
6049             throw new IllegalArgumentException("Task can't reparent to null " + this);
6050         }
6051 
6052         if (getParent() == newParent) {
6053             throw new IllegalArgumentException("Task=" + this + " already child of " + newParent);
6054         }
6055 
6056         if (canBeLaunchedOnDisplay(newParent.getDisplayId())) {
6057             reparent(newParent, onTop ? POSITION_TOP : POSITION_BOTTOM);
6058             if (isLeafTask()) {
6059                 newParent.onLeafTaskMoved(this, onTop, !onTop);
6060             }
6061         } else {
6062             Slog.w(TAG, "Task=" + this + " can't reparent to " + newParent);
6063         }
6064     }
6065 
6066     void setLastRecentsAnimationTransaction(@NonNull PictureInPictureSurfaceTransaction transaction,
6067             @Nullable SurfaceControl overlay) {
6068         mLastRecentsAnimationTransaction = new PictureInPictureSurfaceTransaction(transaction);
6069         mLastRecentsAnimationOverlay = overlay;
6070     }
6071 
6072     void clearLastRecentsAnimationTransaction(boolean forceRemoveOverlay) {
6073         if (forceRemoveOverlay && mLastRecentsAnimationOverlay != null) {
6074             getPendingTransaction().remove(mLastRecentsAnimationOverlay);
6075         }
6076         mLastRecentsAnimationTransaction = null;
6077         mLastRecentsAnimationOverlay = null;
6078         // reset also the crop and transform introduced by mLastRecentsAnimationTransaction
6079         resetSurfaceControlTransforms();
6080     }
6081 
6082     void resetSurfaceControlTransforms() {
6083         getSyncTransaction().setMatrix(mSurfaceControl, Matrix.IDENTITY_MATRIX, new float[9])
6084                 .setWindowCrop(mSurfaceControl, null)
6085                 .setShadowRadius(mSurfaceControl, 0)
6086                 .setCornerRadius(mSurfaceControl, 0);
6087     }
6088 
6089     void maybeApplyLastRecentsAnimationTransaction() {
6090         if (mLastRecentsAnimationTransaction != null) {
6091             final SurfaceControl.Transaction tx = getPendingTransaction();
6092             if (mLastRecentsAnimationOverlay != null) {
6093                 tx.reparent(mLastRecentsAnimationOverlay, mSurfaceControl);
6094             }
6095             PictureInPictureSurfaceTransaction.apply(mLastRecentsAnimationTransaction,
6096                     mSurfaceControl, tx);
6097             // If we are transferring the transform from the root task entering PIP, then also show
6098             // the new task immediately
6099             tx.show(mSurfaceControl);
6100             mLastRecentsAnimationTransaction = null;
6101             mLastRecentsAnimationOverlay = null;
6102         }
6103     }
6104 
6105     private void updateSurfaceBounds() {
6106         updateSurfaceSize(getSyncTransaction());
6107         updateSurfacePositionNonOrganized();
6108         scheduleAnimation();
6109     }
6110 
6111     private Point getRelativePosition() {
6112         Point position = new Point();
6113         getRelativePosition(position);
6114         return position;
6115     }
6116 
6117     boolean shouldIgnoreInput() {
6118         if (mAtmService.mHasLeanbackFeature && inPinnedWindowingMode()
6119                 && !isFocusedRootTaskOnDisplay()) {
6120             // Preventing Picture-in-Picture root task from receiving input on TVs.
6121             return true;
6122         }
6123         return false;
6124     }
6125 
6126     /**
6127      * Simply check and give warning logs if this is not operated on leaf task.
6128      */
6129     private void warnForNonLeafTask(String func) {
6130         if (!isLeafTask()) {
6131             Slog.w(TAG, func + " on non-leaf task " + this);
6132         }
6133     }
6134 
6135     public DisplayInfo getDisplayInfo() {
6136         return mDisplayContent.getDisplayInfo();
6137     }
6138 
6139     AnimatingActivityRegistry getAnimatingActivityRegistry() {
6140         return mAnimatingActivityRegistry;
6141     }
6142 
6143     @Override
6144     void executeAppTransition(ActivityOptions options) {
6145         mDisplayContent.executeAppTransition();
6146         ActivityOptions.abort(options);
6147     }
6148 
6149     boolean shouldSleepActivities() {
6150         final DisplayContent display = mDisplayContent;
6151         final boolean isKeyguardGoingAway = (mDisplayContent != null)
6152                 ? mDisplayContent.isKeyguardGoingAway()
6153                 : mRootWindowContainer.getDefaultDisplay().isKeyguardGoingAway();
6154 
6155         // Do not sleep activities in this root task if we're marked as focused and the keyguard
6156         // is in the process of going away.
6157         if (isKeyguardGoingAway && isFocusedRootTaskOnDisplay()
6158                 // Avoid resuming activities on secondary displays since we don't want bubble
6159                 // activities to be resumed while bubble is still collapsed.
6160                 // TODO(b/113840485): Having keyguard going away state for secondary displays.
6161                 && display.isDefaultDisplay) {
6162             return false;
6163         }
6164 
6165         return display != null ? display.isSleeping() : mAtmService.isSleepingLocked();
6166     }
6167 
6168     private Rect getRawBounds() {
6169         return super.getBounds();
6170     }
6171 
6172     void dispatchTaskInfoChangedIfNeeded(boolean force) {
6173         if (isOrganized()) {
6174             mAtmService.mTaskOrganizerController.onTaskInfoChanged(this, force);
6175         }
6176     }
6177 
6178     void setReparentLeafTaskIfRelaunch(boolean reparentLeafTaskIfRelaunch) {
6179         if (isOrganized()) {
6180             mReparentLeafTaskIfRelaunch = reparentLeafTaskIfRelaunch;
6181         }
6182     }
6183 
6184     /**
6185      * Return true if the activityInfo has the same requiredDisplayCategory as this task.
6186      */
6187     boolean isSameRequiredDisplayCategory(@NonNull ActivityInfo info) {
6188         return mRequiredDisplayCategory != null && mRequiredDisplayCategory.equals(
6189                 info.requiredDisplayCategory)
6190                 || (mRequiredDisplayCategory == null && info.requiredDisplayCategory == null);
6191     }
6192 
6193     @Override
6194     public void dumpDebug(ProtoOutputStream proto, long fieldId,
6195             @WindowTraceLogLevel int logLevel) {
6196         if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
6197             return;
6198         }
6199 
6200         final long token = proto.start(fieldId);
6201 
6202         proto.write(TaskProto.ID, mTaskId);
6203         proto.write(ROOT_TASK_ID, getRootTaskId());
6204 
6205         if (getTopResumedActivity() != null) {
6206             getTopResumedActivity().writeIdentifierToProto(proto, RESUMED_ACTIVITY);
6207         }
6208         if (realActivity != null) {
6209             proto.write(REAL_ACTIVITY, realActivity.flattenToShortString());
6210         }
6211         if (origActivity != null) {
6212             proto.write(ORIG_ACTIVITY, origActivity.flattenToShortString());
6213         }
6214         proto.write(RESIZE_MODE, mResizeMode);
6215         proto.write(FILLS_PARENT, matchParentBounds());
6216         getRawBounds().dumpDebug(proto, BOUNDS);
6217 
6218         if (mLastNonFullscreenBounds != null) {
6219             mLastNonFullscreenBounds.dumpDebug(proto, LAST_NON_FULLSCREEN_BOUNDS);
6220         }
6221 
6222         if (mSurfaceControl != null) {
6223             proto.write(SURFACE_WIDTH, mSurfaceControl.getWidth());
6224             proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
6225         }
6226 
6227         proto.write(CREATED_BY_ORGANIZER, mCreatedByOrganizer);
6228         proto.write(AFFINITY, affinity);
6229         proto.write(HAS_CHILD_PIP_ACTIVITY, mChildPipActivity != null);
6230 
6231         super.dumpDebug(proto, TASK_FRAGMENT, logLevel);
6232 
6233         proto.end(token);
6234     }
6235 
6236     static class Builder {
6237         private final ActivityTaskManagerService mAtmService;
6238         private WindowContainer mParent;
6239         private int mTaskId;
6240         private Intent mIntent;
6241         private Intent mAffinityIntent;
6242         private String mAffinity;
6243         private String mRootAffinity;
6244         private ComponentName mRealActivity;
6245         private ComponentName mOrigActivity;
6246         private boolean mRootWasReset;
6247         private boolean mAutoRemoveRecents;
6248         private boolean mAskedCompatMode;
6249         private int mUserId;
6250         private int mEffectiveUid;
6251         private String mLastDescription;
6252         private long mLastTimeMoved;
6253         private boolean mNeverRelinquishIdentity;
6254         private TaskDescription mLastTaskDescription;
6255         private PersistedTaskSnapshotData mLastSnapshotData;
6256         private int mTaskAffiliation;
6257         private int mPrevAffiliateTaskId = INVALID_TASK_ID;
6258         private int mNextAffiliateTaskId = INVALID_TASK_ID;
6259         private int mCallingUid;
6260         private String mCallingPackage;
6261         private String mCallingFeatureId;
6262         private int mResizeMode;
6263         private boolean mSupportsPictureInPicture;
6264         private boolean mRealActivitySuspended;
6265         private boolean mUserSetupComplete;
6266         private int mMinWidth = INVALID_MIN_SIZE;
6267         private int mMinHeight = INVALID_MIN_SIZE;
6268         private ActivityInfo mActivityInfo;
6269         private ActivityOptions mActivityOptions;
6270         private IVoiceInteractionSession mVoiceSession;
6271         private IVoiceInteractor mVoiceInteractor;
6272         private int mActivityType;
6273         private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
6274         private boolean mCreatedByOrganizer;
6275         private boolean mDeferTaskAppear;
6276         private IBinder mLaunchCookie;
6277         private boolean mOnTop;
6278         private boolean mHasBeenVisible;
6279         private boolean mRemoveWithTaskOrganizer;
6280 
6281         /**
6282          * Records the source task that requesting to build a new task, used to determine which of
6283          * the adjacent roots should be launch root of the new task.
6284          */
6285         private Task mSourceTask;
6286 
6287         /**
6288          * Records launch flags to apply when launching new task.
6289          */
6290         private int mLaunchFlags;
6291 
6292         Builder(ActivityTaskManagerService atm) {
6293             mAtmService = atm;
6294         }
6295 
6296         Builder setParent(WindowContainer parent) {
6297             mParent = parent;
6298             return this;
6299         }
6300 
6301         Builder setSourceTask(Task sourceTask) {
6302             mSourceTask = sourceTask;
6303             return this;
6304         }
6305 
6306         Builder setLaunchFlags(int launchFlags) {
6307             mLaunchFlags = launchFlags;
6308             return this;
6309         }
6310 
6311         Builder setTaskId(int taskId) {
6312             mTaskId = taskId;
6313             return this;
6314         }
6315 
6316         Builder setIntent(Intent intent) {
6317             mIntent = intent;
6318             return this;
6319         }
6320 
6321         Builder setRealActivity(ComponentName realActivity) {
6322             mRealActivity = realActivity;
6323             return this;
6324         }
6325 
6326         Builder setEffectiveUid(int effectiveUid) {
6327             mEffectiveUid = effectiveUid;
6328             return this;
6329         }
6330 
6331         Builder setMinWidth(int minWidth) {
6332             mMinWidth = minWidth;
6333             return this;
6334         }
6335 
6336         Builder setMinHeight(int minHeight) {
6337             mMinHeight = minHeight;
6338             return this;
6339         }
6340 
6341         Builder setActivityInfo(ActivityInfo info) {
6342             mActivityInfo = info;
6343             return this;
6344         }
6345 
6346         Builder setActivityOptions(ActivityOptions opts) {
6347             mActivityOptions = opts;
6348             return this;
6349         }
6350 
6351         Builder setVoiceSession(IVoiceInteractionSession voiceSession) {
6352             mVoiceSession = voiceSession;
6353             return this;
6354         }
6355 
6356         Builder setActivityType(int activityType) {
6357             mActivityType = activityType;
6358             return this;
6359         }
6360 
6361         int getActivityType() {
6362             return mActivityType;
6363         }
6364 
6365         Builder setWindowingMode(int windowingMode) {
6366             mWindowingMode = windowingMode;
6367             return this;
6368         }
6369 
6370         int getWindowingMode() {
6371             return mWindowingMode;
6372         }
6373 
6374         Builder setCreatedByOrganizer(boolean createdByOrganizer) {
6375             mCreatedByOrganizer = createdByOrganizer;
6376             return this;
6377         }
6378 
6379         boolean getCreatedByOrganizer() {
6380             return mCreatedByOrganizer;
6381         }
6382 
6383         Builder setDeferTaskAppear(boolean defer) {
6384             mDeferTaskAppear = defer;
6385             return this;
6386         }
6387 
6388         Builder setLaunchCookie(IBinder launchCookie) {
6389             mLaunchCookie = launchCookie;
6390             return this;
6391         }
6392 
6393         Builder setOnTop(boolean onTop) {
6394             mOnTop = onTop;
6395             return this;
6396         }
6397 
6398         Builder setHasBeenVisible(boolean hasBeenVisible) {
6399             mHasBeenVisible = hasBeenVisible;
6400             return this;
6401         }
6402 
6403         Builder setRemoveWithTaskOrganizer(boolean removeWithTaskOrganizer) {
6404             mRemoveWithTaskOrganizer = removeWithTaskOrganizer;
6405             return this;
6406         }
6407 
6408         private Builder setUserId(int userId) {
6409             mUserId = userId;
6410             return this;
6411         }
6412 
6413         private Builder setLastTimeMoved(long lastTimeMoved) {
6414             mLastTimeMoved = lastTimeMoved;
6415             return this;
6416         }
6417 
6418         private Builder setNeverRelinquishIdentity(boolean neverRelinquishIdentity) {
6419             mNeverRelinquishIdentity = neverRelinquishIdentity;
6420             return this;
6421         }
6422 
6423         private Builder setCallingUid(int callingUid) {
6424             mCallingUid = callingUid;
6425             return this;
6426         }
6427 
6428         private Builder setCallingPackage(String callingPackage) {
6429             mCallingPackage = callingPackage;
6430             return this;
6431         }
6432 
6433         private Builder setResizeMode(int resizeMode) {
6434             mResizeMode = resizeMode;
6435             return this;
6436         }
6437 
6438         private Builder setSupportsPictureInPicture(boolean supportsPictureInPicture) {
6439             mSupportsPictureInPicture = supportsPictureInPicture;
6440             return this;
6441         }
6442 
6443         private Builder setUserSetupComplete(boolean userSetupComplete) {
6444             mUserSetupComplete = userSetupComplete;
6445             return this;
6446         }
6447 
6448         private Builder setTaskAffiliation(int taskAffiliation) {
6449             mTaskAffiliation = taskAffiliation;
6450             return this;
6451         }
6452 
6453         private Builder setPrevAffiliateTaskId(int prevAffiliateTaskId) {
6454             mPrevAffiliateTaskId = prevAffiliateTaskId;
6455             return this;
6456         }
6457 
6458         private Builder setNextAffiliateTaskId(int nextAffiliateTaskId) {
6459             mNextAffiliateTaskId = nextAffiliateTaskId;
6460             return this;
6461         }
6462 
6463         private Builder setCallingFeatureId(String callingFeatureId) {
6464             mCallingFeatureId = callingFeatureId;
6465             return this;
6466         }
6467 
6468         private Builder setRealActivitySuspended(boolean realActivitySuspended) {
6469             mRealActivitySuspended = realActivitySuspended;
6470             return this;
6471         }
6472 
6473         private Builder setLastDescription(String lastDescription) {
6474             mLastDescription = lastDescription;
6475             return this;
6476         }
6477 
6478         private Builder setLastTaskDescription(TaskDescription lastTaskDescription) {
6479             mLastTaskDescription = lastTaskDescription;
6480             return this;
6481         }
6482 
6483         private Builder setLastSnapshotData(PersistedTaskSnapshotData lastSnapshotData) {
6484             mLastSnapshotData = lastSnapshotData;
6485             return this;
6486         }
6487 
6488         private Builder setOrigActivity(ComponentName origActivity) {
6489             mOrigActivity = origActivity;
6490             return this;
6491         }
6492 
6493         private Builder setRootWasReset(boolean rootWasReset) {
6494             mRootWasReset = rootWasReset;
6495             return this;
6496         }
6497 
6498         private Builder setAutoRemoveRecents(boolean autoRemoveRecents) {
6499             mAutoRemoveRecents = autoRemoveRecents;
6500             return this;
6501         }
6502 
6503         private Builder setAskedCompatMode(boolean askedCompatMode) {
6504             mAskedCompatMode = askedCompatMode;
6505             return this;
6506         }
6507 
6508         private Builder setAffinityIntent(Intent affinityIntent) {
6509             mAffinityIntent = affinityIntent;
6510             return this;
6511         }
6512 
6513         private Builder setAffinity(String affinity) {
6514             mAffinity = affinity;
6515             return this;
6516         }
6517 
6518         private Builder setRootAffinity(String rootAffinity) {
6519             mRootAffinity = rootAffinity;
6520             return this;
6521         }
6522 
6523         private Builder setVoiceInteractor(IVoiceInteractor voiceInteractor) {
6524             mVoiceInteractor = voiceInteractor;
6525             return this;
6526         }
6527 
6528         private void validateRootTask(TaskDisplayArea tda) {
6529             if (mActivityType == ACTIVITY_TYPE_UNDEFINED && !mCreatedByOrganizer) {
6530                 // Can't have an undefined root task type yet...so re-map to standard. Anyone
6531                 // that wants anything else should be passing it in anyways...except for the task
6532                 // organizer.
6533                 mActivityType = ACTIVITY_TYPE_STANDARD;
6534             }
6535 
6536             if (mActivityType != ACTIVITY_TYPE_STANDARD
6537                     && mActivityType != ACTIVITY_TYPE_UNDEFINED) {
6538                 // For now there can be only one root task of a particular non-standard activity
6539                 // type on a display. So, get that ignoring whatever windowing mode it is
6540                 // currently in.
6541                 Task rootTask = tda.getRootTask(WINDOWING_MODE_UNDEFINED, mActivityType);
6542                 if (rootTask != null) {
6543                     throw new IllegalArgumentException("Root task=" + rootTask + " of activityType="
6544                             + mActivityType + " already on display=" + tda
6545                             + ". Can't have multiple.");
6546                 }
6547             }
6548 
6549             if (!TaskDisplayArea.isWindowingModeSupported(mWindowingMode,
6550                     mAtmService.mSupportsMultiWindow,
6551                     mAtmService.mSupportsFreeformWindowManagement,
6552                     mAtmService.mSupportsPictureInPicture)) {
6553                 throw new IllegalArgumentException("Can't create root task for unsupported "
6554                         + "windowingMode=" + mWindowingMode);
6555             }
6556 
6557             if (mWindowingMode == WINDOWING_MODE_PINNED
6558                     && mActivityType != ACTIVITY_TYPE_STANDARD) {
6559                 throw new IllegalArgumentException(
6560                         "Root task with pinned windowing mode cannot with "
6561                                 + "non-standard activity type.");
6562             }
6563 
6564             if (mWindowingMode == WINDOWING_MODE_PINNED && tda.getRootPinnedTask() != null) {
6565                 // Only 1 root task can be PINNED at a time, so dismiss the existing one
6566                 tda.getRootPinnedTask().dismissPip();
6567             }
6568 
6569             if (mIntent != null) {
6570                 mLaunchFlags |= mIntent.getFlags();
6571             }
6572 
6573             // Task created by organizer are added as root.
6574             final Task launchRootTask = mCreatedByOrganizer
6575                     ? null : tda.getLaunchRootTask(mWindowingMode, mActivityType, mActivityOptions,
6576                     mSourceTask, mLaunchFlags);
6577             if (launchRootTask != null) {
6578                 // Since this task will be put into a root task, its windowingMode will be
6579                 // inherited.
6580                 mWindowingMode = WINDOWING_MODE_UNDEFINED;
6581                 mParent = launchRootTask;
6582             }
6583 
6584             mTaskId = tda.getNextRootTaskId();
6585         }
6586 
6587         Task build() {
6588             if (mParent != null && mParent instanceof TaskDisplayArea) {
6589                 validateRootTask((TaskDisplayArea) mParent);
6590             }
6591 
6592             if (mActivityInfo == null) {
6593                 mActivityInfo = new ActivityInfo();
6594                 mActivityInfo.applicationInfo = new ApplicationInfo();
6595             }
6596 
6597             mUserId = UserHandle.getUserId(mActivityInfo.applicationInfo.uid);
6598             mTaskAffiliation = mTaskId;
6599             mLastTimeMoved = System.currentTimeMillis();
6600             mNeverRelinquishIdentity = true;
6601             mCallingUid = mActivityInfo.applicationInfo.uid;
6602             mCallingPackage = mActivityInfo.packageName;
6603             mResizeMode = mActivityInfo.resizeMode;
6604             mSupportsPictureInPicture = mActivityInfo.supportsPictureInPicture();
6605             if (!mRemoveWithTaskOrganizer && mActivityOptions != null) {
6606                 mRemoveWithTaskOrganizer = mActivityOptions.getRemoveWithTaskOranizer();
6607             }
6608 
6609             final Task task = buildInner();
6610             task.mHasBeenVisible = mHasBeenVisible;
6611 
6612             // Set activity type before adding the root task to TaskDisplayArea, so home task can
6613             // be cached, see TaskDisplayArea#addRootTaskReferenceIfNeeded().
6614             if (mActivityType != ACTIVITY_TYPE_UNDEFINED) {
6615                 task.setActivityType(mActivityType);
6616             }
6617 
6618             if (mParent != null) {
6619                 if (mParent instanceof Task) {
6620                     final Task parentTask = (Task) mParent;
6621                     parentTask.addChild(task, mOnTop ? POSITION_TOP : POSITION_BOTTOM,
6622                             (mActivityInfo.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
6623                 } else {
6624                     mParent.addChild(task, mOnTop ? POSITION_TOP : POSITION_BOTTOM);
6625                 }
6626             }
6627 
6628             // Set windowing mode after attached to display area or it abort silently.
6629             if (mWindowingMode != WINDOWING_MODE_UNDEFINED) {
6630                 task.setWindowingMode(mWindowingMode, true /* creating */);
6631             }
6632             return task;
6633         }
6634 
6635         /** Don't use {@link Builder#buildInner()} directly. This is only used by XML parser. */
6636         @VisibleForTesting
6637         Task buildInner() {
6638             return new Task(mAtmService, mTaskId, mIntent, mAffinityIntent, mAffinity,
6639                     mRootAffinity, mRealActivity, mOrigActivity, mRootWasReset, mAutoRemoveRecents,
6640                     mAskedCompatMode, mUserId, mEffectiveUid, mLastDescription, mLastTimeMoved,
6641                     mNeverRelinquishIdentity, mLastTaskDescription, mLastSnapshotData,
6642                     mTaskAffiliation, mPrevAffiliateTaskId, mNextAffiliateTaskId, mCallingUid,
6643                     mCallingPackage, mCallingFeatureId, mResizeMode, mSupportsPictureInPicture,
6644                     mRealActivitySuspended, mUserSetupComplete, mMinWidth, mMinHeight,
6645                     mActivityInfo, mVoiceSession, mVoiceInteractor, mCreatedByOrganizer,
6646                     mLaunchCookie, mDeferTaskAppear, mRemoveWithTaskOrganizer);
6647         }
6648     }
6649 
6650     @Override
6651     void updateOverlayInsetsState(WindowState originalChange) {
6652         super.updateOverlayInsetsState(originalChange);
6653         if (originalChange != getTopVisibleAppMainWindow()) {
6654             return;
6655         }
6656         if (mOverlayHost != null) {
6657             final InsetsState s = originalChange.getInsetsState(true);
6658             getBounds(mTmpRect);
6659             mOverlayHost.dispatchInsetsChanged(s, mTmpRect);
6660         }
6661     }
6662 }
6663