1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
20 import static android.app.ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
21 import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
22 import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
23 import static android.app.ActivityOptions.ANIM_CUSTOM;
24 import static android.app.ActivityOptions.ANIM_NONE;
25 import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS;
26 import static android.app.ActivityOptions.ANIM_REMOTE_ANIMATION;
27 import static android.app.ActivityOptions.ANIM_SCALE_UP;
28 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
29 import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
30 import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP;
31 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
32 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
33 import static android.app.ActivityOptions.ANIM_UNDEFINED;
34 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
35 import static android.app.AppOpsManager.MODE_ALLOWED;
36 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
37 import static android.app.WaitResult.INVALID_DELAY;
38 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
39 import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
40 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
41 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
42 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
43 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
44 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
45 import static android.app.WindowConfiguration.activityTypeToString;
46 import static android.content.Intent.ACTION_MAIN;
47 import static android.content.Intent.CATEGORY_HOME;
48 import static android.content.Intent.CATEGORY_LAUNCHER;
49 import static android.content.Intent.CATEGORY_SECONDARY_HOME;
50 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
51 import static android.content.Intent.FLAG_ACTIVITY_NO_HISTORY;
52 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
53 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
54 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
55 import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
56 import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
57 import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
58 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
59 import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
60 import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
61 import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
62 import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS;
63 import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY;
64 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
65 import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
66 import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
67 import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
68 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
69 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
70 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
71 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
72 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
73 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
74 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
75 import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
76 import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
77 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
78 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
79 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
80 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
81 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
82 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
83 import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
84 import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
85 import static android.content.res.Configuration.EMPTY;
86 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
87 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
88 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
89 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
90 import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
91 import static android.os.Build.VERSION_CODES.HONEYCOMB;
92 import static android.os.Build.VERSION_CODES.O;
93 import static android.os.Process.SYSTEM_UID;
94 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
95 import static android.view.Display.COLOR_MODE_DEFAULT;
96 import static android.view.Display.INVALID_DISPLAY;
97 import static android.view.Surface.ROTATION_270;
98 import static android.view.Surface.ROTATION_90;
99 import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
100 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
101 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
102 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
103 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
104 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
105 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
106 import static android.view.WindowManager.TRANSIT_TASK_CLOSE;
107 import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND;
108 import static android.view.WindowManager.TRANSIT_UNSET;
109 
110 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
111 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
112 import static com.android.server.wm.ActivityRecordProto.ALL_DRAWN;
113 import static com.android.server.wm.ActivityRecordProto.APP_STOPPED;
114 import static com.android.server.wm.ActivityRecordProto.CLIENT_VISIBLE;
115 import static com.android.server.wm.ActivityRecordProto.DEFER_HIDING_CLIENT;
116 import static com.android.server.wm.ActivityRecordProto.FILLS_PARENT;
117 import static com.android.server.wm.ActivityRecordProto.FRONT_OF_TASK;
118 import static com.android.server.wm.ActivityRecordProto.FROZEN_BOUNDS;
119 import static com.android.server.wm.ActivityRecordProto.IDENTIFIER;
120 import static com.android.server.wm.ActivityRecordProto.IS_ANIMATING;
121 import static com.android.server.wm.ActivityRecordProto.IS_WAITING_FOR_TRANSITION_START;
122 import static com.android.server.wm.ActivityRecordProto.LAST_ALL_DRAWN;
123 import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING;
124 import static com.android.server.wm.ActivityRecordProto.NAME;
125 import static com.android.server.wm.ActivityRecordProto.NUM_DRAWN_WINDOWS;
126 import static com.android.server.wm.ActivityRecordProto.NUM_INTERESTING_WINDOWS;
127 import static com.android.server.wm.ActivityRecordProto.PROC_ID;
128 import static com.android.server.wm.ActivityRecordProto.REPORTED_DRAWN;
129 import static com.android.server.wm.ActivityRecordProto.REPORTED_VISIBLE;
130 import static com.android.server.wm.ActivityRecordProto.STARTING_DISPLAYED;
131 import static com.android.server.wm.ActivityRecordProto.STARTING_MOVED;
132 import static com.android.server.wm.ActivityRecordProto.STARTING_WINDOW;
133 import static com.android.server.wm.ActivityRecordProto.STATE;
134 import static com.android.server.wm.ActivityRecordProto.THUMBNAIL;
135 import static com.android.server.wm.ActivityRecordProto.TRANSLUCENT;
136 import static com.android.server.wm.ActivityRecordProto.VISIBLE;
137 import static com.android.server.wm.ActivityRecordProto.VISIBLE_REQUESTED;
138 import static com.android.server.wm.ActivityRecordProto.VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW;
139 import static com.android.server.wm.ActivityRecordProto.WINDOW_TOKEN;
140 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
141 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING;
142 import static com.android.server.wm.ActivityStack.ActivityState.FINISHING;
143 import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
144 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
145 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
146 import static com.android.server.wm.ActivityStack.ActivityState.RESTARTING_PROCESS;
147 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
148 import static com.android.server.wm.ActivityStack.ActivityState.STARTED;
149 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
150 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
151 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
152 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
153 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
154 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
155 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
156 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS;
157 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
158 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE;
159 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS;
160 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
161 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
162 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
163 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
164 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING;
165 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
166 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE;
167 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_APP;
168 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
169 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS;
170 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
171 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE;
172 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS;
173 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
174 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
175 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
176 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION;
177 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING;
178 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
179 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
180 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
181 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
182 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
183 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
184 import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutLocked;
185 import static com.android.server.wm.IdentifierProto.HASH_CODE;
186 import static com.android.server.wm.IdentifierProto.TITLE;
187 import static com.android.server.wm.IdentifierProto.USER_ID;
188 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
189 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
190 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
191 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
192 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
193 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
194 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
195 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION;
196 import static com.android.server.wm.TaskPersister.DEBUG;
197 import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
198 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
199 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
200 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
201 import static com.android.server.wm.WindowContainerChildProto.ACTIVITY;
202 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
203 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
204 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
205 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
206 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
207 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
208 import static com.android.server.wm.WindowState.LEGACY_POLICY_VISIBILITY;
209 import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
210 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
211 
212 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
213 import static org.xmlpull.v1.XmlPullParser.END_TAG;
214 import static org.xmlpull.v1.XmlPullParser.START_TAG;
215 
216 import android.annotation.IntDef;
217 import android.annotation.NonNull;
218 import android.annotation.Nullable;
219 import android.annotation.Size;
220 import android.app.Activity;
221 import android.app.ActivityManager;
222 import android.app.ActivityManager.TaskDescription;
223 import android.app.ActivityOptions;
224 import android.app.PendingIntent;
225 import android.app.PictureInPictureParams;
226 import android.app.ResultInfo;
227 import android.app.WaitResult.LaunchState;
228 import android.app.servertransaction.ActivityConfigurationChangeItem;
229 import android.app.servertransaction.ActivityLifecycleItem;
230 import android.app.servertransaction.ActivityRelaunchItem;
231 import android.app.servertransaction.ActivityResultItem;
232 import android.app.servertransaction.ClientTransaction;
233 import android.app.servertransaction.ClientTransactionItem;
234 import android.app.servertransaction.DestroyActivityItem;
235 import android.app.servertransaction.MoveToDisplayItem;
236 import android.app.servertransaction.NewIntentItem;
237 import android.app.servertransaction.PauseActivityItem;
238 import android.app.servertransaction.ResumeActivityItem;
239 import android.app.servertransaction.StartActivityItem;
240 import android.app.servertransaction.StopActivityItem;
241 import android.app.servertransaction.TopResumedActivityChangeItem;
242 import android.app.usage.UsageEvents.Event;
243 import android.content.ComponentName;
244 import android.content.Intent;
245 import android.content.pm.ActivityInfo;
246 import android.content.pm.ApplicationInfo;
247 import android.content.res.CompatibilityInfo;
248 import android.content.res.Configuration;
249 import android.content.res.Resources;
250 import android.graphics.Bitmap;
251 import android.graphics.GraphicBuffer;
252 import android.graphics.PixelFormat;
253 import android.graphics.Point;
254 import android.graphics.Rect;
255 import android.net.Uri;
256 import android.os.Binder;
257 import android.os.Build;
258 import android.os.Bundle;
259 import android.os.Debug;
260 import android.os.IBinder;
261 import android.os.PersistableBundle;
262 import android.os.Process;
263 import android.os.RemoteException;
264 import android.os.SystemClock;
265 import android.os.Trace;
266 import android.os.UserHandle;
267 import android.os.storage.StorageManager;
268 import android.service.dreams.DreamActivity;
269 import android.service.dreams.DreamManagerInternal;
270 import android.service.voice.IVoiceInteractionSession;
271 import android.text.TextUtils;
272 import android.util.ArraySet;
273 import android.util.EventLog;
274 import android.util.Log;
275 import android.util.MergedConfiguration;
276 import android.util.Slog;
277 import android.util.TimeUtils;
278 import android.util.proto.ProtoOutputStream;
279 import android.view.AppTransitionAnimationSpec;
280 import android.view.DisplayCutout;
281 import android.view.DisplayInfo;
282 import android.view.IAppTransitionAnimationSpecsFuture;
283 import android.view.IApplicationToken;
284 import android.view.InputApplicationHandle;
285 import android.view.RemoteAnimationDefinition;
286 import android.view.RemoteAnimationTarget;
287 import android.view.SurfaceControl;
288 import android.view.SurfaceControl.Transaction;
289 import android.view.WindowManager;
290 import android.view.WindowManager.LayoutParams;
291 import android.view.animation.Animation;
292 import android.window.WindowContainerToken;
293 
294 import com.android.internal.R;
295 import com.android.internal.annotations.VisibleForTesting;
296 import com.android.internal.app.ResolverActivity;
297 import com.android.internal.content.ReferrerIntent;
298 import com.android.internal.util.ToBooleanFunction;
299 import com.android.internal.util.XmlUtils;
300 import com.android.internal.util.function.pooled.PooledConsumer;
301 import com.android.internal.util.function.pooled.PooledFunction;
302 import com.android.internal.util.function.pooled.PooledLambda;
303 import com.android.server.AttributeCache;
304 import com.android.server.LocalServices;
305 import com.android.server.am.AppTimeTracker;
306 import com.android.server.am.PendingIntentRecord;
307 import com.android.server.display.color.ColorDisplayService;
308 import com.android.server.policy.WindowManagerPolicy;
309 import com.android.server.protolog.common.ProtoLog;
310 import com.android.server.uri.NeededUriGrants;
311 import com.android.server.uri.UriPermissionOwner;
312 import com.android.server.wm.ActivityMetricsLogger.TransitionInfoSnapshot;
313 import com.android.server.wm.ActivityStack.ActivityState;
314 import com.android.server.wm.SurfaceAnimator.AnimationType;
315 import com.android.server.wm.WindowManagerService.H;
316 import com.android.server.wm.utils.InsetUtils;
317 
318 import com.google.android.collect.Sets;
319 
320 import org.xmlpull.v1.XmlPullParser;
321 import org.xmlpull.v1.XmlPullParserException;
322 import org.xmlpull.v1.XmlSerializer;
323 
324 import java.io.File;
325 import java.io.IOException;
326 import java.io.PrintWriter;
327 import java.lang.ref.WeakReference;
328 import java.util.ArrayDeque;
329 import java.util.ArrayList;
330 import java.util.Arrays;
331 import java.util.HashSet;
332 import java.util.List;
333 import java.util.Objects;
334 import java.util.function.Consumer;
335 import java.util.function.Function;
336 import java.util.function.Predicate;
337 
338 /**
339  * An entry in the history stack, representing an activity.
340  */
341 final class ActivityRecord extends WindowToken implements WindowManagerService.AppFreezeListener {
342     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM;
343     private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
344     private static final String TAG_APP = TAG + POSTFIX_APP;
345     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
346     private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS;
347     private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
348     private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE;
349     private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS;
350     private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
351     private static final String TAG_STATES = TAG + POSTFIX_STATES;
352     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
353     private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION;
354     private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING;
355     private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
356 
357     private static final String ATTR_ID = "id";
358     private static final String TAG_INTENT = "intent";
359     private static final String ATTR_USERID = "user_id";
360     private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
361     private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
362     private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
363     private static final String ATTR_LAUNCHEDFROMFEATURE = "launched_from_feature";
364     private static final String ATTR_RESOLVEDTYPE = "resolved_type";
365     private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
366     static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
367 
368     // How many activities have to be scheduled to stop to force a stop pass.
369     private static final int MAX_STOPPING_TO_FORCE = 3;
370 
371     private static final int STARTING_WINDOW_TYPE_NONE = 0;
372     private static final int STARTING_WINDOW_TYPE_SNAPSHOT = 1;
373     private static final int STARTING_WINDOW_TYPE_SPLASH_SCREEN = 2;
374 
375     /**
376      * Value to increment the z-layer when boosting a layer during animations. BOOST in l33tsp34k.
377      */
378     @VisibleForTesting static final int Z_BOOST_BASE = 800570000;
379     static final int INVALID_PID = -1;
380 
381     // How long we wait until giving up on the last activity to pause.  This
382     // is short because it directly impacts the responsiveness of starting the
383     // next activity.
384     private static final int PAUSE_TIMEOUT = 500;
385 
386     // Ticks during which we check progress while waiting for an app to launch.
387     private static final int LAUNCH_TICK = 500;
388 
389     // How long we wait for the activity to tell us it has stopped before
390     // giving up.  This is a good amount of time because we really need this
391     // from the application in order to get its saved state. Once the stop
392     // is complete we may start destroying client resources triggering
393     // crashes if the UI thread was hung. We put this timeout one second behind
394     // the ANR timeout so these situations will generate ANR instead of
395     // Surface lost or other errors.
396     private static final int STOP_TIMEOUT = 11 * 1000;
397 
398     // How long we wait until giving up on an activity telling us it has
399     // finished destroying itself.
400     private static final int DESTROY_TIMEOUT = 10 * 1000;
401 
402     final ActivityTaskManagerService mAtmService;
403     final ActivityInfo info; // activity info provided by developer in AndroidManifest
404     // Non-null only for application tokens.
405     // TODO: rename to mActivityToken
406     final ActivityRecord.Token appToken;
407     // Which user is this running for?
408     final int mUserId;
409     // The package implementing intent's component
410     // TODO: rename to mPackageName
411     final String packageName;
412     // the intent component, or target of an alias.
413     final ComponentName mActivityComponent;
414     // Has a wallpaper window as a background.
415     // TODO: Rename to mHasWallpaper and also see if it possible to combine this with the
416     // mOccludesParent field.
417     final boolean hasWallpaper;
418     // Input application handle used by the input dispatcher.
419     final InputApplicationHandle mInputApplicationHandle;
420 
421     final int launchedFromPid; // always the pid who started the activity.
422     final int launchedFromUid; // always the uid who started the activity.
423     final String launchedFromPackage; // always the package who started the activity.
424     final @Nullable String launchedFromFeatureId; // always the feature in launchedFromPackage
425     final Intent intent;    // the original intent that generated us
426     final String shortComponentName; // the short component name of the intent
427     final String resolvedType; // as per original caller;
428     final String processName; // process where this component wants to run
429     final String taskAffinity; // as per ActivityInfo.taskAffinity
430     final boolean stateNotNeeded; // As per ActivityInfo.flags
431     @VisibleForTesting
432     int mHandoverLaunchDisplayId = INVALID_DISPLAY; // Handover launch display id to next activity.
433     @VisibleForTesting
434     TaskDisplayArea mHandoverTaskDisplayArea; // Handover launch task display area.
435     private final boolean componentSpecified;  // did caller specify an explicit component?
436     final boolean rootVoiceInteraction;  // was this the root activity of a voice interaction?
437 
438     private CharSequence nonLocalizedLabel;  // the label information from the package mgr.
439     private int labelRes;           // the label information from the package mgr.
440     private int icon;               // resource identifier of activity's icon.
441     private int logo;               // resource identifier of activity's logo.
442     private int theme;              // resource identifier of activity's theme.
443     private int windowFlags;        // custom window flags for preview window.
444     private Task task;              // the task this is in.
445     private long createTime = System.currentTimeMillis();
446     long lastVisibleTime;         // last time this activity became visible
447     long cpuTimeAtResume;         // the cpu time of host process at the time of resuming activity
448     long pauseTime;               // last time we started pausing the activity
449     long launchTickTime;          // base time for launch tick messages
450     long topResumedStateLossTime; // last time we reported top resumed state loss to an activity
451     // Last configuration reported to the activity in the client process.
452     private MergedConfiguration mLastReportedConfiguration;
453     private int mLastReportedDisplayId;
454     boolean mLastReportedMultiWindowMode;
455     boolean mLastReportedPictureInPictureMode;
456     CompatibilityInfo compat;// last used compatibility mode
457     ActivityRecord resultTo; // who started this entry, so will get our reply
458     final String resultWho; // additional identifier for use by resultTo.
459     final int requestCode;  // code given by requester (resultTo)
460     ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
461     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
462     ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
463     Intent mLastNewIntent;  // the last new intent we delivered to client
464     ActivityOptions pendingOptions; // most recently given options
465     ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
466     AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
467     ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
468     UriPermissionOwner uriPermissions; // current special URI access perms.
469     WindowProcessController app;      // if non-null, hosting application
470     private ActivityState mState;    // current state we are in
471     private Bundle mIcicle;         // last saved activity state
472     private PersistableBundle mPersistentState; // last persistently saved activity state
473     private boolean mHaveState = true; // Indicates whether the last saved state of activity is
474                                        // preserved. This starts out 'true', since the initial state
475                                        // of an activity is that we have everything, and we should
476                                        // never consider it lacking in state to be removed if it
477                                        // dies. After an activity is launched it follows the value
478                                        // of #mIcicle.
479     boolean launchFailed;   // set if a launched failed, to abort on 2nd try
480     boolean stopped;        // is activity pause finished?
481     boolean delayedResume;  // not yet resumed because of stopped app switches?
482     boolean finishing;      // activity in pending finish list?
483     boolean deferRelaunchUntilPaused;   // relaunch of activity is being deferred until pause is
484                                         // completed
485     boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
486     int configChangeFlags;  // which config values have changed
487     private boolean keysPaused;     // has key dispatching been paused for it?
488     int launchMode;         // the launch mode activity attribute.
489     int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override
490     private boolean mVisible;        // Should this token's windows be visible?
491     boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
492                                      // might hide this activity?
493     // True if the visible state of this token was forced to true due to a transferred starting
494     // window.
495     private boolean mVisibleSetFromTransferredStartingWindow;
496     // TODO: figure out how to consolidate with the same variable in ActivityRecord.
497     private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
498                                         // process that it is hidden.
499     private boolean mLastDeferHidingClient; // If true we will defer setting mClientVisible to false
500                                            // and reporting to the client that it is hidden.
501     private boolean mSetToSleep; // have we told the activity to sleep?
502     boolean nowVisible;     // is this activity's window visible?
503     boolean mDrawn;          // is this activity's window drawn?
504     boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
505     boolean idle;           // has the activity gone idle?
506     boolean hasBeenLaunched;// has this activity ever been launched?
507     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
508     boolean immersive;      // immersive mode (don't interrupt if possible)
509     boolean forceNewConfig; // force re-create with new config next time
510     boolean supportsEnterPipOnTaskSwitch;  // This flag is set by the system to indicate that the
511         // activity can enter picture in picture while pausing (only when switching to another task)
512     PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build();
513         // The PiP params used when deferring the entering of picture-in-picture.
514     int launchCount;        // count of launches since last state
515     long lastLaunchTime;    // time of last launch of this activity
516     ComponentName requestedVrComponent; // the requested component for handling VR mode.
517 
518     boolean inHistory;  // are we in the history stack?
519     final ActivityStackSupervisor mStackSupervisor;
520     final RootWindowContainer mRootWindowContainer;
521 
522     static final int STARTING_WINDOW_NOT_SHOWN = 0;
523     static final int STARTING_WINDOW_SHOWN = 1;
524     static final int STARTING_WINDOW_REMOVED = 2;
525     int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
526     private boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
527 
528     // Marking the reason why this activity is being relaunched. Mainly used to track that this
529     // activity is being relaunched to fulfill a resize request due to compatibility issues, e.g. in
530     // pre-NYC apps that don't have a sense of being resized.
531     int mRelaunchReason = RELAUNCH_REASON_NONE;
532 
533     TaskDescription taskDescription; // the recents information for this activity
534 
535     // These configurations are collected from application's resources based on size-sensitive
536     // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
537     // and drawable-sw400dp will be added to both as 400.
538     private int[] mVerticalSizeConfigurations;
539     private int[] mHorizontalSizeConfigurations;
540     private int[] mSmallestSizeConfigurations;
541 
542     /**
543      * The precomputed display insets for resolving configuration. It will be non-null if
544      * {@link #shouldUseSizeCompatMode} returns {@code true}.
545      */
546     private CompatDisplayInsets mCompatDisplayInsets;
547 
548     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
549     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
550 
551     boolean mVoiceInteraction;
552 
553     private int mPendingRelaunchCount;
554 
555     // True if we are current in the process of removing this app token from the display
556     private boolean mRemovingFromDisplay = false;
557 
558     private RemoteAnimationDefinition mRemoteAnimationDefinition;
559 
560     AnimatingActivityRegistry mAnimatingActivityRegistry;
561 
562     private Task mLastParent;
563 
564     // Have we told the window clients to show themselves?
565     private boolean mClientVisible;
566 
567     boolean firstWindowDrawn;
568     // Last drawn state we reported to the app token.
569     private boolean reportedDrawn;
570     private final WindowState.UpdateReportedVisibilityResults mReportedVisibilityResults =
571             new WindowState.UpdateReportedVisibilityResults();
572 
573     private boolean mUseTransferredAnimation;
574 
575     /**
576      * @see #currentLaunchCanTurnScreenOn()
577      */
578     private boolean mCurrentLaunchCanTurnScreenOn = true;
579 
580     /** Whether our surface was set to be showing in the last call to {@link #prepareSurfaces} */
581     private boolean mLastSurfaceShowing = true;
582 
583     private Letterbox mLetterbox;
584 
585     /**
586      * The activity is opaque and fills the entire space of this task.
587      * @see WindowContainer#fillsParent()
588      */
589     private boolean mOccludesParent;
590 
591     // The input dispatching timeout for this application token in nanoseconds.
592     long mInputDispatchingTimeoutNanos;
593 
594     private boolean mShowWhenLocked;
595     private boolean mInheritShownWhenLocked;
596     private boolean mTurnScreenOn;
597 
598     /** Have we been asked to have this token keep the screen frozen? */
599     private boolean mFreezingScreen;
600 
601     // These are used for determining when all windows associated with
602     // an activity have been drawn, so they can be made visible together
603     // at the same time.
604     // initialize so that it doesn't match mTransactionSequence which is an int.
605     private long mLastTransactionSequence = Long.MIN_VALUE;
606     private int mNumInterestingWindows;
607     private int mNumDrawnWindows;
608     boolean allDrawn;
609     private boolean mLastAllDrawn;
610 
611     private boolean mLastContainsShowWhenLockedWindow;
612     private boolean mLastContainsDismissKeyguardWindow;
613     private boolean mLastContainsTurnScreenOnWindow;
614 
615     /**
616      * A flag to determine if this AR is in the process of closing or entering PIP. This is needed
617      * to help AR know that the app is in the process of closing but hasn't yet started closing on
618      * the WM side.
619      */
620     private boolean mWillCloseOrEnterPip;
621 
622     /**
623      * The scale to fit at least one side of the activity to its parent. If the activity uses
624      * 1920x1080, and the actually size on the screen is 960x540, then the scale is 0.5.
625      */
626     private float mSizeCompatScale = 1f;
627     /**
628      * The bounds in global coordinates for activity in size compatibility mode.
629      * @see ActivityRecord#hasSizeCompatBounds()
630      */
631     private Rect mSizeCompatBounds;
632 
633     // activity is not displayed?
634     // TODO: rename to mNoDisplay
635     @VisibleForTesting
636     boolean noDisplay;
637     boolean mShowForAllUsers;
638     // TODO: Make this final
639     int mTargetSdk;
640 
641     // Is this window's surface needed?  This is almost like visible, except
642     // it will sometimes be true a little earlier: when the activity record has
643     // been shown, but is still waiting for its app transition to execute
644     // before making its windows shown.
645     boolean mVisibleRequested;
646 
647     // Last visibility state we reported to the app token.
648     boolean reportedVisible;
649 
650     boolean mDisablePreviewScreenshots;
651 
652     // Information about an application starting window if displayed.
653     // Note: these are de-referenced before the starting window animates away.
654     StartingData mStartingData;
655     WindowState startingWindow;
656     WindowManagerPolicy.StartingSurface startingSurface;
657     boolean startingDisplayed;
658     boolean startingMoved;
659 
660     // TODO: Have a WindowContainer state for tracking exiting/deferred removal.
661     boolean mIsExiting;
662 
663     boolean mEnteringAnimation;
664 
665     boolean mAppStopped;
666     // A hint to override the window specified rotation animation, or -1 to use the window specified
667     // value. We use this so that we can select the right animation in the cases of starting
668     // windows, where the app hasn't had time to set a value on the window.
669     int mRotationAnimationHint = -1;
670 
671     ArrayDeque<Rect> mFrozenBounds = new ArrayDeque<>();
672     ArrayDeque<Configuration> mFrozenMergedConfig = new ArrayDeque<>();
673 
674     private AppSaturationInfo mLastAppSaturationInfo;
675 
676     private final ColorDisplayService.ColorTransformController mColorTransformController =
677             (matrix, translation) -> mWmService.mH.post(() -> {
678                 synchronized (mWmService.mGlobalLock) {
679                     if (mLastAppSaturationInfo == null) {
680                         mLastAppSaturationInfo = new AppSaturationInfo();
681                     }
682 
683                     mLastAppSaturationInfo.setSaturation(matrix, translation);
684                     updateColorTransform();
685                 }
686             });
687 
688     /**
689      * Current sequencing integer of the configuration, for skipping old activity configurations.
690      */
691     private int mConfigurationSeq;
692 
693     /**
694      * Temp configs used in {@link #ensureActivityConfiguration(int, boolean)}
695      */
696     private final Configuration mTmpConfig = new Configuration();
697     private final Rect mTmpBounds = new Rect();
698 
699     // Token for targeting this activity for assist purposes.
700     final Binder assistToken = new Binder();
701 
702     private final Runnable mPauseTimeoutRunnable = new Runnable() {
703         @Override
704         public void run() {
705             // We don't at this point know if the activity is fullscreen,
706             // so we need to be conservative and assume it isn't.
707             Slog.w(TAG, "Activity pause timeout for " + ActivityRecord.this);
708             synchronized (mAtmService.mGlobalLock) {
709                 if (hasProcess()) {
710                     mAtmService.logAppTooSlow(app, pauseTime, "pausing " + ActivityRecord.this);
711                 }
712                 activityPaused(true);
713             }
714         }
715     };
716 
717     private final Runnable mLaunchTickRunnable = new Runnable() {
718         @Override
719         public void run() {
720             synchronized (mAtmService.mGlobalLock) {
721                 if (continueLaunchTicking()) {
722                     mAtmService.logAppTooSlow(
723                             app, launchTickTime, "launching " + ActivityRecord.this);
724                 }
725             }
726         }
727     };
728 
729     private final Runnable mDestroyTimeoutRunnable = new Runnable() {
730         @Override
731         public void run() {
732             synchronized (mAtmService.mGlobalLock) {
733                 Slog.w(TAG, "Activity destroy timeout for " + ActivityRecord.this);
734                 destroyed("destroyTimeout");
735             }
736         }
737     };
738 
739     private final Runnable mStopTimeoutRunnable = new Runnable() {
740         @Override
741         public void run() {
742             synchronized (mAtmService.mGlobalLock) {
743                 Slog.w(TAG, "Activity stop timeout for " + ActivityRecord.this);
744                 if (isInHistory()) {
745                     activityStopped(
746                             null /*icicle*/, null /*persistentState*/, null /*description*/);
747                 }
748             }
749         }
750     };
751 
startingWindowStateToString(int state)752     private static String startingWindowStateToString(int state) {
753         switch (state) {
754             case STARTING_WINDOW_NOT_SHOWN:
755                 return "STARTING_WINDOW_NOT_SHOWN";
756             case STARTING_WINDOW_SHOWN:
757                 return "STARTING_WINDOW_SHOWN";
758             case STARTING_WINDOW_REMOVED:
759                 return "STARTING_WINDOW_REMOVED";
760             default:
761                 return "unknown state=" + state;
762         }
763     }
764 
765     @Override
dump(PrintWriter pw, String prefix, boolean dumpAll)766     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
767         final long now = SystemClock.uptimeMillis();
768         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
769                 pw.print(" processName="); pw.println(processName);
770         pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
771                 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
772                 pw.print(" launchedFromFeature="); pw.print(launchedFromFeatureId);
773                 pw.print(" userId="); pw.println(mUserId);
774         pw.print(prefix); pw.print("app="); pw.println(app);
775         pw.print(prefix); pw.println(intent.toInsecureString());
776         pw.print(prefix); pw.print("rootOfTask="); pw.print(isRootOfTask());
777                 pw.print(" task="); pw.println(task);
778         pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
779         pw.print(prefix); pw.print("mActivityComponent=");
780                 pw.println(mActivityComponent.flattenToShortString());
781         if (info != null && info.applicationInfo != null) {
782             final ApplicationInfo appInfo = info.applicationInfo;
783             pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
784             if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
785                 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
786             }
787             pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
788             if (appInfo.splitSourceDirs != null) {
789                 pw.print(prefix); pw.print("splitDir=");
790                         pw.println(Arrays.toString(appInfo.splitSourceDirs));
791             }
792         }
793         pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
794                 pw.print(" componentSpecified="); pw.print(componentSpecified);
795                 pw.print(" mActivityType="); pw.println(
796                         activityTypeToString(getActivityType()));
797         if (rootVoiceInteraction) {
798             pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
799         }
800         pw.print(prefix); pw.print("compat="); pw.print(compat);
801                 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
802                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
803                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
804         pw.println(prefix + "mLastReportedConfigurations:");
805         mLastReportedConfiguration.dump(pw, prefix + "  ");
806 
807         pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
808         if (!getRequestedOverrideConfiguration().equals(EMPTY)) {
809             pw.println(prefix + "RequestedOverrideConfiguration="
810                     + getRequestedOverrideConfiguration());
811         }
812         if (!getResolvedOverrideConfiguration().equals(getRequestedOverrideConfiguration())) {
813             pw.println(prefix + "ResolvedOverrideConfiguration="
814                     + getResolvedOverrideConfiguration());
815         }
816         if (!matchParentBounds()) {
817             pw.println(prefix + "bounds=" + getBounds());
818         }
819         if (resultTo != null || resultWho != null) {
820             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
821                     pw.print(" resultWho="); pw.print(resultWho);
822                     pw.print(" resultCode="); pw.println(requestCode);
823         }
824         if (taskDescription != null) {
825             final String iconFilename = taskDescription.getIconFilename();
826             if (iconFilename != null || taskDescription.getLabel() != null ||
827                     taskDescription.getPrimaryColor() != 0) {
828                 pw.print(prefix); pw.print("taskDescription:");
829                         pw.print(" label=\""); pw.print(taskDescription.getLabel());
830                                 pw.print("\"");
831                         pw.print(" icon="); pw.print(taskDescription.getInMemoryIcon() != null
832                                 ? taskDescription.getInMemoryIcon().getByteCount() + " bytes"
833                                 : "null");
834                         pw.print(" iconResource=");
835                                 pw.print(taskDescription.getIconResourcePackage());
836                                 pw.print("/");
837                                 pw.print(taskDescription.getIconResource());
838                         pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
839                         pw.print(" primaryColor=");
840                         pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
841                         pw.print(prefix); pw.print("  backgroundColor=");
842                         pw.print(Integer.toHexString(taskDescription.getBackgroundColor()));
843                         pw.print(" statusBarColor=");
844                         pw.print(Integer.toHexString(taskDescription.getStatusBarColor()));
845                         pw.print(" navigationBarColor=");
846                         pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
847             }
848         }
849         if (results != null) {
850             pw.print(prefix); pw.print("results="); pw.println(results);
851         }
852         if (pendingResults != null && pendingResults.size() > 0) {
853             pw.print(prefix); pw.println("Pending Results:");
854             for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
855                 PendingIntentRecord pir = wpir != null ? wpir.get() : null;
856                 pw.print(prefix); pw.print("  - ");
857                 if (pir == null) {
858                     pw.println("null");
859                 } else {
860                     pw.println(pir);
861                     pir.dump(pw, prefix + "    ");
862                 }
863             }
864         }
865         if (newIntents != null && newIntents.size() > 0) {
866             pw.print(prefix); pw.println("Pending New Intents:");
867             for (int i=0; i<newIntents.size(); i++) {
868                 Intent intent = newIntents.get(i);
869                 pw.print(prefix); pw.print("  - ");
870                 if (intent == null) {
871                     pw.println("null");
872                 } else {
873                     pw.println(intent.toShortString(false, true, false, false));
874                 }
875             }
876         }
877         if (pendingOptions != null) {
878             pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
879         }
880         if (appTimeTracker != null) {
881             appTimeTracker.dumpWithHeader(pw, prefix, false);
882         }
883         if (uriPermissions != null) {
884             uriPermissions.dump(pw, prefix);
885         }
886         pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
887                 pw.print(" launchCount="); pw.print(launchCount);
888                 pw.print(" lastLaunchTime=");
889                 if (lastLaunchTime == 0) pw.print("0");
890                 else TimeUtils.formatDuration(lastLaunchTime, now, pw);
891                 pw.println();
892         pw.print(prefix); pw.print("mHaveState="); pw.print(mHaveState);
893                 pw.print(" mIcicle="); pw.println(mIcicle);
894         pw.print(prefix); pw.print("state="); pw.print(mState);
895                 pw.print(" stopped="); pw.print(stopped);
896                 pw.print(" delayedResume="); pw.print(delayedResume);
897                 pw.print(" finishing="); pw.println(finishing);
898         pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
899                 pw.print(" inHistory="); pw.print(inHistory);
900         pw.print(" setToSleep="); pw.print(mSetToSleep);
901                 pw.print(" idle="); pw.print(idle);
902                 pw.print(" mStartingWindowState=");
903                 pw.println(startingWindowStateToString(mStartingWindowState));
904         pw.print(prefix); pw.print("occludesParent="); pw.print(occludesParent());
905                 pw.print(" noDisplay="); pw.print(noDisplay);
906                 pw.print(" immersive="); pw.print(immersive);
907                 pw.print(" launchMode="); pw.println(launchMode);
908         pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
909                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
910         pw.print(prefix); pw.print("mActivityType=");
911                 pw.println(activityTypeToString(getActivityType()));
912         if (requestedVrComponent != null) {
913             pw.print(prefix);
914             pw.print("requestedVrComponent=");
915             pw.println(requestedVrComponent);
916         }
917         super.dump(pw, prefix, dumpAll);
918         if (mVoiceInteraction) {
919             pw.println(prefix + "mVoiceInteraction=true");
920         }
921         pw.print(prefix); pw.print("mOccludesParent="); pw.print(mOccludesParent);
922         pw.print(" mOrientation="); pw.println(mOrientation);
923         pw.println(prefix + "mVisibleRequested=" + mVisibleRequested
924                 + " mVisible=" + mVisible + " mClientVisible=" + mClientVisible
925                 + ((mDeferHidingClient) ? " mDeferHidingClient=" + mDeferHidingClient : "")
926                 + " reportedDrawn=" + reportedDrawn + " reportedVisible=" + reportedVisible);
927         if (paused) {
928             pw.print(prefix); pw.print("paused="); pw.println(paused);
929         }
930         if (mAppStopped) {
931             pw.print(prefix); pw.print("mAppStopped="); pw.println(mAppStopped);
932         }
933         if (mNumInterestingWindows != 0 || mNumDrawnWindows != 0
934                 || allDrawn || mLastAllDrawn) {
935             pw.print(prefix); pw.print("mNumInterestingWindows=");
936             pw.print(mNumInterestingWindows);
937             pw.print(" mNumDrawnWindows="); pw.print(mNumDrawnWindows);
938             pw.print(" allDrawn="); pw.print(allDrawn);
939             pw.print(" lastAllDrawn="); pw.print(mLastAllDrawn);
940             pw.println(")");
941         }
942         if (mStartingData != null || firstWindowDrawn || mIsExiting) {
943             pw.print(prefix); pw.print("startingData="); pw.print(mStartingData);
944             pw.print(" firstWindowDrawn="); pw.print(firstWindowDrawn);
945             pw.print(" mIsExiting="); pw.println(mIsExiting);
946         }
947         if (startingWindow != null || startingSurface != null
948                 || startingDisplayed || startingMoved || mVisibleSetFromTransferredStartingWindow) {
949             pw.print(prefix); pw.print("startingWindow="); pw.print(startingWindow);
950             pw.print(" startingSurface="); pw.print(startingSurface);
951             pw.print(" startingDisplayed="); pw.print(startingDisplayed);
952             pw.print(" startingMoved="); pw.print(startingMoved);
953             pw.println(" mHiddenSetFromTransferredStartingWindow="
954                     + mVisibleSetFromTransferredStartingWindow);
955         }
956         if (!mFrozenBounds.isEmpty()) {
957             pw.print(prefix); pw.print("mFrozenBounds="); pw.println(mFrozenBounds);
958             pw.print(prefix); pw.print("mFrozenMergedConfig="); pw.println(mFrozenMergedConfig);
959         }
960         if (mPendingRelaunchCount != 0) {
961             pw.print(prefix); pw.print("mPendingRelaunchCount="); pw.println(mPendingRelaunchCount);
962         }
963         if (mSizeCompatScale != 1f || mSizeCompatBounds != null) {
964             pw.println(prefix + "mSizeCompatScale=" + mSizeCompatScale + " mSizeCompatBounds="
965                     + mSizeCompatBounds);
966         }
967         if (mRemovingFromDisplay) {
968             pw.println(prefix + "mRemovingFromDisplay=" + mRemovingFromDisplay);
969         }
970         if (lastVisibleTime != 0 || nowVisible) {
971             pw.print(prefix); pw.print("nowVisible="); pw.print(nowVisible);
972                     pw.print(" lastVisibleTime=");
973                     if (lastVisibleTime == 0) pw.print("0");
974                     else TimeUtils.formatDuration(lastVisibleTime, now, pw);
975                     pw.println();
976         }
977         if (mDeferHidingClient) {
978             pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient);
979         }
980         if (deferRelaunchUntilPaused || configChangeFlags != 0) {
981             pw.print(prefix); pw.print("deferRelaunchUntilPaused=");
982                     pw.print(deferRelaunchUntilPaused);
983                     pw.print(" configChangeFlags=");
984                     pw.println(Integer.toHexString(configChangeFlags));
985         }
986         if (mServiceConnectionsHolder != null) {
987             pw.print(prefix); pw.print("connections="); pw.println(mServiceConnectionsHolder);
988         }
989         if (info != null) {
990             pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
991             pw.println(prefix + "mLastReportedMultiWindowMode=" + mLastReportedMultiWindowMode
992                     + " mLastReportedPictureInPictureMode=" + mLastReportedPictureInPictureMode);
993             if (info.supportsPictureInPicture()) {
994                 pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture());
995                 pw.println(prefix + "supportsEnterPipOnTaskSwitch: "
996                         + supportsEnterPipOnTaskSwitch);
997             }
998             if (info.maxAspectRatio != 0) {
999                 pw.println(prefix + "maxAspectRatio=" + info.maxAspectRatio);
1000             }
1001             if (info.minAspectRatio != 0) {
1002                 pw.println(prefix + "minAspectRatio=" + info.minAspectRatio);
1003             }
1004             if (info.supportsSizeChanges) {
1005                 pw.println(prefix + "supportsSizeChanges=true");
1006             }
1007         }
1008     }
1009 
setAppTimeTracker(AppTimeTracker att)1010     void setAppTimeTracker(AppTimeTracker att) {
1011         appTimeTracker = att;
1012     }
1013 
1014     /** Update the saved state of an activity. */
setSavedState(@ullable Bundle savedState)1015     void setSavedState(@Nullable Bundle savedState) {
1016         mIcicle = savedState;
1017         mHaveState = mIcicle != null;
1018     }
1019 
1020     /**
1021      * Get the actual Bundle instance of the saved state.
1022      * @see #hasSavedState() for checking if the record has saved state.
1023      */
getSavedState()1024     @Nullable Bundle getSavedState() {
1025         return mIcicle;
1026     }
1027 
1028     /**
1029      * Check if the activity has saved state.
1030      * @return {@code true} if the client reported a non-empty saved state from last onStop(), or
1031      *         if this record was just created and the client is yet to be launched and resumed.
1032      */
hasSavedState()1033     boolean hasSavedState() {
1034         return mHaveState;
1035     }
1036 
1037     /** @return The actual PersistableBundle instance of the saved persistent state. */
getPersistentSavedState()1038     @Nullable PersistableBundle getPersistentSavedState() {
1039         return mPersistentState;
1040     }
1041 
updateApplicationInfo(ApplicationInfo aInfo)1042     void updateApplicationInfo(ApplicationInfo aInfo) {
1043         info.applicationInfo = aInfo;
1044     }
1045 
crossesHorizontalSizeThreshold(int firstDp, int secondDp)1046     private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
1047         return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
1048     }
1049 
crossesVerticalSizeThreshold(int firstDp, int secondDp)1050     private boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
1051         return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp);
1052     }
1053 
crossesSmallestSizeThreshold(int firstDp, int secondDp)1054     private boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
1055         return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp);
1056     }
1057 
1058     /**
1059      * The purpose of this method is to decide whether the activity needs to be relaunched upon
1060      * changing its size. In most cases the activities don't need to be relaunched, if the resize
1061      * is small, all the activity content has to do is relayout itself within new bounds. There are
1062      * cases however, where the activity's content would be completely changed in the new size and
1063      * the full relaunch is required.
1064      *
1065      * The activity will report to us vertical and horizontal thresholds after which a relaunch is
1066      * required. These thresholds are collected from the application resource qualifiers. For
1067      * example, if application has layout-w600dp resource directory, then it needs a relaunch when
1068      * we resize from width of 650dp to 550dp, as it crosses the 600dp threshold. However, if
1069      * it resizes width from 620dp to 700dp, it won't be relaunched as it stays on the same side
1070      * of the threshold.
1071      */
crossesSizeThreshold(int[] thresholds, int firstDp, int secondDp)1072     private static boolean crossesSizeThreshold(int[] thresholds, int firstDp,
1073             int secondDp) {
1074         if (thresholds == null) {
1075             return false;
1076         }
1077         for (int i = thresholds.length - 1; i >= 0; i--) {
1078             final int threshold = thresholds[i];
1079             if ((firstDp < threshold && secondDp >= threshold)
1080                     || (firstDp >= threshold && secondDp < threshold)) {
1081                 return true;
1082             }
1083         }
1084         return false;
1085     }
1086 
setSizeConfigurations(int[] horizontalSizeConfiguration, int[] verticalSizeConfigurations, int[] smallestSizeConfigurations)1087     void setSizeConfigurations(int[] horizontalSizeConfiguration,
1088             int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
1089         mHorizontalSizeConfigurations = horizontalSizeConfiguration;
1090         mVerticalSizeConfigurations = verticalSizeConfigurations;
1091         mSmallestSizeConfigurations = smallestSizeConfigurations;
1092     }
1093 
scheduleActivityMovedToDisplay(int displayId, Configuration config)1094     private void scheduleActivityMovedToDisplay(int displayId, Configuration config) {
1095         if (!attachedToProcess()) {
1096             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.w(TAG,
1097                     "Can't report activity moved to display - client not running, activityRecord="
1098                             + this + ", displayId=" + displayId);
1099             return;
1100         }
1101         try {
1102             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
1103                     "Reporting activity moved to display" + ", activityRecord=" + this
1104                             + ", displayId=" + displayId + ", config=" + config);
1105 
1106             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
1107                     MoveToDisplayItem.obtain(displayId, config));
1108         } catch (RemoteException e) {
1109             // If process died, whatever.
1110         }
1111     }
1112 
scheduleConfigurationChanged(Configuration config)1113     private void scheduleConfigurationChanged(Configuration config) {
1114         if (!attachedToProcess()) {
1115             if (DEBUG_CONFIGURATION) Slog.w(TAG,
1116                     "Can't report activity configuration update - client not running"
1117                             + ", activityRecord=" + this);
1118             return;
1119         }
1120         try {
1121             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "
1122                     + config);
1123 
1124             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
1125                     ActivityConfigurationChangeItem.obtain(config));
1126         } catch (RemoteException e) {
1127             // If process died, whatever.
1128         }
1129     }
1130 
scheduleTopResumedActivityChanged(boolean onTop)1131     boolean scheduleTopResumedActivityChanged(boolean onTop) {
1132         if (!attachedToProcess()) {
1133             if (DEBUG_STATES) {
1134                 Slog.w(TAG, "Can't report activity position update - client not running"
1135                                 + ", activityRecord=" + this);
1136             }
1137             return false;
1138         }
1139         try {
1140             if (DEBUG_STATES) {
1141                 Slog.v(TAG, "Sending position change to " + this + ", onTop: " + onTop);
1142             }
1143 
1144             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
1145                     TopResumedActivityChangeItem.obtain(onTop));
1146         } catch (RemoteException e) {
1147             // If process died, whatever.
1148             return false;
1149         }
1150         return true;
1151     }
1152 
updateMultiWindowMode()1153     void updateMultiWindowMode() {
1154         if (task == null || task.getStack() == null || !attachedToProcess()) {
1155             return;
1156         }
1157 
1158         // An activity is considered to be in multi-window mode if its task isn't fullscreen.
1159         final boolean inMultiWindowMode = inMultiWindowMode();
1160         if (inMultiWindowMode != mLastReportedMultiWindowMode) {
1161             if (!inMultiWindowMode && mLastReportedPictureInPictureMode) {
1162                 updatePictureInPictureMode(null, false);
1163             } else {
1164                 mLastReportedMultiWindowMode = inMultiWindowMode;
1165                 computeConfigurationAfterMultiWindowModeChange();
1166                 // If the activity is in stopping or stopped state, for instance, it's in the
1167                 // split screen task and not the top one, the last configuration it should keep
1168                 // is the one before multi-window mode change.
1169                 final ActivityState state = getState();
1170                 if (state != STOPPED && state != STOPPING) {
1171                     ensureActivityConfiguration(0 /* globalChanges */, PRESERVE_WINDOWS,
1172                             true /* ignoreVisibility */);
1173                 }
1174             }
1175         }
1176     }
1177 
updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate)1178     void updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate) {
1179         if (task == null || task.getStack() == null || !attachedToProcess()) {
1180             return;
1181         }
1182 
1183         final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
1184         if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
1185             // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
1186             // update that here in order. Set the last reported MW state to the same as the PiP
1187             // state since we haven't yet actually resized the task (these callbacks need to
1188             // precede the configuration change from the resize.
1189             mLastReportedPictureInPictureMode = inPictureInPictureMode;
1190             mLastReportedMultiWindowMode = inPictureInPictureMode;
1191             if (targetStackBounds != null && !targetStackBounds.isEmpty()) {
1192                 computeConfigurationAfterMultiWindowModeChange();
1193             }
1194             ensureActivityConfiguration(0 /* globalChanges */, PRESERVE_WINDOWS,
1195                     true /* ignoreVisibility */);
1196         }
1197     }
1198 
computeConfigurationAfterMultiWindowModeChange()1199     private void computeConfigurationAfterMultiWindowModeChange() {
1200         final Configuration newConfig = new Configuration();
1201         newConfig.setTo(task.getRequestedOverrideConfiguration());
1202         Rect outBounds = newConfig.windowConfiguration.getBounds();
1203         final Configuration parentConfig = task.getParent().getConfiguration();
1204         task.adjustForMinimalTaskDimensions(outBounds, outBounds, parentConfig);
1205         task.computeConfigResourceOverrides(newConfig, parentConfig);
1206     }
1207 
getTask()1208     Task getTask() {
1209         return task;
1210     }
1211 
1212     /**
1213      * Sets the Task on this activity for the purposes of re-use during launch where we will
1214      * re-use another activity instead of this one for the launch.
1215      */
setTaskForReuse(Task task)1216     void setTaskForReuse(Task task) {
1217         this.task = task;
1218     }
1219 
getStack()1220     ActivityStack getStack() {
1221         return task != null ? task.getStack() : null;
1222     }
1223 
1224     @Override
onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent)1225     void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
1226         final Task oldTask = oldParent != null ? (Task) oldParent : null;
1227         final Task newTask = newParent != null ? (Task) newParent : null;
1228         this.task = newTask;
1229 
1230         super.onParentChanged(newParent, oldParent);
1231 
1232         if (isPersistable()) {
1233             if (oldTask != null) {
1234                 mAtmService.notifyTaskPersisterLocked(oldTask, false);
1235             }
1236             if (newTask != null) {
1237                 mAtmService.notifyTaskPersisterLocked(newTask, false);
1238             }
1239         }
1240 
1241         if (oldParent == null && newParent != null) {
1242             // First time we are adding the activity to the system.
1243             mVoiceInteraction = newTask.voiceSession != null;
1244             mInputDispatchingTimeoutNanos = getInputDispatchingTimeoutLocked(this) * 1000000L;
1245 
1246             // TODO(b/36505427): Maybe this call should be moved inside
1247             // updateOverrideConfiguration()
1248             newTask.updateOverrideConfigurationFromLaunchBounds();
1249             // Make sure override configuration is up-to-date before using to create window
1250             // controller.
1251             updateSizeCompatMode();
1252             // When an activity is started directly into a split-screen fullscreen stack, we need to
1253             // update the initial multi-window modes so that the callbacks are scheduled correctly
1254             // when the user leaves that mode.
1255             mLastReportedMultiWindowMode = inMultiWindowMode();
1256             mLastReportedPictureInPictureMode = inPinnedWindowingMode();
1257         }
1258 
1259         // When the associated task is {@code null}, the {@link ActivityRecord} can no longer
1260         // access visual elements like the {@link DisplayContent}. We must remove any associations
1261         // such as animations.
1262         if (task == null) {
1263             // It is possible we have been marked as a closing app earlier. We must remove ourselves
1264             // from this list so we do not participate in any future animations.
1265             if (getDisplayContent() != null) {
1266                 getDisplayContent().mClosingApps.remove(this);
1267             }
1268         } else if (mLastParent != null && mLastParent.getStack() != null) {
1269             task.getStack().mExitingActivities.remove(this);
1270         }
1271         final ActivityStack stack = getStack();
1272 
1273         // If we reparent, make sure to remove ourselves from the old animation registry.
1274         if (mAnimatingActivityRegistry != null) {
1275             mAnimatingActivityRegistry.notifyFinished(this);
1276         }
1277         mAnimatingActivityRegistry = stack != null
1278                 ? stack.getAnimatingActivityRegistry()
1279                 : null;
1280 
1281         mLastParent = task;
1282 
1283         updateColorTransform();
1284 
1285         if (oldTask != null) {
1286             oldTask.cleanUpActivityReferences(this);
1287         }
1288         if (newTask != null && isState(RESUMED)) {
1289             newTask.setResumedActivity(this, "onParentChanged");
1290         }
1291 
1292         if (stack != null && stack.topRunningActivity() == this) {
1293             // make ensure the TaskOrganizer still works after re-parenting
1294             if (firstWindowDrawn) {
1295                 stack.setHasBeenVisible(true);
1296             }
1297         }
1298     }
1299 
updateColorTransform()1300     private void updateColorTransform() {
1301         if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
1302             getPendingTransaction().setColorTransform(mSurfaceControl,
1303                     mLastAppSaturationInfo.mMatrix, mLastAppSaturationInfo.mTranslation);
1304             mWmService.scheduleAnimationLocked();
1305         }
1306     }
1307 
1308     @Override
onDisplayChanged(DisplayContent dc)1309     void onDisplayChanged(DisplayContent dc) {
1310         DisplayContent prevDc = mDisplayContent;
1311         super.onDisplayChanged(dc);
1312         if (prevDc == null || prevDc == mDisplayContent) {
1313             return;
1314         }
1315 
1316         if (prevDc.mOpeningApps.remove(this)) {
1317             // Transfer opening transition to new display.
1318             mDisplayContent.mOpeningApps.add(this);
1319             mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
1320             mDisplayContent.executeAppTransition();
1321         }
1322 
1323         prevDc.mClosingApps.remove(this);
1324 
1325         if (prevDc.mFocusedApp == this) {
1326             prevDc.setFocusedApp(null);
1327             if (dc.getTopMostActivity() == this) {
1328                 dc.setFocusedApp(this);
1329             }
1330         }
1331 
1332         if (mLetterbox != null) {
1333             mLetterbox.onMovedToDisplay(mDisplayContent.getDisplayId());
1334         }
1335     }
1336 
layoutLetterbox(WindowState winHint)1337     void layoutLetterbox(WindowState winHint) {
1338         final WindowState w = findMainWindow();
1339         if (w == null || winHint != null && w != winHint) {
1340             return;
1341         }
1342         final boolean surfaceReady = w.isDrawnLw()  // Regular case
1343                 || w.mWinAnimator.mSurfaceDestroyDeferred  // The preserved surface is still ready.
1344                 || w.isDragResizeChanged();  // Waiting for relayoutWindow to call preserveSurface.
1345         final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
1346         if (needsLetterbox) {
1347             if (mLetterbox == null) {
1348                 mLetterbox = new Letterbox(() -> makeChildSurface(null),
1349                         mWmService.mTransactionFactory);
1350                 mLetterbox.attachInput(w);
1351             }
1352             getPosition(mTmpPoint);
1353             // Get the bounds of the "space-to-fill". The transformed bounds have the highest
1354             // priority because the activity is launched in a rotated environment. In multi-window
1355             // mode, the task-level represents this. In fullscreen-mode, the task container does
1356             // (since the orientation letterbox is also applied to the task).
1357             final Rect transformedBounds = getFixedRotationTransformDisplayBounds();
1358             final Rect spaceToFill = transformedBounds != null
1359                     ? transformedBounds
1360                     : inMultiWindowMode()
1361                             ? task.getBounds()
1362                             : getRootTask().getParent().getBounds();
1363             mLetterbox.layout(spaceToFill, w.getFrameLw(), mTmpPoint);
1364         } else if (mLetterbox != null) {
1365             mLetterbox.hide();
1366         }
1367     }
1368 
updateLetterboxSurface(WindowState winHint)1369     void updateLetterboxSurface(WindowState winHint) {
1370         final WindowState w = findMainWindow();
1371         if (w != winHint && winHint != null && w != null) {
1372             return;
1373         }
1374         layoutLetterbox(winHint);
1375         if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
1376             mLetterbox.applySurfaceChanges(getPendingTransaction());
1377         }
1378     }
1379 
getLetterboxInsets()1380     Rect getLetterboxInsets() {
1381         if (mLetterbox != null) {
1382             return mLetterbox.getInsets();
1383         } else {
1384             return new Rect();
1385         }
1386     }
1387 
1388     /** Gets the inner bounds of letterbox. The bounds will be empty if there is no letterbox. */
getLetterboxInnerBounds(Rect outBounds)1389     void getLetterboxInnerBounds(Rect outBounds) {
1390         if (mLetterbox != null) {
1391             outBounds.set(mLetterbox.getInnerFrame());
1392         } else {
1393             outBounds.setEmpty();
1394         }
1395     }
1396 
1397     /**
1398      * @see Letterbox#notIntersectsOrFullyContains(Rect)
1399      */
letterboxNotIntersectsOrFullyContains(Rect rect)1400     boolean letterboxNotIntersectsOrFullyContains(Rect rect) {
1401         return mLetterbox == null || mLetterbox.notIntersectsOrFullyContains(rect);
1402     }
1403 
1404     /**
1405      * @return {@code true} if there is a letterbox and any part of that letterbox overlaps with
1406      * the given {@code rect}.
1407      */
isLetterboxOverlappingWith(Rect rect)1408     boolean isLetterboxOverlappingWith(Rect rect) {
1409         return mLetterbox != null && mLetterbox.isOverlappingWith(rect);
1410     }
1411 
1412     static class Token extends IApplicationToken.Stub {
1413         private WeakReference<ActivityRecord> weakActivity;
1414         private final String name;
1415         private final String tokenString;
1416 
Token(Intent intent)1417         Token(Intent intent) {
1418             name = intent.getComponent().flattenToShortString();
1419             tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
1420         }
1421 
attach(ActivityRecord activity)1422         private void attach(ActivityRecord activity) {
1423             if (weakActivity != null) {
1424                 throw new IllegalStateException("Already attached..." + this);
1425             }
1426             weakActivity = new WeakReference<>(activity);
1427         }
1428 
tokenToActivityRecordLocked(Token token)1429         private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
1430             if (token == null) {
1431                 return null;
1432             }
1433             ActivityRecord r = token.weakActivity.get();
1434             if (r == null || r.getRootTask() == null) {
1435                 return null;
1436             }
1437             return r;
1438         }
1439 
1440         @Override
toString()1441         public String toString() {
1442             StringBuilder sb = new StringBuilder(128);
1443             sb.append("Token{");
1444             sb.append(Integer.toHexString(System.identityHashCode(this)));
1445             sb.append(' ');
1446             if (weakActivity != null) {
1447                 sb.append(weakActivity.get());
1448             }
1449             sb.append('}');
1450             return sb.toString();
1451         }
1452 
1453         @Override
getName()1454         public String getName() {
1455             return name;
1456         }
1457     }
1458 
forTokenLocked(IBinder token)1459     static @Nullable ActivityRecord forTokenLocked(IBinder token) {
1460         try {
1461             return Token.tokenToActivityRecordLocked((Token)token);
1462         } catch (ClassCastException e) {
1463             Slog.w(TAG, "Bad activity token: " + token, e);
1464             return null;
1465         }
1466     }
1467 
isResolverActivity(String className)1468     static boolean isResolverActivity(String className) {
1469         return ResolverActivity.class.getName().equals(className);
1470     }
1471 
isResolverOrDelegateActivity()1472     boolean isResolverOrDelegateActivity() {
1473         return isResolverActivity(mActivityComponent.getClassName()) || Objects.equals(
1474                 mActivityComponent, mAtmService.mStackSupervisor.getSystemChooserActivity());
1475     }
1476 
isResolverOrChildActivity()1477     boolean isResolverOrChildActivity() {
1478         if (!"android".equals(packageName)) {
1479             return false;
1480         }
1481         try {
1482             return ResolverActivity.class.isAssignableFrom(
1483                     Object.class.getClassLoader().loadClass(mActivityComponent.getClassName()));
1484         } catch (ClassNotFoundException e) {
1485             return false;
1486         }
1487     }
1488 
ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller, int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, @Nullable String _launchedFromFeature, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified, boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor, ActivityOptions options, ActivityRecord sourceRecord)1489     ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
1490             int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage,
1491             @Nullable String _launchedFromFeature, Intent _intent, String _resolvedType,
1492             ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo,
1493             String _resultWho, int _reqCode, boolean _componentSpecified,
1494             boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
1495             ActivityOptions options, ActivityRecord sourceRecord) {
1496         super(_service.mWindowManager, new Token(_intent).asBinder(), TYPE_APPLICATION, true,
1497                 null /* displayContent */, false /* ownerCanManageAppTokens */);
1498 
1499         mAtmService = _service;
1500         appToken = (Token) token;
1501         info = aInfo;
1502         mUserId = UserHandle.getUserId(info.applicationInfo.uid);
1503         packageName = info.applicationInfo.packageName;
1504         mInputApplicationHandle = new InputApplicationHandle(appToken);
1505         intent = _intent;
1506 
1507         // If the class name in the intent doesn't match that of the target, this is probably an
1508         // alias. We have to create a new ComponentName object to keep track of the real activity
1509         // name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
1510         if (info.targetActivity == null
1511                 || (info.targetActivity.equals(intent.getComponent().getClassName())
1512                 && (info.launchMode == LAUNCH_MULTIPLE
1513                 || info.launchMode == LAUNCH_SINGLE_TOP))) {
1514             mActivityComponent = intent.getComponent();
1515         } else {
1516             mActivityComponent =
1517                     new ComponentName(info.packageName, info.targetActivity);
1518         }
1519 
1520         mTargetSdk = info.applicationInfo.targetSdkVersion;
1521         mShowForAllUsers = (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0;
1522         setOrientation(info.screenOrientation);
1523         mRotationAnimationHint = info.rotationAnimation;
1524 
1525         mShowWhenLocked = (aInfo.flags & ActivityInfo.FLAG_SHOW_WHEN_LOCKED) != 0;
1526         mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
1527         mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
1528 
1529         int realTheme = info.getThemeResource();
1530         if (realTheme == Resources.ID_NULL) {
1531             realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
1532                     ? android.R.style.Theme : android.R.style.Theme_Holo;
1533         }
1534 
1535         final AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
1536                 realTheme, com.android.internal.R.styleable.Window, mUserId);
1537 
1538         if (ent != null) {
1539             mOccludesParent = !ActivityInfo.isTranslucentOrFloating(ent.array);
1540             hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
1541             noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
1542         } else {
1543             hasWallpaper = false;
1544             noDisplay = false;
1545         }
1546 
1547         if (options != null) {
1548             mLaunchTaskBehind = options.getLaunchTaskBehind();
1549 
1550             final int rotationAnimation = options.getRotationAnimationHint();
1551             // Only override manifest supplied option if set.
1552             if (rotationAnimation >= 0) {
1553                 mRotationAnimationHint = rotationAnimation;
1554             }
1555         }
1556 
1557         // Application tokens start out hidden.
1558         setVisible(false);
1559         mVisibleRequested = false;
1560 
1561         ColorDisplayService.ColorDisplayServiceInternal cds = LocalServices.getService(
1562                 ColorDisplayService.ColorDisplayServiceInternal.class);
1563         cds.attachColorTransformController(packageName, mUserId,
1564                 new WeakReference<>(mColorTransformController));
1565 
1566         appToken.attach(this);
1567 
1568         mRootWindowContainer = _service.mRootWindowContainer;
1569         launchedFromPid = _launchedFromPid;
1570         launchedFromUid = _launchedFromUid;
1571         launchedFromPackage = _launchedFromPackage;
1572         launchedFromFeatureId = _launchedFromFeature;
1573         shortComponentName = _intent.getComponent().flattenToShortString();
1574         resolvedType = _resolvedType;
1575         componentSpecified = _componentSpecified;
1576         rootVoiceInteraction = _rootVoiceInteraction;
1577         mLastReportedConfiguration = new MergedConfiguration(_configuration);
1578         resultTo = _resultTo;
1579         resultWho = _resultWho;
1580         requestCode = _reqCode;
1581         setState(INITIALIZING, "ActivityRecord ctor");
1582         launchFailed = false;
1583         stopped = false;
1584         delayedResume = false;
1585         finishing = false;
1586         deferRelaunchUntilPaused = false;
1587         keysPaused = false;
1588         inHistory = false;
1589         nowVisible = false;
1590         mDrawn = false;
1591         mClientVisible = true;
1592         idle = false;
1593         hasBeenLaunched = false;
1594         mStackSupervisor = supervisor;
1595 
1596         info.taskAffinity = getTaskAffinityWithUid(info.taskAffinity, info.applicationInfo.uid);
1597         taskAffinity = info.taskAffinity;
1598         final String uid = Integer.toString(info.applicationInfo.uid);
1599         if (info.windowLayout != null && info.windowLayout.windowLayoutAffinity != null
1600                 && !info.windowLayout.windowLayoutAffinity.startsWith(uid)) {
1601             info.windowLayout.windowLayoutAffinity =
1602                     uid + ":" + info.windowLayout.windowLayoutAffinity;
1603         }
1604         stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
1605         nonLocalizedLabel = aInfo.nonLocalizedLabel;
1606         labelRes = aInfo.labelRes;
1607         if (nonLocalizedLabel == null && labelRes == 0) {
1608             ApplicationInfo app = aInfo.applicationInfo;
1609             nonLocalizedLabel = app.nonLocalizedLabel;
1610             labelRes = app.labelRes;
1611         }
1612         icon = aInfo.getIconResource();
1613         logo = aInfo.getLogoResource();
1614         theme = aInfo.getThemeResource();
1615         if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
1616             windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
1617         }
1618         if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
1619                 && (aInfo.applicationInfo.uid == SYSTEM_UID
1620                     || aInfo.applicationInfo.uid == _caller.mInfo.uid)) {
1621             processName = _caller.mName;
1622         } else {
1623             processName = aInfo.processName;
1624         }
1625 
1626         if ((aInfo.flags & FLAG_EXCLUDE_FROM_RECENTS) != 0) {
1627             intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1628         }
1629 
1630         launchMode = aInfo.launchMode;
1631 
1632         setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
1633 
1634         immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
1635 
1636         requestedVrComponent = (aInfo.requestedVrComponent == null) ?
1637                 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
1638 
1639         lockTaskLaunchMode = getLockTaskLaunchMode(aInfo, options);
1640 
1641         if (options != null) {
1642             pendingOptions = options;
1643             final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
1644             if (usageReport != null) {
1645                 appTimeTracker = new AppTimeTracker(usageReport);
1646             }
1647             // Gets launch task display area and display id from options. Returns
1648             // null/INVALID_DISPLAY if not set.
1649             final WindowContainerToken daToken = options.getLaunchTaskDisplayArea();
1650             mHandoverTaskDisplayArea = daToken != null
1651                     ? (TaskDisplayArea) WindowContainer.fromBinder(daToken.asBinder()) : null;
1652             mHandoverLaunchDisplayId = options.getLaunchDisplayId();
1653         }
1654     }
1655 
1656     /**
1657      * Generate the task affinity with uid. For b/35954083, Limit task affinity to uid to avoid
1658      * issues associated with sharing affinity across uids.
1659      *
1660      * @param affinity The affinity of the activity.
1661      * @param uid The user-ID that has been assigned to this application.
1662      * @return The task affinity with uid.
1663      */
getTaskAffinityWithUid(String affinity, int uid)1664     static String getTaskAffinityWithUid(String affinity, int uid) {
1665         final String uidStr = Integer.toString(uid);
1666         if (affinity != null && !affinity.startsWith(uidStr)) {
1667             affinity = uidStr + ":" + affinity;
1668         }
1669         return affinity;
1670     }
1671 
getLockTaskLaunchMode(ActivityInfo aInfo, @Nullable ActivityOptions options)1672     static int getLockTaskLaunchMode(ActivityInfo aInfo, @Nullable ActivityOptions options) {
1673         int lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
1674         if (aInfo.applicationInfo.isPrivilegedApp()
1675                 && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
1676                 || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
1677             lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
1678         }
1679         if (options != null) {
1680             final boolean useLockTask = options.getLockTaskMode();
1681             if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
1682                 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
1683             }
1684         }
1685         return lockTaskLaunchMode;
1686     }
1687 
1688     @Override
asActivityRecord()1689     ActivityRecord asActivityRecord() {
1690         // I am an activity record!
1691         return this;
1692     }
1693 
1694     @Override
hasActivity()1695     boolean hasActivity() {
1696         // I am an activity!
1697         return true;
1698     }
1699 
setProcess(WindowProcessController proc)1700     void setProcess(WindowProcessController proc) {
1701         app = proc;
1702         final ActivityRecord root = task != null ? task.getRootActivity() : null;
1703         if (root == this) {
1704             task.setRootProcess(proc);
1705         }
1706         proc.addActivityIfNeeded(this);
1707     }
1708 
hasProcess()1709     boolean hasProcess() {
1710         return app != null;
1711     }
1712 
attachedToProcess()1713     boolean attachedToProcess() {
1714         return hasProcess() && app.hasThread();
1715     }
1716 
addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags, IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated)1717     boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
1718             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
1719             IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
1720             boolean allowTaskSnapshot, boolean activityCreated) {
1721         // If the display is frozen, we won't do anything until the actual window is
1722         // displayed so there is no reason to put in the starting window.
1723         if (!okToDisplay()) {
1724             return false;
1725         }
1726 
1727         if (mStartingData != null) {
1728             return false;
1729         }
1730 
1731         final WindowState mainWin = findMainWindow();
1732         if (mainWin != null && mainWin.mWinAnimator.getShown()) {
1733             // App already has a visible window...why would you want a starting window?
1734             return false;
1735         }
1736 
1737         final ActivityManager.TaskSnapshot snapshot =
1738                 mWmService.mTaskSnapshotController.getSnapshot(task.mTaskId, task.mUserId,
1739                         false /* restoreFromDisk */, false /* isLowResolution */);
1740         final int type = getStartingWindowType(newTask, taskSwitch, processRunning,
1741                 allowTaskSnapshot, activityCreated, snapshot);
1742 
1743         if (type == STARTING_WINDOW_TYPE_SNAPSHOT) {
1744             if (isActivityTypeHome()) {
1745                 // The snapshot of home is only used once because it won't be updated while screen
1746                 // is on (see {@link TaskSnapshotController#screenTurningOff}).
1747                 mWmService.mTaskSnapshotController.removeSnapshotCache(task.mTaskId);
1748                 if ((mDisplayContent.mAppTransition.getTransitFlags()
1749                         & WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0) {
1750                     // Only use snapshot of home as starting window when unlocking directly.
1751                     return false;
1752                 }
1753             }
1754             return createSnapshot(snapshot);
1755         }
1756 
1757         // If this is a translucent window, then don't show a starting window -- the current
1758         // effect (a full-screen opaque starting window that fades away to the real contents
1759         // when it is ready) does not work for this.
1760         ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Checking theme of starting window: 0x%x", theme);
1761         if (theme != 0) {
1762             AttributeCache.Entry ent = AttributeCache.instance().get(pkg, theme,
1763                     com.android.internal.R.styleable.Window,
1764                     mWmService.mCurrentUserId);
1765             if (ent == null) {
1766                 // Whoops!  App doesn't exist. Um. Okay. We'll just pretend like we didn't
1767                 // see that.
1768                 return false;
1769             }
1770             final boolean windowIsTranslucent = ent.array.getBoolean(
1771                     com.android.internal.R.styleable.Window_windowIsTranslucent, false);
1772             final boolean windowIsFloating = ent.array.getBoolean(
1773                     com.android.internal.R.styleable.Window_windowIsFloating, false);
1774             final boolean windowShowWallpaper = ent.array.getBoolean(
1775                     com.android.internal.R.styleable.Window_windowShowWallpaper, false);
1776             final boolean windowDisableStarting = ent.array.getBoolean(
1777                     com.android.internal.R.styleable.Window_windowDisablePreview, false);
1778             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Translucent=%s Floating=%s ShowWallpaper=%s",
1779                     windowIsTranslucent, windowIsFloating, windowShowWallpaper);
1780             if (windowIsTranslucent) {
1781                 return false;
1782             }
1783             if (windowIsFloating || windowDisableStarting) {
1784                 return false;
1785             }
1786             if (windowShowWallpaper) {
1787                 if (getDisplayContent().mWallpaperController
1788                         .getWallpaperTarget() == null) {
1789                     // If this theme is requesting a wallpaper, and the wallpaper
1790                     // is not currently visible, then this effectively serves as
1791                     // an opaque window and our starting window transition animation
1792                     // can still work.  We just need to make sure the starting window
1793                     // is also showing the wallpaper.
1794                     windowFlags |= FLAG_SHOW_WALLPAPER;
1795                 } else {
1796                     return false;
1797                 }
1798             }
1799         }
1800 
1801         if (transferStartingWindow(transferFrom)) {
1802             return true;
1803         }
1804 
1805         // There is no existing starting window, and we don't want to create a splash screen, so
1806         // that's it!
1807         if (type != STARTING_WINDOW_TYPE_SPLASH_SCREEN) {
1808             return false;
1809         }
1810 
1811         ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SplashScreenStartingData");
1812         mStartingData = new SplashScreenStartingData(mWmService, pkg,
1813                 theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
1814                 getMergedOverrideConfiguration());
1815         scheduleAddStartingWindow();
1816         return true;
1817     }
1818 
createSnapshot(ActivityManager.TaskSnapshot snapshot)1819     private boolean createSnapshot(ActivityManager.TaskSnapshot snapshot) {
1820         if (snapshot == null) {
1821             return false;
1822         }
1823 
1824         ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Creating SnapshotStartingData");
1825         mStartingData = new SnapshotStartingData(mWmService, snapshot);
1826         scheduleAddStartingWindow();
1827         return true;
1828     }
1829 
scheduleAddStartingWindow()1830     void scheduleAddStartingWindow() {
1831         // Note: we really want to do sendMessageAtFrontOfQueue() because we
1832         // want to process the message ASAP, before any other queued
1833         // messages.
1834         if (!mWmService.mAnimationHandler.hasCallbacks(mAddStartingWindow)) {
1835             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Enqueueing ADD_STARTING");
1836             mWmService.mAnimationHandler.postAtFrontOfQueue(mAddStartingWindow);
1837         }
1838     }
1839 
1840     private class AddStartingWindow implements Runnable {
1841 
1842         @Override
run()1843         public void run() {
1844             // Can be accessed without holding the global lock
1845             final StartingData startingData;
1846             synchronized (mWmService.mGlobalLock) {
1847                 // There can only be one adding request, silly caller!
1848                 mWmService.mAnimationHandler.removeCallbacks(this);
1849 
1850                 if (mStartingData == null) {
1851                     // Animation has been canceled... do nothing.
1852                     ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1853                             "startingData was nulled out before handling"
1854                                     + " mAddStartingWindow: %s", ActivityRecord.this);
1855                     return;
1856                 }
1857                 startingData = mStartingData;
1858             }
1859 
1860             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Add starting %s: startingData=%s",
1861                     this, startingData);
1862 
1863 
1864             WindowManagerPolicy.StartingSurface surface = null;
1865             try {
1866                 surface = startingData.createStartingSurface(ActivityRecord.this);
1867             } catch (Exception e) {
1868                 Slog.w(TAG, "Exception when adding starting window", e);
1869             }
1870             if (surface != null) {
1871                 boolean abort = false;
1872                 synchronized (mWmService.mGlobalLock) {
1873                     // If the window was successfully added, then we need to remove it.
1874                     if (mStartingData == null) {
1875                         ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Aborted starting %s: startingData=%s",
1876                                 ActivityRecord.this, mStartingData);
1877 
1878                         startingWindow = null;
1879                         mStartingData = null;
1880                         abort = true;
1881                     } else {
1882                         startingSurface = surface;
1883                     }
1884                     if (!abort) {
1885                         ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1886                                 "Added starting %s: startingWindow=%s startingView=%s",
1887                                 ActivityRecord.this, startingWindow, startingSurface);
1888                     }
1889                 }
1890                 if (abort) {
1891                     surface.remove();
1892                 }
1893             } else {
1894                 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Surface returned was null: %s",
1895                         ActivityRecord.this);
1896             }
1897         }
1898     }
1899 
1900     private final AddStartingWindow mAddStartingWindow = new AddStartingWindow();
1901 
getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning, boolean allowTaskSnapshot, boolean activityCreated, ActivityManager.TaskSnapshot snapshot)1902     private int getStartingWindowType(boolean newTask, boolean taskSwitch, boolean processRunning,
1903             boolean allowTaskSnapshot, boolean activityCreated,
1904             ActivityManager.TaskSnapshot snapshot) {
1905         if (newTask || !processRunning || (taskSwitch && !activityCreated)) {
1906             return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1907         } else if (taskSwitch && allowTaskSnapshot) {
1908             if (isSnapshotCompatible(snapshot)) {
1909                 return STARTING_WINDOW_TYPE_SNAPSHOT;
1910             }
1911             if (!isActivityTypeHome()) {
1912                 return STARTING_WINDOW_TYPE_SPLASH_SCREEN;
1913             }
1914             return STARTING_WINDOW_TYPE_NONE;
1915         } else {
1916             return STARTING_WINDOW_TYPE_NONE;
1917         }
1918     }
1919 
1920     /**
1921      * Returns {@code true} if the task snapshot is compatible with this activity (at least the
1922      * rotation must be the same).
1923      */
1924     @VisibleForTesting
isSnapshotCompatible(ActivityManager.TaskSnapshot snapshot)1925     boolean isSnapshotCompatible(ActivityManager.TaskSnapshot snapshot) {
1926         if (snapshot == null) {
1927             return false;
1928         }
1929         final int rotation = mDisplayContent.rotationForActivityInDifferentOrientation(this);
1930         final int targetRotation = rotation != ROTATION_UNDEFINED
1931                 // The display may rotate according to the orientation of this activity.
1932                 ? rotation
1933                 // The activity won't change display orientation.
1934                 : task.getWindowConfiguration().getRotation();
1935         return snapshot.getRotation() == targetRotation;
1936     }
1937 
removeStartingWindow()1938     void removeStartingWindow() {
1939         if (startingWindow == null) {
1940             if (mStartingData != null) {
1941                 // Starting window has not been added yet, but it is scheduled to be added.
1942                 // Go ahead and cancel the request.
1943                 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Clearing startingData for token=%s", this);
1944                 mStartingData = null;
1945             }
1946             return;
1947         }
1948 
1949         final WindowManagerPolicy.StartingSurface surface;
1950         if (mStartingData != null) {
1951             surface = startingSurface;
1952             mStartingData = null;
1953             startingSurface = null;
1954             startingWindow = null;
1955             startingDisplayed = false;
1956             if (surface == null) {
1957                 ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1958                         "startingWindow was set but startingSurface==null, couldn't "
1959                                 + "remove");
1960 
1961                 return;
1962             }
1963         } else {
1964             ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
1965                     "Tried to remove starting window but startingWindow was null: %s",
1966                     this);
1967             return;
1968         }
1969 
1970         ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Schedule remove starting %s startingWindow=%s"
1971                         + " startingView=%s Callers=%s",
1972                 this, startingWindow, startingSurface, Debug.getCallers(5));
1973 
1974 
1975         // Use the same thread to remove the window as we used to add it, as otherwise we end up
1976         // with things in the view hierarchy being called from different threads.
1977         mWmService.mAnimationHandler.post(() -> {
1978             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Removing startingView=%s", surface);
1979             try {
1980                 surface.remove();
1981             } catch (Exception e) {
1982                 Slog.w(TAG_WM, "Exception when removing starting window", e);
1983             }
1984         });
1985     }
1986 
removeAppTokenFromDisplay()1987     private void removeAppTokenFromDisplay() {
1988         if (mWmService.mRoot == null) return;
1989 
1990         final DisplayContent dc = mWmService.mRoot.getDisplayContent(getDisplayId());
1991         if (dc == null) {
1992             Slog.w(TAG, "removeAppTokenFromDisplay: Attempted to remove token: "
1993                     + appToken + " from non-existing displayId=" + getDisplayId());
1994             return;
1995         }
1996         // Resume key dispatching if it is currently paused before we remove the container.
1997         resumeKeyDispatchingLocked();
1998         dc.removeAppToken(appToken.asBinder());
1999     }
2000 
2001     /**
2002      * Reparents this activity into {@param newTask} at the provided {@param position}.  The caller
2003      * should ensure that the {@param newTask} is not already the parent of this activity.
2004      */
reparent(Task newTask, int position, String reason)2005     void reparent(Task newTask, int position, String reason) {
2006         if (getParent() == null) {
2007             Slog.w(TAG, "reparent: Attempted to reparent non-existing app token: " + appToken);
2008             return;
2009         }
2010         final Task prevTask = task;
2011         if (prevTask == newTask) {
2012             throw new IllegalArgumentException(reason + ": task=" + newTask
2013                     + " is already the parent of r=" + this);
2014         }
2015 
2016         ProtoLog.i(WM_DEBUG_ADD_REMOVE, "reparent: moving activity=%s"
2017                 + " to task=%d at %d", this, task.mTaskId, position);
2018         reparent(newTask, position);
2019     }
2020 
isHomeIntent(Intent intent)2021     private boolean isHomeIntent(Intent intent) {
2022         return ACTION_MAIN.equals(intent.getAction())
2023                 && (intent.hasCategory(CATEGORY_HOME)
2024                 || intent.hasCategory(CATEGORY_SECONDARY_HOME))
2025                 && intent.getCategories().size() == 1
2026                 && intent.getData() == null
2027                 && intent.getType() == null;
2028     }
2029 
isMainIntent(Intent intent)2030     static boolean isMainIntent(Intent intent) {
2031         return ACTION_MAIN.equals(intent.getAction())
2032                 && intent.hasCategory(CATEGORY_LAUNCHER)
2033                 && intent.getCategories().size() == 1
2034                 && intent.getData() == null
2035                 && intent.getType() == null;
2036     }
2037 
2038     @VisibleForTesting
canLaunchHomeActivity(int uid, ActivityRecord sourceRecord)2039     boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) {
2040         if (uid == Process.myUid() || uid == 0) {
2041             // System process can launch home activity.
2042             return true;
2043         }
2044         // Allow the recents component to launch the home activity.
2045         final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks();
2046         if (recentTasks != null && recentTasks.isCallerRecents(uid)) {
2047             return true;
2048         }
2049         // Resolver or system chooser activity can launch home activity.
2050         return sourceRecord != null && sourceRecord.isResolverOrDelegateActivity();
2051     }
2052 
2053     /**
2054      * @return whether the given package name can launch an assist activity.
2055      */
canLaunchAssistActivity(String packageName)2056     private boolean canLaunchAssistActivity(String packageName) {
2057         final ComponentName assistComponent =
2058                 mAtmService.mActiveVoiceInteractionServiceComponent;
2059         if (assistComponent != null) {
2060             return assistComponent.getPackageName().equals(packageName);
2061         }
2062         return false;
2063     }
2064 
canLaunchDreamActivity(String packageName)2065     static boolean canLaunchDreamActivity(String packageName) {
2066         if (packageName == null) {
2067             return false;
2068         }
2069 
2070         if (!LocalServices.getService(ActivityTaskManagerInternal.class).isDreaming()) {
2071             return false;
2072         }
2073 
2074         final DreamManagerInternal dreamManager =
2075                 LocalServices.getService(DreamManagerInternal.class);
2076 
2077         // Verify that the package is the current active dream or doze component. The
2078         // getActiveDreamComponent() call path does not acquire the DreamManager lock and thus
2079         // is safe to use.
2080         final ComponentName activeDream = dreamManager.getActiveDreamComponent(false /* doze */);
2081         final ComponentName activeDoze = dreamManager.getActiveDreamComponent(true /* doze */);
2082         return TextUtils.equals(packageName, getPackageName(activeDream))
2083                 || TextUtils.equals(packageName, getPackageName(activeDoze));
2084     }
2085 
getPackageName(ComponentName componentName)2086     private static String getPackageName(ComponentName componentName) {
2087         return componentName != null ? componentName.getPackageName() : null;
2088     }
2089 
setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent, ActivityOptions options, ActivityRecord sourceRecord)2090     private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent,
2091             ActivityOptions options, ActivityRecord sourceRecord) {
2092         int activityType = ACTIVITY_TYPE_UNDEFINED;
2093         if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
2094                 && isHomeIntent(intent) && !isResolverOrDelegateActivity()) {
2095             // This sure looks like a home activity!
2096             activityType = ACTIVITY_TYPE_HOME;
2097 
2098             if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE
2099                     || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
2100                 // We only allow home activities to be resizeable if they explicitly requested it.
2101                 info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
2102             }
2103         } else if (mAtmService.getRecentTasks().isRecentsComponent(mActivityComponent,
2104                 info.applicationInfo.uid)) {
2105             activityType = ACTIVITY_TYPE_RECENTS;
2106         } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
2107                 && canLaunchAssistActivity(launchedFromPackage)) {
2108             activityType = ACTIVITY_TYPE_ASSISTANT;
2109         } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_DREAM
2110                 && canLaunchDreamActivity(launchedFromPackage)
2111                 && DreamActivity.class.getName() == info.name) {
2112             activityType = ACTIVITY_TYPE_DREAM;
2113         }
2114         setActivityType(activityType);
2115     }
2116 
setTaskToAffiliateWith(Task taskToAffiliateWith)2117     void setTaskToAffiliateWith(Task taskToAffiliateWith) {
2118         if (launchMode != LAUNCH_SINGLE_INSTANCE && launchMode != LAUNCH_SINGLE_TASK) {
2119             task.setTaskToAffiliateWith(taskToAffiliateWith);
2120         }
2121     }
2122 
2123     /** @return Root task of this activity, null if there is no task. */
getRootTask()2124     ActivityStack getRootTask() {
2125         return task != null ? (ActivityStack) task.getRootTask() : null;
2126     }
2127 
getRootTaskId()2128     int getRootTaskId() {
2129         return task != null ? task.getRootTaskId() : INVALID_TASK_ID;
2130     }
2131 
getDisplay()2132     DisplayContent getDisplay() {
2133         final ActivityStack stack = getRootTask();
2134         return stack != null ? stack.getDisplay() : null;
2135     }
2136 
2137     @Override
2138     @Nullable
getDisplayArea()2139     TaskDisplayArea getDisplayArea() {
2140         return (TaskDisplayArea) super.getDisplayArea();
2141     }
2142 
2143     @Override
fillsParent()2144     boolean fillsParent() {
2145         return occludesParent(true /* includingFinishing */);
2146     }
2147 
2148     /** Returns true if this activity is not finishing, is opaque and fills the entire space of
2149      * this task. */
occludesParent()2150     boolean occludesParent() {
2151         return occludesParent(false /* includingFinishing */);
2152     }
2153 
occludesParent(boolean includingFinishing)2154     private boolean occludesParent(boolean includingFinishing) {
2155         if (!includingFinishing && finishing) {
2156             return false;
2157         }
2158         return mOccludesParent;
2159     }
2160 
setOccludesParent(boolean occludesParent)2161     boolean setOccludesParent(boolean occludesParent) {
2162         final boolean changed = occludesParent != mOccludesParent;
2163         mOccludesParent = occludesParent;
2164         setMainWindowOpaque(occludesParent);
2165         mWmService.mWindowPlacerLocked.requestTraversal();
2166 
2167         if (changed && task != null && !occludesParent) {
2168             getRootTask().convertActivityToTranslucent(this);
2169         }
2170         // Always ensure visibility if this activity doesn't occlude parent, so the
2171         // {@link #returningOptions} of the activity under this one can be applied in
2172         // {@link #handleAlreadyVisible()}.
2173         if (changed || !occludesParent) {
2174             mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
2175         }
2176         return changed;
2177     }
2178 
setMainWindowOpaque(boolean isOpaque)2179     void setMainWindowOpaque(boolean isOpaque) {
2180         final WindowState win = findMainWindow();
2181         if (win == null) {
2182             return;
2183         }
2184         isOpaque = isOpaque & !PixelFormat.formatHasAlpha(win.getAttrs().format);
2185         win.mWinAnimator.setOpaqueLocked(isOpaque);
2186     }
2187 
takeFromHistory()2188     void takeFromHistory() {
2189         if (inHistory) {
2190             inHistory = false;
2191             if (task != null && !finishing) {
2192                 task = null;
2193             }
2194             clearOptionsLocked();
2195         }
2196     }
2197 
isInHistory()2198     boolean isInHistory() {
2199         return inHistory;
2200     }
2201 
isInStackLocked()2202     boolean isInStackLocked() {
2203         final ActivityStack stack = getRootTask();
2204         return stack != null && stack.isInTask(this) != null;
2205     }
2206 
isPersistable()2207     boolean isPersistable() {
2208         return (info.persistableMode == PERSIST_ROOT_ONLY ||
2209                 info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
2210                 (intent == null || (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
2211     }
2212 
2213     @Override
isFocusable()2214     boolean isFocusable() {
2215         return super.isFocusable() && (canReceiveKeys() || isAlwaysFocusable());
2216     }
2217 
canReceiveKeys()2218     boolean canReceiveKeys() {
2219         // TODO(156521483): Propagate the state down the hierarchy instead of checking the parent
2220         return getWindowConfiguration().canReceiveKeys()
2221                 && (task == null || task.getWindowConfiguration().canReceiveKeys());
2222     }
2223 
isResizeable()2224     boolean isResizeable() {
2225         return mAtmService.mForceResizableActivities
2226                 || ActivityInfo.isResizeableMode(info.resizeMode)
2227                 || info.supportsPictureInPicture();
2228     }
2229 
2230     /** @return whether this activity is non-resizeable or forced to be resizeable */
isNonResizableOrForcedResizable(int windowingMode)2231     boolean isNonResizableOrForcedResizable(int windowingMode) {
2232         if (windowingMode == WINDOWING_MODE_PINNED && info.supportsPictureInPicture()) {
2233             return false;
2234         }
2235         return info.resizeMode != RESIZE_MODE_RESIZEABLE
2236                 && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
2237     }
2238 
2239     /**
2240      * @return whether this activity supports PiP multi-window and can be put in the pinned stack.
2241      */
supportsPictureInPicture()2242     boolean supportsPictureInPicture() {
2243         return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined()
2244                 && info.supportsPictureInPicture();
2245     }
2246 
2247     /**
2248      * @return whether this activity supports split-screen multi-window and can be put in the docked
2249      *         stack.
2250      */
2251     @Override
supportsSplitScreenWindowingMode()2252     public boolean supportsSplitScreenWindowingMode() {
2253         // An activity can not be docked even if it is considered resizeable because it only
2254         // supports picture-in-picture mode but has a non-resizeable resizeMode
2255         return super.supportsSplitScreenWindowingMode()
2256                 && mAtmService.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
2257     }
2258 
2259     /**
2260      * @return whether this activity supports freeform multi-window and can be put in the freeform
2261      *         stack.
2262      */
supportsFreeform()2263     boolean supportsFreeform() {
2264         return mAtmService.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
2265     }
2266 
2267     /**
2268      * @return whether this activity supports non-PiP multi-window.
2269      */
supportsResizeableMultiWindow()2270     private boolean supportsResizeableMultiWindow() {
2271         return mAtmService.mSupportsMultiWindow && !isActivityTypeHome()
2272                 && (ActivityInfo.isResizeableMode(info.resizeMode)
2273                         || mAtmService.mForceResizableActivities);
2274     }
2275 
2276     /**
2277      * Check whether this activity can be launched on the specified display.
2278      *
2279      * @param displayId Target display id.
2280      * @return {@code true} if either it is the default display or this activity can be put on a
2281      *         secondary screen.
2282      */
canBeLaunchedOnDisplay(int displayId)2283     boolean canBeLaunchedOnDisplay(int displayId) {
2284         return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId, launchedFromPid,
2285                 launchedFromUid, info);
2286     }
2287 
2288     /**
2289      * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
2290      *         the activity has requested to enter PiP when it would otherwise be stopped.
2291      *
2292      * @return whether this activity is currently allowed to enter PIP.
2293      */
checkEnterPictureInPictureState(String caller, boolean beforeStopping)2294     boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) {
2295         if (!supportsPictureInPicture()) {
2296             return false;
2297         }
2298 
2299         // Check app-ops and see if PiP is supported for this package
2300         if (!checkEnterPictureInPictureAppOpsState()) {
2301             return false;
2302         }
2303 
2304         // Check to see if we are in VR mode, and disallow PiP if so
2305         if (mAtmService.shouldDisableNonVrUiLocked()) {
2306             return false;
2307         }
2308 
2309         boolean isKeyguardLocked = mAtmService.isKeyguardLocked();
2310         boolean isCurrentAppLocked =
2311                 mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
2312         final TaskDisplayArea taskDisplayArea = getDisplayArea();
2313         boolean hasPinnedStack = taskDisplayArea != null && taskDisplayArea.hasPinnedTask();
2314         // Don't return early if !isNotLocked, since we want to throw an exception if the activity
2315         // is in an incorrect state
2316         boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
2317 
2318         // We don't allow auto-PiP when something else is already pipped.
2319         if (beforeStopping && hasPinnedStack) {
2320             return false;
2321         }
2322 
2323         switch (mState) {
2324             case RESUMED:
2325                 // When visible, allow entering PiP if the app is not locked.  If it is over the
2326                 // keyguard, then we will prompt to unlock in the caller before entering PiP.
2327                 return !isCurrentAppLocked &&
2328                         (supportsEnterPipOnTaskSwitch || !beforeStopping);
2329             case PAUSING:
2330             case PAUSED:
2331                 // When pausing, then only allow enter PiP as in the resume state, and in addition,
2332                 // require that there is not an existing PiP activity and that the current system
2333                 // state supports entering PiP
2334                 return isNotLockedOrOnKeyguard && !hasPinnedStack
2335                         && supportsEnterPipOnTaskSwitch;
2336             case STOPPING:
2337                 // When stopping in a valid state, then only allow enter PiP as in the pause state.
2338                 // Otherwise, fall through to throw an exception if the caller is trying to enter
2339                 // PiP in an invalid stopping state.
2340                 if (supportsEnterPipOnTaskSwitch) {
2341                     return isNotLockedOrOnKeyguard && !hasPinnedStack;
2342                 }
2343             default:
2344                 return false;
2345         }
2346     }
2347 
2348     /**
2349      * Sets if this {@link ActivityRecord} is in the process of closing or entering PIP.
2350      * {@link #mWillCloseOrEnterPip}}
2351      */
setWillCloseOrEnterPip(boolean willCloseOrEnterPip)2352     void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
2353         mWillCloseOrEnterPip = willCloseOrEnterPip;
2354     }
2355 
2356     /**
2357      * Returns whether this {@link ActivityRecord} is considered closing. Conditions are either
2358      * 1. Is this app animating and was requested to be hidden
2359      * 2. App is delayed closing since it might enter PIP.
2360      */
isClosingOrEnteringPip()2361     boolean isClosingOrEnteringPip() {
2362         return (isAnimating(TRANSITION | PARENTS) && !mVisibleRequested) || mWillCloseOrEnterPip;
2363     }
2364     /**
2365      * @return Whether AppOps allows this package to enter picture-in-picture.
2366      */
checkEnterPictureInPictureAppOpsState()2367     private boolean checkEnterPictureInPictureAppOpsState() {
2368         return mAtmService.getAppOpsManager().checkOpNoThrow(
2369                 OP_PICTURE_IN_PICTURE, info.applicationInfo.uid, packageName) == MODE_ALLOWED;
2370     }
2371 
isAlwaysFocusable()2372     private boolean isAlwaysFocusable() {
2373         return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
2374     }
2375 
windowsAreFocusable()2376     boolean windowsAreFocusable() {
2377         return windowsAreFocusable(false /* fromUserTouch */);
2378     }
2379 
2380     // TODO: Does this really need to be different from isAlwaysFocusable()? For the activity side
2381     // focusable means resumeable. I guess with that in mind maybe we should rename the other
2382     // method to isResumeable() or something like that.
windowsAreFocusable(boolean fromUserTouch)2383     boolean windowsAreFocusable(boolean fromUserTouch) {
2384         if (!fromUserTouch && mTargetSdk < Build.VERSION_CODES.Q) {
2385             final int pid = getPid();
2386             final ActivityRecord topFocusedAppOfMyProcess =
2387                     mWmService.mRoot.mTopFocusedAppByProcess.get(pid);
2388             if (topFocusedAppOfMyProcess != null && topFocusedAppOfMyProcess != this) {
2389                 // For the apps below Q, there can be only one app which has the focused window per
2390                 // process, because legacy apps may not be ready for a multi-focus system.
2391                 return false;
2392 
2393             }
2394         }
2395         return (canReceiveKeys() || isAlwaysFocusable()) && getDisplay() != null;
2396     }
2397 
2398     /**
2399      * Move activity with its stack to front and make the stack focused.
2400      * @param reason the reason to move to top
2401      * @return {@code true} if the stack is focusable and has been moved to top or the activity
2402      *         is not yet resumed while the stack is already on top, {@code false} otherwise.
2403      */
moveFocusableActivityToTop(String reason)2404     boolean moveFocusableActivityToTop(String reason) {
2405         if (!isFocusable()) {
2406             if (DEBUG_FOCUS) {
2407                 Slog.d(TAG_FOCUS, "moveActivityStackToFront: unfocusable activity=" + this);
2408             }
2409             return false;
2410         }
2411 
2412         final ActivityStack stack = getRootTask();
2413         if (stack == null) {
2414             Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
2415                     + this + " task=" + task);
2416             return false;
2417         }
2418 
2419         if (mRootWindowContainer.getTopResumedActivity() == this
2420                 && getDisplayContent().mFocusedApp == this) {
2421             if (DEBUG_FOCUS) {
2422                 Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
2423             }
2424             return !isState(RESUMED);
2425         }
2426 
2427         if (DEBUG_FOCUS) {
2428             Slog.d(TAG_FOCUS, "moveActivityStackToFront: activity=" + this);
2429         }
2430 
2431         stack.moveToFront(reason, task);
2432         // Report top activity change to tracking services and WM
2433         if (mRootWindowContainer.getTopResumedActivity() == this) {
2434             mAtmService.setResumedActivityUncheckLocked(this, reason);
2435         }
2436         return true;
2437     }
2438 
finishIfSubActivity(ActivityRecord parent, String otherResultWho, int otherRequestCode)2439     void finishIfSubActivity(ActivityRecord parent, String otherResultWho, int otherRequestCode) {
2440         if (resultTo != parent
2441                 || requestCode != otherRequestCode
2442                 || !Objects.equals(resultWho, otherResultWho)) return;
2443 
2444         finishIfPossible("request-sub", false /* oomAdj */);
2445     }
2446 
2447     /** Finish all activities in the task with the same affinity as this one. */
finishIfSameAffinity(ActivityRecord r)2448     boolean finishIfSameAffinity(ActivityRecord r) {
2449         // End search once we get to the activity that doesn't have the same affinity.
2450         if (!Objects.equals(r.taskAffinity, taskAffinity)) return true;
2451 
2452         r.finishIfPossible("request-affinity", true /* oomAdj */);
2453         return false;
2454     }
2455 
2456     /**
2457      * Sets the result for activity that started this one, clears the references to activities
2458      * started for result from this one, and clears new intents.
2459      */
finishActivityResults(int resultCode, Intent resultData, NeededUriGrants resultGrants)2460     private void finishActivityResults(int resultCode, Intent resultData,
2461             NeededUriGrants resultGrants) {
2462         // Send the result if needed
2463         if (resultTo != null) {
2464             if (DEBUG_RESULTS) {
2465                 Slog.v(TAG_RESULTS, "Adding result to " + resultTo
2466                         + " who=" + resultWho + " req=" + requestCode
2467                         + " res=" + resultCode + " data=" + resultData);
2468             }
2469             if (resultTo.mUserId != mUserId) {
2470                 if (resultData != null) {
2471                     resultData.prepareToLeaveUser(mUserId);
2472                 }
2473             }
2474             if (info.applicationInfo.uid > 0) {
2475                 mAtmService.mUgmInternal.grantUriPermissionUncheckedFromIntent(resultGrants,
2476                         resultTo.getUriPermissionsLocked());
2477             }
2478             resultTo.addResultLocked(this, resultWho, requestCode, resultCode, resultData);
2479             resultTo = null;
2480         } else if (DEBUG_RESULTS) {
2481             Slog.v(TAG_RESULTS, "No result destination from " + this);
2482         }
2483 
2484         // Make sure this HistoryRecord is not holding on to other resources,
2485         // because clients have remote IPC references to this object so we
2486         // can't assume that will go away and want to avoid circular IPC refs.
2487         results = null;
2488         pendingResults = null;
2489         newIntents = null;
2490         setSavedState(null /* savedState */);
2491     }
2492 
2493     /** Activity finish request was not executed. */
2494     static final int FINISH_RESULT_CANCELLED = 0;
2495     /** Activity finish was requested, activity will be fully removed later. */
2496     static final int FINISH_RESULT_REQUESTED = 1;
2497     /** Activity finish was requested, activity was removed from history. */
2498     static final int FINISH_RESULT_REMOVED = 2;
2499 
2500     /** Definition of possible results for activity finish request. */
2501     @IntDef(prefix = { "FINISH_RESULT_" }, value = {
2502             FINISH_RESULT_CANCELLED,
2503             FINISH_RESULT_REQUESTED,
2504             FINISH_RESULT_REMOVED,
2505     })
2506     @interface FinishRequest {}
2507 
2508     /**
2509      * See {@link #finishIfPossible(int, Intent, String, boolean)}
2510      */
finishIfPossible(String reason, boolean oomAdj)2511     @FinishRequest int finishIfPossible(String reason, boolean oomAdj) {
2512         return finishIfPossible(Activity.RESULT_CANCELED,
2513                 null /* resultData */, null /* resultGrants */, reason, oomAdj);
2514     }
2515 
2516     /**
2517      * Finish activity if possible. If activity was resumed - we must first pause it to make the
2518      * activity below resumed. Otherwise we will try to complete the request immediately by calling
2519      * {@link #completeFinishing(String)}.
2520      * @return One of {@link FinishRequest} values:
2521      * {@link #FINISH_RESULT_REMOVED} if this activity has been removed from the history list.
2522      * {@link #FINISH_RESULT_REQUESTED} if removal process was started, but it is still in the list
2523      * and will be removed from history later.
2524      * {@link #FINISH_RESULT_CANCELLED} if activity is already finishing or in invalid state and the
2525      * request to finish it was not ignored.
2526      */
finishIfPossible(int resultCode, Intent resultData, NeededUriGrants resultGrants, String reason, boolean oomAdj)2527     @FinishRequest int finishIfPossible(int resultCode, Intent resultData,
2528             NeededUriGrants resultGrants, String reason, boolean oomAdj) {
2529         if (DEBUG_RESULTS || DEBUG_STATES) {
2530             Slog.v(TAG_STATES, "Finishing activity r=" + this + ", result=" + resultCode
2531                     + ", data=" + resultData + ", reason=" + reason);
2532         }
2533 
2534         if (finishing) {
2535             Slog.w(TAG, "Duplicate finish request for r=" + this);
2536             return FINISH_RESULT_CANCELLED;
2537         }
2538 
2539         if (!isInStackLocked()) {
2540             Slog.w(TAG, "Finish request when not in stack for r=" + this);
2541             return FINISH_RESULT_CANCELLED;
2542         }
2543 
2544         final ActivityStack stack = getRootTask();
2545         final boolean mayAdjustTop = (isState(RESUMED) || stack.mResumedActivity == null)
2546                 && stack.isFocusedStackOnDisplay();
2547         final boolean shouldAdjustGlobalFocus = mayAdjustTop
2548                 // It must be checked before {@link #makeFinishingLocked} is called, because a stack
2549                 // is not visible if it only contains finishing activities.
2550                 && mRootWindowContainer.isTopDisplayFocusedStack(stack);
2551 
2552         mAtmService.deferWindowLayout();
2553         try {
2554             makeFinishingLocked();
2555             // Make a local reference to its task since this.task could be set to null once this
2556             // activity is destroyed and detached from task.
2557             final Task task = getTask();
2558             EventLogTags.writeWmFinishActivity(mUserId, System.identityHashCode(this),
2559                     task.mTaskId, shortComponentName, reason);
2560             ActivityRecord next = task.getActivityAbove(this);
2561             if (next != null) {
2562                 if ((intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2563                     // If the caller asked that this activity (and all above it)
2564                     // be cleared when the task is reset, don't lose that information,
2565                     // but propagate it up to the next activity.
2566                     next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
2567                 }
2568             }
2569 
2570             pauseKeyDispatchingLocked();
2571 
2572             // We are finishing the top focused activity and its task has nothing to be focused so
2573             // the next focusable task should be focused.
2574             if (mayAdjustTop && ((ActivityStack) task).topRunningActivity(true /* focusableOnly */)
2575                     == null) {
2576                 task.adjustFocusToNextFocusableTask("finish-top", false /* allowFocusSelf */,
2577                             shouldAdjustGlobalFocus);
2578             }
2579 
2580             finishActivityResults(resultCode, resultData, resultGrants);
2581 
2582             final boolean endTask = task.getActivityBelow(this) == null
2583                     && !task.isClearingToReuseTask();
2584             final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE;
2585             if (isState(RESUMED)) {
2586                 if (endTask) {
2587                     mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
2588                             task.getTaskInfo());
2589                 }
2590                 // Prepare app close transition, but don't execute just yet. It is possible that
2591                 // an activity that will be made resumed in place of this one will immediately
2592                 // launch another new activity. In this case current closing transition will be
2593                 // combined with open transition for the new activity.
2594                 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) {
2595                     Slog.v(TAG_TRANSITION, "Prepare close transition: finishing " + this);
2596                 }
2597                 mDisplayContent.prepareAppTransition(transit, false);
2598 
2599                 // When finishing the activity preemptively take the snapshot before the app window
2600                 // is marked as hidden and any configuration changes take place
2601                 if (mAtmService.mWindowManager.mTaskSnapshotController != null) {
2602                     final ArraySet<Task> tasks = Sets.newArraySet(task);
2603                     mAtmService.mWindowManager.mTaskSnapshotController.snapshotTasks(tasks);
2604                     mAtmService.mWindowManager.mTaskSnapshotController
2605                             .addSkipClosingAppSnapshotTasks(tasks);
2606                 }
2607 
2608                 // Tell window manager to prepare for this one to be removed.
2609                 setVisibility(false);
2610 
2611                 if (stack.mPausingActivity == null) {
2612                     if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + this);
2613                     if (DEBUG_USER_LEAVING) {
2614                         Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
2615                     }
2616                     stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
2617                             null /* resuming */);
2618                 }
2619 
2620                 if (endTask) {
2621                     mAtmService.getLockTaskController().clearLockedTask(task);
2622                     // This activity was in the top focused stack and this is the last activity in
2623                     // that task, give this activity a higher layer so it can stay on top before the
2624                     // closing task transition be executed.
2625                     if (mayAdjustTop) {
2626                         mNeedsZBoost = true;
2627                         mDisplayContent.assignWindowLayers(false /* setLayoutNeeded */);
2628                     }
2629                 }
2630             } else if (!isState(PAUSING)) {
2631                 if (mVisibleRequested) {
2632                     // Prepare and execute close transition.
2633                     prepareActivityHideTransitionAnimation(transit);
2634                 }
2635 
2636                 final boolean removedActivity = completeFinishing("finishIfPossible") == null;
2637                 // Performance optimization - only invoke OOM adjustment if the state changed to
2638                 // 'STOPPING'. Otherwise it will not change the OOM scores.
2639                 if (oomAdj && isState(STOPPING)) {
2640                     mAtmService.updateOomAdj();
2641                 }
2642 
2643                 // The following code is an optimization. When the last non-task overlay activity
2644                 // is removed from the task, we remove the entire task from the stack. However,
2645                 // since that is done after the scheduled destroy callback from the activity, that
2646                 // call to change the visibility of the task overlay activities would be out of
2647                 // sync with the activity visibility being set for this finishing activity above.
2648                 // In this case, we can set the visibility of all the task overlay activities when
2649                 // we detect the last one is finishing to keep them in sync.
2650                 if (task.onlyHasTaskOverlayActivities(false /* includeFinishing */)) {
2651                     final PooledConsumer c = PooledLambda.obtainConsumer(
2652                             ActivityRecord::prepareActivityHideTransitionAnimationIfOvarlay,
2653                             PooledLambda.__(ActivityRecord.class), transit);
2654                     task.forAllActivities(c);
2655                     c.recycle();
2656                 }
2657                 return removedActivity ? FINISH_RESULT_REMOVED : FINISH_RESULT_REQUESTED;
2658             } else {
2659                 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + this);
2660             }
2661 
2662             return FINISH_RESULT_REQUESTED;
2663         } finally {
2664             mAtmService.continueWindowLayout();
2665         }
2666     }
2667 
prepareActivityHideTransitionAnimationIfOvarlay(int transit)2668     private void prepareActivityHideTransitionAnimationIfOvarlay(int transit) {
2669         if (mTaskOverlay) {
2670             prepareActivityHideTransitionAnimation(transit);
2671         }
2672     }
2673 
prepareActivityHideTransitionAnimation(int transit)2674     private void prepareActivityHideTransitionAnimation(int transit) {
2675         final DisplayContent dc = getDisplay().mDisplayContent;
2676         dc.prepareAppTransition(transit, false);
2677         setVisibility(false);
2678         dc.executeAppTransition();
2679     }
2680 
2681     /**
2682      * Complete activity finish request that was initiated earlier. If the activity is still
2683      * pausing we will wait for it to complete its transition. If the activity that should appear in
2684      * place of this one is not visible yet - we'll wait for it first. Otherwise - activity can be
2685      * destroyed right away.
2686      * @param reason Reason for finishing the activity.
2687      * @return Flag indicating whether the activity was removed from history.
2688      */
completeFinishing(String reason)2689     ActivityRecord completeFinishing(String reason) {
2690         if (!finishing || isState(RESUMED)) {
2691             throw new IllegalArgumentException(
2692                     "Activity must be finishing and not resumed to complete, r=" + this
2693                             + ", finishing=" + finishing + ", state=" + mState);
2694         }
2695 
2696         if (isState(PAUSING)) {
2697             // Activity is marked as finishing and will be processed once it completes.
2698             return this;
2699         }
2700 
2701         final boolean isCurrentVisible = mVisibleRequested || isState(PAUSED);
2702         if (isCurrentVisible) {
2703             final ActivityStack stack = getStack();
2704             final ActivityRecord activity = stack.mResumedActivity;
2705             boolean ensureVisibility = false;
2706             if (activity != null && !activity.occludesParent()) {
2707                 // If the resume activity is not opaque, we need to make sure the visibilities of
2708                 // activities be updated, they may be seen by users.
2709                 ensureVisibility = true;
2710             } else if (mStackSupervisor.getKeyguardController().isKeyguardLocked()
2711                     && stack.topActivityOccludesKeyguard()) {
2712                 // Ensure activity visibilities and update lockscreen occluded/dismiss state when
2713                 // finishing the top activity that occluded keyguard. So that, the
2714                 // ActivityStack#mTopActivityOccludesKeyguard can be updated and the activity below
2715                 // won't be resumed.
2716                 ensureVisibility = true;
2717             }
2718 
2719             if (ensureVisibility) {
2720                 getDisplay().ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
2721                         false /* preserveWindows */, true /* notifyClients */);
2722             }
2723         }
2724 
2725         boolean activityRemoved = false;
2726 
2727         // If this activity is currently visible, and the resumed activity is not yet visible, then
2728         // hold off on finishing until the resumed one becomes visible.
2729         // The activity that we are finishing may be over the lock screen. In this case, we do not
2730         // want to consider activities that cannot be shown on the lock screen as running and should
2731         // proceed with finishing the activity if there is no valid next top running activity.
2732         // Note that if this finishing activity is floating task, we don't need to wait the
2733         // next activity resume and can destroy it directly.
2734         // TODO(b/137329632): find the next activity directly underneath this one, not just anywhere
2735         final ActivityRecord next = getDisplayArea().topRunningActivity(
2736                 true /* considerKeyguardState */);
2737         // isNextNotYetVisible is to check if the next activity is invisible, or it has been
2738         // requested to be invisible but its windows haven't reported as invisible.  If so, it
2739         // implied that the current finishing activity should be added into stopping list rather
2740         // than destroy immediately.
2741         final boolean isNextNotYetVisible = next != null
2742                 && (!next.nowVisible || !next.mVisibleRequested);
2743         if (isCurrentVisible && isNextNotYetVisible) {
2744             // Add this activity to the list of stopping activities. It will be processed and
2745             // destroyed when the next activity reports idle.
2746             addToStopping(false /* scheduleIdle */, false /* idleDelayed */,
2747                     "completeFinishing");
2748             setState(STOPPING, "completeFinishing");
2749         } else if (addToFinishingAndWaitForIdle()) {
2750             // We added this activity to the finishing list and something else is becoming resumed.
2751             // The activity will complete finishing when the next activity reports idle. No need to
2752             // do anything else here.
2753         } else {
2754             // Not waiting for the next one to become visible, and nothing else will be resumed in
2755             // place of this activity - requesting destruction right away.
2756             activityRemoved = destroyIfPossible(reason);
2757         }
2758 
2759         return activityRemoved ? null : this;
2760     }
2761 
2762     /**
2763      * Destroy and cleanup the activity both on client and server if possible. If activity is the
2764      * last one left on display with home stack and there is no other running activity - delay
2765      * destroying it until the next one starts.
2766      */
destroyIfPossible(String reason)2767     boolean destroyIfPossible(String reason) {
2768         setState(FINISHING, "destroyIfPossible");
2769 
2770         // Make sure the record is cleaned out of other places.
2771         mStackSupervisor.mStoppingActivities.remove(this);
2772 
2773         final ActivityStack stack = getRootTask();
2774         final TaskDisplayArea taskDisplayArea = getDisplayArea();
2775         // TODO(b/137329632): Exclude current activity when looking for the next one with
2776         // DisplayContent#topRunningActivity().
2777         final ActivityRecord next = taskDisplayArea.topRunningActivity();
2778         final boolean isLastStackOverEmptyHome =
2779                 next == null && stack.isFocusedStackOnDisplay()
2780                         && taskDisplayArea.getOrCreateRootHomeTask() != null;
2781         if (isLastStackOverEmptyHome) {
2782             // Don't destroy activity immediately if this is the last activity on the display and
2783             // the display contains home stack. Although there is no next activity at the moment,
2784             // another home activity should be started later. Keep this activity alive until next
2785             // home activity is resumed. This way the user won't see a temporary black screen.
2786             addToFinishingAndWaitForIdle();
2787             return false;
2788         }
2789         makeFinishingLocked();
2790 
2791         final boolean activityRemoved = destroyImmediately(true /* removeFromApp */,
2792                 "finish-imm:" + reason);
2793 
2794         // If the display does not have running activity, the configuration may need to be
2795         // updated for restoring original orientation of the display.
2796         if (next == null) {
2797             mRootWindowContainer.ensureVisibilityAndConfig(next, getDisplayId(),
2798                     false /* markFrozenIfConfigChanged */, true /* deferResume */);
2799         }
2800         if (activityRemoved) {
2801             mRootWindowContainer.resumeFocusedStacksTopActivities();
2802         }
2803 
2804         if (DEBUG_CONTAINERS) {
2805             Slog.d(TAG_CONTAINERS, "destroyIfPossible: r=" + this + " destroy returned removed="
2806                     + activityRemoved);
2807         }
2808 
2809         return activityRemoved;
2810     }
2811 
2812     /**
2813      * Add this activity to the list of finishing and trigger resuming of activities in focused
2814      * stacks.
2815      * @return {@code true} if some other activity is being resumed as a result of this call.
2816      */
2817     @VisibleForTesting
addToFinishingAndWaitForIdle()2818     boolean addToFinishingAndWaitForIdle() {
2819         if (DEBUG_STATES) Slog.v(TAG, "Enqueueing pending finish: " + this);
2820         setState(FINISHING, "addToFinishingAndWaitForIdle");
2821         if (!mStackSupervisor.mFinishingActivities.contains(this)) {
2822             mStackSupervisor.mFinishingActivities.add(this);
2823         }
2824         resumeKeyDispatchingLocked();
2825         return mRootWindowContainer.resumeFocusedStacksTopActivities();
2826     }
2827 
2828     /**
2829      * Destroy the current CLIENT SIDE instance of an activity. This may be called both when
2830      * actually finishing an activity, or when performing a configuration switch where we destroy
2831      * the current client-side object but then create a new client-side object for this same
2832      * HistoryRecord.
2833      * Normally the server-side record will be removed when the client reports back after
2834      * destruction. If, however, at this point there is no client process attached, the record will
2835      * be removed immediately.
2836      *
2837      * @return {@code true} if activity was immediately removed from history, {@code false}
2838      * otherwise.
2839      */
destroyImmediately(boolean removeFromApp, String reason)2840     boolean destroyImmediately(boolean removeFromApp, String reason) {
2841         if (DEBUG_SWITCH || DEBUG_CLEANUP) {
2842             Slog.v(TAG_SWITCH, "Removing activity from " + reason + ": token=" + this
2843                     + ", app=" + (hasProcess() ? app.mName : "(null)"));
2844         }
2845 
2846         if (isState(DESTROYING, DESTROYED)) {
2847             if (DEBUG_STATES) {
2848                 Slog.v(TAG_STATES, "activity " + this + " already destroying."
2849                         + "skipping request with reason:" + reason);
2850             }
2851             return false;
2852         }
2853 
2854         EventLogTags.writeWmDestroyActivity(mUserId, System.identityHashCode(this),
2855                 task.mTaskId, shortComponentName, reason);
2856 
2857         boolean removedFromHistory = false;
2858 
2859         cleanUp(false /* cleanServices */, false /* setState */);
2860 
2861         if (hasProcess()) {
2862             if (removeFromApp) {
2863                 app.removeActivity(this);
2864                 if (!app.hasActivities()) {
2865                     mAtmService.clearHeavyWeightProcessIfEquals(app);
2866                     // Update any services we are bound to that might care about whether
2867                     // their client may have activities.
2868                     // No longer have activities, so update LRU list and oom adj.
2869                     app.updateProcessInfo(true /* updateServiceConnectionActivities */,
2870                             false /* activityChange */, true /* updateOomAdj */,
2871                             false /* addPendingTopUid */);
2872                 }
2873             }
2874 
2875             boolean skipDestroy = false;
2876 
2877             try {
2878                 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + this);
2879                 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
2880                         DestroyActivityItem.obtain(finishing, configChangeFlags));
2881             } catch (Exception e) {
2882                 // We can just ignore exceptions here...  if the process has crashed, our death
2883                 // notification will clean things up.
2884                 if (finishing) {
2885                     removeFromHistory(reason + " exceptionInScheduleDestroy");
2886                     removedFromHistory = true;
2887                     skipDestroy = true;
2888                 }
2889             }
2890 
2891             nowVisible = false;
2892 
2893             // If the activity is finishing, we need to wait on removing it from the list to give it
2894             // a chance to do its cleanup.  During that time it may make calls back with its token
2895             // so we need to be able to find it on the list and so we don't want to remove it from
2896             // the list yet.  Otherwise, we can just immediately put it in the destroyed state since
2897             // we are not removing it from the list.
2898             if (finishing && !skipDestroy) {
2899                 if (DEBUG_STATES) {
2900                     Slog.v(TAG_STATES, "Moving to DESTROYING: " + this + " (destroy requested)");
2901                 }
2902                 setState(DESTROYING,
2903                         "destroyActivityLocked. finishing and not skipping destroy");
2904                 mAtmService.mH.postDelayed(mDestroyTimeoutRunnable, DESTROY_TIMEOUT);
2905             } else {
2906                 if (DEBUG_STATES) {
2907                     Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (destroy skipped)");
2908                 }
2909                 setState(DESTROYED,
2910                         "destroyActivityLocked. not finishing or skipping destroy");
2911                 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + this);
2912                 app = null;
2913             }
2914         } else {
2915             // Remove this record from the history.
2916             if (finishing) {
2917                 removeFromHistory(reason + " hadNoApp");
2918                 removedFromHistory = true;
2919             } else {
2920                 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (no app)");
2921                 setState(DESTROYED, "destroyActivityLocked. not finishing and had no app");
2922             }
2923         }
2924 
2925         configChangeFlags = 0;
2926 
2927         return removedFromHistory;
2928     }
2929 
safelyDestroy(String reason)2930     boolean safelyDestroy(String reason) {
2931         if (isDestroyable()) {
2932             if (DEBUG_SWITCH) {
2933                 final ActivityStack stack = getRootTask();
2934                 Slog.v(TAG_SWITCH, "Safely destroying " + this + " in state " + getState()
2935                         + " resumed=" + stack.mResumedActivity
2936                         + " pausing=" + stack.mPausingActivity
2937                         + " for reason " + reason);
2938             }
2939             return destroyImmediately(true /* removeFromApp */, reason);
2940         }
2941         return false;
2942     }
2943 
2944     /** Note: call {@link #cleanUp(boolean, boolean)} before this method. */
removeFromHistory(String reason)2945     void removeFromHistory(String reason) {
2946         finishActivityResults(Activity.RESULT_CANCELED,
2947                 null /* resultData */, null /* resultGrants */);
2948         makeFinishingLocked();
2949         if (ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE) {
2950             Slog.i(TAG_ADD_REMOVE, "Removing activity " + this + " from stack callers="
2951                     + Debug.getCallers(5));
2952         }
2953 
2954         takeFromHistory();
2955         removeTimeouts();
2956         if (DEBUG_STATES) {
2957             Slog.v(TAG_STATES, "Moving to DESTROYED: " + this + " (removed from history)");
2958         }
2959         setState(DESTROYED, "removeFromHistory");
2960         if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + this);
2961         app = null;
2962         removeAppTokenFromDisplay();
2963 
2964         cleanUpActivityServices();
2965         removeUriPermissionsLocked();
2966     }
2967 
makeFinishingLocked()2968     void makeFinishingLocked() {
2969         if (finishing) {
2970             return;
2971         }
2972         finishing = true;
2973         if (stopped) {
2974             clearOptionsLocked();
2975         }
2976     }
2977 
2978     /**
2979      * This method is to only be called from the client via binder when the activity is destroyed
2980      * AND finished.
2981      */
destroyed(String reason)2982     void destroyed(String reason) {
2983         removeDestroyTimeout();
2984 
2985         if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + this);
2986 
2987         if (!isState(DESTROYING, DESTROYED)) {
2988             throw new IllegalStateException(
2989                     "Reported destroyed for activity that is not destroying: r=" + this);
2990         }
2991 
2992         if (isInStackLocked()) {
2993             cleanUp(true /* cleanServices */, false /* setState */);
2994             removeFromHistory(reason);
2995         }
2996 
2997         mRootWindowContainer.resumeFocusedStacksTopActivities();
2998     }
2999 
3000     /**
3001      * Perform the common clean-up of an activity record.  This is called both as part of
3002      * destroyActivityLocked() (when destroying the client-side representation) and cleaning things
3003      * up as a result of its hosting processing going away, in which case there is no remaining
3004      * client-side state to destroy so only the cleanup here is needed.
3005      *
3006      * Note: Call before {@link #removeFromHistory(String)}.
3007      */
cleanUp(boolean cleanServices, boolean setState)3008     void cleanUp(boolean cleanServices, boolean setState) {
3009         task.cleanUpActivityReferences(this);
3010 
3011         deferRelaunchUntilPaused = false;
3012         frozenBeforeDestroy = false;
3013 
3014         if (setState) {
3015             setState(DESTROYED, "cleanUp");
3016             if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + this);
3017             app = null;
3018         }
3019 
3020         // Inform supervisor the activity has been removed.
3021         mStackSupervisor.cleanupActivity(this);
3022 
3023         // Remove any pending results.
3024         if (finishing && pendingResults != null) {
3025             for (WeakReference<PendingIntentRecord> apr : pendingResults) {
3026                 PendingIntentRecord rec = apr.get();
3027                 if (rec != null) {
3028                     mAtmService.mPendingIntentController.cancelIntentSender(rec,
3029                             false /* cleanActivity */);
3030                 }
3031             }
3032             pendingResults = null;
3033         }
3034 
3035         if (cleanServices) {
3036             cleanUpActivityServices();
3037         }
3038 
3039         // Get rid of any pending idle timeouts.
3040         removeTimeouts();
3041         // Clean-up activities are no longer relaunching (e.g. app process died). Notify window
3042         // manager so it can update its bookkeeping.
3043         clearRelaunching();
3044     }
3045 
isRelaunching()3046     boolean isRelaunching() {
3047         return mPendingRelaunchCount > 0;
3048     }
3049 
shouldFreezeBounds()3050     boolean shouldFreezeBounds() {
3051         // For freeform windows, we can't freeze the bounds at the moment because this would make
3052         // the resizing unresponsive.
3053         if (task == null || task.inFreeformWindowingMode()) {
3054             return false;
3055         }
3056 
3057         // We freeze the bounds while drag resizing to deal with the time between
3058         // the divider/drag handle being released, and the handling it's new
3059         // configuration. If we are relaunched outside of the drag resizing state,
3060         // we need to be careful not to do this.
3061         return task.isDragResizing();
3062     }
3063 
startRelaunching()3064     void startRelaunching() {
3065         if (shouldFreezeBounds()) {
3066             freezeBounds();
3067         }
3068 
3069         // In the process of tearing down before relaunching, the app will
3070         // try and clean up it's child surfaces. We need to prevent this from
3071         // happening, so we sever the children, transfering their ownership
3072         // from the client it-self to the parent surface (owned by us).
3073         detachChildren();
3074 
3075         mPendingRelaunchCount++;
3076     }
3077 
3078     /**
3079      * Freezes the task bounds. The size of this task reported the app will be fixed to the bounds
3080      * freezed by {@link Task#prepareFreezingBounds} until {@link #unfreezeBounds} gets called, even
3081      * if they change in the meantime. If the bounds are already frozen, the bounds will be frozen
3082      * with a queue.
3083      */
freezeBounds()3084     private void freezeBounds() {
3085         mFrozenBounds.offer(new Rect(task.mPreparedFrozenBounds));
3086 
3087         if (task.mPreparedFrozenMergedConfig.equals(Configuration.EMPTY)) {
3088             // We didn't call prepareFreezingBounds on the task, so use the current value.
3089             mFrozenMergedConfig.offer(new Configuration(task.getConfiguration()));
3090         } else {
3091             mFrozenMergedConfig.offer(new Configuration(task.mPreparedFrozenMergedConfig));
3092         }
3093         // Calling unset() to make it equal to Configuration.EMPTY.
3094         task.mPreparedFrozenMergedConfig.unset();
3095     }
3096 
detachChildren()3097     void detachChildren() {
3098         SurfaceControl.openTransaction();
3099         for (int i = mChildren.size() - 1; i >= 0; i--) {
3100             final WindowState w = mChildren.get(i);
3101             w.mWinAnimator.detachChildren();
3102         }
3103         SurfaceControl.closeTransaction();
3104     }
3105 
finishRelaunching()3106     void finishRelaunching() {
3107         unfreezeBounds();
3108 
3109         if (mPendingRelaunchCount > 0) {
3110             mPendingRelaunchCount--;
3111         } else {
3112             // Update keyguard flags upon finishing relaunch.
3113             checkKeyguardFlagsChanged();
3114         }
3115     }
3116 
clearRelaunching()3117     void clearRelaunching() {
3118         if (mPendingRelaunchCount == 0) {
3119             return;
3120         }
3121         unfreezeBounds();
3122         mPendingRelaunchCount = 0;
3123     }
3124 
3125     /**
3126      * Unfreezes the previously frozen bounds. See {@link #freezeBounds}.
3127      */
unfreezeBounds()3128     private void unfreezeBounds() {
3129         if (mFrozenBounds.isEmpty()) {
3130             return;
3131         }
3132         mFrozenBounds.remove();
3133         if (!mFrozenMergedConfig.isEmpty()) {
3134             mFrozenMergedConfig.remove();
3135         }
3136         for (int i = mChildren.size() - 1; i >= 0; i--) {
3137             final WindowState win = mChildren.get(i);
3138             win.onUnfreezeBounds();
3139         }
3140         mWmService.mWindowPlacerLocked.performSurfacePlacement();
3141     }
3142 
3143     /**
3144      * Perform clean-up of service connections in an activity record.
3145      */
cleanUpActivityServices()3146     private void cleanUpActivityServices() {
3147         if (mServiceConnectionsHolder == null) {
3148             return;
3149         }
3150         // Throw away any services that have been bound by this activity.
3151         mServiceConnectionsHolder.disconnectActivityFromServices();
3152         // This activity record is removing, make sure not to disconnect twice.
3153         mServiceConnectionsHolder = null;
3154     }
3155 
3156     @Override
removeImmediately()3157     void removeImmediately() {
3158         onRemovedFromDisplay();
3159         super.removeImmediately();
3160     }
3161 
3162     @Override
removeIfPossible()3163     void removeIfPossible() {
3164         mIsExiting = false;
3165         removeAllWindowsIfPossible();
3166         removeImmediately();
3167     }
3168 
3169     @Override
handleCompleteDeferredRemoval()3170     boolean handleCompleteDeferredRemoval() {
3171         if (mIsExiting) {
3172             removeIfPossible();
3173         }
3174         return super.handleCompleteDeferredRemoval();
3175     }
3176 
onRemovedFromDisplay()3177     void onRemovedFromDisplay() {
3178         if (mRemovingFromDisplay) {
3179             return;
3180         }
3181         mRemovingFromDisplay = true;
3182 
3183         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS, "Removing app token: %s", this);
3184 
3185         commitVisibility(false /* visible */, true /* performLayout */);
3186 
3187         getDisplayContent().mOpeningApps.remove(this);
3188         getDisplayContent().mUnknownAppVisibilityController.appRemovedOrHidden(this);
3189         mWmService.mTaskSnapshotController.onAppRemoved(this);
3190         mStackSupervisor.getActivityMetricsLogger().notifyActivityRemoved(this);
3191         waitingToShow = false;
3192 
3193         // Defer removal of this activity when either a child is animating, or app transition is on
3194         // going. App transition animation might be applied on the parent stack not on the activity,
3195         // but the actual frame buffer is associated with the activity, so we have to keep the
3196         // activity while a parent is animating.
3197         boolean delayed = isAnimating(TRANSITION | PARENTS | CHILDREN);
3198         if (getDisplayContent().mClosingApps.contains(this)) {
3199             delayed = true;
3200         } else if (getDisplayContent().mAppTransition.isTransitionSet()) {
3201             getDisplayContent().mClosingApps.add(this);
3202             delayed = true;
3203         }
3204 
3205         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
3206                 "Removing app %s delayed=%b animation=%s animating=%b", this, delayed,
3207                 getAnimation(), isAnimating(TRANSITION | PARENTS));
3208 
3209         ProtoLog.v(WM_DEBUG_ADD_REMOVE, "removeAppToken: %s"
3210                 + " delayed=%b Callers=%s", this, delayed, Debug.getCallers(4));
3211 
3212         if (mStartingData != null) {
3213             removeStartingWindow();
3214         }
3215 
3216         // If this window was animating, then we need to ensure that the app transition notifies
3217         // that animations have completed in DisplayContent.handleAnimatingStoppedAndTransition(),
3218         // so add to that list now
3219         if (isAnimating(TRANSITION | PARENTS)) {
3220             getDisplayContent().mNoAnimationNotifyOnTransitionFinished.add(token);
3221         }
3222 
3223         final ActivityStack stack = getStack();
3224         if (delayed && !isEmpty()) {
3225             // set the token aside because it has an active animation to be finished
3226             ProtoLog.v(WM_DEBUG_ADD_REMOVE,
3227                     "removeAppToken make exiting: %s", this);
3228             if (stack != null) {
3229                 stack.mExitingActivities.add(this);
3230             }
3231             mIsExiting = true;
3232         } else {
3233             // Make sure there is no animation running on this token, so any windows associated
3234             // with it will be removed as soon as their animations are complete
3235             cancelAnimation();
3236             if (stack != null) {
3237                 stack.mExitingActivities.remove(this);
3238             }
3239             removeIfPossible();
3240         }
3241 
3242         stopFreezingScreen(true, true);
3243 
3244         final DisplayContent dc = getDisplayContent();
3245         if (dc.mFocusedApp == this) {
3246             ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
3247                     "Removing focused app token:%s displayId=%d", this,
3248                     dc.getDisplayId());
3249             dc.setFocusedApp(null);
3250             mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
3251         }
3252         if (mLetterbox != null) {
3253             mLetterbox.destroy();
3254             mLetterbox = null;
3255         }
3256 
3257         if (!delayed) {
3258             updateReportedVisibilityLocked();
3259         }
3260 
3261         // Reset the last saved PiP snap fraction on removal.
3262         mDisplayContent.mPinnedStackControllerLocked.onActivityHidden(mActivityComponent);
3263         mWmService.mEmbeddedWindowController.onActivityRemoved(this);
3264         mRemovingFromDisplay = false;
3265     }
3266 
3267     /**
3268      * Returns true if the new child window we are adding to this token is considered greater than
3269      * the existing child window in this token in terms of z-order.
3270      */
3271     @Override
isFirstChildWindowGreaterThanSecond(WindowState newWindow, WindowState existingWindow)3272     protected boolean isFirstChildWindowGreaterThanSecond(WindowState newWindow,
3273             WindowState existingWindow) {
3274         final int type1 = newWindow.mAttrs.type;
3275         final int type2 = existingWindow.mAttrs.type;
3276 
3277         // Base application windows should be z-ordered BELOW all other windows in the app token.
3278         if (type1 == TYPE_BASE_APPLICATION && type2 != TYPE_BASE_APPLICATION) {
3279             return false;
3280         } else if (type1 != TYPE_BASE_APPLICATION && type2 == TYPE_BASE_APPLICATION) {
3281             return true;
3282         }
3283 
3284         // Starting windows should be z-ordered ABOVE all other windows in the app token.
3285         if (type1 == TYPE_APPLICATION_STARTING && type2 != TYPE_APPLICATION_STARTING) {
3286             return true;
3287         } else if (type1 != TYPE_APPLICATION_STARTING && type2 == TYPE_APPLICATION_STARTING) {
3288             return false;
3289         }
3290 
3291         // Otherwise the new window is greater than the existing window.
3292         return true;
3293     }
3294 
3295     /**
3296      * @return {@code true} if starting window is in app's hierarchy.
3297      */
hasStartingWindow()3298     boolean hasStartingWindow() {
3299         if (startingDisplayed || mStartingData != null) {
3300             return true;
3301         }
3302         for (int i = mChildren.size() - 1; i >= 0; i--) {
3303             if (getChildAt(i).mAttrs.type == TYPE_APPLICATION_STARTING) {
3304                 return true;
3305             }
3306         }
3307         return false;
3308     }
3309 
isLastWindow(WindowState win)3310     boolean isLastWindow(WindowState win) {
3311         return mChildren.size() == 1 && mChildren.get(0) == win;
3312     }
3313 
3314     @Override
addWindow(WindowState w)3315     void addWindow(WindowState w) {
3316         super.addWindow(w);
3317 
3318         boolean gotReplacementWindow = false;
3319         for (int i = mChildren.size() - 1; i >= 0; i--) {
3320             final WindowState candidate = mChildren.get(i);
3321             gotReplacementWindow |= candidate.setReplacementWindowIfNeeded(w);
3322         }
3323 
3324         // if we got a replacement window, reset the timeout to give drawing more time
3325         if (gotReplacementWindow) {
3326             mWmService.scheduleWindowReplacementTimeouts(this);
3327         }
3328         checkKeyguardFlagsChanged();
3329     }
3330 
3331     @Override
removeChild(WindowState child)3332     void removeChild(WindowState child) {
3333         if (!mChildren.contains(child)) {
3334             // This can be true when testing.
3335             return;
3336         }
3337         super.removeChild(child);
3338         checkKeyguardFlagsChanged();
3339         updateLetterboxSurface(child);
3340     }
3341 
onWindowReplacementTimeout()3342     void onWindowReplacementTimeout() {
3343         for (int i = mChildren.size() - 1; i >= 0; --i) {
3344             (mChildren.get(i)).onWindowReplacementTimeout();
3345         }
3346     }
3347 
setAppLayoutChanges(int changes, String reason)3348     void setAppLayoutChanges(int changes, String reason) {
3349         if (!mChildren.isEmpty()) {
3350             final DisplayContent dc = getDisplayContent();
3351             dc.pendingLayoutChanges |= changes;
3352             if (DEBUG_LAYOUT_REPEATS) {
3353                 mWmService.mWindowPlacerLocked.debugLayoutRepeats(reason, dc.pendingLayoutChanges);
3354             }
3355         }
3356     }
3357 
removeReplacedWindowIfNeeded(WindowState replacement)3358     void removeReplacedWindowIfNeeded(WindowState replacement) {
3359         for (int i = mChildren.size() - 1; i >= 0; i--) {
3360             final WindowState win = mChildren.get(i);
3361             if (win.removeReplacedWindowIfNeeded(replacement)) {
3362                 return;
3363             }
3364         }
3365     }
3366 
transferStartingWindow(IBinder transferFrom)3367     boolean transferStartingWindow(IBinder transferFrom) {
3368         final ActivityRecord fromActivity = getDisplayContent().getActivityRecord(transferFrom);
3369         if (fromActivity == null) {
3370             return false;
3371         }
3372 
3373         final WindowState tStartingWindow = fromActivity.startingWindow;
3374         if (tStartingWindow != null && fromActivity.startingSurface != null) {
3375             // In this case, the starting icon has already been displayed, so start
3376             // letting windows get shown immediately without any more transitions.
3377             getDisplayContent().mSkipAppTransitionAnimation = true;
3378 
3379             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Moving existing starting %s"
3380                     + " from %s to %s", tStartingWindow, fromActivity, this);
3381 
3382             final long origId = Binder.clearCallingIdentity();
3383             try {
3384                 // Link the fixed rotation transform to this activity since we are transferring the
3385                 // starting window.
3386                 if (fromActivity.hasFixedRotationTransform()) {
3387                     mDisplayContent.handleTopActivityLaunchingInDifferentOrientation(this,
3388                             false /* checkOpening */);
3389                 }
3390 
3391                 // Transfer the starting window over to the new token.
3392                 mStartingData = fromActivity.mStartingData;
3393                 startingSurface = fromActivity.startingSurface;
3394                 startingDisplayed = fromActivity.startingDisplayed;
3395                 fromActivity.startingDisplayed = false;
3396                 startingWindow = tStartingWindow;
3397                 reportedVisible = fromActivity.reportedVisible;
3398                 fromActivity.mStartingData = null;
3399                 fromActivity.startingSurface = null;
3400                 fromActivity.startingWindow = null;
3401                 fromActivity.startingMoved = true;
3402                 tStartingWindow.mToken = this;
3403                 tStartingWindow.mActivityRecord = this;
3404 
3405                 ProtoLog.v(WM_DEBUG_ADD_REMOVE,
3406                         "Removing starting %s from %s", tStartingWindow, fromActivity);
3407                 fromActivity.removeChild(tStartingWindow);
3408                 addWindow(tStartingWindow);
3409 
3410                 // Propagate other interesting state between the tokens. If the old token is displayed,
3411                 // we should immediately force the new one to be displayed. If it is animating, we need
3412                 // to move that animation to the new one.
3413                 if (fromActivity.allDrawn) {
3414                     allDrawn = true;
3415                 }
3416                 if (fromActivity.firstWindowDrawn) {
3417                     firstWindowDrawn = true;
3418                 }
3419                 if (fromActivity.isVisible()) {
3420                     setVisible(true);
3421                     mVisibleRequested = true;
3422                     mVisibleSetFromTransferredStartingWindow = true;
3423                 }
3424                 setClientVisible(fromActivity.mClientVisible);
3425 
3426                 if (fromActivity.isAnimating()) {
3427                     transferAnimation(fromActivity);
3428 
3429                     // When transferring an animation, we no longer need to apply an animation to
3430                     // the token we transfer the animation over. Thus, set this flag to indicate
3431                     // we've transferred the animation.
3432                     mUseTransferredAnimation = true;
3433                 }
3434                 // Post cleanup after the visibility and animation are transferred.
3435                 fromActivity.postWindowRemoveStartingWindowCleanup(tStartingWindow);
3436                 fromActivity.mVisibleSetFromTransferredStartingWindow = false;
3437 
3438                 mWmService.updateFocusedWindowLocked(
3439                         UPDATE_FOCUS_WILL_PLACE_SURFACES, true /*updateInputWindows*/);
3440                 getDisplayContent().setLayoutNeeded();
3441                 mWmService.mWindowPlacerLocked.performSurfacePlacement();
3442             } finally {
3443                 Binder.restoreCallingIdentity(origId);
3444             }
3445             return true;
3446         } else if (fromActivity.mStartingData != null) {
3447             // The previous app was getting ready to show a
3448             // starting window, but hasn't yet done so.  Steal it!
3449             ProtoLog.v(WM_DEBUG_STARTING_WINDOW,
3450                     "Moving pending starting from %s to %s", fromActivity, this);
3451             mStartingData = fromActivity.mStartingData;
3452             fromActivity.mStartingData = null;
3453             fromActivity.startingMoved = true;
3454             scheduleAddStartingWindow();
3455             return true;
3456         }
3457 
3458         // TODO: Transfer thumbnail
3459 
3460         return false;
3461     }
3462 
3463     /**
3464      * Tries to transfer the starting window from a token that's above ourselves in the task but
3465      * not visible anymore. This is a common scenario apps use: Trampoline activity T start main
3466      * activity M in the same task. Now, when reopening the task, T starts on top of M but then
3467      * immediately finishes after, so we have to transfer T to M.
3468      */
transferStartingWindowFromHiddenAboveTokenIfNeeded()3469     void transferStartingWindowFromHiddenAboveTokenIfNeeded() {
3470         final PooledFunction p = PooledLambda.obtainFunction(ActivityRecord::transferStartingWindow,
3471                 this, PooledLambda.__(ActivityRecord.class));
3472         task.forAllActivities(p);
3473         p.recycle();
3474     }
3475 
transferStartingWindow(ActivityRecord fromActivity)3476     private boolean transferStartingWindow(ActivityRecord fromActivity) {
3477         if (fromActivity == this) return true;
3478 
3479         return !fromActivity.mVisibleRequested && transferStartingWindow(fromActivity.token);
3480     }
3481 
checkKeyguardFlagsChanged()3482     void checkKeyguardFlagsChanged() {
3483         final boolean containsDismissKeyguard = containsDismissKeyguardWindow();
3484         final boolean containsShowWhenLocked = containsShowWhenLockedWindow();
3485         if (containsDismissKeyguard != mLastContainsDismissKeyguardWindow
3486                 || containsShowWhenLocked != mLastContainsShowWhenLockedWindow) {
3487             mWmService.notifyKeyguardFlagsChanged(null /* callback */,
3488                     getDisplayContent().getDisplayId());
3489         }
3490         mLastContainsDismissKeyguardWindow = containsDismissKeyguard;
3491         mLastContainsShowWhenLockedWindow = containsShowWhenLocked;
3492         mLastContainsTurnScreenOnWindow = containsTurnScreenOnWindow();
3493     }
3494 
containsDismissKeyguardWindow()3495     boolean containsDismissKeyguardWindow() {
3496         // Window state is transient during relaunch. We are not guaranteed to be frozen during the
3497         // entirety of the relaunch.
3498         if (isRelaunching()) {
3499             return mLastContainsDismissKeyguardWindow;
3500         }
3501 
3502         for (int i = mChildren.size() - 1; i >= 0; i--) {
3503             if ((mChildren.get(i).mAttrs.flags & FLAG_DISMISS_KEYGUARD) != 0) {
3504                 return true;
3505             }
3506         }
3507         return false;
3508     }
3509 
containsShowWhenLockedWindow()3510     boolean containsShowWhenLockedWindow() {
3511         // When we are relaunching, it is possible for us to be unfrozen before our previous
3512         // windows have been added back. Using the cached value ensures that our previous
3513         // showWhenLocked preference is honored until relaunching is complete.
3514         if (isRelaunching()) {
3515             return mLastContainsShowWhenLockedWindow;
3516         }
3517 
3518         for (int i = mChildren.size() - 1; i >= 0; i--) {
3519             if ((mChildren.get(i).mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0) {
3520                 return true;
3521             }
3522         }
3523 
3524         return false;
3525     }
3526 
setShowWhenLocked(boolean showWhenLocked)3527     void setShowWhenLocked(boolean showWhenLocked) {
3528         mShowWhenLocked = showWhenLocked;
3529         mAtmService.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
3530                 0 /* configChanges */, false /* preserveWindows */);
3531     }
3532 
setInheritShowWhenLocked(boolean inheritShowWhenLocked)3533     void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
3534         mInheritShownWhenLocked = inheritShowWhenLocked;
3535         mAtmService.mRootWindowContainer.ensureActivitiesVisible(null /* starting */,
3536                 0 /* configChanges */, false /* preserveWindows */);
3537     }
3538 
3539     /**
3540      * @return {@code true} if the activity windowing mode is not
3541      *         {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
3542      *         contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
3543      *         activity has set {@link #mShowWhenLocked}, or b) if the activity has set
3544      *         {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
3545      *         conditions a) above.
3546      *         Multi-windowing mode will be exited if {@code true} is returned.
3547      */
canShowWhenLocked()3548     boolean canShowWhenLocked() {
3549         if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
3550             return true;
3551         } else if (mInheritShownWhenLocked) {
3552             final ActivityRecord r = task.getActivityBelow(this);
3553             return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
3554                     || r.containsShowWhenLockedWindow());
3555         } else {
3556             return false;
3557         }
3558     }
3559 
3560     /**
3561      * @return Whether we are allowed to show non-starting windows at the moment. We disallow
3562      *         showing windows during transitions in case we have windows that have wide-color-gamut
3563      *         color mode set to avoid jank in the middle of the transition.
3564      */
canShowWindows()3565     boolean canShowWindows() {
3566         return allDrawn && !(isAnimating(PARENTS) && hasNonDefaultColorWindow());
3567     }
3568 
3569     /**
3570      * @return true if we have a window that has a non-default color mode set; false otherwise.
3571      */
hasNonDefaultColorWindow()3572     private boolean hasNonDefaultColorWindow() {
3573         return forAllWindows(ws -> ws.mAttrs.getColorMode() != COLOR_MODE_DEFAULT,
3574                 true /* topToBottom */);
3575     }
3576 
getImeTargetBelowWindow(WindowState w)3577     WindowState getImeTargetBelowWindow(WindowState w) {
3578         final int index = mChildren.indexOf(w);
3579         if (index > 0) {
3580             return mChildren.get(index - 1)
3581                     .getWindow(WindowState::canBeImeTarget);
3582         }
3583         return null;
3584     }
3585 
getHighestAnimLayerWindow(WindowState currentTarget)3586     WindowState getHighestAnimLayerWindow(WindowState currentTarget) {
3587         WindowState candidate = null;
3588         for (int i = mChildren.indexOf(currentTarget); i >= 0; i--) {
3589             final WindowState w = mChildren.get(i);
3590             if (w.mRemoved) {
3591                 continue;
3592             }
3593             if (candidate == null) {
3594                 candidate = w;
3595             }
3596         }
3597         return candidate;
3598     }
3599 
3600     @Override
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)3601     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
3602         // For legacy reasons we process the TaskStack.mExitingActivities first in DisplayContent
3603         // before the non-exiting app tokens. So, we skip the exiting app tokens here.
3604         // TODO: Investigate if we need to continue to do this or if we can just process them
3605         // in-order.
3606         if (mIsExiting && !forAllWindowsUnchecked(WindowState::waitingForReplacement, true)) {
3607             return false;
3608         }
3609         return forAllWindowsUnchecked(callback, traverseTopToBottom);
3610     }
3611 
forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)3612     boolean forAllWindowsUnchecked(ToBooleanFunction<WindowState> callback,
3613             boolean traverseTopToBottom) {
3614         return super.forAllWindows(callback, traverseTopToBottom);
3615     }
3616 
3617     @Override
forAllActivities( Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom)3618     boolean forAllActivities(
3619             Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
3620         return callback.apply(this);
3621     }
3622 
3623     @Override
forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom)3624     void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
3625         callback.accept(this);
3626     }
3627 
3628     @Override
getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom, ActivityRecord boundary)3629     ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
3630             ActivityRecord boundary) {
3631         return callback.test(this) ? this : null;
3632     }
3633 
3634     @Override
setLayer(Transaction t, int layer)3635     protected void setLayer(Transaction t, int layer) {
3636         if (!mSurfaceAnimator.hasLeash()) {
3637             t.setLayer(mSurfaceControl, layer);
3638         }
3639     }
3640 
3641     @Override
setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer)3642     protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
3643         if (!mSurfaceAnimator.hasLeash()) {
3644             t.setRelativeLayer(mSurfaceControl, relativeTo, layer);
3645         }
3646     }
3647 
3648     @Override
reparentSurfaceControl(Transaction t, SurfaceControl newParent)3649     protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
3650         if (!mSurfaceAnimator.hasLeash()) {
3651             t.reparent(mSurfaceControl, newParent);
3652         }
3653     }
3654 
logStartActivity(int tag, Task task)3655     void logStartActivity(int tag, Task task) {
3656         final Uri data = intent.getData();
3657         final String strData = data != null ? data.toSafeString() : null;
3658 
3659         EventLog.writeEvent(tag,
3660                 mUserId, System.identityHashCode(this), task.mTaskId,
3661                 shortComponentName, intent.getAction(),
3662                 intent.getType(), strData, intent.getFlags());
3663     }
3664 
getUriPermissionsLocked()3665     UriPermissionOwner getUriPermissionsLocked() {
3666         if (uriPermissions == null) {
3667             uriPermissions = new UriPermissionOwner(mAtmService.mUgmInternal, this);
3668         }
3669         return uriPermissions;
3670     }
3671 
addResultLocked(ActivityRecord from, String resultWho, int requestCode, int resultCode, Intent resultData)3672     void addResultLocked(ActivityRecord from, String resultWho,
3673             int requestCode, int resultCode,
3674             Intent resultData) {
3675         ActivityResult r = new ActivityResult(from, resultWho,
3676                 requestCode, resultCode, resultData);
3677         if (results == null) {
3678             results = new ArrayList<ResultInfo>();
3679         }
3680         results.add(r);
3681     }
3682 
removeResultsLocked(ActivityRecord from, String resultWho, int requestCode)3683     void removeResultsLocked(ActivityRecord from, String resultWho,
3684             int requestCode) {
3685         if (results != null) {
3686             for (int i=results.size()-1; i>=0; i--) {
3687                 ActivityResult r = (ActivityResult)results.get(i);
3688                 if (r.mFrom != from) continue;
3689                 if (r.mResultWho == null) {
3690                     if (resultWho != null) continue;
3691                 } else {
3692                     if (!r.mResultWho.equals(resultWho)) continue;
3693                 }
3694                 if (r.mRequestCode != requestCode) continue;
3695 
3696                 results.remove(i);
3697             }
3698         }
3699     }
3700 
sendResult(int callingUid, String resultWho, int requestCode, int resultCode, Intent data, NeededUriGrants dataGrants)3701     void sendResult(int callingUid, String resultWho, int requestCode, int resultCode,
3702             Intent data, NeededUriGrants dataGrants) {
3703         if (callingUid > 0) {
3704             mAtmService.mUgmInternal.grantUriPermissionUncheckedFromIntent(dataGrants,
3705                     getUriPermissionsLocked());
3706         }
3707 
3708         if (DEBUG_RESULTS) {
3709             Slog.v(TAG, "Send activity result to " + this
3710                     + " : who=" + resultWho + " req=" + requestCode
3711                     + " res=" + resultCode + " data=" + data);
3712         }
3713         if (isState(RESUMED) && attachedToProcess()) {
3714             try {
3715                 final ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3716                 list.add(new ResultInfo(resultWho, requestCode, resultCode, data));
3717                 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
3718                         ActivityResultItem.obtain(list));
3719                 return;
3720             } catch (Exception e) {
3721                 Slog.w(TAG, "Exception thrown sending result to " + this, e);
3722             }
3723         }
3724 
3725         addResultLocked(null /* from */, resultWho, requestCode, resultCode, data);
3726     }
3727 
addNewIntentLocked(ReferrerIntent intent)3728     private void addNewIntentLocked(ReferrerIntent intent) {
3729         if (newIntents == null) {
3730             newIntents = new ArrayList<>();
3731         }
3732         newIntents.add(intent);
3733     }
3734 
isSleeping()3735     final boolean isSleeping() {
3736         final ActivityStack stack = getRootTask();
3737         return stack != null ? stack.shouldSleepActivities() : mAtmService.isSleepingLocked();
3738     }
3739 
3740     /**
3741      * Deliver a new Intent to an existing activity, so that its onNewIntent()
3742      * method will be called at the proper time.
3743      */
deliverNewIntentLocked(int callingUid, Intent intent, NeededUriGrants intentGrants, String referrer)3744     final void deliverNewIntentLocked(int callingUid, Intent intent, NeededUriGrants intentGrants,
3745             String referrer) {
3746         // The activity now gets access to the data associated with this Intent.
3747         mAtmService.mUgmInternal.grantUriPermissionUncheckedFromIntent(intentGrants,
3748                 getUriPermissionsLocked());
3749         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
3750         boolean unsent = true;
3751         final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
3752 
3753         // We want to immediately deliver the intent to the activity if:
3754         // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
3755         //   the user to see the visual effects caused by the intent delivery now.
3756         // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
3757         if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
3758                 && attachedToProcess()) {
3759             try {
3760                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
3761                 ar.add(rintent);
3762                 // Making sure the client state is RESUMED after transaction completed and doing
3763                 // so only if activity is currently RESUMED. Otherwise, client may have extra
3764                 // life-cycle calls to RESUMED (and PAUSED later).
3765                 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
3766                         NewIntentItem.obtain(ar, mState == RESUMED));
3767                 unsent = false;
3768             } catch (RemoteException e) {
3769                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
3770             } catch (NullPointerException e) {
3771                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
3772             }
3773         }
3774         if (unsent) {
3775             addNewIntentLocked(rintent);
3776         }
3777     }
3778 
updateOptionsLocked(ActivityOptions options)3779     void updateOptionsLocked(ActivityOptions options) {
3780         if (options != null) {
3781             if (DEBUG_TRANSITION) Slog.i(TAG, "Update options for " + this);
3782             if (pendingOptions != null) {
3783                 pendingOptions.abort();
3784             }
3785             pendingOptions = options;
3786         }
3787     }
3788 
applyOptionsLocked()3789     void applyOptionsLocked() {
3790         if (pendingOptions != null
3791                 && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
3792             if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
3793             applyOptionsLocked(pendingOptions, intent);
3794             if (task == null) {
3795                 clearOptionsLocked(false /* withAbort */);
3796             } else {
3797                 // This will clear the options for all the ActivityRecords for this Task.
3798                 task.forAllActivities((r) -> {
3799                     r.clearOptionsLocked(false /* withAbort */);
3800                 });
3801             }
3802         }
3803     }
3804 
3805     /**
3806      * Apply override app transition base on options & animation type.
3807      */
applyOptionsLocked(ActivityOptions pendingOptions, Intent intent)3808     void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
3809         final int animationType = pendingOptions.getAnimationType();
3810         final DisplayContent displayContent = getDisplayContent();
3811         switch (animationType) {
3812             case ANIM_CUSTOM:
3813                 displayContent.mAppTransition.overridePendingAppTransition(
3814                         pendingOptions.getPackageName(),
3815                         pendingOptions.getCustomEnterResId(),
3816                         pendingOptions.getCustomExitResId(),
3817                         pendingOptions.getAnimationStartedListener(),
3818                         pendingOptions.getAnimationFinishedListener());
3819                 break;
3820             case ANIM_CLIP_REVEAL:
3821                 displayContent.mAppTransition.overridePendingAppTransitionClipReveal(
3822                         pendingOptions.getStartX(), pendingOptions.getStartY(),
3823                         pendingOptions.getWidth(), pendingOptions.getHeight());
3824                 if (intent.getSourceBounds() == null) {
3825                     intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3826                             pendingOptions.getStartY(),
3827                             pendingOptions.getStartX() + pendingOptions.getWidth(),
3828                             pendingOptions.getStartY() + pendingOptions.getHeight()));
3829                 }
3830                 break;
3831             case ANIM_SCALE_UP:
3832                 displayContent.mAppTransition.overridePendingAppTransitionScaleUp(
3833                         pendingOptions.getStartX(), pendingOptions.getStartY(),
3834                         pendingOptions.getWidth(), pendingOptions.getHeight());
3835                 if (intent.getSourceBounds() == null) {
3836                     intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3837                             pendingOptions.getStartY(),
3838                             pendingOptions.getStartX() + pendingOptions.getWidth(),
3839                             pendingOptions.getStartY() + pendingOptions.getHeight()));
3840                 }
3841                 break;
3842             case ANIM_THUMBNAIL_SCALE_UP:
3843             case ANIM_THUMBNAIL_SCALE_DOWN:
3844                 final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
3845                 final GraphicBuffer buffer = pendingOptions.getThumbnail();
3846                 displayContent.mAppTransition.overridePendingAppTransitionThumb(buffer,
3847                         pendingOptions.getStartX(), pendingOptions.getStartY(),
3848                         pendingOptions.getAnimationStartedListener(),
3849                         scaleUp);
3850                 if (intent.getSourceBounds() == null && buffer != null) {
3851                     intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3852                             pendingOptions.getStartY(),
3853                             pendingOptions.getStartX() + buffer.getWidth(),
3854                             pendingOptions.getStartY() + buffer.getHeight()));
3855                 }
3856                 break;
3857             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
3858             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
3859                 final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
3860                 final IAppTransitionAnimationSpecsFuture specsFuture =
3861                         pendingOptions.getSpecsFuture();
3862                 if (specsFuture != null) {
3863                     displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(
3864                             specsFuture, pendingOptions.getAnimationStartedListener(),
3865                             animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
3866                 } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
3867                         && specs != null) {
3868                     displayContent.mAppTransition.overridePendingAppTransitionMultiThumb(
3869                             specs, pendingOptions.getAnimationStartedListener(),
3870                             pendingOptions.getAnimationFinishedListener(), false);
3871                 } else {
3872                     displayContent.mAppTransition.overridePendingAppTransitionAspectScaledThumb(
3873                             pendingOptions.getThumbnail(),
3874                             pendingOptions.getStartX(), pendingOptions.getStartY(),
3875                             pendingOptions.getWidth(), pendingOptions.getHeight(),
3876                             pendingOptions.getAnimationStartedListener(),
3877                             (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
3878                     if (intent.getSourceBounds() == null) {
3879                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
3880                                 pendingOptions.getStartY(),
3881                                 pendingOptions.getStartX() + pendingOptions.getWidth(),
3882                                 pendingOptions.getStartY() + pendingOptions.getHeight()));
3883                     }
3884                 }
3885                 break;
3886             case ANIM_OPEN_CROSS_PROFILE_APPS:
3887                 displayContent.mAppTransition
3888                         .overridePendingAppTransitionStartCrossProfileApps();
3889                 break;
3890             case ANIM_REMOTE_ANIMATION:
3891                 displayContent.mAppTransition.overridePendingAppTransitionRemote(
3892                         pendingOptions.getRemoteAnimationAdapter());
3893                 break;
3894             case ANIM_NONE:
3895             case ANIM_UNDEFINED:
3896                 break;
3897             default:
3898                 Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
3899                 break;
3900         }
3901     }
3902 
clearAllDrawn()3903     void clearAllDrawn() {
3904         allDrawn = false;
3905     }
3906 
3907     /**
3908      * Returns whether the drawn window states of this {@link ActivityRecord} has considered every
3909      * child {@link WindowState}. A child is considered if it has been passed into
3910      * {@link #updateDrawnWindowStates(WindowState)} after being added. This is used to determine
3911      * whether states, such as {@code allDrawn}, can be set, which relies on state variables such as
3912      * {@code mNumInterestingWindows}, which depend on all {@link WindowState}s being considered.
3913      *
3914      * @return {@code true} If all children have been considered, {@code false}.
3915      */
allDrawnStatesConsidered()3916     private boolean allDrawnStatesConsidered() {
3917         for (int i = mChildren.size() - 1; i >= 0; --i) {
3918             final WindowState child = mChildren.get(i);
3919             if (child.mightAffectAllDrawn() && !child.getDrawnStateEvaluated()) {
3920                 return false;
3921             }
3922         }
3923         return true;
3924     }
3925 
3926     /**
3927      *  Determines if the token has finished drawing. This should only be called from
3928      *  {@link DisplayContent#applySurfaceChangesTransaction}
3929      */
updateAllDrawn()3930     void updateAllDrawn() {
3931         if (!allDrawn) {
3932             // Number of drawn windows can be less when a window is being relaunched, wait for
3933             // all windows to be launched and drawn for this token be considered all drawn.
3934             final int numInteresting = mNumInterestingWindows;
3935 
3936             // We must make sure that all present children have been considered (determined by
3937             // {@link #allDrawnStatesConsidered}) before evaluating whether everything has been
3938             // drawn.
3939             if (numInteresting > 0 && allDrawnStatesConsidered()
3940                     && mNumDrawnWindows >= numInteresting && !isRelaunching()) {
3941                 if (DEBUG_VISIBILITY) Slog.v(TAG, "allDrawn: " + this
3942                         + " interesting=" + numInteresting + " drawn=" + mNumDrawnWindows);
3943                 allDrawn = true;
3944                 // Force an additional layout pass where
3945                 // WindowStateAnimator#commitFinishDrawingLocked() will call performShowLocked().
3946                 if (mDisplayContent != null) {
3947                     mDisplayContent.setLayoutNeeded();
3948                 }
3949                 mWmService.mH.obtainMessage(H.NOTIFY_ACTIVITY_DRAWN, token).sendToTarget();
3950             }
3951         }
3952     }
3953 
getOptionsForTargetActivityLocked()3954     ActivityOptions getOptionsForTargetActivityLocked() {
3955         return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
3956     }
3957 
clearOptionsLocked()3958     void clearOptionsLocked() {
3959         clearOptionsLocked(true /* withAbort */);
3960     }
3961 
clearOptionsLocked(boolean withAbort)3962     void clearOptionsLocked(boolean withAbort) {
3963         if (withAbort && pendingOptions != null) {
3964             pendingOptions.abort();
3965         }
3966         pendingOptions = null;
3967     }
3968 
takeOptionsLocked(boolean fromClient)3969     ActivityOptions takeOptionsLocked(boolean fromClient) {
3970         if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
3971                 + Debug.getCallers(6));
3972         ActivityOptions opts = pendingOptions;
3973 
3974         // If we are trying to take activity options from the client, do not null it out if it's a
3975         // remote animation as the client doesn't need it ever. This is a workaround when client is
3976         // faster to take the options than we are to resume the next activity.
3977         // TODO (b/132432864): Fix the root cause of these transition preparing/applying options
3978         // timing somehow
3979         if (!fromClient || opts == null || opts.getRemoteAnimationAdapter() == null) {
3980             pendingOptions = null;
3981         }
3982         return opts;
3983     }
3984 
allowMoveToFront()3985     boolean allowMoveToFront() {
3986         return pendingOptions == null || !pendingOptions.getAvoidMoveToFront();
3987     }
3988 
removeUriPermissionsLocked()3989     void removeUriPermissionsLocked() {
3990         if (uriPermissions != null) {
3991             uriPermissions.removeUriPermissions();
3992             uriPermissions = null;
3993         }
3994     }
3995 
pauseKeyDispatchingLocked()3996     void pauseKeyDispatchingLocked() {
3997         if (!keysPaused) {
3998             keysPaused = true;
3999 
4000             if (getDisplayContent() != null) {
4001                 getDisplayContent().getInputMonitor().pauseDispatchingLw(this);
4002             }
4003         }
4004     }
4005 
resumeKeyDispatchingLocked()4006     void resumeKeyDispatchingLocked() {
4007         if (keysPaused) {
4008             keysPaused = false;
4009 
4010             if (getDisplayContent() != null) {
4011                 getDisplayContent().getInputMonitor().resumeDispatchingLw(this);
4012             }
4013         }
4014     }
4015 
updateTaskDescription(CharSequence description)4016     private void updateTaskDescription(CharSequence description) {
4017         task.lastDescription = description;
4018     }
4019 
setDeferHidingClient(boolean deferHidingClient)4020     void setDeferHidingClient(boolean deferHidingClient) {
4021         if (mDeferHidingClient == deferHidingClient) {
4022             return;
4023         }
4024         mDeferHidingClient = deferHidingClient;
4025         if (!mDeferHidingClient && !mVisibleRequested) {
4026             // Hiding the client is no longer deferred and the app isn't visible still, go ahead and
4027             // update the visibility.
4028             setVisibility(false);
4029         }
4030     }
4031 
4032     @Override
isVisible()4033     boolean isVisible() {
4034         // If the activity isn't hidden then it is considered visible and there is no need to check
4035         // its children windows to see if they are visible.
4036         return mVisible;
4037     }
4038 
setVisible(boolean visible)4039     void setVisible(boolean visible) {
4040         if (visible != mVisible) {
4041             mVisible = visible;
4042             scheduleAnimation();
4043         }
4044     }
4045 
4046     /**
4047      * Set visibility on this {@link ActivityRecord}
4048      *
4049      * <p class="note"><strong>Note: </strong>This function might not update the visibility of
4050      * this {@link ActivityRecord} immediately. In case we are preparing an app transition, we
4051      * delay changing the visibility of this {@link ActivityRecord} until we execute that
4052      * transition.</p>
4053      *
4054      * @param visible {@code true} if the {@link ActivityRecord} should become visible, otherwise
4055      *                this should become invisible.
4056      */
setVisibility(boolean visible)4057     void setVisibility(boolean visible) {
4058         if (getParent() == null) {
4059             Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
4060                     + appToken);
4061             return;
4062         }
4063         if (visible) {
4064             mDeferHidingClient = false;
4065         }
4066         setVisibility(visible, mDeferHidingClient);
4067         mAtmService.addWindowLayoutReasons(
4068                 ActivityTaskManagerService.LAYOUT_REASON_VISIBILITY_CHANGED);
4069         mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
4070         mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
4071     }
4072 
4073     @VisibleForTesting
setVisibility(boolean visible, boolean deferHidingClient)4074     void setVisibility(boolean visible, boolean deferHidingClient) {
4075         final AppTransition appTransition = getDisplayContent().mAppTransition;
4076 
4077         // Don't set visibility to false if we were already not visible. This prevents WM from
4078         // adding the app to the closing app list which doesn't make sense for something that is
4079         // already not visible. However, set visibility to true even if we are already visible.
4080         // This makes sure the app is added to the opening apps list so that the right
4081         // transition can be selected.
4082         // TODO: Probably a good idea to separate the concept of opening/closing apps from the
4083         // concept of setting visibility...
4084         if (!visible && !mVisibleRequested) {
4085 
4086             if (!deferHidingClient && mLastDeferHidingClient) {
4087                 // We previously deferred telling the client to hide itself when visibility was
4088                 // initially set to false. Now we would like it to hide, so go ahead and set it.
4089                 mLastDeferHidingClient = deferHidingClient;
4090                 setClientVisible(false);
4091             }
4092             return;
4093         }
4094 
4095         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
4096                 "setAppVisibility(%s, visible=%b): %s visible=%b mVisibleRequested=%b Callers=%s",
4097                 appToken, visible, appTransition, isVisible(), mVisibleRequested,
4098                 Debug.getCallers(6));
4099 
4100         onChildVisibilityRequested(visible);
4101 
4102         final DisplayContent displayContent = getDisplayContent();
4103         displayContent.mOpeningApps.remove(this);
4104         displayContent.mClosingApps.remove(this);
4105         waitingToShow = false;
4106         mVisibleRequested = visible;
4107         mLastDeferHidingClient = deferHidingClient;
4108 
4109         if (!visible) {
4110             // If the app is dead while it was visible, we kept its dead window on screen.
4111             // Now that the app is going invisible, we can remove it. It will be restarted
4112             // if made visible again.
4113             removeDeadWindows();
4114         } else {
4115             if (!appTransition.isTransitionSet()
4116                     && appTransition.isReady()) {
4117                 // Add the app mOpeningApps if transition is unset but ready. This means
4118                 // we're doing a screen freeze, and the unfreeze will wait for all opening
4119                 // apps to be ready.
4120                 displayContent.mOpeningApps.add(this);
4121             }
4122             startingMoved = false;
4123             // If the token is currently hidden (should be the common case), or has been
4124             // stopped, then we need to set up to wait for its windows to be ready.
4125             if (!isVisible() || mAppStopped) {
4126                 clearAllDrawn();
4127 
4128                 // If the app was already visible, don't reset the waitingToShow state.
4129                 if (!isVisible()) {
4130                     waitingToShow = true;
4131 
4132                     // If the client isn't hidden, we don't need to reset the drawing state.
4133                     if (!isClientVisible()) {
4134                         // Let's reset the draw state in order to prevent the starting window to be
4135                         // immediately dismissed when the app still has the surface.
4136                         forAllWindows(w -> {
4137                             if (w.mWinAnimator.mDrawState == HAS_DRAWN) {
4138                                 w.mWinAnimator.resetDrawState();
4139 
4140                                 // Force add to mResizingWindows, so that we are guaranteed to get
4141                                 // another reportDrawn callback.
4142                                 w.resetLastContentInsets();
4143                             }
4144                         }, true /* traverseTopToBottom */);
4145                     }
4146                 }
4147             }
4148 
4149             // In the case where we are making an app visible but holding off for a transition,
4150             // we still need to tell the client to make its windows visible so they get drawn.
4151             // Otherwise, we will wait on performing the transition until all windows have been
4152             // drawn, they never will be, and we are sad.
4153             setClientVisible(true);
4154 
4155             requestUpdateWallpaperIfNeeded();
4156 
4157             ProtoLog.v(WM_DEBUG_ADD_REMOVE, "No longer Stopped: %s", this);
4158             mAppStopped = false;
4159 
4160             transferStartingWindowFromHiddenAboveTokenIfNeeded();
4161         }
4162 
4163         // If we are preparing an app transition, then delay changing
4164         // the visibility of this token until we execute that transition.
4165         // Note that we ignore display frozen since we want the opening / closing transition type
4166         // can be updated correctly even display frozen, and it's safe since in applyAnimation will
4167         // still check DC#okToAnimate again if the transition animation is fine to apply.
4168         if (okToAnimate(true /* ignoreFrozen */) && appTransition.isTransitionSet()) {
4169             if (visible) {
4170                 displayContent.mOpeningApps.add(this);
4171                 mEnteringAnimation = true;
4172             } else {
4173                 displayContent.mClosingApps.add(this);
4174                 mEnteringAnimation = false;
4175             }
4176             if (appTransition.getAppTransition() == TRANSIT_TASK_OPEN_BEHIND) {
4177                 // We're launchingBehind, add the launching activity to mOpeningApps.
4178                 final WindowState win = getDisplayContent().findFocusedWindow();
4179                 if (win != null) {
4180                     final ActivityRecord focusedActivity = win.mActivityRecord;
4181                     if (focusedActivity != null) {
4182                         ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
4183                                 "TRANSIT_TASK_OPEN_BEHIND,  adding %s to mOpeningApps",
4184                                 focusedActivity);
4185 
4186                         // Force animation to be loaded.
4187                         displayContent.mOpeningApps.add(focusedActivity);
4188                     }
4189                 }
4190             }
4191             return;
4192         }
4193 
4194         commitVisibility(visible, true /* performLayout */);
4195         updateReportedVisibilityLocked();
4196     }
4197 
4198     @Override
applyAnimation(LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources)4199     boolean applyAnimation(LayoutParams lp, int transit, boolean enter,
4200             boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) {
4201         if (mUseTransferredAnimation) {
4202             return false;
4203         }
4204         return super.applyAnimation(lp, transit, enter, isVoiceInteraction, sources);
4205     }
4206 
4207     /**
4208      * Update visibility to this {@link ActivityRecord}.
4209      *
4210      * <p class="note"><strong>Note: </strong> Unlike {@link #setVisibility}, this immediately
4211      * updates the visibility without starting an app transition. Since this function may start
4212      * animation on {@link WindowState} depending on app transition animation status, an app
4213      * transition animation must be started before calling this function if necessary.</p>
4214      *
4215      * @param visible {@code true} if this {@link ActivityRecord} should become visible, otherwise
4216      *                this should become invisible.
4217      * @param performLayout if {@code true}, perform surface placement after committing visibility.
4218      */
commitVisibility(boolean visible, boolean performLayout)4219     void commitVisibility(boolean visible, boolean performLayout) {
4220         // Reset the state of mHiddenSetFromTransferredStartingWindow since visibility is actually
4221         // been set by the app now.
4222         mVisibleSetFromTransferredStartingWindow = false;
4223         if (visible == isVisible()) {
4224             return;
4225         }
4226 
4227         final int windowsCount = mChildren.size();
4228         for (int i = 0; i < windowsCount; i++) {
4229             mChildren.get(i).onAppVisibilityChanged(visible, isAnimating(PARENTS));
4230         }
4231         setVisible(visible);
4232         mVisibleRequested = visible;
4233         if (!visible) {
4234             stopFreezingScreen(true, true);
4235         } else {
4236             // If we are being set visible, and the starting window is not yet displayed,
4237             // then make sure it doesn't get displayed.
4238             if (startingWindow != null && !startingWindow.isDrawnLw()) {
4239                 startingWindow.clearPolicyVisibilityFlag(LEGACY_POLICY_VISIBILITY);
4240                 startingWindow.mLegacyPolicyVisibilityAfterAnim = false;
4241             }
4242             // We are becoming visible, so better freeze the screen with the windows that are
4243             // getting visible so we also wait for them.
4244             forAllWindows(mWmService::makeWindowFreezingScreenIfNeededLocked, true);
4245         }
4246         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
4247                 "commitVisibility: %s: visible=%b mVisibleRequested=%b", this,
4248                 isVisible(), mVisibleRequested);
4249         final DisplayContent displayContent = getDisplayContent();
4250         displayContent.getInputMonitor().setUpdateInputWindowsNeededLw();
4251         if (performLayout) {
4252             mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
4253                     false /*updateInputWindows*/);
4254             mWmService.mWindowPlacerLocked.performSurfacePlacement();
4255         }
4256         displayContent.getInputMonitor().updateInputWindowsLw(false /*force*/);
4257         mUseTransferredAnimation = false;
4258 
4259         postApplyAnimation(visible);
4260     }
4261 
4262     /**
4263      * Post process after applying an app transition animation.
4264      *
4265      * <p class="note"><strong>Note: </strong> This function must be called after the animations
4266      * have been applied and {@link #commitVisibility}.</p>
4267      *
4268      * @param visible {@code true} if this {@link ActivityRecord} has become visible, otherwise
4269      *                this has become invisible.
4270      */
postApplyAnimation(boolean visible)4271     private void postApplyAnimation(boolean visible) {
4272         final boolean delayed = isAnimating(PARENTS | CHILDREN);
4273         if (!delayed) {
4274             // We aren't delayed anything, but exiting windows rely on the animation finished
4275             // callback being called in case the ActivityRecord was pretending to be delayed,
4276             // which we might have done because we were in closing/opening apps list.
4277             onAnimationFinished(ANIMATION_TYPE_APP_TRANSITION, null /* AnimationAdapter */);
4278             if (visible) {
4279                 // The token was made immediately visible, there will be no entrance animation.
4280                 // We need to inform the client the enter animation was finished.
4281                 mEnteringAnimation = true;
4282                 mWmService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(
4283                         token);
4284             }
4285         }
4286 
4287         // If we're becoming visible, immediately change client visibility as well. there seem
4288         // to be some edge cases where we change our visibility but client visibility never gets
4289         // updated.
4290         // If we're becoming invisible, update the client visibility if we are not running an
4291         // animation. Otherwise, we'll update client visibility in onAnimationFinished.
4292         if (visible || !isAnimating(PARENTS)) {
4293             setClientVisible(visible);
4294         }
4295 
4296         final DisplayContent displayContent = getDisplayContent();
4297         if (!displayContent.mClosingApps.contains(this)
4298                 && !displayContent.mOpeningApps.contains(this)) {
4299             // Take the screenshot before possibly hiding the WSA, otherwise the screenshot
4300             // will not be taken.
4301             mWmService.mTaskSnapshotController.notifyAppVisibilityChanged(this, visible);
4302         }
4303 
4304         // If we are hidden but there is no delay needed we immediately
4305         // apply the Surface transaction so that the ActivityManager
4306         // can have some guarantee on the Surface state following
4307         // setting the visibility. This captures cases like dismissing
4308         // the docked or pinned stack where there is no app transition.
4309         //
4310         // In the case of a "Null" animation, there will be
4311         // no animation but there will still be a transition set.
4312         // We still need to delay hiding the surface such that it
4313         // can be synchronized with showing the next surface in the transition.
4314         if (!isVisible() && !delayed && !displayContent.mAppTransition.isTransitionSet()) {
4315             SurfaceControl.openTransaction();
4316             try {
4317                 forAllWindows(win -> {
4318                     win.mWinAnimator.hide("immediately hidden"); }, true);
4319             } finally {
4320                 SurfaceControl.closeTransaction();
4321             }
4322         }
4323     }
4324 
4325     /**
4326      * Check if visibility of this {@link ActivityRecord} should be updated as part of an app
4327      * transition.
4328      *
4329      * <p class="note><strong>Note:</strong> If the visibility of this {@link ActivityRecord} is
4330      * already set to {@link #mVisible}, we don't need to update the visibility. So {@code false} is
4331      * returned.</p>
4332      *
4333      * @param visible {@code true} if this {@link ActivityRecord} should become visible,
4334      *                {@code false} if this should become invisible.
4335      * @return {@code true} if visibility of this {@link ActivityRecord} should be updated, and
4336      *         an app transition animation should be run.
4337      */
shouldApplyAnimation(boolean visible)4338     boolean shouldApplyAnimation(boolean visible) {
4339         // Allow for state update and animation to be applied if:
4340         // * activity is transitioning visibility state
4341         // * or the activity was marked as hidden and is exiting before we had a chance to play the
4342         // transition animation
4343         // * or this is an opening app and windows are being replaced (e.g. freeform window to
4344         //   normal window).
4345         return isVisible() != visible || (!isVisible() && mIsExiting)
4346                 || (visible && forAllWindows(WindowState::waitingForReplacement, true));
4347     }
4348 
4349     /**
4350      * See {@link Activity#setDisablePreviewScreenshots}.
4351      */
setDisablePreviewScreenshots(boolean disable)4352     void setDisablePreviewScreenshots(boolean disable) {
4353         mDisablePreviewScreenshots = disable;
4354     }
4355 
4356     /**
4357      * Retrieves whether we'd like to generate a snapshot that's based solely on the theme. This is
4358      * the case when preview screenshots are disabled {@link #setDisablePreviewScreenshots} or when
4359      * we can't take a snapshot for other reasons, for example, if we have a secure window.
4360      *
4361      * @return True if we need to generate an app theme snapshot, false if we'd like to take a real
4362      *         screenshot.
4363      */
shouldUseAppThemeSnapshot()4364     boolean shouldUseAppThemeSnapshot() {
4365         return mDisablePreviewScreenshots || forAllWindows(WindowState::isSecureLocked,
4366                 true /* topToBottom */);
4367     }
4368 
4369     /**
4370      * Sets whether the current launch can turn the screen on.
4371      * @see #currentLaunchCanTurnScreenOn()
4372      */
setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn)4373     void setCurrentLaunchCanTurnScreenOn(boolean currentLaunchCanTurnScreenOn) {
4374         mCurrentLaunchCanTurnScreenOn = currentLaunchCanTurnScreenOn;
4375     }
4376 
4377     /**
4378      * Indicates whether the current launch can turn the screen on. This is to prevent multiple
4379      * relayouts from turning the screen back on. The screen should only turn on at most
4380      * once per activity resume.
4381      * <p>
4382      * Note this flag is only meaningful when {@link WindowManager.LayoutParams#FLAG_TURN_SCREEN_ON}
4383      * or {@link ActivityRecord#canTurnScreenOn} is set.
4384      *
4385      * @return {@code true} if the activity is ready to turn on the screen.
4386      */
currentLaunchCanTurnScreenOn()4387     boolean currentLaunchCanTurnScreenOn() {
4388         return mCurrentLaunchCanTurnScreenOn;
4389     }
4390 
setState(ActivityState state, String reason)4391     void setState(ActivityState state, String reason) {
4392         if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
4393                         + " to:" + state + " reason:" + reason);
4394 
4395         if (state == mState) {
4396             // No need to do anything if state doesn't change.
4397             if (DEBUG_STATES) Slog.v(TAG_STATES, "State unchanged from:" + state);
4398             return;
4399         }
4400 
4401         mState = state;
4402 
4403         if (task != null) {
4404             task.onActivityStateChanged(this, state, reason);
4405         }
4406 
4407         // The WindowManager interprets the app stopping signal as
4408         // an indication that the Surface will eventually be destroyed.
4409         // This however isn't necessarily true if we are going to sleep.
4410         if (state == STOPPING && !isSleeping()) {
4411             if (getParent() == null) {
4412                 Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
4413                         + appToken);
4414                 return;
4415             }
4416             detachChildren();
4417         }
4418 
4419         if (state == RESUMED) {
4420             mAtmService.updateBatteryStats(this, true);
4421             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_RESUMED);
4422         } else if (state == PAUSED) {
4423             mAtmService.updateBatteryStats(this, false);
4424             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
4425         } else if (state == STOPPED) {
4426             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
4427         } else if (state == DESTROYED) {
4428             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED);
4429         }
4430     }
4431 
getState()4432     ActivityState getState() {
4433         return mState;
4434     }
4435 
4436     /**
4437      * Returns {@code true} if the Activity is in the specified state.
4438      */
isState(ActivityState state)4439     boolean isState(ActivityState state) {
4440         return state == mState;
4441     }
4442 
4443     /**
4444      * Returns {@code true} if the Activity is in one of the specified states.
4445      */
isState(ActivityState state1, ActivityState state2)4446     boolean isState(ActivityState state1, ActivityState state2) {
4447         return state1 == mState || state2 == mState;
4448     }
4449 
4450     /**
4451      * Returns {@code true} if the Activity is in one of the specified states.
4452      */
isState(ActivityState state1, ActivityState state2, ActivityState state3)4453     boolean isState(ActivityState state1, ActivityState state2, ActivityState state3) {
4454         return state1 == mState || state2 == mState || state3 == mState;
4455     }
4456 
4457     /**
4458      * Returns {@code true} if the Activity is in one of the specified states.
4459      */
isState(ActivityState state1, ActivityState state2, ActivityState state3, ActivityState state4)4460     boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
4461             ActivityState state4) {
4462         return state1 == mState || state2 == mState || state3 == mState || state4 == mState;
4463     }
4464 
4465     /**
4466      * Returns {@code true} if the Activity is in one of the specified states.
4467      */
isState(ActivityState state1, ActivityState state2, ActivityState state3, ActivityState state4, ActivityState state5)4468     boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
4469             ActivityState state4, ActivityState state5) {
4470         return state1 == mState || state2 == mState || state3 == mState || state4 == mState
4471                 || state5 == mState;
4472     }
4473 
4474     /**
4475      * Returns {@code true} if the Activity is in one of the specified states.
4476      */
isState(ActivityState state1, ActivityState state2, ActivityState state3, ActivityState state4, ActivityState state5, ActivityState state6)4477     boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
4478             ActivityState state4, ActivityState state5, ActivityState state6) {
4479         return state1 == mState || state2 == mState || state3 == mState || state4 == mState
4480                 || state5 == mState || state6 == mState;
4481     }
4482 
destroySurfaces()4483     void destroySurfaces() {
4484         destroySurfaces(false /*cleanupOnResume*/);
4485     }
4486 
4487     /**
4488      * Destroy surfaces which have been marked as eligible by the animator, taking care to ensure
4489      * the client has finished with them.
4490      *
4491      * @param cleanupOnResume whether this is done when app is resumed without fully stopped. If
4492      * set to true, destroy only surfaces of removed windows, and clear relevant flags of the
4493      * others so that they are ready to be reused. If set to false (common case), destroy all
4494      * surfaces that's eligible, if the app is already stopped.
4495      */
destroySurfaces(boolean cleanupOnResume)4496     private void destroySurfaces(boolean cleanupOnResume) {
4497         boolean destroyedSomething = false;
4498 
4499         // Copying to a different list as multiple children can be removed.
4500         final ArrayList<WindowState> children = new ArrayList<>(mChildren);
4501         for (int i = children.size() - 1; i >= 0; i--) {
4502             final WindowState win = children.get(i);
4503             destroyedSomething |= win.destroySurface(cleanupOnResume, mAppStopped);
4504         }
4505         if (destroyedSomething) {
4506             final DisplayContent dc = getDisplayContent();
4507             dc.assignWindowLayers(true /*setLayoutNeeded*/);
4508             updateLetterboxSurface(null);
4509         }
4510     }
4511 
notifyAppResumed(boolean wasStopped)4512     void notifyAppResumed(boolean wasStopped) {
4513         if (getParent() == null) {
4514             Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
4515                     + appToken);
4516             return;
4517         }
4518         ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppResumed: wasStopped=%b %s",
4519                 wasStopped, this);
4520         mAppStopped = false;
4521         // Allow the window to turn the screen on once the app is resumed again.
4522         setCurrentLaunchCanTurnScreenOn(true);
4523         if (!wasStopped) {
4524             destroySurfaces(true /*cleanupOnResume*/);
4525         }
4526     }
4527 
4528     /**
4529      * Notify that the app has stopped, and it is okay to destroy any surfaces which were
4530      * keeping alive in case they were still being used.
4531      */
notifyAppStopped()4532     void notifyAppStopped() {
4533         ProtoLog.v(WM_DEBUG_ADD_REMOVE, "notifyAppStopped: %s", this);
4534         mAppStopped = true;
4535         // Reset the last saved PiP snap fraction on app stop.
4536         mDisplayContent.mPinnedStackControllerLocked.onActivityHidden(mActivityComponent);
4537         destroySurfaces();
4538         // Remove any starting window that was added for this app if they are still around.
4539         removeStartingWindow();
4540     }
4541 
4542     /**
4543      * Suppress transition until the new activity becomes ready, otherwise the keyguard can appear
4544      * for a short amount of time before the new process with the new activity had the ability to
4545      * set its showWhenLocked flags.
4546      */
notifyUnknownVisibilityLaunchedForKeyguardTransition()4547     void notifyUnknownVisibilityLaunchedForKeyguardTransition() {
4548         // No display activities never add a window, so there is no point in waiting them for
4549         // relayout.
4550         if (noDisplay || !mStackSupervisor.getKeyguardController().isKeyguardLocked()) {
4551             return;
4552         }
4553 
4554         mDisplayContent.mUnknownAppVisibilityController.notifyLaunched(this);
4555     }
4556 
4557     /** @return {@code true} if this activity should be made visible. */
shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard)4558     boolean shouldBeVisible(boolean behindFullscreenActivity, boolean ignoringKeyguard) {
4559         // Check whether activity should be visible without Keyguard influence
4560         visibleIgnoringKeyguard = (!behindFullscreenActivity || mLaunchTaskBehind)
4561                 && okToShowLocked();
4562 
4563         if (ignoringKeyguard) {
4564             return visibleIgnoringKeyguard;
4565         }
4566 
4567         final ActivityStack stack = getRootTask();
4568         if (stack == null) {
4569             return false;
4570         }
4571 
4572         // Activity in a pinned stack should not be visible if the stack is in force hidden state.
4573         // Typically due to the FLAG_FORCE_HIDDEN_FOR_PINNED_TASK set on the stack, which is a
4574         // work around to send onStop before windowing mode change callbacks.
4575         // See also ActivityStackSupervisor#removePinnedStackInSurfaceTransaction
4576         // TODO: Should we ever be visible if the stack/task is invisible?
4577         if (inPinnedWindowingMode() && stack.isForceHidden()) {
4578             return false;
4579         }
4580 
4581         // Check if the activity is on a sleeping display, and if it can turn it ON.
4582         if (getDisplay().isSleeping()) {
4583             final boolean canTurnScreenOn = !mSetToSleep || canTurnScreenOn()
4584                     || canShowWhenLocked() || containsDismissKeyguardWindow();
4585             if (!canTurnScreenOn) {
4586                 return false;
4587             }
4588         }
4589 
4590         // Now check whether it's really visible depending on Keyguard state, and update
4591         // {@link ActivityStack} internal states.
4592         // Inform the method if this activity is the top activity of this stack, but exclude the
4593         // case where this is the top activity in a pinned stack.
4594         final boolean isTop = this == stack.getTopNonFinishingActivity();
4595         final boolean isTopNotPinnedStack = stack.isAttached()
4596                 && stack.getDisplayArea().isTopNotPinnedStack(stack);
4597         final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
4598                 visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
4599 
4600         return visibleIgnoringDisplayStatus;
4601     }
4602 
shouldBeVisible()4603     boolean shouldBeVisible() {
4604         final ActivityStack stack = getRootTask();
4605         if (stack == null) {
4606             return false;
4607         }
4608 
4609         final boolean behindFullscreenActivity = stack.checkBehindFullscreenActivity(
4610                 this, null /* handleBehindFullscreenActivity */);
4611         return shouldBeVisible(behindFullscreenActivity, false /* ignoringKeyguard */);
4612     }
4613 
makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient)4614     void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) {
4615         // This activity is not currently visible, but is running. Tell it to become visible.
4616         if (mState == RESUMED || this == starting) {
4617             if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
4618                     "Not making visible, r=" + this + " state=" + mState + " starting=" + starting);
4619             return;
4620         }
4621 
4622         // If this activity is paused, tell it to now show its window.
4623         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
4624                 "Making visible and scheduling visibility: " + this);
4625         final ActivityStack stack = getRootTask();
4626         try {
4627             if (stack.mTranslucentActivityWaiting != null) {
4628                 updateOptionsLocked(returningOptions);
4629                 stack.mUndrawnActivitiesBelowTopTranslucent.add(this);
4630             }
4631             setVisibility(true);
4632             mSetToSleep = false;
4633             app.postPendingUiCleanMsg(true);
4634             if (reportToClient) {
4635                 mClientVisibilityDeferred = false;
4636                 makeActiveIfNeeded(starting);
4637             } else {
4638                 mClientVisibilityDeferred = true;
4639             }
4640             // The activity may be waiting for stop, but that is no longer appropriate for it.
4641             mStackSupervisor.mStoppingActivities.remove(this);
4642         } catch (Exception e) {
4643             // Just skip on any failure; we'll make it visible when it next restarts.
4644             Slog.w(TAG, "Exception thrown making visible: " + intent.getComponent(), e);
4645         }
4646         handleAlreadyVisible();
4647     }
4648 
makeInvisible()4649     void makeInvisible() {
4650         if (!mVisibleRequested) {
4651             if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + this);
4652             return;
4653         }
4654         // Now for any activities that aren't visible to the user, make sure they no longer are
4655         // keeping the screen frozen.
4656         if (DEBUG_VISIBILITY) {
4657             Slog.v(TAG_VISIBILITY, "Making invisible: " + this + ", state=" + getState());
4658         }
4659         try {
4660             final boolean canEnterPictureInPicture = checkEnterPictureInPictureState(
4661                     "makeInvisible", true /* beforeStopping */);
4662             // Defer telling the client it is hidden if it can enter Pip and isn't current paused,
4663             // stopped or stopping. This gives it a chance to enter Pip in onPause().
4664             // TODO: There is still a question surrounding activities in multi-window mode that want
4665             // to enter Pip after they are paused, but are still visible. I they should be okay to
4666             // enter Pip in those cases, but not "auto-Pip" which is what this condition covers and
4667             // the current contract for "auto-Pip" is that the app should enter it before onPause
4668             // returns. Just need to confirm this reasoning makes sense.
4669             final boolean deferHidingClient = canEnterPictureInPicture
4670                     && !isState(STARTED, STOPPING, STOPPED, PAUSED);
4671             setDeferHidingClient(deferHidingClient);
4672             setVisibility(false);
4673 
4674             switch (getState()) {
4675                 case STOPPING:
4676                 case STOPPED:
4677                     // Reset the flag indicating that an app can enter picture-in-picture once the
4678                     // activity is hidden
4679                     supportsEnterPipOnTaskSwitch = false;
4680                     break;
4681                 case RESUMED:
4682                     // If the app is capable of entering PIP, we should try pausing it now
4683                     // so it can PIP correctly.
4684                     if (deferHidingClient) {
4685                         getRootTask().startPausingLocked(
4686                                 mStackSupervisor.mUserLeaving /* userLeaving */,
4687                                 false /* uiSleeping */, null /* resuming */);
4688                         break;
4689                     }
4690                 case INITIALIZING:
4691                 case PAUSING:
4692                 case PAUSED:
4693                 case STARTED:
4694                     addToStopping(true /* scheduleIdle */,
4695                             canEnterPictureInPicture /* idleDelayed */, "makeInvisible");
4696                     break;
4697 
4698                 default:
4699                     break;
4700             }
4701         } catch (Exception e) {
4702             // Just skip on any failure; we'll make it visible when it next restarts.
4703             Slog.w(TAG, "Exception thrown making hidden: " + intent.getComponent(), e);
4704         }
4705     }
4706 
4707     /**
4708      * Make activity resumed or paused if needed.
4709      * @param activeActivity an activity that is resumed or just completed pause action.
4710      *                       We won't change the state of this activity.
4711      */
makeActiveIfNeeded(ActivityRecord activeActivity)4712     boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
4713         if (shouldResumeActivity(activeActivity)) {
4714             if (DEBUG_VISIBILITY) {
4715                 Slog.v(TAG_VISIBILITY, "Resume visible activity, " + this);
4716             }
4717             return getRootTask().resumeTopActivityUncheckedLocked(activeActivity /* prev */,
4718                     null /* options */);
4719         } else if (shouldPauseActivity(activeActivity)) {
4720             if (DEBUG_VISIBILITY) {
4721                 Slog.v(TAG_VISIBILITY, "Pause visible activity, " + this);
4722             }
4723             // An activity must be in the {@link PAUSING} state for the system to validate
4724             // the move to {@link PAUSED}.
4725             setState(PAUSING, "makeActiveIfNeeded");
4726             try {
4727                 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
4728                         PauseActivityItem.obtain(finishing, false /* userLeaving */,
4729                                 configChangeFlags, false /* dontReport */));
4730             } catch (Exception e) {
4731                 Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
4732             }
4733         } else if (shouldStartActivity()) {
4734             if (DEBUG_VISIBILITY) {
4735                 Slog.v(TAG_VISIBILITY, "Start visible activity, " + this);
4736             }
4737             setState(STARTED, "makeActiveIfNeeded");
4738             try {
4739                 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
4740                         StartActivityItem.obtain());
4741             } catch (Exception e) {
4742                 Slog.w(TAG, "Exception thrown sending start: " + intent.getComponent(), e);
4743             }
4744             // The activity may be waiting for stop, but that is no longer appropriate if we are
4745             // starting the activity again
4746             mStackSupervisor.mStoppingActivities.remove(this);
4747         }
4748         return false;
4749     }
4750 
4751     /**
4752      * Check if activity should be moved to PAUSED state. The activity:
4753      * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
4754      * - should be non-focusable
4755      * - should not be currently pausing or paused
4756      * @param activeActivity the activity that is active or just completed pause action. We won't
4757      *                       resume if this activity is active.
4758      */
4759     @VisibleForTesting
shouldPauseActivity(ActivityRecord activeActivity)4760     boolean shouldPauseActivity(ActivityRecord activeActivity) {
4761         return shouldMakeActive(activeActivity) && !isFocusable() && !isState(PAUSING, PAUSED)
4762                 // We will only allow pausing if results is null, otherwise it will cause this
4763                 // activity to resume before getting result
4764                 && (results == null);
4765     }
4766 
4767     /**
4768      * Check if activity should be moved to RESUMED state.
4769      * See {@link #shouldBeResumed(ActivityRecord)}
4770      * @param activeActivity the activity that is active or just completed pause action. We won't
4771      *                       resume if this activity is active.
4772      */
4773     @VisibleForTesting
shouldResumeActivity(ActivityRecord activeActivity)4774     boolean shouldResumeActivity(ActivityRecord activeActivity) {
4775         return shouldBeResumed(activeActivity) && !isState(RESUMED);
4776     }
4777 
4778     /**
4779      * Check if activity should be RESUMED now. The activity:
4780      * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
4781      * - should be focusable
4782      */
shouldBeResumed(ActivityRecord activeActivity)4783     private boolean shouldBeResumed(ActivityRecord activeActivity) {
4784         return shouldMakeActive(activeActivity) && isFocusable()
4785                 && getTask().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE
4786                 && canResumeByCompat();
4787     }
4788 
4789     /**
4790      * Check if activity should be moved to STARTED state.
4791      * NOTE: This will not check if activity should be made paused or resumed first, so it must only
4792      * be called after checking with {@link #shouldResumeActivity(ActivityRecord)}
4793      * and {@link #shouldPauseActivity(ActivityRecord)}.
4794      */
shouldStartActivity()4795     private boolean shouldStartActivity() {
4796         return mVisibleRequested && (isState(STOPPED) || isState(STOPPING));
4797     }
4798 
4799     /**
4800      * Check if activity is eligible to be made active (resumed of paused). The activity:
4801      * - should be paused, stopped or stopping
4802      * - should not be the currently active one or launching behind other tasks
4803      * - should be either the topmost in task, or right below the top activity that is finishing
4804      * If all of these conditions are not met at the same time, the activity cannot be made active.
4805      */
4806     @VisibleForTesting
shouldMakeActive(ActivityRecord activeActivity)4807     boolean shouldMakeActive(ActivityRecord activeActivity) {
4808         // If the activity is stopped, stopping, cycle to an active state. We avoid doing
4809         // this when there is an activity waiting to become translucent as the extra binder
4810         // calls will lead to noticeable jank. A later call to
4811         // ActivityStack#ensureActivitiesVisible will bring the activity to a proper
4812         // active state.
4813         if (!isState(STARTED, RESUMED, PAUSED, STOPPED, STOPPING)
4814                 || getRootTask().mTranslucentActivityWaiting != null) {
4815             return false;
4816         }
4817 
4818         if (this == activeActivity) {
4819             return false;
4820         }
4821 
4822         if (!mStackSupervisor.readyToResume()) {
4823             // Making active is currently deferred (e.g. because an activity launch is in progress).
4824             return false;
4825         }
4826 
4827         if (this.mLaunchTaskBehind) {
4828             // This activity is being launched from behind, which means that it's not intended to be
4829             // presented to user right now, even if it's set to be visible.
4830             return false;
4831         }
4832 
4833         // Check if position in task allows to become paused
4834         if (!task.hasChild(this)) {
4835             throw new IllegalStateException("Activity not found in its task");
4836         }
4837         return task.topRunningActivity() == this;
4838     }
4839 
handleAlreadyVisible()4840     void handleAlreadyVisible() {
4841         stopFreezingScreenLocked(false);
4842         try {
4843             if (returningOptions != null) {
4844                 app.getThread().scheduleOnNewActivityOptions(appToken, returningOptions.toBundle());
4845             }
4846         } catch(RemoteException e) {
4847         }
4848     }
4849 
activityResumedLocked(IBinder token)4850     static void activityResumedLocked(IBinder token) {
4851         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
4852         if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
4853         if (r == null) {
4854             // If an app reports resumed after a long delay, the record on server side might have
4855             // been removed (e.g. destroy timeout), so the token could be null.
4856             return;
4857         }
4858         r.setSavedState(null /* savedState */);
4859 
4860         final DisplayContent display = r.getDisplay();
4861         if (display != null) {
4862             display.handleActivitySizeCompatModeIfNeeded(r);
4863         }
4864 
4865         r.getDisplayContent().mUnknownAppVisibilityController.notifyAppResumedFinished(r);
4866     }
4867 
4868     /**
4869      * Once we know that we have asked an application to put an activity in the resumed state
4870      * (either by launching it or explicitly telling it), this function updates the rest of our
4871      * state to match that fact.
4872      */
completeResumeLocked()4873     void completeResumeLocked() {
4874         final boolean wasVisible = mVisibleRequested;
4875         setVisibility(true);
4876         if (!wasVisible) {
4877             // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
4878             mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
4879         }
4880         idle = false;
4881         results = null;
4882         if (newIntents != null && newIntents.size() > 0) {
4883             mLastNewIntent = newIntents.get(newIntents.size() - 1);
4884         }
4885         newIntents = null;
4886         stopped = false;
4887 
4888         if (isActivityTypeHome()) {
4889             mStackSupervisor.updateHomeProcess(task.getBottomMostActivity().app);
4890         }
4891 
4892         if (nowVisible) {
4893             mStackSupervisor.stopWaitingForActivityVisible(this);
4894         }
4895 
4896         // Schedule an idle timeout in case the app doesn't do it for us.
4897         mStackSupervisor.scheduleIdleTimeout(this);
4898 
4899         mStackSupervisor.reportResumedActivityLocked(this);
4900 
4901         resumeKeyDispatchingLocked();
4902         final ActivityStack stack = getRootTask();
4903         mStackSupervisor.mNoAnimActivities.clear();
4904 
4905         // Mark the point when the activity is resuming
4906         // TODO: To be more accurate, the mark should be before the onCreate,
4907         //       not after the onResume. But for subsequent starts, onResume is fine.
4908         if (hasProcess()) {
4909             cpuTimeAtResume = app.getCpuTime();
4910         } else {
4911             cpuTimeAtResume = 0; // Couldn't get the cpu time of process
4912         }
4913 
4914         returningOptions = null;
4915 
4916         if (canTurnScreenOn()) {
4917             mStackSupervisor.wakeUp("turnScreenOnFlag");
4918         } else {
4919             // If the screen is going to turn on because the caller explicitly requested it and
4920             // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will
4921             // pause and then resume again later, which will result in a double life-cycle event.
4922             stack.checkReadyForSleep();
4923         }
4924     }
4925 
activityPaused(boolean timeout)4926     void activityPaused(boolean timeout) {
4927         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
4928                 "Activity paused: token=" + appToken + ", timeout=" + timeout);
4929 
4930         final ActivityStack stack = getStack();
4931 
4932         if (stack != null) {
4933             removePauseTimeout();
4934 
4935             if (stack.mPausingActivity == this) {
4936                 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + this
4937                         + (timeout ? " (due to timeout)" : " (pause complete)"));
4938                 mAtmService.deferWindowLayout();
4939                 try {
4940                     stack.completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
4941                 } finally {
4942                     mAtmService.continueWindowLayout();
4943                 }
4944                 return;
4945             } else {
4946                 EventLogTags.writeWmFailedToPause(mUserId, System.identityHashCode(this),
4947                         shortComponentName, stack.mPausingActivity != null
4948                                 ? stack.mPausingActivity.shortComponentName : "(none)");
4949                 if (isState(PAUSING)) {
4950                     setState(PAUSED, "activityPausedLocked");
4951                     if (finishing) {
4952                         if (DEBUG_PAUSE) Slog.v(TAG,
4953                                 "Executing finish of failed to pause activity: " + this);
4954                         completeFinishing("activityPausedLocked");
4955                     }
4956                 }
4957             }
4958         }
4959 
4960         mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
4961     }
4962 
4963     /**
4964      * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
4965      * this directly impacts the responsiveness seen by the user.
4966      */
schedulePauseTimeout()4967     void schedulePauseTimeout() {
4968         pauseTime = SystemClock.uptimeMillis();
4969         mAtmService.mH.postDelayed(mPauseTimeoutRunnable, PAUSE_TIMEOUT);
4970         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
4971     }
4972 
removePauseTimeout()4973     private void removePauseTimeout() {
4974         mAtmService.mH.removeCallbacks(mPauseTimeoutRunnable);
4975     }
4976 
removeDestroyTimeout()4977     private void removeDestroyTimeout() {
4978         mAtmService.mH.removeCallbacks(mDestroyTimeoutRunnable);
4979     }
4980 
removeStopTimeout()4981     private void removeStopTimeout() {
4982         mAtmService.mH.removeCallbacks(mStopTimeoutRunnable);
4983     }
4984 
removeTimeouts()4985     void removeTimeouts() {
4986         mStackSupervisor.removeIdleTimeoutForActivity(this);
4987         removePauseTimeout();
4988         removeStopTimeout();
4989         removeDestroyTimeout();
4990         finishLaunchTickingLocked();
4991     }
4992 
stopIfPossible()4993     void stopIfPossible() {
4994         if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + this);
4995         final ActivityStack stack = getRootTask();
4996         if (isNoHistory()) {
4997             if (!finishing) {
4998                 if (!stack.shouldSleepActivities()) {
4999                     if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + this);
5000                     if (finishIfPossible("stop-no-history", false /* oomAdj */)
5001                             != FINISH_RESULT_CANCELLED) {
5002                         resumeKeyDispatchingLocked();
5003                         return;
5004                     }
5005                 } else {
5006                     if (DEBUG_STATES) {
5007                         Slog.d(TAG_STATES, "Not finishing noHistory " + this
5008                                 + " on stop because we're just sleeping");
5009                     }
5010                 }
5011             }
5012         }
5013 
5014         if (!attachedToProcess()) {
5015             return;
5016         }
5017         resumeKeyDispatchingLocked();
5018         try {
5019             stopped = false;
5020             if (DEBUG_STATES) {
5021                 Slog.v(TAG_STATES, "Moving to STOPPING: " + this + " (stop requested)");
5022             }
5023             setState(STOPPING, "stopIfPossible");
5024             if (DEBUG_VISIBILITY) {
5025                 Slog.v(TAG_VISIBILITY, "Stopping:" + this);
5026             }
5027             EventLogTags.writeWmStopActivity(
5028                     mUserId, System.identityHashCode(this), shortComponentName);
5029             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
5030                     StopActivityItem.obtain(configChangeFlags));
5031 
5032             if (stack.shouldSleepOrShutDownActivities()) {
5033                 setSleeping(true);
5034             }
5035             mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
5036         } catch (Exception e) {
5037             // Maybe just ignore exceptions here...  if the process has crashed, our death
5038             // notification will clean things up.
5039             Slog.w(TAG, "Exception thrown during pause", e);
5040             // Just in case, assume it to be stopped.
5041             stopped = true;
5042             if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + this);
5043             setState(STOPPED, "stopIfPossible");
5044             if (deferRelaunchUntilPaused) {
5045                 destroyImmediately(true /* removeFromApp */, "stop-except");
5046             }
5047         }
5048     }
5049 
activityStopped(Bundle newIcicle, PersistableBundle newPersistentState, CharSequence description)5050     void activityStopped(Bundle newIcicle, PersistableBundle newPersistentState,
5051             CharSequence description) {
5052         final ActivityStack stack = getRootTask();
5053         final boolean isStopping = mState == STOPPING;
5054         if (!isStopping && mState != RESTARTING_PROCESS) {
5055             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
5056             removeStopTimeout();
5057             return;
5058         }
5059         if (newPersistentState != null) {
5060             mPersistentState = newPersistentState;
5061             mAtmService.notifyTaskPersisterLocked(task, false);
5062         }
5063 
5064         if (newIcicle != null) {
5065             // If icicle is null, this is happening due to a timeout, so we haven't really saved
5066             // the state.
5067             setSavedState(newIcicle);
5068             launchCount = 0;
5069             updateTaskDescription(description);
5070         }
5071         if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + mIcicle);
5072         if (!stopped) {
5073             if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
5074             removeStopTimeout();
5075             stopped = true;
5076             if (isStopping) {
5077                 setState(STOPPED, "activityStoppedLocked");
5078             }
5079 
5080             notifyAppStopped();
5081 
5082             if (finishing) {
5083                 clearOptionsLocked();
5084             } else {
5085                 if (deferRelaunchUntilPaused) {
5086                     destroyImmediately(true /* removeFromApp */, "stop-config");
5087                     mRootWindowContainer.resumeFocusedStacksTopActivities();
5088                 } else {
5089                     mRootWindowContainer.updatePreviousProcess(this);
5090                 }
5091             }
5092         }
5093     }
5094 
addToStopping(boolean scheduleIdle, boolean idleDelayed, String reason)5095     void addToStopping(boolean scheduleIdle, boolean idleDelayed, String reason) {
5096         if (!mStackSupervisor.mStoppingActivities.contains(this)) {
5097             EventLogTags.writeWmAddToStopping(mUserId, System.identityHashCode(this),
5098                     shortComponentName, reason);
5099             mStackSupervisor.mStoppingActivities.add(this);
5100         }
5101 
5102         final ActivityStack stack = getRootTask();
5103         // If we already have a few activities waiting to stop, then give up on things going idle
5104         // and start clearing them out. Or if r is the last of activity of the last task the stack
5105         // will be empty and must be cleared immediately.
5106         boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE
5107                 || (isRootOfTask() && stack.getChildCount() <= 1);
5108         if (scheduleIdle || forceIdle) {
5109             if (DEBUG_PAUSE) {
5110                 Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle=" + forceIdle
5111                         + "immediate=" + !idleDelayed);
5112             }
5113             if (!idleDelayed) {
5114                 mStackSupervisor.scheduleIdle();
5115             } else {
5116                 mStackSupervisor.scheduleIdleTimeout(this);
5117             }
5118         } else {
5119             stack.checkReadyForSleep();
5120         }
5121     }
5122 
startLaunchTickingLocked()5123     void startLaunchTickingLocked() {
5124         if (Build.IS_USER) {
5125             return;
5126         }
5127         if (launchTickTime == 0) {
5128             launchTickTime = SystemClock.uptimeMillis();
5129             continueLaunchTicking();
5130         }
5131     }
5132 
continueLaunchTicking()5133     private boolean continueLaunchTicking() {
5134         if (launchTickTime == 0) {
5135             return false;
5136         }
5137 
5138         final ActivityStack stack = getRootTask();
5139         if (stack == null) {
5140             return false;
5141         }
5142 
5143         stack.removeLaunchTickMessages();
5144         mAtmService.mH.postDelayed(mLaunchTickRunnable, LAUNCH_TICK);
5145         return true;
5146     }
5147 
removeLaunchTickRunnable()5148     void removeLaunchTickRunnable() {
5149         mAtmService.mH.removeCallbacks(mLaunchTickRunnable);
5150     }
5151 
finishLaunchTickingLocked()5152     void finishLaunchTickingLocked() {
5153         launchTickTime = 0;
5154         final ActivityStack stack = getRootTask();
5155         if (stack == null) {
5156             return;
5157         }
5158         stack.removeLaunchTickMessages();
5159     }
5160 
mayFreezeScreenLocked()5161     boolean mayFreezeScreenLocked() {
5162         return mayFreezeScreenLocked(app);
5163     }
5164 
mayFreezeScreenLocked(WindowProcessController app)5165     private boolean mayFreezeScreenLocked(WindowProcessController app) {
5166         // Only freeze the screen if this activity is currently attached to
5167         // an application, and that application is not blocked or unresponding.
5168         // In any other case, we can't count on getting the screen unfrozen,
5169         // so it is best to leave as-is.
5170         return hasProcess() && !app.isCrashing() && !app.isNotResponding();
5171     }
5172 
startFreezingScreenLocked(int configChanges)5173     void startFreezingScreenLocked(int configChanges) {
5174         startFreezingScreenLocked(app, configChanges);
5175     }
5176 
startFreezingScreenLocked(WindowProcessController app, int configChanges)5177     void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
5178         if (mayFreezeScreenLocked(app)) {
5179             if (getParent() == null) {
5180                 Slog.w(TAG_WM,
5181                         "Attempted to freeze screen with non-existing app token: " + appToken);
5182                 return;
5183             }
5184 
5185             // Window configuration changes only effect windows, so don't require a screen freeze.
5186             int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION);
5187             if (freezableConfigChanges == 0 && okToDisplay()) {
5188                 ProtoLog.v(WM_DEBUG_ORIENTATION, "Skipping set freeze of %s", appToken);
5189                 return;
5190             }
5191 
5192             startFreezingScreen();
5193         }
5194     }
5195 
startFreezingScreen()5196     void startFreezingScreen() {
5197         startFreezingScreen(ROTATION_UNDEFINED /* overrideOriginalDisplayRotation */);
5198     }
5199 
startFreezingScreen(int overrideOriginalDisplayRotation)5200     void startFreezingScreen(int overrideOriginalDisplayRotation) {
5201         ProtoLog.i(WM_DEBUG_ORIENTATION,
5202                 "Set freezing of %s: visible=%b freezing=%b visibleRequested=%b. %s",
5203                 appToken, isVisible(), mFreezingScreen, mVisibleRequested,
5204                 new RuntimeException().fillInStackTrace());
5205         if (!mVisibleRequested) {
5206             return;
5207         }
5208 
5209         // If the override is given, the rotation of display doesn't change but we still want to
5210         // cover the activity whose configuration is changing by freezing the display and running
5211         // the rotation animation.
5212         final boolean forceRotation = overrideOriginalDisplayRotation != ROTATION_UNDEFINED;
5213         if (!mFreezingScreen) {
5214             mFreezingScreen = true;
5215             mWmService.registerAppFreezeListener(this);
5216             mWmService.mAppsFreezingScreen++;
5217             if (mWmService.mAppsFreezingScreen == 1) {
5218                 if (forceRotation) {
5219                     // Make sure normal rotation animation will be applied.
5220                     mDisplayContent.getDisplayRotation().cancelSeamlessRotation();
5221                 }
5222                 mWmService.startFreezingDisplay(0 /* exitAnim */, 0 /* enterAnim */,
5223                         mDisplayContent, overrideOriginalDisplayRotation);
5224                 mWmService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
5225                 mWmService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
5226             }
5227         }
5228         if (forceRotation) {
5229             // The rotation of the real display won't change, so in order to unfreeze the screen
5230             // via {@link #checkAppWindowsReadyToShow}, the windows have to be able to call
5231             // {@link WindowState#reportResized} (it is skipped if the window is freezing) to update
5232             // the drawn state.
5233             return;
5234         }
5235         final int count = mChildren.size();
5236         for (int i = 0; i < count; i++) {
5237             final WindowState w = mChildren.get(i);
5238             w.onStartFreezingScreen();
5239         }
5240     }
5241 
isFreezingScreen()5242     boolean isFreezingScreen() {
5243         return mFreezingScreen;
5244     }
5245 
5246     @Override
onAppFreezeTimeout()5247     public void onAppFreezeTimeout() {
5248         Slog.w(TAG_WM, "Force clearing freeze: " + this);
5249         stopFreezingScreen(true, true);
5250     }
5251 
stopFreezingScreenLocked(boolean force)5252     void stopFreezingScreenLocked(boolean force) {
5253         if (force || frozenBeforeDestroy) {
5254             frozenBeforeDestroy = false;
5255             if (getParent() == null) {
5256                 return;
5257             }
5258             ProtoLog.v(WM_DEBUG_ORIENTATION,
5259                         "Clear freezing of %s: visible=%b freezing=%b", appToken,
5260                                 isVisible(), isFreezingScreen());
5261             stopFreezingScreen(true, force);
5262         }
5263     }
5264 
stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force)5265     void stopFreezingScreen(boolean unfreezeSurfaceNow, boolean force) {
5266         if (!mFreezingScreen) {
5267             return;
5268         }
5269         ProtoLog.v(WM_DEBUG_ORIENTATION,
5270                 "Clear freezing of %s force=%b", this, force);
5271         final int count = mChildren.size();
5272         boolean unfrozeWindows = false;
5273         for (int i = 0; i < count; i++) {
5274             final WindowState w = mChildren.get(i);
5275             unfrozeWindows |= w.onStopFreezingScreen();
5276         }
5277         if (force || unfrozeWindows) {
5278             ProtoLog.v(WM_DEBUG_ORIENTATION, "No longer freezing: %s", this);
5279             mFreezingScreen = false;
5280             mWmService.unregisterAppFreezeListener(this);
5281             mWmService.mAppsFreezingScreen--;
5282             mWmService.mLastFinishedFreezeSource = this;
5283         }
5284         if (unfreezeSurfaceNow) {
5285             if (unfrozeWindows) {
5286                 mWmService.mWindowPlacerLocked.performSurfacePlacement();
5287             }
5288             mWmService.stopFreezingDisplayLocked();
5289         }
5290     }
5291 
reportFullyDrawnLocked(boolean restoredFromBundle)5292     void reportFullyDrawnLocked(boolean restoredFromBundle) {
5293         final TransitionInfoSnapshot info = mStackSupervisor
5294             .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
5295         if (info != null) {
5296             mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
5297                     info.windowsFullyDrawnDelayMs, info.getLaunchState());
5298         }
5299     }
5300 
onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator)5301     void onFirstWindowDrawn(WindowState win, WindowStateAnimator winAnimator) {
5302         firstWindowDrawn = true;
5303 
5304         // We now have a good window to show, remove dead placeholders
5305         removeDeadWindows();
5306 
5307         if (startingWindow != null) {
5308             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finish starting %s"
5309                     + ": first real window is shown, no animation", win.mToken);
5310             // If this initial window is animating, stop it -- we will do an animation to reveal
5311             // it from behind the starting window, so there is no need for it to also be doing its
5312             // own stuff.
5313             win.cancelAnimation();
5314         }
5315         removeStartingWindow();
5316         updateReportedVisibilityLocked();
5317     }
5318 
onStartingWindowDrawn()5319     void onStartingWindowDrawn() {
5320         if (task != null) {
5321             task.setHasBeenVisible(true);
5322         }
5323     }
5324 
5325     /** Called when the windows associated app window container are drawn. */
onWindowsDrawn(boolean drawn, long timestampNs)5326     void onWindowsDrawn(boolean drawn, long timestampNs) {
5327         mDrawn = drawn;
5328         if (!drawn) {
5329             return;
5330         }
5331         final TransitionInfoSnapshot info = mStackSupervisor
5332                 .getActivityMetricsLogger().notifyWindowsDrawn(this, timestampNs);
5333         final boolean validInfo = info != null;
5334         final int windowsDrawnDelayMs = validInfo ? info.windowsDrawnDelayMs : INVALID_DELAY;
5335         final @LaunchState int launchState = validInfo ? info.getLaunchState() : -1;
5336         // The activity may have been requested to be invisible (another activity has been launched)
5337         // so there is no valid info. But if it is the current top activity (e.g. sleeping), the
5338         // invalid state is still reported to make sure the waiting result is notified.
5339         if (validInfo || this == getDisplayArea().topRunningActivity()) {
5340             mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
5341                     windowsDrawnDelayMs, launchState);
5342             mStackSupervisor.stopWaitingForActivityVisible(this, windowsDrawnDelayMs);
5343         }
5344         finishLaunchTickingLocked();
5345         if (task != null) {
5346             task.setHasBeenVisible(true);
5347         }
5348     }
5349 
5350     /** Called when the windows associated app window container are visible. */
onWindowsVisible()5351     void onWindowsVisible() {
5352         if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting visible in " + appToken);
5353         mStackSupervisor.stopWaitingForActivityVisible(this);
5354         if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
5355         if (!nowVisible) {
5356             nowVisible = true;
5357             lastVisibleTime = SystemClock.uptimeMillis();
5358             mAtmService.scheduleAppGcsLocked();
5359         }
5360     }
5361 
5362     /** Called when the windows associated app window container are no longer visible. */
onWindowsGone()5363     void onWindowsGone() {
5364         if (DEBUG_VISIBILITY) Slog.v(TAG_WM, "Reporting gone in " + appToken);
5365         if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
5366         nowVisible = false;
5367     }
5368 
5369     @Override
checkAppWindowsReadyToShow()5370     void checkAppWindowsReadyToShow() {
5371         if (allDrawn == mLastAllDrawn) {
5372             return;
5373         }
5374 
5375         mLastAllDrawn = allDrawn;
5376         if (!allDrawn) {
5377             return;
5378         }
5379 
5380         // The token has now changed state to having all windows shown...  what to do, what to do?
5381         if (mFreezingScreen) {
5382             showAllWindowsLocked();
5383             stopFreezingScreen(false, true);
5384             ProtoLog.i(WM_DEBUG_ORIENTATION,
5385                     "Setting mOrientationChangeComplete=true because wtoken %s "
5386                             + "numInteresting=%d numDrawn=%d",
5387                     this, mNumInterestingWindows, mNumDrawnWindows);
5388             // This will set mOrientationChangeComplete and cause a pass through layout.
5389             setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
5390                     "checkAppWindowsReadyToShow: freezingScreen");
5391         } else {
5392             setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM, "checkAppWindowsReadyToShow");
5393 
5394             // We can now show all of the drawn windows!
5395             if (!getDisplayContent().mOpeningApps.contains(this) && canShowWindows()) {
5396                 showAllWindowsLocked();
5397             }
5398         }
5399     }
5400 
5401     /**
5402      * This must be called while inside a transaction.
5403      */
showAllWindowsLocked()5404     void showAllWindowsLocked() {
5405         forAllWindows(windowState -> {
5406             if (DEBUG_VISIBILITY) Slog.v(TAG, "performing show on: " + windowState);
5407             windowState.performShowLocked();
5408         }, false /* traverseTopToBottom */);
5409     }
5410 
updateReportedVisibilityLocked()5411     void updateReportedVisibilityLocked() {
5412         if (appToken == null) {
5413             return;
5414         }
5415 
5416         if (DEBUG_VISIBILITY) Slog.v(TAG, "Update reported visibility: " + this);
5417         final int count = mChildren.size();
5418 
5419         mReportedVisibilityResults.reset();
5420 
5421         for (int i = 0; i < count; i++) {
5422             final WindowState win = mChildren.get(i);
5423             win.updateReportedVisibility(mReportedVisibilityResults);
5424         }
5425 
5426         int numInteresting = mReportedVisibilityResults.numInteresting;
5427         int numVisible = mReportedVisibilityResults.numVisible;
5428         int numDrawn = mReportedVisibilityResults.numDrawn;
5429         boolean nowGone = mReportedVisibilityResults.nowGone;
5430 
5431         boolean nowDrawn = numInteresting > 0 && numDrawn >= numInteresting;
5432         boolean nowVisible = numInteresting > 0 && numVisible >= numInteresting && isVisible();
5433         if (!nowGone) {
5434             // If the app is not yet gone, then it can only become visible/drawn.
5435             if (!nowDrawn) {
5436                 nowDrawn = reportedDrawn;
5437             }
5438             if (!nowVisible) {
5439                 nowVisible = reportedVisible;
5440             }
5441         }
5442         if (DEBUG_VISIBILITY) Slog.v(TAG, "VIS " + this + ": interesting="
5443                 + numInteresting + " visible=" + numVisible);
5444         if (nowDrawn != reportedDrawn) {
5445             onWindowsDrawn(nowDrawn, SystemClock.elapsedRealtimeNanos());
5446             reportedDrawn = nowDrawn;
5447         }
5448         if (nowVisible != reportedVisible) {
5449             if (DEBUG_VISIBILITY) Slog.v(TAG,
5450                     "Visibility changed in " + this + ": vis=" + nowVisible);
5451             reportedVisible = nowVisible;
5452             if (nowVisible) {
5453                 onWindowsVisible();
5454             } else {
5455                 onWindowsGone();
5456             }
5457         }
5458     }
5459 
isClientVisible()5460     boolean isClientVisible() {
5461         return mClientVisible;
5462     }
5463 
setClientVisible(boolean clientVisible)5464     void setClientVisible(boolean clientVisible) {
5465         if (mClientVisible == clientVisible || (!clientVisible && mDeferHidingClient)) {
5466             return;
5467         }
5468         ProtoLog.v(WM_DEBUG_APP_TRANSITIONS,
5469                 "setClientVisible: %s clientVisible=%b Callers=%s", this, clientVisible,
5470                 Debug.getCallers(5));
5471         mClientVisible = clientVisible;
5472         sendAppVisibilityToClients();
5473     }
5474 
5475     /**
5476      * Updated this app token tracking states for interesting and drawn windows based on the window.
5477      *
5478      * @return Returns true if the input window is considered interesting and drawn while all the
5479      *         windows in this app token where not considered drawn as of the last pass.
5480      */
updateDrawnWindowStates(WindowState w)5481     boolean updateDrawnWindowStates(WindowState w) {
5482         w.setDrawnStateEvaluated(true /*evaluated*/);
5483 
5484         if (DEBUG_STARTING_WINDOW_VERBOSE && w == startingWindow) {
5485             Slog.d(TAG, "updateWindows: starting " + w + " isOnScreen=" + w.isOnScreen()
5486                     + " allDrawn=" + allDrawn + " freezingScreen=" + mFreezingScreen);
5487         }
5488 
5489         if (allDrawn && !mFreezingScreen) {
5490             return false;
5491         }
5492 
5493         if (mLastTransactionSequence != mWmService.mTransactionSequence) {
5494             mLastTransactionSequence = mWmService.mTransactionSequence;
5495             mNumDrawnWindows = 0;
5496             startingDisplayed = false;
5497 
5498             // There is the main base application window, even if it is exiting, wait for it
5499             mNumInterestingWindows = findMainWindow(false /* includeStartingApp */) != null ? 1 : 0;
5500         }
5501 
5502         final WindowStateAnimator winAnimator = w.mWinAnimator;
5503 
5504         boolean isInterestingAndDrawn = false;
5505 
5506         if (!allDrawn && w.mightAffectAllDrawn()) {
5507             if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
5508                 Slog.v(TAG, "Eval win " + w + ": isDrawn=" + w.isDrawnLw()
5509                         + ", isAnimationSet=" + isAnimating(TRANSITION | PARENTS));
5510                 if (!w.isDrawnLw()) {
5511                     Slog.v(TAG, "Not displayed: s=" + winAnimator.mSurfaceController
5512                             + " pv=" + w.isVisibleByPolicy()
5513                             + " mDrawState=" + winAnimator.drawStateToString()
5514                             + " ph=" + w.isParentWindowHidden() + " th=" + mVisibleRequested
5515                             + " a=" + isAnimating(TRANSITION | PARENTS));
5516                 }
5517             }
5518 
5519             if (w != startingWindow) {
5520                 if (w.isInteresting()) {
5521                     // Add non-main window as interesting since the main app has already been added
5522                     if (findMainWindow(false /* includeStartingApp */) != w) {
5523                         mNumInterestingWindows++;
5524                     }
5525                     if (w.isDrawnLw()) {
5526                         mNumDrawnWindows++;
5527 
5528                         if (DEBUG_VISIBILITY || WM_DEBUG_ORIENTATION.isLogToLogcat()) {
5529                             Slog.v(TAG, "tokenMayBeDrawn: "
5530                                     + this + " w=" + w + " numInteresting=" + mNumInterestingWindows
5531                                     + " freezingScreen=" + mFreezingScreen
5532                                     + " mAppFreezing=" + w.mAppFreezing);
5533                         }
5534 
5535                         isInterestingAndDrawn = true;
5536                     }
5537                 }
5538             } else if (w.isDrawnLw()) {
5539                 // The starting window for this container is drawn.
5540                 mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(this);
5541                 startingDisplayed = true;
5542             }
5543         }
5544 
5545         return isInterestingAndDrawn;
5546     }
5547 
5548     /**
5549      * Called when the key dispatching to a window associated with the app window container
5550      * timed-out.
5551      *
5552      * @param reason The reason for the key dispatching time out.
5553      * @param windowPid The pid of the window key dispatching timed out on.
5554      * @return True if input dispatching should be aborted.
5555      */
keyDispatchingTimedOut(String reason, int windowPid)5556     public boolean keyDispatchingTimedOut(String reason, int windowPid) {
5557         ActivityRecord anrActivity;
5558         WindowProcessController anrApp;
5559         boolean windowFromSameProcessAsActivity;
5560         synchronized (mAtmService.mGlobalLock) {
5561             anrActivity = getWaitingHistoryRecordLocked();
5562             anrApp = app;
5563             windowFromSameProcessAsActivity =
5564                     !hasProcess() || app.getPid() == windowPid || windowPid == INVALID_PID;
5565         }
5566 
5567         if (windowFromSameProcessAsActivity) {
5568             return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
5569                     anrActivity.shortComponentName, anrActivity.info.applicationInfo,
5570                     shortComponentName, app, false, reason);
5571         } else {
5572             // In this case another process added windows using this activity token. So, we call the
5573             // generic service input dispatch timed out method so that the right process is blamed.
5574             return mAtmService.mAmInternal.inputDispatchingTimedOut(
5575                     windowPid, false /* aboveSystem */, reason) < 0;
5576         }
5577     }
5578 
getWaitingHistoryRecordLocked()5579     private ActivityRecord getWaitingHistoryRecordLocked() {
5580         // First find the real culprit...  if this activity has stopped, then the key dispatching
5581         // timeout should not be caused by this.
5582         if (stopped) {
5583             final ActivityStack stack = mRootWindowContainer.getTopDisplayFocusedStack();
5584             if (stack == null) {
5585                 return this;
5586             }
5587             // Try to use the one which is closest to top.
5588             ActivityRecord r = stack.getResumedActivity();
5589             if (r == null) {
5590                 r = stack.mPausingActivity;
5591             }
5592             if (r != null) {
5593                 return r;
5594             }
5595         }
5596         return this;
5597     }
5598 
5599     /** Checks whether the activity should be shown for current user. */
okToShowLocked()5600     public boolean okToShowLocked() {
5601         // We cannot show activities when the device is locked and the application is not
5602         // encryption aware.
5603         if (!StorageManager.isUserKeyUnlocked(mUserId)
5604                 && !info.applicationInfo.isEncryptionAware()) {
5605             return false;
5606         }
5607 
5608         return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
5609                 || (mStackSupervisor.isCurrentProfileLocked(mUserId)
5610                 && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
5611     }
5612 
canBeTopRunning()5613     boolean canBeTopRunning() {
5614         return !finishing && okToShowLocked();
5615     }
5616 
5617     /**
5618      * This method will return true if the activity is either visible, is becoming visible, is
5619      * currently pausing, or is resumed.
5620      */
isInterestingToUserLocked()5621     public boolean isInterestingToUserLocked() {
5622         return mVisibleRequested || nowVisible || mState == PAUSING || mState == RESUMED;
5623     }
5624 
setSleeping(boolean sleeping)5625     void setSleeping(boolean sleeping) {
5626         mSetToSleep = sleeping;
5627     }
5628 
getTaskForActivityLocked(IBinder token, boolean onlyRoot)5629     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
5630         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
5631         if (r == null || r.getParent() == null) {
5632             return INVALID_TASK_ID;
5633         }
5634         final Task task = r.task;
5635         if (onlyRoot && r.compareTo(task.getRootActivity(
5636                 false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/)) > 0) {
5637             return INVALID_TASK_ID;
5638         }
5639         return task.mTaskId;
5640     }
5641 
isInStackLocked(IBinder token)5642     static ActivityRecord isInStackLocked(IBinder token) {
5643         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
5644         return (r != null) ? r.getRootTask().isInTask(r) : null;
5645     }
5646 
getStackLocked(IBinder token)5647     static ActivityStack getStackLocked(IBinder token) {
5648         final ActivityRecord r = ActivityRecord.isInStackLocked(token);
5649         if (r != null) {
5650             return r.getRootTask();
5651         }
5652         return null;
5653     }
5654 
5655     /**
5656      * @return display id to which this record is attached,
5657      *         {@link android.view.Display#INVALID_DISPLAY} if not attached.
5658      */
getDisplayId()5659     int getDisplayId() {
5660         final ActivityStack stack = getRootTask();
5661         if (stack == null) {
5662             return INVALID_DISPLAY;
5663         }
5664         return stack.getDisplayId();
5665     }
5666 
isDestroyable()5667     final boolean isDestroyable() {
5668         if (finishing || !hasProcess()) {
5669             // This would be redundant.
5670             return false;
5671         }
5672         final ActivityStack stack = getRootTask();
5673         if (isState(RESUMED) || stack == null || this == stack.mPausingActivity || !mHaveState
5674                 || !stopped) {
5675             // We're not ready for this kind of thing.
5676             return false;
5677         }
5678         if (mVisibleRequested) {
5679             // The user would notice this!
5680             return false;
5681         }
5682         return true;
5683     }
5684 
createImageFilename(long createTime, int taskId)5685     private static String createImageFilename(long createTime, int taskId) {
5686         return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
5687                 IMAGE_EXTENSION;
5688     }
5689 
setTaskDescription(TaskDescription _taskDescription)5690     void setTaskDescription(TaskDescription _taskDescription) {
5691         Bitmap icon;
5692         if (_taskDescription.getIconFilename() == null &&
5693                 (icon = _taskDescription.getIcon()) != null) {
5694             final String iconFilename = createImageFilename(createTime, task.mTaskId);
5695             final File iconFile = new File(TaskPersister.getUserImagesDir(task.mUserId),
5696                     iconFilename);
5697             final String iconFilePath = iconFile.getAbsolutePath();
5698             mAtmService.getRecentTasks().saveImage(icon, iconFilePath);
5699             _taskDescription.setIconFilename(iconFilePath);
5700         }
5701         taskDescription = _taskDescription;
5702         getTask().updateTaskDescription();
5703     }
5704 
setVoiceSessionLocked(IVoiceInteractionSession session)5705     void setVoiceSessionLocked(IVoiceInteractionSession session) {
5706         voiceSession = session;
5707         pendingVoiceInteractionStart = false;
5708     }
5709 
clearVoiceSessionLocked()5710     void clearVoiceSessionLocked() {
5711         voiceSession = null;
5712         pendingVoiceInteractionStart = false;
5713     }
5714 
showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch)5715     void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) {
5716         if (mTaskOverlay) {
5717             // We don't show starting window for overlay activities.
5718             return;
5719         }
5720         if (pendingOptions != null
5721                 && pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
5722             // Don't show starting window when using shared element transition.
5723             return;
5724         }
5725 
5726         final CompatibilityInfo compatInfo =
5727                 mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo);
5728         final boolean shown = addStartingWindow(packageName, theme,
5729                 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
5730                 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
5731                 allowTaskSnapshot(),
5732                 mState.ordinal() >= STARTED.ordinal() && mState.ordinal() <= STOPPED.ordinal());
5733         if (shown) {
5734             mStartingWindowState = STARTING_WINDOW_SHOWN;
5735         }
5736     }
5737 
5738     /**
5739      * If any activities below the top running one are in the INITIALIZING state and they have a
5740      * starting window displayed then remove that starting window. It is possible that the activity
5741      * in this state will never resumed in which case that starting window will be orphaned.
5742      * <p>
5743      * It should only be called if this activity is behind other fullscreen activity.
5744      */
cancelInitializing()5745     void cancelInitializing() {
5746         if (mStartingWindowState == STARTING_WINDOW_SHOWN) {
5747             // Remove orphaned starting window.
5748             if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
5749             mStartingWindowState = STARTING_WINDOW_REMOVED;
5750             removeStartingWindow();
5751         }
5752         if (isState(INITIALIZING) && !shouldBeVisible(
5753                 true /* behindFullscreenActivity */, true /* ignoringKeyguard */)) {
5754             // Remove the unknown visibility record because an invisible activity shouldn't block
5755             // the keyguard transition.
5756             mDisplayContent.mUnknownAppVisibilityController.appRemovedOrHidden(this);
5757         }
5758     }
5759 
postWindowRemoveStartingWindowCleanup(WindowState win)5760     void postWindowRemoveStartingWindowCleanup(WindowState win) {
5761         // TODO: Something smells about the code below...Is there a better way?
5762         if (startingWindow == win) {
5763             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Notify removed startingWindow %s", win);
5764             removeStartingWindow();
5765         } else if (mChildren.size() == 0) {
5766             // If this is the last window and we had requested a starting transition window,
5767             // well there is no point now.
5768             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Nulling last startingData");
5769             mStartingData = null;
5770             if (mVisibleSetFromTransferredStartingWindow) {
5771                 // We set the visible state to true for the token from a transferred starting
5772                 // window. We now reset it back to false since the starting window was the last
5773                 // window in the token.
5774                 setVisible(false);
5775             }
5776         } else if (mChildren.size() == 1 && startingSurface != null && !isRelaunching()) {
5777             // If this is the last window except for a starting transition window,
5778             // we need to get rid of the starting transition.
5779             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Last window, removing starting window %s", win);
5780             removeStartingWindow();
5781         }
5782     }
5783 
removeDeadWindows()5784     void removeDeadWindows() {
5785         for (int winNdx = mChildren.size() - 1; winNdx >= 0; --winNdx) {
5786             WindowState win = mChildren.get(winNdx);
5787             if (win.mAppDied) {
5788                 ProtoLog.w(WM_DEBUG_ADD_REMOVE,
5789                         "removeDeadWindows: %s", win);
5790                 // Set mDestroying, we don't want any animation or delayed removal here.
5791                 win.mDestroying = true;
5792                 // Also removes child windows.
5793                 win.removeIfPossible();
5794             }
5795         }
5796     }
5797 
hasWindowsAlive()5798     boolean hasWindowsAlive() {
5799         for (int i = mChildren.size() - 1; i >= 0; i--) {
5800             // No need to loop through child windows as the answer should be the same as that of the
5801             // parent window.
5802             if (!(mChildren.get(i)).mAppDied) {
5803                 return true;
5804             }
5805         }
5806         return false;
5807     }
5808 
setWillReplaceWindows(boolean animate)5809     void setWillReplaceWindows(boolean animate) {
5810         ProtoLog.d(WM_DEBUG_ADD_REMOVE,
5811                 "Marking app token %s with replacing windows.", this);
5812 
5813         for (int i = mChildren.size() - 1; i >= 0; i--) {
5814             final WindowState w = mChildren.get(i);
5815             w.setWillReplaceWindow(animate);
5816         }
5817     }
5818 
setWillReplaceChildWindows()5819     void setWillReplaceChildWindows() {
5820         ProtoLog.d(WM_DEBUG_ADD_REMOVE, "Marking app token %s"
5821                 + " with replacing child windows.", this);
5822         for (int i = mChildren.size() - 1; i >= 0; i--) {
5823             final WindowState w = mChildren.get(i);
5824             w.setWillReplaceChildWindows();
5825         }
5826     }
5827 
clearWillReplaceWindows()5828     void clearWillReplaceWindows() {
5829         ProtoLog.d(WM_DEBUG_ADD_REMOVE,
5830                 "Resetting app token %s of replacing window marks.", this);
5831 
5832         for (int i = mChildren.size() - 1; i >= 0; i--) {
5833             final WindowState w = mChildren.get(i);
5834             w.clearWillReplaceWindow();
5835         }
5836     }
5837 
requestUpdateWallpaperIfNeeded()5838     void requestUpdateWallpaperIfNeeded() {
5839         for (int i = mChildren.size() - 1; i >= 0; i--) {
5840             final WindowState w = mChildren.get(i);
5841             w.requestUpdateWallpaperIfNeeded();
5842         }
5843     }
5844 
5845     /**
5846      * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
5847      *         true and isn't fully transparent.
5848      */
getTopFullscreenOpaqueWindow()5849     WindowState getTopFullscreenOpaqueWindow() {
5850         for (int i = mChildren.size() - 1; i >= 0; i--) {
5851             final WindowState win = mChildren.get(i);
5852             if (win != null && win.mAttrs.isFullscreen() && !win.isFullyTransparent()) {
5853                 return win;
5854             }
5855         }
5856         return null;
5857     }
5858 
findMainWindow()5859     WindowState findMainWindow() {
5860         return findMainWindow(true);
5861     }
5862 
5863     /**
5864      * Finds the main window that either has type base application or application starting if
5865      * requested.
5866      *
5867      * @param includeStartingApp Allow to search application-starting windows to also be returned.
5868      * @return The main window of type base application or application starting if requested.
5869      */
findMainWindow(boolean includeStartingApp)5870     WindowState findMainWindow(boolean includeStartingApp) {
5871         WindowState candidate = null;
5872         for (int j = mChildren.size() - 1; j >= 0; --j) {
5873             final WindowState win = mChildren.get(j);
5874             final int type = win.mAttrs.type;
5875             // No need to loop through child window as base application and starting types can't be
5876             // child windows.
5877             if (type == TYPE_BASE_APPLICATION
5878                     || (includeStartingApp && type == TYPE_APPLICATION_STARTING)) {
5879                 // In cases where there are multiple windows, we prefer the non-exiting window. This
5880                 // happens for example when replacing windows during an activity relaunch. When
5881                 // constructing the animation, we want the new window, not the exiting one.
5882                 if (win.mAnimatingExit) {
5883                     candidate = win;
5884                 } else {
5885                     return win;
5886                 }
5887             }
5888         }
5889         return candidate;
5890     }
5891 
getAppAnimationLayer()5892     SurfaceControl getAppAnimationLayer() {
5893         return getAppAnimationLayer(isActivityTypeHome() ? ANIMATION_LAYER_HOME
5894                 : needsZBoost() ? ANIMATION_LAYER_BOOSTED
5895                         : ANIMATION_LAYER_STANDARD);
5896     }
5897 
5898     @Override
needsZBoost()5899     boolean needsZBoost() {
5900         return mNeedsZBoost || super.needsZBoost();
5901     }
5902 
5903     @Override
getAnimationLeashParent()5904     public SurfaceControl getAnimationLeashParent() {
5905         // For transitions in the pinned stack (menu activity) we just let them occur as a child
5906         // of the pinned stack.
5907         // All normal app transitions take place in an animation layer which is below the pinned
5908         // stack but may be above the parent stacks of the given animating apps by default. When
5909         // a new hierarchical animation is enabled, we just let them occur as a child of the parent
5910         // stack, i.e. the hierarchy of the surfaces is unchanged.
5911         if (inPinnedWindowingMode()) {
5912             return getStack().getSurfaceControl();
5913         } else if (WindowManagerService.sHierarchicalAnimations) {
5914             return super.getAnimationLeashParent();
5915         } else {
5916             return getAppAnimationLayer();
5917         }
5918     }
5919 
5920     @VisibleForTesting
shouldAnimate()5921     boolean shouldAnimate() {
5922         return task == null || task.shouldAnimate();
5923     }
5924 
5925     /**
5926      * Creates a layer to apply crop to an animation.
5927      */
createAnimationBoundsLayer(Transaction t)5928     private SurfaceControl createAnimationBoundsLayer(Transaction t) {
5929         ProtoLog.i(WM_DEBUG_APP_TRANSITIONS_ANIM, "Creating animation bounds layer");
5930         final SurfaceControl.Builder builder = makeAnimationLeash()
5931                 .setParent(getAnimationLeashParent())
5932                 .setName(getSurfaceControl() + " - animation-bounds")
5933                 .setCallsite("ActivityRecord.createAnimationBoundsLayer");
5934         final SurfaceControl boundsLayer = builder.build();
5935         t.show(boundsLayer);
5936         return boundsLayer;
5937     }
5938 
5939     @Override
shouldDeferAnimationFinish(Runnable endDeferFinishCallback)5940     public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
5941         return mAnimatingActivityRegistry != null
5942                 && mAnimatingActivityRegistry.notifyAboutToFinish(
5943                 this, endDeferFinishCallback);
5944     }
5945 
5946     @Override
isWaitingForTransitionStart()5947     boolean isWaitingForTransitionStart() {
5948         final DisplayContent dc = getDisplayContent();
5949         return dc != null && dc.mAppTransition.isTransitionSet()
5950                 && (dc.mOpeningApps.contains(this)
5951                 || dc.mClosingApps.contains(this)
5952                 || dc.mChangingContainers.contains(this));
5953     }
5954 
getAnimationLayer()5955     private int getAnimationLayer() {
5956         // The leash is parented to the animation layer. We need to preserve the z-order by using
5957         // the prefix order index, but we boost if necessary.
5958         int layer;
5959         if (!inPinnedWindowingMode()) {
5960             layer = getPrefixOrderIndex();
5961         } else {
5962             // Pinned stacks have animations take place within themselves rather than an animation
5963             // layer so we need to preserve the order relative to the stack (e.g. the order of our
5964             // task/parent).
5965             layer = getParent().getPrefixOrderIndex();
5966         }
5967 
5968         if (mNeedsZBoost) {
5969             layer += Z_BOOST_BASE;
5970         }
5971         return layer;
5972     }
5973 
5974     @Override
onAnimationLeashCreated(Transaction t, SurfaceControl leash)5975     public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
5976         t.setLayer(leash, getAnimationLayer());
5977         getDisplayContent().assignStackOrdering();
5978     }
5979 
5980     @Override
onLeashAnimationStarting(Transaction t, SurfaceControl leash)5981     public void onLeashAnimationStarting(Transaction t, SurfaceControl leash) {
5982         if (mAnimatingActivityRegistry != null) {
5983             mAnimatingActivityRegistry.notifyStarting(this);
5984         }
5985 
5986         // If the animation needs to be cropped then an animation bounds layer is created as a child
5987         // of the pinned stack or animation layer. The leash is then reparented to this new layer.
5988         if (mNeedsAnimationBoundsLayer) {
5989             mTmpRect.setEmpty();
5990             if (getDisplayContent().mAppTransitionController.isTransitWithinTask(
5991                     getTransit(), task)) {
5992                 task.getBounds(mTmpRect);
5993             } else {
5994                 final ActivityStack stack = getStack();
5995                 if (stack == null) {
5996                     return;
5997                 }
5998                 // Set clip rect to stack bounds.
5999                 stack.getBounds(mTmpRect);
6000             }
6001             mAnimationBoundsLayer = createAnimationBoundsLayer(t);
6002 
6003             // Crop to stack bounds.
6004             if (!WindowManagerService.sHierarchicalAnimations) {
6005                 // For Hierarchical animation, we don't need to set window crop since the leash
6006                 // surface size has already same as the animating container.
6007                 t.setWindowCrop(mAnimationBoundsLayer, mTmpRect);
6008             }
6009             t.setLayer(leash, 0);
6010             t.setLayer(mAnimationBoundsLayer, getAnimationLayer());
6011 
6012             // Reparent leash to animation bounds layer.
6013             t.reparent(leash, mAnimationBoundsLayer);
6014         }
6015     }
6016 
6017     @Override
prepareSurfaces()6018     void prepareSurfaces() {
6019         final boolean show = isVisible() || isAnimatingExcluding(PARENTS,
6020                 ANIMATION_TYPE_SCREEN_ROTATION);
6021 
6022         if (mSurfaceControl != null) {
6023             if (show && !mLastSurfaceShowing) {
6024                 getSyncTransaction().show(mSurfaceControl);
6025             } else if (!show && mLastSurfaceShowing) {
6026                 getSyncTransaction().hide(mSurfaceControl);
6027             }
6028         }
6029         if (mThumbnail != null) {
6030             mThumbnail.setShowing(getPendingTransaction(), show);
6031         }
6032         mLastSurfaceShowing = show;
6033         super.prepareSurfaces();
6034     }
6035 
6036     /**
6037      * @return Whether our {@link #getSurfaceControl} is currently showing.
6038      */
isSurfaceShowing()6039     boolean isSurfaceShowing() {
6040         return mLastSurfaceShowing;
6041     }
6042 
attachThumbnailAnimation()6043     void attachThumbnailAnimation() {
6044         if (!isAnimating(PARENTS)) {
6045             return;
6046         }
6047         final GraphicBuffer thumbnailHeader =
6048                 getDisplayContent().mAppTransition.getAppTransitionThumbnailHeader(task);
6049         if (thumbnailHeader == null) {
6050             ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, "No thumbnail header bitmap for: %s", task);
6051             return;
6052         }
6053         clearThumbnail();
6054         final Transaction transaction = getAnimatingContainer().getPendingTransaction();
6055         mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
6056                 transaction, getAnimatingContainer(), thumbnailHeader);
6057         mThumbnail.startAnimation(transaction, loadThumbnailAnimation(thumbnailHeader));
6058     }
6059 
6060     /**
6061      * Attaches a surface with a thumbnail for the
6062      * {@link android.app.ActivityOptions#ANIM_OPEN_CROSS_PROFILE_APPS} animation.
6063      */
attachCrossProfileAppsThumbnailAnimation()6064     void attachCrossProfileAppsThumbnailAnimation() {
6065         if (!isAnimating(PARENTS)) {
6066             return;
6067         }
6068         clearThumbnail();
6069 
6070         final WindowState win = findMainWindow();
6071         if (win == null) {
6072             return;
6073         }
6074         final Rect frame = win.getRelativeFrameLw();
6075         final int thumbnailDrawableRes = task.mUserId == mWmService.mCurrentUserId
6076                 ? R.drawable.ic_account_circle
6077                 : R.drawable.ic_corp_badge;
6078         final GraphicBuffer thumbnail =
6079                 getDisplayContent().mAppTransition
6080                         .createCrossProfileAppsThumbnail(thumbnailDrawableRes, frame);
6081         if (thumbnail == null) {
6082             return;
6083         }
6084         final Transaction transaction = getPendingTransaction();
6085         mThumbnail = new WindowContainerThumbnail(mWmService.mSurfaceFactory,
6086                 transaction, getTask(), thumbnail);
6087         final Animation animation =
6088                 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
6089                         frame);
6090         mThumbnail.startAnimation(transaction, animation, new Point(frame.left, frame.top));
6091     }
6092 
loadThumbnailAnimation(GraphicBuffer thumbnailHeader)6093     private Animation loadThumbnailAnimation(GraphicBuffer thumbnailHeader) {
6094         final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
6095 
6096         // If this is a multi-window scenario, we use the windows frame as
6097         // destination of the thumbnail header animation. If this is a full screen
6098         // window scenario, we use the whole display as the target.
6099         WindowState win = findMainWindow();
6100         Rect appRect = win != null ? win.getContentFrameLw() :
6101                 new Rect(0, 0, displayInfo.appWidth, displayInfo.appHeight);
6102         final Rect insets = win != null ? win.getContentInsets() : null;
6103         final Configuration displayConfig = mDisplayContent.getConfiguration();
6104         return getDisplayContent().mAppTransition.createThumbnailAspectScaleAnimationLocked(
6105                 appRect, insets, thumbnailHeader, task, displayConfig.uiMode,
6106                 displayConfig.orientation);
6107     }
6108 
6109     @Override
onAnimationLeashLost(Transaction t)6110     public void onAnimationLeashLost(Transaction t) {
6111         super.onAnimationLeashLost(t);
6112         if (mAnimationBoundsLayer != null) {
6113             t.remove(mAnimationBoundsLayer);
6114             mAnimationBoundsLayer = null;
6115         }
6116 
6117         if (mAnimatingActivityRegistry != null) {
6118             mAnimatingActivityRegistry.notifyFinished(this);
6119         }
6120     }
6121 
6122     @Override
onAnimationFinished(@nimationType int type, AnimationAdapter anim)6123     protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
6124         super.onAnimationFinished(type, anim);
6125 
6126         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished");
6127         mTransit = TRANSIT_UNSET;
6128         mTransitFlags = 0;
6129         mNeedsAnimationBoundsLayer = false;
6130 
6131         setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
6132                 "ActivityRecord");
6133 
6134         clearThumbnail();
6135         setClientVisible(isVisible() || mVisibleRequested);
6136 
6137         getDisplayContent().computeImeTargetIfNeeded(this);
6138 
6139         if (DEBUG_ANIM) Slog.v(TAG, "Animation done in " + this
6140                 + ": reportedVisible=" + reportedVisible
6141                 + " okToDisplay=" + okToDisplay()
6142                 + " okToAnimate=" + okToAnimate()
6143                 + " startingDisplayed=" + startingDisplayed);
6144 
6145         // clean up thumbnail window
6146         if (mThumbnail != null) {
6147             mThumbnail.destroy();
6148             mThumbnail = null;
6149         }
6150 
6151         // WindowState.onExitAnimationDone might modify the children list, so make a copy and then
6152         // traverse the copy.
6153         final ArrayList<WindowState> children = new ArrayList<>(mChildren);
6154         children.forEach(WindowState::onExitAnimationDone);
6155 
6156         getDisplayContent().mAppTransition.notifyAppTransitionFinishedLocked(token);
6157         scheduleAnimation();
6158 
6159         if (!mStackSupervisor.mStoppingActivities.isEmpty()
6160                 || !mStackSupervisor.mFinishingActivities.isEmpty()) {
6161             if (mRootWindowContainer.allResumedActivitiesIdle()) {
6162                 // If all activities are already idle then we now need to make sure we perform
6163                 // the full stop of this activity. This is because we won't do that while they
6164                 // are still waiting for the animation to finish.
6165                 mStackSupervisor.scheduleIdle();
6166             } else if (mRootWindowContainer.allResumedActivitiesVisible()) {
6167                 // If all resumed activities are already visible (and should be drawn, see
6168                 // updateReportedVisibility ~ nowVisible) but not idle, we still schedule to
6169                 // process the stopping and finishing activities because the transition is done.
6170                 // This also avoids if the next activity never reports idle (e.g. animating view),
6171                 // the previous will need to wait until idle timeout to be stopped or destroyed.
6172                 mStackSupervisor.scheduleProcessStoppingAndFinishingActivities();
6173             }
6174         }
6175         Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
6176     }
6177 
clearAnimatingFlags()6178     void clearAnimatingFlags() {
6179         boolean wallpaperMightChange = false;
6180         for (int i = mChildren.size() - 1; i >= 0; i--) {
6181             final WindowState win = mChildren.get(i);
6182             wallpaperMightChange |= win.clearAnimatingFlags();
6183         }
6184         if (wallpaperMightChange) {
6185             requestUpdateWallpaperIfNeeded();
6186         }
6187     }
6188 
6189     @Override
cancelAnimation()6190     void cancelAnimation() {
6191         super.cancelAnimation();
6192         clearThumbnail();
6193     }
6194 
6195     @VisibleForTesting
getThumbnail()6196     WindowContainerThumbnail getThumbnail() {
6197         return mThumbnail;
6198     }
6199 
clearThumbnail()6200     private void clearThumbnail() {
6201         if (mThumbnail == null) {
6202             return;
6203         }
6204         mThumbnail.destroy();
6205         mThumbnail = null;
6206     }
6207 
getTransit()6208     public int getTransit() {
6209         return mTransit;
6210     }
6211 
getTransitFlags()6212     int getTransitFlags() {
6213         return mTransitFlags;
6214     }
6215 
registerRemoteAnimations(RemoteAnimationDefinition definition)6216     void registerRemoteAnimations(RemoteAnimationDefinition definition) {
6217         mRemoteAnimationDefinition = definition;
6218         if (definition != null) {
6219             definition.linkToDeath(this::unregisterRemoteAnimations);
6220         }
6221     }
6222 
unregisterRemoteAnimations()6223     void unregisterRemoteAnimations() {
6224         mRemoteAnimationDefinition = null;
6225     }
6226 
6227     @Override
getRemoteAnimationDefinition()6228     RemoteAnimationDefinition getRemoteAnimationDefinition() {
6229         return mRemoteAnimationDefinition;
6230     }
6231 
6232     @Override
applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames, Configuration config)6233     void applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames,
6234             Configuration config) {
6235         super.applyFixedRotationTransform(info, displayFrames, config);
6236         ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
6237     }
6238 
6239     @Override
onCancelFixedRotationTransform(int originalDisplayRotation)6240     void onCancelFixedRotationTransform(int originalDisplayRotation) {
6241         if (this != mDisplayContent.getLastOrientationSource()
6242                 || getRequestedConfigurationOrientation() != ORIENTATION_UNDEFINED) {
6243             // Only need to handle the activity that should be rotated with display.
6244             return;
6245         }
6246 
6247         // Perform rotation animation according to the rotation of this activity.
6248         startFreezingScreen(originalDisplayRotation);
6249         // This activity may relaunch or perform configuration change so once it has reported drawn,
6250         // the screen can be unfrozen.
6251         ensureActivityConfiguration(0 /* globalChanges */, !PRESERVE_WINDOWS);
6252     }
6253 
setRequestedOrientation(int requestedOrientation)6254     void setRequestedOrientation(int requestedOrientation) {
6255         setOrientation(requestedOrientation, mayFreezeScreenLocked());
6256         mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
6257                 task.mTaskId, requestedOrientation);
6258     }
6259 
setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded)6260     private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
6261         final IBinder binder =
6262                 (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
6263         setOrientation(requestedOrientation, binder, this);
6264 
6265         // Push the new configuration to the requested app in case where it's not pushed, e.g. when
6266         // the request is handled at task level with letterbox.
6267         if (!getMergedOverrideConfiguration().equals(
6268                 mLastReportedConfiguration.getMergedConfiguration())) {
6269             ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
6270         }
6271     }
6272 
reportDescendantOrientationChangeIfNeeded()6273     void reportDescendantOrientationChangeIfNeeded() {
6274         // Orientation request is exposed only when we're visible. Therefore visibility change
6275         // will change requested orientation. Notify upward the hierarchy ladder to adjust
6276         // configuration. This is important to cases where activities with incompatible
6277         // orientations launch, or user goes back from an activity of bi-orientation to an
6278         // activity with specified orientation.
6279         if (getRequestedOrientation() == SCREEN_ORIENTATION_UNSET) {
6280             return;
6281         }
6282 
6283         final IBinder freezeToken = mayFreezeScreenLocked() ? appToken : null;
6284         onDescendantOrientationChanged(freezeToken, this);
6285     }
6286 
6287     /**
6288      * We override because this class doesn't want its children affecting its reported orientation
6289      * in anyway.
6290      */
6291     @Override
getOrientation(int candidate)6292     int getOrientation(int candidate) {
6293         if (candidate == SCREEN_ORIENTATION_BEHIND) {
6294             // Allow app to specify orientation regardless of its visibility state if the current
6295             // candidate want us to use orientation behind. I.e. the visible app on-top of this one
6296             // wants us to use the orientation of the app behind it.
6297             return mOrientation;
6298         }
6299 
6300         // The {@link ActivityRecord} should only specify an orientation when it is not closing.
6301         // Allowing closing {@link ActivityRecord} to participate can lead to an Activity in another
6302         // task being started in the wrong orientation during the transition.
6303         if (!getDisplayContent().mClosingApps.contains(this)
6304                 && (isVisible() || getDisplayContent().mOpeningApps.contains(this))) {
6305             return mOrientation;
6306         }
6307 
6308         return SCREEN_ORIENTATION_UNSET;
6309     }
6310 
6311     /** Returns the app's preferred orientation regardless of its currently visibility state. */
getRequestedOrientation()6312     int getRequestedOrientation() {
6313         return mOrientation;
6314     }
6315 
6316     /**
6317      * Set the last reported global configuration to the client. Should be called whenever a new
6318      * global configuration is sent to the client for this activity.
6319      */
setLastReportedGlobalConfiguration(@onNull Configuration config)6320     void setLastReportedGlobalConfiguration(@NonNull Configuration config) {
6321         mLastReportedConfiguration.setGlobalConfiguration(config);
6322     }
6323 
6324     /**
6325      * Set the last reported configuration to the client. Should be called whenever
6326      * a new merged configuration is sent to the client for this activity.
6327      */
setLastReportedConfiguration(@onNull MergedConfiguration config)6328     void setLastReportedConfiguration(@NonNull MergedConfiguration config) {
6329         setLastReportedConfiguration(config.getGlobalConfiguration(),
6330             config.getOverrideConfiguration());
6331     }
6332 
setLastReportedConfiguration(Configuration global, Configuration override)6333     private void setLastReportedConfiguration(Configuration global, Configuration override) {
6334         mLastReportedConfiguration.setConfiguration(global, override);
6335     }
6336 
6337     /**
6338      * @return {@code true} if this activity is in size compatibility mode that uses the different
6339      *         density than its parent or its bounds don't fit in parent naturally.
6340      */
inSizeCompatMode()6341     boolean inSizeCompatMode() {
6342         if (mCompatDisplayInsets == null || !shouldUseSizeCompatMode()
6343                 // The orientation is different from parent when transforming.
6344                 || isFixedRotationTransforming()) {
6345             return false;
6346         }
6347         final Rect appBounds = getConfiguration().windowConfiguration.getAppBounds();
6348         if (appBounds == null) {
6349             // The app bounds hasn't been computed yet.
6350             return false;
6351         }
6352 
6353         final Configuration parentConfig = getParent().getConfiguration();
6354         // Although colorMode, screenLayout, smallestScreenWidthDp are also fixed, generally these
6355         // fields should be changed with density and bounds, so here only compares the most
6356         // significant field.
6357         if (parentConfig.densityDpi != getConfiguration().densityDpi) {
6358             return true;
6359         }
6360 
6361         final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
6362         final int appWidth = appBounds.width();
6363         final int appHeight = appBounds.height();
6364         final int parentAppWidth = parentAppBounds.width();
6365         final int parentAppHeight = parentAppBounds.height();
6366         if (parentAppWidth == appWidth && parentAppHeight == appHeight) {
6367             // Matched the parent bounds.
6368             return false;
6369         }
6370         if (parentAppWidth > appWidth && parentAppHeight > appHeight) {
6371             // Both sides are smaller than the parent.
6372             return true;
6373         }
6374         if (parentAppWidth < appWidth || parentAppHeight < appHeight) {
6375             // One side is larger than the parent.
6376             return true;
6377         }
6378 
6379         // The rest of the condition is that only one side is smaller than the parent, but it still
6380         // needs to exclude the cases where the size is limited by the fixed aspect ratio.
6381         if (info.maxAspectRatio > 0) {
6382             final float aspectRatio = (0.5f + Math.max(appWidth, appHeight))
6383                     / Math.min(appWidth, appHeight);
6384             if (aspectRatio >= info.maxAspectRatio) {
6385                 // The current size has reached the max aspect ratio.
6386                 return false;
6387             }
6388         }
6389         if (info.minAspectRatio > 0) {
6390             // The activity should have at least the min aspect ratio, so this checks if the parent
6391             // still has available space to provide larger aspect ratio.
6392             final float parentAspectRatio = (0.5f + Math.max(parentAppWidth, parentAppHeight))
6393                     / Math.min(parentAppWidth, parentAppHeight);
6394             if (parentAspectRatio <= info.minAspectRatio) {
6395                 // The long side has reached the parent.
6396                 return false;
6397             }
6398         }
6399         return true;
6400     }
6401 
6402     /**
6403      * Indicates the activity will keep the bounds and screen configuration when it was first
6404      * launched, no matter how its parent changes.
6405      *
6406      * @return {@code true} if this activity is declared as non-resizable and fixed orientation or
6407      *         aspect ratio.
6408      */
shouldUseSizeCompatMode()6409     boolean shouldUseSizeCompatMode() {
6410         if (info.supportsSizeChanges) {
6411             return false;
6412         }
6413         if (inMultiWindowMode() || getWindowConfiguration().hasWindowDecorCaption()) {
6414             final ActivityRecord root = task != null ? task.getRootActivity() : null;
6415             if (root != null && root != this && !root.shouldUseSizeCompatMode()) {
6416                 // If the root activity doesn't use size compatibility mode, the activities above
6417                 // are forced to be the same for consistent visual appearance.
6418                 return false;
6419             }
6420         }
6421         return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
6422                 // The configuration of non-standard type should be enforced by system.
6423                 && isActivityTypeStandard()
6424                 && !mAtmService.mForceResizableActivities;
6425     }
6426 
hasSizeCompatBounds()6427     boolean hasSizeCompatBounds() {
6428         return mSizeCompatBounds != null;
6429     }
6430 
6431     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
updateSizeCompatMode()6432     private void updateSizeCompatMode() {
6433         if (mCompatDisplayInsets != null || !shouldUseSizeCompatMode()) {
6434             // The override configuration is set only once in size compatibility mode.
6435             return;
6436         }
6437         final Configuration parentConfig = getParent().getConfiguration();
6438         if (!hasProcess() && !isConfigurationCompatible(parentConfig)) {
6439             // Don't compute when launching in fullscreen and the fixed orientation is not the
6440             // current orientation. It is more accurately to compute the override bounds from
6441             // the updated configuration after the fixed orientation is applied.
6442             return;
6443         }
6444 
6445         Configuration overrideConfig = getRequestedOverrideConfiguration();
6446         final Configuration fullConfig = getConfiguration();
6447 
6448         // Ensure the screen related fields are set. It is used to prevent activity relaunch
6449         // when moving between displays. For screenWidthDp and screenWidthDp, because they
6450         // are relative to bounds and density, they will be calculated in
6451         // {@link Task#computeConfigResourceOverrides} and the result will also be
6452         // relatively fixed.
6453         overrideConfig.colorMode = fullConfig.colorMode;
6454         overrideConfig.densityDpi = fullConfig.densityDpi;
6455         // The smallest screen width is the short side of screen bounds. Because the bounds
6456         // and density won't be changed, smallestScreenWidthDp is also fixed.
6457         overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp;
6458         if (info.isFixedOrientation()) {
6459             // lock rotation too. When in size-compat, onConfigurationChanged will watch for and
6460             // apply runtime rotation changes.
6461             overrideConfig.windowConfiguration.setRotation(
6462                     fullConfig.windowConfiguration.getRotation());
6463         }
6464 
6465         // The role of CompatDisplayInsets is like the override bounds.
6466         mCompatDisplayInsets = new CompatDisplayInsets(mDisplayContent, this);
6467     }
6468 
6469     @VisibleForTesting
clearSizeCompatMode()6470     void clearSizeCompatMode() {
6471         mSizeCompatScale = 1f;
6472         mSizeCompatBounds = null;
6473         mCompatDisplayInsets = null;
6474         onRequestedOverrideConfigurationChanged(EMPTY);
6475     }
6476 
6477     @Override
matchParentBounds()6478     public boolean matchParentBounds() {
6479         final Rect overrideBounds = getResolvedOverrideBounds();
6480         if (overrideBounds.isEmpty()) {
6481             return true;
6482         }
6483         // An activity in size compatibility mode may have override bounds which equals to its
6484         // parent bounds, so the exact bounds should also be checked to allow IME window to attach
6485         // to the activity. See {@link DisplayContent#isImeAttachedToApp}.
6486         final WindowContainer parent = getParent();
6487         return parent == null || parent.getBounds().equals(overrideBounds);
6488     }
6489 
6490     @Override
getSizeCompatScale()6491     float getSizeCompatScale() {
6492         return hasSizeCompatBounds() ? mSizeCompatScale : super.getSizeCompatScale();
6493     }
6494 
6495     @Override
resolveOverrideConfiguration(Configuration newParentConfiguration)6496     void resolveOverrideConfiguration(Configuration newParentConfiguration) {
6497         super.resolveOverrideConfiguration(newParentConfiguration);
6498         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
6499         if (isFixedRotationTransforming()) {
6500             // The resolved configuration is applied with rotated display configuration. If this
6501             // activity matches its parent (the following resolving procedures are no-op), then it
6502             // can use the resolved configuration directly. Otherwise (e.g. fixed aspect ratio),
6503             // the rotated configuration is used as parent configuration to compute the actual
6504             // resolved configuration. It is like putting the activity in a rotated container.
6505             mTmpConfig.setTo(newParentConfiguration);
6506             mTmpConfig.updateFrom(resolvedConfig);
6507             newParentConfiguration = mTmpConfig;
6508         }
6509         if (mCompatDisplayInsets != null) {
6510             resolveSizeCompatModeConfiguration(newParentConfiguration);
6511         } else {
6512             if (inMultiWindowMode()) {
6513                 // We ignore activities' requested orientation in multi-window modes. Task level may
6514                 // take them into consideration when calculating bounds.
6515                 resolvedConfig.orientation = Configuration.ORIENTATION_UNDEFINED;
6516                 // If the activity has requested override bounds, the configuration needs to be
6517                 // computed accordingly.
6518                 if (!matchParentBounds()) {
6519                     task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration);
6520                 }
6521             } else {
6522                 resolveFullscreenConfiguration(newParentConfiguration);
6523             }
6524         }
6525 
6526         // Assign configuration sequence number into hierarchy because there is a different way than
6527         // ensureActivityConfiguration() in this class that uses configuration in WindowState during
6528         // layout traversals.
6529         mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
6530         getResolvedOverrideConfiguration().seq = mConfigurationSeq;
6531     }
6532 
6533     /**
6534      * Resolves the configuration of activity in fullscreen mode. If the bounds are restricted by
6535      * aspect ratio, the position will be centered horizontally in parent's app bounds to balance
6536      * the visual appearance. The policy of aspect ratio has higher priority than the requested
6537      * override bounds.
6538      */
resolveFullscreenConfiguration(Configuration newParentConfiguration)6539     private void resolveFullscreenConfiguration(Configuration newParentConfiguration) {
6540         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
6541         final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
6542         final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
6543         final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
6544         // Use tmp bounds to calculate aspect ratio so we can know whether the activity should use
6545         // restricted size (resolved bounds may be the requested override bounds).
6546         mTmpBounds.setEmpty();
6547         applyAspectRatio(mTmpBounds, parentAppBounds, parentBounds);
6548         // If the out bounds is not empty, it means the activity cannot fill parent's app bounds,
6549         // then there is space to be centered.
6550         final boolean needToBeCentered = !mTmpBounds.isEmpty();
6551         if (needToBeCentered) {
6552             resolvedBounds.set(mTmpBounds);
6553             // Exclude the horizontal decor area.
6554             resolvedBounds.left = parentAppBounds.left;
6555         }
6556         if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) {
6557             // Compute the configuration based on the resolved bounds. If aspect ratio doesn't
6558             // restrict, the bounds should be the requested override bounds.
6559             task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
6560                     getFixedRotationTransformDisplayInfo());
6561         }
6562         if (needToBeCentered) {
6563             // Offset to center relative to parent's app bounds.
6564             final int offsetX = getHorizontalCenterOffset(
6565                     parentAppBounds.width(), resolvedBounds.width());
6566             offsetBounds(resolvedConfig, offsetX, 0 /* offsetY */);
6567         }
6568     }
6569 
6570     /**
6571      * Resolves consistent screen configuration for orientation and rotation changes without
6572      * inheriting the parent bounds.
6573      */
resolveSizeCompatModeConfiguration(Configuration newParentConfiguration)6574     private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
6575         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
6576         final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
6577         final int requestedOrientation = getRequestedConfigurationOrientation();
6578         final boolean orientationRequested = requestedOrientation != ORIENTATION_UNDEFINED
6579                 && !mDisplayContent.ignoreRotationForApps();
6580         final int orientation = orientationRequested
6581                 ? requestedOrientation
6582                 : newParentConfiguration.orientation;
6583         int rotation = newParentConfiguration.windowConfiguration.getRotation();
6584         final boolean canChangeOrientation = handlesOrientationChangeFromDescendant();
6585         if (canChangeOrientation && !mCompatDisplayInsets.mIsFloating) {
6586             // Use parent rotation because the original display can rotate by requested orientation.
6587             resolvedConfig.windowConfiguration.setRotation(rotation);
6588         } else {
6589             final int overrideRotation = resolvedConfig.windowConfiguration.getRotation();
6590             if (overrideRotation != ROTATION_UNDEFINED) {
6591                 rotation = overrideRotation;
6592             }
6593         }
6594 
6595         // Use compat insets to lock width and height. We should not use the parent width and height
6596         // because apps in compat mode should have a constant width and height. The compat insets
6597         // are locked when the app is first launched and are never changed after that, so we can
6598         // rely on them to contain the original and unchanging width and height of the app.
6599         final Rect containingAppBounds = new Rect();
6600         final Rect containingBounds = mTmpBounds;
6601         mCompatDisplayInsets.getContainerBounds(containingAppBounds, containingBounds, rotation,
6602                 orientation, orientationRequested, canChangeOrientation);
6603         resolvedBounds.set(containingBounds);
6604         // The size of floating task is fixed (only swap), so the aspect ratio is already correct.
6605         if (!mCompatDisplayInsets.mIsFloating) {
6606             applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
6607         }
6608         // If the bounds are restricted by fixed aspect ratio, the resolved bounds should be put in
6609         // the container app bounds. Otherwise the entire container bounds are available.
6610         final boolean fillContainer = resolvedBounds.equals(containingBounds);
6611         if (!fillContainer) {
6612             // The horizontal position should not cover insets.
6613             resolvedBounds.left = containingAppBounds.left;
6614         }
6615 
6616         // Use resolvedBounds to compute other override configurations such as appBounds. The bounds
6617         // are calculated in compat container space. The actual position on screen will be applied
6618         // later, so the calculation is simpler that doesn't need to involve offset from parent.
6619         task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
6620                 mCompatDisplayInsets);
6621         // Use current screen layout as source because the size of app is independent to parent.
6622         resolvedConfig.screenLayout = Task.computeScreenLayoutOverride(
6623                 getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
6624                 resolvedConfig.screenHeightDp);
6625 
6626         // Use parent orientation if it cannot be decided by bounds, so the activity can fit inside
6627         // the parent bounds appropriately.
6628         if (resolvedConfig.screenWidthDp == resolvedConfig.screenHeightDp) {
6629             resolvedConfig.orientation = newParentConfiguration.orientation;
6630         }
6631 
6632         // Below figure is an example that puts an activity which was launched in a larger container
6633         // into a smaller container.
6634         //   The outermost rectangle is the real display bounds.
6635         //   "@" is the parent app bounds.
6636         //   "#" is the {@code resolvedBounds} that applies to application.
6637         //   "*" is the {@code mSizeCompatBounds} that used to show on screen if scaled.
6638         // ------------------------------
6639         // |                            |
6640         // |    @@@@*********@@@@###    |
6641         // |    @   *       *   @  #    |
6642         // |    @   *       *   @  #    |
6643         // |    @   *       *   @  #    |
6644         // |    @@@@*********@@@@  #    |
6645         // ---------#--------------#-----
6646         //          #              #
6647         //          ################
6648         // The application is still layouted in "#" since it was launched, and it will be visually
6649         // scaled and positioned to "*".
6650 
6651         // Calculates the scale and offset to horizontal center the size compatibility bounds into
6652         // the region which is available to application.
6653         final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
6654         final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
6655         final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
6656         final int contentW = resolvedAppBounds.width();
6657         final int contentH = resolvedAppBounds.height();
6658         final int viewportW = parentAppBounds.width();
6659         final int viewportH = parentAppBounds.height();
6660         // Only allow to scale down.
6661         mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
6662                 ? 1f : Math.min((float) viewportW / contentW, (float) viewportH / contentH);
6663         final int screenTopInset = parentAppBounds.top - parentBounds.top;
6664         final boolean topNotAligned = screenTopInset != resolvedAppBounds.top - resolvedBounds.top;
6665         if (mSizeCompatScale != 1f || topNotAligned) {
6666             if (mSizeCompatBounds == null) {
6667                 mSizeCompatBounds = new Rect();
6668             }
6669             mSizeCompatBounds.set(resolvedAppBounds);
6670             mSizeCompatBounds.offsetTo(0, 0);
6671             mSizeCompatBounds.scale(mSizeCompatScale);
6672             // The insets are included in height, e.g. the area of real cutout shouldn't be scaled.
6673             mSizeCompatBounds.bottom += screenTopInset;
6674         } else {
6675             mSizeCompatBounds = null;
6676         }
6677 
6678         // Center horizontally in parent (app bounds) and align to top of parent (bounds)
6679         // - this is a UX choice.
6680         final int offsetX = getHorizontalCenterOffset(
6681                 (int) viewportW, (int) (contentW * mSizeCompatScale));
6682         // Above coordinates are in "@" space, now place "*" and "#" to screen space.
6683         final int screenPosX = (fillContainer ? parentBounds.left : parentAppBounds.left) + offsetX;
6684         final int screenPosY = parentBounds.top;
6685         if (screenPosX != 0 || screenPosY != 0) {
6686             if (mSizeCompatBounds != null) {
6687                 mSizeCompatBounds.offset(screenPosX, screenPosY);
6688             }
6689             // Add the global coordinates and remove the local coordinates.
6690             final int dx = screenPosX - resolvedBounds.left;
6691             final int dy = screenPosY - resolvedBounds.top;
6692             offsetBounds(resolvedConfig, dx, dy);
6693         }
6694     }
6695 
6696     /** @return The horizontal offset of putting the content in the center of viewport. */
getHorizontalCenterOffset(int viewportW, int contentW)6697     private static int getHorizontalCenterOffset(int viewportW, int contentW) {
6698         return (int) ((viewportW - contentW + 1) * 0.5f);
6699     }
6700 
offsetBounds(Configuration inOutConfig, int offsetX, int offsetY)6701     private static void offsetBounds(Configuration inOutConfig, int offsetX, int offsetY) {
6702         inOutConfig.windowConfiguration.getBounds().offset(offsetX, offsetY);
6703         inOutConfig.windowConfiguration.getAppBounds().offset(offsetX, offsetY);
6704     }
6705 
6706     @Override
getBounds()6707     public Rect getBounds() {
6708         if (mSizeCompatBounds != null) {
6709             return mSizeCompatBounds;
6710         }
6711         return super.getBounds();
6712     }
6713 
6714     @VisibleForTesting
6715     @Override
getAnimationBounds(int appStackClipMode)6716     Rect getAnimationBounds(int appStackClipMode) {
6717         if (appStackClipMode == STACK_CLIP_BEFORE_ANIM && getStack() != null) {
6718             // Using the stack bounds here effectively applies the clipping before animation.
6719             return getStack().getBounds();
6720         }
6721         // Use task-bounds if available so that activity-level letterbox (maxAspectRatio) is
6722         // included in the animation.
6723         return task != null ? task.getBounds() : getBounds();
6724     }
6725 
6726     @Override
getAnimationPosition(Point outPosition)6727     void getAnimationPosition(Point outPosition) {
6728         // Always animate from zero because if the activity doesn't fill the task, the letterbox
6729         // will fill the remaining area that should be included in the animation.
6730         outPosition.set(0, 0);
6731     }
6732 
6733     @Override
onConfigurationChanged(Configuration newParentConfig)6734     public void onConfigurationChanged(Configuration newParentConfig) {
6735         if (mCompatDisplayInsets != null) {
6736             Configuration overrideConfig = getRequestedOverrideConfiguration();
6737             // Adapt to changes in orientation locking. The app is still non-resizable, but
6738             // it can change which orientation is fixed. If the fixed orientation changes,
6739             // update the rotation used on the "compat" display
6740             boolean wasFixedOrient =
6741                     overrideConfig.windowConfiguration.getRotation() != ROTATION_UNDEFINED;
6742             int requestedOrient = getRequestedConfigurationOrientation();
6743             if (requestedOrient != ORIENTATION_UNDEFINED
6744                     && requestedOrient != getConfiguration().orientation
6745                     // The task orientation depends on the top activity orientation, so it
6746                     // should match. If it doesn't, just wait until it does.
6747                     && requestedOrient == getParent().getConfiguration().orientation
6748                     && (overrideConfig.windowConfiguration.getRotation()
6749                             != getParent().getWindowConfiguration().getRotation())) {
6750                 overrideConfig.windowConfiguration.setRotation(
6751                         getParent().getWindowConfiguration().getRotation());
6752                 onRequestedOverrideConfigurationChanged(overrideConfig);
6753                 return;
6754             } else if (wasFixedOrient && requestedOrient == ORIENTATION_UNDEFINED
6755                     && (overrideConfig.windowConfiguration.getRotation()
6756                             != ROTATION_UNDEFINED)) {
6757                 overrideConfig.windowConfiguration.setRotation(ROTATION_UNDEFINED);
6758                 onRequestedOverrideConfigurationChanged(overrideConfig);
6759                 return;
6760             }
6761         }
6762         super.onConfigurationChanged(newParentConfig);
6763 
6764         // Configuration's equality doesn't consider seq so if only seq number changes in resolved
6765         // override configuration. Therefore ConfigurationContainer doesn't change merged override
6766         // configuration, but it's used to push configuration changes so explicitly update that.
6767         if (getMergedOverrideConfiguration().seq != getResolvedOverrideConfiguration().seq) {
6768             onMergedOverrideConfigurationChanged();
6769         }
6770 
6771         final DisplayContent display = getDisplay();
6772         if (display == null) {
6773             return;
6774         }
6775         if (mVisibleRequested) {
6776             // It may toggle the UI for user to restart the size compatibility mode activity.
6777             display.handleActivitySizeCompatModeIfNeeded(this);
6778         } else if (mCompatDisplayInsets != null) {
6779             // The override changes can only be obtained from display, because we don't have the
6780             // difference of full configuration in each hierarchy.
6781             final int displayChanges = display.getCurrentOverrideConfigurationChanges();
6782             final int orientationChanges = CONFIG_WINDOW_CONFIGURATION
6783                     | CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION;
6784             final boolean hasNonOrienSizeChanged = hasResizeChange(displayChanges)
6785                     // Filter out the case of simple orientation change.
6786                     && (displayChanges & orientationChanges) != orientationChanges;
6787             // For background activity that uses size compatibility mode, if the size or density of
6788             // the display is changed, then reset the override configuration and kill the activity's
6789             // process if its process state is not important to user.
6790             if (hasNonOrienSizeChanged || (displayChanges & ActivityInfo.CONFIG_DENSITY) != 0) {
6791                 restartProcessIfVisible();
6792             }
6793         }
6794     }
6795 
6796     /** Returns true if the configuration is compatible with this activity. */
isConfigurationCompatible(Configuration config)6797     boolean isConfigurationCompatible(Configuration config) {
6798         final int orientation = getRequestedOrientation();
6799         if (isFixedOrientationPortrait(orientation)
6800                 && config.orientation != ORIENTATION_PORTRAIT) {
6801             return false;
6802         }
6803         if (isFixedOrientationLandscape(orientation)
6804                 && config.orientation != ORIENTATION_LANDSCAPE) {
6805             return false;
6806         }
6807         return true;
6808     }
6809 
6810     /**
6811      * Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
6812      * made to outBounds.
6813      */
6814     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
applyAspectRatio(Rect outBounds, Rect containingAppBounds, Rect containingBounds)6815     private void applyAspectRatio(Rect outBounds, Rect containingAppBounds,
6816             Rect containingBounds) {
6817         final float maxAspectRatio = info.maxAspectRatio;
6818         final ActivityStack stack = getRootTask();
6819         final float minAspectRatio = info.minAspectRatio;
6820 
6821         if (task == null || stack == null || (inMultiWindowMode() && !shouldUseSizeCompatMode())
6822                 || (maxAspectRatio == 0 && minAspectRatio == 0)
6823                 || isInVrUiMode(getConfiguration())) {
6824             // We don't enforce aspect ratio if the activity task is in multiwindow unless it
6825             // is in size-compat mode. We also don't set it if we are in VR mode.
6826             return;
6827         }
6828 
6829         final int containingAppWidth = containingAppBounds.width();
6830         final int containingAppHeight = containingAppBounds.height();
6831         final float containingRatio = Math.max(containingAppWidth, containingAppHeight)
6832                 / (float) Math.min(containingAppWidth, containingAppHeight);
6833 
6834         int activityWidth = containingAppWidth;
6835         int activityHeight = containingAppHeight;
6836 
6837         if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
6838             if (containingAppWidth < containingAppHeight) {
6839                 // Width is the shorter side, so we use that to figure-out what the max. height
6840                 // should be given the aspect ratio.
6841                 activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
6842             } else {
6843                 // Height is the shorter side, so we use that to figure-out what the max. width
6844                 // should be given the aspect ratio.
6845                 activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
6846             }
6847         } else if (containingRatio < minAspectRatio) {
6848             boolean adjustWidth;
6849             switch (getRequestedConfigurationOrientation()) {
6850                 case ORIENTATION_LANDSCAPE:
6851                     // Width should be the longer side for this landscape app, so we use the width
6852                     // to figure-out what the max. height should be given the aspect ratio.
6853                     adjustWidth = false;
6854                     break;
6855                 case ORIENTATION_PORTRAIT:
6856                     // Height should be the longer side for this portrait app, so we use the height
6857                     // to figure-out what the max. width should be given the aspect ratio.
6858                     adjustWidth = true;
6859                     break;
6860                 default:
6861                     // This app doesn't have a preferred orientation, so we keep the length of the
6862                     // longer side, and use it to figure-out the length of the shorter side.
6863                     if (containingAppWidth < containingAppHeight) {
6864                         // Width is the shorter side, so we use the height to figure-out what the
6865                         // max. width should be given the aspect ratio.
6866                         adjustWidth = true;
6867                     } else {
6868                         // Height is the shorter side, so we use the width to figure-out what the
6869                         // max. height should be given the aspect ratio.
6870                         adjustWidth = false;
6871                     }
6872                     break;
6873             }
6874             if (adjustWidth) {
6875                 activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
6876             } else {
6877                 activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
6878             }
6879         }
6880 
6881         if (containingAppWidth <= activityWidth && containingAppHeight <= activityHeight) {
6882             // The display matches or is less than the activity aspect ratio, so nothing else to do.
6883             return;
6884         }
6885 
6886         // Compute configuration based on max supported width and height.
6887         // Also account for the left / top insets (e.g. from display cutouts), which will be clipped
6888         // away later in {@link Task#computeConfigResourceOverrides()}. Otherwise, the app
6889         // bounds would end up too small.
6890         outBounds.set(containingBounds.left, containingBounds.top,
6891                 activityWidth + containingAppBounds.left,
6892                 activityHeight + containingAppBounds.top);
6893     }
6894 
6895     /**
6896      * @return {@code true} if this activity was reparented to another display but
6897      *         {@link #ensureActivityConfiguration} is not called.
6898      */
shouldUpdateConfigForDisplayChanged()6899     boolean shouldUpdateConfigForDisplayChanged() {
6900         return mLastReportedDisplayId != getDisplayId();
6901     }
6902 
ensureActivityConfiguration(int globalChanges, boolean preserveWindow)6903     boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
6904         return ensureActivityConfiguration(globalChanges, preserveWindow,
6905                 false /* ignoreVisibility */);
6906     }
6907 
6908     /**
6909      * Make sure the given activity matches the current configuration. Ensures the HistoryRecord
6910      * is updated with the correct configuration and all other bookkeeping is handled.
6911      *
6912      * @param globalChanges The changes to the global configuration.
6913      * @param preserveWindow If the activity window should be preserved on screen if the activity
6914      *                       is relaunched.
6915      * @param ignoreVisibility If we should try to relaunch the activity even if it is invisible
6916      *                         (stopped state). This is useful for the case where we know the
6917      *                         activity will be visible soon and we want to ensure its configuration
6918      *                         before we make it visible.
6919      * @return False if the activity was relaunched and true if it wasn't relaunched because we
6920      *         can't or the app handles the specific configuration that is changing.
6921      */
ensureActivityConfiguration(int globalChanges, boolean preserveWindow, boolean ignoreVisibility)6922     boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
6923             boolean ignoreVisibility) {
6924         final ActivityStack stack = getRootTask();
6925         if (stack.mConfigWillChange) {
6926             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6927                     "Skipping config check (will change): " + this);
6928             return true;
6929         }
6930 
6931         // We don't worry about activities that are finishing.
6932         if (finishing) {
6933             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6934                     "Configuration doesn't matter in finishing " + this);
6935             stopFreezingScreenLocked(false);
6936             return true;
6937         }
6938 
6939         if (!ignoreVisibility && (mState == STOPPING || mState == STOPPED || !shouldBeVisible())) {
6940             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6941                     "Skipping config check invisible: " + this);
6942             return true;
6943         }
6944 
6945         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6946                 "Ensuring correct configuration: " + this);
6947 
6948         final int newDisplayId = getDisplayId();
6949         final boolean displayChanged = mLastReportedDisplayId != newDisplayId;
6950         if (displayChanged) {
6951             mLastReportedDisplayId = newDisplayId;
6952         }
6953         // TODO(b/36505427): Is there a better place to do this?
6954         updateSizeCompatMode();
6955 
6956         // Short circuit: if the two full configurations are equal (the common case), then there is
6957         // nothing to do.  We test the full configuration instead of the global and merged override
6958         // configurations because there are cases (like moving a task to the pinned stack) where
6959         // the combine configurations are equal, but would otherwise differ in the override config
6960         mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration());
6961         if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) {
6962             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6963                     "Configuration & display unchanged in " + this);
6964             return true;
6965         }
6966 
6967         // Okay we now are going to make this activity have the new config.
6968         // But then we need to figure out how it needs to deal with that.
6969 
6970         // Find changes between last reported merged configuration and the current one. This is used
6971         // to decide whether to relaunch an activity or just report a configuration change.
6972         final int changes = getConfigurationChanges(mTmpConfig);
6973 
6974         // Update last reported values.
6975         final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
6976 
6977         setLastReportedConfiguration(getProcessGlobalConfiguration(), newMergedOverrideConfig);
6978 
6979         if (mState == INITIALIZING) {
6980             // No need to relaunch or schedule new config for activity that hasn't been launched
6981             // yet. We do, however, return after applying the config to activity record, so that
6982             // it will use it for launch transaction.
6983             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6984                     "Skipping config check for initializing activity: " + this);
6985             return true;
6986         }
6987 
6988         if (changes == 0 && !forceNewConfig) {
6989             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
6990                     "Configuration no differences in " + this);
6991             // There are no significant differences, so we won't relaunch but should still deliver
6992             // the new configuration to the client process.
6993             if (displayChanged) {
6994                 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
6995             } else {
6996                 scheduleConfigurationChanged(newMergedOverrideConfig);
6997             }
6998             return true;
6999         }
7000 
7001         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
7002                 "Configuration changes for " + this + ", allChanges="
7003                         + Configuration.configurationDiffToString(changes));
7004 
7005         // If the activity isn't currently running, just leave the new configuration and it will
7006         // pick that up next time it starts.
7007         if (!attachedToProcess()) {
7008             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
7009                     "Configuration doesn't matter not running " + this);
7010             stopFreezingScreenLocked(false);
7011             forceNewConfig = false;
7012             return true;
7013         }
7014 
7015         // Figure out how to handle the changes between the configurations.
7016         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
7017                 "Checking to restart " + info.name + ": changed=0x"
7018                         + Integer.toHexString(changes) + ", handles=0x"
7019                         + Integer.toHexString(info.getRealConfigChanged())
7020                         + ", mLastReportedConfiguration=" + mLastReportedConfiguration);
7021 
7022         if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
7023             // Aha, the activity isn't handling the change, so DIE DIE DIE.
7024             configChangeFlags |= changes;
7025             startFreezingScreenLocked(globalChanges);
7026             forceNewConfig = false;
7027             preserveWindow &= isResizeOnlyChange(changes);
7028             final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
7029             if (hasResizeChange) {
7030                 final boolean isDragResizing = task.isDragResizing();
7031                 mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
7032                         : RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
7033             } else {
7034                 mRelaunchReason = RELAUNCH_REASON_NONE;
7035             }
7036             if (!attachedToProcess()) {
7037                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
7038                         "Config is destroying non-running " + this);
7039                 destroyImmediately(true /* removeFromApp */, "config");
7040             } else if (mState == PAUSING) {
7041                 // A little annoying: we are waiting for this activity to finish pausing. Let's not
7042                 // do anything now, but just flag that it needs to be restarted when done pausing.
7043                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
7044                         "Config is skipping already pausing " + this);
7045                 deferRelaunchUntilPaused = true;
7046                 preserveWindowOnDeferredRelaunch = preserveWindow;
7047                 return true;
7048             } else {
7049                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
7050                         "Config is relaunching " + this);
7051                 if (DEBUG_STATES && !mVisibleRequested) {
7052                     Slog.v(TAG_STATES, "Config is relaunching invisible activity " + this
7053                             + " called by " + Debug.getCallers(4));
7054                 }
7055                 relaunchActivityLocked(preserveWindow);
7056             }
7057 
7058             // All done...  tell the caller we weren't able to keep this activity around.
7059             return false;
7060         }
7061 
7062         // Default case: the activity can handle this new configuration, so hand it over.
7063         // NOTE: We only forward the override configuration as the system level configuration
7064         // changes is always sent to all processes when they happen so it can just use whatever
7065         // system level configuration it last got.
7066         if (displayChanged) {
7067             scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
7068         } else {
7069             scheduleConfigurationChanged(newMergedOverrideConfig);
7070         }
7071         stopFreezingScreenLocked(false);
7072 
7073         return true;
7074     }
7075 
7076     /** Get process configuration, or global config if the process is not set. */
getProcessGlobalConfiguration()7077     private Configuration getProcessGlobalConfiguration() {
7078         return app != null ? app.getConfiguration() : mAtmService.getGlobalConfiguration();
7079     }
7080 
7081     /**
7082      * When assessing a configuration change, decide if the changes flags and the new configurations
7083      * should cause the Activity to relaunch.
7084      *
7085      * @param changes the changes due to the given configuration.
7086      * @param changesConfig the configuration that was used to calculate the given changes via a
7087      *        call to getConfigurationChanges.
7088      */
shouldRelaunchLocked(int changes, Configuration changesConfig)7089     private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
7090         int configChanged = info.getRealConfigChanged();
7091         boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
7092 
7093         // Override for apps targeting pre-O sdks
7094         // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
7095         // to the config change.
7096         // For O and later, apps will be required to add configChanges="uimode" to their manifest.
7097         if (info.applicationInfo.targetSdkVersion < O
7098                 && requestedVrComponent != null
7099                 && onlyVrUiModeChanged) {
7100             configChanged |= CONFIG_UI_MODE;
7101         }
7102 
7103         return (changes&(~configChanged)) != 0;
7104     }
7105 
7106     /**
7107      * Returns true if the configuration change is solely due to the UI mode switching into or out
7108      * of UI_MODE_TYPE_VR_HEADSET.
7109      */
onlyVrUiModeChanged(int changes, Configuration lastReportedConfig)7110     private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
7111         final Configuration currentConfig = getConfiguration();
7112         return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
7113             != isInVrUiMode(lastReportedConfig));
7114     }
7115 
getConfigurationChanges(Configuration lastReportedConfig)7116     private int getConfigurationChanges(Configuration lastReportedConfig) {
7117         // Determine what has changed.  May be nothing, if this is a config that has come back from
7118         // the app after going idle.  In that case we just want to leave the official config object
7119         // now in the activity and do nothing else.
7120         final Configuration currentConfig = getConfiguration();
7121         int changes = lastReportedConfig.diff(currentConfig);
7122         // We don't want to use size changes if they don't cross boundaries that are important to
7123         // the app.
7124         if ((changes & CONFIG_SCREEN_SIZE) != 0) {
7125             final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp,
7126                     currentConfig.screenWidthDp)
7127                     || crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp,
7128                     currentConfig.screenHeightDp);
7129             if (!crosses) {
7130                 changes &= ~CONFIG_SCREEN_SIZE;
7131             }
7132         }
7133         if ((changes & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
7134             final int oldSmallest = lastReportedConfig.smallestScreenWidthDp;
7135             final int newSmallest = currentConfig.smallestScreenWidthDp;
7136             if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
7137                 changes &= ~CONFIG_SMALLEST_SCREEN_SIZE;
7138             }
7139         }
7140         // We don't want window configuration to cause relaunches.
7141         if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) {
7142             changes &= ~CONFIG_WINDOW_CONFIGURATION;
7143         }
7144 
7145         return changes;
7146     }
7147 
isResizeOnlyChange(int change)7148     private static boolean isResizeOnlyChange(int change) {
7149         return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
7150                 | CONFIG_SCREEN_LAYOUT)) == 0;
7151     }
7152 
hasResizeChange(int change)7153     private static boolean hasResizeChange(int change) {
7154         return (change & (CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
7155                 | CONFIG_SCREEN_LAYOUT)) != 0;
7156     }
7157 
relaunchActivityLocked(boolean preserveWindow)7158     void relaunchActivityLocked(boolean preserveWindow) {
7159         if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
7160             configChangeFlags = 0;
7161             return;
7162         }
7163 
7164         final boolean andResume = shouldBeResumed(null /*activeActivity*/);
7165         List<ResultInfo> pendingResults = null;
7166         List<ReferrerIntent> pendingNewIntents = null;
7167         if (andResume) {
7168             pendingResults = results;
7169             pendingNewIntents = newIntents;
7170         }
7171         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
7172                 "Relaunching: " + this + " with results=" + pendingResults
7173                         + " newIntents=" + pendingNewIntents + " andResume=" + andResume
7174                         + " preserveWindow=" + preserveWindow);
7175         if (andResume) {
7176             EventLogTags.writeWmRelaunchResumeActivity(mUserId, System.identityHashCode(this),
7177                     task.mTaskId, shortComponentName);
7178         } else {
7179             EventLogTags.writeWmRelaunchActivity(mUserId, System.identityHashCode(this),
7180                     task.mTaskId, shortComponentName);
7181         }
7182 
7183         startFreezingScreenLocked(0);
7184 
7185         try {
7186             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
7187                     "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
7188                             + " callers=" + Debug.getCallers(6));
7189             forceNewConfig = false;
7190             startRelaunching();
7191             final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
7192                     pendingNewIntents, configChangeFlags,
7193                     new MergedConfiguration(getProcessGlobalConfiguration(),
7194                             getMergedOverrideConfiguration()),
7195                     preserveWindow);
7196             final ActivityLifecycleItem lifecycleItem;
7197             if (andResume) {
7198                 lifecycleItem = ResumeActivityItem.obtain(
7199                         getDisplay().mDisplayContent.isNextTransitionForward());
7200             } else {
7201                 lifecycleItem = PauseActivityItem.obtain();
7202             }
7203             final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
7204             transaction.addCallback(callbackItem);
7205             transaction.setLifecycleStateRequest(lifecycleItem);
7206             mAtmService.getLifecycleManager().scheduleTransaction(transaction);
7207             // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
7208             // request resume if this activity is currently resumed, which implies we aren't
7209             // sleeping.
7210         } catch (RemoteException e) {
7211             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
7212         }
7213 
7214         if (andResume) {
7215             if (DEBUG_STATES) {
7216                 Slog.d(TAG_STATES, "Resumed after relaunch " + this);
7217             }
7218             results = null;
7219             newIntents = null;
7220             mAtmService.getAppWarningsLocked().onResumeActivity(this);
7221         } else {
7222             removePauseTimeout();
7223             setState(PAUSED, "relaunchActivityLocked");
7224         }
7225 
7226         configChangeFlags = 0;
7227         deferRelaunchUntilPaused = false;
7228         preserveWindowOnDeferredRelaunch = false;
7229     }
7230 
7231     /**
7232      * Request the process of the activity to restart with its saved state (from
7233      * {@link android.app.Activity#onSaveInstanceState}) if possible. It also forces to recompute
7234      * the override configuration. Note if the activity is in background, the process will be killed
7235      * directly with keeping its record.
7236      */
restartProcessIfVisible()7237     void restartProcessIfVisible() {
7238         Slog.i(TAG, "Request to restart process of " + this);
7239 
7240         // Reset the existing override configuration so it can be updated according to the latest
7241         // configuration.
7242         clearSizeCompatMode();
7243         if (mVisibleRequested) {
7244             // Configuration will be ensured when becoming visible, so if it is already visible,
7245             // then the manual update is needed.
7246             updateSizeCompatMode();
7247         }
7248 
7249         if (!attachedToProcess()) {
7250             return;
7251         }
7252 
7253         // The restarting state avoids removing this record when process is died.
7254         setState(RESTARTING_PROCESS, "restartActivityProcess");
7255 
7256         if (!mVisibleRequested || mHaveState) {
7257             // Kill its process immediately because the activity should be in background.
7258             // The activity state will be update to {@link #DESTROYED} in
7259             // {@link ActivityStack#cleanUp} when handling process died.
7260             mAtmService.mH.post(() -> {
7261                 final WindowProcessController wpc;
7262                 synchronized (mAtmService.mGlobalLock) {
7263                     if (!hasProcess()
7264                             || app.getReportedProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND) {
7265                         return;
7266                     }
7267                     wpc = app;
7268                 }
7269                 mAtmService.mAmInternal.killProcess(wpc.mName, wpc.mUid, "resetConfig");
7270             });
7271             return;
7272         }
7273 
7274         if (getParent() != null) {
7275             startFreezingScreen();
7276         }
7277         // The process will be killed until the activity reports stopped with saved state (see
7278         // {@link ActivityTaskManagerService.activityStopped}).
7279         try {
7280             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
7281                     StopActivityItem.obtain(0 /* configChanges */));
7282         } catch (RemoteException e) {
7283             Slog.w(TAG, "Exception thrown during restart " + this, e);
7284         }
7285         mStackSupervisor.scheduleRestartTimeout(this);
7286     }
7287 
isProcessRunning()7288     boolean isProcessRunning() {
7289         WindowProcessController proc = app;
7290         if (proc == null) {
7291             proc = mAtmService.mProcessNames.get(processName, info.applicationInfo.uid);
7292         }
7293         return proc != null && proc.hasThread();
7294     }
7295 
7296     /**
7297      * @return Whether a task snapshot starting window may be shown.
7298      */
allowTaskSnapshot()7299     private boolean allowTaskSnapshot() {
7300         if (newIntents == null) {
7301             return true;
7302         }
7303 
7304         // Restrict task snapshot starting window to launcher start, or is same as the last
7305         // delivered intent, or there is no intent at all (eg. task being brought to front). If
7306         // the intent is something else, likely the app is going to show some specific page or
7307         // view, instead of what's left last time.
7308         for (int i = newIntents.size() - 1; i >= 0; i--) {
7309             final Intent intent = newIntents.get(i);
7310             if (intent == null || ActivityRecord.isMainIntent(intent)) {
7311                 continue;
7312             }
7313 
7314             final boolean sameIntent = mLastNewIntent != null ? mLastNewIntent.filterEquals(intent)
7315                     : this.intent.filterEquals(intent);
7316             if (!sameIntent || intent.getExtras() != null) {
7317                 return false;
7318             }
7319         }
7320         return true;
7321     }
7322 
7323     /**
7324      * Returns {@code true} if the associated activity has the no history flag set on it.
7325      * {@code false} otherwise.
7326      */
isNoHistory()7327     boolean isNoHistory() {
7328         return (intent.getFlags() & FLAG_ACTIVITY_NO_HISTORY) != 0
7329                 || (info.flags & FLAG_NO_HISTORY) != 0;
7330     }
7331 
saveToXml(XmlSerializer out)7332     void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
7333         out.attribute(null, ATTR_ID, String.valueOf(createTime));
7334         out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
7335         if (launchedFromPackage != null) {
7336             out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
7337         }
7338         if (launchedFromFeatureId != null) {
7339             out.attribute(null, ATTR_LAUNCHEDFROMFEATURE, launchedFromFeatureId);
7340         }
7341         if (resolvedType != null) {
7342             out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
7343         }
7344         out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
7345         out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
7346 
7347         if (taskDescription != null) {
7348             taskDescription.saveToXml(out);
7349         }
7350 
7351         out.startTag(null, TAG_INTENT);
7352         intent.saveToXml(out);
7353         out.endTag(null, TAG_INTENT);
7354 
7355         if (isPersistable() && mPersistentState != null) {
7356             out.startTag(null, TAG_PERSISTABLEBUNDLE);
7357             mPersistentState.saveToXml(out);
7358             out.endTag(null, TAG_PERSISTABLEBUNDLE);
7359         }
7360     }
7361 
restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)7362     static ActivityRecord restoreFromXml(XmlPullParser in,
7363             ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
7364         Intent intent = null;
7365         PersistableBundle persistentState = null;
7366         int launchedFromUid = 0;
7367         String launchedFromPackage = null;
7368         String launchedFromFeature = null;
7369         String resolvedType = null;
7370         boolean componentSpecified = false;
7371         int userId = 0;
7372         long createTime = -1;
7373         final int outerDepth = in.getDepth();
7374         TaskDescription taskDescription = new TaskDescription();
7375 
7376         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
7377             final String attrName = in.getAttributeName(attrNdx);
7378             final String attrValue = in.getAttributeValue(attrNdx);
7379             if (DEBUG) Slog.d(TaskPersister.TAG,
7380                         "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
7381             if (ATTR_ID.equals(attrName)) {
7382                 createTime = Long.parseLong(attrValue);
7383             } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
7384                 launchedFromUid = Integer.parseInt(attrValue);
7385             } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
7386                 launchedFromPackage = attrValue;
7387             } else if (ATTR_LAUNCHEDFROMFEATURE.equals(attrName)) {
7388                 launchedFromFeature = attrValue;
7389             } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
7390                 resolvedType = attrValue;
7391             } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
7392                 componentSpecified = Boolean.parseBoolean(attrValue);
7393             } else if (ATTR_USERID.equals(attrName)) {
7394                 userId = Integer.parseInt(attrValue);
7395             } else if (!attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) {
7396                 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
7397             }
7398         }
7399         taskDescription.restoreFromXml(in);
7400 
7401         int event;
7402         while (((event = in.next()) != END_DOCUMENT) &&
7403                 (event != END_TAG || in.getDepth() >= outerDepth)) {
7404             if (event == START_TAG) {
7405                 final String name = in.getName();
7406                 if (DEBUG)
7407                         Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
7408                 if (TAG_INTENT.equals(name)) {
7409                     intent = Intent.restoreFromXml(in);
7410                     if (DEBUG)
7411                             Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
7412                 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
7413                     persistentState = PersistableBundle.restoreFromXml(in);
7414                     if (DEBUG) Slog.d(TaskPersister.TAG,
7415                             "ActivityRecord: persistentState=" + persistentState);
7416                 } else {
7417                     Slog.w(TAG, "restoreActivity: unexpected name=" + name);
7418                     XmlUtils.skipCurrentTag(in);
7419                 }
7420             }
7421         }
7422 
7423         if (intent == null) {
7424             throw new XmlPullParserException("restoreActivity error intent=" + intent);
7425         }
7426 
7427         final ActivityTaskManagerService service = stackSupervisor.mService;
7428         final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
7429                 userId, Binder.getCallingUid());
7430         if (aInfo == null) {
7431             throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
7432                     " resolvedType=" + resolvedType);
7433         }
7434         final ActivityRecord r = new ActivityRecord(service, null /* caller */,
7435                 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, launchedFromFeature,
7436                 intent, resolvedType, aInfo, service.getConfiguration(), null /* resultTo */,
7437                 null /* resultWho */, 0 /* reqCode */, componentSpecified,
7438                 false /* rootVoiceInteraction */, stackSupervisor, null /* options */,
7439                 null /* sourceRecord */);
7440 
7441         r.mPersistentState = persistentState;
7442         r.taskDescription = taskDescription;
7443         r.createTime = createTime;
7444 
7445         return r;
7446     }
7447 
isInVrUiMode(Configuration config)7448     private static boolean isInVrUiMode(Configuration config) {
7449         return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
7450     }
7451 
getUid()7452     int getUid() {
7453         return info.applicationInfo.uid;
7454     }
7455 
isUid(int uid)7456     boolean isUid(int uid) {
7457         return info.applicationInfo.uid == uid;
7458     }
7459 
getPid()7460     int getPid() {
7461         return app != null ? app.getPid() : 0;
7462     }
7463 
7464     /**
7465      * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
7466      * {@link ActivityRecord#getTurnScreenOnFlag} is set and checks whether the ActivityRecord
7467      * should be visible depending on Keyguard state
7468      *
7469      * @return true if the screen can be turned on, false otherwise.
7470      */
canTurnScreenOn()7471     boolean canTurnScreenOn() {
7472         if (!getTurnScreenOnFlag()) {
7473             return false;
7474         }
7475         final ActivityStack stack = getRootTask();
7476         return stack != null &&
7477                 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */,
7478                         stack.topRunningActivity() == this /* isTop */);
7479     }
7480 
setTurnScreenOn(boolean turnScreenOn)7481     void setTurnScreenOn(boolean turnScreenOn) {
7482         mTurnScreenOn = turnScreenOn;
7483     }
7484 
getTurnScreenOnFlag()7485     boolean getTurnScreenOnFlag() {
7486         return mTurnScreenOn || containsTurnScreenOnWindow();
7487     }
7488 
containsTurnScreenOnWindow()7489     private boolean containsTurnScreenOnWindow() {
7490         // When we are relaunching, it is possible for us to be unfrozen before our previous
7491         // windows have been added back. Using the cached value ensures that our previous
7492         // showWhenLocked preference is honored until relaunching is complete.
7493         if (isRelaunching()) {
7494             return mLastContainsTurnScreenOnWindow;
7495         }
7496         for (int i = mChildren.size() - 1; i >= 0; i--) {
7497             if ((mChildren.get(i).mAttrs.flags & LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
7498                 return true;
7499             }
7500         }
7501         return false;
7502     }
7503 
7504     /**
7505      * Check if this activity is able to resume. For pre-Q apps, only the topmost activities of each
7506      * process are allowed to be resumed.
7507      *
7508      * @return true if this activity can be resumed.
7509      */
canResumeByCompat()7510     boolean canResumeByCompat() {
7511         return app == null || app.updateTopResumingActivityInProcessIfNeeded(this);
7512     }
7513 
isTopRunningActivity()7514     boolean isTopRunningActivity() {
7515         return mRootWindowContainer.topRunningActivity() == this;
7516     }
7517 
7518     /**
7519      * @return {@code true} if this is the resumed activity on its current display, {@code false}
7520      * otherwise.
7521      */
isResumedActivityOnDisplay()7522     boolean isResumedActivityOnDisplay() {
7523         final DisplayContent display = getDisplay();
7524         if (display == null) {
7525             return false;
7526         }
7527         for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
7528             final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
7529             final ActivityRecord resumedActivity = taskDisplayArea.getFocusedActivity();
7530             if (resumedActivity != null) {
7531                 return resumedActivity == this;
7532             }
7533         }
7534         return false;
7535     }
7536 
7537 
7538     /**
7539      * Check if this is the root of the task - first activity that is not finishing, starting from
7540      * the bottom of the task. If all activities are finishing - then this method will return
7541      * {@code true} if the activity is at the bottom.
7542      *
7543      * NOTE: This is different from 'effective root' - an activity that defines the task identity.
7544      */
isRootOfTask()7545     boolean isRootOfTask() {
7546         if (task == null) {
7547             return false;
7548         }
7549         final ActivityRecord rootActivity = task.getRootActivity(true);
7550         return this == rootActivity;
7551     }
7552 
setTaskOverlay(boolean taskOverlay)7553     void setTaskOverlay(boolean taskOverlay) {
7554         mTaskOverlay = taskOverlay;
7555         setAlwaysOnTop(mTaskOverlay);
7556     }
7557 
isTaskOverlay()7558     boolean isTaskOverlay() {
7559         return mTaskOverlay;
7560     }
7561 
7562     @Override
showToCurrentUser()7563     boolean showToCurrentUser() {
7564         return mShowForAllUsers || mWmService.isCurrentProfile(mUserId);
7565     }
7566 
7567     @Override
toString()7568     public String toString() {
7569         if (stringName != null) {
7570             return stringName + " t" + (task == null ? INVALID_TASK_ID : task.mTaskId) +
7571                     (finishing ? " f}" : "") + (mIsExiting ? " isExiting" : "") + "}";
7572         }
7573         StringBuilder sb = new StringBuilder(128);
7574         sb.append("ActivityRecord{");
7575         sb.append(Integer.toHexString(System.identityHashCode(this)));
7576         sb.append(" u");
7577         sb.append(mUserId);
7578         sb.append(' ');
7579         sb.append(intent.getComponent().flattenToShortString());
7580         stringName = sb.toString();
7581         return stringName;
7582     }
7583 
7584     /**
7585      * Write all fields to an {@code ActivityRecordProto}. This assumes the
7586      * {@code ActivityRecordProto} is the outer-most proto data.
7587      */
dumpDebug(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel)7588     void dumpDebug(ProtoOutputStream proto, @WindowTraceLogLevel int logLevel) {
7589         writeNameToProto(proto, NAME);
7590         super.dumpDebug(proto, WINDOW_TOKEN, logLevel);
7591         proto.write(LAST_SURFACE_SHOWING, mLastSurfaceShowing);
7592         proto.write(IS_WAITING_FOR_TRANSITION_START, isWaitingForTransitionStart());
7593         proto.write(IS_ANIMATING, isAnimating(PARENTS));
7594         if (mThumbnail != null){
7595             mThumbnail.dumpDebug(proto, THUMBNAIL);
7596         }
7597         proto.write(FILLS_PARENT, fillsParent());
7598         proto.write(APP_STOPPED, mAppStopped);
7599         proto.write(TRANSLUCENT, !occludesParent());
7600         proto.write(VISIBLE, mVisible);
7601         proto.write(VISIBLE_REQUESTED, mVisibleRequested);
7602         proto.write(CLIENT_VISIBLE, mClientVisible);
7603         proto.write(DEFER_HIDING_CLIENT, mDeferHidingClient);
7604         proto.write(REPORTED_DRAWN, reportedDrawn);
7605         proto.write(REPORTED_VISIBLE, reportedVisible);
7606         proto.write(NUM_INTERESTING_WINDOWS, mNumInterestingWindows);
7607         proto.write(NUM_DRAWN_WINDOWS, mNumDrawnWindows);
7608         proto.write(ALL_DRAWN, allDrawn);
7609         proto.write(LAST_ALL_DRAWN, mLastAllDrawn);
7610         if (startingWindow != null) {
7611             startingWindow.writeIdentifierToProto(proto, STARTING_WINDOW);
7612         }
7613         proto.write(STARTING_DISPLAYED, startingDisplayed);
7614         proto.write(STARTING_MOVED, startingMoved);
7615         proto.write(VISIBLE_SET_FROM_TRANSFERRED_STARTING_WINDOW,
7616                 mVisibleSetFromTransferredStartingWindow);
7617         for (Rect bounds : mFrozenBounds) {
7618             bounds.dumpDebug(proto, FROZEN_BOUNDS);
7619         }
7620 
7621         writeIdentifierToProto(proto, IDENTIFIER);
7622         proto.write(STATE, mState.toString());
7623         proto.write(FRONT_OF_TASK, isRootOfTask());
7624         if (hasProcess()) {
7625             proto.write(PROC_ID, app.getPid());
7626         }
7627     }
7628 
7629     @Override
getProtoFieldId()7630     long getProtoFieldId() {
7631         return ACTIVITY;
7632     }
7633 
7634     @Override
dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)7635     public void dumpDebug(ProtoOutputStream proto, long fieldId,
7636             @WindowTraceLogLevel int logLevel) {
7637         // Critical log level logs only visible elements to mitigate performance overheard
7638         if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
7639             return;
7640         }
7641 
7642         final long token = proto.start(fieldId);
7643         dumpDebug(proto, logLevel);
7644         proto.end(token);
7645     }
7646 
writeNameToProto(ProtoOutputStream proto, long fieldId)7647     void writeNameToProto(ProtoOutputStream proto, long fieldId) {
7648         if (appToken != null) {
7649             proto.write(fieldId, appToken.getName());
7650         }
7651     }
7652 
7653     @Override
writeIdentifierToProto(ProtoOutputStream proto, long fieldId)7654     void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
7655         final long token = proto.start(fieldId);
7656         proto.write(HASH_CODE, System.identityHashCode(this));
7657         proto.write(USER_ID, mUserId);
7658         proto.write(TITLE, intent.getComponent().flattenToShortString());
7659         proto.end(token);
7660     }
7661 
7662     /**
7663      * The precomputed insets of the display in each rotation. This is used to make the size
7664      * compatibility mode activity compute the configuration without relying on its current display.
7665      * This currently only supports fullscreen and freeform windowing mode.
7666      */
7667     static class CompatDisplayInsets {
7668         private final int mWidth;
7669         private final int mHeight;
7670         final boolean mIsFloating;
7671 
7672         /**
7673          * The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
7674          * is used to compute the appBounds.
7675          */
7676         final Rect[] mNonDecorInsets = new Rect[4];
7677         /**
7678          * The stableInsets for each rotation. Includes the status bar inset and the
7679          * nonDecorInsets. It is used to compute {@link Configuration#screenWidthDp} and
7680          * {@link Configuration#screenHeightDp}.
7681          */
7682         final Rect[] mStableInsets = new Rect[4];
7683 
7684         /** Constructs the environment to simulate the bounds behavior of the given container. */
CompatDisplayInsets(DisplayContent display, WindowContainer container)7685         CompatDisplayInsets(DisplayContent display, WindowContainer container) {
7686             mIsFloating = container.getWindowConfiguration().tasksAreFloating();
7687             if (mIsFloating) {
7688                 final Rect containerBounds = container.getWindowConfiguration().getBounds();
7689                 mWidth = containerBounds.width();
7690                 mHeight = containerBounds.height();
7691                 // For apps in freeform, the task bounds are the parent bounds from the app's
7692                 // perspective. No insets because within a window.
7693                 final Rect emptyRect = new Rect();
7694                 for (int rotation = 0; rotation < 4; rotation++) {
7695                     mNonDecorInsets[rotation] = emptyRect;
7696                     mStableInsets[rotation] = emptyRect;
7697                 }
7698                 return;
7699             }
7700 
7701             // If the activity is not floating, assume it fills the display.
7702             mWidth = display.mBaseDisplayWidth;
7703             mHeight = display.mBaseDisplayHeight;
7704             final DisplayPolicy policy = display.getDisplayPolicy();
7705             for (int rotation = 0; rotation < 4; rotation++) {
7706                 mNonDecorInsets[rotation] = new Rect();
7707                 mStableInsets[rotation] = new Rect();
7708                 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
7709                 final int dw = rotated ? mHeight : mWidth;
7710                 final int dh = rotated ? mWidth : mHeight;
7711                 final DisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation)
7712                         .getDisplayCutout();
7713                 policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
7714                 mStableInsets[rotation].set(mNonDecorInsets[rotation]);
7715                 policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
7716             }
7717         }
7718 
getBoundsByRotation(Rect outBounds, int rotation)7719         void getBoundsByRotation(Rect outBounds, int rotation) {
7720             final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
7721             final int dw = rotated ? mHeight : mWidth;
7722             final int dh = rotated ? mWidth : mHeight;
7723             outBounds.set(0, 0, dw, dh);
7724         }
7725 
getFrameByOrientation(Rect outBounds, int orientation)7726         void getFrameByOrientation(Rect outBounds, int orientation) {
7727             final int longSide = Math.max(mWidth, mHeight);
7728             final int shortSide = Math.min(mWidth, mHeight);
7729             final boolean isLandscape = orientation == ORIENTATION_LANDSCAPE;
7730             outBounds.set(0, 0, isLandscape ? longSide : shortSide,
7731                     isLandscape ? shortSide : longSide);
7732         }
7733 
7734         /** Gets the horizontal centered container bounds for size compatibility mode. */
getContainerBounds(Rect outAppBounds, Rect outBounds, int rotation, int orientation, boolean orientationRequested, boolean canChangeOrientation)7735         void getContainerBounds(Rect outAppBounds, Rect outBounds, int rotation, int orientation,
7736                 boolean orientationRequested, boolean canChangeOrientation) {
7737             if (mIsFloating) {
7738                 getFrameByOrientation(outBounds, orientation);
7739                 outAppBounds.set(outBounds);
7740                 return;
7741             }
7742 
7743             if (canChangeOrientation) {
7744                 getBoundsByRotation(outBounds, rotation);
7745                 if (orientationRequested) {
7746                     getFrameByOrientation(outAppBounds, orientation);
7747                 } else {
7748                     outAppBounds.set(outBounds);
7749                 }
7750             } else {
7751                 if (orientationRequested) {
7752                     getFrameByOrientation(outBounds, orientation);
7753                     if ((outBounds.width() > outBounds.height()) != (mWidth > mHeight)) {
7754                         // The orientation is mismatched but the display cannot rotate. The bounds
7755                         // will fit to the short side of display.
7756                         if (orientation == ORIENTATION_LANDSCAPE) {
7757                             outBounds.bottom = (int) ((float) mWidth * mWidth / mHeight);
7758                             outBounds.right = mWidth;
7759                         } else {
7760                             outBounds.bottom = mHeight;
7761                             outBounds.right = (int) ((float) mHeight * mHeight / mWidth);
7762                         }
7763                         outBounds.offset(
7764                                 getHorizontalCenterOffset(mWidth, outBounds.width()), 0 /* dy */);
7765                     }
7766                 } else {
7767                     outBounds.set(0, 0, mWidth, mHeight);
7768                 }
7769                 outAppBounds.set(outBounds);
7770             }
7771 
7772             if (rotation != ROTATION_UNDEFINED) {
7773                 // Ensure the app bounds won't overlap with insets.
7774                 Task.intersectWithInsetsIfFits(outAppBounds, outBounds, mNonDecorInsets[rotation]);
7775             }
7776         }
7777     }
7778 
7779     private static class AppSaturationInfo {
7780         float[] mMatrix = new float[9];
7781         float[] mTranslation = new float[3];
7782 
setSaturation(@ize9) float[] matrix, @Size(3) float[] translation)7783         void setSaturation(@Size(9) float[] matrix, @Size(3) float[] translation) {
7784             System.arraycopy(matrix, 0, mMatrix, 0, mMatrix.length);
7785             System.arraycopy(translation, 0, mTranslation, 0, mTranslation.length);
7786         }
7787     }
7788 
7789     @Override
createRemoteAnimationTarget( RemoteAnimationController.RemoteAnimationRecord record)7790     RemoteAnimationTarget createRemoteAnimationTarget(
7791             RemoteAnimationController.RemoteAnimationRecord record) {
7792         final WindowState mainWindow = findMainWindow();
7793         if (task == null || mainWindow == null) {
7794             return null;
7795         }
7796         final Rect insets = new Rect();
7797         mainWindow.getContentInsets(insets);
7798         InsetUtils.addInsets(insets, getLetterboxInsets());
7799         return new RemoteAnimationTarget(task.mTaskId, record.getMode(),
7800                 record.mAdapter.mCapturedLeash, !fillsParent(),
7801                 mainWindow.mWinAnimator.mLastClipRect, insets,
7802                 getPrefixOrderIndex(), record.mAdapter.mPosition, record.mAdapter.mLocalBounds,
7803                 record.mAdapter.mStackBounds, task.getWindowConfiguration(),
7804                 false /*isNotInRecents*/,
7805                 record.mThumbnailAdapter != null ? record.mThumbnailAdapter.mCapturedLeash : null,
7806                 record.mStartBounds);
7807     }
7808 
7809     @Override
canCreateRemoteAnimationTarget()7810     boolean canCreateRemoteAnimationTarget() {
7811         return true;
7812     }
7813 
7814     @Override
getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, Rect outSurfaceInsets)7815     void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
7816             Rect outSurfaceInsets) {
7817         final WindowState win = findMainWindow();
7818         if (win == null) {
7819             return;
7820         }
7821         win.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets);
7822     }
7823 
setPictureInPictureParams(PictureInPictureParams p)7824     void setPictureInPictureParams(PictureInPictureParams p) {
7825         pictureInPictureArgs.copyOnlySet(p);
7826         getTask().getRootTask().onPictureInPictureParamsChanged();
7827     }
7828 }
7829