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