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