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