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