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.ActivityTaskManager.INVALID_STACK_ID;
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_HOME;
40 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
41 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
42 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
43 import static android.app.WindowConfiguration.activityTypeToString;
44 import static android.content.Intent.ACTION_MAIN;
45 import static android.content.Intent.CATEGORY_HOME;
46 import static android.content.Intent.CATEGORY_LAUNCHER;
47 import static android.content.Intent.CATEGORY_SECONDARY_HOME;
48 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
49 import static android.content.Intent.FLAG_ACTIVITY_NO_HISTORY;
50 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
51 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
52 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
53 import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
54 import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
55 import static android.content.pm.ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
56 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
57 import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
58 import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
59 import static android.content.pm.ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
60 import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS;
61 import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY;
62 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
63 import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
64 import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
65 import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
66 import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
67 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
68 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
69 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
70 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
71 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
72 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
73 import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
74 import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
75 import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
76 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
77 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
78 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
79 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
80 import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
81 import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
82 import static android.content.res.Configuration.EMPTY;
83 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
84 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
85 import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
86 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
87 import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
88 import static android.os.Build.VERSION_CODES.HONEYCOMB;
89 import static android.os.Build.VERSION_CODES.O;
90 import static android.os.Process.SYSTEM_UID;
91 import static android.view.Display.DEFAULT_DISPLAY;
92 import static android.view.Display.INVALID_DISPLAY;
93 import static android.view.Surface.ROTATION_270;
94 import static android.view.Surface.ROTATION_90;
95 
96 import static com.android.server.am.ActivityRecordProto.CONFIGURATION_CONTAINER;
97 import static com.android.server.am.ActivityRecordProto.FRONT_OF_TASK;
98 import static com.android.server.am.ActivityRecordProto.IDENTIFIER;
99 import static com.android.server.am.ActivityRecordProto.PROC_ID;
100 import static com.android.server.am.ActivityRecordProto.STATE;
101 import static com.android.server.am.ActivityRecordProto.TRANSLUCENT;
102 import static com.android.server.am.ActivityRecordProto.VISIBLE;
103 import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
104 import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
105 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED;
106 import static com.android.server.wm.ActivityStack.ActivityState.INITIALIZING;
107 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED;
108 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING;
109 import static com.android.server.wm.ActivityStack.ActivityState.RESTARTING_PROCESS;
110 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
111 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
112 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
113 import static com.android.server.wm.ActivityStack.LAUNCH_TICK;
114 import static com.android.server.wm.ActivityStack.LAUNCH_TICK_MSG;
115 import static com.android.server.wm.ActivityStack.PAUSE_TIMEOUT_MSG;
116 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
117 import static com.android.server.wm.ActivityStack.STOP_TIMEOUT_MSG;
118 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONFIGURATION;
119 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_FOCUS;
120 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE;
121 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
122 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
123 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION;
124 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY;
125 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
126 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_FOCUS;
127 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE;
128 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES;
129 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH;
130 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY;
131 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
132 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
133 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE;
134 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
135 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
136 import static com.android.server.wm.IdentifierProto.HASH_CODE;
137 import static com.android.server.wm.IdentifierProto.TITLE;
138 import static com.android.server.wm.IdentifierProto.USER_ID;
139 import static com.android.server.wm.TaskPersister.DEBUG;
140 import static com.android.server.wm.TaskPersister.IMAGE_EXTENSION;
141 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
142 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
143 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
144 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TOKEN_MOVEMENT;
145 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
146 
147 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
148 import static org.xmlpull.v1.XmlPullParser.END_TAG;
149 import static org.xmlpull.v1.XmlPullParser.START_TAG;
150 
151 import android.annotation.NonNull;
152 import android.annotation.Nullable;
153 import android.app.ActivityManager.TaskDescription;
154 import android.app.ActivityOptions;
155 import android.app.PendingIntent;
156 import android.app.PictureInPictureParams;
157 import android.app.ResultInfo;
158 import android.app.WaitResult.LaunchState;
159 import android.app.servertransaction.ActivityConfigurationChangeItem;
160 import android.app.servertransaction.ActivityLifecycleItem;
161 import android.app.servertransaction.ActivityRelaunchItem;
162 import android.app.servertransaction.ClientTransaction;
163 import android.app.servertransaction.ClientTransactionItem;
164 import android.app.servertransaction.MoveToDisplayItem;
165 import android.app.servertransaction.MultiWindowModeChangeItem;
166 import android.app.servertransaction.NewIntentItem;
167 import android.app.servertransaction.PauseActivityItem;
168 import android.app.servertransaction.PipModeChangeItem;
169 import android.app.servertransaction.ResumeActivityItem;
170 import android.app.servertransaction.StopActivityItem;
171 import android.app.servertransaction.TopResumedActivityChangeItem;
172 import android.app.servertransaction.WindowVisibilityItem;
173 import android.app.usage.UsageEvents.Event;
174 import android.content.ComponentName;
175 import android.content.Intent;
176 import android.content.pm.ActivityInfo;
177 import android.content.pm.ApplicationInfo;
178 import android.content.res.CompatibilityInfo;
179 import android.content.res.Configuration;
180 import android.graphics.Bitmap;
181 import android.graphics.GraphicBuffer;
182 import android.graphics.Rect;
183 import android.os.Binder;
184 import android.os.Build;
185 import android.os.Bundle;
186 import android.os.Debug;
187 import android.os.IBinder;
188 import android.os.Message;
189 import android.os.PersistableBundle;
190 import android.os.Process;
191 import android.os.RemoteException;
192 import android.os.SystemClock;
193 import android.os.UserHandle;
194 import android.os.storage.StorageManager;
195 import android.service.voice.IVoiceInteractionSession;
196 import android.util.EventLog;
197 import android.util.Log;
198 import android.util.MergedConfiguration;
199 import android.util.Slog;
200 import android.util.TimeUtils;
201 import android.util.proto.ProtoOutputStream;
202 import android.view.AppTransitionAnimationSpec;
203 import android.view.DisplayCutout;
204 import android.view.IAppTransitionAnimationSpecsFuture;
205 import android.view.IApplicationToken;
206 import android.view.RemoteAnimationDefinition;
207 import android.view.WindowManager.LayoutParams;
208 
209 import com.android.internal.R;
210 import com.android.internal.annotations.VisibleForTesting;
211 import com.android.internal.app.ResolverActivity;
212 import com.android.internal.content.ReferrerIntent;
213 import com.android.internal.util.XmlUtils;
214 import com.android.server.AttributeCache;
215 import com.android.server.AttributeCache.Entry;
216 import com.android.server.am.AppTimeTracker;
217 import com.android.server.am.PendingIntentRecord;
218 import com.android.server.uri.UriPermissionOwner;
219 import com.android.server.wm.ActivityMetricsLogger.WindowingModeTransitionInfoSnapshot;
220 import com.android.server.wm.ActivityStack.ActivityState;
221 
222 import org.xmlpull.v1.XmlPullParser;
223 import org.xmlpull.v1.XmlPullParserException;
224 import org.xmlpull.v1.XmlSerializer;
225 
226 import java.io.File;
227 import java.io.IOException;
228 import java.io.PrintWriter;
229 import java.lang.ref.WeakReference;
230 import java.util.ArrayList;
231 import java.util.Arrays;
232 import java.util.HashSet;
233 import java.util.List;
234 import java.util.Objects;
235 
236 /**
237  * An entry in the history stack, representing an activity.
238  */
239 final class ActivityRecord extends ConfigurationContainer {
240     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_ATM;
241     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
242     private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
243     private static final String TAG_STATES = TAG + POSTFIX_STATES;
244     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
245     private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
246     private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
247     // TODO(b/67864419): Remove once recents component is overridden
248     private static final String LEGACY_RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
249 
250     private static final boolean SHOW_ACTIVITY_START_TIME = true;
251 
252     private static final String ATTR_ID = "id";
253     private static final String TAG_INTENT = "intent";
254     private static final String ATTR_USERID = "user_id";
255     private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
256     private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
257     private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
258     private static final String ATTR_RESOLVEDTYPE = "resolved_type";
259     private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
260     static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
261 
262     final ActivityTaskManagerService mAtmService; // owner
263     final IApplicationToken.Stub appToken; // window manager token
264     // TODO: Remove after unification
265     AppWindowToken mAppWindowToken;
266 
267     final ActivityInfo info; // all about me
268     // TODO: This is duplicated state already contained in info.applicationInfo - remove
269     ApplicationInfo appInfo; // information about activity's app
270     final int launchedFromPid; // always the pid who started the activity.
271     final int launchedFromUid; // always the uid who started the activity.
272     final String launchedFromPackage; // always the package who started the activity.
273     final int mUserId;          // Which user is this running for?
274     final Intent intent;    // the original intent that generated us
275     final ComponentName mActivityComponent;  // the intent component, or target of an alias.
276     final String shortComponentName; // the short component name of the intent
277     final String resolvedType; // as per original caller;
278     final String packageName; // the package implementing intent's component
279     final String processName; // process where this component wants to run
280     final String taskAffinity; // as per ActivityInfo.taskAffinity
281     final boolean stateNotNeeded; // As per ActivityInfo.flags
282     boolean fullscreen; // The activity is opaque and fills the entire space of this task.
283     // TODO: See if it possible to combine this with the fullscreen field.
284     final boolean hasWallpaper; // Has a wallpaper window as a background.
285     @VisibleForTesting
286     boolean noDisplay;  // activity is not displayed?
287     @VisibleForTesting
288     int mHandoverLaunchDisplayId = INVALID_DISPLAY; // Handover launch display id to next activity.
289     private final boolean componentSpecified;  // did caller specify an explicit component?
290     final boolean rootVoiceInteraction;  // was this the root activity of a voice interaction?
291 
292     private CharSequence nonLocalizedLabel;  // the label information from the package mgr.
293     private int labelRes;           // the label information from the package mgr.
294     private int icon;               // resource identifier of activity's icon.
295     private int logo;               // resource identifier of activity's logo.
296     private int theme;              // resource identifier of activity's theme.
297     private int realTheme;          // actual theme resource we will use, never 0.
298     private int windowFlags;        // custom window flags for preview window.
299     private TaskRecord task;        // the task this is in.
300     private long createTime = System.currentTimeMillis();
301     long lastVisibleTime;         // last time this activity became visible
302     long cpuTimeAtResume;         // the cpu time of host process at the time of resuming activity
303     long pauseTime;               // last time we started pausing the activity
304     long launchTickTime;          // base time for launch tick messages
305     long topResumedStateLossTime; // last time we reported top resumed state loss to an activity
306     // Last configuration reported to the activity in the client process.
307     private MergedConfiguration mLastReportedConfiguration;
308     private int mLastReportedDisplayId;
309     private boolean mLastReportedMultiWindowMode;
310     private boolean mLastReportedPictureInPictureMode;
311     CompatibilityInfo compat;// last used compatibility mode
312     ActivityRecord resultTo; // who started this entry, so will get our reply
313     final String resultWho; // additional identifier for use by resultTo.
314     final int requestCode;  // code given by requester (resultTo)
315     ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
316     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
317     ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
318     ActivityOptions pendingOptions; // most recently given options
319     ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
320     AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
321     ActivityServiceConnectionsHolder mServiceConnectionsHolder; // Service connections.
322     UriPermissionOwner uriPermissions; // current special URI access perms.
323     WindowProcessController app;      // if non-null, hosting application
324     private ActivityState mState;    // current state we are in
325     Bundle  icicle;         // last saved activity state
326     PersistableBundle persistentState; // last persistently saved activity state
327     // TODO: See if this is still needed.
328     boolean frontOfTask;    // is this the root activity of its task?
329     boolean launchFailed;   // set if a launched failed, to abort on 2nd try
330     boolean haveState;      // have we gotten the last activity state?
331     boolean stopped;        // is activity pause finished?
332     boolean delayedResume;  // not yet resumed because of stopped app switches?
333     boolean finishing;      // activity in pending finish list?
334     boolean deferRelaunchUntilPaused;   // relaunch of activity is being deferred until pause is
335                                         // completed
336     boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
337     int configChangeFlags;  // which config values have changed
338     private boolean keysPaused;     // has key dispatching been paused for it?
339     int launchMode;         // the launch mode activity attribute.
340     int lockTaskLaunchMode; // the lockTaskMode manifest attribute, subject to override
341     boolean visible;        // does this activity's window need to be shown?
342     boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
343                                      // might hide this activity?
344     private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
345                                         // process that it is hidden.
346     boolean sleeping;       // have we told the activity to sleep?
347     boolean nowVisible;     // is this activity's window visible?
348     boolean mDrawn;          // is this activity's window drawn?
349     boolean mClientVisibilityDeferred;// was the visibility change message to client deferred?
350     boolean idle;           // has the activity gone idle?
351     boolean hasBeenLaunched;// has this activity ever been launched?
352     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
353     boolean immersive;      // immersive mode (don't interrupt if possible)
354     boolean forceNewConfig; // force re-create with new config next time
355     boolean supportsEnterPipOnTaskSwitch;  // This flag is set by the system to indicate that the
356         // activity can enter picture in picture while pausing (only when switching to another task)
357     PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build();
358         // The PiP params used when deferring the entering of picture-in-picture.
359     int launchCount;        // count of launches since last state
360     long lastLaunchTime;    // time of last launch of this activity
361     ComponentName requestedVrComponent; // the requested component for handling VR mode.
362 
363     String stringName;      // for caching of toString().
364 
365     private boolean inHistory;  // are we in the history stack?
366     final ActivityStackSupervisor mStackSupervisor;
367     final RootActivityContainer mRootActivityContainer;
368 
369     static final int STARTING_WINDOW_NOT_SHOWN = 0;
370     static final int STARTING_WINDOW_SHOWN = 1;
371     static final int STARTING_WINDOW_REMOVED = 2;
372     int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
373     boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
374 
375     // Marking the reason why this activity is being relaunched. Mainly used to track that this
376     // activity is being relaunched to fulfill a resize request due to compatibility issues, e.g. in
377     // pre-NYC apps that don't have a sense of being resized.
378     int mRelaunchReason = RELAUNCH_REASON_NONE;
379 
380     TaskDescription taskDescription; // the recents information for this activity
381     boolean mLaunchTaskBehind; // this activity is actively being launched with
382         // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed.
383 
384     // These configurations are collected from application's resources based on size-sensitive
385     // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
386     // and drawable-sw400dp will be added to both as 400.
387     private int[] mVerticalSizeConfigurations;
388     private int[] mHorizontalSizeConfigurations;
389     private int[] mSmallestSizeConfigurations;
390 
391     /**
392      * The precomputed display insets for resolving configuration. It will be non-null if
393      * {@link #shouldUseSizeCompatMode} returns {@code true}.
394      */
395     private CompatDisplayInsets mCompatDisplayInsets;
396 
397     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
398     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
399 
400     // A hint to override the window specified rotation animation, or -1
401     // to use the window specified value. We use this so that
402     // we can select the right animation in the cases of starting
403     // windows, where the app hasn't had time to set a value
404     // on the window.
405     int mRotationAnimationHint = -1;
406 
407     private boolean mShowWhenLocked;
408     private boolean mInheritShownWhenLocked;
409     private boolean mTurnScreenOn;
410 
411     /**
412      * Current sequencing integer of the configuration, for skipping old activity configurations.
413      */
414     private int mConfigurationSeq;
415 
416     /**
417      * Temp configs used in {@link #ensureActivityConfiguration(int, boolean)}
418      */
419     private final Configuration mTmpConfig = new Configuration();
420     private final Rect mTmpBounds = new Rect();
421 
422     // Token for targeting this activity for assist purposes.
423     final Binder assistToken = new Binder();
424 
startingWindowStateToString(int state)425     private static String startingWindowStateToString(int state) {
426         switch (state) {
427             case STARTING_WINDOW_NOT_SHOWN:
428                 return "STARTING_WINDOW_NOT_SHOWN";
429             case STARTING_WINDOW_SHOWN:
430                 return "STARTING_WINDOW_SHOWN";
431             case STARTING_WINDOW_REMOVED:
432                 return "STARTING_WINDOW_REMOVED";
433             default:
434                 return "unknown state=" + state;
435         }
436     }
437 
dump(PrintWriter pw, String prefix)438     void dump(PrintWriter pw, String prefix) {
439         final long now = SystemClock.uptimeMillis();
440         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
441                 pw.print(" processName="); pw.println(processName);
442         pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
443                 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
444                 pw.print(" userId="); pw.println(mUserId);
445         pw.print(prefix); pw.print("app="); pw.println(app);
446         pw.print(prefix); pw.println(intent.toInsecureStringWithClip());
447         pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
448                 pw.print(" task="); pw.println(task);
449         pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
450         pw.print(prefix); pw.print("mActivityComponent=");
451                 pw.println(mActivityComponent.flattenToShortString());
452         if (appInfo != null) {
453             pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
454             if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
455                 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
456             }
457             pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
458             if (appInfo.splitSourceDirs != null) {
459                 pw.print(prefix); pw.print("splitDir=");
460                         pw.println(Arrays.toString(appInfo.splitSourceDirs));
461             }
462         }
463         pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
464                 pw.print(" componentSpecified="); pw.print(componentSpecified);
465                 pw.print(" mActivityType="); pw.println(
466                         activityTypeToString(getActivityType()));
467         if (rootVoiceInteraction) {
468             pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
469         }
470         pw.print(prefix); pw.print("compat="); pw.print(compat);
471                 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
472                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
473                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
474         pw.println(prefix + "mLastReportedConfigurations:");
475         mLastReportedConfiguration.dump(pw, prefix + " ");
476 
477         pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
478         if (!getRequestedOverrideConfiguration().equals(EMPTY)) {
479             pw.println(prefix + "RequestedOverrideConfiguration="
480                     + getRequestedOverrideConfiguration());
481         }
482         if (!getResolvedOverrideConfiguration().equals(getRequestedOverrideConfiguration())) {
483             pw.println(prefix + "ResolvedOverrideConfiguration="
484                     + getResolvedOverrideConfiguration());
485         }
486         if (!matchParentBounds()) {
487             pw.println(prefix + "bounds=" + getBounds());
488         }
489         if (resultTo != null || resultWho != null) {
490             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
491                     pw.print(" resultWho="); pw.print(resultWho);
492                     pw.print(" resultCode="); pw.println(requestCode);
493         }
494         if (taskDescription != null) {
495             final String iconFilename = taskDescription.getIconFilename();
496             if (iconFilename != null || taskDescription.getLabel() != null ||
497                     taskDescription.getPrimaryColor() != 0) {
498                 pw.print(prefix); pw.print("taskDescription:");
499                         pw.print(" label=\""); pw.print(taskDescription.getLabel());
500                                 pw.print("\"");
501                         pw.print(" icon="); pw.print(taskDescription.getInMemoryIcon() != null
502                                 ? taskDescription.getInMemoryIcon().getByteCount() + " bytes"
503                                 : "null");
504                         pw.print(" iconResource="); pw.print(taskDescription.getIconResource());
505                         pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
506                         pw.print(" primaryColor=");
507                         pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
508                         pw.print(prefix + " backgroundColor=");
509                         pw.println(Integer.toHexString(taskDescription.getBackgroundColor()));
510                         pw.print(prefix + " statusBarColor=");
511                         pw.println(Integer.toHexString(taskDescription.getStatusBarColor()));
512                         pw.print(prefix + " navigationBarColor=");
513                         pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
514             }
515         }
516         if (results != null) {
517             pw.print(prefix); pw.print("results="); pw.println(results);
518         }
519         if (pendingResults != null && pendingResults.size() > 0) {
520             pw.print(prefix); pw.println("Pending Results:");
521             for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
522                 PendingIntentRecord pir = wpir != null ? wpir.get() : null;
523                 pw.print(prefix); pw.print("  - ");
524                 if (pir == null) {
525                     pw.println("null");
526                 } else {
527                     pw.println(pir);
528                     pir.dump(pw, prefix + "    ");
529                 }
530             }
531         }
532         if (newIntents != null && newIntents.size() > 0) {
533             pw.print(prefix); pw.println("Pending New Intents:");
534             for (int i=0; i<newIntents.size(); i++) {
535                 Intent intent = newIntents.get(i);
536                 pw.print(prefix); pw.print("  - ");
537                 if (intent == null) {
538                     pw.println("null");
539                 } else {
540                     pw.println(intent.toShortString(false, true, false, true));
541                 }
542             }
543         }
544         if (pendingOptions != null) {
545             pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
546         }
547         if (appTimeTracker != null) {
548             appTimeTracker.dumpWithHeader(pw, prefix, false);
549         }
550         if (uriPermissions != null) {
551             uriPermissions.dump(pw, prefix);
552         }
553         pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
554                 pw.print(" launchCount="); pw.print(launchCount);
555                 pw.print(" lastLaunchTime=");
556                 if (lastLaunchTime == 0) pw.print("0");
557                 else TimeUtils.formatDuration(lastLaunchTime, now, pw);
558                 pw.println();
559         pw.print(prefix); pw.print("haveState="); pw.print(haveState);
560                 pw.print(" icicle="); pw.println(icicle);
561         pw.print(prefix); pw.print("state="); pw.print(mState);
562                 pw.print(" stopped="); pw.print(stopped);
563                 pw.print(" delayedResume="); pw.print(delayedResume);
564                 pw.print(" finishing="); pw.println(finishing);
565         pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
566                 pw.print(" inHistory="); pw.print(inHistory);
567                 pw.print(" visible="); pw.print(visible);
568                 pw.print(" sleeping="); pw.print(sleeping);
569                 pw.print(" idle="); pw.print(idle);
570                 pw.print(" mStartingWindowState=");
571                 pw.println(startingWindowStateToString(mStartingWindowState));
572         pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
573                 pw.print(" noDisplay="); pw.print(noDisplay);
574                 pw.print(" immersive="); pw.print(immersive);
575                 pw.print(" launchMode="); pw.println(launchMode);
576         pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
577                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
578         pw.print(prefix); pw.print("mActivityType=");
579                 pw.println(activityTypeToString(getActivityType()));
580         if (requestedVrComponent != null) {
581             pw.print(prefix);
582             pw.print("requestedVrComponent=");
583             pw.println(requestedVrComponent);
584         }
585         if (lastVisibleTime != 0 || nowVisible) {
586             pw.print(prefix); pw.print(" nowVisible="); pw.print(nowVisible);
587                     pw.print(" lastVisibleTime=");
588                     if (lastVisibleTime == 0) pw.print("0");
589                     else TimeUtils.formatDuration(lastVisibleTime, now, pw);
590                     pw.println();
591         }
592         if (mDeferHidingClient) {
593             pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient);
594         }
595         if (deferRelaunchUntilPaused || configChangeFlags != 0) {
596             pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused);
597                     pw.print(" configChangeFlags=");
598                     pw.println(Integer.toHexString(configChangeFlags));
599         }
600         if (mServiceConnectionsHolder != null) {
601             pw.print(prefix); pw.print("connections="); pw.println(mServiceConnectionsHolder);
602         }
603         if (info != null) {
604             pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
605             pw.println(prefix + "mLastReportedMultiWindowMode=" + mLastReportedMultiWindowMode
606                     + " mLastReportedPictureInPictureMode=" + mLastReportedPictureInPictureMode);
607             if (info.supportsPictureInPicture()) {
608                 pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture());
609                 pw.println(prefix + "supportsEnterPipOnTaskSwitch: "
610                         + supportsEnterPipOnTaskSwitch);
611             }
612             if (info.maxAspectRatio != 0) {
613                 pw.println(prefix + "maxAspectRatio=" + info.maxAspectRatio);
614             }
615             if (info.minAspectRatio != 0) {
616                 pw.println(prefix + "minAspectRatio=" + info.minAspectRatio);
617             }
618         }
619     }
620 
updateApplicationInfo(ApplicationInfo aInfo)621     void updateApplicationInfo(ApplicationInfo aInfo) {
622         appInfo = aInfo;
623         info.applicationInfo = aInfo;
624     }
625 
crossesHorizontalSizeThreshold(int firstDp, int secondDp)626     private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
627         return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
628     }
629 
crossesVerticalSizeThreshold(int firstDp, int secondDp)630     private boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
631         return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp);
632     }
633 
crossesSmallestSizeThreshold(int firstDp, int secondDp)634     private boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
635         return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp);
636     }
637 
638     /**
639      * The purpose of this method is to decide whether the activity needs to be relaunched upon
640      * changing its size. In most cases the activities don't need to be relaunched, if the resize
641      * is small, all the activity content has to do is relayout itself within new bounds. There are
642      * cases however, where the activity's content would be completely changed in the new size and
643      * the full relaunch is required.
644      *
645      * The activity will report to us vertical and horizontal thresholds after which a relaunch is
646      * required. These thresholds are collected from the application resource qualifiers. For
647      * example, if application has layout-w600dp resource directory, then it needs a relaunch when
648      * we resize from width of 650dp to 550dp, as it crosses the 600dp threshold. However, if
649      * it resizes width from 620dp to 700dp, it won't be relaunched as it stays on the same side
650      * of the threshold.
651      */
crossesSizeThreshold(int[] thresholds, int firstDp, int secondDp)652     private static boolean crossesSizeThreshold(int[] thresholds, int firstDp,
653             int secondDp) {
654         if (thresholds == null) {
655             return false;
656         }
657         for (int i = thresholds.length - 1; i >= 0; i--) {
658             final int threshold = thresholds[i];
659             if ((firstDp < threshold && secondDp >= threshold)
660                     || (firstDp >= threshold && secondDp < threshold)) {
661                 return true;
662             }
663         }
664         return false;
665     }
666 
setSizeConfigurations(int[] horizontalSizeConfiguration, int[] verticalSizeConfigurations, int[] smallestSizeConfigurations)667     void setSizeConfigurations(int[] horizontalSizeConfiguration,
668             int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
669         mHorizontalSizeConfigurations = horizontalSizeConfiguration;
670         mVerticalSizeConfigurations = verticalSizeConfigurations;
671         mSmallestSizeConfigurations = smallestSizeConfigurations;
672     }
673 
scheduleActivityMovedToDisplay(int displayId, Configuration config)674     private void scheduleActivityMovedToDisplay(int displayId, Configuration config) {
675         if (!attachedToProcess()) {
676             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.w(TAG,
677                     "Can't report activity moved to display - client not running, activityRecord="
678                             + this + ", displayId=" + displayId);
679             return;
680         }
681         try {
682             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
683                     "Reporting activity moved to display" + ", activityRecord=" + this
684                             + ", displayId=" + displayId + ", config=" + config);
685 
686             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
687                     MoveToDisplayItem.obtain(displayId, config));
688         } catch (RemoteException e) {
689             // If process died, whatever.
690         }
691     }
692 
scheduleConfigurationChanged(Configuration config)693     private void scheduleConfigurationChanged(Configuration config) {
694         if (!attachedToProcess()) {
695             if (DEBUG_CONFIGURATION) Slog.w(TAG,
696                     "Can't report activity configuration update - client not running"
697                             + ", activityRecord=" + this);
698             return;
699         }
700         try {
701             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "
702                     + config);
703 
704             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
705                     ActivityConfigurationChangeItem.obtain(config));
706         } catch (RemoteException e) {
707             // If process died, whatever.
708         }
709     }
710 
scheduleTopResumedActivityChanged(boolean onTop)711     boolean scheduleTopResumedActivityChanged(boolean onTop) {
712         if (!attachedToProcess()) {
713             if (DEBUG_STATES) {
714                 Slog.w(TAG, "Can't report activity position update - client not running"
715                                 + ", activityRecord=" + this);
716             }
717             return false;
718         }
719         try {
720             if (DEBUG_STATES) {
721                 Slog.v(TAG, "Sending position change to " + this + ", onTop: " + onTop);
722             }
723 
724             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
725                     TopResumedActivityChangeItem.obtain(onTop));
726         } catch (RemoteException e) {
727             // If process died, whatever.
728             return false;
729         }
730         return true;
731     }
732 
updateMultiWindowMode()733     void updateMultiWindowMode() {
734         if (task == null || task.getStack() == null || !attachedToProcess()) {
735             return;
736         }
737 
738         if (task.getStack().deferScheduleMultiWindowModeChanged()) {
739             // Don't do anything if we are currently deferring multi-window mode change.
740             return;
741         }
742 
743         // An activity is considered to be in multi-window mode if its task isn't fullscreen.
744         final boolean inMultiWindowMode = inMultiWindowMode();
745         if (inMultiWindowMode != mLastReportedMultiWindowMode) {
746             mLastReportedMultiWindowMode = inMultiWindowMode;
747             scheduleMultiWindowModeChanged(getConfiguration());
748         }
749     }
750 
scheduleMultiWindowModeChanged(Configuration overrideConfig)751     private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
752         try {
753             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
754                     MultiWindowModeChangeItem.obtain(mLastReportedMultiWindowMode, overrideConfig));
755         } catch (Exception e) {
756             // If process died, I don't care.
757         }
758     }
759 
updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate)760     void updatePictureInPictureMode(Rect targetStackBounds, boolean forceUpdate) {
761         if (task == null || task.getStack() == null || !attachedToProcess()) {
762             return;
763         }
764 
765         final boolean inPictureInPictureMode = inPinnedWindowingMode() && targetStackBounds != null;
766         if (inPictureInPictureMode != mLastReportedPictureInPictureMode || forceUpdate) {
767             // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
768             // update that here in order. Set the last reported MW state to the same as the PiP
769             // state since we haven't yet actually resized the task (these callbacks need to
770             // preceed the configuration change from the resiez.
771             // TODO(110009072): Once we move these callbacks to the client, remove all logic related
772             // to forcing the update of the picture-in-picture mode as a part of the PiP animation.
773             mLastReportedPictureInPictureMode = inPictureInPictureMode;
774             mLastReportedMultiWindowMode = inPictureInPictureMode;
775             final Configuration newConfig = new Configuration();
776             if (targetStackBounds != null && !targetStackBounds.isEmpty()) {
777                 newConfig.setTo(task.getRequestedOverrideConfiguration());
778                 Rect outBounds = newConfig.windowConfiguration.getBounds();
779                 task.adjustForMinimalTaskDimensions(outBounds, outBounds);
780                 task.computeConfigResourceOverrides(newConfig, task.getParent().getConfiguration());
781             }
782             schedulePictureInPictureModeChanged(newConfig);
783             scheduleMultiWindowModeChanged(newConfig);
784         }
785     }
786 
schedulePictureInPictureModeChanged(Configuration overrideConfig)787     private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
788         try {
789             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
790                     PipModeChangeItem.obtain(mLastReportedPictureInPictureMode,
791                             overrideConfig));
792         } catch (Exception e) {
793             // If process died, no one cares.
794         }
795     }
796 
797     @Override
getChildCount()798     protected int getChildCount() {
799         // {@link ActivityRecord} is a leaf node and has no children.
800         return 0;
801     }
802 
803     @Override
getChildAt(int index)804     protected ConfigurationContainer getChildAt(int index) {
805         return null;
806     }
807 
808     @Override
getParent()809     protected ConfigurationContainer getParent() {
810         return getTaskRecord();
811     }
812 
getTaskRecord()813     TaskRecord getTaskRecord() {
814         return task;
815     }
816 
817     /**
818      * Sets reference to the {@link TaskRecord} the {@link ActivityRecord} will treat as its parent.
819      * Note that this does not actually add the {@link ActivityRecord} as a {@link TaskRecord}
820      * children. However, this method will clean up references to this {@link ActivityRecord} in
821      * {@link ActivityStack}.
822      * @param task The new parent {@link TaskRecord}.
823      */
setTask(TaskRecord task)824     void setTask(TaskRecord task) {
825         setTask(task /* task */, false /* reparenting */);
826     }
827 
828     /**
829      * This method should only be called by {@link TaskRecord#removeActivity(ActivityRecord)}.
830      * @param task          The new parent task.
831      * @param reparenting   Whether we're in the middle of reparenting.
832      */
setTask(TaskRecord task, boolean reparenting)833     void setTask(TaskRecord task, boolean reparenting) {
834         // Do nothing if the {@link TaskRecord} is the same as the current {@link getTaskRecord}.
835         if (task != null && task == getTaskRecord()) {
836             return;
837         }
838 
839         final ActivityStack oldStack = getActivityStack();
840         final ActivityStack newStack = task != null ? task.getStack() : null;
841 
842         // Inform old stack (if present) of activity removal and new stack (if set) of activity
843         // addition.
844         if (oldStack != newStack) {
845             if (!reparenting && oldStack != null) {
846                 oldStack.onActivityRemovedFromStack(this);
847             }
848 
849             if (newStack != null) {
850                 newStack.onActivityAddedToStack(this);
851             }
852         }
853 
854         this.task = task;
855 
856         if (!reparenting) {
857             onParentChanged();
858         }
859     }
860 
861     /**
862      * Notifies AWT that this app is waiting to pause in order to determine if it will enter PIP.
863      * This information helps AWT know that the app is in the process of pausing before it gets the
864      * signal on the WM side.
865      */
setWillCloseOrEnterPip(boolean willCloseOrEnterPip)866     void setWillCloseOrEnterPip(boolean willCloseOrEnterPip) {
867         if (mAppWindowToken == null) {
868             return;
869         }
870 
871         mAppWindowToken.setWillCloseOrEnterPip(willCloseOrEnterPip);
872     }
873 
874     static class Token extends IApplicationToken.Stub {
875         private final WeakReference<ActivityRecord> weakActivity;
876         private final String name;
877 
Token(ActivityRecord activity, Intent intent)878         Token(ActivityRecord activity, Intent intent) {
879             weakActivity = new WeakReference<>(activity);
880             name = intent.getComponent().flattenToShortString();
881         }
882 
tokenToActivityRecordLocked(Token token)883         private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
884             if (token == null) {
885                 return null;
886             }
887             ActivityRecord r = token.weakActivity.get();
888             if (r == null || r.getActivityStack() == null) {
889                 return null;
890             }
891             return r;
892         }
893 
894         @Override
toString()895         public String toString() {
896             StringBuilder sb = new StringBuilder(128);
897             sb.append("Token{");
898             sb.append(Integer.toHexString(System.identityHashCode(this)));
899             sb.append(' ');
900             sb.append(weakActivity.get());
901             sb.append('}');
902             return sb.toString();
903         }
904 
905         @Override
getName()906         public String getName() {
907             return name;
908         }
909     }
910 
forTokenLocked(IBinder token)911     static @Nullable ActivityRecord forTokenLocked(IBinder token) {
912         try {
913             return Token.tokenToActivityRecordLocked((Token)token);
914         } catch (ClassCastException e) {
915             Slog.w(TAG, "Bad activity token: " + token, e);
916             return null;
917         }
918     }
919 
isResolverActivity(String className)920     static boolean isResolverActivity(String className) {
921         return ResolverActivity.class.getName().equals(className);
922     }
923 
isResolverOrDelegateActivity()924     boolean isResolverOrDelegateActivity() {
925         return isResolverActivity(mActivityComponent.getClassName()) || Objects.equals(
926                 mActivityComponent, mAtmService.mStackSupervisor.getSystemChooserActivity());
927     }
928 
isResolverOrChildActivity()929     boolean isResolverOrChildActivity() {
930         if (!"android".equals(packageName)) {
931             return false;
932         }
933         try {
934             return ResolverActivity.class.isAssignableFrom(
935                     Object.class.getClassLoader().loadClass(mActivityComponent.getClassName()));
936         } catch (ClassNotFoundException e) {
937             return false;
938         }
939     }
940 
ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller, int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType, ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified, boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor, ActivityOptions options, ActivityRecord sourceRecord)941     ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
942             int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent,
943             String _resolvedType, ActivityInfo aInfo, Configuration _configuration,
944             ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
945             boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
946             ActivityOptions options, ActivityRecord sourceRecord) {
947         mAtmService = _service;
948         mRootActivityContainer = _service.mRootActivityContainer;
949         appToken = new Token(this, _intent);
950         info = aInfo;
951         launchedFromPid = _launchedFromPid;
952         launchedFromUid = _launchedFromUid;
953         launchedFromPackage = _launchedFromPackage;
954         mUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
955         intent = _intent;
956         shortComponentName = _intent.getComponent().flattenToShortString();
957         resolvedType = _resolvedType;
958         componentSpecified = _componentSpecified;
959         rootVoiceInteraction = _rootVoiceInteraction;
960         mLastReportedConfiguration = new MergedConfiguration(_configuration);
961         resultTo = _resultTo;
962         resultWho = _resultWho;
963         requestCode = _reqCode;
964         setState(INITIALIZING, "ActivityRecord ctor");
965         frontOfTask = false;
966         launchFailed = false;
967         stopped = false;
968         delayedResume = false;
969         finishing = false;
970         deferRelaunchUntilPaused = false;
971         keysPaused = false;
972         inHistory = false;
973         visible = false;
974         nowVisible = false;
975         mDrawn = false;
976         idle = false;
977         hasBeenLaunched = false;
978         mStackSupervisor = supervisor;
979 
980         // This starts out true, since the initial state of an activity is that we have everything,
981         // and we shouldn't never consider it lacking in state to be removed if it dies.
982         haveState = true;
983 
984         // If the class name in the intent doesn't match that of the target, this is
985         // probably an alias. We have to create a new ComponentName object to keep track
986         // of the real activity name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
987         if (aInfo.targetActivity == null
988                 || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
989                 && (aInfo.launchMode == LAUNCH_MULTIPLE
990                 || aInfo.launchMode == LAUNCH_SINGLE_TOP))) {
991             mActivityComponent = _intent.getComponent();
992         } else {
993             mActivityComponent = new ComponentName(aInfo.packageName, aInfo.targetActivity);
994         }
995         taskAffinity = aInfo.taskAffinity;
996         stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
997         appInfo = aInfo.applicationInfo;
998         nonLocalizedLabel = aInfo.nonLocalizedLabel;
999         labelRes = aInfo.labelRes;
1000         if (nonLocalizedLabel == null && labelRes == 0) {
1001             ApplicationInfo app = aInfo.applicationInfo;
1002             nonLocalizedLabel = app.nonLocalizedLabel;
1003             labelRes = app.labelRes;
1004         }
1005         icon = aInfo.getIconResource();
1006         logo = aInfo.getLogoResource();
1007         theme = aInfo.getThemeResource();
1008         realTheme = theme;
1009         if (realTheme == 0) {
1010             realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
1011                     ? android.R.style.Theme : android.R.style.Theme_Holo;
1012         }
1013         if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
1014             windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
1015         }
1016         if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
1017                 && (aInfo.applicationInfo.uid == SYSTEM_UID
1018                     || aInfo.applicationInfo.uid == _caller.mInfo.uid)) {
1019             processName = _caller.mName;
1020         } else {
1021             processName = aInfo.processName;
1022         }
1023 
1024         if ((aInfo.flags & FLAG_EXCLUDE_FROM_RECENTS) != 0) {
1025             intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1026         }
1027 
1028         packageName = aInfo.applicationInfo.packageName;
1029         launchMode = aInfo.launchMode;
1030 
1031         Entry ent = AttributeCache.instance().get(packageName,
1032                 realTheme, com.android.internal.R.styleable.Window, mUserId);
1033 
1034         if (ent != null) {
1035             fullscreen = !ActivityInfo.isTranslucentOrFloating(ent.array);
1036             hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
1037             noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
1038         } else {
1039             hasWallpaper = false;
1040             noDisplay = false;
1041         }
1042 
1043         setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
1044 
1045         immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
1046 
1047         requestedVrComponent = (aInfo.requestedVrComponent == null) ?
1048                 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
1049 
1050         mShowWhenLocked = (aInfo.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
1051         mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
1052         mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
1053 
1054         mRotationAnimationHint = aInfo.rotationAnimation;
1055         lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
1056         if (appInfo.isPrivilegedApp() && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
1057                 || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
1058             lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
1059         }
1060 
1061         if (options != null) {
1062             pendingOptions = options;
1063             mLaunchTaskBehind = options.getLaunchTaskBehind();
1064 
1065             final int rotationAnimation = pendingOptions.getRotationAnimationHint();
1066             // Only override manifest supplied option if set.
1067             if (rotationAnimation >= 0) {
1068                 mRotationAnimationHint = rotationAnimation;
1069             }
1070             final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
1071             if (usageReport != null) {
1072                 appTimeTracker = new AppTimeTracker(usageReport);
1073             }
1074             final boolean useLockTask = pendingOptions.getLockTaskMode();
1075             if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
1076                 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
1077             }
1078             // Gets launch display id from options. It returns INVALID_DISPLAY if not set.
1079             mHandoverLaunchDisplayId = options.getLaunchDisplayId();
1080         }
1081     }
1082 
setProcess(WindowProcessController proc)1083     void setProcess(WindowProcessController proc) {
1084         app = proc;
1085         final ActivityRecord root = task != null ? task.getRootActivity() : null;
1086         if (root == this) {
1087             task.setRootProcess(proc);
1088         }
1089     }
1090 
hasProcess()1091     boolean hasProcess() {
1092         return app != null;
1093     }
1094 
attachedToProcess()1095     boolean attachedToProcess() {
1096         return hasProcess() && app.hasThread();
1097     }
1098 
createAppWindowToken()1099     void createAppWindowToken() {
1100         if (mAppWindowToken != null) {
1101             throw new IllegalArgumentException("App Window Token=" + mAppWindowToken
1102                     + " already created for r=" + this);
1103         }
1104 
1105         inHistory = true;
1106 
1107         // TODO(b/36505427): Maybe this call should be moved inside updateOverrideConfiguration()
1108         task.updateOverrideConfigurationFromLaunchBounds();
1109         // Make sure override configuration is up-to-date before using to create window controller.
1110         updateOverrideConfiguration();
1111 
1112         // TODO: remove after unification
1113         mAppWindowToken = mAtmService.mWindowManager.mRoot.getAppWindowToken(appToken.asBinder());
1114         if (mAppWindowToken != null) {
1115             // TODO: Should this throw an exception instead?
1116             Slog.w(TAG, "Attempted to add existing app token: " + appToken);
1117         } else {
1118             final Task container = task.getTask();
1119             if (container == null) {
1120                 throw new IllegalArgumentException("createAppWindowToken: invalid task =" + task);
1121             }
1122             mAppWindowToken = createAppWindow(mAtmService.mWindowManager, appToken,
1123                     task.voiceSession != null, container.getDisplayContent(),
1124                     ActivityTaskManagerService.getInputDispatchingTimeoutLocked(this)
1125                             * 1000000L, fullscreen,
1126                     (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, appInfo.targetSdkVersion,
1127                     info.screenOrientation, mRotationAnimationHint,
1128                     mLaunchTaskBehind, isAlwaysFocusable());
1129             if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) {
1130                 Slog.v(TAG, "addAppToken: "
1131                         + mAppWindowToken + " task=" + container + " at "
1132                         + Integer.MAX_VALUE);
1133             }
1134             container.addChild(mAppWindowToken, Integer.MAX_VALUE /* add on top */);
1135         }
1136 
1137         task.addActivityToTop(this);
1138 
1139         // When an activity is started directly into a split-screen fullscreen stack, we need to
1140         // update the initial multi-window modes so that the callbacks are scheduled correctly when
1141         // the user leaves that mode.
1142         mLastReportedMultiWindowMode = inMultiWindowMode();
1143         mLastReportedPictureInPictureMode = inPinnedWindowingMode();
1144     }
1145 
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, boolean fromRecents)1146     boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
1147             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
1148             IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
1149             boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
1150         if (DEBUG_STARTING_WINDOW) {
1151             Slog.v(TAG, "setAppStartingWindow: token=" + appToken
1152                     + " pkg=" + pkg + " transferFrom=" + transferFrom + " newTask=" + newTask
1153                     + " taskSwitch=" + taskSwitch + " processRunning=" + processRunning
1154                     + " allowTaskSnapshot=" + allowTaskSnapshot);
1155         }
1156         if (mAppWindowToken == null) {
1157             Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + appToken);
1158             return false;
1159         }
1160         if (mAppWindowToken.getTask() == null) {
1161             // Can be removed after unification of Task and TaskRecord.
1162             Slog.w(TAG_WM, "Attempted to start a window to an app token not having attached to any"
1163                     + " task: " + appToken);
1164             return false;
1165         }
1166         return mAppWindowToken.addStartingWindow(pkg, theme, compatInfo, nonLocalizedLabel,
1167                 labelRes, icon, logo, windowFlags, transferFrom, newTask, taskSwitch,
1168                 processRunning, allowTaskSnapshot, activityCreated, fromRecents);
1169     }
1170 
1171     // TODO: Remove after unification
1172     @VisibleForTesting
createAppWindow(WindowManagerService service, IApplicationToken token, boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos, boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation, int rotationAnimationHint, boolean launchTaskBehind, boolean alwaysFocusable)1173     AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
1174             boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
1175             boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
1176             int rotationAnimationHint, boolean launchTaskBehind,
1177             boolean alwaysFocusable) {
1178         return new AppWindowToken(service, token, mActivityComponent, voiceInteraction, dc,
1179                 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
1180                 rotationAnimationHint, launchTaskBehind, alwaysFocusable,
1181                 this);
1182     }
1183 
removeWindowContainer()1184     void removeWindowContainer() {
1185         if (mAtmService.mWindowManager.mRoot == null) return;
1186 
1187         final DisplayContent dc = mAtmService.mWindowManager.mRoot.getDisplayContent(
1188                 getDisplayId());
1189         if (dc == null) {
1190             Slog.w(TAG, "removeWindowContainer: Attempted to remove token: "
1191                     + appToken + " from non-existing displayId=" + getDisplayId());
1192             return;
1193         }
1194         // Resume key dispatching if it is currently paused before we remove the container.
1195         resumeKeyDispatchingLocked();
1196         dc.removeAppToken(appToken.asBinder());
1197     }
1198 
1199     /**
1200      * Reparents this activity into {@param newTask} at the provided {@param position}.  The caller
1201      * should ensure that the {@param newTask} is not already the parent of this activity.
1202      */
reparent(TaskRecord newTask, int position, String reason)1203     void reparent(TaskRecord newTask, int position, String reason) {
1204         if (mAppWindowToken == null) {
1205             Slog.w(TAG, "reparent: Attempted to reparent non-existing app token: " + appToken);
1206             return;
1207         }
1208         final TaskRecord prevTask = task;
1209         if (prevTask == newTask) {
1210             throw new IllegalArgumentException(reason + ": task=" + newTask
1211                     + " is already the parent of r=" + this);
1212         }
1213 
1214         // TODO: Ensure that we do not directly reparent activities across stacks, as that may leave
1215         //       the stacks in strange states. For now, we should use Task.reparent() to ensure that
1216         //       the stack is left in an OK state.
1217         if (prevTask != null && newTask != null && prevTask.getStack() != newTask.getStack()) {
1218             throw new IllegalArgumentException(reason + ": task=" + newTask
1219                     + " is in a different stack (" + newTask.getStackId() + ") than the parent of"
1220                     + " r=" + this + " (" + prevTask.getStackId() + ")");
1221         }
1222 
1223         mAppWindowToken.reparent(newTask.getTask(), position);
1224 
1225         // Reparenting prevents informing the parent stack of activity removal in the case that
1226         // the new stack has the same parent. we must manually signal here if this is not the case.
1227         final ActivityStack prevStack = prevTask.getStack();
1228 
1229         if (prevStack != newTask.getStack()) {
1230             prevStack.onActivityRemovedFromStack(this);
1231         }
1232         // Remove the activity from the old task and add it to the new task.
1233         prevTask.removeActivity(this, true /* reparenting */);
1234 
1235         newTask.addActivityAtIndex(position, this);
1236     }
1237 
isHomeIntent(Intent intent)1238     private boolean isHomeIntent(Intent intent) {
1239         return ACTION_MAIN.equals(intent.getAction())
1240                 && (intent.hasCategory(CATEGORY_HOME)
1241                 || intent.hasCategory(CATEGORY_SECONDARY_HOME))
1242                 && intent.getCategories().size() == 1
1243                 && intent.getData() == null
1244                 && intent.getType() == null;
1245     }
1246 
isMainIntent(Intent intent)1247     static boolean isMainIntent(Intent intent) {
1248         return ACTION_MAIN.equals(intent.getAction())
1249                 && intent.hasCategory(CATEGORY_LAUNCHER)
1250                 && intent.getCategories().size() == 1
1251                 && intent.getData() == null
1252                 && intent.getType() == null;
1253     }
1254 
1255     @VisibleForTesting
canLaunchHomeActivity(int uid, ActivityRecord sourceRecord)1256     boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) {
1257         if (uid == Process.myUid() || uid == 0) {
1258             // System process can launch home activity.
1259             return true;
1260         }
1261         // Allow the recents component to launch the home activity.
1262         final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks();
1263         if (recentTasks != null && recentTasks.isCallerRecents(uid)) {
1264             return true;
1265         }
1266         // Resolver or system chooser activity can launch home activity.
1267         return sourceRecord != null && sourceRecord.isResolverOrDelegateActivity();
1268     }
1269 
1270     /**
1271      * @return whether the given package name can launch an assist activity.
1272      */
canLaunchAssistActivity(String packageName)1273     private boolean canLaunchAssistActivity(String packageName) {
1274         final ComponentName assistComponent =
1275                 mAtmService.mActiveVoiceInteractionServiceComponent;
1276         if (assistComponent != null) {
1277             return assistComponent.getPackageName().equals(packageName);
1278         }
1279         return false;
1280     }
1281 
setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent, ActivityOptions options, ActivityRecord sourceRecord)1282     private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent,
1283             ActivityOptions options, ActivityRecord sourceRecord) {
1284         int activityType = ACTIVITY_TYPE_UNDEFINED;
1285         if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
1286                 && isHomeIntent(intent) && !isResolverOrDelegateActivity()) {
1287             // This sure looks like a home activity!
1288             activityType = ACTIVITY_TYPE_HOME;
1289 
1290             if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE
1291                     || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
1292                 // We only allow home activities to be resizeable if they explicitly requested it.
1293                 info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
1294             }
1295         } else if (mActivityComponent.getClassName().contains(LEGACY_RECENTS_PACKAGE_NAME)
1296                 || mAtmService.getRecentTasks().isRecentsComponent(mActivityComponent, appInfo.uid)) {
1297             activityType = ACTIVITY_TYPE_RECENTS;
1298         } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
1299                 && canLaunchAssistActivity(launchedFromPackage)) {
1300             activityType = ACTIVITY_TYPE_ASSISTANT;
1301         }
1302         setActivityType(activityType);
1303     }
1304 
setTaskToAffiliateWith(TaskRecord taskToAffiliateWith)1305     void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
1306         if (launchMode != LAUNCH_SINGLE_INSTANCE && launchMode != LAUNCH_SINGLE_TASK) {
1307             task.setTaskToAffiliateWith(taskToAffiliateWith);
1308         }
1309     }
1310 
1311     /**
1312      * @return Stack value from current task, null if there is no task.
1313      */
getActivityStack()1314     <T extends ActivityStack> T getActivityStack() {
1315         return task != null ? (T) task.getStack() : null;
1316     }
1317 
getStackId()1318     int getStackId() {
1319         return getActivityStack() != null ? getActivityStack().mStackId : INVALID_STACK_ID;
1320     }
1321 
getDisplay()1322     ActivityDisplay getDisplay() {
1323         final ActivityStack stack = getActivityStack();
1324         return stack != null ? stack.getDisplay() : null;
1325     }
1326 
changeWindowTranslucency(boolean toOpaque)1327     boolean changeWindowTranslucency(boolean toOpaque) {
1328         if (fullscreen == toOpaque) {
1329             return false;
1330         }
1331 
1332         // Keep track of the number of fullscreen activities in this task.
1333         task.numFullscreen += toOpaque ? +1 : -1;
1334 
1335         fullscreen = toOpaque;
1336         return true;
1337     }
1338 
takeFromHistory()1339     void takeFromHistory() {
1340         if (inHistory) {
1341             inHistory = false;
1342             if (task != null && !finishing) {
1343                 task = null;
1344             }
1345             clearOptionsLocked();
1346         }
1347     }
1348 
isInHistory()1349     boolean isInHistory() {
1350         return inHistory;
1351     }
1352 
isInStackLocked()1353     boolean isInStackLocked() {
1354         final ActivityStack stack = getActivityStack();
1355         return stack != null && stack.isInStackLocked(this) != null;
1356     }
1357 
isPersistable()1358     boolean isPersistable() {
1359         return (info.persistableMode == PERSIST_ROOT_ONLY ||
1360                 info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
1361                 (intent == null || (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
1362     }
1363 
isFocusable()1364     boolean isFocusable() {
1365         return mRootActivityContainer.isFocusable(this, isAlwaysFocusable());
1366     }
1367 
isResizeable()1368     boolean isResizeable() {
1369         return ActivityInfo.isResizeableMode(info.resizeMode) || info.supportsPictureInPicture();
1370     }
1371 
1372     /**
1373      * @return whether this activity is non-resizeable or forced to be resizeable
1374      */
isNonResizableOrForcedResizable()1375     boolean isNonResizableOrForcedResizable() {
1376         return info.resizeMode != RESIZE_MODE_RESIZEABLE
1377                 && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
1378     }
1379 
1380     /**
1381      * @return whether this activity supports PiP multi-window and can be put in the pinned stack.
1382      */
supportsPictureInPicture()1383     boolean supportsPictureInPicture() {
1384         return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined()
1385                 && info.supportsPictureInPicture();
1386     }
1387 
1388     /**
1389      * @return whether this activity supports split-screen multi-window and can be put in the docked
1390      *         stack.
1391      */
1392     @Override
supportsSplitScreenWindowingMode()1393     public boolean supportsSplitScreenWindowingMode() {
1394         // An activity can not be docked even if it is considered resizeable because it only
1395         // supports picture-in-picture mode but has a non-resizeable resizeMode
1396         return super.supportsSplitScreenWindowingMode()
1397                 && mAtmService.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
1398     }
1399 
1400     /**
1401      * @return whether this activity supports freeform multi-window and can be put in the freeform
1402      *         stack.
1403      */
supportsFreeform()1404     boolean supportsFreeform() {
1405         return mAtmService.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
1406     }
1407 
1408     /**
1409      * @return whether this activity supports non-PiP multi-window.
1410      */
supportsResizeableMultiWindow()1411     private boolean supportsResizeableMultiWindow() {
1412         return mAtmService.mSupportsMultiWindow && !isActivityTypeHome()
1413                 && (ActivityInfo.isResizeableMode(info.resizeMode)
1414                         || mAtmService.mForceResizableActivities);
1415     }
1416 
1417     /**
1418      * Check whether this activity can be launched on the specified display.
1419      *
1420      * @param displayId Target display id.
1421      * @return {@code true} if either it is the default display or this activity can be put on a
1422      *         secondary screen.
1423      */
canBeLaunchedOnDisplay(int displayId)1424     boolean canBeLaunchedOnDisplay(int displayId) {
1425         return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId, launchedFromPid,
1426                 launchedFromUid, info);
1427     }
1428 
1429     /**
1430      * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
1431      *         the activity has requested to enter PiP when it would otherwise be stopped.
1432      *
1433      * @return whether this activity is currently allowed to enter PIP.
1434      */
checkEnterPictureInPictureState(String caller, boolean beforeStopping)1435     boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) {
1436         if (!supportsPictureInPicture()) {
1437             return false;
1438         }
1439 
1440         // Check app-ops and see if PiP is supported for this package
1441         if (!checkEnterPictureInPictureAppOpsState()) {
1442             return false;
1443         }
1444 
1445         // Check to see if we are in VR mode, and disallow PiP if so
1446         if (mAtmService.shouldDisableNonVrUiLocked()) {
1447             return false;
1448         }
1449 
1450         boolean isKeyguardLocked = mAtmService.isKeyguardLocked();
1451         boolean isCurrentAppLocked =
1452                 mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
1453         final ActivityDisplay display = getDisplay();
1454         boolean hasPinnedStack = display != null && display.hasPinnedStack();
1455         // Don't return early if !isNotLocked, since we want to throw an exception if the activity
1456         // is in an incorrect state
1457         boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
1458 
1459         // We don't allow auto-PiP when something else is already pipped.
1460         if (beforeStopping && hasPinnedStack) {
1461             return false;
1462         }
1463 
1464         switch (mState) {
1465             case RESUMED:
1466                 // When visible, allow entering PiP if the app is not locked.  If it is over the
1467                 // keyguard, then we will prompt to unlock in the caller before entering PiP.
1468                 return !isCurrentAppLocked &&
1469                         (supportsEnterPipOnTaskSwitch || !beforeStopping);
1470             case PAUSING:
1471             case PAUSED:
1472                 // When pausing, then only allow enter PiP as in the resume state, and in addition,
1473                 // require that there is not an existing PiP activity and that the current system
1474                 // state supports entering PiP
1475                 return isNotLockedOrOnKeyguard && !hasPinnedStack
1476                         && supportsEnterPipOnTaskSwitch;
1477             case STOPPING:
1478                 // When stopping in a valid state, then only allow enter PiP as in the pause state.
1479                 // Otherwise, fall through to throw an exception if the caller is trying to enter
1480                 // PiP in an invalid stopping state.
1481                 if (supportsEnterPipOnTaskSwitch) {
1482                     return isNotLockedOrOnKeyguard && !hasPinnedStack;
1483                 }
1484             default:
1485                 return false;
1486         }
1487     }
1488 
1489     /**
1490      * @return Whether AppOps allows this package to enter picture-in-picture.
1491      */
checkEnterPictureInPictureAppOpsState()1492     private boolean checkEnterPictureInPictureAppOpsState() {
1493         return mAtmService.getAppOpsService().checkOperation(
1494                 OP_PICTURE_IN_PICTURE, appInfo.uid, packageName) == MODE_ALLOWED;
1495     }
1496 
isAlwaysFocusable()1497     boolean isAlwaysFocusable() {
1498         return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
1499     }
1500 
1501     /** Move activity with its stack to front and make the stack focused. */
moveFocusableActivityToTop(String reason)1502     boolean moveFocusableActivityToTop(String reason) {
1503         if (!isFocusable()) {
1504             if (DEBUG_FOCUS) {
1505                 Slog.d(TAG_FOCUS, "moveActivityStackToFront: unfocusable activity=" + this);
1506             }
1507             return false;
1508         }
1509 
1510         final TaskRecord task = getTaskRecord();
1511         final ActivityStack stack = getActivityStack();
1512         if (stack == null) {
1513             Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
1514                     + this + " task=" + task);
1515             return false;
1516         }
1517 
1518         if (mRootActivityContainer.getTopResumedActivity() == this) {
1519             if (DEBUG_FOCUS) {
1520                 Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
1521             }
1522             return false;
1523         }
1524 
1525         if (DEBUG_FOCUS) {
1526             Slog.d(TAG_FOCUS, "moveActivityStackToFront: activity=" + this);
1527         }
1528 
1529         stack.moveToFront(reason, task);
1530         // Report top activity change to tracking services and WM
1531         if (mRootActivityContainer.getTopResumedActivity() == this) {
1532             // TODO(b/111361570): Support multiple focused apps in WM
1533             mAtmService.setResumedActivityUncheckLocked(this, reason);
1534         }
1535         return true;
1536     }
1537 
makeFinishingLocked()1538     void makeFinishingLocked() {
1539         if (finishing) {
1540             return;
1541         }
1542         finishing = true;
1543         if (stopped) {
1544             clearOptionsLocked();
1545         }
1546     }
1547 
getUriPermissionsLocked()1548     UriPermissionOwner getUriPermissionsLocked() {
1549         if (uriPermissions == null) {
1550             uriPermissions = new UriPermissionOwner(mAtmService.mUgmInternal, this);
1551         }
1552         return uriPermissions;
1553     }
1554 
addResultLocked(ActivityRecord from, String resultWho, int requestCode, int resultCode, Intent resultData)1555     void addResultLocked(ActivityRecord from, String resultWho,
1556             int requestCode, int resultCode,
1557             Intent resultData) {
1558         ActivityResult r = new ActivityResult(from, resultWho,
1559                 requestCode, resultCode, resultData);
1560         if (results == null) {
1561             results = new ArrayList<ResultInfo>();
1562         }
1563         results.add(r);
1564     }
1565 
removeResultsLocked(ActivityRecord from, String resultWho, int requestCode)1566     void removeResultsLocked(ActivityRecord from, String resultWho,
1567             int requestCode) {
1568         if (results != null) {
1569             for (int i=results.size()-1; i>=0; i--) {
1570                 ActivityResult r = (ActivityResult)results.get(i);
1571                 if (r.mFrom != from) continue;
1572                 if (r.mResultWho == null) {
1573                     if (resultWho != null) continue;
1574                 } else {
1575                     if (!r.mResultWho.equals(resultWho)) continue;
1576                 }
1577                 if (r.mRequestCode != requestCode) continue;
1578 
1579                 results.remove(i);
1580             }
1581         }
1582     }
1583 
addNewIntentLocked(ReferrerIntent intent)1584     private void addNewIntentLocked(ReferrerIntent intent) {
1585         if (newIntents == null) {
1586             newIntents = new ArrayList<>();
1587         }
1588         newIntents.add(intent);
1589     }
1590 
isSleeping()1591     final boolean isSleeping() {
1592         final ActivityStack stack = getActivityStack();
1593         return stack != null ? stack.shouldSleepActivities() : mAtmService.isSleepingLocked();
1594     }
1595 
1596     /**
1597      * Deliver a new Intent to an existing activity, so that its onNewIntent()
1598      * method will be called at the proper time.
1599      */
deliverNewIntentLocked(int callingUid, Intent intent, String referrer)1600     final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
1601         // The activity now gets access to the data associated with this Intent.
1602         mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
1603                 intent, getUriPermissionsLocked(), mUserId);
1604         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
1605         boolean unsent = true;
1606         final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
1607 
1608         // We want to immediately deliver the intent to the activity if:
1609         // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
1610         //   the user to see the visual effects caused by the intent delivery now.
1611         // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
1612         if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
1613                 && attachedToProcess()) {
1614             try {
1615                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
1616                 ar.add(rintent);
1617                 // Making sure the client state is RESUMED after transaction completed and doing
1618                 // so only if activity is currently RESUMED. Otherwise, client may have extra
1619                 // life-cycle calls to RESUMED (and PAUSED later).
1620                 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
1621                         NewIntentItem.obtain(ar, mState == RESUMED));
1622                 unsent = false;
1623             } catch (RemoteException e) {
1624                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
1625             } catch (NullPointerException e) {
1626                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
1627             }
1628         }
1629         if (unsent) {
1630             addNewIntentLocked(rintent);
1631         }
1632     }
1633 
updateOptionsLocked(ActivityOptions options)1634     void updateOptionsLocked(ActivityOptions options) {
1635         if (options != null) {
1636             if (DEBUG_TRANSITION) Slog.i(TAG, "Update options for " + this);
1637             if (pendingOptions != null) {
1638                 pendingOptions.abort();
1639             }
1640             pendingOptions = options;
1641         }
1642     }
1643 
applyOptionsLocked()1644     void applyOptionsLocked() {
1645         if (pendingOptions != null
1646                 && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
1647             if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
1648             applyOptionsLocked(pendingOptions, intent);
1649             if (task == null) {
1650                 clearOptionsLocked(false /* withAbort */);
1651             } else {
1652                 // This will clear the options for all the ActivityRecords for this Task.
1653                 task.clearAllPendingOptions();
1654             }
1655         }
1656     }
1657 
1658     /**
1659      * Apply override app transition base on options & animation type.
1660      */
applyOptionsLocked(ActivityOptions pendingOptions, Intent intent)1661     void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
1662         final int animationType = pendingOptions.getAnimationType();
1663         final DisplayContent displayContent = mAppWindowToken.getDisplayContent();
1664         switch (animationType) {
1665             case ANIM_CUSTOM:
1666                 displayContent.mAppTransition.overridePendingAppTransition(
1667                         pendingOptions.getPackageName(),
1668                         pendingOptions.getCustomEnterResId(),
1669                         pendingOptions.getCustomExitResId(),
1670                         pendingOptions.getOnAnimationStartListener());
1671                 break;
1672             case ANIM_CLIP_REVEAL:
1673                 displayContent.mAppTransition.overridePendingAppTransitionClipReveal(
1674                         pendingOptions.getStartX(), pendingOptions.getStartY(),
1675                         pendingOptions.getWidth(), pendingOptions.getHeight());
1676                 if (intent.getSourceBounds() == null) {
1677                     intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1678                             pendingOptions.getStartY(),
1679                             pendingOptions.getStartX() + pendingOptions.getWidth(),
1680                             pendingOptions.getStartY() + pendingOptions.getHeight()));
1681                 }
1682                 break;
1683             case ANIM_SCALE_UP:
1684                 displayContent.mAppTransition.overridePendingAppTransitionScaleUp(
1685                         pendingOptions.getStartX(), pendingOptions.getStartY(),
1686                         pendingOptions.getWidth(), pendingOptions.getHeight());
1687                 if (intent.getSourceBounds() == null) {
1688                     intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1689                             pendingOptions.getStartY(),
1690                             pendingOptions.getStartX() + pendingOptions.getWidth(),
1691                             pendingOptions.getStartY() + pendingOptions.getHeight()));
1692                 }
1693                 break;
1694             case ANIM_THUMBNAIL_SCALE_UP:
1695             case ANIM_THUMBNAIL_SCALE_DOWN:
1696                 final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
1697                 final GraphicBuffer buffer = pendingOptions.getThumbnail();
1698                 displayContent.mAppTransition.overridePendingAppTransitionThumb(buffer,
1699                         pendingOptions.getStartX(), pendingOptions.getStartY(),
1700                         pendingOptions.getOnAnimationStartListener(),
1701                         scaleUp);
1702                 if (intent.getSourceBounds() == null && buffer != null) {
1703                     intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1704                             pendingOptions.getStartY(),
1705                             pendingOptions.getStartX() + buffer.getWidth(),
1706                             pendingOptions.getStartY() + buffer.getHeight()));
1707                 }
1708                 break;
1709             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
1710             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
1711                 final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
1712                 final IAppTransitionAnimationSpecsFuture specsFuture =
1713                         pendingOptions.getSpecsFuture();
1714                 if (specsFuture != null) {
1715                     displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(
1716                             specsFuture, pendingOptions.getOnAnimationStartListener(),
1717                             animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
1718                 } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
1719                         && specs != null) {
1720                     displayContent.mAppTransition.overridePendingAppTransitionMultiThumb(
1721                             specs, pendingOptions.getOnAnimationStartListener(),
1722                             pendingOptions.getAnimationFinishedListener(), false);
1723                 } else {
1724                     displayContent.mAppTransition.overridePendingAppTransitionAspectScaledThumb(
1725                             pendingOptions.getThumbnail(),
1726                             pendingOptions.getStartX(), pendingOptions.getStartY(),
1727                             pendingOptions.getWidth(), pendingOptions.getHeight(),
1728                             pendingOptions.getOnAnimationStartListener(),
1729                             (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
1730                     if (intent.getSourceBounds() == null) {
1731                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1732                                 pendingOptions.getStartY(),
1733                                 pendingOptions.getStartX() + pendingOptions.getWidth(),
1734                                 pendingOptions.getStartY() + pendingOptions.getHeight()));
1735                     }
1736                 }
1737                 break;
1738             case ANIM_OPEN_CROSS_PROFILE_APPS:
1739                 displayContent.mAppTransition
1740                         .overridePendingAppTransitionStartCrossProfileApps();
1741                 break;
1742             case ANIM_REMOTE_ANIMATION:
1743                 displayContent.mAppTransition.overridePendingAppTransitionRemote(
1744                         pendingOptions.getRemoteAnimationAdapter());
1745                 break;
1746             case ANIM_NONE:
1747                 break;
1748             default:
1749                 Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
1750                 break;
1751         }
1752     }
1753 
getOptionsForTargetActivityLocked()1754     ActivityOptions getOptionsForTargetActivityLocked() {
1755         return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
1756     }
1757 
clearOptionsLocked()1758     void clearOptionsLocked() {
1759         clearOptionsLocked(true /* withAbort */);
1760     }
1761 
clearOptionsLocked(boolean withAbort)1762     void clearOptionsLocked(boolean withAbort) {
1763         if (withAbort && pendingOptions != null) {
1764             pendingOptions.abort();
1765         }
1766         pendingOptions = null;
1767     }
1768 
takeOptionsLocked(boolean fromClient)1769     ActivityOptions takeOptionsLocked(boolean fromClient) {
1770         if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
1771                 + Debug.getCallers(6));
1772         ActivityOptions opts = pendingOptions;
1773 
1774         // If we are trying to take activity options from the client, do not null it out if it's a
1775         // remote animation as the client doesn't need it ever. This is a workaround when client is
1776         // faster to take the options than we are to resume the next activity.
1777         // TODO (b/132432864): Fix the root cause of these transition preparing/applying options
1778         // timing somehow
1779         if (!fromClient || opts == null || opts.getRemoteAnimationAdapter() == null) {
1780             pendingOptions = null;
1781         }
1782         return opts;
1783     }
1784 
removeUriPermissionsLocked()1785     void removeUriPermissionsLocked() {
1786         if (uriPermissions != null) {
1787             uriPermissions.removeUriPermissions();
1788             uriPermissions = null;
1789         }
1790     }
1791 
pauseKeyDispatchingLocked()1792     void pauseKeyDispatchingLocked() {
1793         if (!keysPaused) {
1794             keysPaused = true;
1795 
1796             // TODO: remove the check after unification with AppWindowToken. The DC check is not
1797             // needed after no mock mAppWindowToken in tests.
1798             if (mAppWindowToken != null && mAppWindowToken.getDisplayContent() != null) {
1799                 mAppWindowToken.getDisplayContent().getInputMonitor().pauseDispatchingLw(
1800                         mAppWindowToken);
1801             }
1802         }
1803     }
1804 
resumeKeyDispatchingLocked()1805     void resumeKeyDispatchingLocked() {
1806         if (keysPaused) {
1807             keysPaused = false;
1808 
1809             // TODO: remove the check after unification with AppWindowToken. The DC check is not
1810             // needed after no mock mAppWindowToken in tests.
1811             if (mAppWindowToken != null && mAppWindowToken.getDisplayContent() != null) {
1812                 mAppWindowToken.getDisplayContent().getInputMonitor().resumeDispatchingLw(
1813                         mAppWindowToken);
1814             }
1815         }
1816     }
1817 
updateTaskDescription(CharSequence description)1818     private void updateTaskDescription(CharSequence description) {
1819         task.lastDescription = description;
1820     }
1821 
setDeferHidingClient(boolean deferHidingClient)1822     void setDeferHidingClient(boolean deferHidingClient) {
1823         if (mDeferHidingClient == deferHidingClient) {
1824             return;
1825         }
1826         mDeferHidingClient = deferHidingClient;
1827         if (!mDeferHidingClient && !visible) {
1828             // Hiding the client is no longer deferred and the app isn't visible still, go ahead and
1829             // update the visibility.
1830             setVisibility(false);
1831         }
1832     }
1833 
setVisibility(boolean visible)1834     void setVisibility(boolean visible) {
1835         if (mAppWindowToken == null) {
1836             Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
1837                     + appToken);
1838             return;
1839         }
1840         mAppWindowToken.setVisibility(visible, mDeferHidingClient);
1841         mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
1842     }
1843 
1844     // TODO: Look into merging with #commitVisibility()
setVisible(boolean newVisible)1845     void setVisible(boolean newVisible) {
1846         visible = newVisible;
1847         mDeferHidingClient = !visible && mDeferHidingClient;
1848         setVisibility(visible);
1849         mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
1850     }
1851 
setState(ActivityState state, String reason)1852     void setState(ActivityState state, String reason) {
1853         if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
1854                         + " to:" + state + " reason:" + reason);
1855 
1856         if (state == mState) {
1857             // No need to do anything if state doesn't change.
1858             if (DEBUG_STATES) Slog.v(TAG_STATES, "State unchanged from:" + state);
1859             return;
1860         }
1861 
1862         mState = state;
1863 
1864         final TaskRecord parent = getTaskRecord();
1865 
1866         if (parent != null) {
1867             parent.onActivityStateChanged(this, state, reason);
1868         }
1869 
1870         // The WindowManager interprets the app stopping signal as
1871         // an indication that the Surface will eventually be destroyed.
1872         // This however isn't necessarily true if we are going to sleep.
1873         if (state == STOPPING && !isSleeping()) {
1874             if (mAppWindowToken == null) {
1875                 Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
1876                         + appToken);
1877                 return;
1878             }
1879             mAppWindowToken.detachChildren();
1880         }
1881 
1882         if (state == RESUMED) {
1883             mAtmService.updateBatteryStats(this, true);
1884             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_RESUMED);
1885         } else if (state == PAUSED) {
1886             mAtmService.updateBatteryStats(this, false);
1887             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
1888         } else if (state == STOPPED) {
1889             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
1890         } else if (state == DESTROYED) {
1891             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED);
1892         }
1893     }
1894 
getState()1895     ActivityState getState() {
1896         return mState;
1897     }
1898 
1899     /**
1900      * Returns {@code true} if the Activity is in the specified state.
1901      */
isState(ActivityState state)1902     boolean isState(ActivityState state) {
1903         return state == mState;
1904     }
1905 
1906     /**
1907      * Returns {@code true} if the Activity is in one of the specified states.
1908      */
isState(ActivityState state1, ActivityState state2)1909     boolean isState(ActivityState state1, ActivityState state2) {
1910         return state1 == mState || state2 == mState;
1911     }
1912 
1913     /**
1914      * Returns {@code true} if the Activity is in one of the specified states.
1915      */
isState(ActivityState state1, ActivityState state2, ActivityState state3)1916     boolean isState(ActivityState state1, ActivityState state2, ActivityState state3) {
1917         return state1 == mState || state2 == mState || state3 == mState;
1918     }
1919 
1920     /**
1921      * Returns {@code true} if the Activity is in one of the specified states.
1922      */
isState(ActivityState state1, ActivityState state2, ActivityState state3, ActivityState state4)1923     boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
1924             ActivityState state4) {
1925         return state1 == mState || state2 == mState || state3 == mState || state4 == mState;
1926     }
1927 
notifyAppResumed(boolean wasStopped)1928     void notifyAppResumed(boolean wasStopped) {
1929         if (mAppWindowToken == null) {
1930             Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
1931                     + appToken);
1932             return;
1933         }
1934         mAppWindowToken.notifyAppResumed(wasStopped);
1935     }
1936 
notifyUnknownVisibilityLaunched()1937     void notifyUnknownVisibilityLaunched() {
1938 
1939         // No display activities never add a window, so there is no point in waiting them for
1940         // relayout.
1941         if (!noDisplay) {
1942             if (mAppWindowToken != null) {
1943                 mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
1944                         .notifyLaunched(mAppWindowToken);
1945             }
1946         }
1947     }
1948 
1949     /**
1950      * @return true if the input activity should be made visible, ignoring any effect Keyguard
1951      * might have on the visibility
1952      *
1953      * TODO(b/123540470): Combine this method and {@link #shouldBeVisible(boolean)}.
1954      *
1955      * @see {@link ActivityStack#checkKeyguardVisibility}
1956      */
shouldBeVisibleIgnoringKeyguard(boolean behindFullscreenActivity)1957     boolean shouldBeVisibleIgnoringKeyguard(boolean behindFullscreenActivity) {
1958         if (!okToShowLocked()) {
1959             return false;
1960         }
1961 
1962         return !behindFullscreenActivity || mLaunchTaskBehind;
1963     }
1964 
shouldBeVisible(boolean behindFullscreenActivity)1965     boolean shouldBeVisible(boolean behindFullscreenActivity) {
1966         // Check whether activity should be visible without Keyguard influence
1967         visibleIgnoringKeyguard = shouldBeVisibleIgnoringKeyguard(behindFullscreenActivity);
1968 
1969         final ActivityStack stack = getActivityStack();
1970         if (stack == null) {
1971             return false;
1972         }
1973 
1974         // Whether the activity is on the sleeping display.
1975         // TODO(b/129750406): This should be applied for the default display, too.
1976         final boolean isDisplaySleeping = getDisplay().isSleeping()
1977                 && getDisplayId() != DEFAULT_DISPLAY;
1978         // Whether this activity is the top activity of this stack.
1979         final boolean isTop = this == stack.getTopActivity();
1980         // Exclude the case where this is the top activity in a pinned stack.
1981         final boolean isTopNotPinnedStack = stack.isAttached()
1982                 && stack.getDisplay().isTopNotPinnedStack(stack);
1983         // Now check whether it's really visible depending on Keyguard state, and update
1984         // {@link ActivityStack} internal states.
1985         final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
1986                 visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
1987         return visibleIgnoringDisplayStatus && !isDisplaySleeping;
1988     }
1989 
shouldBeVisible()1990     boolean shouldBeVisible() {
1991         final ActivityStack stack = getActivityStack();
1992         if (stack == null) {
1993             return false;
1994         }
1995 
1996         // TODO: Use real value of behindFullscreenActivity calculated using the same logic in
1997         // ActivityStack#ensureActivitiesVisibleLocked().
1998         return shouldBeVisible(!stack.shouldBeVisible(null /* starting */));
1999     }
2000 
makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient)2001     void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) {
2002         // This activity is not currently visible, but is running. Tell it to become visible.
2003         if (mState == RESUMED || this == starting) {
2004             if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
2005                     "Not making visible, r=" + this + " state=" + mState + " starting=" + starting);
2006             return;
2007         }
2008 
2009         // If this activity is paused, tell it to now show its window.
2010         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
2011                 "Making visible and scheduling visibility: " + this);
2012         final ActivityStack stack = getActivityStack();
2013         try {
2014             if (stack.mTranslucentActivityWaiting != null) {
2015                 updateOptionsLocked(returningOptions);
2016                 stack.mUndrawnActivitiesBelowTopTranslucent.add(this);
2017             }
2018             setVisible(true);
2019             sleeping = false;
2020             app.postPendingUiCleanMsg(true);
2021             if (reportToClient) {
2022                 makeClientVisible();
2023             } else {
2024                 mClientVisibilityDeferred = true;
2025             }
2026             // The activity may be waiting for stop, but that is no longer appropriate for it.
2027             mStackSupervisor.mStoppingActivities.remove(this);
2028             mStackSupervisor.mGoingToSleepActivities.remove(this);
2029         } catch (Exception e) {
2030             // Just skip on any failure; we'll make it visible when it next restarts.
2031             Slog.w(TAG, "Exception thrown making visible: " + intent.getComponent(), e);
2032         }
2033         handleAlreadyVisible();
2034     }
2035 
2036     /** Send visibility change message to the client and pause if needed. */
makeClientVisible()2037     void makeClientVisible() {
2038         mClientVisibilityDeferred = false;
2039         try {
2040             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
2041                     WindowVisibilityItem.obtain(true /* showWindow */));
2042             makeActiveIfNeeded(null /* activeActivity*/);
2043             if (isState(STOPPING, STOPPED) && isFocusable()) {
2044                 // #shouldMakeActive() only evaluates the topmost activities in task, so
2045                 // activities that are not the topmost in task are not being resumed or paused.
2046                 // For activities that are still in STOPPING or STOPPED state, updates the state
2047                 // to PAUSE at least when making it visible.
2048                 setState(PAUSED, "makeClientVisible");
2049             }
2050         } catch (Exception e) {
2051             Slog.w(TAG, "Exception thrown sending visibility update: " + intent.getComponent(), e);
2052         }
2053     }
2054 
2055     /**
2056      * Make activity resumed or paused if needed.
2057      * @param activeActivity an activity that is resumed or just completed pause action.
2058      *                       We won't change the state of this activity.
2059      */
makeActiveIfNeeded(ActivityRecord activeActivity)2060     boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
2061         if (shouldResumeActivity(activeActivity)) {
2062             if (DEBUG_VISIBILITY) {
2063                 Slog.v("TAG_VISIBILITY", "Resume visible activity, " + this);
2064             }
2065             return getActivityStack().resumeTopActivityUncheckedLocked(activeActivity /* prev */,
2066                     null /* options */);
2067         } else if (shouldPauseActivity(activeActivity)) {
2068             if (DEBUG_VISIBILITY) {
2069                 Slog.v("TAG_VISIBILITY", "Pause visible activity, " + this);
2070             }
2071             // An activity must be in the {@link PAUSING} state for the system to validate
2072             // the move to {@link PAUSED}.
2073             setState(PAUSING, "makeVisibleIfNeeded");
2074             try {
2075                 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
2076                         PauseActivityItem.obtain(finishing, false /* userLeaving */,
2077                                 configChangeFlags, false /* dontReport */));
2078             } catch (Exception e) {
2079                 Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
2080             }
2081         }
2082         return false;
2083     }
2084 
2085     /**
2086      * Check if activity should be moved to PAUSED state. The activity:
2087      * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
2088      * - should be non-focusable
2089      * - should not be currently pausing or paused
2090      * @param activeActivity the activity that is active or just completed pause action. We won't
2091      *                       resume if this activity is active.
2092      */
shouldPauseActivity(ActivityRecord activeActivity)2093     private boolean shouldPauseActivity(ActivityRecord activeActivity) {
2094         return shouldMakeActive(activeActivity) && !isFocusable() && !isState(PAUSING, PAUSED);
2095     }
2096 
2097     /**
2098      * Check if activity should be moved to RESUMED state. The activity:
2099      * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
2100      * - should be focusable
2101      * @param activeActivity the activity that is active or just completed pause action. We won't
2102      *                       resume if this activity is active.
2103      */
2104     @VisibleForTesting
shouldResumeActivity(ActivityRecord activeActivity)2105     boolean shouldResumeActivity(ActivityRecord activeActivity) {
2106         return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED)
2107                 && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE;
2108     }
2109 
2110     /**
2111      * Check if activity is eligible to be made active (resumed of paused). The activity:
2112      * - should be paused, stopped or stopping
2113      * - should not be the currently active one or launching behind other tasks
2114      * - should be either the topmost in task, or right below the top activity that is finishing
2115      * If all of these conditions are not met at the same time, the activity cannot be made active.
2116      */
2117     @VisibleForTesting
shouldMakeActive(ActivityRecord activeActivity)2118     boolean shouldMakeActive(ActivityRecord activeActivity) {
2119         // If the activity is stopped, stopping, cycle to an active state. We avoid doing
2120         // this when there is an activity waiting to become translucent as the extra binder
2121         // calls will lead to noticeable jank. A later call to
2122         // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to a proper
2123         // active state.
2124         if (!isState(RESUMED, PAUSED, STOPPED, STOPPING)
2125                 || getActivityStack().mTranslucentActivityWaiting != null) {
2126             return false;
2127         }
2128 
2129         if (this == activeActivity) {
2130             return false;
2131         }
2132 
2133         if (!mStackSupervisor.readyToResume()) {
2134             // Making active is currently deferred (e.g. because an activity launch is in progress).
2135             return false;
2136         }
2137 
2138         if (this.mLaunchTaskBehind) {
2139             // This activity is being launched from behind, which means that it's not intended to be
2140             // presented to user right now, even if it's set to be visible.
2141             return false;
2142         }
2143 
2144         // Check if position in task allows to become paused
2145         final int positionInTask = task.mActivities.indexOf(this);
2146         if (positionInTask == -1) {
2147             throw new IllegalStateException("Activity not found in its task");
2148         }
2149         if (positionInTask == task.mActivities.size() - 1) {
2150             // It's the topmost activity in the task - should become resumed now
2151             return true;
2152         }
2153         // Check if activity above is finishing now and this one becomes the topmost in task.
2154         final ActivityRecord activityAbove = task.mActivities.get(positionInTask + 1);
2155         if (activityAbove.finishing && results == null) {
2156             // We will only allow making active if activity above wasn't launched for result.
2157             // Otherwise it will cause this activity to resume before getting result.
2158             return true;
2159         }
2160         return false;
2161     }
2162 
handleAlreadyVisible()2163     boolean handleAlreadyVisible() {
2164         stopFreezingScreenLocked(false);
2165         try {
2166             if (returningOptions != null) {
2167                 app.getThread().scheduleOnNewActivityOptions(appToken, returningOptions.toBundle());
2168             }
2169         } catch(RemoteException e) {
2170         }
2171         return mState == RESUMED;
2172     }
2173 
activityResumedLocked(IBinder token)2174     static void activityResumedLocked(IBinder token) {
2175         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2176         if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
2177         if (r == null) {
2178             // If an app reports resumed after a long delay, the record on server side might have
2179             // been removed (e.g. destroy timeout), so the token could be null.
2180             return;
2181         }
2182         r.icicle = null;
2183         r.haveState = false;
2184 
2185         final ActivityDisplay display = r.getDisplay();
2186         if (display != null) {
2187             display.handleActivitySizeCompatModeIfNeeded(r);
2188         }
2189     }
2190 
2191     /**
2192      * Once we know that we have asked an application to put an activity in the resumed state
2193      * (either by launching it or explicitly telling it), this function updates the rest of our
2194      * state to match that fact.
2195      */
completeResumeLocked()2196     void completeResumeLocked() {
2197         final boolean wasVisible = visible;
2198         setVisible(true);
2199         if (!wasVisible) {
2200             // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
2201             mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
2202         }
2203         idle = false;
2204         results = null;
2205         newIntents = null;
2206         stopped = false;
2207 
2208         if (isActivityTypeHome()) {
2209             mStackSupervisor.updateHomeProcess(task.mActivities.get(0).app);
2210         }
2211 
2212         if (nowVisible) {
2213             mStackSupervisor.stopWaitingForActivityVisible(this);
2214         }
2215 
2216         // Schedule an idle timeout in case the app doesn't do it for us.
2217         mStackSupervisor.scheduleIdleTimeoutLocked(this);
2218 
2219         mStackSupervisor.reportResumedActivityLocked(this);
2220 
2221         resumeKeyDispatchingLocked();
2222         final ActivityStack stack = getActivityStack();
2223         mStackSupervisor.mNoAnimActivities.clear();
2224 
2225         // Mark the point when the activity is resuming
2226         // TODO: To be more accurate, the mark should be before the onCreate,
2227         //       not after the onResume. But for subsequent starts, onResume is fine.
2228         if (hasProcess()) {
2229             cpuTimeAtResume = app.getCpuTime();
2230         } else {
2231             cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2232         }
2233 
2234         returningOptions = null;
2235 
2236         if (canTurnScreenOn()) {
2237             mStackSupervisor.wakeUp("turnScreenOnFlag");
2238         } else {
2239             // If the screen is going to turn on because the caller explicitly requested it and
2240             // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will
2241             // pause and then resume again later, which will result in a double life-cycle event.
2242             stack.checkReadyForSleep();
2243         }
2244     }
2245 
activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState, CharSequence description)2246     final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
2247             CharSequence description) {
2248         final ActivityStack stack = getActivityStack();
2249         final boolean isStopping = mState == STOPPING;
2250         if (!isStopping && mState != RESTARTING_PROCESS) {
2251             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
2252             stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
2253             return;
2254         }
2255         if (newPersistentState != null) {
2256             persistentState = newPersistentState;
2257             mAtmService.notifyTaskPersisterLocked(task, false);
2258         }
2259         if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + icicle);
2260 
2261         if (newIcicle != null) {
2262             // If icicle is null, this is happening due to a timeout, so we haven't really saved
2263             // the state.
2264             icicle = newIcicle;
2265             haveState = true;
2266             launchCount = 0;
2267             updateTaskDescription(description);
2268         }
2269         if (!stopped) {
2270             if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
2271             stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
2272             stopped = true;
2273             if (isStopping) {
2274                 setState(STOPPED, "activityStoppedLocked");
2275             }
2276 
2277             if (mAppWindowToken != null) {
2278                 mAppWindowToken.notifyAppStopped();
2279             }
2280 
2281             if (finishing) {
2282                 clearOptionsLocked();
2283             } else {
2284                 if (deferRelaunchUntilPaused) {
2285                     stack.destroyActivityLocked(this, true /* removeFromApp */, "stop-config");
2286                     mRootActivityContainer.resumeFocusedStacksTopActivities();
2287                 } else {
2288                     mRootActivityContainer.updatePreviousProcess(this);
2289                 }
2290             }
2291         }
2292     }
2293 
startLaunchTickingLocked()2294     void startLaunchTickingLocked() {
2295         if (Build.IS_USER) {
2296             return;
2297         }
2298         if (launchTickTime == 0) {
2299             launchTickTime = SystemClock.uptimeMillis();
2300             continueLaunchTickingLocked();
2301         }
2302     }
2303 
continueLaunchTickingLocked()2304     boolean continueLaunchTickingLocked() {
2305         if (launchTickTime == 0) {
2306             return false;
2307         }
2308 
2309         final ActivityStack stack = getActivityStack();
2310         if (stack == null) {
2311             return false;
2312         }
2313 
2314         Message msg = stack.mHandler.obtainMessage(LAUNCH_TICK_MSG, this);
2315         stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
2316         stack.mHandler.sendMessageDelayed(msg, LAUNCH_TICK);
2317         return true;
2318     }
2319 
finishLaunchTickingLocked()2320     void finishLaunchTickingLocked() {
2321         launchTickTime = 0;
2322         final ActivityStack stack = getActivityStack();
2323         if (stack != null) {
2324             stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
2325         }
2326     }
2327 
2328     // IApplicationToken
2329 
mayFreezeScreenLocked(WindowProcessController app)2330     public boolean mayFreezeScreenLocked(WindowProcessController app) {
2331         // Only freeze the screen if this activity is currently attached to
2332         // an application, and that application is not blocked or unresponding.
2333         // In any other case, we can't count on getting the screen unfrozen,
2334         // so it is best to leave as-is.
2335         return hasProcess() && !app.isCrashing() && !app.isNotResponding();
2336     }
2337 
startFreezingScreenLocked(WindowProcessController app, int configChanges)2338     public void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
2339         if (mayFreezeScreenLocked(app)) {
2340             if (mAppWindowToken == null) {
2341                 Slog.w(TAG_WM,
2342                         "Attempted to freeze screen with non-existing app token: " + appToken);
2343                 return;
2344             }
2345 
2346             // Window configuration changes only effect windows, so don't require a screen freeze.
2347             int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION);
2348             if (freezableConfigChanges == 0 && mAppWindowToken.okToDisplay()) {
2349                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + appToken);
2350                 return;
2351             }
2352 
2353             mAppWindowToken.startFreezingScreen();
2354         }
2355     }
2356 
stopFreezingScreenLocked(boolean force)2357     public void stopFreezingScreenLocked(boolean force) {
2358         if (force || frozenBeforeDestroy) {
2359             frozenBeforeDestroy = false;
2360             if (mAppWindowToken == null) {
2361                 return;
2362             }
2363             if (DEBUG_ORIENTATION) {
2364                 Slog.v(TAG_WM, "Clear freezing of " + appToken + ": hidden="
2365                         + mAppWindowToken.isHidden() + " freezing="
2366                         + mAppWindowToken.isFreezingScreen());
2367             }
2368             mAppWindowToken.stopFreezingScreen(true, force);
2369         }
2370     }
2371 
reportFullyDrawnLocked(boolean restoredFromBundle)2372     public void reportFullyDrawnLocked(boolean restoredFromBundle) {
2373         final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
2374                 .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
2375         if (info != null) {
2376             mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
2377                     info.windowsFullyDrawnDelayMs, info.getLaunchState());
2378         }
2379     }
2380 
2381     /**
2382      * Called when the starting window for this container is drawn.
2383      */
onStartingWindowDrawn(long timestamp)2384     public void onStartingWindowDrawn(long timestamp) {
2385         synchronized (mAtmService.mGlobalLock) {
2386             mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
2387                     getWindowingMode(), timestamp);
2388         }
2389     }
2390 
2391     /** Called when the windows associated app window container are drawn. */
onWindowsDrawn(boolean drawn, long timestamp)2392     public void onWindowsDrawn(boolean drawn, long timestamp) {
2393         synchronized (mAtmService.mGlobalLock) {
2394             mDrawn = drawn;
2395             if (!drawn) {
2396                 return;
2397             }
2398             final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
2399                     .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
2400             final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
2401             final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
2402             mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
2403                     windowsDrawnDelayMs, launchState);
2404             mStackSupervisor.stopWaitingForActivityVisible(this);
2405             finishLaunchTickingLocked();
2406             if (task != null) {
2407                 task.hasBeenVisible = true;
2408             }
2409         }
2410     }
2411 
2412     /** Called when the windows associated app window container are visible. */
onWindowsVisible()2413     public void onWindowsVisible() {
2414         synchronized (mAtmService.mGlobalLock) {
2415             mStackSupervisor.stopWaitingForActivityVisible(this);
2416             if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
2417             if (!nowVisible) {
2418                 nowVisible = true;
2419                 lastVisibleTime = SystemClock.uptimeMillis();
2420                 mAtmService.scheduleAppGcsLocked();
2421             }
2422         }
2423     }
2424 
2425     /** Called when the windows associated app window container are no longer visible. */
onWindowsGone()2426     public void onWindowsGone() {
2427         synchronized (mAtmService.mGlobalLock) {
2428             if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
2429             nowVisible = false;
2430         }
2431     }
2432 
onAnimationFinished()2433     void onAnimationFinished() {
2434         if (mRootActivityContainer.allResumedActivitiesIdle()
2435                 || mStackSupervisor.isStoppingNoHistoryActivity()) {
2436             // If all activities are already idle or there is an activity that must be
2437             // stopped immediately after visible, then we now need to make sure we perform
2438             // the full stop of this activity. This is because we won't do that while they are still
2439             // waiting for the animation to finish.
2440             if (mStackSupervisor.mStoppingActivities.contains(this)) {
2441                 mStackSupervisor.scheduleIdleLocked();
2442             }
2443         } else {
2444             // Instead of doing the full stop routine here, let's just hide any activities
2445             // we now can, and let them stop when the normal idle happens.
2446             mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
2447                     false /* remove */, true /* processPausingActivities */);
2448         }
2449     }
2450 
2451     /**
2452      * Called when the key dispatching to a window associated with the app window container
2453      * timed-out.
2454      *
2455      * @param reason The reason for the key dispatching time out.
2456      * @param windowPid The pid of the window key dispatching timed out on.
2457      * @return True if input dispatching should be aborted.
2458      */
keyDispatchingTimedOut(String reason, int windowPid)2459     public boolean keyDispatchingTimedOut(String reason, int windowPid) {
2460         ActivityRecord anrActivity;
2461         WindowProcessController anrApp;
2462         boolean windowFromSameProcessAsActivity;
2463         synchronized (mAtmService.mGlobalLock) {
2464             anrActivity = getWaitingHistoryRecordLocked();
2465             anrApp = app;
2466             windowFromSameProcessAsActivity =
2467                     !hasProcess() || app.getPid() == windowPid || windowPid == -1;
2468         }
2469 
2470         if (windowFromSameProcessAsActivity) {
2471             return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
2472                     anrActivity.shortComponentName, anrActivity.appInfo, shortComponentName,
2473                     app, false, reason);
2474         } else {
2475             // In this case another process added windows using this activity token. So, we call the
2476             // generic service input dispatch timed out method so that the right process is blamed.
2477             return mAtmService.mAmInternal.inputDispatchingTimedOut(
2478                     windowPid, false /* aboveSystem */, reason) < 0;
2479         }
2480     }
2481 
getWaitingHistoryRecordLocked()2482     private ActivityRecord getWaitingHistoryRecordLocked() {
2483         // First find the real culprit...  if this activity has stopped, then the key dispatching
2484         // timeout should not be caused by this.
2485         if (stopped) {
2486             final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
2487             // Try to use the one which is closest to top.
2488             ActivityRecord r = stack.getResumedActivity();
2489             if (r == null) {
2490                 r = stack.mPausingActivity;
2491             }
2492             if (r != null) {
2493                 return r;
2494             }
2495         }
2496         return this;
2497     }
2498 
2499     /** Checks whether the activity should be shown for current user. */
okToShowLocked()2500     public boolean okToShowLocked() {
2501         // We cannot show activities when the device is locked and the application is not
2502         // encryption aware.
2503         if (!StorageManager.isUserKeyUnlocked(mUserId)
2504                 && !info.applicationInfo.isEncryptionAware()) {
2505             return false;
2506         }
2507 
2508         return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
2509                 || (mStackSupervisor.isCurrentProfileLocked(mUserId)
2510                 && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
2511     }
2512 
2513     /**
2514      * This method will return true if the activity is either visible, is becoming visible, is
2515      * currently pausing, or is resumed.
2516      */
isInterestingToUserLocked()2517     public boolean isInterestingToUserLocked() {
2518         return visible || nowVisible || mState == PAUSING || mState == RESUMED;
2519     }
2520 
setSleeping(boolean _sleeping)2521     void setSleeping(boolean _sleeping) {
2522         setSleeping(_sleeping, false);
2523     }
2524 
setSleeping(boolean _sleeping, boolean force)2525     void setSleeping(boolean _sleeping, boolean force) {
2526         if (!force && sleeping == _sleeping) {
2527             return;
2528         }
2529         if (attachedToProcess()) {
2530             try {
2531                 app.getThread().scheduleSleeping(appToken, _sleeping);
2532                 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
2533                     mStackSupervisor.mGoingToSleepActivities.add(this);
2534                 }
2535                 sleeping = _sleeping;
2536             } catch (RemoteException e) {
2537                 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
2538             }
2539         }
2540     }
2541 
getTaskForActivityLocked(IBinder token, boolean onlyRoot)2542     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
2543         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2544         if (r == null) {
2545             return INVALID_TASK_ID;
2546         }
2547         final TaskRecord task = r.task;
2548         final int activityNdx = task.mActivities.indexOf(r);
2549         if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) {
2550             return INVALID_TASK_ID;
2551         }
2552         return task.taskId;
2553     }
2554 
isInStackLocked(IBinder token)2555     static ActivityRecord isInStackLocked(IBinder token) {
2556         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2557         return (r != null) ? r.getActivityStack().isInStackLocked(r) : null;
2558     }
2559 
getStackLocked(IBinder token)2560     static ActivityStack getStackLocked(IBinder token) {
2561         final ActivityRecord r = ActivityRecord.isInStackLocked(token);
2562         if (r != null) {
2563             return r.getActivityStack();
2564         }
2565         return null;
2566     }
2567 
2568     /**
2569      * @return display id to which this record is attached,
2570      *         {@link android.view.Display#INVALID_DISPLAY} if not attached.
2571      */
getDisplayId()2572     int getDisplayId() {
2573         final ActivityStack stack = getActivityStack();
2574         if (stack == null) {
2575             return INVALID_DISPLAY;
2576         }
2577         return stack.mDisplayId;
2578     }
2579 
isDestroyable()2580     final boolean isDestroyable() {
2581         if (finishing || !hasProcess()) {
2582             // This would be redundant.
2583             return false;
2584         }
2585         final ActivityStack stack = getActivityStack();
2586         if (stack == null || this == stack.getResumedActivity() || this == stack.mPausingActivity
2587                 || !haveState || !stopped) {
2588             // We're not ready for this kind of thing.
2589             return false;
2590         }
2591         if (visible) {
2592             // The user would notice this!
2593             return false;
2594         }
2595         return true;
2596     }
2597 
createImageFilename(long createTime, int taskId)2598     private static String createImageFilename(long createTime, int taskId) {
2599         return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
2600                 IMAGE_EXTENSION;
2601     }
2602 
setTaskDescription(TaskDescription _taskDescription)2603     void setTaskDescription(TaskDescription _taskDescription) {
2604         Bitmap icon;
2605         if (_taskDescription.getIconFilename() == null &&
2606                 (icon = _taskDescription.getIcon()) != null) {
2607             final String iconFilename = createImageFilename(createTime, task.taskId);
2608             final File iconFile = new File(TaskPersister.getUserImagesDir(task.userId),
2609                     iconFilename);
2610             final String iconFilePath = iconFile.getAbsolutePath();
2611             mAtmService.getRecentTasks().saveImage(icon, iconFilePath);
2612             _taskDescription.setIconFilename(iconFilePath);
2613         }
2614         taskDescription = _taskDescription;
2615     }
2616 
setVoiceSessionLocked(IVoiceInteractionSession session)2617     void setVoiceSessionLocked(IVoiceInteractionSession session) {
2618         voiceSession = session;
2619         pendingVoiceInteractionStart = false;
2620     }
2621 
clearVoiceSessionLocked()2622     void clearVoiceSessionLocked() {
2623         voiceSession = null;
2624         pendingVoiceInteractionStart = false;
2625     }
2626 
showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch)2627     void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) {
2628         showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */);
2629     }
2630 
showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch, boolean fromRecents)2631     void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
2632             boolean fromRecents) {
2633         if (mAppWindowToken == null) {
2634             return;
2635         }
2636         if (mTaskOverlay) {
2637             // We don't show starting window for overlay activities.
2638             return;
2639         }
2640         if (pendingOptions != null
2641                 && pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
2642             // Don't show starting window when using shared element transition.
2643             return;
2644         }
2645 
2646         final CompatibilityInfo compatInfo =
2647                 mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo);
2648         final boolean shown = addStartingWindow(packageName, theme,
2649                 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2650                 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
2651                 allowTaskSnapshot(),
2652                 mState.ordinal() >= RESUMED.ordinal() && mState.ordinal() <= STOPPED.ordinal(),
2653                 fromRecents);
2654         if (shown) {
2655             mStartingWindowState = STARTING_WINDOW_SHOWN;
2656         }
2657     }
2658 
removeOrphanedStartingWindow(boolean behindFullscreenActivity)2659     void removeOrphanedStartingWindow(boolean behindFullscreenActivity) {
2660         if (mStartingWindowState == STARTING_WINDOW_SHOWN && behindFullscreenActivity) {
2661             if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
2662             mStartingWindowState = STARTING_WINDOW_REMOVED;
2663             mAppWindowToken.removeStartingWindow();
2664         }
2665     }
2666 
setRequestedOrientation(int requestedOrientation)2667     void setRequestedOrientation(int requestedOrientation) {
2668         setOrientation(requestedOrientation, mayFreezeScreenLocked(app));
2669         mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
2670                 task.taskId, requestedOrientation);
2671     }
2672 
setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded)2673     private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
2674         if (mAppWindowToken == null) {
2675             Slog.w(TAG_WM,
2676                     "Attempted to set orientation of non-existing app token: " + appToken);
2677             return;
2678         }
2679 
2680         final IBinder binder =
2681                 (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
2682         mAppWindowToken.setOrientation(requestedOrientation, binder, this);
2683 
2684         // Push the new configuration to the requested app in case where it's not pushed, e.g. when
2685         // the request is handled at task level with letterbox.
2686         if (!getMergedOverrideConfiguration().equals(
2687                 mLastReportedConfiguration.getMergedConfiguration())) {
2688             ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
2689         }
2690     }
2691 
getOrientation()2692     int getOrientation() {
2693         if (mAppWindowToken == null) {
2694             return info.screenOrientation;
2695         }
2696 
2697         return mAppWindowToken.getOrientationIgnoreVisibility();
2698     }
2699 
setDisablePreviewScreenshots(boolean disable)2700     void setDisablePreviewScreenshots(boolean disable) {
2701         if (mAppWindowToken == null) {
2702             Slog.w(TAG_WM, "Attempted to set disable screenshots of non-existing app"
2703                     + " token: " + appToken);
2704             return;
2705         }
2706         mAppWindowToken.setDisablePreviewScreenshots(disable);
2707     }
2708 
2709     /**
2710      * Set the last reported global configuration to the client. Should be called whenever a new
2711      * global configuration is sent to the client for this activity.
2712      */
setLastReportedGlobalConfiguration(@onNull Configuration config)2713     void setLastReportedGlobalConfiguration(@NonNull Configuration config) {
2714         mLastReportedConfiguration.setGlobalConfiguration(config);
2715     }
2716 
2717     /**
2718      * Set the last reported configuration to the client. Should be called whenever
2719      * a new merged configuration is sent to the client for this activity.
2720      */
setLastReportedConfiguration(@onNull MergedConfiguration config)2721     void setLastReportedConfiguration(@NonNull MergedConfiguration config) {
2722         setLastReportedConfiguration(config.getGlobalConfiguration(),
2723             config.getOverrideConfiguration());
2724     }
2725 
setLastReportedConfiguration(Configuration global, Configuration override)2726     private void setLastReportedConfiguration(Configuration global, Configuration override) {
2727         mLastReportedConfiguration.setConfiguration(global, override);
2728     }
2729 
2730     /**
2731      * Get the configuration orientation by the requested screen orientation
2732      * ({@link ActivityInfo.ScreenOrientation}) of this activity.
2733      *
2734      * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
2735      *         {@link Configuration#ORIENTATION_PORTRAIT},
2736      *         {@link Configuration#ORIENTATION_UNDEFINED}).
2737      */
getRequestedConfigurationOrientation()2738     int getRequestedConfigurationOrientation() {
2739         final int screenOrientation = getOrientation();
2740         if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
2741             // NOSENSOR means the display's "natural" orientation, so return that.
2742             final ActivityDisplay display = getDisplay();
2743             if (display != null && display.mDisplayContent != null) {
2744                 return display.mDisplayContent.getNaturalOrientation();
2745             }
2746         } else if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
2747             // LOCKED means the activity's orientation remains unchanged, so return existing value.
2748             return getConfiguration().orientation;
2749         } else if (isFixedOrientationLandscape(screenOrientation)) {
2750             return ORIENTATION_LANDSCAPE;
2751         } else if (isFixedOrientationPortrait(screenOrientation)) {
2752             return ORIENTATION_PORTRAIT;
2753         }
2754         return ORIENTATION_UNDEFINED;
2755     }
2756 
2757     /**
2758      * @return {@code true} if this activity is in size compatibility mode that uses the different
2759      *         density or bounds from its parent.
2760      */
inSizeCompatMode()2761     boolean inSizeCompatMode() {
2762         if (!shouldUseSizeCompatMode()) {
2763             return false;
2764         }
2765         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
2766         final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
2767         if (resolvedAppBounds == null) {
2768             // The override configuration has not been resolved yet.
2769             return false;
2770         }
2771 
2772         final Configuration parentConfig = getParent().getConfiguration();
2773         // Although colorMode, screenLayout, smallestScreenWidthDp are also fixed, generally these
2774         // fields should be changed with density and bounds, so here only compares the most
2775         // significant field.
2776         if (parentConfig.densityDpi != resolvedConfig.densityDpi) {
2777             return true;
2778         }
2779 
2780         final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
2781         final int appWidth = resolvedAppBounds.width();
2782         final int appHeight = resolvedAppBounds.height();
2783         final int parentAppWidth = parentAppBounds.width();
2784         final int parentAppHeight = parentAppBounds.height();
2785         if (parentAppWidth == appWidth && parentAppHeight == appHeight) {
2786             // Matched the parent bounds.
2787             return false;
2788         }
2789         if (parentAppWidth > appWidth && parentAppHeight > appHeight) {
2790             // Both sides are smaller than the parent.
2791             return true;
2792         }
2793         if (parentAppWidth < appWidth || parentAppHeight < appHeight) {
2794             // One side is larger than the parent.
2795             return true;
2796         }
2797 
2798         // The rest of the condition is that only one side is smaller than the parent, but it still
2799         // needs to exclude the cases where the size is limited by the fixed aspect ratio.
2800         if (info.maxAspectRatio > 0) {
2801             final float aspectRatio = (0.5f + Math.max(appWidth, appHeight))
2802                     / Math.min(appWidth, appHeight);
2803             if (aspectRatio >= info.maxAspectRatio) {
2804                 // The current size has reached the max aspect ratio.
2805                 return false;
2806             }
2807         }
2808         if (info.minAspectRatio > 0) {
2809             // The activity should have at least the min aspect ratio, so this checks if the parent
2810             // still has available space to provide larger aspect ratio.
2811             final float parentAspectRatio = (0.5f + Math.max(parentAppWidth, parentAppHeight))
2812                     / Math.min(parentAppWidth, parentAppHeight);
2813             if (parentAspectRatio <= info.minAspectRatio) {
2814                 // The long side has reached the parent.
2815                 return false;
2816             }
2817         }
2818         return true;
2819     }
2820 
2821     /**
2822      * Indicates the activity will keep the bounds and screen configuration when it was first
2823      * launched, no matter how its parent changes.
2824      *
2825      * @return {@code true} if this activity is declared as non-resizable and fixed orientation or
2826      *         aspect ratio.
2827      */
shouldUseSizeCompatMode()2828     boolean shouldUseSizeCompatMode() {
2829         return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
2830                 // The configuration of non-standard type should be enforced by system.
2831                 && isActivityTypeStandard()
2832                 && !mAtmService.mForceResizableActivities;
2833     }
2834 
2835     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
updateOverrideConfiguration()2836     private void updateOverrideConfiguration() {
2837         final Configuration overrideConfig = mTmpConfig;
2838         if (shouldUseSizeCompatMode()) {
2839             if (mCompatDisplayInsets != null) {
2840                 // The override configuration is set only once in size compatibility mode.
2841                 return;
2842             }
2843             final Configuration parentConfig = getParent().getConfiguration();
2844             if (!hasProcess() && !isConfigurationCompatible(parentConfig)) {
2845                 // Don't compute when launching in fullscreen and the fixed orientation is not the
2846                 // current orientation. It is more accurately to compute the override bounds from
2847                 // the updated configuration after the fixed orientation is applied.
2848                 return;
2849             }
2850 
2851             // Ensure the screen related fields are set. It is used to prevent activity relaunch
2852             // when moving between displays. For screenWidthDp and screenWidthDp, because they
2853             // are relative to bounds and density, they will be calculated in
2854             // {@link TaskRecord#computeConfigResourceOverrides} and the result will also be
2855             // relatively fixed.
2856             overrideConfig.unset();
2857             overrideConfig.colorMode = parentConfig.colorMode;
2858             overrideConfig.densityDpi = parentConfig.densityDpi;
2859             overrideConfig.screenLayout = parentConfig.screenLayout
2860                     & (Configuration.SCREENLAYOUT_LONG_MASK
2861                             | Configuration.SCREENLAYOUT_SIZE_MASK);
2862             // The smallest screen width is the short side of screen bounds. Because the bounds
2863             // and density won't be changed, smallestScreenWidthDp is also fixed.
2864             overrideConfig.smallestScreenWidthDp = parentConfig.smallestScreenWidthDp;
2865 
2866             // The role of CompatDisplayInsets is like the override bounds.
2867             final ActivityDisplay display = getDisplay();
2868             if (display != null && display.mDisplayContent != null) {
2869                 mCompatDisplayInsets = new CompatDisplayInsets(display.mDisplayContent);
2870             }
2871         } else {
2872             // We must base this on the parent configuration, because we set our override
2873             // configuration's appBounds based on the result of this method. If we used our own
2874             // configuration, it would be influenced by past invocations.
2875             computeBounds(mTmpBounds, getParent().getWindowConfiguration().getAppBounds());
2876 
2877             if (mTmpBounds.equals(getRequestedOverrideBounds())) {
2878                 // The bounds is not changed or the activity is resizable (both the 2 bounds are
2879                 // empty).
2880                 return;
2881             }
2882 
2883             overrideConfig.unset();
2884             overrideConfig.windowConfiguration.setBounds(mTmpBounds);
2885         }
2886 
2887         onRequestedOverrideConfigurationChanged(overrideConfig);
2888     }
2889 
2890     @Override
resolveOverrideConfiguration(Configuration newParentConfiguration)2891     void resolveOverrideConfiguration(Configuration newParentConfiguration) {
2892         if (mCompatDisplayInsets != null) {
2893             resolveSizeCompatModeConfiguration(newParentConfiguration);
2894         } else {
2895             super.resolveOverrideConfiguration(newParentConfiguration);
2896             // If the activity has override bounds, the relative configuration (e.g. screen size,
2897             // layout) needs to be resolved according to the bounds.
2898             if (!matchParentBounds()) {
2899                 task.computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
2900                         newParentConfiguration);
2901             }
2902         }
2903 
2904         // Assign configuration sequence number into hierarchy because there is a different way than
2905         // ensureActivityConfiguration() in this class that uses configuration in WindowState during
2906         // layout traversals.
2907         mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
2908         getResolvedOverrideConfiguration().seq = mConfigurationSeq;
2909     }
2910 
2911     /**
2912      * Resolves consistent screen configuration for orientation and rotation changes without
2913      * inheriting the parent bounds.
2914      */
resolveSizeCompatModeConfiguration(Configuration newParentConfiguration)2915     private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
2916         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
2917         final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
2918 
2919         final int parentRotation = newParentConfiguration.windowConfiguration.getRotation();
2920         final int parentOrientation = newParentConfiguration.orientation;
2921         int orientation = getConfiguration().orientation;
2922         if (orientation != parentOrientation && isConfigurationCompatible(newParentConfiguration)) {
2923             // The activity is compatible to apply the orientation change or it requests different
2924             // fixed orientation.
2925             orientation = parentOrientation;
2926         } else {
2927             if (!resolvedBounds.isEmpty()
2928                     // The decor insets may be different according to the rotation.
2929                     && getWindowConfiguration().getRotation() == parentRotation) {
2930                 // Keep the computed resolved override configuration.
2931                 return;
2932             }
2933             final int requestedOrientation = getRequestedConfigurationOrientation();
2934             if (requestedOrientation != ORIENTATION_UNDEFINED) {
2935                 orientation = requestedOrientation;
2936             }
2937         }
2938 
2939         super.resolveOverrideConfiguration(newParentConfiguration);
2940 
2941         boolean useParentOverrideBounds = false;
2942         final Rect displayBounds = mTmpBounds;
2943         final Rect containingAppBounds = new Rect();
2944         if (task.handlesOrientationChangeFromDescendant()) {
2945             // Prefer to use the orientation which is determined by this activity to calculate
2946             // bounds because the parent will follow the requested orientation.
2947             mCompatDisplayInsets.getDisplayBoundsByOrientation(displayBounds, orientation);
2948         } else {
2949             // The parent hierarchy doesn't handle the orientation changes. This is usually because
2950             // the aspect ratio of display is close to square or the display rotation is fixed.
2951             // In this case, task will compute override bounds to fit the app with respect to the
2952             // requested orientation. So here we perform similar calculation to have consistent
2953             // bounds even the original parent hierarchies were changed.
2954             final int baseOrientation = task.getParent().getConfiguration().orientation;
2955             mCompatDisplayInsets.getDisplayBoundsByOrientation(displayBounds, baseOrientation);
2956             task.computeFullscreenBounds(containingAppBounds, this, displayBounds, baseOrientation);
2957             useParentOverrideBounds = !containingAppBounds.isEmpty();
2958         }
2959 
2960         // The offsets will be non-zero if the parent has override bounds.
2961         final int containingOffsetX = containingAppBounds.left;
2962         final int containingOffsetY = containingAppBounds.top;
2963         if (!useParentOverrideBounds) {
2964             containingAppBounds.set(displayBounds);
2965         }
2966         if (parentRotation != ROTATION_UNDEFINED) {
2967             // Ensure the container bounds won't overlap with the decors.
2968             TaskRecord.intersectWithInsetsIfFits(containingAppBounds, displayBounds,
2969                     mCompatDisplayInsets.mNonDecorInsets[parentRotation]);
2970         }
2971 
2972         computeBounds(resolvedBounds, containingAppBounds);
2973         if (resolvedBounds.isEmpty()) {
2974             // Use the entire available bounds because there is no restriction.
2975             resolvedBounds.set(useParentOverrideBounds ? containingAppBounds : displayBounds);
2976         } else {
2977             // The offsets are included in width and height by {@link #computeBounds}, so we have to
2978             // restore it.
2979             resolvedBounds.left += containingOffsetX;
2980             resolvedBounds.top += containingOffsetY;
2981         }
2982         task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
2983                 mCompatDisplayInsets);
2984 
2985         // The horizontal inset included in width is not needed if the activity cannot fill the
2986         // parent, because the offset will be applied by {@link AppWindowToken#mSizeCompatBounds}.
2987         final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
2988         final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
2989         if (resolvedBounds.width() < parentAppBounds.width()) {
2990             resolvedBounds.right -= resolvedAppBounds.left;
2991         }
2992         // Use parent orientation if it cannot be decided by bounds, so the activity can fit inside
2993         // the parent bounds appropriately.
2994         if (resolvedConfig.screenWidthDp == resolvedConfig.screenHeightDp) {
2995             resolvedConfig.orientation = newParentConfiguration.orientation;
2996         }
2997     }
2998 
2999     @Override
onConfigurationChanged(Configuration newParentConfig)3000     public void onConfigurationChanged(Configuration newParentConfig) {
3001         super.onConfigurationChanged(newParentConfig);
3002 
3003         // Configuration's equality doesn't consider seq so if only seq number changes in resolved
3004         // override configuration. Therefore ConfigurationContainer doesn't change merged override
3005         // configuration, but it's used to push configuration changes so explicitly update that.
3006         if (getMergedOverrideConfiguration().seq != getResolvedOverrideConfiguration().seq) {
3007             onMergedOverrideConfigurationChanged();
3008         }
3009 
3010         // TODO(b/80414790): Remove code below after unification.
3011         // Same as above it doesn't notify configuration listeners, and consequently AppWindowToken
3012         // can't get updated seq number. However WindowState's merged override configuration needs
3013         // to have this seq number because that's also used for activity config pushes during layout
3014         // traversal. Therefore explicitly update them here.
3015         if (mAppWindowToken == null) {
3016             return;
3017         }
3018         final Configuration appWindowTokenRequestedOverrideConfig =
3019                 mAppWindowToken.getRequestedOverrideConfiguration();
3020         if (appWindowTokenRequestedOverrideConfig.seq != getResolvedOverrideConfiguration().seq) {
3021             appWindowTokenRequestedOverrideConfig.seq =
3022                     getResolvedOverrideConfiguration().seq;
3023             mAppWindowToken.onMergedOverrideConfigurationChanged();
3024         }
3025 
3026         final ActivityDisplay display = getDisplay();
3027         if (display == null) {
3028             return;
3029         }
3030         if (visible) {
3031             // It may toggle the UI for user to restart the size compatibility mode activity.
3032             display.handleActivitySizeCompatModeIfNeeded(this);
3033         } else if (shouldUseSizeCompatMode()) {
3034             // The override changes can only be obtained from display, because we don't have the
3035             // difference of full configuration in each hierarchy.
3036             final int displayChanges = display.getLastOverrideConfigurationChanges();
3037             final int orientationChanges = CONFIG_WINDOW_CONFIGURATION
3038                     | CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION;
3039             final boolean hasNonOrienSizeChanged = hasResizeChange(displayChanges)
3040                     // Filter out the case of simple orientation change.
3041                     && (displayChanges & orientationChanges) != orientationChanges;
3042             // For background activity that uses size compatibility mode, if the size or density of
3043             // the display is changed, then reset the override configuration and kill the activity's
3044             // process if its process state is not important to user.
3045             if (hasNonOrienSizeChanged || (displayChanges & ActivityInfo.CONFIG_DENSITY) != 0) {
3046                 restartProcessIfVisible();
3047             }
3048         }
3049     }
3050 
3051     /** Returns true if the configuration is compatible with this activity. */
isConfigurationCompatible(Configuration config)3052     boolean isConfigurationCompatible(Configuration config) {
3053         final int orientation = getOrientation();
3054         if (isFixedOrientationPortrait(orientation)
3055                 && config.orientation != ORIENTATION_PORTRAIT) {
3056             return false;
3057         }
3058         if (isFixedOrientationLandscape(orientation)
3059                 && config.orientation != ORIENTATION_LANDSCAPE) {
3060             return false;
3061         }
3062         return true;
3063     }
3064 
3065     /**
3066      * Computes the bounds to fit the Activity within the bounds of the {@link Configuration}.
3067      */
3068     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
computeBounds(Rect outBounds, Rect containingAppBounds)3069     private void computeBounds(Rect outBounds, Rect containingAppBounds) {
3070         outBounds.setEmpty();
3071         final float maxAspectRatio = info.maxAspectRatio;
3072         final ActivityStack stack = getActivityStack();
3073         final float minAspectRatio = info.minAspectRatio;
3074 
3075         if (task == null || stack == null || task.inMultiWindowMode()
3076                 || (maxAspectRatio == 0 && minAspectRatio == 0)
3077                 || isInVrUiMode(getConfiguration())) {
3078             // We don't set override configuration if that activity task isn't fullscreen. I.e. the
3079             // activity is in multi-window mode. Or, there isn't a max aspect ratio specified for
3080             // the activity. This is indicated by an empty {@link outBounds}. We also don't set it
3081             // if we are in VR mode.
3082             return;
3083         }
3084 
3085         final int containingAppWidth = containingAppBounds.width();
3086         final int containingAppHeight = containingAppBounds.height();
3087         final float containingRatio = Math.max(containingAppWidth, containingAppHeight)
3088                 / (float) Math.min(containingAppWidth, containingAppHeight);
3089 
3090         int activityWidth = containingAppWidth;
3091         int activityHeight = containingAppHeight;
3092 
3093         if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
3094             if (containingAppWidth < containingAppHeight) {
3095                 // Width is the shorter side, so we use that to figure-out what the max. height
3096                 // should be given the aspect ratio.
3097                 activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
3098             } else {
3099                 // Height is the shorter side, so we use that to figure-out what the max. width
3100                 // should be given the aspect ratio.
3101                 activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
3102             }
3103         } else if (containingRatio < minAspectRatio) {
3104             boolean adjustWidth;
3105             switch (getRequestedConfigurationOrientation()) {
3106                 case ORIENTATION_LANDSCAPE:
3107                     // Width should be the longer side for this landscape app, so we use the width
3108                     // to figure-out what the max. height should be given the aspect ratio.
3109                     adjustWidth = false;
3110                     break;
3111                 case ORIENTATION_PORTRAIT:
3112                     // Height should be the longer side for this portrait app, so we use the height
3113                     // to figure-out what the max. width should be given the aspect ratio.
3114                     adjustWidth = true;
3115                     break;
3116                 default:
3117                     // This app doesn't have a preferred orientation, so we keep the length of the
3118                     // longer side, and use it to figure-out the length of the shorter side.
3119                     if (containingAppWidth < containingAppHeight) {
3120                         // Width is the shorter side, so we use the height to figure-out what the
3121                         // max. width should be given the aspect ratio.
3122                         adjustWidth = true;
3123                     } else {
3124                         // Height is the shorter side, so we use the width to figure-out what the
3125                         // max. height should be given the aspect ratio.
3126                         adjustWidth = false;
3127                     }
3128                     break;
3129             }
3130             if (adjustWidth) {
3131                 activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
3132             } else {
3133                 activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
3134             }
3135         }
3136 
3137         if (containingAppWidth <= activityWidth && containingAppHeight <= activityHeight) {
3138             // The display matches or is less than the activity aspect ratio, so nothing else to do.
3139             // Return the existing bounds. If this method is running for the first time,
3140             // {@link #getRequestedOverrideBounds()} will be empty (representing no override). If
3141             // the method has run before, then effect of {@link #getRequestedOverrideBounds()} will
3142             // already have been applied to the value returned from {@link getConfiguration}. Refer
3143             // to {@link TaskRecord#computeConfigResourceOverrides()}.
3144             outBounds.set(getRequestedOverrideBounds());
3145             return;
3146         }
3147 
3148         // Compute configuration based on max supported width and height.
3149         // Also account for the left / top insets (e.g. from display cutouts), which will be clipped
3150         // away later in {@link TaskRecord#computeConfigResourceOverrides()}. Otherwise, the app
3151         // bounds would end up too small.
3152         outBounds.set(0, 0, activityWidth + containingAppBounds.left,
3153                 activityHeight + containingAppBounds.top);
3154     }
3155 
3156     /**
3157      * @return {@code true} if this activity was reparented to another display but
3158      *         {@link #ensureActivityConfiguration} is not called.
3159      */
shouldUpdateConfigForDisplayChanged()3160     boolean shouldUpdateConfigForDisplayChanged() {
3161         return mLastReportedDisplayId != getDisplayId();
3162     }
3163 
ensureActivityConfiguration(int globalChanges, boolean preserveWindow)3164     boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
3165         return ensureActivityConfiguration(globalChanges, preserveWindow,
3166                 false /* ignoreVisibility */);
3167     }
3168 
3169     /**
3170      * Make sure the given activity matches the current configuration. Ensures the HistoryRecord
3171      * is updated with the correct configuration and all other bookkeeping is handled.
3172      *
3173      * @param globalChanges The changes to the global configuration.
3174      * @param preserveWindow If the activity window should be preserved on screen if the activity
3175      *                       is relaunched.
3176      * @param ignoreVisibility If we should try to relaunch the activity even if it is invisible
3177      *                         (stopped state). This is useful for the case where we know the
3178      *                         activity will be visible soon and we want to ensure its configuration
3179      *                         before we make it visible.
3180      * @return False if the activity was relaunched and true if it wasn't relaunched because we
3181      *         can't or the app handles the specific configuration that is changing.
3182      */
ensureActivityConfiguration(int globalChanges, boolean preserveWindow, boolean ignoreVisibility)3183     boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
3184             boolean ignoreVisibility) {
3185         final ActivityStack stack = getActivityStack();
3186         if (stack.mConfigWillChange) {
3187             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3188                     "Skipping config check (will change): " + this);
3189             return true;
3190         }
3191 
3192         // We don't worry about activities that are finishing.
3193         if (finishing) {
3194             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3195                     "Configuration doesn't matter in finishing " + this);
3196             stopFreezingScreenLocked(false);
3197             return true;
3198         }
3199 
3200         if (!ignoreVisibility && (mState == STOPPING || mState == STOPPED || !shouldBeVisible())) {
3201             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3202                     "Skipping config check invisible: " + this);
3203             return true;
3204         }
3205 
3206         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3207                 "Ensuring correct configuration: " + this);
3208 
3209         final int newDisplayId = getDisplayId();
3210         final boolean displayChanged = mLastReportedDisplayId != newDisplayId;
3211         if (displayChanged) {
3212             mLastReportedDisplayId = newDisplayId;
3213         }
3214         // TODO(b/36505427): Is there a better place to do this?
3215         updateOverrideConfiguration();
3216 
3217         // Short circuit: if the two full configurations are equal (the common case), then there is
3218         // nothing to do.  We test the full configuration instead of the global and merged override
3219         // configurations because there are cases (like moving a task to the pinned stack) where
3220         // the combine configurations are equal, but would otherwise differ in the override config
3221         mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration());
3222         if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) {
3223             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3224                     "Configuration & display unchanged in " + this);
3225             return true;
3226         }
3227 
3228         // Okay we now are going to make this activity have the new config.
3229         // But then we need to figure out how it needs to deal with that.
3230 
3231         // Find changes between last reported merged configuration and the current one. This is used
3232         // to decide whether to relaunch an activity or just report a configuration change.
3233         final int changes = getConfigurationChanges(mTmpConfig);
3234 
3235         // Update last reported values.
3236         final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
3237 
3238         setLastReportedConfiguration(mAtmService.getGlobalConfiguration(), newMergedOverrideConfig);
3239 
3240         if (mState == INITIALIZING) {
3241             // No need to relaunch or schedule new config for activity that hasn't been launched
3242             // yet. We do, however, return after applying the config to activity record, so that
3243             // it will use it for launch transaction.
3244             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3245                     "Skipping config check for initializing activity: " + this);
3246             return true;
3247         }
3248 
3249         if (changes == 0 && !forceNewConfig) {
3250             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3251                     "Configuration no differences in " + this);
3252             // There are no significant differences, so we won't relaunch but should still deliver
3253             // the new configuration to the client process.
3254             if (displayChanged) {
3255                 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
3256             } else {
3257                 scheduleConfigurationChanged(newMergedOverrideConfig);
3258             }
3259             return true;
3260         }
3261 
3262         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3263                 "Configuration changes for " + this + ", allChanges="
3264                         + Configuration.configurationDiffToString(changes));
3265 
3266         // If the activity isn't currently running, just leave the new configuration and it will
3267         // pick that up next time it starts.
3268         if (!attachedToProcess()) {
3269             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3270                     "Configuration doesn't matter not running " + this);
3271             stopFreezingScreenLocked(false);
3272             forceNewConfig = false;
3273             return true;
3274         }
3275 
3276         // Figure out how to handle the changes between the configurations.
3277         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3278                 "Checking to restart " + info.name + ": changed=0x"
3279                         + Integer.toHexString(changes) + ", handles=0x"
3280                         + Integer.toHexString(info.getRealConfigChanged())
3281                         + ", mLastReportedConfiguration=" + mLastReportedConfiguration);
3282 
3283         if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
3284             // Aha, the activity isn't handling the change, so DIE DIE DIE.
3285             configChangeFlags |= changes;
3286             startFreezingScreenLocked(app, globalChanges);
3287             forceNewConfig = false;
3288             preserveWindow &= isResizeOnlyChange(changes);
3289             final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
3290             if (hasResizeChange) {
3291                 final boolean isDragResizing =
3292                         getTaskRecord().getTask().isDragResizing();
3293                 mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
3294                         : RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
3295             } else {
3296                 mRelaunchReason = RELAUNCH_REASON_NONE;
3297             }
3298             if (!attachedToProcess()) {
3299                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3300                         "Config is destroying non-running " + this);
3301                 stack.destroyActivityLocked(this, true, "config");
3302             } else if (mState == PAUSING) {
3303                 // A little annoying: we are waiting for this activity to finish pausing. Let's not
3304                 // do anything now, but just flag that it needs to be restarted when done pausing.
3305                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3306                         "Config is skipping already pausing " + this);
3307                 deferRelaunchUntilPaused = true;
3308                 preserveWindowOnDeferredRelaunch = preserveWindow;
3309                 return true;
3310             } else if (mState == RESUMED) {
3311                 // Try to optimize this case: the configuration is changing and we need to restart
3312                 // the top, resumed activity. Instead of doing the normal handshaking, just say
3313                 // "restart!".
3314                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3315                         "Config is relaunching resumed " + this);
3316 
3317                 if (DEBUG_STATES && !visible) {
3318                     Slog.v(TAG_STATES, "Config is relaunching resumed invisible activity " + this
3319                             + " called by " + Debug.getCallers(4));
3320                 }
3321 
3322                 relaunchActivityLocked(true /* andResume */, preserveWindow);
3323             } else {
3324                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3325                         "Config is relaunching non-resumed " + this);
3326                 relaunchActivityLocked(false /* andResume */, preserveWindow);
3327             }
3328 
3329             // All done...  tell the caller we weren't able to keep this activity around.
3330             return false;
3331         }
3332 
3333         // Default case: the activity can handle this new configuration, so hand it over.
3334         // NOTE: We only forward the override configuration as the system level configuration
3335         // changes is always sent to all processes when they happen so it can just use whatever
3336         // system level configuration it last got.
3337         if (displayChanged) {
3338             scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
3339         } else {
3340             scheduleConfigurationChanged(newMergedOverrideConfig);
3341         }
3342         stopFreezingScreenLocked(false);
3343 
3344         return true;
3345     }
3346 
3347     /**
3348      * When assessing a configuration change, decide if the changes flags and the new configurations
3349      * should cause the Activity to relaunch.
3350      *
3351      * @param changes the changes due to the given configuration.
3352      * @param changesConfig the configuration that was used to calculate the given changes via a
3353      *        call to getConfigurationChanges.
3354      */
shouldRelaunchLocked(int changes, Configuration changesConfig)3355     private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
3356         int configChanged = info.getRealConfigChanged();
3357         boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
3358 
3359         // Override for apps targeting pre-O sdks
3360         // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
3361         // to the config change.
3362         // For O and later, apps will be required to add configChanges="uimode" to their manifest.
3363         if (appInfo.targetSdkVersion < O
3364                 && requestedVrComponent != null
3365                 && onlyVrUiModeChanged) {
3366             configChanged |= CONFIG_UI_MODE;
3367         }
3368 
3369         return (changes&(~configChanged)) != 0;
3370     }
3371 
3372     /**
3373      * Returns true if the configuration change is solely due to the UI mode switching into or out
3374      * of UI_MODE_TYPE_VR_HEADSET.
3375      */
onlyVrUiModeChanged(int changes, Configuration lastReportedConfig)3376     private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
3377         final Configuration currentConfig = getConfiguration();
3378         return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
3379             != isInVrUiMode(lastReportedConfig));
3380     }
3381 
getConfigurationChanges(Configuration lastReportedConfig)3382     private int getConfigurationChanges(Configuration lastReportedConfig) {
3383         // Determine what has changed.  May be nothing, if this is a config that has come back from
3384         // the app after going idle.  In that case we just want to leave the official config object
3385         // now in the activity and do nothing else.
3386         final Configuration currentConfig = getConfiguration();
3387         int changes = lastReportedConfig.diff(currentConfig);
3388         // We don't want to use size changes if they don't cross boundaries that are important to
3389         // the app.
3390         if ((changes & CONFIG_SCREEN_SIZE) != 0) {
3391             final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp,
3392                     currentConfig.screenWidthDp)
3393                     || crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp,
3394                     currentConfig.screenHeightDp);
3395             if (!crosses) {
3396                 changes &= ~CONFIG_SCREEN_SIZE;
3397             }
3398         }
3399         if ((changes & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
3400             final int oldSmallest = lastReportedConfig.smallestScreenWidthDp;
3401             final int newSmallest = currentConfig.smallestScreenWidthDp;
3402             if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
3403                 changes &= ~CONFIG_SMALLEST_SCREEN_SIZE;
3404             }
3405         }
3406         // We don't want window configuration to cause relaunches.
3407         if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) {
3408             changes &= ~CONFIG_WINDOW_CONFIGURATION;
3409         }
3410 
3411         return changes;
3412     }
3413 
isResizeOnlyChange(int change)3414     private static boolean isResizeOnlyChange(int change) {
3415         return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
3416                 | CONFIG_SCREEN_LAYOUT)) == 0;
3417     }
3418 
hasResizeChange(int change)3419     private static boolean hasResizeChange(int change) {
3420         return (change & (CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
3421                 | CONFIG_SCREEN_LAYOUT)) != 0;
3422     }
3423 
relaunchActivityLocked(boolean andResume, boolean preserveWindow)3424     void relaunchActivityLocked(boolean andResume, boolean preserveWindow) {
3425         if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
3426             configChangeFlags = 0;
3427             return;
3428         }
3429 
3430         List<ResultInfo> pendingResults = null;
3431         List<ReferrerIntent> pendingNewIntents = null;
3432         if (andResume) {
3433             pendingResults = results;
3434             pendingNewIntents = newIntents;
3435         }
3436         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
3437                 "Relaunching: " + this + " with results=" + pendingResults
3438                         + " newIntents=" + pendingNewIntents + " andResume=" + andResume
3439                         + " preserveWindow=" + preserveWindow);
3440         EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY
3441                         : AM_RELAUNCH_ACTIVITY, mUserId, System.identityHashCode(this),
3442                 task.taskId, shortComponentName);
3443 
3444         startFreezingScreenLocked(app, 0);
3445 
3446         try {
3447             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
3448                     "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
3449                             + " callers=" + Debug.getCallers(6));
3450             forceNewConfig = false;
3451             mStackSupervisor.activityRelaunchingLocked(this);
3452             final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
3453                     pendingNewIntents, configChangeFlags,
3454                     new MergedConfiguration(mAtmService.getGlobalConfiguration(),
3455                             getMergedOverrideConfiguration()),
3456                     preserveWindow);
3457             final ActivityLifecycleItem lifecycleItem;
3458             if (andResume) {
3459                 lifecycleItem = ResumeActivityItem.obtain(
3460                         getDisplay().mDisplayContent.isNextTransitionForward());
3461             } else {
3462                 lifecycleItem = PauseActivityItem.obtain();
3463             }
3464             final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
3465             transaction.addCallback(callbackItem);
3466             transaction.setLifecycleStateRequest(lifecycleItem);
3467             mAtmService.getLifecycleManager().scheduleTransaction(transaction);
3468             // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
3469             // request resume if this activity is currently resumed, which implies we aren't
3470             // sleeping.
3471         } catch (RemoteException e) {
3472             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
3473         }
3474 
3475         if (andResume) {
3476             if (DEBUG_STATES) {
3477                 Slog.d(TAG_STATES, "Resumed after relaunch " + this);
3478             }
3479             results = null;
3480             newIntents = null;
3481             mAtmService.getAppWarningsLocked().onResumeActivity(this);
3482         } else {
3483             final ActivityStack stack = getActivityStack();
3484             if (stack != null) {
3485                 stack.mHandler.removeMessages(PAUSE_TIMEOUT_MSG, this);
3486             }
3487             setState(PAUSED, "relaunchActivityLocked");
3488         }
3489 
3490         configChangeFlags = 0;
3491         deferRelaunchUntilPaused = false;
3492         preserveWindowOnDeferredRelaunch = false;
3493     }
3494 
3495     /**
3496      * Request the process of the activity to restart with its saved state (from
3497      * {@link android.app.Activity#onSaveInstanceState}) if possible. It also forces to recompute
3498      * the override configuration. Note if the activity is in background, the process will be killed
3499      * directly with keeping its record.
3500      */
restartProcessIfVisible()3501     void restartProcessIfVisible() {
3502         Slog.i(TAG, "Request to restart process of " + this);
3503 
3504         // Reset the existing override configuration so it can be updated according to the latest
3505         // configuration.
3506         getRequestedOverrideConfiguration().unset();
3507         getResolvedOverrideConfiguration().unset();
3508         mCompatDisplayInsets = null;
3509         if (visible) {
3510             // Configuration will be ensured when becoming visible, so if it is already visible,
3511             // then the manual update is needed.
3512             updateOverrideConfiguration();
3513         }
3514 
3515         if (!attachedToProcess()) {
3516             return;
3517         }
3518 
3519         // The restarting state avoids removing this record when process is died.
3520         setState(RESTARTING_PROCESS, "restartActivityProcess");
3521 
3522         if (!visible || haveState) {
3523             // Kill its process immediately because the activity should be in background.
3524             // The activity state will be update to {@link #DESTROYED} in
3525             // {@link ActivityStack#cleanUpActivityLocked} when handling process died.
3526             mAtmService.mH.post(() -> {
3527                 final WindowProcessController wpc;
3528                 synchronized (mAtmService.mGlobalLock) {
3529                     if (!hasProcess()
3530                             || app.getReportedProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND) {
3531                         return;
3532                     }
3533                     wpc = app;
3534                 }
3535                 mAtmService.mAmInternal.killProcess(wpc.mName, wpc.mUid, "resetConfig");
3536             });
3537             return;
3538         }
3539 
3540         if (mAppWindowToken != null) {
3541             mAppWindowToken.startFreezingScreen();
3542         }
3543         // The process will be killed until the activity reports stopped with saved state (see
3544         // {@link ActivityTaskManagerService.activityStopped}).
3545         try {
3546             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
3547                     StopActivityItem.obtain(false /* showWindow */, 0 /* configChanges */));
3548         } catch (RemoteException e) {
3549             Slog.w(TAG, "Exception thrown during restart " + this, e);
3550         }
3551         mStackSupervisor.scheduleRestartTimeout(this);
3552     }
3553 
isProcessRunning()3554     boolean isProcessRunning() {
3555         WindowProcessController proc = app;
3556         if (proc == null) {
3557             proc = mAtmService.mProcessNames.get(processName, info.applicationInfo.uid);
3558         }
3559         return proc != null && proc.hasThread();
3560     }
3561 
3562     /**
3563      * @return Whether a task snapshot starting window may be shown.
3564      */
allowTaskSnapshot()3565     private boolean allowTaskSnapshot() {
3566         if (newIntents == null) {
3567             return true;
3568         }
3569 
3570         // Restrict task snapshot starting window to launcher start, or there is no intent at all
3571         // (eg. task being brought to front). If the intent is something else, likely the app is
3572         // going to show some specific page or view, instead of what's left last time.
3573         for (int i = newIntents.size() - 1; i >= 0; i--) {
3574             final Intent intent = newIntents.get(i);
3575             if (intent != null && !ActivityRecord.isMainIntent(intent)) {
3576                 return false;
3577             }
3578         }
3579         return true;
3580     }
3581 
3582     /**
3583      * Returns {@code true} if the associated activity has the no history flag set on it.
3584      * {@code false} otherwise.
3585      */
isNoHistory()3586     boolean isNoHistory() {
3587         return (intent.getFlags() & FLAG_ACTIVITY_NO_HISTORY) != 0
3588                 || (info.flags & FLAG_NO_HISTORY) != 0;
3589     }
3590 
saveToXml(XmlSerializer out)3591     void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
3592         out.attribute(null, ATTR_ID, String.valueOf(createTime));
3593         out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
3594         if (launchedFromPackage != null) {
3595             out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
3596         }
3597         if (resolvedType != null) {
3598             out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
3599         }
3600         out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
3601         out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
3602 
3603         if (taskDescription != null) {
3604             taskDescription.saveToXml(out);
3605         }
3606 
3607         out.startTag(null, TAG_INTENT);
3608         intent.saveToXml(out);
3609         out.endTag(null, TAG_INTENT);
3610 
3611         if (isPersistable() && persistentState != null) {
3612             out.startTag(null, TAG_PERSISTABLEBUNDLE);
3613             persistentState.saveToXml(out);
3614             out.endTag(null, TAG_PERSISTABLEBUNDLE);
3615         }
3616     }
3617 
restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)3618     static ActivityRecord restoreFromXml(XmlPullParser in,
3619             ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
3620         Intent intent = null;
3621         PersistableBundle persistentState = null;
3622         int launchedFromUid = 0;
3623         String launchedFromPackage = null;
3624         String resolvedType = null;
3625         boolean componentSpecified = false;
3626         int userId = 0;
3627         long createTime = -1;
3628         final int outerDepth = in.getDepth();
3629         TaskDescription taskDescription = new TaskDescription();
3630 
3631         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
3632             final String attrName = in.getAttributeName(attrNdx);
3633             final String attrValue = in.getAttributeValue(attrNdx);
3634             if (DEBUG) Slog.d(TaskPersister.TAG,
3635                         "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
3636             if (ATTR_ID.equals(attrName)) {
3637                 createTime = Long.parseLong(attrValue);
3638             } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
3639                 launchedFromUid = Integer.parseInt(attrValue);
3640             } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
3641                 launchedFromPackage = attrValue;
3642             } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
3643                 resolvedType = attrValue;
3644             } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
3645                 componentSpecified = Boolean.parseBoolean(attrValue);
3646             } else if (ATTR_USERID.equals(attrName)) {
3647                 userId = Integer.parseInt(attrValue);
3648             } else if (attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) {
3649                 taskDescription.restoreFromXml(attrName, attrValue);
3650             } else {
3651                 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
3652             }
3653         }
3654 
3655         int event;
3656         while (((event = in.next()) != END_DOCUMENT) &&
3657                 (event != END_TAG || in.getDepth() >= outerDepth)) {
3658             if (event == START_TAG) {
3659                 final String name = in.getName();
3660                 if (DEBUG)
3661                         Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
3662                 if (TAG_INTENT.equals(name)) {
3663                     intent = Intent.restoreFromXml(in);
3664                     if (DEBUG)
3665                             Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
3666                 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
3667                     persistentState = PersistableBundle.restoreFromXml(in);
3668                     if (DEBUG) Slog.d(TaskPersister.TAG,
3669                             "ActivityRecord: persistentState=" + persistentState);
3670                 } else {
3671                     Slog.w(TAG, "restoreActivity: unexpected name=" + name);
3672                     XmlUtils.skipCurrentTag(in);
3673                 }
3674             }
3675         }
3676 
3677         if (intent == null) {
3678             throw new XmlPullParserException("restoreActivity error intent=" + intent);
3679         }
3680 
3681         final ActivityTaskManagerService service = stackSupervisor.mService;
3682         final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
3683                 userId, Binder.getCallingUid());
3684         if (aInfo == null) {
3685             throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
3686                     " resolvedType=" + resolvedType);
3687         }
3688         final ActivityRecord r = new ActivityRecord(service, null /* caller */,
3689                 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType,
3690                 aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */,
3691                 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */,
3692                 stackSupervisor, null /* options */, null /* sourceRecord */);
3693 
3694         r.persistentState = persistentState;
3695         r.taskDescription = taskDescription;
3696         r.createTime = createTime;
3697 
3698         return r;
3699     }
3700 
isInVrUiMode(Configuration config)3701     private static boolean isInVrUiMode(Configuration config) {
3702         return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
3703     }
3704 
getUid()3705     int getUid() {
3706         return info.applicationInfo.uid;
3707     }
3708 
setShowWhenLocked(boolean showWhenLocked)3709     void setShowWhenLocked(boolean showWhenLocked) {
3710         mShowWhenLocked = showWhenLocked;
3711         mRootActivityContainer.ensureActivitiesVisible(null, 0 /* configChanges */,
3712                 false /* preserveWindows */);
3713     }
3714 
setInheritShowWhenLocked(boolean inheritShowWhenLocked)3715     void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
3716         mInheritShownWhenLocked = inheritShowWhenLocked;
3717         mRootActivityContainer.ensureActivitiesVisible(null, 0, false);
3718     }
3719 
3720     /**
3721      * @return true if the activity windowing mode is not
3722      *         {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
3723      *         contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
3724      *         activity has set {@link #mShowWhenLocked}, or b) if the activity has set
3725      *         {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
3726      *         conditions a) above.
3727      *         Multi-windowing mode will be exited if true is returned.
3728      */
canShowWhenLocked()3729     boolean canShowWhenLocked() {
3730         if (!inPinnedWindowingMode() && (mShowWhenLocked
3731                 || (mAppWindowToken != null && mAppWindowToken.containsShowWhenLockedWindow()))) {
3732             return true;
3733         } else if (mInheritShownWhenLocked) {
3734             ActivityRecord r = getActivityBelow();
3735             return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
3736                     || (r.mAppWindowToken != null
3737                         && r.mAppWindowToken.containsShowWhenLockedWindow()));
3738         } else {
3739             return false;
3740         }
3741     }
3742 
3743     /**
3744      * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
3745      * such activity exists.
3746      */
3747     @Nullable
getActivityBelow()3748     private ActivityRecord getActivityBelow() {
3749         final int pos = task.mActivities.indexOf(this);
3750         if (pos == -1) {
3751             throw new IllegalStateException("Activity not found in its task");
3752         }
3753         return pos == 0 ? null : task.getChildAt(pos - 1);
3754     }
3755 
setTurnScreenOn(boolean turnScreenOn)3756     void setTurnScreenOn(boolean turnScreenOn) {
3757         mTurnScreenOn = turnScreenOn;
3758     }
3759 
3760     /**
3761      * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
3762      * {@link #mTurnScreenOn} is set and checks whether the ActivityRecord should be visible
3763      * depending on Keyguard state
3764      *
3765      * @return true if the screen can be turned on, false otherwise.
3766      */
canTurnScreenOn()3767     boolean canTurnScreenOn() {
3768         final ActivityStack stack = getActivityStack();
3769         return mTurnScreenOn && stack != null &&
3770                 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */);
3771     }
3772 
3773     /**
3774      * Check if this activity is able to resume. For pre-Q apps, only the topmost activities of each
3775      * process are allowed to be resumed.
3776      *
3777      * @return true if this activity can be resumed.
3778      */
canResumeByCompat()3779     boolean canResumeByCompat() {
3780         return app == null || app.updateTopResumingActivityInProcessIfNeeded(this);
3781     }
3782 
getTurnScreenOnFlag()3783     boolean getTurnScreenOnFlag() {
3784         return mTurnScreenOn;
3785     }
3786 
isTopRunningActivity()3787     boolean isTopRunningActivity() {
3788         return mRootActivityContainer.topRunningActivity() == this;
3789     }
3790 
3791     /**
3792      * @return {@code true} if this is the resumed activity on its current display, {@code false}
3793      * otherwise.
3794      */
isResumedActivityOnDisplay()3795     boolean isResumedActivityOnDisplay() {
3796         final ActivityDisplay display = getDisplay();
3797         return display != null && this == display.getResumedActivity();
3798     }
3799 
registerRemoteAnimations(RemoteAnimationDefinition definition)3800     void registerRemoteAnimations(RemoteAnimationDefinition definition) {
3801         if (mAppWindowToken == null) {
3802             Slog.w(TAG_WM, "Attempted to register remote animations with non-existing app"
3803                     + " token: " + appToken);
3804             return;
3805         }
3806         mAppWindowToken.registerRemoteAnimations(definition);
3807     }
3808 
3809     @Override
toString()3810     public String toString() {
3811         if (stringName != null) {
3812             return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) +
3813                     (finishing ? " f}" : "}");
3814         }
3815         StringBuilder sb = new StringBuilder(128);
3816         sb.append("ActivityRecord{");
3817         sb.append(Integer.toHexString(System.identityHashCode(this)));
3818         sb.append(" u");
3819         sb.append(mUserId);
3820         sb.append(' ');
3821         sb.append(intent.getComponent().flattenToShortString());
3822         stringName = sb.toString();
3823         return toString();
3824     }
3825 
writeIdentifierToProto(ProtoOutputStream proto, long fieldId)3826     void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
3827         final long token = proto.start(fieldId);
3828         proto.write(HASH_CODE, System.identityHashCode(this));
3829         proto.write(USER_ID, mUserId);
3830         proto.write(TITLE, intent.getComponent().flattenToShortString());
3831         proto.end(token);
3832     }
3833 
3834     /**
3835      * Write all fields to an {@code ActivityRecordProto}. This assumes the
3836      * {@code ActivityRecordProto} is the outer-most proto data.
3837      */
writeToProto(ProtoOutputStream proto)3838     void writeToProto(ProtoOutputStream proto) {
3839         super.writeToProto(proto, CONFIGURATION_CONTAINER, WindowTraceLogLevel.ALL);
3840         writeIdentifierToProto(proto, IDENTIFIER);
3841         proto.write(STATE, mState.toString());
3842         proto.write(VISIBLE, visible);
3843         proto.write(FRONT_OF_TASK, frontOfTask);
3844         if (hasProcess()) {
3845             proto.write(PROC_ID, app.getPid());
3846         }
3847         proto.write(TRANSLUCENT, !fullscreen);
3848     }
3849 
writeToProto(ProtoOutputStream proto, long fieldId)3850     public void writeToProto(ProtoOutputStream proto, long fieldId) {
3851         final long token = proto.start(fieldId);
3852         writeToProto(proto);
3853         proto.end(token);
3854     }
3855 
3856     /**
3857      * The precomputed insets of the display in each rotation. This is used to make the size
3858      * compatibility mode activity compute the configuration without relying on its current display.
3859      */
3860     static class CompatDisplayInsets {
3861         final int mDisplayWidth;
3862         final int mDisplayHeight;
3863 
3864         /**
3865          * The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
3866          * is used to compute the appBounds.
3867          */
3868         final Rect[] mNonDecorInsets = new Rect[4];
3869         /**
3870          * The stableInsets for each rotation. Includes the status bar inset and the
3871          * nonDecorInsets. It is used to compute {@link Configuration#screenWidthDp} and
3872          * {@link Configuration#screenHeightDp}.
3873          */
3874         final Rect[] mStableInsets = new Rect[4];
3875 
CompatDisplayInsets(DisplayContent display)3876         CompatDisplayInsets(DisplayContent display) {
3877             mDisplayWidth = display.mBaseDisplayWidth;
3878             mDisplayHeight = display.mBaseDisplayHeight;
3879             final DisplayPolicy policy = display.getDisplayPolicy();
3880             for (int rotation = 0; rotation < 4; rotation++) {
3881                 mNonDecorInsets[rotation] = new Rect();
3882                 mStableInsets[rotation] = new Rect();
3883                 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
3884                 final int dw = rotated ? mDisplayHeight : mDisplayWidth;
3885                 final int dh = rotated ? mDisplayWidth : mDisplayHeight;
3886                 final DisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation)
3887                         .getDisplayCutout();
3888                 policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
3889                 mStableInsets[rotation].set(mNonDecorInsets[rotation]);
3890                 policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
3891             }
3892         }
3893 
getDisplayBoundsByRotation(Rect outBounds, int rotation)3894         void getDisplayBoundsByRotation(Rect outBounds, int rotation) {
3895             final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
3896             final int dw = rotated ? mDisplayHeight : mDisplayWidth;
3897             final int dh = rotated ? mDisplayWidth : mDisplayHeight;
3898             outBounds.set(0, 0, dw, dh);
3899         }
3900 
getDisplayBoundsByOrientation(Rect outBounds, int orientation)3901         void getDisplayBoundsByOrientation(Rect outBounds, int orientation) {
3902             final int longSide = Math.max(mDisplayWidth, mDisplayHeight);
3903             final int shortSide = Math.min(mDisplayWidth, mDisplayHeight);
3904             final boolean isLandscape = orientation == ORIENTATION_LANDSCAPE;
3905             outBounds.set(0, 0, isLandscape ? longSide : shortSide,
3906                     isLandscape ? shortSide : longSide);
3907         }
3908     }
3909 }
3910