blob: fec484935d68195a7a3af4c5fb15e926e1315583 [file] [log] [blame]
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08001/*
Louis Changcdec0802019-11-11 11:45:07 +08002 * Copyright (C) 2006 The Android Open Source Project
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08003 *
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
17package com.android.server.wm;
18
Louis Changcdec0802019-11-11 11:45:07 +080019import static android.app.ActivityTaskManager.INVALID_TASK_ID;
20import static android.app.ActivityTaskManager.RESIZE_MODE_FORCED;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070021import static android.app.ActivityTaskManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
Riddle Hsu9a8e3ae2020-03-24 15:22:48 +080022import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
23import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
24import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
Louis Changcdec0802019-11-11 11:45:07 +080025import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
26import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -080027import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
Louis Changcdec0802019-11-11 11:45:07 +080028import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
29import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
30import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Louis Changcdec0802019-11-11 11:45:07 +080031import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
32import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
33import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080034import static android.app.WindowConfiguration.activityTypeToString;
35import static android.app.WindowConfiguration.windowingModeToString;
Louis Changcdec0802019-11-11 11:45:07 +080036import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
37import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
38import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
39import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
40import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
41import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
42import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
43import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
44import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080045import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
Jason Monkba53d8a2017-04-06 18:28:19 +000046import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
Jorim Jaggi30d64f32017-04-07 16:33:17 +020047import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Louis Changcdec0802019-11-11 11:45:07 +080048import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
49import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
50import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
51import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Bryce Lee61fbcbc2017-03-10 14:14:03 -080052import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Louis Changcdec0802019-11-11 11:45:07 +080053import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
54import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
55import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
56import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
57import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -080058import static android.view.Display.INVALID_DISPLAY;
Evan Rosky9020c072018-12-06 14:11:12 -080059import static android.view.SurfaceControl.METADATA_TASK_ID;
Evan Rosky55bddd82020-01-29 13:07:18 -080060import static android.view.WindowManager.TRANSIT_TASK_CHANGE_WINDOWING_MODE;
chaviw8c9d1f52018-07-25 14:56:07 -070061
Vishnu Nairf6ef1c72020-01-23 16:28:33 -080062import static com.android.internal.policy.DecorView.DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP;
63import static com.android.internal.policy.DecorView.DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
Louis Changcdec0802019-11-11 11:45:07 +080064import static com.android.server.wm.ActivityRecord.STARTING_WINDOW_SHOWN;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080065import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
Wale Ogunwale0db64ac2020-04-11 10:00:42 -070066import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_INVISIBLE;
67import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
68import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
Louis Changcdec0802019-11-11 11:45:07 +080069import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
70import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
71import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
72import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
73import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
74import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS;
75import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
76import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
77import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
78import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS;
79import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS;
80import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
81import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080082import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
Evan Rosky55bddd82020-01-29 13:07:18 -080083import static com.android.server.wm.IdentifierProto.HASH_CODE;
84import static com.android.server.wm.IdentifierProto.TITLE;
85import static com.android.server.wm.IdentifierProto.USER_ID;
Louis Changcdec0802019-11-11 11:45:07 +080086import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
lumark04bceb92020-03-07 00:03:33 +080087import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_RECENTS_ANIMATIONS;
lumark9bca6b42019-10-17 18:35:22 +080088import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
89import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Vishnu Nairdddc9f52020-03-09 09:37:27 -070090import static com.android.server.wm.WindowContainerChildProto.TASK;
chaviw8c9d1f52018-07-25 14:56:07 -070091import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
Wale Ogunwale8f93b642019-12-26 12:10:52 -080092import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
chaviw8c9d1f52018-07-25 14:56:07 -070093import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -080094import static com.android.server.wm.WindowManagerService.dipToPixel;
lumark5341d1c2019-12-14 01:54:02 +080095import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
Wale Ogunwale99db1862015-10-23 20:08:22 -070096
Louis Changcdec0802019-11-11 11:45:07 +080097import static java.lang.Integer.MAX_VALUE;
98
99import android.annotation.IntDef;
100import android.annotation.NonNull;
101import android.annotation.Nullable;
102import android.app.Activity;
Yunfan Chen0e7aff92018-12-05 16:35:32 -0800103import android.app.ActivityManager;
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100104import android.app.ActivityManager.TaskDescription;
Louis Changcdec0802019-11-11 11:45:07 +0800105import android.app.ActivityManager.TaskSnapshot;
106import android.app.ActivityOptions;
107import android.app.ActivityTaskManager;
108import android.app.AppGlobals;
109import android.app.TaskInfo;
110import android.app.WindowConfiguration;
111import android.content.ComponentName;
112import android.content.Intent;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800113import android.content.pm.ActivityInfo;
Louis Changcdec0802019-11-11 11:45:07 +0800114import android.content.pm.ApplicationInfo;
115import android.content.pm.IPackageManager;
116import android.content.pm.PackageManager;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700117import android.content.res.Configuration;
Louis Chang2570e332020-04-10 11:58:49 +0800118import android.graphics.Point;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700119import android.graphics.Rect;
Louis Changcdec0802019-11-11 11:45:07 +0800120import android.os.Debug;
Garfield Tan90b04282018-12-11 14:04:42 -0800121import android.os.IBinder;
Louis Changcdec0802019-11-11 11:45:07 +0800122import android.os.RemoteException;
123import android.os.SystemClock;
124import android.os.Trace;
125import android.os.UserHandle;
126import android.provider.Settings;
127import android.service.voice.IVoiceInteractionSession;
Evan Rosky55bddd82020-01-29 13:07:18 -0800128import android.util.ArraySet;
Louis Changcdec0802019-11-11 11:45:07 +0800129import android.util.DisplayMetrics;
Craig Mautner42bf39e2014-02-21 16:46:22 -0800130import android.util.Slog;
Evan Rosky55bddd82020-01-29 13:07:18 -0800131import android.util.proto.ProtoOutputStream;
Louis Changcdec0802019-11-11 11:45:07 +0800132import android.view.DisplayInfo;
Evan Rosky55bddd82020-01-29 13:07:18 -0800133import android.view.RemoteAnimationAdapter;
lumark19a5d2e2019-10-11 16:19:30 +0800134import android.view.RemoteAnimationTarget;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700135import android.view.Surface;
Winson Chungd41f71d2018-03-16 15:26:07 -0700136import android.view.SurfaceControl;
lumark04bceb92020-03-07 00:03:33 +0800137import android.view.WindowManager;
Garfield Tana7c9f7c2020-03-13 15:56:51 -0700138import android.window.ITaskOrganizer;
chaviw8c9d1f52018-07-25 14:56:07 -0700139
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800140import com.android.internal.annotations.VisibleForTesting;
Louis Changcdec0802019-11-11 11:45:07 +0800141import com.android.internal.app.IVoiceInteractor;
Louis Changcdec0802019-11-11 11:45:07 +0800142import com.android.internal.util.XmlUtils;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800143import com.android.internal.util.function.pooled.PooledConsumer;
144import com.android.internal.util.function.pooled.PooledFunction;
145import com.android.internal.util.function.pooled.PooledLambda;
146import com.android.internal.util.function.pooled.PooledPredicate;
Louis Changcdec0802019-11-11 11:45:07 +0800147import com.android.server.protolog.common.ProtoLog;
148import com.android.server.wm.ActivityStack.ActivityState;
Craig Mautner2c2549c2013-11-12 08:31:15 -0800149
Louis Changcdec0802019-11-11 11:45:07 +0800150import org.xmlpull.v1.XmlPullParser;
151import org.xmlpull.v1.XmlPullParserException;
152import org.xmlpull.v1.XmlSerializer;
153
154import java.io.IOException;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700155import java.io.PrintWriter;
Louis Changcdec0802019-11-11 11:45:07 +0800156import java.lang.annotation.Retention;
157import java.lang.annotation.RetentionPolicy;
158import java.util.ArrayList;
159import java.util.Objects;
Jorim Jaggi51304d72017-05-17 17:25:32 +0200160import java.util.function.Consumer;
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900161import java.util.function.Function;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800162import java.util.function.Predicate;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700163
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800164class Task extends WindowContainer<WindowContainer> {
Louis Changcdec0802019-11-11 11:45:07 +0800165 private static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_ATM;
166 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
167 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
168 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
169 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
170
171 private static final String ATTR_TASKID = "task_id";
172 private static final String TAG_INTENT = "intent";
173 private static final String TAG_AFFINITYINTENT = "affinity_intent";
174 private static final String ATTR_REALACTIVITY = "real_activity";
175 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
176 private static final String ATTR_ORIGACTIVITY = "orig_activity";
177 private static final String TAG_ACTIVITY = "activity";
178 private static final String ATTR_AFFINITY = "affinity";
179 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
180 private static final String ATTR_ROOTHASRESET = "root_has_reset";
181 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
182 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
183 private static final String ATTR_USERID = "user_id";
184 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
185 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
186 @Deprecated
187 private static final String ATTR_TASKTYPE = "task_type";
188 private static final String ATTR_LASTDESCRIPTION = "last_description";
189 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
190 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
191 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
192 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
193 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
194 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
195 private static final String ATTR_CALLING_UID = "calling_uid";
196 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Philip P. Moltmannee295092020-02-10 08:46:26 -0800197 private static final String ATTR_CALLING_FEATURE_ID = "calling_feature_id";
Louis Changcdec0802019-11-11 11:45:07 +0800198 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
199 private static final String ATTR_RESIZE_MODE = "resize_mode";
200 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
201 private static final String ATTR_MIN_WIDTH = "min_width";
202 private static final String ATTR_MIN_HEIGHT = "min_height";
203 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Garfield Tan5901e7c2020-02-07 17:12:22 -0800204 private static final String ATTR_WINDOW_LAYOUT_AFFINITY = "window_layout_affinity";
Louis Changcdec0802019-11-11 11:45:07 +0800205
206 // Current version of the task record we persist. Used to check if we need to run any upgrade
207 // code.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800208 static final int PERSIST_TASK_VERSION = 1;
Louis Changcdec0802019-11-11 11:45:07 +0800209
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800210 static final int INVALID_MIN_SIZE = -1;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -0800211 private float mShadowRadius = 0;
Louis Changcdec0802019-11-11 11:45:07 +0800212
213 /**
214 * The modes to control how the stack is moved to the front when calling {@link Task#reparent}.
215 */
216 @Retention(RetentionPolicy.SOURCE)
217 @IntDef({
218 REPARENT_MOVE_STACK_TO_FRONT,
219 REPARENT_KEEP_STACK_AT_FRONT,
220 REPARENT_LEAVE_STACK_IN_PLACE
221 })
222 @interface ReparentMoveStackMode {}
223 // Moves the stack to the front if it was not at the front
224 static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
225 // Only moves the stack to the front if it was focused or front most already
226 static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
227 // Do not move the stack as a part of reparenting
228 static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
229
Louis Changcdec0802019-11-11 11:45:07 +0800230 String affinity; // The affinity name for this task, or null; may change identity.
231 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Garfield Tan5901e7c2020-02-07 17:12:22 -0800232 String mWindowLayoutAffinity; // Launch param affinity of this task or null. Used when saving
233 // launch params of this task.
Wale Ogunwale0d465192020-01-23 19:14:44 -0800234 IVoiceInteractionSession voiceSession; // Voice interaction session driving task
235 IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
Louis Changcdec0802019-11-11 11:45:07 +0800236 Intent intent; // The original intent that started the task. Note that this value can
237 // be null.
238 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
239 int effectiveUid; // The current effective uid of the identity of this task.
240 ComponentName origActivity; // The non-alias activity component of the intent.
241 ComponentName realActivity; // The actual activity component that started the task.
242 boolean realActivitySuspended; // True if the actual activity component that started the
243 // task is suspended.
244 boolean inRecents; // Actually in the recents list?
245 long lastActiveTime; // Last time this task was active in the current device session,
246 // including sleep. This time is initialized to the elapsed time when
247 // restored from disk.
248 boolean isAvailable; // Is the activity available to be launched?
249 boolean rootWasReset; // True if the intent at the root of the task had
250 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
251 boolean autoRemoveRecents; // If true, we should automatically remove the task from
252 // recents when activity finishes
253 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Robert Carrde96c8a2020-03-24 15:22:21 -0700254 private boolean mHasBeenVisible; // Set if any activities in the task have been visible
Louis Changcdec0802019-11-11 11:45:07 +0800255
256 String stringName; // caching of toString() result.
257 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
258 // was changed.
259
Louis Changcdec0802019-11-11 11:45:07 +0800260 /** Can't be put in lockTask mode. */
261 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
262 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
263 final static int LOCK_TASK_AUTH_PINNABLE = 1;
264 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
265 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
266 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
267 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
268 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
269 * lockTask task. */
270 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
271 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
272
273 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
274
Louis Changcdec0802019-11-11 11:45:07 +0800275 /** The process that had previously hosted the root activity of this task.
276 * Used to know that we should try harder to keep this process around, in case the
277 * user wants to return to it. */
278 private WindowProcessController mRootProcess;
279
280 /** Takes on same value as first root activity */
281 boolean isPersistable = false;
282 int maxRecents;
283
284 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
285 * determining the order when restoring. Sign indicates whether last task movement was to front
286 * (positive) or back (negative). Absolute value indicates time. */
287 long mLastTimeMoved;
288
289 /** If original intent did not allow relinquishing task identity, save that information */
290 private boolean mNeverRelinquishIdentity = true;
291
292 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
293 // do not want to delete the stack when the task goes empty.
294 private boolean mReuseTask = false;
295
296 CharSequence lastDescription; // Last description captured for this item.
297
298 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
299 int mAffiliatedTaskColor; // color of the parent task affiliation.
300 Task mPrevAffiliate; // previous task in affiliated chain.
301 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
302 Task mNextAffiliate; // next task in affiliated chain.
303 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
304
305 // For relaunching the task from recents as though it was launched by the original launcher.
306 int mCallingUid;
307 String mCallingPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800308 String mCallingFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +0800309
310 private final Rect mTmpStableBounds = new Rect();
311 private final Rect mTmpNonDecorBounds = new Rect();
312 private final Rect mTmpBounds = new Rect();
313 private final Rect mTmpInsets = new Rect();
Evan Rosky70213702019-11-05 10:26:24 -0800314 private final Rect mTmpFullBounds = new Rect();
Louis Changcdec0802019-11-11 11:45:07 +0800315
316 // Last non-fullscreen bounds the task was launched in or resized to.
317 // The information is persisted and used to determine the appropriate stack to launch the
318 // task into on restore.
319 Rect mLastNonFullscreenBounds = null;
320 // Minimal width and height of this task when it's resizeable. -1 means it should use the
321 // default minimal width/height.
322 int mMinWidth;
323 int mMinHeight;
324
325 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
326 // This number will be assigned when we evaluate OOM scores for all visible tasks.
327 int mLayerRank = -1;
328
329 /** Helper object used for updating override configuration. */
330 private Configuration mTmpConfig = new Configuration();
331
332 /** Used by fillTaskInfo */
333 final TaskActivitiesReport mReuseActivitiesReport = new TaskActivitiesReport();
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700334
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200335 final ActivityTaskManagerService mAtmService;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800336 final ActivityStackSupervisor mStackSupervisor;
337 final RootWindowContainer mRootWindowContainer;
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200338
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700339 /* Unique identifier for this task. */
Craig Mautner83162a92015-01-26 14:43:30 -0800340 final int mTaskId;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700341 /* User for which this task was created. */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200342 // TODO: Make final
343 int mUserId;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800344
Jorim Jaggi0429f352015-12-22 16:29:16 +0100345 final Rect mPreparedFrozenBounds = new Rect();
Jorim Jaggi26c8c422016-05-09 19:57:25 -0700346 final Configuration mPreparedFrozenMergedConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700347
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800348 // Id of the previous display the stack was on.
349 int mPrevDisplayId = INVALID_DISPLAY;
350
Garfield Tandec96db2018-10-30 11:28:49 -0700351 /** ID of the display which rotation {@link #mRotation} has. */
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800352 private int mLastRotationDisplayId = INVALID_DISPLAY;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800353
Garfield Tandec96db2018-10-30 11:28:49 -0700354 /**
355 * Display rotation as of the last time {@link #setBounds(Rect)} was called or this task was
356 * moved to a new display.
357 */
Vadim Caenfc14c662020-01-20 16:00:31 +0100358 @Surface.Rotation
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700359 private int mRotation;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700360
Garfield Tanafa0de82020-03-03 16:07:07 -0800361 /**
362 * Last requested orientation reported to DisplayContent. This is different from {@link
363 * #mOrientation} in the sense that this takes activities' requested orientation into
364 * account. Start with {@link ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} so that we don't need
365 * to notify for activities that don't specify any orientation.
366 */
367 int mLastReportedRequestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
368
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700369 // For comparison with DisplayContent bounds.
370 private Rect mTmpRect = new Rect();
371 // For handling display rotations.
372 private Rect mTmpRect2 = new Rect();
373
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800374 // Resize mode of the task. See {@link ActivityInfo#resizeMode}
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200375 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
376 int mResizeMode;
Chong Zhangb15758a2015-11-17 12:12:03 -0800377
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200378 // Whether or not this task and its activities support PiP. Based on the
379 // {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag of the root activity.
380 boolean mSupportsPictureInPicture;
Winson Chungd3395382016-12-13 11:49:09 -0800381
Chong Zhang3005e752015-09-18 18:46:28 -0700382 // Whether the task is currently being drag-resized
383 private boolean mDragResizing;
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +0100384 private int mDragResizeMode;
Chong Zhang3005e752015-09-18 18:46:28 -0700385
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700386 // This represents the last resolved activity values for this task
387 // NOTE: This value needs to be persisted with each task
Jorim Jaggi829b9cd2017-01-23 16:20:53 +0100388 private TaskDescription mTaskDescription;
389
Robert Carr18f622f2017-05-08 11:20:43 -0700390 // If set to true, the task will report that it is not in the floating
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700391 // state regardless of it's stack affiliation. As the floating state drives
Robert Carr18f622f2017-05-08 11:20:43 -0700392 // production of content insets this can be used to preserve them across
393 // stack moves and we in fact do so when moving from full screen to pinned.
394 private boolean mPreserveNonFloatingState = false;
395
Robert Carrf59b8dd2017-10-02 18:58:36 -0700396 private Dimmer mDimmer = new Dimmer(this);
397 private final Rect mTmpDimBoundsRect = new Rect();
Louis Chang2570e332020-04-10 11:58:49 +0800398 private final Point mLastSurfaceSize = new Point();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700399
Jorim Jaggi50bf59c2018-03-09 17:29:48 +0100400 /** @see #setCanAffectSystemUiFlags */
401 private boolean mCanAffectSystemUiFlags = true;
402
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800403 private static Exception sTmpException;
404
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800405 /** ActivityRecords that are exiting, but still on screen for animations. */
406 final ArrayList<ActivityRecord> mExitingActivities = new ArrayList<>();
407
408 /**
409 * When we are in the process of pausing an activity, before starting the
410 * next one, this variable holds the activity that is currently being paused.
411 */
412 ActivityRecord mPausingActivity = null;
413
414 /**
415 * This is the last activity that we put into the paused state. This is
416 * used to determine if we need to do an activity transition while sleeping,
417 * when we normally hold the top activity paused.
418 */
419 ActivityRecord mLastPausedActivity = null;
420
421 /**
422 * Activities that specify No History must be removed once the user navigates away from them.
423 * If the device goes to sleep with such an activity in the paused state then we save it here
424 * and finish it later if another activity replaces it on wakeup.
425 */
426 ActivityRecord mLastNoHistoryActivity = null;
427
428 /** Current activity that is resumed, or null if there is none. */
429 ActivityRecord mResumedActivity = null;
430
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -0800431 private boolean mForceShowForAllUsers;
432
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800433 /** When set, will force the task to report as invisible. */
Robert Carrf6878a42019-12-18 02:13:12 -0800434 static final int FLAG_FORCE_HIDDEN_FOR_PINNED_TASK = 1;
435 static final int FLAG_FORCE_HIDDEN_FOR_TASK_ORG = 1 << 1;
436 private int mForceHiddenFlags = 0;
437
Evan Rosky0c86ced2020-05-20 13:38:34 -0700438 // When non-null, this is a transaction that will get applied on the next frame returned after
439 // a relayout is requested from the client. While this is only valid on a leaf task; since the
440 // transaction can effect an ancestor task, this also needs to keep track of the ancestor task
441 // that this transaction manipulates because deferUntilFrame acts on individual surfaces.
Robert Carr711e7052020-02-19 11:14:33 -0800442 SurfaceControl.Transaction mMainWindowSizeChangeTransaction;
Evan Rosky0c86ced2020-05-20 13:38:34 -0700443 Task mMainWindowSizeChangeTask;
Robert Carr711e7052020-02-19 11:14:33 -0800444
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800445 private final FindRootHelper mFindRootHelper = new FindRootHelper();
446 private class FindRootHelper {
447 private ActivityRecord mRoot;
448
449 private void clear() {
450 mRoot = null;
451 }
452
453 ActivityRecord findRoot(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
454 final PooledFunction f = PooledLambda.obtainFunction(FindRootHelper::processActivity,
455 this, PooledLambda.__(ActivityRecord.class), ignoreRelinquishIdentity,
456 setToBottomIfNone);
457 clear();
458 forAllActivities(f, false /*traverseTopToBottom*/);
459 f.recycle();
460 return mRoot;
461 }
462
463 private boolean processActivity(ActivityRecord r,
464 boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
465 if (mRoot == null && setToBottomIfNone) {
466 // This is the first activity we are process. Set it as the candidate root in case
467 // we don't find a better one.
468 mRoot = r;
469 }
470
471 if (r.finishing) return false;
472
473 // Set this as the candidate root since it isn't finishing.
474 mRoot = r;
475
476 // Only end search if we are ignore relinquishing identity or we are not relinquishing.
477 return ignoreRelinquishIdentity || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
478 }
479 }
480
Louis Changcdec0802019-11-11 11:45:07 +0800481 /**
Robert Carr8a2f9132019-11-11 15:03:15 -0800482 * The TaskOrganizer which is delegated presentation of this task. If set the Task will
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700483 * emit an WindowContainerToken (allowing access to it's SurfaceControl leash) to the organizers
Robert Carr8a2f9132019-11-11 15:03:15 -0800484 * taskAppeared callback, and emit a taskRemoved callback when the Task is vanished.
485 */
486 ITaskOrganizer mTaskOrganizer;
Winson Chung77338ab2020-03-09 16:32:34 -0700487 private int mLastTaskOrganizerWindowingMode = -1;
Robert Carrde96c8a2020-03-24 15:22:21 -0700488 /**
489 * Prevent duplicate calls to onTaskAppeared.
490 */
491 boolean mTaskAppearedSent;
Robert Carr8a2f9132019-11-11 15:03:15 -0800492
Robert Carrf6690d12020-02-04 14:16:21 -0800493 /**
Louis Changa009c762020-02-26 11:21:31 +0800494 * This task was created by the task organizer which has the following implementations.
495 * <ul>
496 * <lis>The task won't be removed when it is empty. Removal has to be an explicit request
497 * from the task organizer.</li>
498 * <li>Unlike other non-root tasks, it's direct children are visible to the task
499 * organizer for ordering purposes.</li>
500 * </ul>
501 */
502 boolean mCreatedByOrganizer;
503
504 /**
Louis Changcdec0802019-11-11 11:45:07 +0800505 * Don't use constructor directly. Use {@link #create(ActivityTaskManagerService, int,
506 * ActivityInfo, Intent, TaskDescription)} instead.
507 */
508 Task(ActivityTaskManagerService atmService, int _taskId, ActivityInfo info, Intent _intent,
509 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
510 TaskDescription _taskDescription, ActivityStack stack) {
511 this(atmService, _taskId, _intent, null /*_affinityIntent*/, null /*_affinity*/,
512 null /*_rootAffinity*/, null /*_realActivity*/, null /*_origActivity*/,
513 false /*_rootWasReset*/, false /*_autoRemoveRecents*/, false /*_askedCompatMode*/,
514 UserHandle.getUserId(info.applicationInfo.uid), 0 /*_effectiveUid*/,
515 null /*_lastDescription*/, System.currentTimeMillis(),
516 true /*neverRelinquishIdentity*/,
517 _taskDescription != null ? _taskDescription : new TaskDescription(),
518 _taskId, INVALID_TASK_ID, INVALID_TASK_ID, 0 /*taskAffiliationColor*/,
Philip P. Moltmannee295092020-02-10 08:46:26 -0800519 info.applicationInfo.uid, info.packageName, null /* default featureId */,
520 info.resizeMode, info.supportsPictureInPicture(), false /*_realActivitySuspended*/,
Louis Changcdec0802019-11-11 11:45:07 +0800521 false /*userSetupComplete*/, INVALID_MIN_SIZE, INVALID_MIN_SIZE, info,
522 _voiceSession, _voiceInteractor, stack);
523 }
524
525 /** Don't use constructor directly. This is only used by XML parser. */
Philip P. Moltmannee295092020-02-10 08:46:26 -0800526 Task(ActivityTaskManagerService atmService, int _taskId, Intent _intent, Intent _affinityIntent,
527 String _affinity, String _rootAffinity, ComponentName _realActivity,
528 ComponentName _origActivity, boolean _rootWasReset, boolean _autoRemoveRecents,
529 boolean _askedCompatMode, int _userId, int _effectiveUid, String _lastDescription,
Louis Changcdec0802019-11-11 11:45:07 +0800530 long lastTimeMoved, boolean neverRelinquishIdentity,
531 TaskDescription _lastTaskDescription, int taskAffiliation, int prevTaskId,
532 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Philip P. Moltmannee295092020-02-10 08:46:26 -0800533 @Nullable String callingFeatureId, int resizeMode, boolean supportsPictureInPicture,
534 boolean _realActivitySuspended, boolean userSetupComplete, int minWidth, int minHeight,
535 ActivityInfo info, IVoiceInteractionSession _voiceSession,
536 IVoiceInteractor _voiceInteractor, ActivityStack stack) {
Louis Changcdec0802019-11-11 11:45:07 +0800537 super(atmService.mWindowManager);
538
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -0800539 EventLogTags.writeWmTaskCreated(_taskId, stack != null ? getRootTaskId() : INVALID_TASK_ID);
Louis Changcdec0802019-11-11 11:45:07 +0800540 mAtmService = atmService;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800541 mStackSupervisor = atmService.mStackSupervisor;
542 mRootWindowContainer = mAtmService.mRootWindowContainer;
Louis Changcdec0802019-11-11 11:45:07 +0800543 mTaskId = _taskId;
544 mUserId = _userId;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800545 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800546 mSupportsPictureInPicture = supportsPictureInPicture;
Louis Changcdec0802019-11-11 11:45:07 +0800547 mTaskDescription = _lastTaskDescription;
Riddle Hsu6b76cd32019-10-08 00:37:19 +0800548 // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED).
549 setOrientation(SCREEN_ORIENTATION_UNSET);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700550 mRemoteToken = new RemoteToken(this);
Louis Changcdec0802019-11-11 11:45:07 +0800551 affinityIntent = _affinityIntent;
552 affinity = _affinity;
553 rootAffinity = _rootAffinity;
554 voiceSession = _voiceSession;
555 voiceInteractor = _voiceInteractor;
556 realActivity = _realActivity;
557 realActivitySuspended = _realActivitySuspended;
558 origActivity = _origActivity;
559 rootWasReset = _rootWasReset;
560 isAvailable = true;
561 autoRemoveRecents = _autoRemoveRecents;
562 askedCompatMode = _askedCompatMode;
563 mUserSetupComplete = userSetupComplete;
564 effectiveUid = _effectiveUid;
565 touchActiveTime();
566 lastDescription = _lastDescription;
567 mLastTimeMoved = lastTimeMoved;
568 mNeverRelinquishIdentity = neverRelinquishIdentity;
569 mAffiliatedTaskId = taskAffiliation;
570 mAffiliatedTaskColor = taskAffiliationColor;
571 mPrevAffiliateTaskId = prevTaskId;
572 mNextAffiliateTaskId = nextTaskId;
573 mCallingUid = callingUid;
574 mCallingPackage = callingPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800575 mCallingFeatureId = callingFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +0800576 mResizeMode = resizeMode;
577 if (info != null) {
578 setIntent(_intent, info);
579 setMinDimensions(info);
580 } else {
581 intent = _intent;
582 mMinWidth = minWidth;
583 mMinHeight = minHeight;
584 }
585 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
586 }
587
Wale Ogunwale0d465192020-01-23 19:14:44 -0800588 Task reuseAsLeafTask(IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
Louis Changfbcf55f2020-03-02 12:27:15 +0800589 Intent intent, ActivityInfo info, ActivityRecord activity) {
Wale Ogunwale0d465192020-01-23 19:14:44 -0800590 voiceSession = _voiceSession;
591 voiceInteractor = _voiceInteractor;
Louis Changfbcf55f2020-03-02 12:27:15 +0800592 setIntent(activity, intent, info);
Wale Ogunwale0d465192020-01-23 19:14:44 -0800593 setMinDimensions(info);
Garfield Tana7c9f7c2020-03-13 15:56:51 -0700594 // Before we began to reuse a root task (old ActivityStack) as the leaf task, we used to
595 // create a leaf task in this case. Therefore now we won't send out the task created
596 // notification when we decide to reuse it here, so we send out the notification below.
597 // The reason why the created notification sent out when root task is created doesn't work
598 // is that realActivity isn't set until setIntent() method above is called for the first
599 // time. Eventually this notification will be removed when we can populate those information
600 // when root task is created.
601 mAtmService.getTaskChangeNotificationController().notifyTaskCreated(mTaskId, realActivity);
Wale Ogunwale0d465192020-01-23 19:14:44 -0800602 return this;
603 }
604
Garfield Tan8b096b22020-01-07 14:55:20 -0800605 private void cleanUpResourcesForDestroy(ConfigurationContainer oldParent) {
Louis Changcdec0802019-11-11 11:45:07 +0800606 if (hasChild()) {
607 return;
608 }
609
Garfield Tan59a60fa2020-03-24 10:32:29 -0700610 if (isLeafTask()) {
Garfield Tan8b096b22020-01-07 14:55:20 -0800611 // This task is going away, so save the last state if necessary.
612 saveLaunchingStateIfNeeded(((WindowContainer) oldParent).getDisplayContent());
613 }
Louis Changcdec0802019-11-11 11:45:07 +0800614
615 // TODO: VI what about activity?
616 final boolean isVoiceSession = voiceSession != null;
617 if (isVoiceSession) {
618 try {
619 voiceSession.taskFinished(intent, mTaskId);
620 } catch (RemoteException e) {
621 }
622 }
623 if (autoRemoveFromRecents() || isVoiceSession) {
624 // Task creator asked to remove this when done, or this task was a voice
625 // interaction, so it should not remain on the recent tasks list.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800626 mStackSupervisor.mRecentTasks.remove(this);
Louis Changcdec0802019-11-11 11:45:07 +0800627 }
628
629 removeIfPossible();
630 }
631
632 @VisibleForTesting
633 @Override
634 void removeIfPossible() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800635 final boolean isRootTask = isRootTask();
636 if (!isRootTask) {
637 mAtmService.getLockTaskController().clearLockedTask(this);
638 }
Louis Changcdec0802019-11-11 11:45:07 +0800639 if (shouldDeferRemoval()) {
640 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId);
641 return;
642 }
643 removeImmediately();
Yuncheol Heo1c211c22020-04-20 13:08:43 -0700644 if (isLeafTask()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800645 mAtmService.getTaskChangeNotificationController().notifyTaskRemoved(mTaskId);
646 }
Louis Changcdec0802019-11-11 11:45:07 +0800647 }
648
649 void setResizeMode(int resizeMode) {
650 if (mResizeMode == resizeMode) {
651 return;
652 }
653 mResizeMode = resizeMode;
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800654 mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
655 mRootWindowContainer.resumeFocusedStacksTopActivities();
Louis Changcdec0802019-11-11 11:45:07 +0800656 updateTaskDescription();
657 }
658
Evan Rosky18e00a72020-05-08 09:36:27 -0700659 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow) {
Louis Changcdec0802019-11-11 11:45:07 +0800660 mAtmService.deferWindowLayout();
661
662 try {
663 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
664
665 if (getParent() == null) {
666 // Task doesn't exist in window manager yet (e.g. was restored from recents).
667 // All we can do for now is update the bounds so it can be used when the task is
668 // added to window manager.
669 setBounds(bounds);
670 if (!inFreeformWindowingMode()) {
671 // re-restore the task so it can have the proper stack association.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800672 mStackSupervisor.restoreRecentTaskLocked(this, null, !ON_TOP);
Louis Changcdec0802019-11-11 11:45:07 +0800673 }
674 return true;
675 }
676
677 if (!canResizeToBounds(bounds)) {
678 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
679 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
680 }
681
682 // Do not move the task to another stack here.
683 // This method assumes that the task is already placed in the right stack.
684 // we do not mess with that decision and we only do the resize!
685
686 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizeTask_" + mTaskId);
687
688 boolean updatedConfig = false;
689 mTmpConfig.setTo(getResolvedOverrideConfiguration());
690 if (setBounds(bounds) != BOUNDS_CHANGE_NONE) {
691 updatedConfig = !mTmpConfig.equals(getResolvedOverrideConfiguration());
692 }
693 // This variable holds information whether the configuration didn't change in a
694 // significant way and the activity was kept the way it was. If it's false, it means
695 // the activity had to be relaunched due to configuration change.
696 boolean kept = true;
697 if (updatedConfig) {
698 final ActivityRecord r = topRunningActivityLocked();
Evan Rosky18e00a72020-05-08 09:36:27 -0700699 if (r != null) {
Louis Changcdec0802019-11-11 11:45:07 +0800700 kept = r.ensureActivityConfiguration(0 /* globalChanges */,
701 preserveWindow);
702 // Preserve other windows for resizing because if resizing happens when there
703 // is a dialog activity in the front, the activity that still shows some
704 // content to the user will become black and cause flickers. Note in most cases
705 // this won't cause tons of irrelevant windows being preserved because only
706 // activities in this task may experience a bounds change. Configs for other
707 // activities stay the same.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800708 mRootWindowContainer.ensureActivitiesVisible(r, 0, preserveWindow);
Louis Changcdec0802019-11-11 11:45:07 +0800709 if (!kept) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800710 mRootWindowContainer.resumeFocusedStacksTopActivities();
Louis Changcdec0802019-11-11 11:45:07 +0800711 }
712 }
713 }
714 resize(kept, forced);
715
716 saveLaunchingStateIfNeeded();
717
718 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
719 return kept;
720 } finally {
721 mAtmService.continueWindowLayout();
722 }
723 }
724
725 /** Convenience method to reparent a task to the top or bottom position of the stack. */
726 boolean reparent(ActivityStack preferredStack, boolean toTop,
727 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
728 String reason) {
729 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate, deferResume,
730 true /* schedulePictureInPictureModeChange */, reason);
731 }
732
733 /**
734 * Convenience method to reparent a task to the top or bottom position of the stack, with
735 * an option to skip scheduling the picture-in-picture mode change.
736 */
737 boolean reparent(ActivityStack preferredStack, boolean toTop,
738 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
739 boolean schedulePictureInPictureModeChange, String reason) {
740 return reparent(preferredStack, toTop ? MAX_VALUE : 0, moveStackMode, animate,
741 deferResume, schedulePictureInPictureModeChange, reason);
742 }
743
744 /** Convenience method to reparent a task to a specific position of the stack. */
745 boolean reparent(ActivityStack preferredStack, int position,
746 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
747 String reason) {
748 return reparent(preferredStack, position, moveStackMode, animate, deferResume,
749 true /* schedulePictureInPictureModeChange */, reason);
750 }
751
752 /**
753 * Reparents the task into a preferred stack, creating it if necessary.
754 *
755 * @param preferredStack the target stack to move this task
756 * @param position the position to place this task in the new stack
757 * @param animate whether or not we should wait for the new window created as a part of the
758 * reparenting to be drawn and animated in
759 * @param moveStackMode whether or not to move the stack to the front always, only if it was
760 * previously focused & in front, or never
761 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
762 * have changed as a result of this reparenting
763 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
764 * change. Callers may set this to false if they are explicitly scheduling PiP mode
765 * changes themselves, like during the PiP animation
766 * @param reason the caller of this reparenting
767 * @return whether the task was reparented
768 */
769 // TODO: Inspect all call sites and change to just changing windowing mode of the stack vs.
770 // re-parenting the task. Can only be done when we are no longer using static stack Ids.
771 boolean reparent(ActivityStack preferredStack, int position,
772 @ReparentMoveStackMode int moveStackMode, boolean animate, boolean deferResume,
773 boolean schedulePictureInPictureModeChange, String reason) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800774 final ActivityStackSupervisor supervisor = mStackSupervisor;
775 final RootWindowContainer root = mRootWindowContainer;
Louis Changcdec0802019-11-11 11:45:07 +0800776 final WindowManagerService windowManager = mAtmService.mWindowManager;
777 final ActivityStack sourceStack = getStack();
778 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStack,
779 position == MAX_VALUE);
780 if (toStack == sourceStack) {
781 return false;
782 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800783 if (!canBeLaunchedOnDisplay(toStack.getDisplayId())) {
Louis Changcdec0802019-11-11 11:45:07 +0800784 return false;
785 }
786
787 final boolean toTopOfStack = position == MAX_VALUE;
788 if (toTopOfStack && toStack.getResumedActivity() != null
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900789 && toStack.topRunningActivity() != null) {
Louis Changcdec0802019-11-11 11:45:07 +0800790 // Pause the resumed activity on the target stack while re-parenting task on top of it.
791 toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
792 null /* resuming */);
793 }
794
795 final int toStackWindowingMode = toStack.getWindowingMode();
Wale Ogunwale21e06482019-11-18 05:14:15 -0800796 final ActivityRecord topActivity = getTopNonFinishingActivity();
Louis Changcdec0802019-11-11 11:45:07 +0800797
798 final boolean mightReplaceWindow = topActivity != null
799 && replaceWindowsOnTaskMove(getWindowingMode(), toStackWindowingMode);
800 if (mightReplaceWindow) {
801 // We are about to relaunch the activity because its configuration changed due to
802 // being maximized, i.e. size change. The activity will first remove the old window
803 // and then add a new one. This call will tell window manager about this, so it can
804 // preserve the old window until the new one is drawn. This prevents having a gap
805 // between the removal and addition, in which no window is visible. We also want the
806 // entrance of the new window to be properly animated.
807 // Note here we always set the replacing window first, as the flags might be needed
808 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
809 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
810 }
811
812 mAtmService.deferWindowLayout();
813 boolean kept = true;
814 try {
815 final ActivityRecord r = topRunningActivityLocked();
Louis Changcdec0802019-11-11 11:45:07 +0800816 final boolean wasFocused = r != null && root.isTopDisplayFocusedStack(sourceStack)
817 && (topRunningActivityLocked() == r);
818 final boolean wasResumed = r != null && sourceStack.getResumedActivity() == r;
819 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
820
821 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
822 // Whenever we are moving the top activity from the front stack we want to make sure to
823 // move the stack to the front.
Andrii Kulian86d676c2020-03-27 19:34:54 -0700824 final boolean wasFront = r != null && sourceStack.isTopStackInDisplayArea()
Wale Ogunwale85fb19a2019-12-05 10:41:05 +0900825 && (sourceStack.topRunningActivity() == r);
Louis Changcdec0802019-11-11 11:45:07 +0800826
827 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
828 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
829
830 reparent(toStack, position, moveStackToFront, reason);
831
832 if (schedulePictureInPictureModeChange) {
833 // Notify of picture-in-picture mode changes
834 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
835 }
836
837 // If the task had focus before (or we're requested to move focus), move focus to the
838 // new stack by moving the stack to the front.
839 if (r != null) {
840 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
841 wasPaused, reason);
842 }
843 if (!animate) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800844 mStackSupervisor.mNoAnimActivities.add(topActivity);
Louis Changcdec0802019-11-11 11:45:07 +0800845 }
846
847 // We might trigger a configuration change. Save the current task bounds for freezing.
848 // TODO: Should this call be moved inside the resize method in WM?
849 toStack.prepareFreezingTaskBounds();
850
Evan Rosky18e00a72020-05-08 09:36:27 -0700851 if (toStackWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
852 && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
853 // Move recents to front so it is not behind home stack when going into docked
854 // mode
855 mStackSupervisor.moveRecentsStackToFront(reason);
Louis Changcdec0802019-11-11 11:45:07 +0800856 }
857 } finally {
858 mAtmService.continueWindowLayout();
859 }
860
861 if (mightReplaceWindow) {
862 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
863 // window), we need to clear the replace window settings. Otherwise, we schedule a
864 // timeout to remove the old window if the replacing window is not coming in time.
865 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
866 }
867
868 if (!deferResume) {
869 // The task might have already been running and its visibility needs to be synchronized
870 // with the visibility of the stack / windows.
871 root.ensureActivitiesVisible(null, 0, !mightReplaceWindow);
872 root.resumeFocusedStacksTopActivities();
873 }
874
875 // TODO: Handle incorrect request to move before the actual move, not after.
876 supervisor.handleNonResizableTaskIfNeeded(this, preferredStack.getWindowingMode(),
Andrii Kulian1cb59dd2020-04-10 12:17:17 -0700877 mRootWindowContainer.getDefaultTaskDisplayArea(), toStack);
Louis Changcdec0802019-11-11 11:45:07 +0800878
879 return (preferredStack == toStack);
880 }
881
882 /**
883 * @return {@code true} if the windows of tasks being moved to the target stack from the
884 * source stack should be replaced, meaning that window manager will keep the old window
885 * around until the new is ready.
886 */
887 private static boolean replaceWindowsOnTaskMove(
888 int sourceWindowingMode, int targetWindowingMode) {
889 return sourceWindowingMode == WINDOWING_MODE_FREEFORM
890 || targetWindowingMode == WINDOWING_MODE_FREEFORM;
891 }
892
893 /**
894 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
895 */
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800896 TaskSnapshot getSnapshot(boolean isLowResolution, boolean restoreFromDisk) {
Louis Changcdec0802019-11-11 11:45:07 +0800897
898 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
899 // synchronized between AM and WM.
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800900 return mAtmService.mWindowManager.getTaskSnapshot(mTaskId, mUserId, isLowResolution,
Louis Changcdec0802019-11-11 11:45:07 +0800901 restoreFromDisk);
902 }
903
904 void touchActiveTime() {
905 lastActiveTime = SystemClock.elapsedRealtime();
906 }
907
908 long getInactiveDuration() {
909 return SystemClock.elapsedRealtime() - lastActiveTime;
910 }
911
Louis Changfbcf55f2020-03-02 12:27:15 +0800912 /** @see #setIntent(ActivityRecord, Intent, ActivityInfo) */
Louis Changcdec0802019-11-11 11:45:07 +0800913 void setIntent(ActivityRecord r) {
Louis Changfbcf55f2020-03-02 12:27:15 +0800914 setIntent(r, null /* intent */, null /* info */);
915 }
916
917 /**
918 * Sets the original intent, and the calling uid and package.
919 *
920 * @param r The activity that started the task
921 * @param intent The task info which could be different from {@code r.intent} if set.
922 * @param info The activity info which could be different from {@code r.info} if set.
923 */
924 void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) {
Louis Changcdec0802019-11-11 11:45:07 +0800925 mCallingUid = r.launchedFromUid;
926 mCallingPackage = r.launchedFromPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -0800927 mCallingFeatureId = r.launchedFromFeatureId;
Louis Changfbcf55f2020-03-02 12:27:15 +0800928 setIntent(intent != null ? intent : r.intent, info != null ? info : r.info);
Louis Changcdec0802019-11-11 11:45:07 +0800929 setLockTaskAuth(r);
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800930
931 final WindowContainer parent = getParent();
932 if (parent != null) {
933 final Task t = parent.asTask();
934 if (t != null) {
935 t.setIntent(r);
936 }
937 }
Louis Changcdec0802019-11-11 11:45:07 +0800938 }
939
940 /** Sets the original intent, _without_ updating the calling uid or package. */
941 private void setIntent(Intent _intent, ActivityInfo info) {
Evan Rosky889f4962020-06-12 14:49:56 -0700942 final boolean isLeaf = isLeafTask();
Louis Changcdec0802019-11-11 11:45:07 +0800943 if (intent == null) {
944 mNeverRelinquishIdentity =
945 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Evan Rosky889f4962020-06-12 14:49:56 -0700946 } else if (mNeverRelinquishIdentity && isLeaf) {
Louis Changcdec0802019-11-11 11:45:07 +0800947 return;
948 }
949
Evan Rosky889f4962020-06-12 14:49:56 -0700950 affinity = isLeaf ? info.taskAffinity : null;
Louis Changcdec0802019-11-11 11:45:07 +0800951 if (intent == null) {
952 // If this task already has an intent associated with it, don't set the root
953 // affinity -- we don't want it changing after initially set, but the initially
954 // set value may be null.
955 rootAffinity = affinity;
956 }
957 effectiveUid = info.applicationInfo.uid;
958 stringName = null;
959
960 if (info.targetActivity == null) {
961 if (_intent != null) {
962 // If this Intent has a selector, we want to clear it for the
963 // recent task since it is not relevant if the user later wants
964 // to re-launch the app.
965 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
966 _intent = new Intent(_intent);
967 _intent.setSelector(null);
968 _intent.setSourceBounds(null);
969 }
970 }
971 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
972 intent = _intent;
973 realActivity = _intent != null ? _intent.getComponent() : null;
974 origActivity = null;
975 } else {
976 ComponentName targetComponent = new ComponentName(
977 info.packageName, info.targetActivity);
978 if (_intent != null) {
979 Intent targetIntent = new Intent(_intent);
980 targetIntent.setSelector(null);
981 targetIntent.setSourceBounds(null);
982 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
983 "Setting Intent of " + this + " to target " + targetIntent);
984 intent = targetIntent;
985 realActivity = targetComponent;
986 origActivity = _intent.getComponent();
987 } else {
988 intent = null;
989 realActivity = targetComponent;
990 origActivity = new ComponentName(info.packageName, info.name);
991 }
992 }
Garfield Tan5901e7c2020-02-07 17:12:22 -0800993 mWindowLayoutAffinity =
994 info.windowLayout == null ? null : info.windowLayout.windowLayoutAffinity;
Louis Changcdec0802019-11-11 11:45:07 +0800995
996 final int intentFlags = intent == null ? 0 : intent.getFlags();
997 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
998 // Once we are set to an Intent with this flag, we count this
999 // task as having a true root activity.
1000 rootWasReset = true;
1001 }
1002 mUserId = UserHandle.getUserId(info.applicationInfo.uid);
1003 mUserSetupComplete = Settings.Secure.getIntForUser(
1004 mAtmService.mContext.getContentResolver(), USER_SETUP_COMPLETE, 0, mUserId) != 0;
1005 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
1006 // If the activity itself has requested auto-remove, then just always do it.
1007 autoRemoveRecents = true;
1008 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
1009 == FLAG_ACTIVITY_NEW_DOCUMENT) {
1010 // If the caller has not asked for the document to be retained, then we may
1011 // want to turn on auto-remove, depending on whether the target has set its
1012 // own document launch mode.
1013 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
1014 autoRemoveRecents = false;
1015 } else {
1016 autoRemoveRecents = true;
1017 }
1018 } else {
1019 autoRemoveRecents = false;
1020 }
1021 if (mResizeMode != info.resizeMode) {
1022 mResizeMode = info.resizeMode;
1023 updateTaskDescription();
1024 }
1025 mSupportsPictureInPicture = info.supportsPictureInPicture();
1026 }
1027
1028 /** Sets the original minimal width and height. */
Wale Ogunwale0d465192020-01-23 19:14:44 -08001029 void setMinDimensions(ActivityInfo info) {
Louis Changcdec0802019-11-11 11:45:07 +08001030 if (info != null && info.windowLayout != null) {
1031 mMinWidth = info.windowLayout.minWidth;
1032 mMinHeight = info.windowLayout.minHeight;
1033 } else {
1034 mMinWidth = INVALID_MIN_SIZE;
1035 mMinHeight = INVALID_MIN_SIZE;
1036 }
1037 }
1038
1039 /**
1040 * Return true if the input activity has the same intent filter as the intent this task
1041 * record is based on (normally the root activity intent).
1042 */
1043 boolean isSameIntentFilter(ActivityRecord r) {
1044 final Intent intent = new Intent(r.intent);
1045 // Make sure the component are the same if the input activity has the same real activity
1046 // as the one in the task because either one of them could be the alias activity.
1047 if (Objects.equals(realActivity, r.mActivityComponent) && this.intent != null) {
1048 intent.setComponent(this.intent.getComponent());
1049 }
1050 return intent.filterEquals(this.intent);
1051 }
1052
1053 boolean returnsToHomeStack() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001054 if (inMultiWindowMode() || !hasChild()) return false;
1055 if (intent != null) {
1056 final int returnHomeFlags = FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME;
1057 return intent != null && (intent.getFlags() & returnHomeFlags) == returnHomeFlags;
1058 }
1059 final Task bottomTask = getBottomMostTask();
1060 return bottomTask != this && bottomTask.returnsToHomeStack();
Louis Changcdec0802019-11-11 11:45:07 +08001061 }
1062
1063 void setPrevAffiliate(Task prevAffiliate) {
1064 mPrevAffiliate = prevAffiliate;
1065 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.mTaskId;
1066 }
1067
1068 void setNextAffiliate(Task nextAffiliate) {
1069 mNextAffiliate = nextAffiliate;
1070 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.mTaskId;
1071 }
1072
Louis Changcdec0802019-11-11 11:45:07 +08001073 @Override
1074 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001075 final DisplayContent display = newParent != null
1076 ? ((WindowContainer) newParent).getDisplayContent() : null;
1077 final DisplayContent oldDisplay = oldParent != null
1078 ? ((WindowContainer) oldParent).getDisplayContent() : null;
1079
1080 mPrevDisplayId = (oldDisplay != null) ? oldDisplay.mDisplayId : INVALID_DISPLAY;
Louis Changcdec0802019-11-11 11:45:07 +08001081
Louis Chang8bda2322019-12-05 16:38:11 +08001082 if (oldParent != null && newParent == null) {
Garfield Tan8b096b22020-01-07 14:55:20 -08001083 cleanUpResourcesForDestroy(oldParent);
Louis Chang8bda2322019-12-05 16:38:11 +08001084 }
1085
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001086 if (display != null) {
1087 // TODO(NOW!): Chat with the erosky@ of this code to see if this really makes sense here...
1088 // Rotations are relative to the display. This means if there are 2 displays rotated
1089 // differently (eg. 2 monitors with one landscape and one portrait), moving a stack
1090 // from one to the other could look like a rotation change. To prevent this
1091 // apparent rotation change (and corresponding bounds rotation), pretend like our
1092 // current rotation is already the same as the new display.
1093 // Note, if ActivityStack or related logic ever gets nested, this logic will need
1094 // to move to onConfigurationChanged.
1095 getConfiguration().windowConfiguration.setRotation(
1096 display.getWindowConfiguration().getRotation());
1097 }
1098
Louis Changcdec0802019-11-11 11:45:07 +08001099 super.onParentChanged(newParent, oldParent);
1100
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001101 // TODO(NOW): The check for null display content and setting it to null doesn't really
1102 // make sense here...
Louis Changcdec0802019-11-11 11:45:07 +08001103
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001104 // TODO(stack-merge): This is mostly taking care of the case where the stask is removing from
1105 // the display, so we should probably consolidate it there instead.
1106
1107 if (getParent() == null && mDisplayContent != null) {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08001108 EventLogTags.writeWmStackRemoved(getRootTaskId());
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001109 mDisplayContent = null;
1110 mWmService.mWindowPlacerLocked.requestTraversal();
1111 }
1112
1113 if (oldParent != null) {
1114 final Task oldParentTask = ((WindowContainer) oldParent).asTask();
1115 if (oldParentTask != null) {
1116 final PooledConsumer c = PooledLambda.obtainConsumer(
1117 Task::cleanUpActivityReferences, oldParentTask,
1118 PooledLambda.__(ActivityRecord.class));
1119 forAllActivities(c);
1120 c.recycle();
1121 }
1122
1123 if (oldParent.inPinnedWindowingMode()
1124 && (newParent == null || !newParent.inPinnedWindowingMode())) {
Louis Changcdec0802019-11-11 11:45:07 +08001125 // Notify if a task from the pinned stack is being removed
1126 // (or moved depending on the mode).
1127 mAtmService.getTaskChangeNotificationController().notifyActivityUnpinned();
1128 }
1129 }
1130
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001131 if (newParent != null) {
1132 final Task newParentTask = ((WindowContainer) newParent).asTask();
1133 if (newParentTask != null) {
1134 final ActivityRecord top = newParentTask.getTopNonFinishingActivity(
1135 false /* includeOverlays */);
1136 if (top != null && top.isState(RESUMED)) {
1137 newParentTask.setResumedActivity(top, "addedToTask");
1138 }
1139 }
Louis Changcdec0802019-11-11 11:45:07 +08001140
1141 // TODO: Ensure that this is actually necessary here
1142 // Notify the voice session if required
1143 if (voiceSession != null) {
1144 try {
1145 voiceSession.taskStarted(intent, mTaskId);
1146 } catch (RemoteException e) {
1147 }
1148 }
1149 }
1150
1151 // First time we are adding the task to the system.
1152 if (oldParent == null && newParent != null) {
1153
1154 // TODO: Super random place to be doing this, but aligns with what used to be done
1155 // before we unified Task level. Look into if this can be done in a better place.
1156 updateOverrideConfigurationFromLaunchBounds();
1157 }
1158
Louis Changcdec0802019-11-11 11:45:07 +08001159 // Update task bounds if needed.
1160 adjustBoundsForDisplayChangeIfNeeded(getDisplayContent());
1161
1162 if (getWindowConfiguration().windowsAreScaleable()) {
1163 // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them
1164 // while a resize is pending.
1165 forceWindowsScaleable(true /* force */);
1166 } else {
1167 forceWindowsScaleable(false /* force */);
1168 }
1169
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001170 mRootWindowContainer.updateUIDsPresentOnDisplay();
1171 }
1172
1173 void cleanUpActivityReferences(ActivityRecord r) {
1174 final WindowContainer parent = getParent();
1175 if (parent != null && parent.asTask() != null) {
1176 parent.asTask().cleanUpActivityReferences(r);
1177 return;
1178 }
1179 r.removeTimeouts();
1180 mExitingActivities.remove(r);
1181
1182 if (mResumedActivity != null && mResumedActivity == r) {
1183 setResumedActivity(null, "cleanUpActivityReferences");
1184 }
1185 if (mPausingActivity != null && mPausingActivity == r) {
1186 mPausingActivity = null;
1187 }
1188 }
1189
1190 /** @return the currently resumed activity. */
1191 ActivityRecord getResumedActivity() {
1192 return mResumedActivity;
1193 }
1194
1195 void setResumedActivity(ActivityRecord r, String reason) {
1196 if (mResumedActivity == r) {
1197 return;
1198 }
1199
1200 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) Slog.d(TAG_STACK,
1201 "setResumedActivity stack:" + this + " + from: "
1202 + mResumedActivity + " to:" + r + " reason:" + reason);
1203 mResumedActivity = r;
1204 mStackSupervisor.updateTopResumedActivityIfNeeded();
Louis Changcdec0802019-11-11 11:45:07 +08001205 }
1206
1207 void updateTaskMovement(boolean toFront) {
1208 if (isPersistable) {
1209 mLastTimeMoved = System.currentTimeMillis();
1210 // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
1211 // recently will be most negative, tasks sent to the bottom before that will be less
1212 // negative. Similarly for recent tasks moved to the top which will be most positive.
1213 if (!toFront) {
1214 mLastTimeMoved *= -1;
1215 }
1216 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001217 mRootWindowContainer.invalidateTaskLayers();
Louis Changcdec0802019-11-11 11:45:07 +08001218 }
1219
Louis Changcdec0802019-11-11 11:45:07 +08001220 // Close up recents linked list.
1221 private void closeRecentsChain() {
1222 if (mPrevAffiliate != null) {
1223 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
1224 }
1225 if (mNextAffiliate != null) {
1226 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
1227 }
1228 setPrevAffiliate(null);
1229 setNextAffiliate(null);
1230 }
1231
1232 void removedFromRecents() {
1233 closeRecentsChain();
1234 if (inRecents) {
1235 inRecents = false;
1236 mAtmService.notifyTaskPersisterLocked(this, false);
1237 }
1238
1239 clearRootProcess();
1240
1241 mAtmService.mWindowManager.mTaskSnapshotController.notifyTaskRemovedFromRecents(
1242 mTaskId, mUserId);
1243 }
1244
1245 void setTaskToAffiliateWith(Task taskToAffiliateWith) {
1246 closeRecentsChain();
1247 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
1248 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
1249 // Find the end
1250 while (taskToAffiliateWith.mNextAffiliate != null) {
1251 final Task nextRecents = taskToAffiliateWith.mNextAffiliate;
1252 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1253 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1254 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1255 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1256 nextRecents.setPrevAffiliate(null);
1257 }
1258 taskToAffiliateWith.setNextAffiliate(null);
1259 break;
1260 }
1261 taskToAffiliateWith = nextRecents;
1262 }
1263 taskToAffiliateWith.setNextAffiliate(this);
1264 setPrevAffiliate(taskToAffiliateWith);
1265 setNextAffiliate(null);
1266 }
1267
1268 /** Returns the intent for the root activity for this task */
1269 Intent getBaseIntent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001270 if (intent != null) return intent;
1271 if (affinityIntent != null) return affinityIntent;
1272 // Probably a task that contains other tasks, so return the intent for the top task?
1273 final Task topTask = getTopMostTask();
Evan Rosky0037e5f2019-11-05 10:26:24 -08001274 return (topTask != this && topTask != null) ? topTask.getBaseIntent() : null;
Louis Changcdec0802019-11-11 11:45:07 +08001275 }
1276
1277 /** Returns the first non-finishing activity from the bottom. */
1278 ActivityRecord getRootActivity() {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001279 // TODO: Figure out why we historical ignore relinquish identity for this case...
1280 return getRootActivity(true /*ignoreRelinquishIdentity*/, false /*setToBottomIfNone*/);
1281 }
1282
1283 ActivityRecord getRootActivity(boolean setToBottomIfNone) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001284 return getRootActivity(false /*ignoreRelinquishIdentity*/, setToBottomIfNone);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001285 }
1286
1287 ActivityRecord getRootActivity(boolean ignoreRelinquishIdentity, boolean setToBottomIfNone) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001288 return mFindRootHelper.findRoot(ignoreRelinquishIdentity, setToBottomIfNone);
Louis Changcdec0802019-11-11 11:45:07 +08001289 }
1290
Wale Ogunwale21e06482019-11-18 05:14:15 -08001291 ActivityRecord getTopNonFinishingActivity() {
1292 return getTopNonFinishingActivity(true /* includeOverlays */);
Louis Changcdec0802019-11-11 11:45:07 +08001293 }
1294
Wale Ogunwale21e06482019-11-18 05:14:15 -08001295 ActivityRecord getTopNonFinishingActivity(boolean includeOverlays) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001296 return getTopActivity(false /*includeFinishing*/, includeOverlays);
Louis Changcdec0802019-11-11 11:45:07 +08001297 }
1298
1299 ActivityRecord topRunningActivityLocked() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001300 if (getParent() == null) {
1301 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001302 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001303 return getActivity(ActivityRecord::canBeTopRunning);
Louis Changcdec0802019-11-11 11:45:07 +08001304 }
1305
1306 /**
1307 * Return true if any activities in this task belongs to input uid.
1308 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001309 boolean isUidPresent(int uid) {
1310 final PooledPredicate p = PooledLambda.obtainPredicate(
1311 ActivityRecord::isUid, PooledLambda.__(ActivityRecord.class), uid);
1312 final boolean isUidPresent = getActivity(p) != null;
1313 p.recycle();
1314 return isUidPresent;
Louis Changcdec0802019-11-11 11:45:07 +08001315 }
1316
Riddle Hsuffc12462020-05-27 17:43:25 +08001317 ActivityRecord topActivityWithStartingWindow() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001318 if (getParent() == null) {
1319 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001320 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001321 return getActivity((r) -> r.mStartingWindowState == STARTING_WINDOW_SHOWN
Riddle Hsuffc12462020-05-27 17:43:25 +08001322 && r.okToShowLocked());
Louis Changcdec0802019-11-11 11:45:07 +08001323 }
1324
1325 /**
1326 * Return the number of running activities, and the number of non-finishing/initializing
1327 * activities in the provided {@param reportOut} respectively.
1328 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001329 private void getNumRunningActivities(TaskActivitiesReport reportOut) {
Louis Changcdec0802019-11-11 11:45:07 +08001330 reportOut.reset();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001331 forAllActivities(reportOut);
Louis Changcdec0802019-11-11 11:45:07 +08001332 }
1333
1334 /**
1335 * Reorder the history stack so that the passed activity is brought to the front.
1336 */
1337 final void moveActivityToFrontLocked(ActivityRecord newTop) {
1338 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, "Removing and adding activity "
1339 + newTop + " to stack at top callers=" + Debug.getCallers(4));
1340
1341 positionChildAtTop(newTop);
1342 updateEffectiveIntent();
1343 }
1344
1345 @Override
1346 public int getActivityType() {
1347 final int applicationType = super.getActivityType();
1348 if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
1349 return applicationType;
1350 }
Louis Changa009c762020-02-26 11:21:31 +08001351 return getTopChild().getActivityType();
Louis Changcdec0802019-11-11 11:45:07 +08001352 }
1353
1354 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001355 void addChild(WindowContainer child, int index) {
Louis Changcdec0802019-11-11 11:45:07 +08001356 // If this task had any child before we added this one.
1357 boolean hadChild = hasChild();
Evan Rosky660b1752020-04-15 18:07:15 -07001358 // getActivityType() looks at the top child, so we need to read the type before adding
1359 // a new child in case the new child is on top and UNDEFINED.
1360 final int activityType = getActivityType();
Louis Changcdec0802019-11-11 11:45:07 +08001361
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001362 index = getAdjustedChildPosition(child, index);
1363 super.addChild(child, index);
Louis Changcdec0802019-11-11 11:45:07 +08001364
1365 ProtoLog.v(WM_DEBUG_ADD_REMOVE, "addChild: %s at top.", this);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001366
Louis Changa009c762020-02-26 11:21:31 +08001367 // A rootable task that is now being added to be the child of an organized task. Making
1368 // sure the stack references is keep updated.
1369 if (mTaskOrganizer != null && mCreatedByOrganizer && child.asTask() != null) {
Andrii Kulian86d676c2020-03-27 19:34:54 -07001370 getDisplayArea().addStackReferenceIfNeeded((ActivityStack) child);
Louis Changa009c762020-02-26 11:21:31 +08001371 }
1372
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001373 // Make sure the list of display UID whitelists is updated
1374 // now that this record is in a new task.
1375 mRootWindowContainer.updateUIDsPresentOnDisplay();
1376
1377 final ActivityRecord r = child.asActivityRecord();
1378 if (r == null) return;
1379
Louis Changcdec0802019-11-11 11:45:07 +08001380 r.inHistory = true;
1381
Louis Changcdec0802019-11-11 11:45:07 +08001382 // Only set this based on the first activity
1383 if (!hadChild) {
1384 if (r.getActivityType() == ACTIVITY_TYPE_UNDEFINED) {
1385 // Normally non-standard activity type for the activity record will be set when the
1386 // object is created, however we delay setting the standard application type until
1387 // this point so that the task can set the type for additional activities added in
1388 // the else condition below.
1389 r.setActivityType(ACTIVITY_TYPE_STANDARD);
1390 }
1391 setActivityType(r.getActivityType());
1392 isPersistable = r.isPersistable();
1393 mCallingUid = r.launchedFromUid;
1394 mCallingPackage = r.launchedFromPackage;
Philip P. Moltmannee295092020-02-10 08:46:26 -08001395 mCallingFeatureId = r.launchedFromFeatureId;
Louis Changcdec0802019-11-11 11:45:07 +08001396 // Clamp to [1, max].
1397 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1398 ActivityTaskManager.getMaxAppRecentsLimitStatic());
1399 } else {
1400 // Otherwise make all added activities match this one.
Evan Rosky660b1752020-04-15 18:07:15 -07001401 r.setActivityType(activityType);
Louis Changcdec0802019-11-11 11:45:07 +08001402 }
1403
1404 updateEffectiveIntent();
Louis Changcdec0802019-11-11 11:45:07 +08001405 }
1406
1407 void addChild(ActivityRecord r) {
1408 addChild(r, Integer.MAX_VALUE /* add on top */);
1409 }
1410
1411 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001412 void removeChild(WindowContainer child) {
1413 removeChild(child, "removeChild");
1414 }
1415
1416 void removeChild(WindowContainer r, String reason) {
Riddle Hsu9adc55f2020-04-28 17:07:33 +08001417 // A rootable child task that is now being removed from an organized task. Making sure
1418 // the stack references is keep updated.
1419 if (mTaskOrganizer != null && mCreatedByOrganizer && r.asTask() != null) {
1420 getDisplayArea().removeStackReferenceIfNeeded((ActivityStack) r);
1421 }
Louis Changcdec0802019-11-11 11:45:07 +08001422 if (!mChildren.contains(r)) {
1423 Slog.e(TAG, "removeChild: r=" + r + " not found in t=" + this);
1424 return;
1425 }
1426
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001427 if (DEBUG_TASK_MOVEMENT) {
1428 Slog.d(TAG_WM, "removeChild: child=" + r + " reason=" + reason);
1429 }
Louis Changcdec0802019-11-11 11:45:07 +08001430 super.removeChild(r);
Louis Changcdec0802019-11-11 11:45:07 +08001431
1432 if (inPinnedWindowingMode()) {
1433 // We normally notify listeners of task stack changes on pause, however pinned stack
1434 // activities are normally in the paused state so no notification will be sent there
1435 // before the activity is removed. We send it here so instead.
1436 mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
1437 }
1438
Louis Changcdec0802019-11-11 11:45:07 +08001439 if (hasChild()) {
1440 updateEffectiveIntent();
1441
1442 // The following block can be executed multiple times if there is more than one overlay.
1443 // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup
1444 // of the task by id and exiting early if not found.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001445 if (onlyHasTaskOverlayActivities(true /*includeFinishing*/)) {
Louis Changcdec0802019-11-11 11:45:07 +08001446 // When destroying a task, tell the supervisor to remove it so that any activity it
1447 // has can be cleaned up correctly. This is currently the only place where we remove
1448 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays
1449 // state into removeChild(), we just clear the task here before the other residual
1450 // work.
1451 // TODO: If the callers to removeChild() changes such that we have multiple places
1452 // where we are destroying the task, move this back into removeChild()
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001453 mStackSupervisor.removeTask(this, false /* killProcess */,
Louis Changcdec0802019-11-11 11:45:07 +08001454 !REMOVE_FROM_RECENTS, reason);
1455 }
Louis Changa009c762020-02-26 11:21:31 +08001456 } else if (!mReuseTask && !mCreatedByOrganizer) {
Louis Changcdec0802019-11-11 11:45:07 +08001457 // Remove entire task if it doesn't have any activity left and it isn't marked for reuse
Louis Changa009c762020-02-26 11:21:31 +08001458 // or created by task organizer.
Issei Suzuki4a46a922020-06-09 11:23:29 +02001459 if (!isRootTask()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001460 getStack().removeChild(this, reason);
1461 }
Jeff Changd136e772019-11-05 20:33:52 +08001462 EventLogTags.writeWmTaskRemoved(mTaskId,
Louis Changcdec0802019-11-11 11:45:07 +08001463 "removeChild: last r=" + r + " in t=" + this);
1464 removeIfPossible();
1465 }
1466 }
1467
1468 /**
Louis Changfd5539e2020-02-04 14:34:24 +08001469 * @return whether or not there are ONLY task overlay activities in the task.
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001470 * If {@param includeFinishing} is set, then don't ignore finishing activities in the
1471 * check. If there are no task overlay activities, this call returns false.
Louis Changcdec0802019-11-11 11:45:07 +08001472 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001473 boolean onlyHasTaskOverlayActivities(boolean includeFinishing) {
Louis Changfd5539e2020-02-04 14:34:24 +08001474 int count = 0;
1475 for (int i = getChildCount() - 1; i >= 0; i--) {
1476 final ActivityRecord r = getChildAt(i).asActivityRecord();
1477 if (r == null) {
1478 // Has a child that is other than Activity.
1479 return false;
1480 }
1481 if (!includeFinishing && r.finishing) {
1482 continue;
1483 }
1484 if (!r.isTaskOverlay()) {
1485 return false;
1486 }
1487 count++;
Louis Changcdec0802019-11-11 11:45:07 +08001488 }
Louis Changfd5539e2020-02-04 14:34:24 +08001489 return count > 0;
Louis Changcdec0802019-11-11 11:45:07 +08001490 }
1491
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001492 private boolean autoRemoveFromRecents() {
Louis Changcdec0802019-11-11 11:45:07 +08001493 // We will automatically remove the task either if it has explicitly asked for
1494 // this, or it is empty and has never contained an activity that got shown to
1495 // the user.
Robert Carrde96c8a2020-03-24 15:22:21 -07001496 return autoRemoveRecents || (!hasChild() && !getHasBeenVisible());
Louis Changcdec0802019-11-11 11:45:07 +08001497 }
1498
1499 /**
1500 * Completely remove all activities associated with an existing
1501 * task starting at a specified index.
1502 */
Wale Ogunwale21e06482019-11-18 05:14:15 -08001503 private void performClearTaskAtIndexLocked(String reason) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001504 // Broken down into to cases to avoid object create due to capturing mStack.
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001505 if (getStack() == null) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001506 forAllActivities((r) -> {
1507 if (r.finishing) return;
Louis Changcdec0802019-11-11 11:45:07 +08001508 // Task was restored from persistent storage.
1509 r.takeFromHistory();
1510 removeChild(r);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001511 });
1512 } else {
1513 forAllActivities((r) -> {
1514 if (r.finishing) return;
1515 // TODO: figure-out how to avoid object creation due to capture of reason variable.
Jeff Sharkey307ea7a2020-04-13 10:24:49 -06001516 r.finishIfPossible(Activity.RESULT_CANCELED,
1517 null /* resultData */, null /* resultGrants */, reason, false /* oomAdj */);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001518 });
Louis Changcdec0802019-11-11 11:45:07 +08001519 }
1520 }
1521
1522 /**
1523 * Completely remove all activities associated with an existing task.
1524 */
1525 void performClearTaskLocked() {
1526 mReuseTask = true;
Wale Ogunwale21e06482019-11-18 05:14:15 -08001527 performClearTaskAtIndexLocked("clear-task-all");
Louis Changcdec0802019-11-11 11:45:07 +08001528 mReuseTask = false;
1529 }
1530
1531 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1532 mReuseTask = true;
1533 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1534 mReuseTask = false;
1535 return result;
1536 }
1537
1538 /**
1539 * Perform clear operation as requested by
1540 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1541 * stack to the given task, then look for
1542 * an instance of that activity in the stack and, if found, finish all
1543 * activities on top of it and return the instance.
1544 *
1545 * @param newR Description of the new activity being started.
1546 * @return Returns the old activity that should be continued to be used,
1547 * or {@code null} if none was found.
1548 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001549 private ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
1550 final ActivityRecord r = findActivityInHistory(newR.mActivityComponent);
1551 if (r == null) return null;
Louis Changcdec0802019-11-11 11:45:07 +08001552
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001553 final PooledFunction f = PooledLambda.obtainFunction(Task::finishActivityAbove,
1554 PooledLambda.__(ActivityRecord.class), r);
1555 forAllActivities(f);
1556 f.recycle();
Louis Changcdec0802019-11-11 11:45:07 +08001557
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001558 // Finally, if this is a normal launch mode (that is, not expecting onNewIntent()), then we
1559 // will finish the current instance of the activity so a new fresh one can be started.
1560 if (r.launchMode == ActivityInfo.LAUNCH_MULTIPLE
1561 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1562 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
1563 if (!r.finishing) {
1564 r.finishIfPossible("clear-task-top", false /* oomAdj */);
1565 return null;
Louis Changcdec0802019-11-11 11:45:07 +08001566 }
1567 }
1568
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001569 return r;
1570 }
1571
1572 private static boolean finishActivityAbove(ActivityRecord r, ActivityRecord boundaryActivity) {
1573 // Stop operation once we reach the boundary activity.
1574 if (r == boundaryActivity) return true;
1575
1576 if (!r.finishing) {
1577 final ActivityOptions opts = r.takeOptionsLocked(false /* fromClient */);
1578 if (opts != null) {
1579 // TODO: Why is this updating the boundary activity vs. the current activity???
1580 boundaryActivity.updateOptionsLocked(opts);
1581 }
1582 r.finishIfPossible("clear-task-stack", false /* oomAdj */);
1583 }
1584
1585 return false;
Louis Changcdec0802019-11-11 11:45:07 +08001586 }
1587
1588 void removeTaskActivitiesLocked(String reason) {
1589 // Just remove the entire task.
Wale Ogunwale21e06482019-11-18 05:14:15 -08001590 performClearTaskAtIndexLocked(reason);
Louis Changcdec0802019-11-11 11:45:07 +08001591 }
1592
1593 String lockTaskAuthToString() {
1594 switch (mLockTaskAuth) {
1595 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1596 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1597 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1598 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
1599 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
1600 default: return "unknown=" + mLockTaskAuth;
1601 }
1602 }
1603
1604 void setLockTaskAuth() {
1605 setLockTaskAuth(getRootActivity());
1606 }
1607
1608 private void setLockTaskAuth(@Nullable ActivityRecord r) {
1609 if (r == null) {
1610 mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
1611 return;
1612 }
1613
1614 final String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
1615 final LockTaskController lockTaskController = mAtmService.getLockTaskController();
1616 switch (r.lockTaskLaunchMode) {
1617 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
1618 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
1619 ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
1620 break;
1621
1622 case LOCK_TASK_LAUNCH_MODE_NEVER:
1623 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
1624 break;
1625
1626 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
1627 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
1628 break;
1629
1630 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
1631 mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
1632 ? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
1633 break;
1634 }
1635 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this
1636 + " mLockTaskAuth=" + lockTaskAuthToString());
1637 }
1638
1639 @Override
1640 public boolean supportsSplitScreenWindowingMode() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001641 final Task topTask = getTopMostTask();
1642 return super.supportsSplitScreenWindowingMode()
1643 && (topTask == null || topTask.supportsSplitScreenWindowingModeInner());
1644 }
1645
1646 private boolean supportsSplitScreenWindowingModeInner() {
Louis Changcdec0802019-11-11 11:45:07 +08001647 // A task can not be docked even if it is considered resizeable because it only supports
1648 // picture-in-picture mode but has a non-resizeable resizeMode
1649 return super.supportsSplitScreenWindowingMode()
Louis Changcdec0802019-11-11 11:45:07 +08001650 && mAtmService.mSupportsSplitScreenMultiWindow
1651 && (mAtmService.mForceResizableActivities
1652 || (isResizeable(false /* checkSupportsPip */)
1653 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
1654 }
1655
1656 /**
1657 * Check whether this task can be launched on the specified display.
1658 *
1659 * @param displayId Target display id.
1660 * @return {@code true} if either it is the default display or this activity can be put on a
1661 * secondary display.
1662 */
1663 boolean canBeLaunchedOnDisplay(int displayId) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001664 return mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Louis Changcdec0802019-11-11 11:45:07 +08001665 -1 /* don't check PID */, -1 /* don't check UID */, null /* activityInfo */);
1666 }
1667
1668 /**
1669 * Check that a given bounds matches the application requested orientation.
1670 *
1671 * @param bounds The bounds to be tested.
1672 * @return True if the requested bounds are okay for a resizing request.
1673 */
1674 private boolean canResizeToBounds(Rect bounds) {
1675 if (bounds == null || !inFreeformWindowingMode()) {
1676 // Note: If not on the freeform workspace, we ignore the bounds.
1677 return true;
1678 }
1679 final boolean landscape = bounds.width() > bounds.height();
1680 final Rect configBounds = getRequestedOverrideBounds();
1681 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
1682 return configBounds.isEmpty()
1683 || landscape == (configBounds.width() > configBounds.height());
1684 }
1685 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1686 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1687 }
1688
1689 /**
1690 * @return {@code true} if the task is being cleared for the purposes of being reused.
1691 */
1692 boolean isClearingToReuseTask() {
1693 return mReuseTask;
1694 }
1695
1696 /**
1697 * Find the activity in the history stack within the given task. Returns
1698 * the index within the history at which it's found, or < 0 if not found.
1699 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001700 ActivityRecord findActivityInHistory(ComponentName component) {
1701 final PooledPredicate p = PooledLambda.obtainPredicate(Task::matchesActivityInHistory,
1702 PooledLambda.__(ActivityRecord.class), component);
1703 final ActivityRecord r = getActivity(p);
1704 p.recycle();
1705 return r;
1706 }
1707
1708 private static boolean matchesActivityInHistory(
1709 ActivityRecord r, ComponentName activityComponent) {
1710 return !r.finishing && r.mActivityComponent.equals(activityComponent);
Louis Changcdec0802019-11-11 11:45:07 +08001711 }
1712
1713 /** Updates the last task description values. */
1714 void updateTaskDescription() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001715 final ActivityRecord root = getRootActivity(true);
1716 if (root == null) return;
1717
1718 final TaskDescription taskDescription = new TaskDescription();
1719 final PooledFunction f = PooledLambda.obtainFunction(
1720 Task::setTaskDescriptionFromActivityAboveRoot,
1721 PooledLambda.__(ActivityRecord.class), root, taskDescription);
1722 forAllActivities(f);
1723 f.recycle();
1724 taskDescription.setResizeMode(mResizeMode);
1725 taskDescription.setMinWidth(mMinWidth);
1726 taskDescription.setMinHeight(mMinHeight);
1727 setTaskDescription(taskDescription);
1728 // Update the task affiliation color if we are the parent of the group
1729 if (mTaskId == mAffiliatedTaskId) {
1730 mAffiliatedTaskColor = taskDescription.getPrimaryColor();
Louis Changcdec0802019-11-11 11:45:07 +08001731 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001732 mAtmService.getTaskChangeNotificationController().notifyTaskDescriptionChanged(
1733 getTaskInfo());
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001734
1735 final WindowContainer parent = getParent();
1736 if (parent != null) {
1737 final Task t = parent.asTask();
1738 if (t != null) {
1739 t.updateTaskDescription();
1740 }
1741 }
Winson Chung1df39e22020-04-09 14:30:55 -07001742
1743 if (isOrganized()) {
Evan Rosky0c86ced2020-05-20 13:38:34 -07001744 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, false /* force */);
Winson Chung1df39e22020-04-09 14:30:55 -07001745 }
Louis Changcdec0802019-11-11 11:45:07 +08001746 }
1747
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001748 private static boolean setTaskDescriptionFromActivityAboveRoot(
1749 ActivityRecord r, ActivityRecord root, TaskDescription td) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001750 if (!r.isTaskOverlay() && r.taskDescription != null) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001751 final TaskDescription atd = r.taskDescription;
1752 if (td.getLabel() == null) {
1753 td.setLabel(atd.getLabel());
Louis Changcdec0802019-11-11 11:45:07 +08001754 }
Winson Chungd6722032020-02-18 15:16:08 -08001755 if (td.getRawIcon() == null) {
1756 td.setIcon(atd.getRawIcon());
Louis Changcdec0802019-11-11 11:45:07 +08001757 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001758 if (td.getIconFilename() == null) {
1759 td.setIconFilename(atd.getIconFilename());
1760 }
1761 if (td.getPrimaryColor() == 0) {
1762 td.setPrimaryColor(atd.getPrimaryColor());
1763 }
1764 if (td.getBackgroundColor() == 0) {
1765 td.setBackgroundColor(atd.getBackgroundColor());
1766 }
1767 if (td.getStatusBarColor() == 0) {
1768 td.setStatusBarColor(atd.getStatusBarColor());
1769 td.setEnsureStatusBarContrastWhenTransparent(
1770 atd.getEnsureStatusBarContrastWhenTransparent());
1771 }
1772 if (td.getNavigationBarColor() == 0) {
1773 td.setNavigationBarColor(atd.getNavigationBarColor());
1774 td.setEnsureNavigationBarContrastWhenTransparent(
1775 atd.getEnsureNavigationBarContrastWhenTransparent());
1776 }
1777
Louis Changcdec0802019-11-11 11:45:07 +08001778 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001779
1780 // End search once we get to root.
1781 return r == root;
Louis Changcdec0802019-11-11 11:45:07 +08001782 }
1783
1784 // TODO (AM refactor): Invoke automatically when there is a change in children
1785 @VisibleForTesting
1786 void updateEffectiveIntent() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001787 final ActivityRecord root = getRootActivity(true /*setToBottomIfNone*/);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001788 if (root != null) {
1789 setIntent(root);
1790 // Update the task description when the activities change
1791 updateTaskDescription();
1792 }
Louis Changcdec0802019-11-11 11:45:07 +08001793 }
1794
Riddle Hsudd49c632020-04-30 22:39:51 +08001795 void adjustForMinimalTaskDimensions(@NonNull Rect bounds, @NonNull Rect previousBounds,
1796 @NonNull Configuration parentConfig) {
Louis Changcdec0802019-11-11 11:45:07 +08001797 int minWidth = mMinWidth;
1798 int minHeight = mMinHeight;
1799 // If the task has no requested minimal size, we'd like to enforce a minimal size
1800 // so that the user can not render the task too small to manipulate. We don't need
1801 // to do this for the pinned stack as the bounds are controlled by the system.
Riddle Hsudd49c632020-04-30 22:39:51 +08001802 if (!inPinnedWindowingMode()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001803 final int defaultMinSizeDp = mRootWindowContainer.mDefaultMinSizeOfResizeableTaskDp;
Riddle Hsudd49c632020-04-30 22:39:51 +08001804 final float density = (float) parentConfig.densityDpi / DisplayMetrics.DENSITY_DEFAULT;
Louis Changcdec0802019-11-11 11:45:07 +08001805 final int defaultMinSize = (int) (defaultMinSizeDp * density);
1806
1807 if (minWidth == INVALID_MIN_SIZE) {
1808 minWidth = defaultMinSize;
1809 }
1810 if (minHeight == INVALID_MIN_SIZE) {
1811 minHeight = defaultMinSize;
1812 }
1813 }
Evan Rosky70213702019-11-05 10:26:24 -08001814 if (bounds.isEmpty()) {
1815 // If inheriting parent bounds, check if parent bounds adhere to minimum size. If they
1816 // do, we can just skip.
Riddle Hsudd49c632020-04-30 22:39:51 +08001817 final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
Evan Rosky70213702019-11-05 10:26:24 -08001818 if (parentBounds.width() >= minWidth && parentBounds.height() >= minHeight) {
1819 return;
1820 }
1821 bounds.set(parentBounds);
1822 }
Louis Changcdec0802019-11-11 11:45:07 +08001823 final boolean adjustWidth = minWidth > bounds.width();
1824 final boolean adjustHeight = minHeight > bounds.height();
1825 if (!(adjustWidth || adjustHeight)) {
1826 return;
1827 }
1828
1829 if (adjustWidth) {
1830 if (!previousBounds.isEmpty() && bounds.right == previousBounds.right) {
1831 bounds.left = bounds.right - minWidth;
1832 } else {
1833 // Either left bounds match, or neither match, or the previous bounds were
1834 // fullscreen and we default to keeping left.
1835 bounds.right = bounds.left + minWidth;
1836 }
1837 }
1838 if (adjustHeight) {
1839 if (!previousBounds.isEmpty() && bounds.bottom == previousBounds.bottom) {
1840 bounds.top = bounds.bottom - minHeight;
1841 } else {
1842 // Either top bounds match, or neither match, or the previous bounds were
1843 // fullscreen and we default to keeping top.
1844 bounds.bottom = bounds.top + minHeight;
1845 }
1846 }
1847 }
1848
1849 void setLastNonFullscreenBounds(Rect bounds) {
1850 if (mLastNonFullscreenBounds == null) {
1851 mLastNonFullscreenBounds = new Rect(bounds);
1852 } else {
1853 mLastNonFullscreenBounds.set(bounds);
1854 }
1855 }
1856
1857 /**
1858 * This should be called when an child activity changes state. This should only
1859 * be called from
1860 * {@link ActivityRecord#setState(ActivityState, String)} .
1861 * @param record The {@link ActivityRecord} whose state has changed.
1862 * @param state The new state.
1863 * @param reason The reason for the change.
1864 */
1865 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001866 final Task parentTask = getParent().asTask();
1867 if (parentTask != null) {
1868 parentTask.onActivityStateChanged(record, state, reason);
Louis Changa009c762020-02-26 11:21:31 +08001869 // We still want to update the resumed activity if the parent task is created by
1870 // organizer in order to keep the information synced once got reparented out from the
1871 // organized task.
1872 if (!parentTask.mCreatedByOrganizer) {
1873 return;
1874 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001875 }
Louis Changcdec0802019-11-11 11:45:07 +08001876
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001877 if (record == mResumedActivity && state != RESUMED) {
1878 setResumedActivity(null, reason + " - onActivityStateChanged");
1879 }
1880
1881 if (state == RESUMED) {
1882 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
1883 Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" + reason);
1884 }
1885 setResumedActivity(record, reason + " - onActivityStateChanged");
1886 if (record == mRootWindowContainer.getTopResumedActivity()) {
1887 mAtmService.setResumedActivityUncheckLocked(record, reason);
1888 }
1889 mStackSupervisor.mRecentTasks.add(record.getTask());
Louis Changcdec0802019-11-11 11:45:07 +08001890 }
1891 }
1892
1893 @Override
1894 public void onConfigurationChanged(Configuration newParentConfig) {
1895 // Check if the new configuration supports persistent bounds (eg. is Freeform) and if so
1896 // restore the last recorded non-fullscreen bounds.
1897 final boolean prevPersistTaskBounds = getWindowConfiguration().persistTaskBounds();
Ben Lin50038ee2020-04-24 17:09:12 -07001898 boolean nextPersistTaskBounds =
1899 getRequestedOverrideConfiguration().windowConfiguration.persistTaskBounds();
1900 if (getRequestedOverrideWindowingMode() == WINDOWING_MODE_UNDEFINED) {
1901 nextPersistTaskBounds = newParentConfig.windowConfiguration.persistTaskBounds();
1902 }
Louis Changcdec0802019-11-11 11:45:07 +08001903 if (!prevPersistTaskBounds && nextPersistTaskBounds
1904 && mLastNonFullscreenBounds != null && !mLastNonFullscreenBounds.isEmpty()) {
1905 // Bypass onRequestedOverrideConfigurationChanged here to avoid infinite loop.
1906 getRequestedOverrideConfiguration().windowConfiguration
1907 .setBounds(mLastNonFullscreenBounds);
1908 }
1909
Evan Rosky55bddd82020-01-29 13:07:18 -08001910 final int prevWinMode = getWindowingMode();
1911 mTmpPrevBounds.set(getBounds());
Louis Changcdec0802019-11-11 11:45:07 +08001912 final boolean wasInMultiWindowMode = inMultiWindowMode();
Hongwei Wang5c52ff82020-04-20 16:02:30 -07001913 final boolean wasInPictureInPicture = inPinnedWindowingMode();
Louis Changcdec0802019-11-11 11:45:07 +08001914 super.onConfigurationChanged(newParentConfig);
Louis Chang2570e332020-04-10 11:58:49 +08001915 // Only need to update surface size here since the super method will handle updating
1916 // surface position.
chaviw89cc30e2020-05-19 10:36:27 -07001917 updateSurfaceSize(getSyncTransaction());
Louis Chang2570e332020-04-10 11:58:49 +08001918
Hongwei Wang5c52ff82020-04-20 16:02:30 -07001919 if (wasInPictureInPicture != inPinnedWindowingMode()) {
1920 mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, getStack());
1921 } else if (wasInMultiWindowMode != inMultiWindowMode()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08001922 mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Louis Changcdec0802019-11-11 11:45:07 +08001923 }
1924
Evan Rosky55bddd82020-01-29 13:07:18 -08001925 final int newWinMode = getWindowingMode();
1926 if ((prevWinMode != newWinMode) && (mDisplayContent != null)
1927 && shouldStartChangeTransition(prevWinMode, newWinMode)) {
1928 initializeChangeTransition(mTmpPrevBounds);
1929 }
1930
Louis Changcdec0802019-11-11 11:45:07 +08001931 // If the configuration supports persistent bounds (eg. Freeform), keep track of the
1932 // current (non-fullscreen) bounds for persistence.
1933 if (getWindowConfiguration().persistTaskBounds()) {
1934 final Rect currentBounds = getRequestedOverrideBounds();
1935 if (!currentBounds.isEmpty()) {
1936 setLastNonFullscreenBounds(currentBounds);
1937 }
1938 }
Louis Changcdec0802019-11-11 11:45:07 +08001939
1940 saveLaunchingStateIfNeeded();
Evan Roskyf64f5da2020-03-16 13:47:48 -07001941 final boolean taskOrgChanged = updateTaskOrganizerState(false /* forceUpdate */);
1942 // If the task organizer has changed, then it will already be receiving taskAppeared with
1943 // the latest task-info thus the task-info won't have changed.
Winson Chung1df39e22020-04-09 14:30:55 -07001944 if (!taskOrgChanged && isOrganized()) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07001945 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, false /* force */);
1946 }
Louis Changcdec0802019-11-11 11:45:07 +08001947 }
1948
1949 /**
Evan Rosky55bddd82020-01-29 13:07:18 -08001950 * Initializes a change transition. See {@link SurfaceFreezer} for more information.
1951 */
1952 private void initializeChangeTransition(Rect startBounds) {
1953 mDisplayContent.prepareAppTransition(TRANSIT_TASK_CHANGE_WINDOWING_MODE,
1954 false /* alwaysKeepCurrent */, 0, false /* forceOverride */);
1955 mDisplayContent.mChangingContainers.add(this);
1956
1957 mSurfaceFreezer.freeze(getPendingTransaction(), startBounds);
1958 }
1959
1960 private boolean shouldStartChangeTransition(int prevWinMode, int newWinMode) {
1961 if (mWmService.mDisableTransitionAnimation
1962 || !isVisible()
1963 || getDisplayContent().mAppTransition.isTransitionSet()
Evan Rosky8d4ee722020-04-21 17:28:31 -07001964 || getSurfaceControl() == null
1965 || !isLeafTask()) {
Evan Rosky55bddd82020-01-29 13:07:18 -08001966 return false;
1967 }
1968 // Only do an animation into and out-of freeform mode for now. Other mode
1969 // transition animations are currently handled by system-ui.
1970 return (prevWinMode == WINDOWING_MODE_FREEFORM) != (newWinMode == WINDOWING_MODE_FREEFORM);
1971 }
1972
chaviwda7b3c22020-04-24 11:25:08 -07001973 @Override
1974 void migrateToNewSurfaceControl() {
1975 super.migrateToNewSurfaceControl();
1976 mLastSurfaceSize.x = 0;
1977 mLastSurfaceSize.y = 0;
1978 updateSurfaceSize(getPendingTransaction());
1979 }
1980
Louis Chang2570e332020-04-10 11:58:49 +08001981 void updateSurfaceSize(SurfaceControl.Transaction transaction) {
Robert Carr1530eee2020-05-05 15:15:01 -07001982 if (mSurfaceControl == null || isOrganized()) {
Louis Chang2570e332020-04-10 11:58:49 +08001983 return;
1984 }
1985
1986 // Apply crop to root tasks only and clear the crops of the descendant tasks.
1987 int width = 0;
1988 int height = 0;
1989 if (isRootTask()) {
1990 final Rect taskBounds = getBounds();
1991 width = taskBounds.width();
1992 height = taskBounds.height();
1993
1994 final int outset = getTaskOutset();
1995 width += 2 * outset;
1996 height += 2 * outset;
1997 }
1998 if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
1999 return;
2000 }
2001 transaction.setWindowCrop(mSurfaceControl, width, height);
2002 mLastSurfaceSize.set(width, height);
2003 }
2004
2005 /**
2006 * Calculate an amount by which to expand the task bounds in each direction.
2007 * Used to make room for shadows in the pinned windowing mode.
2008 */
2009 int getTaskOutset() {
2010 // If we are drawing shadows on the task then don't outset the stack.
2011 if (mWmService.mRenderShadowsInCompositor) {
2012 return 0;
2013 }
2014 DisplayContent displayContent = getDisplayContent();
2015 if (inPinnedWindowingMode() && displayContent != null) {
2016 final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
2017
2018 // We multiply by two to match the client logic for converting view elevation
2019 // to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets}
2020 return (int) Math.ceil(
2021 mWmService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP, displayMetrics)
2022 * 2);
2023 }
2024 return 0;
2025 }
2026
2027 @VisibleForTesting
2028 Point getLastSurfaceSize() {
2029 return mLastSurfaceSize;
2030 }
2031
Evan Rosky55bddd82020-01-29 13:07:18 -08002032 @VisibleForTesting
2033 boolean isInChangeTransition() {
2034 return mSurfaceFreezer.hasLeash() || AppTransition.isChangeTransit(mTransit);
2035 }
2036
2037 @Override
2038 public SurfaceControl getFreezeSnapshotTarget() {
2039 final int transit = mDisplayContent.mAppTransition.getAppTransition();
2040 if (!AppTransition.isChangeTransit(transit)) {
2041 return null;
2042 }
2043 // Skip creating snapshot if this transition is controlled by a remote animator which
2044 // doesn't need it.
2045 final ArraySet<Integer> activityTypes = new ArraySet<>();
2046 activityTypes.add(getActivityType());
2047 final RemoteAnimationAdapter adapter =
2048 mDisplayContent.mAppTransitionController.getRemoteAnimationOverride(
2049 this, transit, activityTypes);
2050 if (adapter != null && !adapter.getChangeNeedsSnapshot()) {
2051 return null;
2052 }
2053 return getSurfaceControl();
2054 }
2055
2056 @Override
2057 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
2058 final long token = proto.start(fieldId);
2059 proto.write(HASH_CODE, System.identityHashCode(this));
2060 proto.write(USER_ID, mUserId);
2061 proto.write(TITLE, intent != null && intent.getComponent() != null
2062 ? intent.getComponent().flattenToShortString() : "Task");
2063 proto.end(token);
2064 }
2065
2066 /**
Louis Changcdec0802019-11-11 11:45:07 +08002067 * Saves launching state if necessary so that we can launch the activity to its latest state.
2068 * It only saves state if this task has been shown to user and it's in fullscreen or freeform
2069 * mode on freeform displays.
2070 */
Garfield Tan8b096b22020-01-07 14:55:20 -08002071 private void saveLaunchingStateIfNeeded() {
2072 saveLaunchingStateIfNeeded(getDisplayContent());
2073 }
2074
2075 private void saveLaunchingStateIfNeeded(DisplayContent display) {
Robert Carrde96c8a2020-03-24 15:22:21 -07002076 if (!getHasBeenVisible()) {
Louis Changcdec0802019-11-11 11:45:07 +08002077 // Not ever visible to user.
2078 return;
2079 }
2080
2081 final int windowingMode = getWindowingMode();
2082 if (windowingMode != WINDOWING_MODE_FULLSCREEN
2083 && windowingMode != WINDOWING_MODE_FREEFORM) {
2084 return;
2085 }
2086
2087 // Don't persist state if display isn't in freeform mode. Then the task will be launched
2088 // back to its last state in a freeform display when it's launched in a freeform display
2089 // next time.
2090 if (getWindowConfiguration().getDisplayWindowingMode() != WINDOWING_MODE_FREEFORM) {
2091 return;
2092 }
2093
2094 // Saves the new state so that we can launch the activity at the same location.
Garfield Tan8b096b22020-01-07 14:55:20 -08002095 mStackSupervisor.mLaunchParamsPersister.saveTask(this, display);
Louis Changcdec0802019-11-11 11:45:07 +08002096 }
2097
2098 /**
2099 * Adjust bounds to stay within stack bounds.
2100 *
2101 * Since bounds might be outside of stack bounds, this method tries to move the bounds in a way
2102 * that keep them unchanged, but be contained within the stack bounds.
2103 *
2104 * @param bounds Bounds to be adjusted.
2105 * @param stackBounds Bounds within which the other bounds should remain.
2106 * @param overlapPxX The amount of px required to be visible in the X dimension.
2107 * @param overlapPxY The amount of px required to be visible in the Y dimension.
2108 */
2109 private static void fitWithinBounds(Rect bounds, Rect stackBounds, int overlapPxX,
2110 int overlapPxY) {
2111 if (stackBounds == null || stackBounds.isEmpty() || stackBounds.contains(bounds)) {
2112 return;
2113 }
2114
2115 // For each side of the parent (eg. left), check if the opposing side of the window (eg.
2116 // right) is at least overlap pixels away. If less, offset the window by that difference.
2117 int horizontalDiff = 0;
2118 // If window is smaller than overlap, use it's smallest dimension instead
2119 int overlapLR = Math.min(overlapPxX, bounds.width());
2120 if (bounds.right < (stackBounds.left + overlapLR)) {
2121 horizontalDiff = overlapLR - (bounds.right - stackBounds.left);
2122 } else if (bounds.left > (stackBounds.right - overlapLR)) {
2123 horizontalDiff = -(overlapLR - (stackBounds.right - bounds.left));
2124 }
2125 int verticalDiff = 0;
2126 int overlapTB = Math.min(overlapPxY, bounds.width());
2127 if (bounds.bottom < (stackBounds.top + overlapTB)) {
2128 verticalDiff = overlapTB - (bounds.bottom - stackBounds.top);
2129 } else if (bounds.top > (stackBounds.bottom - overlapTB)) {
2130 verticalDiff = -(overlapTB - (stackBounds.bottom - bounds.top));
2131 }
2132 bounds.offset(horizontalDiff, verticalDiff);
2133 }
2134
2135 /**
2136 * Intersects inOutBounds with intersectBounds-intersectInsets. If inOutBounds is larger than
2137 * intersectBounds on a side, then the respective side will not be intersected.
2138 *
2139 * The assumption is that if inOutBounds is initially larger than intersectBounds, then the
2140 * inset on that side is no-longer applicable. This scenario happens when a task's minimal
2141 * bounds are larger than the provided parent/display bounds.
2142 *
2143 * @param inOutBounds the bounds to intersect.
2144 * @param intersectBounds the bounds to intersect with.
2145 * @param intersectInsets insets to apply to intersectBounds before intersecting.
2146 */
2147 static void intersectWithInsetsIfFits(
2148 Rect inOutBounds, Rect intersectBounds, Rect intersectInsets) {
2149 if (inOutBounds.right <= intersectBounds.right) {
2150 inOutBounds.right =
2151 Math.min(intersectBounds.right - intersectInsets.right, inOutBounds.right);
2152 }
2153 if (inOutBounds.bottom <= intersectBounds.bottom) {
2154 inOutBounds.bottom =
2155 Math.min(intersectBounds.bottom - intersectInsets.bottom, inOutBounds.bottom);
2156 }
2157 if (inOutBounds.left >= intersectBounds.left) {
2158 inOutBounds.left =
2159 Math.max(intersectBounds.left + intersectInsets.left, inOutBounds.left);
2160 }
2161 if (inOutBounds.top >= intersectBounds.top) {
2162 inOutBounds.top =
2163 Math.max(intersectBounds.top + intersectInsets.top, inOutBounds.top);
2164 }
2165 }
2166
2167 /**
2168 * Gets bounds with non-decor and stable insets applied respectively.
2169 *
2170 * If bounds overhangs the display, those edges will not get insets. See
2171 * {@link #intersectWithInsetsIfFits}
2172 *
2173 * @param outNonDecorBounds where to place bounds with non-decor insets applied.
2174 * @param outStableBounds where to place bounds with stable insets applied.
2175 * @param bounds the bounds to inset.
2176 */
2177 private void calculateInsetFrames(Rect outNonDecorBounds, Rect outStableBounds, Rect bounds,
2178 DisplayInfo displayInfo) {
2179 outNonDecorBounds.set(bounds);
2180 outStableBounds.set(bounds);
2181 if (getStack() == null || getStack().getDisplay() == null) {
2182 return;
2183 }
2184 DisplayPolicy policy = getStack().getDisplay().mDisplayContent.getDisplayPolicy();
2185 if (policy == null) {
2186 return;
2187 }
2188 mTmpBounds.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
2189
2190 policy.getNonDecorInsetsLw(displayInfo.rotation, displayInfo.logicalWidth,
2191 displayInfo.logicalHeight, displayInfo.displayCutout, mTmpInsets);
2192 intersectWithInsetsIfFits(outNonDecorBounds, mTmpBounds, mTmpInsets);
2193
2194 policy.convertNonDecorInsetsToStableInsets(mTmpInsets, displayInfo.rotation);
2195 intersectWithInsetsIfFits(outStableBounds, mTmpBounds, mTmpInsets);
2196 }
2197
Riddle Hsu23e18a92020-03-10 00:26:51 +08002198 /**
2199 * Forces the app bounds related configuration can be computed by
2200 * {@link #computeConfigResourceOverrides(Configuration, Configuration, DisplayInfo,
2201 * ActivityRecord.CompatDisplayInsets)}.
2202 */
2203 private static void invalidateAppBoundsConfig(@NonNull Configuration inOutConfig) {
2204 final Rect appBounds = inOutConfig.windowConfiguration.getAppBounds();
2205 if (appBounds != null) {
2206 appBounds.setEmpty();
2207 }
2208 inOutConfig.screenWidthDp = Configuration.SCREEN_WIDTH_DP_UNDEFINED;
2209 inOutConfig.screenHeightDp = Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
2210 }
2211
Louis Changcdec0802019-11-11 11:45:07 +08002212 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Riddle Hsu9264a272020-03-04 23:10:41 +08002213 @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo) {
2214 if (overrideDisplayInfo != null) {
2215 // Make sure the screen related configs can be computed by the provided display info.
Riddle Hsu9264a272020-03-04 23:10:41 +08002216 inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED;
Riddle Hsu23e18a92020-03-10 00:26:51 +08002217 invalidateAppBoundsConfig(inOutConfig);
Riddle Hsu9264a272020-03-04 23:10:41 +08002218 }
2219 computeConfigResourceOverrides(inOutConfig, parentConfig, overrideDisplayInfo,
2220 null /* compatInsets */);
2221 }
2222
2223 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Louis Changcdec0802019-11-11 11:45:07 +08002224 @NonNull Configuration parentConfig) {
Riddle Hsu9264a272020-03-04 23:10:41 +08002225 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
2226 null /* compatInsets */);
2227 }
2228
2229 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
2230 @NonNull Configuration parentConfig,
2231 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
Riddle Hsu23e18a92020-03-10 00:26:51 +08002232 if (compatInsets != null) {
2233 // Make sure the app bounds can be computed by the compat insets.
2234 invalidateAppBoundsConfig(inOutConfig);
2235 }
Riddle Hsu9264a272020-03-04 23:10:41 +08002236 computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */,
2237 compatInsets);
Louis Changcdec0802019-11-11 11:45:07 +08002238 }
2239
2240 /**
2241 * Calculates configuration values used by the client to get resources. This should be run
2242 * using app-facing bounds (bounds unmodified by animations or transient interactions).
2243 *
2244 * This assumes bounds are non-empty/null. For the null-bounds case, the caller is likely
2245 * configuring an "inherit-bounds" window which means that all configuration settings would
2246 * just be inherited from the parent configuration.
2247 **/
2248 void computeConfigResourceOverrides(@NonNull Configuration inOutConfig,
Riddle Hsu9264a272020-03-04 23:10:41 +08002249 @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo,
Louis Changcdec0802019-11-11 11:45:07 +08002250 @Nullable ActivityRecord.CompatDisplayInsets compatInsets) {
2251 int windowingMode = inOutConfig.windowConfiguration.getWindowingMode();
2252 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2253 windowingMode = parentConfig.windowConfiguration.getWindowingMode();
2254 }
2255
2256 float density = inOutConfig.densityDpi;
2257 if (density == Configuration.DENSITY_DPI_UNDEFINED) {
2258 density = parentConfig.densityDpi;
2259 }
2260 density *= DisplayMetrics.DENSITY_DEFAULT_SCALE;
2261
Riddle Hsu1f931a592020-04-22 21:15:38 +08002262 // The bounds may have been overridden at this level. If the parent cannot cover these
2263 // bounds, the configuration is still computed according to the override bounds.
2264 final boolean insideParentBounds;
Evan Roskyc440b4e2020-04-17 15:11:22 -07002265
Riddle Hsu1f931a592020-04-22 21:15:38 +08002266 final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
Evan Rosky70213702019-11-05 10:26:24 -08002267 final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds();
Evan Roskyc440b4e2020-04-17 15:11:22 -07002268 if (resolvedBounds == null || resolvedBounds.isEmpty()) {
Riddle Hsu1f931a592020-04-22 21:15:38 +08002269 mTmpFullBounds.set(parentBounds);
2270 insideParentBounds = true;
Evan Rosky70213702019-11-05 10:26:24 -08002271 } else {
2272 mTmpFullBounds.set(resolvedBounds);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002273 insideParentBounds = parentBounds.contains(resolvedBounds);
Evan Rosky70213702019-11-05 10:26:24 -08002274 }
2275
Evan Roskye067ddf2020-04-24 18:28:25 -07002276 // Non-null compatibility insets means the activity prefers to keep its original size, so
2277 // out bounds doesn't need to be restricted by the parent or current display
2278 final boolean customContainerPolicy = compatInsets != null;
2279
Louis Changcdec0802019-11-11 11:45:07 +08002280 Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
2281 if (outAppBounds == null || outAppBounds.isEmpty()) {
Evan Roskye067ddf2020-04-24 18:28:25 -07002282 // App-bounds hasn't been overridden, so calculate a value for it.
Evan Rosky70213702019-11-05 10:26:24 -08002283 inOutConfig.windowConfiguration.setAppBounds(mTmpFullBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002284 outAppBounds = inOutConfig.windowConfiguration.getAppBounds();
Evan Roskye067ddf2020-04-24 18:28:25 -07002285
2286 if (!customContainerPolicy && windowingMode != WINDOWING_MODE_FREEFORM) {
2287 final Rect containingAppBounds;
2288 if (insideParentBounds) {
2289 containingAppBounds = parentConfig.windowConfiguration.getAppBounds();
2290 } else {
2291 // Restrict appBounds to display non-decor rather than parent because the
2292 // override bounds are beyond the parent. Otherwise, it won't match the
2293 // overridden bounds.
2294 final TaskDisplayArea displayArea = getDisplayArea();
2295 containingAppBounds = displayArea != null
2296 ? displayArea.getWindowConfiguration().getAppBounds() : null;
2297 }
2298 if (containingAppBounds != null && !containingAppBounds.isEmpty()) {
2299 outAppBounds.intersect(containingAppBounds);
2300 }
Louis Changcdec0802019-11-11 11:45:07 +08002301 }
2302 }
2303
2304 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED
2305 || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
Riddle Hsu1f931a592020-04-22 21:15:38 +08002306 if (!customContainerPolicy && WindowConfiguration.isFloating(windowingMode)) {
jaehoon.kim643293e2019-11-08 06:36:28 +09002307 mTmpNonDecorBounds.set(mTmpFullBounds);
2308 mTmpStableBounds.set(mTmpFullBounds);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002309 } else if (!customContainerPolicy
Riddle Hsu9264a272020-03-04 23:10:41 +08002310 && (overrideDisplayInfo != null || getDisplayContent() != null)) {
2311 final DisplayInfo di = overrideDisplayInfo != null
2312 ? overrideDisplayInfo
2313 : getDisplayContent().getDisplayInfo();
Louis Changcdec0802019-11-11 11:45:07 +08002314
2315 // For calculating screenWidthDp, screenWidthDp, we use the stable inset screen
2316 // area, i.e. the screen area without the system bars.
2317 // The non decor inset are areas that could never be removed in Honeycomb. See
2318 // {@link WindowManagerPolicy#getNonDecorInsetsLw}.
Evan Rosky70213702019-11-05 10:26:24 -08002319 calculateInsetFrames(mTmpNonDecorBounds, mTmpStableBounds, mTmpFullBounds, di);
Louis Changcdec0802019-11-11 11:45:07 +08002320 } else {
2321 // Apply the given non-decor and stable insets to calculate the corresponding bounds
2322 // for screen size of configuration.
2323 int rotation = inOutConfig.windowConfiguration.getRotation();
2324 if (rotation == ROTATION_UNDEFINED) {
2325 rotation = parentConfig.windowConfiguration.getRotation();
2326 }
Riddle Hsu1f931a592020-04-22 21:15:38 +08002327 if (rotation != ROTATION_UNDEFINED && customContainerPolicy) {
Evan Rosky70213702019-11-05 10:26:24 -08002328 mTmpNonDecorBounds.set(mTmpFullBounds);
2329 mTmpStableBounds.set(mTmpFullBounds);
Riddle Hsue47501b2020-02-18 12:45:41 +08002330 compatInsets.getBoundsByRotation(mTmpBounds, rotation);
Louis Changcdec0802019-11-11 11:45:07 +08002331 intersectWithInsetsIfFits(mTmpNonDecorBounds, mTmpBounds,
2332 compatInsets.mNonDecorInsets[rotation]);
2333 intersectWithInsetsIfFits(mTmpStableBounds, mTmpBounds,
2334 compatInsets.mStableInsets[rotation]);
2335 outAppBounds.set(mTmpNonDecorBounds);
2336 } else {
2337 // Set to app bounds because it excludes decor insets.
2338 mTmpNonDecorBounds.set(outAppBounds);
2339 mTmpStableBounds.set(outAppBounds);
2340 }
2341 }
2342
2343 if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) {
2344 final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002345 inOutConfig.screenWidthDp = (insideParentBounds && !customContainerPolicy)
Louis Changcdec0802019-11-11 11:45:07 +08002346 ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp)
2347 : overrideScreenWidthDp;
2348 }
2349 if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) {
2350 final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density);
Riddle Hsu1f931a592020-04-22 21:15:38 +08002351 inOutConfig.screenHeightDp = (insideParentBounds && !customContainerPolicy)
Louis Changcdec0802019-11-11 11:45:07 +08002352 ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp)
2353 : overrideScreenHeightDp;
2354 }
2355
2356 if (inOutConfig.smallestScreenWidthDp
2357 == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) {
2358 if (WindowConfiguration.isFloating(windowingMode)) {
2359 // For floating tasks, calculate the smallest width from the bounds of the task
2360 inOutConfig.smallestScreenWidthDp = (int) (
Evan Rosky70213702019-11-05 10:26:24 -08002361 Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density);
Louis Changcdec0802019-11-11 11:45:07 +08002362 }
2363 // otherwise, it will just inherit
2364 }
2365 }
2366
2367 if (inOutConfig.orientation == ORIENTATION_UNDEFINED) {
2368 inOutConfig.orientation = (inOutConfig.screenWidthDp <= inOutConfig.screenHeightDp)
2369 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
2370 }
2371 if (inOutConfig.screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) {
2372 // For calculating screen layout, we need to use the non-decor inset screen area for the
2373 // calculation for compatibility reasons, i.e. screen area without system bars that
2374 // could never go away in Honeycomb.
2375 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
2376 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Louis Changcdec0802019-11-11 11:45:07 +08002377 // Reducing the screen layout starting from its parent config.
Riddle Hsuca928562019-11-22 01:04:14 +08002378 inOutConfig.screenLayout = computeScreenLayoutOverride(parentConfig.screenLayout,
2379 compatScreenWidthDp, compatScreenHeightDp);
Louis Changcdec0802019-11-11 11:45:07 +08002380 }
2381 }
2382
Riddle Hsuca928562019-11-22 01:04:14 +08002383 /** Computes LONG, SIZE and COMPAT parts of {@link Configuration#screenLayout}. */
2384 static int computeScreenLayoutOverride(int sourceScreenLayout, int screenWidthDp,
2385 int screenHeightDp) {
2386 sourceScreenLayout = sourceScreenLayout
2387 & (Configuration.SCREENLAYOUT_LONG_MASK | Configuration.SCREENLAYOUT_SIZE_MASK);
2388 final int longSize = Math.max(screenWidthDp, screenHeightDp);
2389 final int shortSize = Math.min(screenWidthDp, screenHeightDp);
2390 return Configuration.reduceScreenLayout(sourceScreenLayout, longSize, shortSize);
2391 }
2392
Louis Changcdec0802019-11-11 11:45:07 +08002393 @Override
2394 void resolveOverrideConfiguration(Configuration newParentConfig) {
2395 mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
Louis Changdff902b2020-03-31 13:32:47 +08002396 super.resolveOverrideConfiguration(newParentConfig);
2397
Louis Changcdec0802019-11-11 11:45:07 +08002398 int windowingMode =
Wale Ogunwale0d465192020-01-23 19:14:44 -08002399 getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
Evan Roskyc440b4e2020-04-17 15:11:22 -07002400
2401 // Resolve override windowing mode to fullscreen for home task (even on freeform
2402 // display), or split-screen if in split-screen mode.
Louis Changdff902b2020-03-31 13:32:47 +08002403 if (getActivityType() == ACTIVITY_TYPE_HOME && windowingMode == WINDOWING_MODE_UNDEFINED) {
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07002404 final int parentWindowingMode = newParentConfig.windowConfiguration.getWindowingMode();
Evan Roskyc440b4e2020-04-17 15:11:22 -07002405 windowingMode = WindowConfiguration.isSplitScreenWindowingMode(parentWindowingMode)
2406 ? parentWindowingMode : WINDOWING_MODE_FULLSCREEN;
Louis Changdff902b2020-03-31 13:32:47 +08002407 getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode);
2408 }
2409
Evan Roskyc440b4e2020-04-17 15:11:22 -07002410 if (isLeafTask()) {
Riddle Hsudd49c632020-04-30 22:39:51 +08002411 resolveLeafOnlyOverrideConfigs(newParentConfig, mTmpBounds /* previousBounds */);
Louis Changdff902b2020-03-31 13:32:47 +08002412 }
Evan Roskyc440b4e2020-04-17 15:11:22 -07002413 computeConfigResourceOverrides(getResolvedOverrideConfiguration(), newParentConfig);
2414 }
Louis Changdff902b2020-03-31 13:32:47 +08002415
Riddle Hsudd49c632020-04-30 22:39:51 +08002416 private void resolveLeafOnlyOverrideConfigs(Configuration newParentConfig,
2417 Rect previousBounds) {
Evan Roskyc440b4e2020-04-17 15:11:22 -07002418 int windowingMode =
2419 getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
Louis Changcdec0802019-11-11 11:45:07 +08002420 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
2421 windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
2422 }
2423 Rect outOverrideBounds =
2424 getResolvedOverrideConfiguration().windowConfiguration.getBounds();
2425
2426 if (windowingMode == WINDOWING_MODE_FULLSCREEN) {
2427 computeFullscreenBounds(outOverrideBounds, null /* refActivity */,
2428 newParentConfig.windowConfiguration.getBounds(),
2429 newParentConfig.orientation);
Riddle Hsudd49c632020-04-30 22:39:51 +08002430 // The bounds for fullscreen mode shouldn't be adjusted by minimal size. Otherwise if
2431 // the parent or display is smaller than the size, the content may be cropped.
2432 return;
Louis Changcdec0802019-11-11 11:45:07 +08002433 }
2434
Riddle Hsudd49c632020-04-30 22:39:51 +08002435 adjustForMinimalTaskDimensions(outOverrideBounds, previousBounds, newParentConfig);
Louis Changcdec0802019-11-11 11:45:07 +08002436 if (windowingMode == WINDOWING_MODE_FREEFORM) {
2437 // by policy, make sure the window remains within parent somewhere
2438 final float density =
2439 ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT;
2440 final Rect parentBounds =
2441 new Rect(newParentConfig.windowConfiguration.getBounds());
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002442 final DisplayContent display = getDisplayContent();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002443 if (display != null) {
Louis Changcdec0802019-11-11 11:45:07 +08002444 // If a freeform window moves below system bar, there is no way to move it again
2445 // by touch. Because its caption is covered by system bar. So we exclude them
2446 // from stack bounds. and then caption will be shown inside stable area.
2447 final Rect stableBounds = new Rect();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002448 display.getStableRect(stableBounds);
Louis Changcdec0802019-11-11 11:45:07 +08002449 parentBounds.intersect(stableBounds);
2450 }
2451
2452 fitWithinBounds(outOverrideBounds, parentBounds,
2453 (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP),
2454 (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP));
2455
2456 // Prevent to overlap caption with stable insets.
2457 final int offsetTop = parentBounds.top - outOverrideBounds.top;
2458 if (offsetTop > 0) {
2459 outOverrideBounds.offset(0, offsetTop);
2460 }
2461 }
Louis Changcdec0802019-11-11 11:45:07 +08002462 }
2463
2464 /**
2465 * Compute bounds (letterbox or pillarbox) for
2466 * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the
2467 * orientation change and the requested orientation is different from the parent.
2468 */
2469 void computeFullscreenBounds(@NonNull Rect outBounds, @Nullable ActivityRecord refActivity,
2470 @NonNull Rect parentBounds, int parentOrientation) {
2471 // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent".
2472 outBounds.setEmpty();
2473 if (handlesOrientationChangeFromDescendant()) {
2474 return;
2475 }
2476 if (refActivity == null) {
2477 // Use the top activity as the reference of orientation. Don't include overlays because
2478 // it is usually not the actual content or just temporarily shown.
2479 // E.g. ForcedResizableInfoActivity.
Wale Ogunwale21e06482019-11-18 05:14:15 -08002480 refActivity = getTopNonFinishingActivity(false /* includeOverlays */);
Louis Changcdec0802019-11-11 11:45:07 +08002481 }
2482
2483 // If the task or the reference activity requires a different orientation (either by
2484 // override or activityInfo), make it fit the available bounds by scaling down its bounds.
2485 final int overrideOrientation = getRequestedOverrideConfiguration().orientation;
2486 final int forcedOrientation =
2487 (overrideOrientation != ORIENTATION_UNDEFINED || refActivity == null)
2488 ? overrideOrientation : refActivity.getRequestedConfigurationOrientation();
2489 if (forcedOrientation == ORIENTATION_UNDEFINED || forcedOrientation == parentOrientation) {
2490 return;
2491 }
2492
2493 final int parentWidth = parentBounds.width();
2494 final int parentHeight = parentBounds.height();
2495 final float aspect = ((float) parentHeight) / parentWidth;
2496 if (forcedOrientation == ORIENTATION_LANDSCAPE) {
2497 final int height = (int) (parentWidth / aspect);
2498 final int top = parentBounds.centerY() - height / 2;
2499 outBounds.set(parentBounds.left, top, parentBounds.right, top + height);
2500 } else {
2501 final int width = (int) (parentHeight * aspect);
2502 final int left = parentBounds.centerX() - width / 2;
2503 outBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
2504 }
2505 }
2506
2507 Rect updateOverrideConfigurationFromLaunchBounds() {
Louis Changa009c762020-02-26 11:21:31 +08002508 // If the task is controlled by another organized task, do not set override
2509 // configurations and let its parent (organized task) to control it;
Louis Chang06107a32020-04-06 11:55:46 +08002510 final Task rootTask = getRootTask();
2511 final Rect bounds = rootTask != this && rootTask.isOrganized() ? null : getLaunchBounds();
Louis Changcdec0802019-11-11 11:45:07 +08002512 setBounds(bounds);
2513 if (bounds != null && !bounds.isEmpty()) {
2514 // TODO: Review if we actually want to do this - we are setting the launch bounds
2515 // directly here.
2516 bounds.set(getRequestedOverrideBounds());
2517 }
2518 return bounds;
2519 }
2520
2521 /** Updates the task's bounds and override configuration to match what is expected for the
2522 * input stack. */
2523 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002524 final ActivityStack stack = getStack();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002525
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002526 if (stack != null && stack == inStack) {
Louis Changcdec0802019-11-11 11:45:07 +08002527 return;
2528 }
2529
2530 if (inStack.inFreeformWindowingMode()) {
2531 if (!isResizeable()) {
2532 throw new IllegalArgumentException("Can not position non-resizeable task="
2533 + this + " in stack=" + inStack);
2534 }
2535 if (!matchParentBounds()) {
2536 return;
2537 }
2538 if (mLastNonFullscreenBounds != null) {
2539 setBounds(mLastNonFullscreenBounds);
2540 } else {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002541 mStackSupervisor.getLaunchParamsController().layoutTask(this, null);
Louis Changcdec0802019-11-11 11:45:07 +08002542 }
2543 } else {
2544 setBounds(inStack.getRequestedOverrideBounds());
2545 }
2546 }
2547
2548 /** Returns the bounds that should be used to launch this task. */
2549 Rect getLaunchBounds() {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002550 final ActivityStack stack = getStack();
2551 if (stack == null) {
Louis Changcdec0802019-11-11 11:45:07 +08002552 return null;
2553 }
2554
2555 final int windowingMode = getWindowingMode();
2556 if (!isActivityTypeStandardOrUndefined()
2557 || windowingMode == WINDOWING_MODE_FULLSCREEN
2558 || (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && !isResizeable())) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002559 return isResizeable() ? stack.getRequestedOverrideBounds() : null;
Louis Changcdec0802019-11-11 11:45:07 +08002560 } else if (!getWindowConfiguration().persistTaskBounds()) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002561 return stack.getRequestedOverrideBounds();
Louis Changcdec0802019-11-11 11:45:07 +08002562 }
2563 return mLastNonFullscreenBounds;
2564 }
2565
Louis Changcdec0802019-11-11 11:45:07 +08002566 void setRootProcess(WindowProcessController proc) {
2567 clearRootProcess();
2568 if (intent != null
2569 && (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0) {
2570 mRootProcess = proc;
2571 mRootProcess.addRecentTask(this);
2572 }
2573 }
2574
2575 void clearRootProcess() {
2576 if (mRootProcess != null) {
2577 mRootProcess.removeRecentTask(this);
2578 mRootProcess = null;
2579 }
2580 }
2581
Tiger Huanged6794e2019-05-07 20:07:59 +08002582 @Override
Craig Mautnerc00204b2013-03-05 15:02:14 -08002583 DisplayContent getDisplayContent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002584 // TODO: Why aren't we just using our own display content vs. parent's???
2585 final ActivityStack stack = getStack();
2586 return stack != null && stack != this
2587 ? stack.getDisplayContent() : super.getDisplayContent();
Wale Ogunwale8577a052019-10-26 23:22:34 -07002588 }
2589
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002590 int getDisplayId() {
2591 final DisplayContent dc = getDisplayContent();
2592 return dc != null ? dc.mDisplayId : INVALID_DISPLAY;
2593 }
2594
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002595 // TODO: Migrate callers to getRootTask()
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002596 ActivityStack getStack() {
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002597 return (ActivityStack) getRootTask();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002598 }
2599
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08002600 /** @return Id of root task. */
2601 int getRootTaskId() {
2602 return getRootTask().mTaskId;
2603 }
2604
2605 Task getRootTask() {
2606 final WindowContainer parent = getParent();
2607 if (parent == null) return this;
2608
2609 final Task parentTask = parent.asTask();
2610 return parentTask == null ? this : parentTask.getRootTask();
2611 }
2612
2613 // TODO(task-merge): Figure out what's the right thing to do for places that used it.
2614 boolean isRootTask() {
2615 return getRootTask() == this;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002616 }
2617
Louis Changfd5539e2020-02-04 14:34:24 +08002618 boolean isLeafTask() {
2619 for (int i = mChildren.size() - 1; i >= 0; --i) {
2620 if (mChildren.get(i).asTask() != null) {
2621 return false;
2622 }
2623 }
2624 return true;
2625 }
2626
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002627 int getDescendantTaskCount() {
2628 final int[] currentCount = {0};
2629 final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
2630 PooledLambda.__(Task.class), currentCount);
Wale Ogunwale0d465192020-01-23 19:14:44 -08002631 forAllLeafTasks(c, false /* traverseTopToBottom */);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002632 c.recycle();
2633 return currentCount[0];
2634 }
2635
Louis Chang6434be42020-04-10 17:39:35 +08002636 /**
2637 * Find next proper focusable stack and make it focused.
2638 * @return The stack that now got the focus, {@code null} if none found.
2639 */
2640 ActivityStack adjustFocusToNextFocusableTask(String reason) {
2641 return adjustFocusToNextFocusableTask(reason, false /* allowFocusSelf */,
wilsonshih046523c2020-06-02 12:28:26 +08002642 true /* moveDisplayToTop */);
Louis Chang6434be42020-04-10 17:39:35 +08002643 }
2644
2645 /** Return the next focusable task by looking from the siblings and parent tasks */
2646 private Task getNextFocusableTask(boolean allowFocusSelf) {
2647 final WindowContainer parent = getParent();
2648 if (parent == null) {
2649 return null;
2650 }
2651
2652 final Task focusableTask = parent.getTask((task) -> (allowFocusSelf || task != this)
2653 && ((ActivityStack) task).isFocusableAndVisible());
2654 if (focusableTask == null && parent.asTask() != null) {
2655 return parent.asTask().getNextFocusableTask(allowFocusSelf);
2656 } else {
2657 return focusableTask;
2658 }
2659 }
2660
2661 /**
2662 * Find next proper focusable task and make it focused.
2663 * @param reason The reason of making the adjustment.
2664 * @param allowFocusSelf Is the focus allowed to remain on the same task.
wilsonshih046523c2020-06-02 12:28:26 +08002665 * @param moveDisplayToTop Whether to move display to top while making the task focused.
Louis Chang6434be42020-04-10 17:39:35 +08002666 * @return The root task that now got the focus, {@code null} if none found.
2667 */
2668 ActivityStack adjustFocusToNextFocusableTask(String reason, boolean allowFocusSelf,
wilsonshih046523c2020-06-02 12:28:26 +08002669 boolean moveDisplayToTop) {
Louis Chang6434be42020-04-10 17:39:35 +08002670 ActivityStack focusableTask = (ActivityStack) getNextFocusableTask(allowFocusSelf);
2671 if (focusableTask == null) {
2672 focusableTask = mRootWindowContainer.getNextFocusableStack((ActivityStack) this,
2673 !allowFocusSelf);
2674 }
2675 if (focusableTask == null) {
2676 return null;
2677 }
2678
Louis Chang6434be42020-04-10 17:39:35 +08002679 final ActivityStack rootTask = (ActivityStack) focusableTask.getRootTask();
wilsonshih046523c2020-06-02 12:28:26 +08002680 if (!moveDisplayToTop) {
2681 // There may be multiple task layers above this task, so when relocating the task to the
2682 // top, we should move this task and each of its parent task that below display area to
2683 // the top of each layer.
Louis Chang6434be42020-04-10 17:39:35 +08002684 WindowContainer parent = focusableTask.getParent();
wilsonshih046523c2020-06-02 12:28:26 +08002685 WindowContainer next = focusableTask;
2686 do {
2687 parent.positionChildAt(POSITION_TOP, next, false /* includingParents */);
2688 next = parent;
2689 parent = next.getParent();
2690 } while (next.asTask() != null && parent != null);
Louis Chang6434be42020-04-10 17:39:35 +08002691 return rootTask;
2692 }
2693
wilsonshiha31e01f2020-04-24 11:41:29 +08002694 final String myReason = reason + " adjustFocusToNextFocusableStack";
2695 final ActivityRecord top = focusableTask.topRunningActivity();
2696 if (focusableTask.isActivityTypeHome() && (top == null || !top.mVisibleRequested)) {
2697 // If we will be focusing on the home stack next and its current top activity isn't
2698 // visible, then use the move the home stack task to top to make the activity visible.
2699 focusableTask.getDisplayArea().moveHomeActivityToTop(myReason);
2700 return rootTask;
2701 }
2702
Louis Chang6434be42020-04-10 17:39:35 +08002703 // Move the entire hierarchy to top with updating global top resumed activity
2704 // and focused application if needed.
2705 focusableTask.moveToFront(myReason);
2706 // Top display focused stack is changed, update top resumed activity if needed.
2707 if (rootTask.mResumedActivity != null) {
2708 mStackSupervisor.updateTopResumedActivityIfNeeded();
2709 // Set focused app directly because if the next focused activity is already resumed
2710 // (e.g. the next top activity is on a different display), there won't have activity
2711 // state change to update it.
2712 mAtmService.setResumedActivityUncheckLocked(rootTask.mResumedActivity, reason);
2713 }
2714 return rootTask;
2715 }
2716
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002717 /** Calculate the minimum possible position for a task that can be shown to the user.
2718 * The minimum position will be above all other tasks that can't be shown.
2719 * @param minPosition The minimum position the caller is suggesting.
2720 * We will start adjusting up from here.
2721 * @param size The size of the current task list.
2722 */
2723 // TODO: Move user to their own window container.
2724 private int computeMinUserPosition(int minPosition, int size) {
2725 while (minPosition < size) {
2726 final WindowContainer child = mChildren.get(minPosition);
2727 final boolean canShow = child.showToCurrentUser();
2728 if (canShow) {
2729 break;
2730 }
2731 minPosition++;
2732 }
2733 return minPosition;
2734 }
2735
2736 /** Calculate the maximum possible position for a task that can't be shown to the user.
2737 * The maximum position will be below all other tasks that can be shown.
2738 * @param maxPosition The maximum position the caller is suggesting.
2739 * We will start adjusting down from here.
2740 */
2741 // TODO: Move user to their own window container.
2742 private int computeMaxUserPosition(int maxPosition) {
2743 while (maxPosition > 0) {
2744 final WindowContainer child = mChildren.get(maxPosition);
2745 final boolean canShow = child.showToCurrentUser();
2746 if (!canShow) {
2747 break;
2748 }
2749 maxPosition--;
2750 }
2751 return maxPosition;
2752 }
2753
2754 private int getAdjustedChildPosition(WindowContainer wc, int suggestedPosition) {
2755 final boolean canShowChild = wc.showToCurrentUser();
2756
2757 final int size = mChildren.size();
2758
2759 // Figure-out min/max possible position depending on if child can show for current user.
2760 int minPosition = (canShowChild) ? computeMinUserPosition(0, size) : 0;
2761 int maxPosition = (canShowChild) ? size : computeMaxUserPosition(size - 1);
2762
2763 // Factor in always-on-top children in max possible position.
2764 if (!wc.isAlwaysOnTop()) {
2765
2766 // We want to place all non-always-on-top containers below always-on-top ones.
2767 while (maxPosition > minPosition) {
2768 if (!mChildren.get(maxPosition - 1).isAlwaysOnTop()) break;
2769 --maxPosition;
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002770 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002771 }
2772
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002773 // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
2774 if (suggestedPosition == POSITION_BOTTOM && minPosition == 0) {
2775 return POSITION_BOTTOM;
Louis Changa009c762020-02-26 11:21:31 +08002776 } else if (suggestedPosition == POSITION_TOP && maxPosition >= (size - 1)) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002777 return POSITION_TOP;
2778 }
2779 // Reset position based on minimum/maximum possible positions.
2780 return Math.min(Math.max(suggestedPosition, minPosition), maxPosition);
Craig Mautnerc00204b2013-03-05 15:02:14 -08002781 }
2782
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002783 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002784 void positionChildAt(int position, WindowContainer child, boolean includingParents) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002785 position = getAdjustedChildPosition(child, position);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002786 super.positionChildAt(position, child, includingParents);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002787
2788 // Log positioning.
2789 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "positionChildAt: child=" + child
2790 + " position=" + position + " parent=" + this);
2791
2792 final int toTop = position >= (mChildren.size() - 1) ? 1 : 0;
2793 final Task task = child.asTask();
2794 if (task != null) {
2795 EventLogTags.writeWmTaskMoved(task.mTaskId, toTop, position);
2796 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002797 }
2798
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002799 @VisibleForTesting
2800 boolean hasWindowsAlive() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002801 return getActivity(ActivityRecord::hasWindowsAlive) != null;
Chong Zhang7e8eeb72016-01-06 19:14:47 -08002802 }
2803
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002804 @VisibleForTesting
2805 boolean shouldDeferRemoval() {
Wale Ogunwalec17418e2019-10-13 23:00:40 +02002806 if (mChildren.isEmpty()) {
2807 // No reason to defer removal of a Task that doesn't have any child.
2808 return false;
2809 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002810 return hasWindowsAlive() && getStack().isAnimating(TRANSITION | CHILDREN);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -08002811 }
2812
Wale Ogunwalef6192862016-09-10 13:42:30 -07002813 @Override
Andrii Kulian45a61fe2017-01-05 16:53:19 -08002814 void removeImmediately() {
Wale Ogunwaleb9b16a72016-01-27 12:24:44 -08002815 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId);
Jeff Changd136e772019-11-05 20:33:52 +08002816 EventLogTags.writeWmTaskRemoved(mTaskId, "removeTask");
Robert Carr8a2f9132019-11-11 15:03:15 -08002817
Issei Suzuki4a46a922020-06-09 11:23:29 +02002818 if (mDisplayContent != null && mDisplayContent.isSingleTaskInstance()) {
2819 mAtmService.notifySingleTaskDisplayEmpty(mDisplayContent.mDisplayId);
2820 }
2821
Robert Carr8a2f9132019-11-11 15:03:15 -08002822 // If applicable let the TaskOrganizer know the Task is vanishing.
2823 setTaskOrganizer(null);
2824
Andrii Kulian45a61fe2017-01-05 16:53:19 -08002825 super.removeImmediately();
Craig Mautnere3119b72015-01-20 15:02:36 -08002826 }
2827
Louis Changcdec0802019-11-11 11:45:07 +08002828 // TODO: Consolidate this with Task.reparent()
Louis Changdc077272019-11-12 16:52:56 +08002829 void reparent(ActivityStack stack, int position, boolean moveParents, String reason) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -08002830 if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002831 + " from stack=" + getStack());
Louis Chang074cdf22019-12-13 13:15:13 +08002832 EventLogTags.writeWmTaskRemoved(mTaskId, "reParentTask:" + reason);
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002833
2834 reparent(stack, position);
2835
Louis Changcdec0802019-11-11 11:45:07 +08002836 stack.positionChildAt(position, this, moveParents);
Andrii Kulian7cd7c2d2017-01-18 12:14:37 -08002837
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002838 // If we are moving from the fullscreen stack to the pinned stack then we want to preserve
2839 // our insets so that there will not be a jump in the area covered by system decorations.
2840 // We rely on the pinned animation to later unset this value.
2841 mPreserveNonFloatingState = stack.inPinnedWindowingMode();
Wale Ogunwale53a29a92015-02-23 15:42:52 -08002842 }
2843
Bryce Leef3c6a472017-11-14 14:53:06 -08002844 public int setBounds(Rect bounds, boolean forceResize) {
2845 final int boundsChanged = setBounds(bounds);
2846
2847 if (forceResize && (boundsChanged & BOUNDS_CHANGE_SIZE) != BOUNDS_CHANGE_SIZE) {
2848 onResize();
2849 return BOUNDS_CHANGE_SIZE | boundsChanged;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002850 }
Wale Ogunwale68278562017-09-23 17:13:55 -07002851
Bryce Leef3c6a472017-11-14 14:53:06 -08002852 return boundsChanged;
2853 }
2854
2855 /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
2856 @Override
2857 public int setBounds(Rect bounds) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002858 int rotation = Surface.ROTATION_0;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002859 final DisplayContent displayContent = getStack() != null
2860 ? getStack().getDisplayContent() : null;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002861 if (displayContent != null) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002862 rotation = displayContent.getDisplayInfo().rotation;
Wale Ogunwale2cc92f52015-09-09 13:12:10 -07002863 }
2864
Bryce Leef3c6a472017-11-14 14:53:06 -08002865 final int boundsChange = super.setBounds(bounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002866 mRotation = rotation;
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002867 updateSurfacePosition();
Wale Ogunwale2cc92f52015-09-09 13:12:10 -07002868 return boundsChange;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002869 }
2870
Garfield Tan90b04282018-12-11 14:04:42 -08002871 @Override
2872 public boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
2873 ConfigurationContainer requestingContainer) {
2874 if (super.onDescendantOrientationChanged(freezeDisplayToken, requestingContainer)) {
2875 return true;
2876 }
2877
2878 // No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
2879 // it if possible.
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002880 if (getParent() != null) {
2881 onConfigurationChanged(getParent().getConfiguration());
Garfield Tan90b04282018-12-11 14:04:42 -08002882 return true;
2883 }
2884 return false;
2885 }
2886
Yunfan Chen0e7aff92018-12-05 16:35:32 -08002887 void resize(boolean relayout, boolean forced) {
2888 if (setBounds(getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE && relayout) {
2889 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
2890 }
2891 }
2892
Louis Chang7501e332018-08-20 13:08:39 +08002893 @Override
2894 void onDisplayChanged(DisplayContent dc) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002895 final boolean isRootTask = isRootTask();
2896 if (!isRootTask) {
2897 adjustBoundsForDisplayChangeIfNeeded(dc);
2898 }
Louis Chang7501e332018-08-20 13:08:39 +08002899 super.onDisplayChanged(dc);
Yuncheol Heo1c211c22020-04-20 13:08:43 -07002900 if (isLeafTask()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002901 final int displayId = (dc != null) ? dc.getDisplayId() : INVALID_DISPLAY;
2902 mWmService.mAtmService.getTaskChangeNotificationController().notifyTaskDisplayChanged(
2903 mTaskId, displayId);
2904 }
Louis Chang7501e332018-08-20 13:08:39 +08002905 }
2906
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002907 boolean isResizeable(boolean checkSupportsPip) {
2908 return (mAtmService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
2909 || (checkSupportsPip && mSupportsPictureInPicture));
Chong Zhangb15758a2015-11-17 12:12:03 -08002910 }
2911
2912 boolean isResizeable() {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02002913 return isResizeable(true /* checkSupportsPip */);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002914 }
2915
skuhne@google.com322347b2016-12-02 12:54:03 -08002916 /**
2917 * Tests if the orientation should be preserved upon user interactive resizig operations.
2918
2919 * @return true if orientation should not get changed upon resizing operation.
2920 */
2921 boolean preserveOrientationOnResize() {
2922 return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY
2923 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY
2924 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
2925 }
2926
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002927 boolean cropWindowsToStackBounds() {
Evan Rosky364c9122020-06-04 16:09:31 -07002928 // Don't crop HOME/RECENTS windows to stack bounds. This is because in split-screen
2929 // they extend past their stack and sysui uses the stack surface to control cropping.
2930 // TODO(b/158242495): get rid of this when drag/drop can use surface bounds.
Evan Rosky38e9b212020-06-16 14:50:09 -07002931 if (isActivityTypeHome() || isActivityTypeRecents()) {
2932 // Make sure this is the top-most non-organizer root task (if not top-most, it means
2933 // another translucent task could be above this, so this needs to stay cropped.
2934 final Task rootTask = getRootTask();
2935 final Task topNonOrgTask =
2936 rootTask.mCreatedByOrganizer ? rootTask.getTopMostTask() : rootTask;
2937 if (isDescendantOf(topNonOrgTask)) {
2938 return false;
2939 }
2940 }
2941 return isResizeable();
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002942 }
2943
Jorim Jaggi0429f352015-12-22 16:29:16 +01002944 /**
2945 * Prepares the task bounds to be frozen with the current size. See
Garfield Tane8d84ab2019-10-11 09:49:40 -07002946 * {@link ActivityRecord#freezeBounds}.
Jorim Jaggi0429f352015-12-22 16:29:16 +01002947 */
2948 void prepareFreezingBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -08002949 mPreparedFrozenBounds.set(getBounds());
Andrii Kulian441e4492016-09-29 15:25:00 -07002950 mPreparedFrozenMergedConfig.setTo(getConfiguration());
Jorim Jaggi0429f352015-12-22 16:29:16 +01002951 }
2952
Issei Suzukiad287d02019-10-31 16:19:44 +01002953 @Override
2954 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2955 Rect outSurfaceInsets) {
2956 final WindowState windowState = getTopVisibleAppMainWindow();
2957 if (windowState != null) {
2958 windowState.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2959 } else {
2960 super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
2961 }
2962 }
2963
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002964 /**
2965 * Calculate the maximum visible area of this task. If the task has only one app,
2966 * the result will be visible frame of that app. If the task has more than one apps,
2967 * we search from top down if the next app got different visible area.
2968 *
2969 * This effort is to handle the case where some task (eg. GMail composer) might pop up
2970 * a dialog that's different in size from the activity below, in which case we should
2971 * be dimming the entire task area behind the dialog.
2972 *
2973 * @param out Rect containing the max visible bounds.
2974 * @return true if the task has some visible app windows; false otherwise.
2975 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002976 private static void getMaxVisibleBounds(ActivityRecord token, Rect out, boolean[] foundTop) {
2977 // skip hidden (or about to hide) apps
2978 if (token.mIsExiting || !token.isClientVisible() || !token.mVisibleRequested) {
2979 return;
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002980 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08002981 final WindowState win = token.findMainWindow();
2982 if (win == null) {
2983 return;
2984 }
2985 if (!foundTop[0]) {
2986 foundTop[0] = true;
2987 out.setEmpty();
2988 }
2989
2990 win.getMaxVisibleBounds(out);
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08002991 }
2992
2993 /** Bounds of the task to be used for dimming, as well as touch related tests. */
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002994 void getDimBounds(Rect out) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08002995 final DisplayContent displayContent = getStack().getDisplayContent();
Robert Carra86a6bf2016-04-08 17:34:16 -07002996 // It doesn't matter if we in particular are part of the resize, since we couldn't have
2997 // a DimLayer anyway if we weren't visible.
Wale Ogunwalef6192862016-09-10 13:42:30 -07002998 final boolean dockedResizing = displayContent != null
2999 && displayContent.mDividerControllerLocked.isResizing();
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003000 if (inFreeformWindowingMode()) {
3001 boolean[] foundTop = { false };
3002 final PooledConsumer c = PooledLambda.obtainConsumer(Task::getMaxVisibleBounds,
3003 PooledLambda.__(ActivityRecord.class), out, foundTop);
Vishnu Nair4d7a6002020-01-23 14:34:40 -08003004 forAllActivities(c);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003005 c.recycle();
3006 if (foundTop[0]) {
3007 return;
3008 }
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08003009 }
3010
Evan Rosky4fb1e912019-03-06 13:54:43 -08003011 if (!matchParentBounds()) {
3012 // When minimizing the docked stack when going home, we don't adjust the task bounds
3013 // so we need to intersect the task bounds with the stack bounds here.
3014 //
3015 // If we are Docked Resizing with snap points, the task bounds could be smaller than the
3016 // stack bounds and so we don't even want to use them. Even if the app should not be
3017 // resized the Dim should keep up with the divider.
3018 if (dockedResizing) {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003019 getStack().getBounds(out);
Evan Rosky4fb1e912019-03-06 13:54:43 -08003020 } else {
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003021 getStack().getBounds(mTmpRect);
Evan Rosky4fb1e912019-03-06 13:54:43 -08003022 mTmpRect.intersect(getBounds());
3023 out.set(mTmpRect);
3024 }
3025 } else {
3026 out.set(getBounds());
Wale Ogunwalef6192862016-09-10 13:42:30 -07003027 }
Evan Rosky4fb1e912019-03-06 13:54:43 -08003028 return;
Chong Zhang4c9ba52a2015-11-10 18:36:33 -08003029 }
3030
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003031 void setDragResizing(boolean dragResizing, int dragResizeMode) {
Jorim Jaggic662d8e2016-02-05 16:54:54 -08003032 if (mDragResizing != dragResizing) {
chaviw8c9d1f52018-07-25 14:56:07 -07003033 // No need to check if the mode is allowed if it's leaving dragResize
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003034 if (dragResizing && !DragResizeMode.isModeAllowedForStack(getStack(), dragResizeMode)) {
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003035 throw new IllegalArgumentException("Drag resize mode not allow for stack stackId="
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003036 + getRootTaskId() + " dragResizeMode=" + dragResizeMode);
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003037 }
Jorim Jaggic662d8e2016-02-05 16:54:54 -08003038 mDragResizing = dragResizing;
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003039 mDragResizeMode = dragResizeMode;
Jorim Jaggic662d8e2016-02-05 16:54:54 -08003040 resetDragResizingChangeReported();
3041 }
3042 }
3043
Chong Zhang3005e752015-09-18 18:46:28 -07003044 boolean isDragResizing() {
Wale Ogunwaled1c37912016-08-16 03:19:39 -07003045 return mDragResizing;
Chong Zhang3005e752015-09-18 18:46:28 -07003046 }
3047
Jorim Jaggi0b46f3c2016-03-14 12:21:37 +01003048 int getDragResizeMode() {
3049 return mDragResizeMode;
3050 }
3051
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003052 void adjustBoundsForDisplayChangeIfNeeded(final DisplayContent displayContent) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003053 if (displayContent == null) {
3054 return;
3055 }
Bryce Leef3c6a472017-11-14 14:53:06 -08003056 if (matchParentBounds()) {
Wale Ogunwale68278562017-09-23 17:13:55 -07003057 // TODO: Yeah...not sure if this works with WindowConfiguration, but shouldn't be a
3058 // problem once we move mBounds into WindowConfiguration.
Bryce Leef3c6a472017-11-14 14:53:06 -08003059 setBounds(null);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003060 return;
3061 }
Garfield Tandec96db2018-10-30 11:28:49 -07003062 final int displayId = displayContent.getDisplayId();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003063 final int newRotation = displayContent.getDisplayInfo().rotation;
Garfield Tandec96db2018-10-30 11:28:49 -07003064 if (displayId != mLastRotationDisplayId) {
3065 // This task is on a display that it wasn't on. There is no point to keep the relative
3066 // position if display rotations for old and new displays are different. Just keep these
3067 // values.
3068 mLastRotationDisplayId = displayId;
3069 mRotation = newRotation;
3070 return;
3071 }
3072
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003073 if (mRotation == newRotation) {
Garfield Tandec96db2018-10-30 11:28:49 -07003074 // Rotation didn't change. We don't need to adjust the bounds to keep the relative
3075 // position.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003076 return;
3077 }
3078
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003079 // Device rotation changed.
Chong Zhang2e2c81a2016-07-15 11:28:17 -07003080 // - We don't want the task to move around on the screen when this happens, so update the
3081 // task bounds so it stays in the same place.
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003082 // - Rotate the bounds and notify activity manager if the task can be resized independently
Chong Zhang2e2c81a2016-07-15 11:28:17 -07003083 // from its stack. The stack will take care of task rotation for the other case.
Bryce Leef3c6a472017-11-14 14:53:06 -08003084 mTmpRect2.set(getBounds());
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003085
Wale Ogunwale3382ab12017-07-27 08:55:03 -07003086 if (!getWindowConfiguration().canResizeTask()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08003087 setBounds(mTmpRect2);
Wale Ogunwalee1fe4d12016-01-14 08:52:30 -08003088 return;
3089 }
3090
Wale Ogunwale94744212015-09-21 19:01:47 -07003091 displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
Bryce Leef3c6a472017-11-14 14:53:06 -08003092 if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003093 mAtmService.resizeTask(mTaskId, getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION);
Wale Ogunwale1ed0d892015-09-28 13:27:44 -07003094 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003095 }
3096
Wale Ogunwalef6192862016-09-10 13:42:30 -07003097 /** Cancels any running app transitions associated with the task. */
Winsonc28098f2015-10-30 14:50:19 -07003098 void cancelTaskWindowTransition() {
Wale Ogunwalef6192862016-09-10 13:42:30 -07003099 for (int i = mChildren.size() - 1; i >= 0; --i) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003100 mChildren.get(i).cancelAnimation();
Winsonc28098f2015-10-30 14:50:19 -07003101 }
3102 }
3103
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07003104 boolean showForAllUsers() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003105 if (mChildren.isEmpty()) return false;
3106 final ActivityRecord r = getTopNonFinishingActivity();
3107 return r != null && r.mShowForAllUsers;
Jorim Jaggiff71d202016-04-14 13:12:36 -07003108 }
3109
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08003110 @Override
3111 boolean showToCurrentUser() {
Louis Changedbda502020-04-27 15:51:42 +08003112 return mForceShowForAllUsers || showForAllUsers()
3113 || mWmService.isCurrentProfile(getTopMostTask().mUserId);
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08003114 }
3115
3116 void setForceShowForAllUsers(boolean forceShowForAllUsers) {
3117 mForceShowForAllUsers = forceShowForAllUsers;
3118 }
3119
Evan Rosky688c8382020-04-03 17:27:08 -07003120 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003121 public boolean isAttached() {
Andrii Kulian86d676c2020-03-27 19:34:54 -07003122 final TaskDisplayArea taskDisplayArea = getDisplayArea();
3123 return taskDisplayArea != null && !taskDisplayArea.isRemoved();
3124 }
3125
3126 @Override
3127 @Nullable
3128 TaskDisplayArea getDisplayArea() {
3129 return (TaskDisplayArea) super.getDisplayArea();
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003130 }
3131
Robert Carr7e4c90e2017-02-15 19:52:38 -08003132 /**
3133 * When we are in a floating stack (Freeform, Pinned, ...) we calculate
3134 * insets differently. However if we are animating to the fullscreen stack
3135 * we need to begin calculating insets as if we were fullscreen, otherwise
3136 * we will have a jump at the end.
3137 */
Robert Carre6275582016-02-29 15:45:45 -08003138 boolean isFloating() {
Hongwei Wang85cf41f2020-01-15 15:14:47 -08003139 return getWindowConfiguration().tasksAreFloating() && !mPreserveNonFloatingState;
Robert Carre6275582016-02-29 15:45:45 -08003140 }
3141
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003142 /**
3143 * Returns true if the stack is translucent and can have other contents visible behind it if
3144 * needed. A stack is considered translucent if it don't contain a visible or
3145 * starting (about to be visible) activity that is fullscreen (opaque).
3146 * @param starting The currently starting activity or null if there is none.
3147 */
3148 @VisibleForTesting
3149 boolean isTranslucent(ActivityRecord starting) {
Robert Carrf6878a42019-12-18 02:13:12 -08003150 if (!isAttached() || isForceHidden()) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003151 return true;
3152 }
3153 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isOpaqueActivity,
3154 PooledLambda.__(ActivityRecord.class), starting);
3155 final ActivityRecord opaque = getActivity(p);
3156 p.recycle();
3157 return opaque == null;
3158 }
3159
3160 private static boolean isOpaqueActivity(ActivityRecord r, ActivityRecord starting) {
3161 if (r.finishing) {
3162 // We don't factor in finishing activities when determining translucency since
3163 // they will be gone soon.
3164 return false;
3165 }
3166
3167 if (!r.visibleIgnoringKeyguard && r != starting) {
3168 // Also ignore invisible activities that are not the currently starting
3169 // activity (about to be visible).
3170 return false;
3171 }
3172
3173 if (r.occludesParent() || r.hasWallpaper) {
3174 // Stack isn't translucent if it has at least one fullscreen activity
3175 // that is visible.
3176 return true;
3177 }
3178 return false;
3179 }
3180
Winson Chungd41f71d2018-03-16 15:26:07 -07003181 @Override
Evan Roskyfb89d1a2020-06-02 18:42:11 -07003182 public SurfaceControl.Builder makeAnimationLeash() {
3183 return super.makeAnimationLeash().setMetadata(METADATA_TASK_ID, mTaskId);
3184 }
3185
3186 @Override
Winson Chungd41f71d2018-03-16 15:26:07 -07003187 public SurfaceControl getAnimationLeashParent() {
Riddle Hsud8302832019-09-23 21:14:07 +08003188 if (WindowManagerService.sHierarchicalAnimations) {
Issei Suzuki71142152019-08-15 14:39:40 +02003189 return super.getAnimationLeashParent();
3190 }
Winson Chung732446a2018-09-19 13:15:17 -07003191 // Currently, only the recents animation will create animation leashes for tasks. In this
3192 // case, reparent the task to the home animation layer while it is being animated to allow
3193 // the home activity to reorder the app windows relative to its own.
3194 return getAppAnimationLayer(ANIMATION_LAYER_HOME);
Winson Chungd41f71d2018-03-16 15:26:07 -07003195 }
3196
lumark5341d1c2019-12-14 01:54:02 +08003197 @Override
3198 Rect getAnimationBounds(int appStackClipMode) {
3199 // TODO(b/131661052): we should remove appStackClipMode with hierarchical animations.
3200 if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
3201 // Using the stack bounds here effectively applies the clipping before animation.
3202 return getStack().getBounds();
3203 }
3204 return super.getAnimationBounds(appStackClipMode);
3205 }
3206
lumark19a5d2e2019-10-11 16:19:30 +08003207 boolean shouldAnimate() {
Robert Carr8a2f9132019-11-11 15:03:15 -08003208 /**
3209 * Animations are handled by the TaskOrganizer implementation.
3210 */
Wale Ogunwaledec34082020-03-22 09:45:00 -07003211 if (isOrganized()) {
Robert Carr8a2f9132019-11-11 15:03:15 -08003212 return false;
3213 }
lumark19a5d2e2019-10-11 16:19:30 +08003214 // Don't animate while the task runs recents animation but only if we are in the mode
3215 // where we cancel with deferred screenshot, which means that the controller has
3216 // transformed the task.
3217 final RecentsAnimationController controller = mWmService.getRecentsAnimationController();
3218 if (controller != null && controller.isAnimatingTask(this)
3219 && controller.shouldDeferCancelUntilNextTransition()) {
3220 return false;
3221 }
3222 return true;
3223 }
3224
Evan Rosky9020c072018-12-06 14:11:12 -08003225 @Override
chaviw21ea1872020-05-28 17:26:38 -07003226 void setInitialSurfaceControlProperties(SurfaceControl.Builder b) {
Vishnu Nair06cff302020-05-29 14:39:20 -07003227 b.setEffectLayer().setMetadata(METADATA_TASK_ID, mTaskId);
chaviw21ea1872020-05-28 17:26:38 -07003228 super.setInitialSurfaceControlProperties(b);
Evan Rosky9020c072018-12-06 14:11:12 -08003229 }
3230
Winson Chungd41f71d2018-03-16 15:26:07 -07003231 boolean isTaskAnimating() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003232 final RecentsAnimationController recentsAnim = mWmService.getRecentsAnimationController();
Winson Chungd41f71d2018-03-16 15:26:07 -07003233 if (recentsAnim != null) {
3234 if (recentsAnim.isAnimatingTask(this)) {
3235 return true;
3236 }
3237 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003238 return forAllTasks((t) -> { return t != this && t.isTaskAnimating(); });
Winson Chungd41f71d2018-03-16 15:26:07 -07003239 }
3240
lumark19a5d2e2019-10-11 16:19:30 +08003241 @Override
3242 RemoteAnimationTarget createRemoteAnimationTarget(
3243 RemoteAnimationController.RemoteAnimationRecord record) {
lumark5341d1c2019-12-14 01:54:02 +08003244 final ActivityRecord activity = getTopMostActivity();
lumark19a5d2e2019-10-11 16:19:30 +08003245 return activity != null ? activity.createRemoteAnimationTarget(record) : null;
3246 }
3247
Daichi Hirono8ecfc6b2020-02-18 16:28:03 +09003248 @Override
3249 boolean canCreateRemoteAnimationTarget() {
3250 return true;
3251 }
3252
Chong Zhangd8ceb852015-11-11 14:53:41 -08003253 WindowState getTopVisibleAppMainWindow() {
Garfield Tane8d84ab2019-10-11 09:49:40 -07003254 final ActivityRecord activity = getTopVisibleActivity();
3255 return activity != null ? activity.findMainWindow() : null;
Chong Zhang9184ec62015-09-24 12:32:21 -07003256 }
3257
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003258 ActivityRecord topRunningActivity() {
3259 return topRunningActivity(false /* focusableOnly */);
3260 }
3261
3262 ActivityRecord topRunningActivity(boolean focusableOnly) {
3263 // Split into 2 to avoid object creation due to variable capture.
3264 if (focusableOnly) {
3265 return getActivity((r) -> r.canBeTopRunning() && r.isFocusable());
3266 } else {
3267 return getActivity(ActivityRecord::canBeTopRunning);
3268 }
3269 }
3270
3271 ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
3272 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunningNonDelayed
3273 , PooledLambda.__(ActivityRecord.class), notTop);
3274 final ActivityRecord r = getActivity(p);
3275 p.recycle();
3276 return r;
3277 }
3278
3279 private static boolean isTopRunningNonDelayed(ActivityRecord r, ActivityRecord notTop) {
3280 return !r.delayedResume && r != notTop && r.canBeTopRunning();
3281 }
3282
3283 /**
3284 * This is a simplified version of topRunningActivity that provides a number of
3285 * optional skip-over modes. It is intended for use with the ActivityController hook only.
3286 *
3287 * @param token If non-null, any history records matching this token will be skipped.
3288 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
3289 *
3290 * @return Returns the HistoryRecord of the next activity on the stack.
3291 */
3292 ActivityRecord topRunningActivity(IBinder token, int taskId) {
3293 final PooledPredicate p = PooledLambda.obtainPredicate(Task::isTopRunning,
3294 PooledLambda.__(ActivityRecord.class), taskId, token);
3295 final ActivityRecord r = getActivity(p);
3296 p.recycle();
3297 return r;
3298 }
3299
3300 private static boolean isTopRunning(ActivityRecord r, int taskId, IBinder notTop) {
3301 return r.getTask().mTaskId != taskId && r.appToken != notTop && r.canBeTopRunning();
3302 }
3303
Garfield Tane8d84ab2019-10-11 09:49:40 -07003304 ActivityRecord getTopFullscreenActivity() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003305 return getActivity((r) -> {
3306 final WindowState win = r.findMainWindow();
3307 return (win != null && win.mAttrs.isFullscreen());
3308 });
Jorim Jaggie6c6ecb2017-07-20 18:09:20 +02003309 }
3310
Garfield Tane8d84ab2019-10-11 09:49:40 -07003311 ActivityRecord getTopVisibleActivity() {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003312 return getActivity((r) -> {
3313 // skip hidden (or about to hide) apps
3314 return !r.mIsExiting && r.isClientVisible() && r.mVisibleRequested;
3315 });
Chong Zhangbef461f2015-10-27 11:38:24 -07003316 }
3317
Winson Chungb5ce37c2020-04-22 10:08:28 -07003318 boolean isTopActivityFocusable() {
3319 final ActivityRecord r = topRunningActivity();
3320 return r != null ? r.isFocusable()
3321 : (isFocusable() && getWindowConfiguration().canReceiveKeys());
3322 }
3323
3324 boolean isFocusableAndVisible() {
3325 return isTopActivityFocusable() && shouldBeVisible(null /* starting */);
3326 }
3327
Wale Ogunwale3198da42019-10-10 14:45:03 +02003328 void positionChildAtTop(ActivityRecord child) {
3329 positionChildAt(child, POSITION_TOP);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003330 }
3331
Wale Ogunwale3198da42019-10-10 14:45:03 +02003332 void positionChildAt(ActivityRecord child, int position) {
3333 if (child == null) {
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003334 Slog.w(TAG_WM,
3335 "Attempted to position of non-existing app");
3336 return;
3337 }
3338
Wale Ogunwale3198da42019-10-10 14:45:03 +02003339 positionChildAt(position, child, false /* includeParents */);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003340 }
3341
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003342 void forceWindowsScaleable(boolean force) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003343 mWmService.openSurfaceTransaction();
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003344 try {
Wale Ogunwalef6192862016-09-10 13:42:30 -07003345 for (int i = mChildren.size() - 1; i >= 0; i--) {
3346 mChildren.get(i).forceWindowsScaleableInTransaction(force);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003347 }
3348 } finally {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08003349 mWmService.closeSurfaceTransaction("forceWindowsScaleable");
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07003350 }
3351 }
3352
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01003353 void setTaskDescription(TaskDescription taskDescription) {
3354 mTaskDescription = taskDescription;
3355 }
3356
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003357 void onSnapshotChanged(ActivityManager.TaskSnapshot snapshot) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02003358 mAtmService.getTaskChangeNotificationController().notifyTaskSnapshotChanged(
3359 mTaskId, snapshot);
Yunfan Chen0e7aff92018-12-05 16:35:32 -08003360 }
3361
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01003362 TaskDescription getTaskDescription() {
3363 return mTaskDescription;
3364 }
3365
Wale Ogunwalef6192862016-09-10 13:42:30 -07003366 @Override
Riddle Hsu9a8e3ae2020-03-24 15:22:48 +08003367 int getOrientation(int candidate) {
3368 return canSpecifyOrientation() ? super.getOrientation(candidate) : SCREEN_ORIENTATION_UNSET;
3369 }
3370
3371 private boolean canSpecifyOrientation() {
3372 final int windowingMode = getWindowingMode();
3373 final int activityType = getActivityType();
3374 return windowingMode == WINDOWING_MODE_FULLSCREEN
3375 || activityType == ACTIVITY_TYPE_HOME
3376 || activityType == ACTIVITY_TYPE_RECENTS
3377 || activityType == ACTIVITY_TYPE_ASSISTANT;
3378 }
3379
3380 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07003381 boolean fillsParent() {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003382 return matchParentBounds();
3383 }
3384
Jeff Changdc9c1d42020-02-11 14:57:34 +08003385 @Override
Wale Ogunwale0d465192020-01-23 19:14:44 -08003386 void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
3387 final int count = mChildren.size();
3388 boolean isLeafTask = true;
3389 if (traverseTopToBottom) {
3390 for (int i = count - 1; i >= 0; --i) {
3391 final Task child = mChildren.get(i).asTask();
3392 if (child != null) {
3393 isLeafTask = false;
3394 child.forAllLeafTasks(callback, traverseTopToBottom);
3395 }
3396 }
3397 } else {
3398 for (int i = 0; i < count; i++) {
3399 final Task child = mChildren.get(i).asTask();
3400 if (child != null) {
3401 isLeafTask = false;
3402 child.forAllLeafTasks(callback, traverseTopToBottom);
3403 }
3404 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003405 }
Wale Ogunwale0d465192020-01-23 19:14:44 -08003406 if (isLeafTask) callback.accept(this);
Wale Ogunwale51362492016-09-08 17:49:17 -07003407 }
3408
Jorim Jaggi329a5832017-01-05 18:57:12 +01003409 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003410 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08003411 super.forAllTasks(callback, traverseTopToBottom);
3412 callback.accept(this);
Jorim Jaggi51304d72017-05-17 17:25:32 +02003413 }
3414
lumarkbc0032a2019-11-01 21:38:13 +08003415 @Override
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003416 boolean forAllTasks(Function<Task, Boolean> callback) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003417 if (super.forAllTasks(callback)) return true;
lumarkbc0032a2019-11-01 21:38:13 +08003418 return callback.apply(this);
3419 }
3420
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003421 @Override
Louis Chang87ca32e2020-05-14 13:40:16 +08003422 boolean forAllLeafTasks(Function<Task, Boolean> callback) {
3423 boolean isLeafTask = true;
3424 for (int i = mChildren.size() - 1; i >= 0; --i) {
3425 final Task child = mChildren.get(i).asTask();
3426 if (child != null) {
3427 isLeafTask = false;
3428 if (child.forAllLeafTasks(callback)) {
3429 return true;
3430 }
3431 }
3432 }
3433 if (isLeafTask) {
3434 return callback.apply(this);
3435 }
3436 return false;
3437 }
3438
3439 @Override
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003440 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003441 final Task t = super.getTask(callback, traverseTopToBottom);
3442 if (t != null) return t;
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003443 return callback.test(this) ? this : null;
3444 }
3445
Jorim Jaggi50bf59c2018-03-09 17:29:48 +01003446 /**
3447 * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI
3448 * flags. See {@link WindowState#canAffectSystemUiFlags()}.
3449 */
3450 void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) {
3451 mCanAffectSystemUiFlags = canAffectSystemUiFlags;
3452 }
3453
3454 /**
3455 * @see #setCanAffectSystemUiFlags
3456 */
3457 boolean canAffectSystemUiFlags() {
3458 return mCanAffectSystemUiFlags;
3459 }
3460
chaviw87ca63a2018-03-26 14:06:17 -07003461 void dontAnimateDimExit() {
3462 mDimmer.dontAnimateExit();
3463 }
3464
Wale Ogunwale9adfe572016-09-08 20:43:58 -07003465 String getName() {
Louis Changcdec0802019-11-11 11:45:07 +08003466 return "Task=" + mTaskId;
Wale Ogunwale9adfe572016-09-08 20:43:58 -07003467 }
3468
Robert Carr18f622f2017-05-08 11:20:43 -07003469 void clearPreserveNonFloatingState() {
3470 mPreserveNonFloatingState = false;
3471 }
3472
chaviw2fb06bc2018-01-19 17:09:15 -08003473 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07003474 Dimmer getDimmer() {
chaviw51e4c2f2020-04-03 13:49:45 -07003475 // If the window is in multi-window mode, we want to dim at the Task level to ensure the dim
3476 // bounds match the area the app lives in
3477 if (inMultiWindowMode()) {
3478 return mDimmer;
3479 }
3480
3481 // If we're not at the root task level, we want to keep traversing through the parents to
3482 // find the root.
3483 // Once at the root task level, we want to check {@link #isTranslucent(ActivityRecord)}.
3484 // If true, we want to get the Dimmer from the level above since we don't want to animate
3485 // the dim with the Task.
3486 if (!isRootTask() || isTranslucent(null)) {
3487 return super.getDimmer();
3488 }
3489
Robert Carrf59b8dd2017-10-02 18:58:36 -07003490 return mDimmer;
3491 }
3492
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07003493 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07003494 void prepareSurfaces() {
3495 mDimmer.resetDimStates();
3496 super.prepareSurfaces();
3497 getDimBounds(mTmpDimBoundsRect);
chaviwe07246a2017-12-12 16:18:29 -08003498
3499 // Bounds need to be relative, as the dim layer is a child.
HEO SEUNGe10f4192019-11-21 10:21:04 +09003500 if (inFreeformWindowingMode()) {
3501 getBounds(mTmpRect);
3502 mTmpDimBoundsRect.offsetTo(mTmpDimBoundsRect.left - mTmpRect.left,
3503 mTmpDimBoundsRect.top - mTmpRect.top);
3504 } else {
3505 mTmpDimBoundsRect.offsetTo(0, 0);
3506 }
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08003507
chaviw89cc30e2020-05-19 10:36:27 -07003508 updateShadowsRadius(isFocused(), getSyncTransaction());
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08003509
Evan Roskyb6238132020-06-18 18:27:01 -07003510 if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
Robert Carrf59b8dd2017-10-02 18:58:36 -07003511 scheduleAnimation();
3512 }
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07003513 }
3514
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003515 @Override
lumark04bceb92020-03-07 00:03:33 +08003516 protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
3517 int transit, boolean isVoiceInteraction,
Issei Suzuki737b7f12020-05-25 14:54:06 +02003518 @Nullable ArrayList<WindowContainer> sources) {
lumark04bceb92020-03-07 00:03:33 +08003519 final RecentsAnimationController control = mWmService.getRecentsAnimationController();
Ming-Shin Luaa9376b2020-05-17 22:23:13 +08003520 if (control != null) {
lumark04bceb92020-03-07 00:03:33 +08003521 // We let the transition to be controlled by RecentsAnimation, and callback task's
3522 // RemoteAnimationTarget for remote runner to animate.
Ming-Shin Luaa9376b2020-05-17 22:23:13 +08003523 if (enter) {
3524 ProtoLog.d(WM_DEBUG_RECENTS_ANIMATIONS,
3525 "applyAnimationUnchecked, control: %s, task: %s, transit: %s",
3526 control, asTask(), AppTransition.appTransitionToString(transit));
Issei Suzuki737b7f12020-05-25 14:54:06 +02003527 control.addTaskToTargets(this, (type, anim) -> {
3528 for (int i = 0; i < sources.size(); ++i) {
3529 sources.get(i).onAnimationFinished(type, anim);
3530 }
3531 });
Ming-Shin Luaa9376b2020-05-17 22:23:13 +08003532 }
lumark04bceb92020-03-07 00:03:33 +08003533 } else {
Issei Suzuki737b7f12020-05-25 14:54:06 +02003534 super.applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
lumark04bceb92020-03-07 00:03:33 +08003535 }
3536 }
3537
3538 @Override
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003539 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02003540 super.dump(pw, prefix, dumpAll);
Riddle Hsu4f088b62020-06-05 00:44:26 +08003541 pw.println(prefix + "bounds=" + getBounds().toShortString());
Wale Ogunwaleb429e682016-01-06 12:36:34 -08003542 final String doublePrefix = prefix + " ";
Riddle Hsu4f088b62020-06-05 00:44:26 +08003543 for (int i = mChildren.size() - 1; i >= 0; i--) {
3544 final WindowContainer<?> child = mChildren.get(i);
3545 pw.println(prefix + "* " + child);
3546 // Only dump non-activity because full activity info is already printed by
3547 // RootWindowContainer#dumpActivities.
3548 if (child.asActivityRecord() == null) {
3549 child.dump(pw, doublePrefix, dumpAll);
3550 }
3551 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07003552 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07003553
Louis Changcdec0802019-11-11 11:45:07 +08003554 /**
Winson Chung66b08f02020-03-03 14:32:35 -08003555 * Fills in a {@link TaskInfo} with information from this task. Note that the base intent in the
3556 * task info will not include any extras or clip data.
Louis Changcdec0802019-11-11 11:45:07 +08003557 */
3558 void fillTaskInfo(TaskInfo info) {
3559 getNumRunningActivities(mReuseActivitiesReport);
3560 info.userId = mUserId;
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003561 info.stackId = getRootTaskId();
Louis Changcdec0802019-11-11 11:45:07 +08003562 info.taskId = mTaskId;
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08003563 info.displayId = getDisplayId();
Wale Ogunwale21e06482019-11-18 05:14:15 -08003564 info.isRunning = getTopNonFinishingActivity() != null;
Evan Rosky0037e5f2019-11-05 10:26:24 -08003565 final Intent baseIntent = getBaseIntent();
Riddle Hsuc5a1bd42020-02-02 19:32:17 +08003566 // Make a copy of base intent because this is like a snapshot info.
3567 // Besides, {@link RecentTasks#getRecentTasksImpl} may modify it.
Winson Chung661d8662020-04-14 14:47:32 -07003568 final int baseIntentFlags = baseIntent == null ? 0 : baseIntent.getFlags();
Winson Chung66b08f02020-03-03 14:32:35 -08003569 info.baseIntent = baseIntent == null ? new Intent() : baseIntent.cloneFilter();
Winson Chung661d8662020-04-14 14:47:32 -07003570 info.baseIntent.setFlags(baseIntentFlags);
Louis Changcdec0802019-11-11 11:45:07 +08003571 info.baseActivity = mReuseActivitiesReport.base != null
3572 ? mReuseActivitiesReport.base.intent.getComponent()
3573 : null;
3574 info.topActivity = mReuseActivitiesReport.top != null
3575 ? mReuseActivitiesReport.top.mActivityComponent
3576 : null;
3577 info.origActivity = origActivity;
3578 info.realActivity = realActivity;
3579 info.numActivities = mReuseActivitiesReport.numActivities;
3580 info.lastActiveTime = lastActiveTime;
3581 info.taskDescription = new ActivityManager.TaskDescription(getTaskDescription());
3582 info.supportsSplitScreenMultiWindow = supportsSplitScreenWindowingMode();
Louis Changcdec0802019-11-11 11:45:07 +08003583 info.configuration.setTo(getConfiguration());
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07003584 info.token = mRemoteToken.toWindowContainerToken();
Evan Roskya8fde152020-01-07 19:09:13 -08003585
3586 //TODO (AM refactor): Just use local once updateEffectiveIntent is run during all child
3587 // order changes.
3588 final Task top = getTopMostTask();
3589 info.resizeMode = top != null ? top.mResizeMode : mResizeMode;
Louis Changa009c762020-02-26 11:21:31 +08003590 info.topActivityType = top.getActivityType();
Evan Rosky889f4962020-06-12 14:49:56 -07003591 info.isResizeable = isResizeable();
Robert Carrf6690d12020-02-04 14:16:21 -08003592
Evan Rosky2af969c2020-05-08 16:26:31 +00003593 ActivityRecord rootActivity = top.getRootActivity();
3594 if (rootActivity == null || rootActivity.pictureInPictureArgs.empty()) {
Robert Carrf6690d12020-02-04 14:16:21 -08003595 info.pictureInPictureParams = null;
3596 } else {
Evan Rosky2af969c2020-05-08 16:26:31 +00003597 info.pictureInPictureParams = rootActivity.pictureInPictureArgs;
Robert Carrf6690d12020-02-04 14:16:21 -08003598 }
Hongwei Wang2e725be2020-03-10 11:01:28 -07003599 info.topActivityInfo = mReuseActivitiesReport.top != null
3600 ? mReuseActivitiesReport.top.info
3601 : null;
Louis Changcdec0802019-11-11 11:45:07 +08003602 }
3603
3604 /**
3605 * Returns a {@link TaskInfo} with information from this task.
3606 */
3607 ActivityManager.RunningTaskInfo getTaskInfo() {
3608 ActivityManager.RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
3609 fillTaskInfo(info);
3610 return info;
3611 }
3612
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09003613 boolean isTaskId(int taskId) {
3614 return mTaskId == taskId;
3615 }
3616
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003617 @Override
3618 Task asTask() {
3619 // I'm a task!
3620 return this;
3621 }
3622
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003623 /**
3624 * Returns true if the task should be visible.
3625 *
3626 * @param starting The currently starting activity or null if there is none.
3627 */
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003628 boolean shouldBeVisible(ActivityRecord starting) {
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003629 return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE;
3630 }
3631
3632 /**
3633 * Returns true if the task should be visible.
3634 *
3635 * @param starting The currently starting activity or null if there is none.
3636 */
3637 @ActivityStack.StackVisibility
3638 int getVisibility(ActivityRecord starting) {
3639 if (!isAttached() || isForceHidden()) {
3640 return STACK_VISIBILITY_INVISIBLE;
3641 }
3642
3643 boolean gotSplitScreenStack = false;
3644 boolean gotOpaqueSplitScreenPrimary = false;
3645 boolean gotOpaqueSplitScreenSecondary = false;
3646 boolean gotTranslucentFullscreen = false;
3647 boolean gotTranslucentSplitScreenPrimary = false;
3648 boolean gotTranslucentSplitScreenSecondary = false;
3649 boolean shouldBeVisible = true;
3650
3651 // This stack is only considered visible if all its parent stacks are considered visible,
3652 // so check the visibility of all ancestor stacks first.
3653 final WindowContainer parent = getParent();
3654 if (parent.asTask() != null) {
3655 final int parentVisibility = parent.asTask().getVisibility(starting);
3656 if (parentVisibility == STACK_VISIBILITY_INVISIBLE) {
3657 // Can't be visible if parent isn't visible
3658 return STACK_VISIBILITY_INVISIBLE;
3659 } else if (parentVisibility == STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT) {
3660 // Parent is behind a translucent container so the highest visibility this container
3661 // can get is that.
3662 gotTranslucentFullscreen = true;
3663 }
3664 }
3665
3666 final int windowingMode = getWindowingMode();
3667 final boolean isAssistantType = isActivityTypeAssistant();
3668 for (int i = parent.getChildCount() - 1; i >= 0; --i) {
3669 final WindowContainer wc = parent.getChildAt(i);
3670 final Task other = wc.asTask();
3671 if (other == null) continue;
3672
3673 final boolean hasRunningActivities = other.topRunningActivity() != null;
3674 if (other == this) {
3675 // Should be visible if there is no other stack occluding it, unless it doesn't
3676 // have any running activities, not starting one and not home stack.
3677 shouldBeVisible = hasRunningActivities || isInTask(starting) != null
3678 || isActivityTypeHome();
3679 break;
3680 }
3681
3682 if (!hasRunningActivities) {
3683 continue;
3684 }
3685
3686 final int otherWindowingMode = other.getWindowingMode();
3687
3688 if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) {
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003689 if (other.isTranslucent(starting)) {
3690 // Can be visible behind a translucent fullscreen stack.
3691 gotTranslucentFullscreen = true;
3692 continue;
3693 }
3694 return STACK_VISIBILITY_INVISIBLE;
3695 } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
3696 && !gotOpaqueSplitScreenPrimary) {
3697 gotSplitScreenStack = true;
3698 gotTranslucentSplitScreenPrimary = other.isTranslucent(starting);
3699 gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary;
3700 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
3701 && gotOpaqueSplitScreenPrimary) {
3702 // Can not be visible behind another opaque stack in split-screen-primary mode.
3703 return STACK_VISIBILITY_INVISIBLE;
3704 }
3705 } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
3706 && !gotOpaqueSplitScreenSecondary) {
3707 gotSplitScreenStack = true;
3708 gotTranslucentSplitScreenSecondary = other.isTranslucent(starting);
3709 gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary;
3710 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
3711 && gotOpaqueSplitScreenSecondary) {
3712 // Can not be visible behind another opaque stack in split-screen-secondary mode.
3713 return STACK_VISIBILITY_INVISIBLE;
3714 }
3715 }
3716 if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) {
3717 // Can not be visible if we are in split-screen windowing mode and both halves of
3718 // the screen are opaque.
3719 return STACK_VISIBILITY_INVISIBLE;
3720 }
3721 if (isAssistantType && gotSplitScreenStack) {
3722 // Assistant stack can't be visible behind split-screen. In addition to this not
3723 // making sense, it also works around an issue here we boost the z-order of the
3724 // assistant window surfaces in window manager whenever it is visible.
3725 return STACK_VISIBILITY_INVISIBLE;
3726 }
3727 }
3728
3729 if (!shouldBeVisible) {
3730 return STACK_VISIBILITY_INVISIBLE;
3731 }
3732
3733 // Handle cases when there can be a translucent split-screen stack on top.
3734 switch (windowingMode) {
3735 case WINDOWING_MODE_FULLSCREEN:
3736 if (gotTranslucentSplitScreenPrimary || gotTranslucentSplitScreenSecondary) {
3737 // At least one of the split-screen stacks that covers this one is translucent.
3738 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
3739 }
3740 break;
3741 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY:
3742 if (gotTranslucentSplitScreenPrimary) {
3743 // Covered by translucent primary split-screen on top.
3744 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
3745 }
3746 break;
3747 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY:
3748 if (gotTranslucentSplitScreenSecondary) {
3749 // Covered by translucent secondary split-screen on top.
3750 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
3751 }
3752 break;
3753 }
3754
3755 // Lastly - check if there is a translucent fullscreen stack on top.
3756 return gotTranslucentFullscreen ? STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT
3757 : STACK_VISIBILITY_VISIBLE;
3758 }
3759
3760 ActivityRecord isInTask(ActivityRecord r) {
3761 if (r == null) {
3762 return null;
3763 }
Louis Chang523e3e82020-05-20 16:04:31 +08003764 if (r.isDescendantOf(this)) {
Wale Ogunwale0db64ac2020-04-11 10:00:42 -07003765 return r;
3766 }
3767 return null;
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003768 }
3769
Louis Changcdec0802019-11-11 11:45:07 +08003770 void dump(PrintWriter pw, String prefix) {
3771 pw.print(prefix); pw.print("userId="); pw.print(mUserId);
3772 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
3773 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
3774 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Wale Ogunwale0d465192020-01-23 19:14:44 -08003775 pw.print(" mCallingPackage="); pw.print(mCallingPackage);
Philip P. Moltmannee295092020-02-10 08:46:26 -08003776 pw.print(" mCallingFeatureId="); pw.println(mCallingFeatureId);
Louis Changcdec0802019-11-11 11:45:07 +08003777 if (affinity != null || rootAffinity != null) {
3778 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
3779 if (affinity == null || !affinity.equals(rootAffinity)) {
3780 pw.print(" root="); pw.println(rootAffinity);
3781 } else {
3782 pw.println();
3783 }
3784 }
Garfield Tan5901e7c2020-02-07 17:12:22 -08003785 if (mWindowLayoutAffinity != null) {
3786 pw.print(prefix); pw.print("windowLayoutAffinity="); pw.println(mWindowLayoutAffinity);
3787 }
Louis Changcdec0802019-11-11 11:45:07 +08003788 if (voiceSession != null || voiceInteractor != null) {
3789 pw.print(prefix); pw.print("VOICE: session=0x");
3790 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
3791 pw.print(" interactor=0x");
3792 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
3793 }
3794 if (intent != null) {
3795 StringBuilder sb = new StringBuilder(128);
3796 sb.append(prefix); sb.append("intent={");
3797 intent.toShortString(sb, false, true, false, false);
3798 sb.append('}');
3799 pw.println(sb.toString());
3800 }
3801 if (affinityIntent != null) {
3802 StringBuilder sb = new StringBuilder(128);
3803 sb.append(prefix); sb.append("affinityIntent={");
3804 affinityIntent.toShortString(sb, false, true, false, false);
3805 sb.append('}');
3806 pw.println(sb.toString());
3807 }
3808 if (origActivity != null) {
3809 pw.print(prefix); pw.print("origActivity=");
3810 pw.println(origActivity.flattenToShortString());
3811 }
3812 if (realActivity != null) {
3813 pw.print(prefix); pw.print("mActivityComponent=");
3814 pw.println(realActivity.flattenToShortString());
3815 }
Wale Ogunwale7a8889a2019-11-16 08:23:42 -08003816 if (autoRemoveRecents || isPersistable || !isActivityTypeStandard()) {
Louis Changcdec0802019-11-11 11:45:07 +08003817 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
3818 pw.print(" isPersistable="); pw.print(isPersistable);
Louis Changcdec0802019-11-11 11:45:07 +08003819 pw.print(" activityType="); pw.println(getActivityType());
3820 }
3821 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
3822 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
3823 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
3824 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
3825 pw.print(" mReuseTask="); pw.print(mReuseTask);
3826 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
3827 }
3828 if (mAffiliatedTaskId != mTaskId || mPrevAffiliateTaskId != INVALID_TASK_ID
3829 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
3830 || mNextAffiliate != null) {
3831 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
3832 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
3833 pw.print(" (");
3834 if (mPrevAffiliate == null) {
3835 pw.print("null");
3836 } else {
3837 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
3838 }
3839 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
3840 pw.print(" (");
3841 if (mNextAffiliate == null) {
3842 pw.print("null");
3843 } else {
3844 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
3845 }
3846 pw.println(")");
3847 }
3848 pw.print(prefix); pw.print("Activities="); pw.println(mChildren);
3849 if (!askedCompatMode || !inRecents || !isAvailable) {
3850 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
3851 pw.print(" inRecents="); pw.print(inRecents);
3852 pw.print(" isAvailable="); pw.println(isAvailable);
3853 }
3854 if (lastDescription != null) {
3855 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
3856 }
3857 if (mRootProcess != null) {
3858 pw.print(prefix); pw.print("mRootProcess="); pw.println(mRootProcess);
3859 }
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003860 pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" stackId=" + getRootTaskId());
Dianne Hackborn9106f2a2020-04-30 16:23:20 -07003861 pw.print(prefix); pw.print("mHasBeenVisible="); pw.println(getHasBeenVisible());
3862 pw.print(prefix); pw.print("mResizeMode=");
3863 pw.print(ActivityInfo.resizeModeToString(mResizeMode));
3864 pw.print(" mSupportsPictureInPicture="); pw.print(mSupportsPictureInPicture);
3865 pw.print(" isResizeable="); pw.println(isResizeable());
3866 pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime);
Louis Changcdec0802019-11-11 11:45:07 +08003867 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
3868 }
3869
3870 @Override
3871 public String toString() {
3872 StringBuilder sb = new StringBuilder(128);
3873 if (stringName != null) {
3874 sb.append(stringName);
3875 sb.append(" U=");
3876 sb.append(mUserId);
3877 sb.append(" StackId=");
Wale Ogunwale1ebcd8e2020-01-21 11:27:03 -08003878 sb.append(getRootTaskId());
Louis Changcdec0802019-11-11 11:45:07 +08003879 sb.append(" sz=");
3880 sb.append(getChildCount());
3881 sb.append('}');
3882 return sb.toString();
3883 }
3884 sb.append("Task{");
3885 sb.append(Integer.toHexString(System.identityHashCode(this)));
3886 sb.append(" #");
3887 sb.append(mTaskId);
Wale Ogunwale8f93b642019-12-26 12:10:52 -08003888 sb.append(" visible=" + shouldBeVisible(null /* starting */));
3889 sb.append(" type=" + activityTypeToString(getActivityType()));
3890 sb.append(" mode=" + windowingModeToString(getWindowingMode()));
3891 sb.append(" translucent=" + isTranslucent(null /* starting */));
Louis Changcdec0802019-11-11 11:45:07 +08003892 if (affinity != null) {
3893 sb.append(" A=");
3894 sb.append(affinity);
Evan Rosky0037e5f2019-11-05 10:26:24 -08003895 } else if (intent != null && intent.getComponent() != null) {
Louis Changcdec0802019-11-11 11:45:07 +08003896 sb.append(" I=");
3897 sb.append(intent.getComponent().flattenToShortString());
3898 } else if (affinityIntent != null && affinityIntent.getComponent() != null) {
3899 sb.append(" aI=");
3900 sb.append(affinityIntent.getComponent().flattenToShortString());
3901 } else {
3902 sb.append(" ??");
3903 }
3904 stringName = sb.toString();
3905 return toString();
3906 }
3907
Louis Changcdec0802019-11-11 11:45:07 +08003908 /** @see #getNumRunningActivities(TaskActivitiesReport) */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003909 static class TaskActivitiesReport implements Consumer<ActivityRecord> {
Louis Changcdec0802019-11-11 11:45:07 +08003910 int numRunning;
3911 int numActivities;
3912 ActivityRecord top;
3913 ActivityRecord base;
3914
3915 void reset() {
3916 numRunning = numActivities = 0;
3917 top = base = null;
3918 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003919
3920 @Override
3921 public void accept(ActivityRecord r) {
3922 if (r.finishing) {
3923 return;
3924 }
3925
3926 base = r;
3927
3928 // Increment the total number of non-finishing activities
3929 numActivities++;
3930
3931 if (top == null || (top.isState(ActivityState.INITIALIZING))) {
3932 top = r;
3933 // Reset the number of running activities until we hit the first non-initializing
3934 // activity
3935 numRunning = 0;
3936 }
3937 if (r.attachedToProcess()) {
3938 // Increment the number of actually running activities
3939 numRunning++;
3940 }
3941 }
Louis Changcdec0802019-11-11 11:45:07 +08003942 }
3943
3944 /**
3945 * Saves this {@link Task} to XML using given serializer.
3946 */
Wale Ogunwalea38654f2019-11-17 20:37:15 -08003947 void saveToXml(XmlSerializer out) throws Exception {
Louis Changcdec0802019-11-11 11:45:07 +08003948 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
3949
3950 out.attribute(null, ATTR_TASKID, String.valueOf(mTaskId));
3951 if (realActivity != null) {
3952 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
3953 }
3954 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
3955 if (origActivity != null) {
3956 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
3957 }
3958 // Write affinity, and root affinity if it is different from affinity.
3959 // We use the special string "@" for a null root affinity, so we can identify
3960 // later whether we were given a root affinity or should just make it the
3961 // same as the affinity.
3962 if (affinity != null) {
3963 out.attribute(null, ATTR_AFFINITY, affinity);
3964 if (!affinity.equals(rootAffinity)) {
3965 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3966 }
3967 } else if (rootAffinity != null) {
3968 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
3969 }
Garfield Tan5901e7c2020-02-07 17:12:22 -08003970 if (mWindowLayoutAffinity != null) {
3971 out.attribute(null, ATTR_WINDOW_LAYOUT_AFFINITY, mWindowLayoutAffinity);
3972 }
Louis Changcdec0802019-11-11 11:45:07 +08003973 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
3974 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
3975 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
3976 out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
3977 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
3978 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
3979 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
3980 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
3981 if (lastDescription != null) {
3982 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
3983 }
3984 if (getTaskDescription() != null) {
3985 getTaskDescription().saveToXml(out);
3986 }
3987 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
3988 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
3989 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
3990 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
3991 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
3992 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
Philip P. Moltmannee295092020-02-10 08:46:26 -08003993 out.attribute(null, ATTR_CALLING_FEATURE_ID,
3994 mCallingFeatureId == null ? "" : mCallingFeatureId);
Louis Changcdec0802019-11-11 11:45:07 +08003995 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
3996 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
3997 String.valueOf(mSupportsPictureInPicture));
3998 if (mLastNonFullscreenBounds != null) {
3999 out.attribute(
4000 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
4001 }
4002 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
4003 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
4004 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
4005
4006 if (affinityIntent != null) {
4007 out.startTag(null, TAG_AFFINITYINTENT);
4008 affinityIntent.saveToXml(out);
4009 out.endTag(null, TAG_AFFINITYINTENT);
4010 }
4011
4012 if (intent != null) {
4013 out.startTag(null, TAG_INTENT);
4014 intent.saveToXml(out);
4015 out.endTag(null, TAG_INTENT);
4016 }
4017
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004018 sTmpException = null;
4019 final PooledFunction f = PooledLambda.obtainFunction(Task::saveActivityToXml,
4020 PooledLambda.__(ActivityRecord.class), getBottomMostActivity(), out);
4021 forAllActivities(f);
4022 f.recycle();
4023 if (sTmpException != null) {
4024 throw sTmpException;
4025 }
4026 }
4027
4028 private static boolean saveActivityToXml(
4029 ActivityRecord r, ActivityRecord first, XmlSerializer out) {
4030 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable()
4031 || ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
4032 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT)
4033 && r != first) {
4034 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
4035 return true;
4036 }
4037 try {
Louis Changcdec0802019-11-11 11:45:07 +08004038 out.startTag(null, TAG_ACTIVITY);
4039 r.saveToXml(out);
4040 out.endTag(null, TAG_ACTIVITY);
Wale Ogunwalea38654f2019-11-17 20:37:15 -08004041 return false;
4042 } catch (Exception e) {
4043 sTmpException = e;
4044 return true;
Louis Changcdec0802019-11-11 11:45:07 +08004045 }
4046 }
4047
Louis Changcdec0802019-11-11 11:45:07 +08004048 static Task restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
4049 throws IOException, XmlPullParserException {
Garfield Tan5044a152020-05-01 14:13:35 -07004050 Intent intent = null;
4051 Intent affinityIntent = null;
4052 ArrayList<ActivityRecord> activities = new ArrayList<>();
4053 ComponentName realActivity = null;
4054 boolean realActivitySuspended = false;
4055 ComponentName origActivity = null;
4056 String affinity = null;
4057 String rootAffinity = null;
4058 boolean hasRootAffinity = false;
4059 String windowLayoutAffinity = null;
4060 boolean rootHasReset = false;
4061 boolean autoRemoveRecents = false;
4062 boolean askedCompatMode = false;
4063 int taskType = 0;
4064 int userId = 0;
4065 boolean userSetupComplete = true;
4066 int effectiveUid = -1;
4067 String lastDescription = null;
4068 long lastTimeOnTop = 0;
4069 boolean neverRelinquishIdentity = true;
4070 int taskId = INVALID_TASK_ID;
4071 final int outerDepth = in.getDepth();
4072 TaskDescription taskDescription = new TaskDescription();
4073 int taskAffiliation = INVALID_TASK_ID;
4074 int taskAffiliationColor = 0;
4075 int prevTaskId = INVALID_TASK_ID;
4076 int nextTaskId = INVALID_TASK_ID;
4077 int callingUid = -1;
4078 String callingPackage = "";
4079 String callingFeatureId = null;
4080 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
4081 boolean supportsPictureInPicture = false;
4082 Rect lastNonFullscreenBounds = null;
4083 int minWidth = INVALID_MIN_SIZE;
4084 int minHeight = INVALID_MIN_SIZE;
4085 int persistTaskVersion = 0;
Louis Changcdec0802019-11-11 11:45:07 +08004086
Garfield Tan5044a152020-05-01 14:13:35 -07004087 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
4088 final String attrName = in.getAttributeName(attrNdx);
4089 final String attrValue = in.getAttributeValue(attrNdx);
4090 if (TaskPersister.DEBUG) {
4091 Slog.d(TaskPersister.TAG, "Task: attribute name=" + attrName + " value="
4092 + attrValue);
Louis Changcdec0802019-11-11 11:45:07 +08004093 }
Garfield Tan5044a152020-05-01 14:13:35 -07004094 switch (attrName) {
4095 case ATTR_TASKID:
4096 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
4097 break;
4098 case ATTR_REALACTIVITY:
4099 realActivity = ComponentName.unflattenFromString(attrValue);
4100 break;
4101 case ATTR_REALACTIVITY_SUSPENDED:
4102 realActivitySuspended = Boolean.valueOf(attrValue);
4103 break;
4104 case ATTR_ORIGACTIVITY:
4105 origActivity = ComponentName.unflattenFromString(attrValue);
4106 break;
4107 case ATTR_AFFINITY:
4108 affinity = attrValue;
4109 break;
4110 case ATTR_ROOT_AFFINITY:
4111 rootAffinity = attrValue;
4112 hasRootAffinity = true;
4113 break;
4114 case ATTR_WINDOW_LAYOUT_AFFINITY:
4115 windowLayoutAffinity = attrValue;
4116 break;
4117 case ATTR_ROOTHASRESET:
4118 rootHasReset = Boolean.parseBoolean(attrValue);
4119 break;
4120 case ATTR_AUTOREMOVERECENTS:
4121 autoRemoveRecents = Boolean.parseBoolean(attrValue);
4122 break;
4123 case ATTR_ASKEDCOMPATMODE:
4124 askedCompatMode = Boolean.parseBoolean(attrValue);
4125 break;
4126 case ATTR_USERID:
4127 userId = Integer.parseInt(attrValue);
4128 break;
4129 case ATTR_USER_SETUP_COMPLETE:
4130 userSetupComplete = Boolean.parseBoolean(attrValue);
4131 break;
4132 case ATTR_EFFECTIVE_UID:
4133 effectiveUid = Integer.parseInt(attrValue);
4134 break;
4135 case ATTR_TASKTYPE:
4136 taskType = Integer.parseInt(attrValue);
4137 break;
4138 case ATTR_LASTDESCRIPTION:
4139 lastDescription = attrValue;
4140 break;
4141 case ATTR_LASTTIMEMOVED:
4142 lastTimeOnTop = Long.parseLong(attrValue);
4143 break;
4144 case ATTR_NEVERRELINQUISH:
4145 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
4146 break;
4147 case ATTR_TASK_AFFILIATION:
4148 taskAffiliation = Integer.parseInt(attrValue);
4149 break;
4150 case ATTR_PREV_AFFILIATION:
4151 prevTaskId = Integer.parseInt(attrValue);
4152 break;
4153 case ATTR_NEXT_AFFILIATION:
4154 nextTaskId = Integer.parseInt(attrValue);
4155 break;
4156 case ATTR_TASK_AFFILIATION_COLOR:
4157 taskAffiliationColor = Integer.parseInt(attrValue);
4158 break;
4159 case ATTR_CALLING_UID:
4160 callingUid = Integer.parseInt(attrValue);
4161 break;
4162 case ATTR_CALLING_PACKAGE:
4163 callingPackage = attrValue;
4164 break;
4165 case ATTR_CALLING_FEATURE_ID:
4166 callingFeatureId = attrValue;
4167 break;
4168 case ATTR_RESIZE_MODE:
4169 resizeMode = Integer.parseInt(attrValue);
4170 break;
4171 case ATTR_SUPPORTS_PICTURE_IN_PICTURE:
4172 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
4173 break;
4174 case ATTR_NON_FULLSCREEN_BOUNDS:
4175 lastNonFullscreenBounds = Rect.unflattenFromString(attrValue);
4176 break;
4177 case ATTR_MIN_WIDTH:
4178 minWidth = Integer.parseInt(attrValue);
4179 break;
4180 case ATTR_MIN_HEIGHT:
4181 minHeight = Integer.parseInt(attrValue);
4182 break;
4183 case ATTR_PERSIST_TASK_VERSION:
4184 persistTaskVersion = Integer.parseInt(attrValue);
4185 break;
4186 default:
4187 if (!attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
4188 Slog.w(TAG, "Task: Unknown attribute=" + attrName);
Louis Changcdec0802019-11-11 11:45:07 +08004189 }
Louis Changcdec0802019-11-11 11:45:07 +08004190 }
Garfield Tan5044a152020-05-01 14:13:35 -07004191 }
4192 taskDescription.restoreFromXml(in);
4193
4194 int event;
4195 while (((event = in.next()) != XmlPullParser.END_DOCUMENT)
4196 && (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
4197 if (event == XmlPullParser.START_TAG) {
4198 final String name = in.getName();
4199 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "Task: START_TAG name=" + name);
4200 if (TAG_AFFINITYINTENT.equals(name)) {
4201 affinityIntent = Intent.restoreFromXml(in);
4202 } else if (TAG_INTENT.equals(name)) {
4203 intent = Intent.restoreFromXml(in);
4204 } else if (TAG_ACTIVITY.equals(name)) {
4205 ActivityRecord activity =
4206 ActivityRecord.restoreFromXml(in, stackSupervisor);
4207 if (TaskPersister.DEBUG) {
4208 Slog.d(TaskPersister.TAG, "Task: activity=" + activity);
Louis Changcdec0802019-11-11 11:45:07 +08004209 }
Garfield Tan5044a152020-05-01 14:13:35 -07004210 if (activity != null) {
4211 activities.add(activity);
4212 }
4213 } else {
4214 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
4215 XmlUtils.skipCurrentTag(in);
Louis Changcdec0802019-11-11 11:45:07 +08004216 }
4217 }
Garfield Tan5044a152020-05-01 14:13:35 -07004218 }
4219 if (!hasRootAffinity) {
4220 rootAffinity = affinity;
4221 } else if ("@".equals(rootAffinity)) {
4222 rootAffinity = null;
4223 }
4224 if (effectiveUid <= 0) {
4225 Intent checkIntent = intent != null ? intent : affinityIntent;
4226 effectiveUid = 0;
4227 if (checkIntent != null) {
4228 IPackageManager pm = AppGlobals.getPackageManager();
4229 try {
4230 ApplicationInfo ai = pm.getApplicationInfo(
4231 checkIntent.getComponent().getPackageName(),
4232 PackageManager.MATCH_UNINSTALLED_PACKAGES
4233 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
4234 if (ai != null) {
4235 effectiveUid = ai.uid;
4236 }
4237 } catch (RemoteException e) {
4238 }
Louis Changcdec0802019-11-11 11:45:07 +08004239 }
Garfield Tan5044a152020-05-01 14:13:35 -07004240 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
4241 + ": effectiveUid=" + effectiveUid);
Louis Changcdec0802019-11-11 11:45:07 +08004242 }
4243
Garfield Tan5044a152020-05-01 14:13:35 -07004244 if (persistTaskVersion < 1) {
4245 // We need to convert the resize mode of home activities saved before version one if
4246 // they are marked as RESIZE_MODE_RESIZEABLE to
4247 // RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION since we didn't have that differentiation
4248 // before version 1 and the system didn't resize home activities before then.
4249 if (taskType == 1 /* old home type */ && resizeMode == RESIZE_MODE_RESIZEABLE) {
4250 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
4251 }
4252 } else {
4253 // This activity has previously marked itself explicitly as both resizeable and
4254 // supporting picture-in-picture. Since there is no longer a requirement for
4255 // picture-in-picture activities to be resizeable, we can mark this simply as
4256 // resizeable and supporting picture-in-picture separately.
4257 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
4258 resizeMode = RESIZE_MODE_RESIZEABLE;
4259 supportsPictureInPicture = true;
4260 }
Louis Changcdec0802019-11-11 11:45:07 +08004261 }
Garfield Tan5044a152020-05-01 14:13:35 -07004262
4263 final Task task = new ActivityStack(stackSupervisor.mService, taskId, intent,
4264 affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
4265 autoRemoveRecents, askedCompatMode, userId, effectiveUid, lastDescription,
4266 lastTimeOnTop, neverRelinquishIdentity, taskDescription, taskAffiliation,
4267 prevTaskId, nextTaskId, taskAffiliationColor, callingUid, callingPackage,
4268 callingFeatureId, resizeMode, supportsPictureInPicture, realActivitySuspended,
4269 userSetupComplete, minWidth, minHeight, null /*ActivityInfo*/,
4270 null /*_voiceSession*/, null /*_voiceInteractor*/, null /* stack */);
4271 task.mLastNonFullscreenBounds = lastNonFullscreenBounds;
4272 task.setBounds(lastNonFullscreenBounds);
4273 task.mWindowLayoutAffinity = windowLayoutAffinity;
4274
4275 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4276 task.addChild(activities.get(activityNdx));
4277 }
4278
4279 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
4280 return task;
Robert Carrf59b8dd2017-10-02 18:58:36 -07004281 }
Robert Carr8a2f9132019-11-11 15:03:15 -08004282
Wale Ogunwaledec34082020-03-22 09:45:00 -07004283 @Override
4284 boolean isOrganized() {
Wale Ogunwale465b1e12020-03-31 12:15:51 -07004285 return mTaskOrganizer != null;
Robert Carr8a2f9132019-11-11 15:03:15 -08004286 }
4287
4288 @Override
4289 protected void reparentSurfaceControl(SurfaceControl.Transaction t, SurfaceControl newParent) {
4290 /**
Louis Changa009c762020-02-26 11:21:31 +08004291 * Avoid reparenting SurfaceControl of the organized tasks that are always on top, since
4292 * the surfaces should be controlled by the organizer itself, like bubbles.
Robert Carr8a2f9132019-11-11 15:03:15 -08004293 */
Louis Changa009c762020-02-26 11:21:31 +08004294 if (isOrganized() && isAlwaysOnTop()) {
Robert Carr8a2f9132019-11-11 15:03:15 -08004295 return;
4296 }
4297 super.reparentSurfaceControl(t, newParent);
4298 }
4299
Robert Carrde96c8a2020-03-24 15:22:21 -07004300 void setHasBeenVisible(boolean hasBeenVisible) {
Winson Chung8b5d23a2020-04-06 19:23:23 -07004301 final boolean prevHasBeenVisible = mHasBeenVisible;
Robert Carrde96c8a2020-03-24 15:22:21 -07004302 mHasBeenVisible = hasBeenVisible;
4303 if (hasBeenVisible) {
Winson Chung8b5d23a2020-04-06 19:23:23 -07004304 // If the task is not yet visible when it is added to the task organizer, then we should
4305 // hide it to allow the task organizer to show it when it is properly reparented. We
4306 // skip this for tasks created by the organizer because they can synchronously update
4307 // the leash before new children are added to the task.
4308 if (!mCreatedByOrganizer && mTaskOrganizer != null && !prevHasBeenVisible) {
chaviw89cc30e2020-05-19 10:36:27 -07004309 getSyncTransaction().hide(getSurfaceControl());
Winson Chung8b5d23a2020-04-06 19:23:23 -07004310 commitPendingTransaction();
4311 }
4312
Robert Carrde96c8a2020-03-24 15:22:21 -07004313 sendTaskAppeared();
4314 if (!isRootTask()) {
4315 getRootTask().setHasBeenVisible(true);
4316 }
4317 }
4318 }
4319
4320 boolean getHasBeenVisible() {
4321 return mHasBeenVisible;
4322 }
4323
chaviwda7b3c22020-04-24 11:25:08 -07004324 /** In the case that these conditions are true, we want to send the Task to the organizer:
4325 * 1. An organizer has been set
4326 * 2. The Task was created by the organizer
4327 * or
4328 * 2a. We have a SurfaceControl
4329 * 2b. We have finished drawing
Robert Carrde96c8a2020-03-24 15:22:21 -07004330 * Any time any of these conditions are updated, the updating code should call
4331 * sendTaskAppeared.
4332 */
Louis Chang9d35a3a2020-04-06 17:23:02 +08004333 boolean taskAppearedReady() {
chaviwda7b3c22020-04-24 11:25:08 -07004334 if (mTaskOrganizer == null) {
4335 return false;
4336 }
4337
4338 if (mCreatedByOrganizer) {
4339 return true;
4340 }
4341
4342 return mSurfaceControl != null && getHasBeenVisible();
Robert Carrde96c8a2020-03-24 15:22:21 -07004343 }
4344
Robert Carr8a2f9132019-11-11 15:03:15 -08004345 private void sendTaskAppeared() {
Louis Chang9d35a3a2020-04-06 17:23:02 +08004346 if (mTaskOrganizer != null) {
Robert Carr8a2f9132019-11-11 15:03:15 -08004347 mAtmService.mTaskOrganizerController.onTaskAppeared(mTaskOrganizer, this);
4348 }
4349 }
4350
chaviwda7b3c22020-04-24 11:25:08 -07004351 private void sendTaskVanished(ITaskOrganizer organizer) {
4352 if (organizer != null) {
4353 mAtmService.mTaskOrganizerController.onTaskVanished(organizer, this);
Robert Carr8a2f9132019-11-11 15:03:15 -08004354 }
4355 }
4356
Wale Ogunwale465b1e12020-03-31 12:15:51 -07004357 @VisibleForTesting
Evan Roskyf64f5da2020-03-16 13:47:48 -07004358 boolean setTaskOrganizer(ITaskOrganizer organizer) {
Evan Rosky0037e5f2019-11-05 10:26:24 -08004359 if (mTaskOrganizer == organizer) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07004360 return false;
Evan Rosky0037e5f2019-11-05 10:26:24 -08004361 }
chaviwda7b3c22020-04-24 11:25:08 -07004362
4363 ITaskOrganizer previousOrganizer = mTaskOrganizer;
4364 // Update the new task organizer before calling sendTaskVanished since it could result in
4365 // a new SurfaceControl getting created that would notify the old organizer about it.
Robert Carr8a2f9132019-11-11 15:03:15 -08004366 mTaskOrganizer = organizer;
chaviwda7b3c22020-04-24 11:25:08 -07004367 // Let the old organizer know it has lost control.
4368 sendTaskVanished(previousOrganizer);
Robert Carr8a2f9132019-11-11 15:03:15 -08004369
Wale Ogunwale20ab6d42020-04-13 07:30:59 -07004370 if (mTaskOrganizer != null) {
4371 sendTaskAppeared();
4372 } else {
4373 // No longer managed by any organizer.
4374 mTaskAppearedSent = false;
4375 mLastTaskOrganizerWindowingMode = -1;
4376 setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, false /* set */);
4377 if (mCreatedByOrganizer) {
4378 removeImmediately();
4379 }
Louis Changa009c762020-02-26 11:21:31 +08004380 }
Wale Ogunwale20ab6d42020-04-13 07:30:59 -07004381
4382 return true;
Winson Chung77338ab2020-03-09 16:32:34 -07004383 }
4384
4385 /**
4386 * Called when the task state changes (ie. from windowing mode change) an the task organizer
4387 * state should also be updated.
4388 *
4389 * @param forceUpdate Updates the task organizer to the one currently specified in the task
4390 * org controller for the task's windowing mode, ignoring the cached
4391 * windowing mode checks.
Evan Roskyf64f5da2020-03-16 13:47:48 -07004392 * @return {@code true} if task organizer changed.
Winson Chung77338ab2020-03-09 16:32:34 -07004393 */
Evan Roskyf64f5da2020-03-16 13:47:48 -07004394 boolean updateTaskOrganizerState(boolean forceUpdate) {
Winson Chung77338ab2020-03-09 16:32:34 -07004395 if (!isRootTask()) {
Evan Roskyf64f5da2020-03-16 13:47:48 -07004396 return false;
Winson Chung77338ab2020-03-09 16:32:34 -07004397 }
4398
4399 final int windowingMode = getWindowingMode();
4400 if (!forceUpdate && windowingMode == mLastTaskOrganizerWindowingMode) {
4401 // If our windowing mode hasn't actually changed, then just stick
4402 // with our old organizer. This lets us implement the semantic
4403 // where SysUI can continue to manage it's old tasks
4404 // while CTS temporarily takes over the registration.
Evan Roskyf64f5da2020-03-16 13:47:48 -07004405 return false;
Winson Chung77338ab2020-03-09 16:32:34 -07004406 }
4407 /*
4408 * Different windowing modes may be managed by different task organizers. If
4409 * getTaskOrganizer returns null, we still call setTaskOrganizer to
4410 * make sure we clear it.
4411 */
4412 final ITaskOrganizer org =
4413 mWmService.mAtmService.mTaskOrganizerController.getTaskOrganizer(windowingMode);
Evan Roskyf64f5da2020-03-16 13:47:48 -07004414 final boolean result = setTaskOrganizer(org);
Winson Chung77338ab2020-03-09 16:32:34 -07004415 mLastTaskOrganizerWindowingMode = windowingMode;
Evan Roskyf64f5da2020-03-16 13:47:48 -07004416 return result;
Robert Carr8a2f9132019-11-11 15:03:15 -08004417 }
4418
4419 @Override
4420 void setSurfaceControl(SurfaceControl sc) {
4421 super.setSurfaceControl(sc);
4422 // If the TaskOrganizer was set before we created the SurfaceControl, we need to
4423 // emit the callbacks now.
4424 sendTaskAppeared();
4425 }
4426
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004427 /**
4428 * @return true if the task is currently focused.
4429 */
4430 private boolean isFocused() {
4431 if (mDisplayContent == null || mDisplayContent.mCurrentFocus == null) {
4432 return false;
4433 }
4434 return mDisplayContent.mCurrentFocus.getTask() == this;
4435 }
4436
4437 /**
Vishnu Nairae3b0772020-03-19 16:55:25 -07004438 * @return true if the task is visible and has at least one visible child.
4439 */
4440 private boolean hasVisibleChildren() {
4441 if (!isAttached() || isForceHidden()) {
4442 return false;
4443 }
4444
4445 return getActivity(ActivityRecord::isVisible) != null;
4446 }
4447
4448 /**
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004449 * @return the desired shadow radius in pixels for the current task.
4450 */
4451 private float getShadowRadius(boolean taskIsFocused) {
Vishnu Nairae3b0772020-03-19 16:55:25 -07004452 int elevation = 0;
4453
4454 // Get elevation for a specific windowing mode.
4455 if (inPinnedWindowingMode()) {
4456 elevation = PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
Garfield Tan7e1cb5c2020-04-10 15:21:23 -07004457 } else if (inFreeformWindowingMode()) {
Vishnu Nairae3b0772020-03-19 16:55:25 -07004458 elevation = taskIsFocused
4459 ? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
4460 } else {
4461 // For all other windowing modes, do not draw a shadow.
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004462 return 0;
4463 }
4464
Vishnu Nairae3b0772020-03-19 16:55:25 -07004465 // If the task has no visible children, do not draw a shadow.
4466 if (!hasVisibleChildren()) {
4467 return 0;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004468 }
4469
Vishnu Nairae3b0772020-03-19 16:55:25 -07004470 return dipToPixel(elevation, getDisplayContent().getDisplayMetrics());
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004471 }
4472
4473 /**
4474 * Update the length of the shadow if needed based on windowing mode and task focus state.
4475 */
4476 private void updateShadowsRadius(boolean taskIsFocused,
4477 SurfaceControl.Transaction pendingTransaction) {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08004478 if (!mWmService.mRenderShadowsInCompositor || !isRootTask()) return;
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004479
4480 final float newShadowRadius = getShadowRadius(taskIsFocused);
4481 if (mShadowRadius != newShadowRadius) {
4482 mShadowRadius = newShadowRadius;
4483 pendingTransaction.setShadowRadius(getSurfaceControl(), mShadowRadius);
4484 }
4485 }
4486
4487 /**
4488 * Called on the task of a window which gained or lost focus.
4489 * @param hasFocus
4490 */
4491 void onWindowFocusChanged(boolean hasFocus) {
chaviw89cc30e2020-05-19 10:36:27 -07004492 updateShadowsRadius(hasFocus, getSyncTransaction());
Vishnu Nairf6ef1c72020-01-23 16:28:33 -08004493 }
Robert Carrf6690d12020-02-04 14:16:21 -08004494
Evan Rosky2af969c2020-05-08 16:26:31 +00004495 void onPictureInPictureParamsChanged() {
Winson Chung1df39e22020-04-09 14:30:55 -07004496 if (isOrganized()) {
4497 mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(this, true /* force */);
4498 }
Robert Carrf6690d12020-02-04 14:16:21 -08004499 }
Robert Carr711e7052020-02-19 11:14:33 -08004500
4501 /**
4502 * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this
4503 * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy
4504 * to resize, and it will defer the transaction until that resize frame completes.
4505 */
4506 void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t) {
Evan Rosky0c86ced2020-05-20 13:38:34 -07004507 setMainWindowSizeChangeTransaction(t, this);
4508 }
4509
4510 private void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t, Task origin) {
4511 // This is only meaningful on an activity's task, so put it on the top one.
4512 ActivityRecord topActivity = getTopNonFinishingActivity();
4513 Task leaf = topActivity != null ? topActivity.getTask() : null;
4514 if (leaf == null) {
4515 return;
4516 }
4517 if (leaf != this) {
4518 leaf.setMainWindowSizeChangeTransaction(t, origin);
4519 return;
4520 }
Robert Carr711e7052020-02-19 11:14:33 -08004521 mMainWindowSizeChangeTransaction = t;
Evan Rosky0c86ced2020-05-20 13:38:34 -07004522 mMainWindowSizeChangeTask = t == null ? null : origin;
Robert Carr711e7052020-02-19 11:14:33 -08004523 }
4524
4525 SurfaceControl.Transaction getMainWindowSizeChangeTransaction() {
4526 return mMainWindowSizeChangeTransaction;
4527 }
Vishnu Nairdddc9f52020-03-09 09:37:27 -07004528
Evan Rosky0c86ced2020-05-20 13:38:34 -07004529 Task getMainWindowSizeChangeTask() {
4530 return mMainWindowSizeChangeTask;
4531 }
4532
Robert Carr2bed6212020-02-20 16:55:07 -08004533 void setActivityWindowingMode(int windowingMode) {
4534 PooledConsumer c = PooledLambda.obtainConsumer(ActivityRecord::setWindowingMode,
chaviw6630d852020-04-15 19:06:56 -07004535 PooledLambda.__(ActivityRecord.class), windowingMode);
Robert Carr2bed6212020-02-20 16:55:07 -08004536 forAllActivities(c);
4537 c.recycle();
4538 }
4539
Robert Carrf6878a42019-12-18 02:13:12 -08004540 /**
4541 * Sets/unsets the forced-hidden state flag for this task depending on {@param set}.
4542 * @return Whether the force hidden state changed
4543 */
4544 boolean setForceHidden(int flags, boolean set) {
4545 int newFlags = mForceHiddenFlags;
4546 if (set) {
4547 newFlags |= flags;
4548 } else {
4549 newFlags &= ~flags;
4550 }
4551 if (mForceHiddenFlags == newFlags) {
4552 return false;
4553 }
Winson Chungb5ce37c2020-04-22 10:08:28 -07004554 final boolean wasHidden = isForceHidden();
Robert Carrf6878a42019-12-18 02:13:12 -08004555 mForceHiddenFlags = newFlags;
Winson Chungb5ce37c2020-04-22 10:08:28 -07004556 if (wasHidden && isFocusableAndVisible()) {
4557 // The change in force-hidden state will change visibility without triggering a stack
4558 // order change, so we should reset the preferred top focusable stack to ensure it's not
4559 // used if a new activity is started from this task.
4560 getDisplayArea().resetPreferredTopFocusableStackIfBelow(this);
4561 }
Robert Carrf6878a42019-12-18 02:13:12 -08004562 return true;
4563 }
4564
4565 /**
4566 * Returns whether this task is currently forced to be hidden for any reason.
4567 */
4568 protected boolean isForceHidden() {
4569 return mForceHiddenFlags != 0;
4570 }
4571
Vishnu Nairdddc9f52020-03-09 09:37:27 -07004572 @Override
4573 long getProtoFieldId() {
4574 return TASK;
4575 }
Robert Carr2bed6212020-02-20 16:55:07 -08004576
Craig Mautnerb1fd65c02013-02-05 13:34:57 -08004577}