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