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