• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.app.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 
isResolverActivity()924     boolean isResolverActivity() {
925         return isResolverActivity(mActivityComponent.getClassName());
926     }
927 
isResolverOrChildActivity()928     boolean isResolverOrChildActivity() {
929         if (!"android".equals(packageName)) {
930             return false;
931         }
932         try {
933             return ResolverActivity.class.isAssignableFrom(
934                     Object.class.getClassLoader().loadClass(mActivityComponent.getClassName()));
935         } catch (ClassNotFoundException e) {
936             return false;
937         }
938     }
939 
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)940     ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
941             int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage, Intent _intent,
942             String _resolvedType, ActivityInfo aInfo, Configuration _configuration,
943             ActivityRecord _resultTo, String _resultWho, int _reqCode, boolean _componentSpecified,
944             boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
945             ActivityOptions options, ActivityRecord sourceRecord) {
946         mAtmService = _service;
947         mRootActivityContainer = _service.mRootActivityContainer;
948         appToken = new Token(this, _intent);
949         info = aInfo;
950         launchedFromPid = _launchedFromPid;
951         launchedFromUid = _launchedFromUid;
952         launchedFromPackage = _launchedFromPackage;
953         mUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
954         intent = _intent;
955         shortComponentName = _intent.getComponent().flattenToShortString();
956         resolvedType = _resolvedType;
957         componentSpecified = _componentSpecified;
958         rootVoiceInteraction = _rootVoiceInteraction;
959         mLastReportedConfiguration = new MergedConfiguration(_configuration);
960         resultTo = _resultTo;
961         resultWho = _resultWho;
962         requestCode = _reqCode;
963         setState(INITIALIZING, "ActivityRecord ctor");
964         frontOfTask = false;
965         launchFailed = false;
966         stopped = false;
967         delayedResume = false;
968         finishing = false;
969         deferRelaunchUntilPaused = false;
970         keysPaused = false;
971         inHistory = false;
972         visible = false;
973         nowVisible = false;
974         mDrawn = false;
975         idle = false;
976         hasBeenLaunched = false;
977         mStackSupervisor = supervisor;
978 
979         // This starts out true, since the initial state of an activity is that we have everything,
980         // and we shouldn't never consider it lacking in state to be removed if it dies.
981         haveState = true;
982 
983         // If the class name in the intent doesn't match that of the target, this is
984         // probably an alias. We have to create a new ComponentName object to keep track
985         // of the real activity name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
986         if (aInfo.targetActivity == null
987                 || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
988                 && (aInfo.launchMode == LAUNCH_MULTIPLE
989                 || aInfo.launchMode == LAUNCH_SINGLE_TOP))) {
990             mActivityComponent = _intent.getComponent();
991         } else {
992             mActivityComponent = new ComponentName(aInfo.packageName, aInfo.targetActivity);
993         }
994         taskAffinity = aInfo.taskAffinity;
995         stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
996         appInfo = aInfo.applicationInfo;
997         nonLocalizedLabel = aInfo.nonLocalizedLabel;
998         labelRes = aInfo.labelRes;
999         if (nonLocalizedLabel == null && labelRes == 0) {
1000             ApplicationInfo app = aInfo.applicationInfo;
1001             nonLocalizedLabel = app.nonLocalizedLabel;
1002             labelRes = app.labelRes;
1003         }
1004         icon = aInfo.getIconResource();
1005         logo = aInfo.getLogoResource();
1006         theme = aInfo.getThemeResource();
1007         realTheme = theme;
1008         if (realTheme == 0) {
1009             realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
1010                     ? android.R.style.Theme : android.R.style.Theme_Holo;
1011         }
1012         if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
1013             windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
1014         }
1015         if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
1016                 && (aInfo.applicationInfo.uid == SYSTEM_UID
1017                     || aInfo.applicationInfo.uid == _caller.mInfo.uid)) {
1018             processName = _caller.mName;
1019         } else {
1020             processName = aInfo.processName;
1021         }
1022 
1023         if ((aInfo.flags & FLAG_EXCLUDE_FROM_RECENTS) != 0) {
1024             intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
1025         }
1026 
1027         packageName = aInfo.applicationInfo.packageName;
1028         launchMode = aInfo.launchMode;
1029 
1030         Entry ent = AttributeCache.instance().get(packageName,
1031                 realTheme, com.android.internal.R.styleable.Window, mUserId);
1032 
1033         if (ent != null) {
1034             fullscreen = !ActivityInfo.isTranslucentOrFloating(ent.array);
1035             hasWallpaper = ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
1036             noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
1037         } else {
1038             hasWallpaper = false;
1039             noDisplay = false;
1040         }
1041 
1042         setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
1043 
1044         immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
1045 
1046         requestedVrComponent = (aInfo.requestedVrComponent == null) ?
1047                 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
1048 
1049         mShowWhenLocked = (aInfo.flags & FLAG_SHOW_WHEN_LOCKED) != 0;
1050         mInheritShownWhenLocked = (aInfo.privateFlags & FLAG_INHERIT_SHOW_WHEN_LOCKED) != 0;
1051         mTurnScreenOn = (aInfo.flags & FLAG_TURN_SCREEN_ON) != 0;
1052 
1053         mRotationAnimationHint = aInfo.rotationAnimation;
1054         lockTaskLaunchMode = aInfo.lockTaskLaunchMode;
1055         if (appInfo.isPrivilegedApp() && (lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_ALWAYS
1056                 || lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
1057             lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
1058         }
1059 
1060         if (options != null) {
1061             pendingOptions = options;
1062             mLaunchTaskBehind = options.getLaunchTaskBehind();
1063 
1064             final int rotationAnimation = pendingOptions.getRotationAnimationHint();
1065             // Only override manifest supplied option if set.
1066             if (rotationAnimation >= 0) {
1067                 mRotationAnimationHint = rotationAnimation;
1068             }
1069             final PendingIntent usageReport = pendingOptions.getUsageTimeReport();
1070             if (usageReport != null) {
1071                 appTimeTracker = new AppTimeTracker(usageReport);
1072             }
1073             final boolean useLockTask = pendingOptions.getLockTaskMode();
1074             if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
1075                 lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
1076             }
1077             // Gets launch display id from options. It returns INVALID_DISPLAY if not set.
1078             mHandoverLaunchDisplayId = options.getLaunchDisplayId();
1079         }
1080     }
1081 
setProcess(WindowProcessController proc)1082     void setProcess(WindowProcessController proc) {
1083         app = proc;
1084         final ActivityRecord root = task != null ? task.getRootActivity() : null;
1085         if (root == this) {
1086             task.setRootProcess(proc);
1087         }
1088     }
1089 
hasProcess()1090     boolean hasProcess() {
1091         return app != null;
1092     }
1093 
attachedToProcess()1094     boolean attachedToProcess() {
1095         return hasProcess() && app.hasThread();
1096     }
1097 
createAppWindowToken()1098     void createAppWindowToken() {
1099         if (mAppWindowToken != null) {
1100             throw new IllegalArgumentException("App Window Token=" + mAppWindowToken
1101                     + " already created for r=" + this);
1102         }
1103 
1104         inHistory = true;
1105 
1106         // TODO(b/36505427): Maybe this call should be moved inside updateOverrideConfiguration()
1107         task.updateOverrideConfigurationFromLaunchBounds();
1108         // Make sure override configuration is up-to-date before using to create window controller.
1109         updateOverrideConfiguration();
1110 
1111         // TODO: remove after unification
1112         mAppWindowToken = mAtmService.mWindowManager.mRoot.getAppWindowToken(appToken.asBinder());
1113         if (mAppWindowToken != null) {
1114             // TODO: Should this throw an exception instead?
1115             Slog.w(TAG, "Attempted to add existing app token: " + appToken);
1116         } else {
1117             final Task container = task.getTask();
1118             if (container == null) {
1119                 throw new IllegalArgumentException("createAppWindowToken: invalid task =" + task);
1120             }
1121             mAppWindowToken = createAppWindow(mAtmService.mWindowManager, appToken,
1122                     task.voiceSession != null, container.getDisplayContent(),
1123                     ActivityTaskManagerService.getInputDispatchingTimeoutLocked(this)
1124                             * 1000000L, fullscreen,
1125                     (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, appInfo.targetSdkVersion,
1126                     info.screenOrientation, mRotationAnimationHint,
1127                     mLaunchTaskBehind, isAlwaysFocusable());
1128             if (DEBUG_TOKEN_MOVEMENT || DEBUG_ADD_REMOVE) {
1129                 Slog.v(TAG, "addAppToken: "
1130                         + mAppWindowToken + " task=" + container + " at "
1131                         + Integer.MAX_VALUE);
1132             }
1133             container.addChild(mAppWindowToken, Integer.MAX_VALUE /* add on top */);
1134         }
1135 
1136         task.addActivityToTop(this);
1137 
1138         // When an activity is started directly into a split-screen fullscreen stack, we need to
1139         // update the initial multi-window modes so that the callbacks are scheduled correctly when
1140         // the user leaves that mode.
1141         mLastReportedMultiWindowMode = inMultiWindowMode();
1142         mLastReportedPictureInPictureMode = inPinnedWindowingMode();
1143     }
1144 
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)1145     boolean addStartingWindow(String pkg, int theme, CompatibilityInfo compatInfo,
1146             CharSequence nonLocalizedLabel, int labelRes, int icon, int logo, int windowFlags,
1147             IBinder transferFrom, boolean newTask, boolean taskSwitch, boolean processRunning,
1148             boolean allowTaskSnapshot, boolean activityCreated, boolean fromRecents) {
1149         if (DEBUG_STARTING_WINDOW) {
1150             Slog.v(TAG, "setAppStartingWindow: token=" + appToken
1151                     + " pkg=" + pkg + " transferFrom=" + transferFrom + " newTask=" + newTask
1152                     + " taskSwitch=" + taskSwitch + " processRunning=" + processRunning
1153                     + " allowTaskSnapshot=" + allowTaskSnapshot);
1154         }
1155         if (mAppWindowToken == null) {
1156             Slog.w(TAG_WM, "Attempted to set icon of non-existing app token: " + appToken);
1157             return false;
1158         }
1159         if (mAppWindowToken.getTask() == null) {
1160             // Can be removed after unification of Task and TaskRecord.
1161             Slog.w(TAG_WM, "Attempted to start a window to an app token not having attached to any"
1162                     + " task: " + appToken);
1163             return false;
1164         }
1165         return mAppWindowToken.addStartingWindow(pkg, theme, compatInfo, nonLocalizedLabel,
1166                 labelRes, icon, logo, windowFlags, transferFrom, newTask, taskSwitch,
1167                 processRunning, allowTaskSnapshot, activityCreated, fromRecents);
1168     }
1169 
1170     // TODO: Remove after unification
1171     @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)1172     AppWindowToken createAppWindow(WindowManagerService service, IApplicationToken token,
1173             boolean voiceInteraction, DisplayContent dc, long inputDispatchingTimeoutNanos,
1174             boolean fullscreen, boolean showForAllUsers, int targetSdk, int orientation,
1175             int rotationAnimationHint, boolean launchTaskBehind,
1176             boolean alwaysFocusable) {
1177         return new AppWindowToken(service, token, mActivityComponent, voiceInteraction, dc,
1178                 inputDispatchingTimeoutNanos, fullscreen, showForAllUsers, targetSdk, orientation,
1179                 rotationAnimationHint, launchTaskBehind, alwaysFocusable,
1180                 this);
1181     }
1182 
removeWindowContainer()1183     void removeWindowContainer() {
1184         if (mAtmService.mWindowManager.mRoot == null) return;
1185 
1186         final DisplayContent dc = mAtmService.mWindowManager.mRoot.getDisplayContent(
1187                 getDisplayId());
1188         if (dc == null) {
1189             Slog.w(TAG, "removeWindowContainer: Attempted to remove token: "
1190                     + appToken + " from non-existing displayId=" + getDisplayId());
1191             return;
1192         }
1193         // Resume key dispatching if it is currently paused before we remove the container.
1194         resumeKeyDispatchingLocked();
1195         dc.removeAppToken(appToken.asBinder());
1196     }
1197 
1198     /**
1199      * Reparents this activity into {@param newTask} at the provided {@param position}.  The caller
1200      * should ensure that the {@param newTask} is not already the parent of this activity.
1201      */
reparent(TaskRecord newTask, int position, String reason)1202     void reparent(TaskRecord newTask, int position, String reason) {
1203         if (mAppWindowToken == null) {
1204             Slog.w(TAG, "reparent: Attempted to reparent non-existing app token: " + appToken);
1205             return;
1206         }
1207         final TaskRecord prevTask = task;
1208         if (prevTask == newTask) {
1209             throw new IllegalArgumentException(reason + ": task=" + newTask
1210                     + " is already the parent of r=" + this);
1211         }
1212 
1213         // TODO: Ensure that we do not directly reparent activities across stacks, as that may leave
1214         //       the stacks in strange states. For now, we should use Task.reparent() to ensure that
1215         //       the stack is left in an OK state.
1216         if (prevTask != null && newTask != null && prevTask.getStack() != newTask.getStack()) {
1217             throw new IllegalArgumentException(reason + ": task=" + newTask
1218                     + " is in a different stack (" + newTask.getStackId() + ") than the parent of"
1219                     + " r=" + this + " (" + prevTask.getStackId() + ")");
1220         }
1221 
1222         mAppWindowToken.reparent(newTask.getTask(), position);
1223 
1224         // Reparenting prevents informing the parent stack of activity removal in the case that
1225         // the new stack has the same parent. we must manually signal here if this is not the case.
1226         final ActivityStack prevStack = prevTask.getStack();
1227 
1228         if (prevStack != newTask.getStack()) {
1229             prevStack.onActivityRemovedFromStack(this);
1230         }
1231         // Remove the activity from the old task and add it to the new task.
1232         prevTask.removeActivity(this, true /* reparenting */);
1233 
1234         newTask.addActivityAtIndex(position, this);
1235     }
1236 
isHomeIntent(Intent intent)1237     private boolean isHomeIntent(Intent intent) {
1238         return ACTION_MAIN.equals(intent.getAction())
1239                 && (intent.hasCategory(CATEGORY_HOME)
1240                 || intent.hasCategory(CATEGORY_SECONDARY_HOME))
1241                 && intent.getCategories().size() == 1
1242                 && intent.getData() == null
1243                 && intent.getType() == null;
1244     }
1245 
isMainIntent(Intent intent)1246     static boolean isMainIntent(Intent intent) {
1247         return ACTION_MAIN.equals(intent.getAction())
1248                 && intent.hasCategory(CATEGORY_LAUNCHER)
1249                 && intent.getCategories().size() == 1
1250                 && intent.getData() == null
1251                 && intent.getType() == null;
1252     }
1253 
canLaunchHomeActivity(int uid, ActivityRecord sourceRecord)1254     private boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) {
1255         if (uid == Process.myUid() || uid == 0) {
1256             // System process can launch home activity.
1257             return true;
1258         }
1259         // Allow the recents component to launch the home activity.
1260         final RecentTasks recentTasks = mStackSupervisor.mService.getRecentTasks();
1261         if (recentTasks != null && recentTasks.isCallerRecents(uid)) {
1262             return true;
1263         }
1264         // Resolver activity can launch home activity.
1265         return sourceRecord != null && sourceRecord.isResolverActivity();
1266     }
1267 
1268     /**
1269      * @return whether the given package name can launch an assist activity.
1270      */
canLaunchAssistActivity(String packageName)1271     private boolean canLaunchAssistActivity(String packageName) {
1272         final ComponentName assistComponent =
1273                 mAtmService.mActiveVoiceInteractionServiceComponent;
1274         if (assistComponent != null) {
1275             return assistComponent.getPackageName().equals(packageName);
1276         }
1277         return false;
1278     }
1279 
setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent, ActivityOptions options, ActivityRecord sourceRecord)1280     private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent,
1281             ActivityOptions options, ActivityRecord sourceRecord) {
1282         int activityType = ACTIVITY_TYPE_UNDEFINED;
1283         if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
1284                 && isHomeIntent(intent) && !isResolverActivity()) {
1285             // This sure looks like a home activity!
1286             activityType = ACTIVITY_TYPE_HOME;
1287 
1288             if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE
1289                     || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
1290                 // We only allow home activities to be resizeable if they explicitly requested it.
1291                 info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
1292             }
1293         } else if (mActivityComponent.getClassName().contains(LEGACY_RECENTS_PACKAGE_NAME)
1294                 || mAtmService.getRecentTasks().isRecentsComponent(mActivityComponent, appInfo.uid)) {
1295             activityType = ACTIVITY_TYPE_RECENTS;
1296         } else if (options != null && options.getLaunchActivityType() == ACTIVITY_TYPE_ASSISTANT
1297                 && canLaunchAssistActivity(launchedFromPackage)) {
1298             activityType = ACTIVITY_TYPE_ASSISTANT;
1299         }
1300         setActivityType(activityType);
1301     }
1302 
setTaskToAffiliateWith(TaskRecord taskToAffiliateWith)1303     void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
1304         if (launchMode != LAUNCH_SINGLE_INSTANCE && launchMode != LAUNCH_SINGLE_TASK) {
1305             task.setTaskToAffiliateWith(taskToAffiliateWith);
1306         }
1307     }
1308 
1309     /**
1310      * @return Stack value from current task, null if there is no task.
1311      */
getActivityStack()1312     <T extends ActivityStack> T getActivityStack() {
1313         return task != null ? (T) task.getStack() : null;
1314     }
1315 
getStackId()1316     int getStackId() {
1317         return getActivityStack() != null ? getActivityStack().mStackId : INVALID_STACK_ID;
1318     }
1319 
getDisplay()1320     ActivityDisplay getDisplay() {
1321         final ActivityStack stack = getActivityStack();
1322         return stack != null ? stack.getDisplay() : null;
1323     }
1324 
changeWindowTranslucency(boolean toOpaque)1325     boolean changeWindowTranslucency(boolean toOpaque) {
1326         if (fullscreen == toOpaque) {
1327             return false;
1328         }
1329 
1330         // Keep track of the number of fullscreen activities in this task.
1331         task.numFullscreen += toOpaque ? +1 : -1;
1332 
1333         fullscreen = toOpaque;
1334         return true;
1335     }
1336 
takeFromHistory()1337     void takeFromHistory() {
1338         if (inHistory) {
1339             inHistory = false;
1340             if (task != null && !finishing) {
1341                 task = null;
1342             }
1343             clearOptionsLocked();
1344         }
1345     }
1346 
isInHistory()1347     boolean isInHistory() {
1348         return inHistory;
1349     }
1350 
isInStackLocked()1351     boolean isInStackLocked() {
1352         final ActivityStack stack = getActivityStack();
1353         return stack != null && stack.isInStackLocked(this) != null;
1354     }
1355 
isPersistable()1356     boolean isPersistable() {
1357         return (info.persistableMode == PERSIST_ROOT_ONLY ||
1358                 info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
1359                 (intent == null || (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
1360     }
1361 
isFocusable()1362     boolean isFocusable() {
1363         return mRootActivityContainer.isFocusable(this, isAlwaysFocusable());
1364     }
1365 
isResizeable()1366     boolean isResizeable() {
1367         return ActivityInfo.isResizeableMode(info.resizeMode) || info.supportsPictureInPicture();
1368     }
1369 
1370     /**
1371      * @return whether this activity is non-resizeable or forced to be resizeable
1372      */
isNonResizableOrForcedResizable()1373     boolean isNonResizableOrForcedResizable() {
1374         return info.resizeMode != RESIZE_MODE_RESIZEABLE
1375                 && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
1376     }
1377 
1378     /**
1379      * @return whether this activity supports PiP multi-window and can be put in the pinned stack.
1380      */
supportsPictureInPicture()1381     boolean supportsPictureInPicture() {
1382         return mAtmService.mSupportsPictureInPicture && isActivityTypeStandardOrUndefined()
1383                 && info.supportsPictureInPicture();
1384     }
1385 
1386     /**
1387      * @return whether this activity supports split-screen multi-window and can be put in the docked
1388      *         stack.
1389      */
1390     @Override
supportsSplitScreenWindowingMode()1391     public boolean supportsSplitScreenWindowingMode() {
1392         // An activity can not be docked even if it is considered resizeable because it only
1393         // supports picture-in-picture mode but has a non-resizeable resizeMode
1394         return super.supportsSplitScreenWindowingMode()
1395                 && mAtmService.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
1396     }
1397 
1398     /**
1399      * @return whether this activity supports freeform multi-window and can be put in the freeform
1400      *         stack.
1401      */
supportsFreeform()1402     boolean supportsFreeform() {
1403         return mAtmService.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
1404     }
1405 
1406     /**
1407      * @return whether this activity supports non-PiP multi-window.
1408      */
supportsResizeableMultiWindow()1409     private boolean supportsResizeableMultiWindow() {
1410         return mAtmService.mSupportsMultiWindow && !isActivityTypeHome()
1411                 && (ActivityInfo.isResizeableMode(info.resizeMode)
1412                         || mAtmService.mForceResizableActivities);
1413     }
1414 
1415     /**
1416      * Check whether this activity can be launched on the specified display.
1417      *
1418      * @param displayId Target display id.
1419      * @return {@code true} if either it is the default display or this activity can be put on a
1420      *         secondary screen.
1421      */
canBeLaunchedOnDisplay(int displayId)1422     boolean canBeLaunchedOnDisplay(int displayId) {
1423         return mAtmService.mStackSupervisor.canPlaceEntityOnDisplay(displayId, launchedFromPid,
1424                 launchedFromUid, info);
1425     }
1426 
1427     /**
1428      * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
1429      *         the activity has requested to enter PiP when it would otherwise be stopped.
1430      *
1431      * @return whether this activity is currently allowed to enter PIP.
1432      */
checkEnterPictureInPictureState(String caller, boolean beforeStopping)1433     boolean checkEnterPictureInPictureState(String caller, boolean beforeStopping) {
1434         if (!supportsPictureInPicture()) {
1435             return false;
1436         }
1437 
1438         // Check app-ops and see if PiP is supported for this package
1439         if (!checkEnterPictureInPictureAppOpsState()) {
1440             return false;
1441         }
1442 
1443         // Check to see if we are in VR mode, and disallow PiP if so
1444         if (mAtmService.shouldDisableNonVrUiLocked()) {
1445             return false;
1446         }
1447 
1448         boolean isKeyguardLocked = mAtmService.isKeyguardLocked();
1449         boolean isCurrentAppLocked =
1450                 mAtmService.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
1451         final ActivityDisplay display = getDisplay();
1452         boolean hasPinnedStack = display != null && display.hasPinnedStack();
1453         // Don't return early if !isNotLocked, since we want to throw an exception if the activity
1454         // is in an incorrect state
1455         boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
1456 
1457         // We don't allow auto-PiP when something else is already pipped.
1458         if (beforeStopping && hasPinnedStack) {
1459             return false;
1460         }
1461 
1462         switch (mState) {
1463             case RESUMED:
1464                 // When visible, allow entering PiP if the app is not locked.  If it is over the
1465                 // keyguard, then we will prompt to unlock in the caller before entering PiP.
1466                 return !isCurrentAppLocked &&
1467                         (supportsEnterPipOnTaskSwitch || !beforeStopping);
1468             case PAUSING:
1469             case PAUSED:
1470                 // When pausing, then only allow enter PiP as in the resume state, and in addition,
1471                 // require that there is not an existing PiP activity and that the current system
1472                 // state supports entering PiP
1473                 return isNotLockedOrOnKeyguard && !hasPinnedStack
1474                         && supportsEnterPipOnTaskSwitch;
1475             case STOPPING:
1476                 // When stopping in a valid state, then only allow enter PiP as in the pause state.
1477                 // Otherwise, fall through to throw an exception if the caller is trying to enter
1478                 // PiP in an invalid stopping state.
1479                 if (supportsEnterPipOnTaskSwitch) {
1480                     return isNotLockedOrOnKeyguard && !hasPinnedStack;
1481                 }
1482             default:
1483                 return false;
1484         }
1485     }
1486 
1487     /**
1488      * @return Whether AppOps allows this package to enter picture-in-picture.
1489      */
checkEnterPictureInPictureAppOpsState()1490     private boolean checkEnterPictureInPictureAppOpsState() {
1491         return mAtmService.getAppOpsService().checkOperation(
1492                 OP_PICTURE_IN_PICTURE, appInfo.uid, packageName) == MODE_ALLOWED;
1493     }
1494 
isAlwaysFocusable()1495     boolean isAlwaysFocusable() {
1496         return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
1497     }
1498 
1499     /** Move activity with its stack to front and make the stack focused. */
moveFocusableActivityToTop(String reason)1500     boolean moveFocusableActivityToTop(String reason) {
1501         if (!isFocusable()) {
1502             if (DEBUG_FOCUS) {
1503                 Slog.d(TAG_FOCUS, "moveActivityStackToFront: unfocusable activity=" + this);
1504             }
1505             return false;
1506         }
1507 
1508         final TaskRecord task = getTaskRecord();
1509         final ActivityStack stack = getActivityStack();
1510         if (stack == null) {
1511             Slog.w(TAG, "moveActivityStackToFront: invalid task or stack: activity="
1512                     + this + " task=" + task);
1513             return false;
1514         }
1515 
1516         if (mRootActivityContainer.getTopResumedActivity() == this) {
1517             if (DEBUG_FOCUS) {
1518                 Slog.d(TAG_FOCUS, "moveActivityStackToFront: already on top, activity=" + this);
1519             }
1520             return false;
1521         }
1522 
1523         if (DEBUG_FOCUS) {
1524             Slog.d(TAG_FOCUS, "moveActivityStackToFront: activity=" + this);
1525         }
1526 
1527         stack.moveToFront(reason, task);
1528         // Report top activity change to tracking services and WM
1529         if (mRootActivityContainer.getTopResumedActivity() == this) {
1530             // TODO(b/111361570): Support multiple focused apps in WM
1531             mAtmService.setResumedActivityUncheckLocked(this, reason);
1532         }
1533         return true;
1534     }
1535 
makeFinishingLocked()1536     void makeFinishingLocked() {
1537         if (finishing) {
1538             return;
1539         }
1540         finishing = true;
1541         if (stopped) {
1542             clearOptionsLocked();
1543         }
1544 
1545         if (mAtmService != null) {
1546             mAtmService.getTaskChangeNotificationController().notifyTaskStackChanged();
1547         }
1548     }
1549 
getUriPermissionsLocked()1550     UriPermissionOwner getUriPermissionsLocked() {
1551         if (uriPermissions == null) {
1552             uriPermissions = new UriPermissionOwner(mAtmService.mUgmInternal, this);
1553         }
1554         return uriPermissions;
1555     }
1556 
addResultLocked(ActivityRecord from, String resultWho, int requestCode, int resultCode, Intent resultData)1557     void addResultLocked(ActivityRecord from, String resultWho,
1558             int requestCode, int resultCode,
1559             Intent resultData) {
1560         ActivityResult r = new ActivityResult(from, resultWho,
1561                 requestCode, resultCode, resultData);
1562         if (results == null) {
1563             results = new ArrayList<ResultInfo>();
1564         }
1565         results.add(r);
1566     }
1567 
removeResultsLocked(ActivityRecord from, String resultWho, int requestCode)1568     void removeResultsLocked(ActivityRecord from, String resultWho,
1569             int requestCode) {
1570         if (results != null) {
1571             for (int i=results.size()-1; i>=0; i--) {
1572                 ActivityResult r = (ActivityResult)results.get(i);
1573                 if (r.mFrom != from) continue;
1574                 if (r.mResultWho == null) {
1575                     if (resultWho != null) continue;
1576                 } else {
1577                     if (!r.mResultWho.equals(resultWho)) continue;
1578                 }
1579                 if (r.mRequestCode != requestCode) continue;
1580 
1581                 results.remove(i);
1582             }
1583         }
1584     }
1585 
addNewIntentLocked(ReferrerIntent intent)1586     private void addNewIntentLocked(ReferrerIntent intent) {
1587         if (newIntents == null) {
1588             newIntents = new ArrayList<>();
1589         }
1590         newIntents.add(intent);
1591     }
1592 
isSleeping()1593     final boolean isSleeping() {
1594         final ActivityStack stack = getActivityStack();
1595         return stack != null ? stack.shouldSleepActivities() : mAtmService.isSleepingLocked();
1596     }
1597 
1598     /**
1599      * Deliver a new Intent to an existing activity, so that its onNewIntent()
1600      * method will be called at the proper time.
1601      */
deliverNewIntentLocked(int callingUid, Intent intent, String referrer)1602     final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
1603         // The activity now gets access to the data associated with this Intent.
1604         mAtmService.mUgmInternal.grantUriPermissionFromIntent(callingUid, packageName,
1605                 intent, getUriPermissionsLocked(), mUserId);
1606         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
1607         boolean unsent = true;
1608         final boolean isTopActivityWhileSleeping = isTopRunningActivity() && isSleeping();
1609 
1610         // We want to immediately deliver the intent to the activity if:
1611         // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
1612         //   the user to see the visual effects caused by the intent delivery now.
1613         // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
1614         if ((mState == RESUMED || mState == PAUSED || isTopActivityWhileSleeping)
1615                 && attachedToProcess()) {
1616             try {
1617                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
1618                 ar.add(rintent);
1619                 // Making sure the client state is RESUMED after transaction completed and doing
1620                 // so only if activity is currently RESUMED. Otherwise, client may have extra
1621                 // life-cycle calls to RESUMED (and PAUSED later).
1622                 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
1623                         NewIntentItem.obtain(ar, mState == RESUMED));
1624                 unsent = false;
1625             } catch (RemoteException e) {
1626                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
1627             } catch (NullPointerException e) {
1628                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
1629             }
1630         }
1631         if (unsent) {
1632             addNewIntentLocked(rintent);
1633         }
1634     }
1635 
updateOptionsLocked(ActivityOptions options)1636     void updateOptionsLocked(ActivityOptions options) {
1637         if (options != null) {
1638             if (DEBUG_TRANSITION) Slog.i(TAG, "Update options for " + this);
1639             if (pendingOptions != null) {
1640                 pendingOptions.abort();
1641             }
1642             pendingOptions = options;
1643         }
1644     }
1645 
applyOptionsLocked()1646     void applyOptionsLocked() {
1647         if (pendingOptions != null
1648                 && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
1649             if (DEBUG_TRANSITION) Slog.i(TAG, "Applying options for " + this);
1650             applyOptionsLocked(pendingOptions, intent);
1651             if (task == null) {
1652                 clearOptionsLocked(false /* withAbort */);
1653             } else {
1654                 // This will clear the options for all the ActivityRecords for this Task.
1655                 task.clearAllPendingOptions();
1656             }
1657         }
1658     }
1659 
1660     /**
1661      * Apply override app transition base on options & animation type.
1662      */
applyOptionsLocked(ActivityOptions pendingOptions, Intent intent)1663     void applyOptionsLocked(ActivityOptions pendingOptions, Intent intent) {
1664         final int animationType = pendingOptions.getAnimationType();
1665         final DisplayContent displayContent = mAppWindowToken.getDisplayContent();
1666         switch (animationType) {
1667             case ANIM_CUSTOM:
1668                 displayContent.mAppTransition.overridePendingAppTransition(
1669                         pendingOptions.getPackageName(),
1670                         pendingOptions.getCustomEnterResId(),
1671                         pendingOptions.getCustomExitResId(),
1672                         pendingOptions.getOnAnimationStartListener());
1673                 break;
1674             case ANIM_CLIP_REVEAL:
1675                 displayContent.mAppTransition.overridePendingAppTransitionClipReveal(
1676                         pendingOptions.getStartX(), pendingOptions.getStartY(),
1677                         pendingOptions.getWidth(), pendingOptions.getHeight());
1678                 if (intent.getSourceBounds() == null) {
1679                     intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1680                             pendingOptions.getStartY(),
1681                             pendingOptions.getStartX() + pendingOptions.getWidth(),
1682                             pendingOptions.getStartY() + pendingOptions.getHeight()));
1683                 }
1684                 break;
1685             case ANIM_SCALE_UP:
1686                 displayContent.mAppTransition.overridePendingAppTransitionScaleUp(
1687                         pendingOptions.getStartX(), pendingOptions.getStartY(),
1688                         pendingOptions.getWidth(), pendingOptions.getHeight());
1689                 if (intent.getSourceBounds() == null) {
1690                     intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1691                             pendingOptions.getStartY(),
1692                             pendingOptions.getStartX() + pendingOptions.getWidth(),
1693                             pendingOptions.getStartY() + pendingOptions.getHeight()));
1694                 }
1695                 break;
1696             case ANIM_THUMBNAIL_SCALE_UP:
1697             case ANIM_THUMBNAIL_SCALE_DOWN:
1698                 final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
1699                 final GraphicBuffer buffer = pendingOptions.getThumbnail();
1700                 displayContent.mAppTransition.overridePendingAppTransitionThumb(buffer,
1701                         pendingOptions.getStartX(), pendingOptions.getStartY(),
1702                         pendingOptions.getOnAnimationStartListener(),
1703                         scaleUp);
1704                 if (intent.getSourceBounds() == null && buffer != null) {
1705                     intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1706                             pendingOptions.getStartY(),
1707                             pendingOptions.getStartX() + buffer.getWidth(),
1708                             pendingOptions.getStartY() + buffer.getHeight()));
1709                 }
1710                 break;
1711             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
1712             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
1713                 final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
1714                 final IAppTransitionAnimationSpecsFuture specsFuture =
1715                         pendingOptions.getSpecsFuture();
1716                 if (specsFuture != null) {
1717                     displayContent.mAppTransition.overridePendingAppTransitionMultiThumbFuture(
1718                             specsFuture, pendingOptions.getOnAnimationStartListener(),
1719                             animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
1720                 } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
1721                         && specs != null) {
1722                     displayContent.mAppTransition.overridePendingAppTransitionMultiThumb(
1723                             specs, pendingOptions.getOnAnimationStartListener(),
1724                             pendingOptions.getAnimationFinishedListener(), false);
1725                 } else {
1726                     displayContent.mAppTransition.overridePendingAppTransitionAspectScaledThumb(
1727                             pendingOptions.getThumbnail(),
1728                             pendingOptions.getStartX(), pendingOptions.getStartY(),
1729                             pendingOptions.getWidth(), pendingOptions.getHeight(),
1730                             pendingOptions.getOnAnimationStartListener(),
1731                             (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
1732                     if (intent.getSourceBounds() == null) {
1733                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1734                                 pendingOptions.getStartY(),
1735                                 pendingOptions.getStartX() + pendingOptions.getWidth(),
1736                                 pendingOptions.getStartY() + pendingOptions.getHeight()));
1737                     }
1738                 }
1739                 break;
1740             case ANIM_OPEN_CROSS_PROFILE_APPS:
1741                 displayContent.mAppTransition
1742                         .overridePendingAppTransitionStartCrossProfileApps();
1743                 break;
1744             case ANIM_REMOTE_ANIMATION:
1745                 displayContent.mAppTransition.overridePendingAppTransitionRemote(
1746                         pendingOptions.getRemoteAnimationAdapter());
1747                 break;
1748             case ANIM_NONE:
1749                 break;
1750             default:
1751                 Slog.e(TAG_WM, "applyOptionsLocked: Unknown animationType=" + animationType);
1752                 break;
1753         }
1754     }
1755 
getOptionsForTargetActivityLocked()1756     ActivityOptions getOptionsForTargetActivityLocked() {
1757         return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
1758     }
1759 
clearOptionsLocked()1760     void clearOptionsLocked() {
1761         clearOptionsLocked(true /* withAbort */);
1762     }
1763 
clearOptionsLocked(boolean withAbort)1764     void clearOptionsLocked(boolean withAbort) {
1765         if (withAbort && pendingOptions != null) {
1766             pendingOptions.abort();
1767         }
1768         pendingOptions = null;
1769     }
1770 
takeOptionsLocked(boolean fromClient)1771     ActivityOptions takeOptionsLocked(boolean fromClient) {
1772         if (DEBUG_TRANSITION) Slog.i(TAG, "Taking options for " + this + " callers="
1773                 + Debug.getCallers(6));
1774         ActivityOptions opts = pendingOptions;
1775 
1776         // If we are trying to take activity options from the client, do not null it out if it's a
1777         // remote animation as the client doesn't need it ever. This is a workaround when client is
1778         // faster to take the options than we are to resume the next activity.
1779         // TODO (b/132432864): Fix the root cause of these transition preparing/applying options
1780         // timing somehow
1781         if (!fromClient || opts == null || opts.getRemoteAnimationAdapter() == null) {
1782             pendingOptions = null;
1783         }
1784         return opts;
1785     }
1786 
removeUriPermissionsLocked()1787     void removeUriPermissionsLocked() {
1788         if (uriPermissions != null) {
1789             uriPermissions.removeUriPermissions();
1790             uriPermissions = null;
1791         }
1792     }
1793 
pauseKeyDispatchingLocked()1794     void pauseKeyDispatchingLocked() {
1795         if (!keysPaused) {
1796             keysPaused = true;
1797 
1798             // TODO: remove the check after unification with AppWindowToken. The DC check is not
1799             // needed after no mock mAppWindowToken in tests.
1800             if (mAppWindowToken != null && mAppWindowToken.getDisplayContent() != null) {
1801                 mAppWindowToken.getDisplayContent().getInputMonitor().pauseDispatchingLw(
1802                         mAppWindowToken);
1803             }
1804         }
1805     }
1806 
resumeKeyDispatchingLocked()1807     void resumeKeyDispatchingLocked() {
1808         if (keysPaused) {
1809             keysPaused = false;
1810 
1811             // TODO: remove the check after unification with AppWindowToken. The DC check is not
1812             // needed after no mock mAppWindowToken in tests.
1813             if (mAppWindowToken != null && mAppWindowToken.getDisplayContent() != null) {
1814                 mAppWindowToken.getDisplayContent().getInputMonitor().resumeDispatchingLw(
1815                         mAppWindowToken);
1816             }
1817         }
1818     }
1819 
updateTaskDescription(CharSequence description)1820     private void updateTaskDescription(CharSequence description) {
1821         task.lastDescription = description;
1822     }
1823 
setDeferHidingClient(boolean deferHidingClient)1824     void setDeferHidingClient(boolean deferHidingClient) {
1825         if (mDeferHidingClient == deferHidingClient) {
1826             return;
1827         }
1828         mDeferHidingClient = deferHidingClient;
1829         if (!mDeferHidingClient && !visible) {
1830             // Hiding the client is no longer deferred and the app isn't visible still, go ahead and
1831             // update the visibility.
1832             setVisibility(false);
1833         }
1834     }
1835 
setVisibility(boolean visible)1836     void setVisibility(boolean visible) {
1837         if (mAppWindowToken == null) {
1838             Slog.w(TAG_WM, "Attempted to set visibility of non-existing app token: "
1839                     + appToken);
1840             return;
1841         }
1842         mAppWindowToken.setVisibility(visible, mDeferHidingClient);
1843         mStackSupervisor.getActivityMetricsLogger().notifyVisibilityChanged(this);
1844     }
1845 
1846     // TODO: Look into merging with #commitVisibility()
setVisible(boolean newVisible)1847     void setVisible(boolean newVisible) {
1848         visible = newVisible;
1849         mDeferHidingClient = !visible && mDeferHidingClient;
1850         setVisibility(visible);
1851         mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
1852     }
1853 
setState(ActivityState state, String reason)1854     void setState(ActivityState state, String reason) {
1855         if (DEBUG_STATES) Slog.v(TAG_STATES, "State movement: " + this + " from:" + getState()
1856                         + " to:" + state + " reason:" + reason);
1857 
1858         if (state == mState) {
1859             // No need to do anything if state doesn't change.
1860             if (DEBUG_STATES) Slog.v(TAG_STATES, "State unchanged from:" + state);
1861             return;
1862         }
1863 
1864         mState = state;
1865 
1866         final TaskRecord parent = getTaskRecord();
1867 
1868         if (parent != null) {
1869             parent.onActivityStateChanged(this, state, reason);
1870         }
1871 
1872         // The WindowManager interprets the app stopping signal as
1873         // an indication that the Surface will eventually be destroyed.
1874         // This however isn't necessarily true if we are going to sleep.
1875         if (state == STOPPING && !isSleeping()) {
1876             if (mAppWindowToken == null) {
1877                 Slog.w(TAG_WM, "Attempted to notify stopping on non-existing app token: "
1878                         + appToken);
1879                 return;
1880             }
1881             mAppWindowToken.detachChildren();
1882         }
1883 
1884         if (state == RESUMED) {
1885             mAtmService.updateBatteryStats(this, true);
1886             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_RESUMED);
1887         } else if (state == PAUSED) {
1888             mAtmService.updateBatteryStats(this, false);
1889             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_PAUSED);
1890         } else if (state == STOPPED) {
1891             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_STOPPED);
1892         } else if (state == DESTROYED) {
1893             mAtmService.updateActivityUsageStats(this, Event.ACTIVITY_DESTROYED);
1894         }
1895     }
1896 
getState()1897     ActivityState getState() {
1898         return mState;
1899     }
1900 
1901     /**
1902      * Returns {@code true} if the Activity is in the specified state.
1903      */
isState(ActivityState state)1904     boolean isState(ActivityState state) {
1905         return state == mState;
1906     }
1907 
1908     /**
1909      * Returns {@code true} if the Activity is in one of the specified states.
1910      */
isState(ActivityState state1, ActivityState state2)1911     boolean isState(ActivityState state1, ActivityState state2) {
1912         return state1 == mState || state2 == mState;
1913     }
1914 
1915     /**
1916      * Returns {@code true} if the Activity is in one of the specified states.
1917      */
isState(ActivityState state1, ActivityState state2, ActivityState state3)1918     boolean isState(ActivityState state1, ActivityState state2, ActivityState state3) {
1919         return state1 == mState || state2 == mState || state3 == mState;
1920     }
1921 
1922     /**
1923      * Returns {@code true} if the Activity is in one of the specified states.
1924      */
isState(ActivityState state1, ActivityState state2, ActivityState state3, ActivityState state4)1925     boolean isState(ActivityState state1, ActivityState state2, ActivityState state3,
1926             ActivityState state4) {
1927         return state1 == mState || state2 == mState || state3 == mState || state4 == mState;
1928     }
1929 
notifyAppResumed(boolean wasStopped)1930     void notifyAppResumed(boolean wasStopped) {
1931         if (mAppWindowToken == null) {
1932             Slog.w(TAG_WM, "Attempted to notify resumed of non-existing app token: "
1933                     + appToken);
1934             return;
1935         }
1936         mAppWindowToken.notifyAppResumed(wasStopped);
1937     }
1938 
notifyUnknownVisibilityLaunched()1939     void notifyUnknownVisibilityLaunched() {
1940 
1941         // No display activities never add a window, so there is no point in waiting them for
1942         // relayout.
1943         if (!noDisplay) {
1944             if (mAppWindowToken != null) {
1945                 mAppWindowToken.getDisplayContent().mUnknownAppVisibilityController
1946                         .notifyLaunched(mAppWindowToken);
1947             }
1948         }
1949     }
1950 
1951     /**
1952      * @return true if the input activity should be made visible, ignoring any effect Keyguard
1953      * might have on the visibility
1954      *
1955      * TODO(b/123540470): Combine this method and {@link #shouldBeVisible(boolean)}.
1956      *
1957      * @see {@link ActivityStack#checkKeyguardVisibility}
1958      */
shouldBeVisibleIgnoringKeyguard(boolean behindFullscreenActivity)1959     boolean shouldBeVisibleIgnoringKeyguard(boolean behindFullscreenActivity) {
1960         if (!okToShowLocked()) {
1961             return false;
1962         }
1963 
1964         return !behindFullscreenActivity || mLaunchTaskBehind;
1965     }
1966 
shouldBeVisible(boolean behindFullscreenActivity)1967     boolean shouldBeVisible(boolean behindFullscreenActivity) {
1968         // Check whether activity should be visible without Keyguard influence
1969         visibleIgnoringKeyguard = shouldBeVisibleIgnoringKeyguard(behindFullscreenActivity);
1970 
1971         final ActivityStack stack = getActivityStack();
1972         if (stack == null) {
1973             return false;
1974         }
1975 
1976         // Whether the activity is on the sleeping display.
1977         // TODO(b/129750406): This should be applied for the default display, too.
1978         final boolean isDisplaySleeping = getDisplay().isSleeping()
1979                 && getDisplayId() != DEFAULT_DISPLAY;
1980         // Whether this activity is the top activity of this stack.
1981         final boolean isTop = this == stack.getTopActivity();
1982         // Exclude the case where this is the top activity in a pinned stack.
1983         final boolean isTopNotPinnedStack = stack.isAttached()
1984                 && stack.getDisplay().isTopNotPinnedStack(stack);
1985         // Now check whether it's really visible depending on Keyguard state, and update
1986         // {@link ActivityStack} internal states.
1987         final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
1988                 visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
1989         return visibleIgnoringDisplayStatus && !isDisplaySleeping;
1990     }
1991 
shouldBeVisible()1992     boolean shouldBeVisible() {
1993         final ActivityStack stack = getActivityStack();
1994         if (stack == null) {
1995             return false;
1996         }
1997 
1998         // TODO: Use real value of behindFullscreenActivity calculated using the same logic in
1999         // ActivityStack#ensureActivitiesVisibleLocked().
2000         return shouldBeVisible(!stack.shouldBeVisible(null /* starting */));
2001     }
2002 
makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient)2003     void makeVisibleIfNeeded(ActivityRecord starting, boolean reportToClient) {
2004         // This activity is not currently visible, but is running. Tell it to become visible.
2005         if (mState == RESUMED || this == starting) {
2006             if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
2007                     "Not making visible, r=" + this + " state=" + mState + " starting=" + starting);
2008             return;
2009         }
2010 
2011         // If this activity is paused, tell it to now show its window.
2012         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
2013                 "Making visible and scheduling visibility: " + this);
2014         final ActivityStack stack = getActivityStack();
2015         try {
2016             if (stack.mTranslucentActivityWaiting != null) {
2017                 updateOptionsLocked(returningOptions);
2018                 stack.mUndrawnActivitiesBelowTopTranslucent.add(this);
2019             }
2020             setVisible(true);
2021             sleeping = false;
2022             app.postPendingUiCleanMsg(true);
2023             if (reportToClient) {
2024                 makeClientVisible();
2025             } else {
2026                 mClientVisibilityDeferred = true;
2027             }
2028             // The activity may be waiting for stop, but that is no longer appropriate for it.
2029             mStackSupervisor.mStoppingActivities.remove(this);
2030             mStackSupervisor.mGoingToSleepActivities.remove(this);
2031         } catch (Exception e) {
2032             // Just skip on any failure; we'll make it visible when it next restarts.
2033             Slog.w(TAG, "Exception thrown making visible: " + intent.getComponent(), e);
2034         }
2035         handleAlreadyVisible();
2036     }
2037 
2038     /** Send visibility change message to the client and pause if needed. */
makeClientVisible()2039     void makeClientVisible() {
2040         mClientVisibilityDeferred = false;
2041         try {
2042             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
2043                     WindowVisibilityItem.obtain(true /* showWindow */));
2044             makeActiveIfNeeded(null /* activeActivity*/);
2045             if (isState(STOPPING, STOPPED) && isFocusable()) {
2046                 // #shouldMakeActive() only evaluates the topmost activities in task, so
2047                 // activities that are not the topmost in task are not being resumed or paused.
2048                 // For activities that are still in STOPPING or STOPPED state, updates the state
2049                 // to PAUSE at least when making it visible.
2050                 setState(PAUSED, "makeClientVisible");
2051             }
2052         } catch (Exception e) {
2053             Slog.w(TAG, "Exception thrown sending visibility update: " + intent.getComponent(), e);
2054         }
2055     }
2056 
2057     /**
2058      * Make activity resumed or paused if needed.
2059      * @param activeActivity an activity that is resumed or just completed pause action.
2060      *                       We won't change the state of this activity.
2061      */
makeActiveIfNeeded(ActivityRecord activeActivity)2062     boolean makeActiveIfNeeded(ActivityRecord activeActivity) {
2063         if (shouldResumeActivity(activeActivity)) {
2064             if (DEBUG_VISIBILITY) {
2065                 Slog.v("TAG_VISIBILITY", "Resume visible activity, " + this);
2066             }
2067             return getActivityStack().resumeTopActivityUncheckedLocked(activeActivity /* prev */,
2068                     null /* options */);
2069         } else if (shouldPauseActivity(activeActivity)) {
2070             if (DEBUG_VISIBILITY) {
2071                 Slog.v("TAG_VISIBILITY", "Pause visible activity, " + this);
2072             }
2073             // An activity must be in the {@link PAUSING} state for the system to validate
2074             // the move to {@link PAUSED}.
2075             setState(PAUSING, "makeVisibleIfNeeded");
2076             try {
2077                 mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
2078                         PauseActivityItem.obtain(finishing, false /* userLeaving */,
2079                                 configChangeFlags, false /* dontReport */));
2080             } catch (Exception e) {
2081                 Slog.w(TAG, "Exception thrown sending pause: " + intent.getComponent(), e);
2082             }
2083         }
2084         return false;
2085     }
2086 
2087     /**
2088      * Check if activity should be moved to PAUSED state. The activity:
2089      * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
2090      * - should be non-focusable
2091      * - should not be currently pausing or paused
2092      * @param activeActivity the activity that is active or just completed pause action. We won't
2093      *                       resume if this activity is active.
2094      */
shouldPauseActivity(ActivityRecord activeActivity)2095     private boolean shouldPauseActivity(ActivityRecord activeActivity) {
2096         return shouldMakeActive(activeActivity) && !isFocusable() && !isState(PAUSING, PAUSED);
2097     }
2098 
2099     /**
2100      * Check if activity should be moved to RESUMED state. The activity:
2101      * - should be eligible to be made active (see {@link #shouldMakeActive(ActivityRecord)})
2102      * - should be focusable
2103      * @param activeActivity the activity that is active or just completed pause action. We won't
2104      *                       resume if this activity is active.
2105      */
2106     @VisibleForTesting
shouldResumeActivity(ActivityRecord activeActivity)2107     boolean shouldResumeActivity(ActivityRecord activeActivity) {
2108         return shouldMakeActive(activeActivity) && isFocusable() && !isState(RESUMED)
2109                 && getActivityStack().getVisibility(activeActivity) == STACK_VISIBILITY_VISIBLE;
2110     }
2111 
2112     /**
2113      * Check if activity is eligible to be made active (resumed of paused). The activity:
2114      * - should be paused, stopped or stopping
2115      * - should not be the currently active one or launching behind other tasks
2116      * - should be either the topmost in task, or right below the top activity that is finishing
2117      * If all of these conditions are not met at the same time, the activity cannot be made active.
2118      */
2119     @VisibleForTesting
shouldMakeActive(ActivityRecord activeActivity)2120     boolean shouldMakeActive(ActivityRecord activeActivity) {
2121         // If the activity is stopped, stopping, cycle to an active state. We avoid doing
2122         // this when there is an activity waiting to become translucent as the extra binder
2123         // calls will lead to noticeable jank. A later call to
2124         // ActivityStack#ensureActivitiesVisibleLocked will bring the activity to a proper
2125         // active state.
2126         if (!isState(RESUMED, PAUSED, STOPPED, STOPPING)
2127                 || getActivityStack().mTranslucentActivityWaiting != null) {
2128             return false;
2129         }
2130 
2131         if (this == activeActivity) {
2132             return false;
2133         }
2134 
2135         if (!mStackSupervisor.readyToResume()) {
2136             // Making active is currently deferred (e.g. because an activity launch is in progress).
2137             return false;
2138         }
2139 
2140         if (this.mLaunchTaskBehind) {
2141             // This activity is being launched from behind, which means that it's not intended to be
2142             // presented to user right now, even if it's set to be visible.
2143             return false;
2144         }
2145 
2146         // Check if position in task allows to become paused
2147         final int positionInTask = task.mActivities.indexOf(this);
2148         if (positionInTask == -1) {
2149             throw new IllegalStateException("Activity not found in its task");
2150         }
2151         if (positionInTask == task.mActivities.size() - 1) {
2152             // It's the topmost activity in the task - should become resumed now
2153             return true;
2154         }
2155         // Check if activity above is finishing now and this one becomes the topmost in task.
2156         final ActivityRecord activityAbove = task.mActivities.get(positionInTask + 1);
2157         if (activityAbove.finishing && results == null) {
2158             // We will only allow making active if activity above wasn't launched for result.
2159             // Otherwise it will cause this activity to resume before getting result.
2160             return true;
2161         }
2162         return false;
2163     }
2164 
handleAlreadyVisible()2165     boolean handleAlreadyVisible() {
2166         stopFreezingScreenLocked(false);
2167         try {
2168             if (returningOptions != null) {
2169                 app.getThread().scheduleOnNewActivityOptions(appToken, returningOptions.toBundle());
2170             }
2171         } catch(RemoteException e) {
2172         }
2173         return mState == RESUMED;
2174     }
2175 
activityResumedLocked(IBinder token)2176     static void activityResumedLocked(IBinder token) {
2177         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2178         if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
2179         if (r == null) {
2180             // If an app reports resumed after a long delay, the record on server side might have
2181             // been removed (e.g. destroy timeout), so the token could be null.
2182             return;
2183         }
2184         r.icicle = null;
2185         r.haveState = false;
2186 
2187         final ActivityDisplay display = r.getDisplay();
2188         if (display != null) {
2189             display.handleActivitySizeCompatModeIfNeeded(r);
2190         }
2191     }
2192 
2193     /**
2194      * Once we know that we have asked an application to put an activity in the resumed state
2195      * (either by launching it or explicitly telling it), this function updates the rest of our
2196      * state to match that fact.
2197      */
completeResumeLocked()2198     void completeResumeLocked() {
2199         final boolean wasVisible = visible;
2200         setVisible(true);
2201         if (!wasVisible) {
2202             // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
2203             mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
2204         }
2205         idle = false;
2206         results = null;
2207         newIntents = null;
2208         stopped = false;
2209 
2210         if (isActivityTypeHome()) {
2211             mStackSupervisor.updateHomeProcess(task.mActivities.get(0).app);
2212         }
2213 
2214         if (nowVisible) {
2215             mStackSupervisor.stopWaitingForActivityVisible(this);
2216         }
2217 
2218         // Schedule an idle timeout in case the app doesn't do it for us.
2219         mStackSupervisor.scheduleIdleTimeoutLocked(this);
2220 
2221         mStackSupervisor.reportResumedActivityLocked(this);
2222 
2223         resumeKeyDispatchingLocked();
2224         final ActivityStack stack = getActivityStack();
2225         mStackSupervisor.mNoAnimActivities.clear();
2226 
2227         // Mark the point when the activity is resuming
2228         // TODO: To be more accurate, the mark should be before the onCreate,
2229         //       not after the onResume. But for subsequent starts, onResume is fine.
2230         if (hasProcess()) {
2231             cpuTimeAtResume = app.getCpuTime();
2232         } else {
2233             cpuTimeAtResume = 0; // Couldn't get the cpu time of process
2234         }
2235 
2236         returningOptions = null;
2237 
2238         if (canTurnScreenOn()) {
2239             mStackSupervisor.wakeUp("turnScreenOnFlag");
2240         } else {
2241             // If the screen is going to turn on because the caller explicitly requested it and
2242             // the keyguard is not showing don't attempt to sleep. Otherwise the Activity will
2243             // pause and then resume again later, which will result in a double life-cycle event.
2244             stack.checkReadyForSleep();
2245         }
2246     }
2247 
activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState, CharSequence description)2248     final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
2249             CharSequence description) {
2250         final ActivityStack stack = getActivityStack();
2251         final boolean isStopping = mState == STOPPING;
2252         if (!isStopping && mState != RESTARTING_PROCESS) {
2253             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
2254             stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
2255             return;
2256         }
2257         if (newPersistentState != null) {
2258             persistentState = newPersistentState;
2259             mAtmService.notifyTaskPersisterLocked(task, false);
2260         }
2261         if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + icicle);
2262 
2263         if (newIcicle != null) {
2264             // If icicle is null, this is happening due to a timeout, so we haven't really saved
2265             // the state.
2266             icicle = newIcicle;
2267             haveState = true;
2268             launchCount = 0;
2269             updateTaskDescription(description);
2270         }
2271         if (!stopped) {
2272             if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
2273             stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
2274             stopped = true;
2275             if (isStopping) {
2276                 setState(STOPPED, "activityStoppedLocked");
2277             }
2278 
2279             if (mAppWindowToken != null) {
2280                 mAppWindowToken.notifyAppStopped();
2281             }
2282 
2283             if (finishing) {
2284                 clearOptionsLocked();
2285             } else {
2286                 if (deferRelaunchUntilPaused) {
2287                     stack.destroyActivityLocked(this, true /* removeFromApp */, "stop-config");
2288                     mRootActivityContainer.resumeFocusedStacksTopActivities();
2289                 } else {
2290                     mRootActivityContainer.updatePreviousProcess(this);
2291                 }
2292             }
2293         }
2294     }
2295 
startLaunchTickingLocked()2296     void startLaunchTickingLocked() {
2297         if (Build.IS_USER) {
2298             return;
2299         }
2300         if (launchTickTime == 0) {
2301             launchTickTime = SystemClock.uptimeMillis();
2302             continueLaunchTickingLocked();
2303         }
2304     }
2305 
continueLaunchTickingLocked()2306     boolean continueLaunchTickingLocked() {
2307         if (launchTickTime == 0) {
2308             return false;
2309         }
2310 
2311         final ActivityStack stack = getActivityStack();
2312         if (stack == null) {
2313             return false;
2314         }
2315 
2316         Message msg = stack.mHandler.obtainMessage(LAUNCH_TICK_MSG, this);
2317         stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
2318         stack.mHandler.sendMessageDelayed(msg, LAUNCH_TICK);
2319         return true;
2320     }
2321 
finishLaunchTickingLocked()2322     void finishLaunchTickingLocked() {
2323         launchTickTime = 0;
2324         final ActivityStack stack = getActivityStack();
2325         if (stack != null) {
2326             stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
2327         }
2328     }
2329 
2330     // IApplicationToken
2331 
mayFreezeScreenLocked(WindowProcessController app)2332     public boolean mayFreezeScreenLocked(WindowProcessController app) {
2333         // Only freeze the screen if this activity is currently attached to
2334         // an application, and that application is not blocked or unresponding.
2335         // In any other case, we can't count on getting the screen unfrozen,
2336         // so it is best to leave as-is.
2337         return hasProcess() && !app.isCrashing() && !app.isNotResponding();
2338     }
2339 
startFreezingScreenLocked(WindowProcessController app, int configChanges)2340     public void startFreezingScreenLocked(WindowProcessController app, int configChanges) {
2341         if (mayFreezeScreenLocked(app)) {
2342             if (mAppWindowToken == null) {
2343                 Slog.w(TAG_WM,
2344                         "Attempted to freeze screen with non-existing app token: " + appToken);
2345                 return;
2346             }
2347 
2348             // Window configuration changes only effect windows, so don't require a screen freeze.
2349             int freezableConfigChanges = configChanges & ~(CONFIG_WINDOW_CONFIGURATION);
2350             if (freezableConfigChanges == 0 && mAppWindowToken.okToDisplay()) {
2351                 if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Skipping set freeze of " + appToken);
2352                 return;
2353             }
2354 
2355             mAppWindowToken.startFreezingScreen();
2356         }
2357     }
2358 
stopFreezingScreenLocked(boolean force)2359     public void stopFreezingScreenLocked(boolean force) {
2360         if (force || frozenBeforeDestroy) {
2361             frozenBeforeDestroy = false;
2362             if (mAppWindowToken == null) {
2363                 return;
2364             }
2365             if (DEBUG_ORIENTATION) {
2366                 Slog.v(TAG_WM, "Clear freezing of " + appToken + ": hidden="
2367                         + mAppWindowToken.isHidden() + " freezing="
2368                         + mAppWindowToken.isFreezingScreen());
2369             }
2370             mAppWindowToken.stopFreezingScreen(true, force);
2371         }
2372     }
2373 
reportFullyDrawnLocked(boolean restoredFromBundle)2374     public void reportFullyDrawnLocked(boolean restoredFromBundle) {
2375         final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
2376                 .getActivityMetricsLogger().logAppTransitionReportedDrawn(this, restoredFromBundle);
2377         if (info != null) {
2378             mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
2379                     info.windowsFullyDrawnDelayMs, info.getLaunchState());
2380         }
2381     }
2382 
2383     /**
2384      * Called when the starting window for this container is drawn.
2385      */
onStartingWindowDrawn(long timestamp)2386     public void onStartingWindowDrawn(long timestamp) {
2387         synchronized (mAtmService.mGlobalLock) {
2388             mStackSupervisor.getActivityMetricsLogger().notifyStartingWindowDrawn(
2389                     getWindowingMode(), timestamp);
2390         }
2391     }
2392 
2393     /** Called when the windows associated app window container are drawn. */
onWindowsDrawn(boolean drawn, long timestamp)2394     public void onWindowsDrawn(boolean drawn, long timestamp) {
2395         synchronized (mAtmService.mGlobalLock) {
2396             mDrawn = drawn;
2397             if (!drawn) {
2398                 return;
2399             }
2400             final WindowingModeTransitionInfoSnapshot info = mStackSupervisor
2401                     .getActivityMetricsLogger().notifyWindowsDrawn(getWindowingMode(), timestamp);
2402             final int windowsDrawnDelayMs = info != null ? info.windowsDrawnDelayMs : INVALID_DELAY;
2403             final @LaunchState int launchState = info != null ? info.getLaunchState() : -1;
2404             mStackSupervisor.reportActivityLaunchedLocked(false /* timeout */, this,
2405                     windowsDrawnDelayMs, launchState);
2406             mStackSupervisor.stopWaitingForActivityVisible(this);
2407             finishLaunchTickingLocked();
2408             if (task != null) {
2409                 task.hasBeenVisible = true;
2410             }
2411         }
2412     }
2413 
2414     /** Called when the windows associated app window container are visible. */
onWindowsVisible()2415     public void onWindowsVisible() {
2416         synchronized (mAtmService.mGlobalLock) {
2417             mStackSupervisor.stopWaitingForActivityVisible(this);
2418             if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
2419             if (!nowVisible) {
2420                 nowVisible = true;
2421                 lastVisibleTime = SystemClock.uptimeMillis();
2422                 mAtmService.scheduleAppGcsLocked();
2423             }
2424         }
2425     }
2426 
2427     /** Called when the windows associated app window container are no longer visible. */
onWindowsGone()2428     public void onWindowsGone() {
2429         synchronized (mAtmService.mGlobalLock) {
2430             if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
2431             nowVisible = false;
2432         }
2433     }
2434 
onAnimationFinished()2435     void onAnimationFinished() {
2436         if (mRootActivityContainer.allResumedActivitiesIdle()
2437                 || mStackSupervisor.isStoppingNoHistoryActivity()) {
2438             // If all activities are already idle or there is an activity that must be
2439             // stopped immediately after visible, then we now need to make sure we perform
2440             // the full stop of this activity. This is because we won't do that while they are still
2441             // waiting for the animation to finish.
2442             if (mStackSupervisor.mStoppingActivities.contains(this)) {
2443                 mStackSupervisor.scheduleIdleLocked();
2444             }
2445         } else {
2446             // Instead of doing the full stop routine here, let's just hide any activities
2447             // we now can, and let them stop when the normal idle happens.
2448             mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
2449                     false /* remove */, true /* processPausingActivities */);
2450         }
2451     }
2452 
2453     /**
2454      * Called when the key dispatching to a window associated with the app window container
2455      * timed-out.
2456      *
2457      * @param reason The reason for the key dispatching time out.
2458      * @param windowPid The pid of the window key dispatching timed out on.
2459      * @return True if input dispatching should be aborted.
2460      */
keyDispatchingTimedOut(String reason, int windowPid)2461     public boolean keyDispatchingTimedOut(String reason, int windowPid) {
2462         ActivityRecord anrActivity;
2463         WindowProcessController anrApp;
2464         boolean windowFromSameProcessAsActivity;
2465         synchronized (mAtmService.mGlobalLock) {
2466             anrActivity = getWaitingHistoryRecordLocked();
2467             anrApp = app;
2468             windowFromSameProcessAsActivity =
2469                     !hasProcess() || app.getPid() == windowPid || windowPid == -1;
2470         }
2471 
2472         if (windowFromSameProcessAsActivity) {
2473             return mAtmService.mAmInternal.inputDispatchingTimedOut(anrApp.mOwner,
2474                     anrActivity.shortComponentName, anrActivity.appInfo, shortComponentName,
2475                     app, false, reason);
2476         } else {
2477             // In this case another process added windows using this activity token. So, we call the
2478             // generic service input dispatch timed out method so that the right process is blamed.
2479             return mAtmService.mAmInternal.inputDispatchingTimedOut(
2480                     windowPid, false /* aboveSystem */, reason) < 0;
2481         }
2482     }
2483 
getWaitingHistoryRecordLocked()2484     private ActivityRecord getWaitingHistoryRecordLocked() {
2485         // First find the real culprit...  if this activity has stopped, then the key dispatching
2486         // timeout should not be caused by this.
2487         if (stopped) {
2488             final ActivityStack stack = mRootActivityContainer.getTopDisplayFocusedStack();
2489             // Try to use the one which is closest to top.
2490             ActivityRecord r = stack.getResumedActivity();
2491             if (r == null) {
2492                 r = stack.mPausingActivity;
2493             }
2494             if (r != null) {
2495                 return r;
2496             }
2497         }
2498         return this;
2499     }
2500 
2501     /** Checks whether the activity should be shown for current user. */
okToShowLocked()2502     public boolean okToShowLocked() {
2503         // We cannot show activities when the device is locked and the application is not
2504         // encryption aware.
2505         if (!StorageManager.isUserKeyUnlocked(mUserId)
2506                 && !info.applicationInfo.isEncryptionAware()) {
2507             return false;
2508         }
2509 
2510         return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
2511                 || (mStackSupervisor.isCurrentProfileLocked(mUserId)
2512                 && mAtmService.mAmInternal.isUserRunning(mUserId, 0 /* flags */));
2513     }
2514 
2515     /**
2516      * This method will return true if the activity is either visible, is becoming visible, is
2517      * currently pausing, or is resumed.
2518      */
isInterestingToUserLocked()2519     public boolean isInterestingToUserLocked() {
2520         return visible || nowVisible || mState == PAUSING || mState == RESUMED;
2521     }
2522 
setSleeping(boolean _sleeping)2523     void setSleeping(boolean _sleeping) {
2524         setSleeping(_sleeping, false);
2525     }
2526 
setSleeping(boolean _sleeping, boolean force)2527     void setSleeping(boolean _sleeping, boolean force) {
2528         if (!force && sleeping == _sleeping) {
2529             return;
2530         }
2531         if (attachedToProcess()) {
2532             try {
2533                 app.getThread().scheduleSleeping(appToken, _sleeping);
2534                 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
2535                     mStackSupervisor.mGoingToSleepActivities.add(this);
2536                 }
2537                 sleeping = _sleeping;
2538             } catch (RemoteException e) {
2539                 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
2540             }
2541         }
2542     }
2543 
getTaskForActivityLocked(IBinder token, boolean onlyRoot)2544     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
2545         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2546         if (r == null) {
2547             return INVALID_TASK_ID;
2548         }
2549         final TaskRecord task = r.task;
2550         final int activityNdx = task.mActivities.indexOf(r);
2551         if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) {
2552             return INVALID_TASK_ID;
2553         }
2554         return task.taskId;
2555     }
2556 
isInStackLocked(IBinder token)2557     static ActivityRecord isInStackLocked(IBinder token) {
2558         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2559         return (r != null) ? r.getActivityStack().isInStackLocked(r) : null;
2560     }
2561 
getStackLocked(IBinder token)2562     static ActivityStack getStackLocked(IBinder token) {
2563         final ActivityRecord r = ActivityRecord.isInStackLocked(token);
2564         if (r != null) {
2565             return r.getActivityStack();
2566         }
2567         return null;
2568     }
2569 
2570     /**
2571      * @return display id to which this record is attached,
2572      *         {@link android.view.Display#INVALID_DISPLAY} if not attached.
2573      */
getDisplayId()2574     int getDisplayId() {
2575         final ActivityStack stack = getActivityStack();
2576         if (stack == null) {
2577             return INVALID_DISPLAY;
2578         }
2579         return stack.mDisplayId;
2580     }
2581 
isDestroyable()2582     final boolean isDestroyable() {
2583         if (finishing || !hasProcess()) {
2584             // This would be redundant.
2585             return false;
2586         }
2587         final ActivityStack stack = getActivityStack();
2588         if (stack == null || this == stack.getResumedActivity() || this == stack.mPausingActivity
2589                 || !haveState || !stopped) {
2590             // We're not ready for this kind of thing.
2591             return false;
2592         }
2593         if (visible) {
2594             // The user would notice this!
2595             return false;
2596         }
2597         return true;
2598     }
2599 
createImageFilename(long createTime, int taskId)2600     private static String createImageFilename(long createTime, int taskId) {
2601         return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
2602                 IMAGE_EXTENSION;
2603     }
2604 
setTaskDescription(TaskDescription _taskDescription)2605     void setTaskDescription(TaskDescription _taskDescription) {
2606         Bitmap icon;
2607         if (_taskDescription.getIconFilename() == null &&
2608                 (icon = _taskDescription.getIcon()) != null) {
2609             final String iconFilename = createImageFilename(createTime, task.taskId);
2610             final File iconFile = new File(TaskPersister.getUserImagesDir(task.userId),
2611                     iconFilename);
2612             final String iconFilePath = iconFile.getAbsolutePath();
2613             mAtmService.getRecentTasks().saveImage(icon, iconFilePath);
2614             _taskDescription.setIconFilename(iconFilePath);
2615         }
2616         taskDescription = _taskDescription;
2617     }
2618 
setVoiceSessionLocked(IVoiceInteractionSession session)2619     void setVoiceSessionLocked(IVoiceInteractionSession session) {
2620         voiceSession = session;
2621         pendingVoiceInteractionStart = false;
2622     }
2623 
clearVoiceSessionLocked()2624     void clearVoiceSessionLocked() {
2625         voiceSession = null;
2626         pendingVoiceInteractionStart = false;
2627     }
2628 
showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch)2629     void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) {
2630         showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */);
2631     }
2632 
showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch, boolean fromRecents)2633     void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
2634             boolean fromRecents) {
2635         if (mAppWindowToken == null) {
2636             return;
2637         }
2638         if (mTaskOverlay) {
2639             // We don't show starting window for overlay activities.
2640             return;
2641         }
2642         if (pendingOptions != null
2643                 && pendingOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
2644             // Don't show starting window when using shared element transition.
2645             return;
2646         }
2647 
2648         final CompatibilityInfo compatInfo =
2649                 mAtmService.compatibilityInfoForPackageLocked(info.applicationInfo);
2650         final boolean shown = addStartingWindow(packageName, theme,
2651                 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2652                 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
2653                 allowTaskSnapshot(),
2654                 mState.ordinal() >= RESUMED.ordinal() && mState.ordinal() <= STOPPED.ordinal(),
2655                 fromRecents);
2656         if (shown) {
2657             mStartingWindowState = STARTING_WINDOW_SHOWN;
2658         }
2659     }
2660 
removeOrphanedStartingWindow(boolean behindFullscreenActivity)2661     void removeOrphanedStartingWindow(boolean behindFullscreenActivity) {
2662         if (mStartingWindowState == STARTING_WINDOW_SHOWN && behindFullscreenActivity) {
2663             if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
2664             mStartingWindowState = STARTING_WINDOW_REMOVED;
2665             mAppWindowToken.removeStartingWindow();
2666         }
2667     }
2668 
setRequestedOrientation(int requestedOrientation)2669     void setRequestedOrientation(int requestedOrientation) {
2670         setOrientation(requestedOrientation, mayFreezeScreenLocked(app));
2671         mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
2672                 task.taskId, requestedOrientation);
2673     }
2674 
setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded)2675     private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
2676         if (mAppWindowToken == null) {
2677             Slog.w(TAG_WM,
2678                     "Attempted to set orientation of non-existing app token: " + appToken);
2679             return;
2680         }
2681 
2682         final IBinder binder =
2683                 (freezeScreenIfNeeded && appToken != null) ? appToken.asBinder() : null;
2684         mAppWindowToken.setOrientation(requestedOrientation, binder, this);
2685 
2686         // Push the new configuration to the requested app in case where it's not pushed, e.g. when
2687         // the request is handled at task level with letterbox.
2688         if (!getMergedOverrideConfiguration().equals(
2689                 mLastReportedConfiguration.getMergedConfiguration())) {
2690             ensureActivityConfiguration(0 /* globalChanges */, false /* preserveWindow */);
2691         }
2692     }
2693 
getOrientation()2694     int getOrientation() {
2695         if (mAppWindowToken == null) {
2696             return info.screenOrientation;
2697         }
2698 
2699         return mAppWindowToken.getOrientationIgnoreVisibility();
2700     }
2701 
setDisablePreviewScreenshots(boolean disable)2702     void setDisablePreviewScreenshots(boolean disable) {
2703         if (mAppWindowToken == null) {
2704             Slog.w(TAG_WM, "Attempted to set disable screenshots of non-existing app"
2705                     + " token: " + appToken);
2706             return;
2707         }
2708         mAppWindowToken.setDisablePreviewScreenshots(disable);
2709     }
2710 
2711     /**
2712      * Set the last reported global configuration to the client. Should be called whenever a new
2713      * global configuration is sent to the client for this activity.
2714      */
setLastReportedGlobalConfiguration(@onNull Configuration config)2715     void setLastReportedGlobalConfiguration(@NonNull Configuration config) {
2716         mLastReportedConfiguration.setGlobalConfiguration(config);
2717     }
2718 
2719     /**
2720      * Set the last reported configuration to the client. Should be called whenever
2721      * a new merged configuration is sent to the client for this activity.
2722      */
setLastReportedConfiguration(@onNull MergedConfiguration config)2723     void setLastReportedConfiguration(@NonNull MergedConfiguration config) {
2724         setLastReportedConfiguration(config.getGlobalConfiguration(),
2725             config.getOverrideConfiguration());
2726     }
2727 
setLastReportedConfiguration(Configuration global, Configuration override)2728     private void setLastReportedConfiguration(Configuration global, Configuration override) {
2729         mLastReportedConfiguration.setConfiguration(global, override);
2730     }
2731 
2732     /**
2733      * Get the configuration orientation by the requested screen orientation
2734      * ({@link ActivityInfo.ScreenOrientation}) of this activity.
2735      *
2736      * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
2737      *         {@link Configuration#ORIENTATION_PORTRAIT},
2738      *         {@link Configuration#ORIENTATION_UNDEFINED}).
2739      */
getRequestedConfigurationOrientation()2740     int getRequestedConfigurationOrientation() {
2741         final int screenOrientation = getOrientation();
2742         if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
2743             // NOSENSOR means the display's "natural" orientation, so return that.
2744             final ActivityDisplay display = getDisplay();
2745             if (display != null && display.mDisplayContent != null) {
2746                 return display.mDisplayContent.getNaturalOrientation();
2747             }
2748         } else if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
2749             // LOCKED means the activity's orientation remains unchanged, so return existing value.
2750             return getConfiguration().orientation;
2751         } else if (isFixedOrientationLandscape(screenOrientation)) {
2752             return ORIENTATION_LANDSCAPE;
2753         } else if (isFixedOrientationPortrait(screenOrientation)) {
2754             return ORIENTATION_PORTRAIT;
2755         }
2756         return ORIENTATION_UNDEFINED;
2757     }
2758 
2759     /**
2760      * @return {@code true} if this activity is in size compatibility mode that uses the different
2761      *         density or bounds from its parent.
2762      */
inSizeCompatMode()2763     boolean inSizeCompatMode() {
2764         if (!shouldUseSizeCompatMode()) {
2765             return false;
2766         }
2767         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
2768         final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
2769         if (resolvedAppBounds == null) {
2770             // The override configuration has not been resolved yet.
2771             return false;
2772         }
2773 
2774         final Configuration parentConfig = getParent().getConfiguration();
2775         // Although colorMode, screenLayout, smallestScreenWidthDp are also fixed, generally these
2776         // fields should be changed with density and bounds, so here only compares the most
2777         // significant field.
2778         if (parentConfig.densityDpi != resolvedConfig.densityDpi) {
2779             return true;
2780         }
2781 
2782         final Rect parentAppBounds = parentConfig.windowConfiguration.getAppBounds();
2783         final int appWidth = resolvedAppBounds.width();
2784         final int appHeight = resolvedAppBounds.height();
2785         final int parentAppWidth = parentAppBounds.width();
2786         final int parentAppHeight = parentAppBounds.height();
2787         if (parentAppWidth == appWidth && parentAppHeight == appHeight) {
2788             // Matched the parent bounds.
2789             return false;
2790         }
2791         if (parentAppWidth > appWidth && parentAppHeight > appHeight) {
2792             // Both sides are smaller than the parent.
2793             return true;
2794         }
2795         if (parentAppWidth < appWidth || parentAppHeight < appHeight) {
2796             // One side is larger than the parent.
2797             return true;
2798         }
2799 
2800         // The rest of the condition is that only one side is smaller than the parent, but it still
2801         // needs to exclude the cases where the size is limited by the fixed aspect ratio.
2802         if (info.maxAspectRatio > 0) {
2803             final float aspectRatio = (0.5f + Math.max(appWidth, appHeight))
2804                     / Math.min(appWidth, appHeight);
2805             if (aspectRatio >= info.maxAspectRatio) {
2806                 // The current size has reached the max aspect ratio.
2807                 return false;
2808             }
2809         }
2810         if (info.minAspectRatio > 0) {
2811             // The activity should have at least the min aspect ratio, so this checks if the parent
2812             // still has available space to provide larger aspect ratio.
2813             final float parentAspectRatio = (0.5f + Math.max(parentAppWidth, parentAppHeight))
2814                     / Math.min(parentAppWidth, parentAppHeight);
2815             if (parentAspectRatio <= info.minAspectRatio) {
2816                 // The long side has reached the parent.
2817                 return false;
2818             }
2819         }
2820         return true;
2821     }
2822 
2823     /**
2824      * Indicates the activity will keep the bounds and screen configuration when it was first
2825      * launched, no matter how its parent changes.
2826      *
2827      * @return {@code true} if this activity is declared as non-resizable and fixed orientation or
2828      *         aspect ratio.
2829      */
shouldUseSizeCompatMode()2830     boolean shouldUseSizeCompatMode() {
2831         return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
2832                 // The configuration of non-standard type should be enforced by system.
2833                 && isActivityTypeStandard()
2834                 && !mAtmService.mForceResizableActivities;
2835     }
2836 
2837     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
updateOverrideConfiguration()2838     private void updateOverrideConfiguration() {
2839         final Configuration overrideConfig = mTmpConfig;
2840         if (shouldUseSizeCompatMode()) {
2841             if (mCompatDisplayInsets != null) {
2842                 // The override configuration is set only once in size compatibility mode.
2843                 return;
2844             }
2845             final Configuration parentConfig = getParent().getConfiguration();
2846             if (!hasProcess() && !isConfigurationCompatible(parentConfig)) {
2847                 // Don't compute when launching in fullscreen and the fixed orientation is not the
2848                 // current orientation. It is more accurately to compute the override bounds from
2849                 // the updated configuration after the fixed orientation is applied.
2850                 return;
2851             }
2852 
2853             // Ensure the screen related fields are set. It is used to prevent activity relaunch
2854             // when moving between displays. For screenWidthDp and screenWidthDp, because they
2855             // are relative to bounds and density, they will be calculated in
2856             // {@link TaskRecord#computeConfigResourceOverrides} and the result will also be
2857             // relatively fixed.
2858             overrideConfig.unset();
2859             overrideConfig.colorMode = parentConfig.colorMode;
2860             overrideConfig.densityDpi = parentConfig.densityDpi;
2861             overrideConfig.screenLayout = parentConfig.screenLayout
2862                     & (Configuration.SCREENLAYOUT_LONG_MASK
2863                             | Configuration.SCREENLAYOUT_SIZE_MASK);
2864             // The smallest screen width is the short side of screen bounds. Because the bounds
2865             // and density won't be changed, smallestScreenWidthDp is also fixed.
2866             overrideConfig.smallestScreenWidthDp = parentConfig.smallestScreenWidthDp;
2867 
2868             // The role of CompatDisplayInsets is like the override bounds.
2869             final ActivityDisplay display = getDisplay();
2870             if (display != null && display.mDisplayContent != null) {
2871                 mCompatDisplayInsets = new CompatDisplayInsets(display.mDisplayContent);
2872             }
2873         } else {
2874             // We must base this on the parent configuration, because we set our override
2875             // configuration's appBounds based on the result of this method. If we used our own
2876             // configuration, it would be influenced by past invocations.
2877             computeBounds(mTmpBounds, getParent().getWindowConfiguration().getAppBounds());
2878 
2879             if (mTmpBounds.equals(getRequestedOverrideBounds())) {
2880                 // The bounds is not changed or the activity is resizable (both the 2 bounds are
2881                 // empty).
2882                 return;
2883             }
2884 
2885             overrideConfig.unset();
2886             overrideConfig.windowConfiguration.setBounds(mTmpBounds);
2887         }
2888 
2889         onRequestedOverrideConfigurationChanged(overrideConfig);
2890     }
2891 
2892     @Override
resolveOverrideConfiguration(Configuration newParentConfiguration)2893     void resolveOverrideConfiguration(Configuration newParentConfiguration) {
2894         if (mCompatDisplayInsets != null) {
2895             resolveSizeCompatModeConfiguration(newParentConfiguration);
2896         } else {
2897             super.resolveOverrideConfiguration(newParentConfiguration);
2898             // If the activity has override bounds, the relative configuration (e.g. screen size,
2899             // layout) needs to be resolved according to the bounds.
2900             if (!matchParentBounds()) {
2901                 task.computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
2902                         newParentConfiguration);
2903             }
2904         }
2905 
2906         // Assign configuration sequence number into hierarchy because there is a different way than
2907         // ensureActivityConfiguration() in this class that uses configuration in WindowState during
2908         // layout traversals.
2909         mConfigurationSeq = Math.max(++mConfigurationSeq, 1);
2910         getResolvedOverrideConfiguration().seq = mConfigurationSeq;
2911     }
2912 
2913     /**
2914      * Resolves consistent screen configuration for orientation and rotation changes without
2915      * inheriting the parent bounds.
2916      */
resolveSizeCompatModeConfiguration(Configuration newParentConfiguration)2917     private void resolveSizeCompatModeConfiguration(Configuration newParentConfiguration) {
2918         final Configuration resolvedConfig = getResolvedOverrideConfiguration();
2919         final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
2920 
2921         final int parentRotation = newParentConfiguration.windowConfiguration.getRotation();
2922         final int parentOrientation = newParentConfiguration.orientation;
2923         int orientation = getConfiguration().orientation;
2924         if (orientation != parentOrientation && isConfigurationCompatible(newParentConfiguration)) {
2925             // The activity is compatible to apply the orientation change or it requests different
2926             // fixed orientation.
2927             orientation = parentOrientation;
2928         } else {
2929             if (!resolvedBounds.isEmpty()
2930                     // The decor insets may be different according to the rotation.
2931                     && getWindowConfiguration().getRotation() == parentRotation) {
2932                 // Keep the computed resolved override configuration.
2933                 return;
2934             }
2935             final int requestedOrientation = getRequestedConfigurationOrientation();
2936             if (requestedOrientation != ORIENTATION_UNDEFINED) {
2937                 orientation = requestedOrientation;
2938             }
2939         }
2940 
2941         super.resolveOverrideConfiguration(newParentConfiguration);
2942 
2943         boolean useParentOverrideBounds = false;
2944         final Rect displayBounds = mTmpBounds;
2945         final Rect containingAppBounds = new Rect();
2946         if (task.handlesOrientationChangeFromDescendant()) {
2947             // Prefer to use the orientation which is determined by this activity to calculate
2948             // bounds because the parent will follow the requested orientation.
2949             mCompatDisplayInsets.getDisplayBoundsByOrientation(displayBounds, orientation);
2950         } else {
2951             // The parent hierarchy doesn't handle the orientation changes. This is usually because
2952             // the aspect ratio of display is close to square or the display rotation is fixed.
2953             // In this case, task will compute override bounds to fit the app with respect to the
2954             // requested orientation. So here we perform similar calculation to have consistent
2955             // bounds even the original parent hierarchies were changed.
2956             final int baseOrientation = task.getParent().getConfiguration().orientation;
2957             mCompatDisplayInsets.getDisplayBoundsByOrientation(displayBounds, baseOrientation);
2958             task.computeFullscreenBounds(containingAppBounds, this, displayBounds, baseOrientation);
2959             useParentOverrideBounds = !containingAppBounds.isEmpty();
2960         }
2961 
2962         // The offsets will be non-zero if the parent has override bounds.
2963         final int containingOffsetX = containingAppBounds.left;
2964         final int containingOffsetY = containingAppBounds.top;
2965         if (!useParentOverrideBounds) {
2966             containingAppBounds.set(displayBounds);
2967         }
2968         if (parentRotation != ROTATION_UNDEFINED) {
2969             // Ensure the container bounds won't overlap with the decors.
2970             TaskRecord.intersectWithInsetsIfFits(containingAppBounds, displayBounds,
2971                     mCompatDisplayInsets.mNonDecorInsets[parentRotation]);
2972         }
2973 
2974         computeBounds(resolvedBounds, containingAppBounds);
2975         if (resolvedBounds.isEmpty()) {
2976             // Use the entire available bounds because there is no restriction.
2977             resolvedBounds.set(useParentOverrideBounds ? containingAppBounds : displayBounds);
2978         } else {
2979             // The offsets are included in width and height by {@link #computeBounds}, so we have to
2980             // restore it.
2981             resolvedBounds.left += containingOffsetX;
2982             resolvedBounds.top += containingOffsetY;
2983         }
2984         task.computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
2985                 mCompatDisplayInsets);
2986 
2987         // The horizontal inset included in width is not needed if the activity cannot fill the
2988         // parent, because the offset will be applied by {@link AppWindowToken#mSizeCompatBounds}.
2989         final Rect resolvedAppBounds = resolvedConfig.windowConfiguration.getAppBounds();
2990         final Rect parentAppBounds = newParentConfiguration.windowConfiguration.getAppBounds();
2991         if (resolvedBounds.width() < parentAppBounds.width()) {
2992             resolvedBounds.right -= resolvedAppBounds.left;
2993         }
2994         // Use parent orientation if it cannot be decided by bounds, so the activity can fit inside
2995         // the parent bounds appropriately.
2996         if (resolvedConfig.screenWidthDp == resolvedConfig.screenHeightDp) {
2997             resolvedConfig.orientation = newParentConfiguration.orientation;
2998         }
2999     }
3000 
3001     @Override
onConfigurationChanged(Configuration newParentConfig)3002     public void onConfigurationChanged(Configuration newParentConfig) {
3003         super.onConfigurationChanged(newParentConfig);
3004 
3005         // Configuration's equality doesn't consider seq so if only seq number changes in resolved
3006         // override configuration. Therefore ConfigurationContainer doesn't change merged override
3007         // configuration, but it's used to push configuration changes so explicitly update that.
3008         if (getMergedOverrideConfiguration().seq != getResolvedOverrideConfiguration().seq) {
3009             onMergedOverrideConfigurationChanged();
3010         }
3011 
3012         // TODO(b/80414790): Remove code below after unification.
3013         // Same as above it doesn't notify configuration listeners, and consequently AppWindowToken
3014         // can't get updated seq number. However WindowState's merged override configuration needs
3015         // to have this seq number because that's also used for activity config pushes during layout
3016         // traversal. Therefore explicitly update them here.
3017         if (mAppWindowToken == null) {
3018             return;
3019         }
3020         final Configuration appWindowTokenRequestedOverrideConfig =
3021                 mAppWindowToken.getRequestedOverrideConfiguration();
3022         if (appWindowTokenRequestedOverrideConfig.seq != getResolvedOverrideConfiguration().seq) {
3023             appWindowTokenRequestedOverrideConfig.seq =
3024                     getResolvedOverrideConfiguration().seq;
3025             mAppWindowToken.onMergedOverrideConfigurationChanged();
3026         }
3027 
3028         final ActivityDisplay display = getDisplay();
3029         if (display == null) {
3030             return;
3031         }
3032         if (visible) {
3033             // It may toggle the UI for user to restart the size compatibility mode activity.
3034             display.handleActivitySizeCompatModeIfNeeded(this);
3035         } else if (shouldUseSizeCompatMode()) {
3036             // The override changes can only be obtained from display, because we don't have the
3037             // difference of full configuration in each hierarchy.
3038             final int displayChanges = display.getLastOverrideConfigurationChanges();
3039             final int orientationChanges = CONFIG_WINDOW_CONFIGURATION
3040                     | CONFIG_SCREEN_SIZE | CONFIG_ORIENTATION;
3041             final boolean hasNonOrienSizeChanged = hasResizeChange(displayChanges)
3042                     // Filter out the case of simple orientation change.
3043                     && (displayChanges & orientationChanges) != orientationChanges;
3044             // For background activity that uses size compatibility mode, if the size or density of
3045             // the display is changed, then reset the override configuration and kill the activity's
3046             // process if its process state is not important to user.
3047             if (hasNonOrienSizeChanged || (displayChanges & ActivityInfo.CONFIG_DENSITY) != 0) {
3048                 restartProcessIfVisible();
3049             }
3050         }
3051     }
3052 
3053     /** Returns true if the configuration is compatible with this activity. */
isConfigurationCompatible(Configuration config)3054     boolean isConfigurationCompatible(Configuration config) {
3055         final int orientation = getOrientation();
3056         if (isFixedOrientationPortrait(orientation)
3057                 && config.orientation != ORIENTATION_PORTRAIT) {
3058             return false;
3059         }
3060         if (isFixedOrientationLandscape(orientation)
3061                 && config.orientation != ORIENTATION_LANDSCAPE) {
3062             return false;
3063         }
3064         return true;
3065     }
3066 
3067     /**
3068      * Computes the bounds to fit the Activity within the bounds of the {@link Configuration}.
3069      */
3070     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
computeBounds(Rect outBounds, Rect containingAppBounds)3071     private void computeBounds(Rect outBounds, Rect containingAppBounds) {
3072         outBounds.setEmpty();
3073         final float maxAspectRatio = info.maxAspectRatio;
3074         final ActivityStack stack = getActivityStack();
3075         final float minAspectRatio = info.minAspectRatio;
3076 
3077         if (task == null || stack == null || task.inMultiWindowMode()
3078                 || (maxAspectRatio == 0 && minAspectRatio == 0)
3079                 || isInVrUiMode(getConfiguration())) {
3080             // We don't set override configuration if that activity task isn't fullscreen. I.e. the
3081             // activity is in multi-window mode. Or, there isn't a max aspect ratio specified for
3082             // the activity. This is indicated by an empty {@link outBounds}. We also don't set it
3083             // if we are in VR mode.
3084             return;
3085         }
3086 
3087         final int containingAppWidth = containingAppBounds.width();
3088         final int containingAppHeight = containingAppBounds.height();
3089         final float containingRatio = Math.max(containingAppWidth, containingAppHeight)
3090                 / (float) Math.min(containingAppWidth, containingAppHeight);
3091 
3092         int activityWidth = containingAppWidth;
3093         int activityHeight = containingAppHeight;
3094 
3095         if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
3096             if (containingAppWidth < containingAppHeight) {
3097                 // Width is the shorter side, so we use that to figure-out what the max. height
3098                 // should be given the aspect ratio.
3099                 activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
3100             } else {
3101                 // Height is the shorter side, so we use that to figure-out what the max. width
3102                 // should be given the aspect ratio.
3103                 activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
3104             }
3105         } else if (containingRatio < minAspectRatio) {
3106             boolean adjustWidth;
3107             switch (getRequestedConfigurationOrientation()) {
3108                 case ORIENTATION_LANDSCAPE:
3109                     // Width should be the longer side for this landscape app, so we use the width
3110                     // to figure-out what the max. height should be given the aspect ratio.
3111                     adjustWidth = false;
3112                     break;
3113                 case ORIENTATION_PORTRAIT:
3114                     // Height should be the longer side for this portrait app, so we use the height
3115                     // to figure-out what the max. width should be given the aspect ratio.
3116                     adjustWidth = true;
3117                     break;
3118                 default:
3119                     // This app doesn't have a preferred orientation, so we keep the length of the
3120                     // longer side, and use it to figure-out the length of the shorter side.
3121                     if (containingAppWidth < containingAppHeight) {
3122                         // Width is the shorter side, so we use the height to figure-out what the
3123                         // max. width should be given the aspect ratio.
3124                         adjustWidth = true;
3125                     } else {
3126                         // Height is the shorter side, so we use the width to figure-out what the
3127                         // max. height should be given the aspect ratio.
3128                         adjustWidth = false;
3129                     }
3130                     break;
3131             }
3132             if (adjustWidth) {
3133                 activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
3134             } else {
3135                 activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
3136             }
3137         }
3138 
3139         if (containingAppWidth <= activityWidth && containingAppHeight <= activityHeight) {
3140             // The display matches or is less than the activity aspect ratio, so nothing else to do.
3141             // Return the existing bounds. If this method is running for the first time,
3142             // {@link #getRequestedOverrideBounds()} will be empty (representing no override). If
3143             // the method has run before, then effect of {@link #getRequestedOverrideBounds()} will
3144             // already have been applied to the value returned from {@link getConfiguration}. Refer
3145             // to {@link TaskRecord#computeConfigResourceOverrides()}.
3146             outBounds.set(getRequestedOverrideBounds());
3147             return;
3148         }
3149 
3150         // Compute configuration based on max supported width and height.
3151         // Also account for the left / top insets (e.g. from display cutouts), which will be clipped
3152         // away later in {@link TaskRecord#computeConfigResourceOverrides()}. Otherwise, the app
3153         // bounds would end up too small.
3154         outBounds.set(0, 0, activityWidth + containingAppBounds.left,
3155                 activityHeight + containingAppBounds.top);
3156     }
3157 
3158     /**
3159      * @return {@code true} if this activity was reparented to another display but
3160      *         {@link #ensureActivityConfiguration} is not called.
3161      */
shouldUpdateConfigForDisplayChanged()3162     boolean shouldUpdateConfigForDisplayChanged() {
3163         return mLastReportedDisplayId != getDisplayId();
3164     }
3165 
ensureActivityConfiguration(int globalChanges, boolean preserveWindow)3166     boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow) {
3167         return ensureActivityConfiguration(globalChanges, preserveWindow,
3168                 false /* ignoreStopState */);
3169     }
3170 
3171     /**
3172      * Make sure the given activity matches the current configuration. Ensures the HistoryRecord
3173      * is updated with the correct configuration and all other bookkeeping is handled.
3174      *
3175      * @param globalChanges The changes to the global configuration.
3176      * @param preserveWindow If the activity window should be preserved on screen if the activity
3177      *                       is relaunched.
3178      * @param ignoreStopState If we should try to relaunch the activity even if it is in the stopped
3179      *                        state. This is useful for the case where we know the activity will be
3180      *                        visible soon and we want to ensure its configuration before we make it
3181      *                        visible.
3182      * @return False if the activity was relaunched and true if it wasn't relaunched because we
3183      *         can't or the app handles the specific configuration that is changing.
3184      */
ensureActivityConfiguration(int globalChanges, boolean preserveWindow, boolean ignoreStopState)3185     boolean ensureActivityConfiguration(int globalChanges, boolean preserveWindow,
3186             boolean ignoreStopState) {
3187         final ActivityStack stack = getActivityStack();
3188         if (stack.mConfigWillChange) {
3189             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3190                     "Skipping config check (will change): " + this);
3191             return true;
3192         }
3193 
3194         // We don't worry about activities that are finishing.
3195         if (finishing) {
3196             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3197                     "Configuration doesn't matter in finishing " + this);
3198             stopFreezingScreenLocked(false);
3199             return true;
3200         }
3201 
3202         if (!ignoreStopState && (mState == STOPPING || mState == STOPPED)) {
3203             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3204                     "Skipping config check stopped or stopping: " + this);
3205             return true;
3206         }
3207 
3208         if (!shouldBeVisible()) {
3209             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3210                     "Skipping config check invisible stack: " + this);
3211             return true;
3212         }
3213 
3214         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3215                 "Ensuring correct configuration: " + this);
3216 
3217         final int newDisplayId = getDisplayId();
3218         final boolean displayChanged = mLastReportedDisplayId != newDisplayId;
3219         if (displayChanged) {
3220             mLastReportedDisplayId = newDisplayId;
3221         }
3222         // TODO(b/36505427): Is there a better place to do this?
3223         updateOverrideConfiguration();
3224 
3225         // Short circuit: if the two full configurations are equal (the common case), then there is
3226         // nothing to do.  We test the full configuration instead of the global and merged override
3227         // configurations because there are cases (like moving a task to the pinned stack) where
3228         // the combine configurations are equal, but would otherwise differ in the override config
3229         mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration());
3230         if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) {
3231             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3232                     "Configuration & display unchanged in " + this);
3233             return true;
3234         }
3235 
3236         // Okay we now are going to make this activity have the new config.
3237         // But then we need to figure out how it needs to deal with that.
3238 
3239         // Find changes between last reported merged configuration and the current one. This is used
3240         // to decide whether to relaunch an activity or just report a configuration change.
3241         final int changes = getConfigurationChanges(mTmpConfig);
3242 
3243         // Update last reported values.
3244         final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
3245 
3246         setLastReportedConfiguration(mAtmService.getGlobalConfiguration(), newMergedOverrideConfig);
3247 
3248         if (mState == INITIALIZING) {
3249             // No need to relaunch or schedule new config for activity that hasn't been launched
3250             // yet. We do, however, return after applying the config to activity record, so that
3251             // it will use it for launch transaction.
3252             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3253                     "Skipping config check for initializing activity: " + this);
3254             return true;
3255         }
3256 
3257         if (changes == 0 && !forceNewConfig) {
3258             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3259                     "Configuration no differences in " + this);
3260             // There are no significant differences, so we won't relaunch but should still deliver
3261             // the new configuration to the client process.
3262             if (displayChanged) {
3263                 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
3264             } else {
3265                 scheduleConfigurationChanged(newMergedOverrideConfig);
3266             }
3267             return true;
3268         }
3269 
3270         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3271                 "Configuration changes for " + this + ", allChanges="
3272                         + Configuration.configurationDiffToString(changes));
3273 
3274         // If the activity isn't currently running, just leave the new configuration and it will
3275         // pick that up next time it starts.
3276         if (!attachedToProcess()) {
3277             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3278                     "Configuration doesn't matter not running " + this);
3279             stopFreezingScreenLocked(false);
3280             forceNewConfig = false;
3281             return true;
3282         }
3283 
3284         // Figure out how to handle the changes between the configurations.
3285         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3286                 "Checking to restart " + info.name + ": changed=0x"
3287                         + Integer.toHexString(changes) + ", handles=0x"
3288                         + Integer.toHexString(info.getRealConfigChanged())
3289                         + ", mLastReportedConfiguration=" + mLastReportedConfiguration);
3290 
3291         if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
3292             // Aha, the activity isn't handling the change, so DIE DIE DIE.
3293             configChangeFlags |= changes;
3294             startFreezingScreenLocked(app, globalChanges);
3295             forceNewConfig = false;
3296             preserveWindow &= isResizeOnlyChange(changes);
3297             final boolean hasResizeChange = hasResizeChange(changes & ~info.getRealConfigChanged());
3298             if (hasResizeChange) {
3299                 final boolean isDragResizing =
3300                         getTaskRecord().getTask().isDragResizing();
3301                 mRelaunchReason = isDragResizing ? RELAUNCH_REASON_FREE_RESIZE
3302                         : RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
3303             } else {
3304                 mRelaunchReason = RELAUNCH_REASON_NONE;
3305             }
3306             if (!attachedToProcess()) {
3307                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3308                         "Config is destroying non-running " + this);
3309                 stack.destroyActivityLocked(this, true, "config");
3310             } else if (mState == PAUSING) {
3311                 // A little annoying: we are waiting for this activity to finish pausing. Let's not
3312                 // do anything now, but just flag that it needs to be restarted when done pausing.
3313                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3314                         "Config is skipping already pausing " + this);
3315                 deferRelaunchUntilPaused = true;
3316                 preserveWindowOnDeferredRelaunch = preserveWindow;
3317                 return true;
3318             } else if (mState == RESUMED) {
3319                 // Try to optimize this case: the configuration is changing and we need to restart
3320                 // the top, resumed activity. Instead of doing the normal handshaking, just say
3321                 // "restart!".
3322                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3323                         "Config is relaunching resumed " + this);
3324 
3325                 if (DEBUG_STATES && !visible) {
3326                     Slog.v(TAG_STATES, "Config is relaunching resumed invisible activity " + this
3327                             + " called by " + Debug.getCallers(4));
3328                 }
3329 
3330                 relaunchActivityLocked(true /* andResume */, preserveWindow);
3331             } else {
3332                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
3333                         "Config is relaunching non-resumed " + this);
3334                 relaunchActivityLocked(false /* andResume */, preserveWindow);
3335             }
3336 
3337             // All done...  tell the caller we weren't able to keep this activity around.
3338             return false;
3339         }
3340 
3341         // Default case: the activity can handle this new configuration, so hand it over.
3342         // NOTE: We only forward the override configuration as the system level configuration
3343         // changes is always sent to all processes when they happen so it can just use whatever
3344         // system level configuration it last got.
3345         if (displayChanged) {
3346             scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
3347         } else {
3348             scheduleConfigurationChanged(newMergedOverrideConfig);
3349         }
3350         stopFreezingScreenLocked(false);
3351 
3352         return true;
3353     }
3354 
3355     /**
3356      * When assessing a configuration change, decide if the changes flags and the new configurations
3357      * should cause the Activity to relaunch.
3358      *
3359      * @param changes the changes due to the given configuration.
3360      * @param changesConfig the configuration that was used to calculate the given changes via a
3361      *        call to getConfigurationChanges.
3362      */
shouldRelaunchLocked(int changes, Configuration changesConfig)3363     private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
3364         int configChanged = info.getRealConfigChanged();
3365         boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
3366 
3367         // Override for apps targeting pre-O sdks
3368         // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
3369         // to the config change.
3370         // For O and later, apps will be required to add configChanges="uimode" to their manifest.
3371         if (appInfo.targetSdkVersion < O
3372                 && requestedVrComponent != null
3373                 && onlyVrUiModeChanged) {
3374             configChanged |= CONFIG_UI_MODE;
3375         }
3376 
3377         return (changes&(~configChanged)) != 0;
3378     }
3379 
3380     /**
3381      * Returns true if the configuration change is solely due to the UI mode switching into or out
3382      * of UI_MODE_TYPE_VR_HEADSET.
3383      */
onlyVrUiModeChanged(int changes, Configuration lastReportedConfig)3384     private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
3385         final Configuration currentConfig = getConfiguration();
3386         return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
3387             != isInVrUiMode(lastReportedConfig));
3388     }
3389 
getConfigurationChanges(Configuration lastReportedConfig)3390     private int getConfigurationChanges(Configuration lastReportedConfig) {
3391         // Determine what has changed.  May be nothing, if this is a config that has come back from
3392         // the app after going idle.  In that case we just want to leave the official config object
3393         // now in the activity and do nothing else.
3394         final Configuration currentConfig = getConfiguration();
3395         int changes = lastReportedConfig.diff(currentConfig);
3396         // We don't want to use size changes if they don't cross boundaries that are important to
3397         // the app.
3398         if ((changes & CONFIG_SCREEN_SIZE) != 0) {
3399             final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp,
3400                     currentConfig.screenWidthDp)
3401                     || crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp,
3402                     currentConfig.screenHeightDp);
3403             if (!crosses) {
3404                 changes &= ~CONFIG_SCREEN_SIZE;
3405             }
3406         }
3407         if ((changes & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
3408             final int oldSmallest = lastReportedConfig.smallestScreenWidthDp;
3409             final int newSmallest = currentConfig.smallestScreenWidthDp;
3410             if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
3411                 changes &= ~CONFIG_SMALLEST_SCREEN_SIZE;
3412             }
3413         }
3414         // We don't want window configuration to cause relaunches.
3415         if ((changes & CONFIG_WINDOW_CONFIGURATION) != 0) {
3416             changes &= ~CONFIG_WINDOW_CONFIGURATION;
3417         }
3418 
3419         return changes;
3420     }
3421 
isResizeOnlyChange(int change)3422     private static boolean isResizeOnlyChange(int change) {
3423         return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
3424                 | CONFIG_SCREEN_LAYOUT)) == 0;
3425     }
3426 
hasResizeChange(int change)3427     private static boolean hasResizeChange(int change) {
3428         return (change & (CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
3429                 | CONFIG_SCREEN_LAYOUT)) != 0;
3430     }
3431 
relaunchActivityLocked(boolean andResume, boolean preserveWindow)3432     void relaunchActivityLocked(boolean andResume, boolean preserveWindow) {
3433         if (mAtmService.mSuppressResizeConfigChanges && preserveWindow) {
3434             configChangeFlags = 0;
3435             return;
3436         }
3437 
3438         List<ResultInfo> pendingResults = null;
3439         List<ReferrerIntent> pendingNewIntents = null;
3440         if (andResume) {
3441             pendingResults = results;
3442             pendingNewIntents = newIntents;
3443         }
3444         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
3445                 "Relaunching: " + this + " with results=" + pendingResults
3446                         + " newIntents=" + pendingNewIntents + " andResume=" + andResume
3447                         + " preserveWindow=" + preserveWindow);
3448         EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY
3449                         : AM_RELAUNCH_ACTIVITY, mUserId, System.identityHashCode(this),
3450                 task.taskId, shortComponentName);
3451 
3452         startFreezingScreenLocked(app, 0);
3453 
3454         try {
3455             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
3456                     "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
3457                             + " callers=" + Debug.getCallers(6));
3458             forceNewConfig = false;
3459             mStackSupervisor.activityRelaunchingLocked(this);
3460             final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(pendingResults,
3461                     pendingNewIntents, configChangeFlags,
3462                     new MergedConfiguration(mAtmService.getGlobalConfiguration(),
3463                             getMergedOverrideConfiguration()),
3464                     preserveWindow);
3465             final ActivityLifecycleItem lifecycleItem;
3466             if (andResume) {
3467                 lifecycleItem = ResumeActivityItem.obtain(
3468                         getDisplay().mDisplayContent.isNextTransitionForward());
3469             } else {
3470                 lifecycleItem = PauseActivityItem.obtain();
3471             }
3472             final ClientTransaction transaction = ClientTransaction.obtain(app.getThread(), appToken);
3473             transaction.addCallback(callbackItem);
3474             transaction.setLifecycleStateRequest(lifecycleItem);
3475             mAtmService.getLifecycleManager().scheduleTransaction(transaction);
3476             // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
3477             // request resume if this activity is currently resumed, which implies we aren't
3478             // sleeping.
3479         } catch (RemoteException e) {
3480             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
3481         }
3482 
3483         if (andResume) {
3484             if (DEBUG_STATES) {
3485                 Slog.d(TAG_STATES, "Resumed after relaunch " + this);
3486             }
3487             results = null;
3488             newIntents = null;
3489             mAtmService.getAppWarningsLocked().onResumeActivity(this);
3490         } else {
3491             final ActivityStack stack = getActivityStack();
3492             if (stack != null) {
3493                 stack.mHandler.removeMessages(PAUSE_TIMEOUT_MSG, this);
3494             }
3495             setState(PAUSED, "relaunchActivityLocked");
3496         }
3497 
3498         configChangeFlags = 0;
3499         deferRelaunchUntilPaused = false;
3500         preserveWindowOnDeferredRelaunch = false;
3501     }
3502 
3503     /**
3504      * Request the process of the activity to restart with its saved state (from
3505      * {@link android.app.Activity#onSaveInstanceState}) if possible. It also forces to recompute
3506      * the override configuration. Note if the activity is in background, the process will be killed
3507      * directly with keeping its record.
3508      */
restartProcessIfVisible()3509     void restartProcessIfVisible() {
3510         Slog.i(TAG, "Request to restart process of " + this);
3511 
3512         // Reset the existing override configuration so it can be updated according to the latest
3513         // configuration.
3514         getRequestedOverrideConfiguration().unset();
3515         getResolvedOverrideConfiguration().unset();
3516         mCompatDisplayInsets = null;
3517         if (visible) {
3518             // Configuration will be ensured when becoming visible, so if it is already visible,
3519             // then the manual update is needed.
3520             updateOverrideConfiguration();
3521         }
3522 
3523         if (!attachedToProcess()) {
3524             return;
3525         }
3526 
3527         // The restarting state avoids removing this record when process is died.
3528         setState(RESTARTING_PROCESS, "restartActivityProcess");
3529 
3530         if (!visible || haveState) {
3531             // Kill its process immediately because the activity should be in background.
3532             // The activity state will be update to {@link #DESTROYED} in
3533             // {@link ActivityStack#cleanUpActivityLocked} when handling process died.
3534             mAtmService.mH.post(() -> {
3535                 final WindowProcessController wpc;
3536                 synchronized (mAtmService.mGlobalLock) {
3537                     if (!hasProcess()
3538                             || app.getReportedProcState() <= PROCESS_STATE_IMPORTANT_FOREGROUND) {
3539                         return;
3540                     }
3541                     wpc = app;
3542                 }
3543                 mAtmService.mAmInternal.killProcess(wpc.mName, wpc.mUid, "resetConfig");
3544             });
3545             return;
3546         }
3547 
3548         if (mAppWindowToken != null) {
3549             mAppWindowToken.startFreezingScreen();
3550         }
3551         // The process will be killed until the activity reports stopped with saved state (see
3552         // {@link ActivityTaskManagerService.activityStopped}).
3553         try {
3554             mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(), appToken,
3555                     StopActivityItem.obtain(false /* showWindow */, 0 /* configChanges */));
3556         } catch (RemoteException e) {
3557             Slog.w(TAG, "Exception thrown during restart " + this, e);
3558         }
3559         mStackSupervisor.scheduleRestartTimeout(this);
3560     }
3561 
isProcessRunning()3562     private boolean isProcessRunning() {
3563         WindowProcessController proc = app;
3564         if (proc == null) {
3565             proc = mAtmService.mProcessNames.get(processName, info.applicationInfo.uid);
3566         }
3567         return proc != null && proc.hasThread();
3568     }
3569 
3570     /**
3571      * @return Whether a task snapshot starting window may be shown.
3572      */
allowTaskSnapshot()3573     private boolean allowTaskSnapshot() {
3574         if (newIntents == null) {
3575             return true;
3576         }
3577 
3578         // Restrict task snapshot starting window to launcher start, or there is no intent at all
3579         // (eg. task being brought to front). If the intent is something else, likely the app is
3580         // going to show some specific page or view, instead of what's left last time.
3581         for (int i = newIntents.size() - 1; i >= 0; i--) {
3582             final Intent intent = newIntents.get(i);
3583             if (intent != null && !ActivityRecord.isMainIntent(intent)) {
3584                 return false;
3585             }
3586         }
3587         return true;
3588     }
3589 
3590     /**
3591      * Returns {@code true} if the associated activity has the no history flag set on it.
3592      * {@code false} otherwise.
3593      */
isNoHistory()3594     boolean isNoHistory() {
3595         return (intent.getFlags() & FLAG_ACTIVITY_NO_HISTORY) != 0
3596                 || (info.flags & FLAG_NO_HISTORY) != 0;
3597     }
3598 
saveToXml(XmlSerializer out)3599     void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
3600         out.attribute(null, ATTR_ID, String.valueOf(createTime));
3601         out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
3602         if (launchedFromPackage != null) {
3603             out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
3604         }
3605         if (resolvedType != null) {
3606             out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
3607         }
3608         out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
3609         out.attribute(null, ATTR_USERID, String.valueOf(mUserId));
3610 
3611         if (taskDescription != null) {
3612             taskDescription.saveToXml(out);
3613         }
3614 
3615         out.startTag(null, TAG_INTENT);
3616         intent.saveToXml(out);
3617         out.endTag(null, TAG_INTENT);
3618 
3619         if (isPersistable() && persistentState != null) {
3620             out.startTag(null, TAG_PERSISTABLEBUNDLE);
3621             persistentState.saveToXml(out);
3622             out.endTag(null, TAG_PERSISTABLEBUNDLE);
3623         }
3624     }
3625 
restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)3626     static ActivityRecord restoreFromXml(XmlPullParser in,
3627             ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
3628         Intent intent = null;
3629         PersistableBundle persistentState = null;
3630         int launchedFromUid = 0;
3631         String launchedFromPackage = null;
3632         String resolvedType = null;
3633         boolean componentSpecified = false;
3634         int userId = 0;
3635         long createTime = -1;
3636         final int outerDepth = in.getDepth();
3637         TaskDescription taskDescription = new TaskDescription();
3638 
3639         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
3640             final String attrName = in.getAttributeName(attrNdx);
3641             final String attrValue = in.getAttributeValue(attrNdx);
3642             if (DEBUG) Slog.d(TaskPersister.TAG,
3643                         "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
3644             if (ATTR_ID.equals(attrName)) {
3645                 createTime = Long.parseLong(attrValue);
3646             } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
3647                 launchedFromUid = Integer.parseInt(attrValue);
3648             } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
3649                 launchedFromPackage = attrValue;
3650             } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
3651                 resolvedType = attrValue;
3652             } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
3653                 componentSpecified = Boolean.parseBoolean(attrValue);
3654             } else if (ATTR_USERID.equals(attrName)) {
3655                 userId = Integer.parseInt(attrValue);
3656             } else if (attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) {
3657                 taskDescription.restoreFromXml(attrName, attrValue);
3658             } else {
3659                 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
3660             }
3661         }
3662 
3663         int event;
3664         while (((event = in.next()) != END_DOCUMENT) &&
3665                 (event != END_TAG || in.getDepth() >= outerDepth)) {
3666             if (event == START_TAG) {
3667                 final String name = in.getName();
3668                 if (DEBUG)
3669                         Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
3670                 if (TAG_INTENT.equals(name)) {
3671                     intent = Intent.restoreFromXml(in);
3672                     if (DEBUG)
3673                             Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
3674                 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
3675                     persistentState = PersistableBundle.restoreFromXml(in);
3676                     if (DEBUG) Slog.d(TaskPersister.TAG,
3677                             "ActivityRecord: persistentState=" + persistentState);
3678                 } else {
3679                     Slog.w(TAG, "restoreActivity: unexpected name=" + name);
3680                     XmlUtils.skipCurrentTag(in);
3681                 }
3682             }
3683         }
3684 
3685         if (intent == null) {
3686             throw new XmlPullParserException("restoreActivity error intent=" + intent);
3687         }
3688 
3689         final ActivityTaskManagerService service = stackSupervisor.mService;
3690         final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
3691                 userId, Binder.getCallingUid());
3692         if (aInfo == null) {
3693             throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
3694                     " resolvedType=" + resolvedType);
3695         }
3696         final ActivityRecord r = new ActivityRecord(service, null /* caller */,
3697                 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType,
3698                 aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */,
3699                 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */,
3700                 stackSupervisor, null /* options */, null /* sourceRecord */);
3701 
3702         r.persistentState = persistentState;
3703         r.taskDescription = taskDescription;
3704         r.createTime = createTime;
3705 
3706         return r;
3707     }
3708 
isInVrUiMode(Configuration config)3709     private static boolean isInVrUiMode(Configuration config) {
3710         return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
3711     }
3712 
getUid()3713     int getUid() {
3714         return info.applicationInfo.uid;
3715     }
3716 
setShowWhenLocked(boolean showWhenLocked)3717     void setShowWhenLocked(boolean showWhenLocked) {
3718         mShowWhenLocked = showWhenLocked;
3719         mRootActivityContainer.ensureActivitiesVisible(null, 0 /* configChanges */,
3720                 false /* preserveWindows */);
3721     }
3722 
setInheritShowWhenLocked(boolean inheritShowWhenLocked)3723     void setInheritShowWhenLocked(boolean inheritShowWhenLocked) {
3724         mInheritShownWhenLocked = inheritShowWhenLocked;
3725         mRootActivityContainer.ensureActivitiesVisible(null, 0, false);
3726     }
3727 
3728     /**
3729      * @return true if the activity windowing mode is not
3730      *         {@link android.app.WindowConfiguration#WINDOWING_MODE_PINNED} and a) activity
3731      *         contains windows that have {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set or if the
3732      *         activity has set {@link #mShowWhenLocked}, or b) if the activity has set
3733      *         {@link #mInheritShownWhenLocked} and the activity behind this satisfies the
3734      *         conditions a) above.
3735      *         Multi-windowing mode will be exited if true is returned.
3736      */
canShowWhenLocked()3737     boolean canShowWhenLocked() {
3738         if (!inPinnedWindowingMode() && (mShowWhenLocked
3739                 || (mAppWindowToken != null && mAppWindowToken.containsShowWhenLockedWindow()))) {
3740             return true;
3741         } else if (mInheritShownWhenLocked) {
3742             ActivityRecord r = getActivityBelow();
3743             return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
3744                     || (r.mAppWindowToken != null
3745                         && r.mAppWindowToken.containsShowWhenLockedWindow()));
3746         } else {
3747             return false;
3748         }
3749     }
3750 
3751     /**
3752      * @return an {@link ActivityRecord} of the activity below this activity, or {@code null} if no
3753      * such activity exists.
3754      */
3755     @Nullable
getActivityBelow()3756     private ActivityRecord getActivityBelow() {
3757         final int pos = task.mActivities.indexOf(this);
3758         if (pos == -1) {
3759             throw new IllegalStateException("Activity not found in its task");
3760         }
3761         return pos == 0 ? null : task.getChildAt(pos - 1);
3762     }
3763 
setTurnScreenOn(boolean turnScreenOn)3764     void setTurnScreenOn(boolean turnScreenOn) {
3765         mTurnScreenOn = turnScreenOn;
3766     }
3767 
3768     /**
3769      * Determines whether this ActivityRecord can turn the screen on. It checks whether the flag
3770      * {@link #mTurnScreenOn} is set and checks whether the ActivityRecord should be visible
3771      * depending on Keyguard state
3772      *
3773      * @return true if the screen can be turned on, false otherwise.
3774      */
canTurnScreenOn()3775     boolean canTurnScreenOn() {
3776         final ActivityStack stack = getActivityStack();
3777         return mTurnScreenOn && stack != null &&
3778                 stack.checkKeyguardVisibility(this, true /* shouldBeVisible */, true /* isTop */);
3779     }
3780 
3781     /**
3782      * Check if this activity is able to resume. For pre-Q apps, only the topmost activities of each
3783      * process are allowed to be resumed.
3784      *
3785      * @return true if this activity can be resumed.
3786      */
canResumeByCompat()3787     boolean canResumeByCompat() {
3788         return app == null || app.updateTopResumingActivityInProcessIfNeeded(this);
3789     }
3790 
getTurnScreenOnFlag()3791     boolean getTurnScreenOnFlag() {
3792         return mTurnScreenOn;
3793     }
3794 
isTopRunningActivity()3795     boolean isTopRunningActivity() {
3796         return mRootActivityContainer.topRunningActivity() == this;
3797     }
3798 
3799     /**
3800      * @return {@code true} if this is the resumed activity on its current display, {@code false}
3801      * otherwise.
3802      */
isResumedActivityOnDisplay()3803     boolean isResumedActivityOnDisplay() {
3804         final ActivityDisplay display = getDisplay();
3805         return display != null && this == display.getResumedActivity();
3806     }
3807 
registerRemoteAnimations(RemoteAnimationDefinition definition)3808     void registerRemoteAnimations(RemoteAnimationDefinition definition) {
3809         if (mAppWindowToken == null) {
3810             Slog.w(TAG_WM, "Attempted to register remote animations with non-existing app"
3811                     + " token: " + appToken);
3812             return;
3813         }
3814         mAppWindowToken.registerRemoteAnimations(definition);
3815     }
3816 
3817     @Override
toString()3818     public String toString() {
3819         if (stringName != null) {
3820             return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) +
3821                     (finishing ? " f}" : "}");
3822         }
3823         StringBuilder sb = new StringBuilder(128);
3824         sb.append("ActivityRecord{");
3825         sb.append(Integer.toHexString(System.identityHashCode(this)));
3826         sb.append(" u");
3827         sb.append(mUserId);
3828         sb.append(' ');
3829         sb.append(intent.getComponent().flattenToShortString());
3830         stringName = sb.toString();
3831         return toString();
3832     }
3833 
writeIdentifierToProto(ProtoOutputStream proto, long fieldId)3834     void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
3835         final long token = proto.start(fieldId);
3836         proto.write(HASH_CODE, System.identityHashCode(this));
3837         proto.write(USER_ID, mUserId);
3838         proto.write(TITLE, intent.getComponent().flattenToShortString());
3839         proto.end(token);
3840     }
3841 
3842     /**
3843      * Write all fields to an {@code ActivityRecordProto}. This assumes the
3844      * {@code ActivityRecordProto} is the outer-most proto data.
3845      */
writeToProto(ProtoOutputStream proto)3846     void writeToProto(ProtoOutputStream proto) {
3847         super.writeToProto(proto, CONFIGURATION_CONTAINER, WindowTraceLogLevel.ALL);
3848         writeIdentifierToProto(proto, IDENTIFIER);
3849         proto.write(STATE, mState.toString());
3850         proto.write(VISIBLE, visible);
3851         proto.write(FRONT_OF_TASK, frontOfTask);
3852         if (hasProcess()) {
3853             proto.write(PROC_ID, app.getPid());
3854         }
3855         proto.write(TRANSLUCENT, !fullscreen);
3856     }
3857 
writeToProto(ProtoOutputStream proto, long fieldId)3858     public void writeToProto(ProtoOutputStream proto, long fieldId) {
3859         final long token = proto.start(fieldId);
3860         writeToProto(proto);
3861         proto.end(token);
3862     }
3863 
3864     /**
3865      * The precomputed insets of the display in each rotation. This is used to make the size
3866      * compatibility mode activity compute the configuration without relying on its current display.
3867      */
3868     static class CompatDisplayInsets {
3869         final int mDisplayWidth;
3870         final int mDisplayHeight;
3871 
3872         /**
3873          * The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
3874          * is used to compute the appBounds.
3875          */
3876         final Rect[] mNonDecorInsets = new Rect[4];
3877         /**
3878          * The stableInsets for each rotation. Includes the status bar inset and the
3879          * nonDecorInsets. It is used to compute {@link Configuration#screenWidthDp} and
3880          * {@link Configuration#screenHeightDp}.
3881          */
3882         final Rect[] mStableInsets = new Rect[4];
3883 
CompatDisplayInsets(DisplayContent display)3884         CompatDisplayInsets(DisplayContent display) {
3885             mDisplayWidth = display.mBaseDisplayWidth;
3886             mDisplayHeight = display.mBaseDisplayHeight;
3887             final DisplayPolicy policy = display.getDisplayPolicy();
3888             for (int rotation = 0; rotation < 4; rotation++) {
3889                 mNonDecorInsets[rotation] = new Rect();
3890                 mStableInsets[rotation] = new Rect();
3891                 final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
3892                 final int dw = rotated ? mDisplayHeight : mDisplayWidth;
3893                 final int dh = rotated ? mDisplayWidth : mDisplayHeight;
3894                 final DisplayCutout cutout = display.calculateDisplayCutoutForRotation(rotation)
3895                         .getDisplayCutout();
3896                 policy.getNonDecorInsetsLw(rotation, dw, dh, cutout, mNonDecorInsets[rotation]);
3897                 mStableInsets[rotation].set(mNonDecorInsets[rotation]);
3898                 policy.convertNonDecorInsetsToStableInsets(mStableInsets[rotation], rotation);
3899             }
3900         }
3901 
getDisplayBoundsByRotation(Rect outBounds, int rotation)3902         void getDisplayBoundsByRotation(Rect outBounds, int rotation) {
3903             final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);
3904             final int dw = rotated ? mDisplayHeight : mDisplayWidth;
3905             final int dh = rotated ? mDisplayWidth : mDisplayHeight;
3906             outBounds.set(0, 0, dw, dh);
3907         }
3908 
getDisplayBoundsByOrientation(Rect outBounds, int orientation)3909         void getDisplayBoundsByOrientation(Rect outBounds, int orientation) {
3910             final int longSide = Math.max(mDisplayWidth, mDisplayHeight);
3911             final int shortSide = Math.min(mDisplayWidth, mDisplayHeight);
3912             final boolean isLandscape = orientation == ORIENTATION_LANDSCAPE;
3913             outBounds.set(0, 0, isLandscape ? longSide : shortSide,
3914                     isLandscape ? shortSide : longSide);
3915         }
3916     }
3917 }
3918