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.am;
18 
19 import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
20 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
21 import static android.app.ActivityManager.StackId;
22 import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
23 import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
24 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
25 import static android.app.ActivityManager.StackId.HOME_STACK_ID;
26 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
27 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
28 import static android.app.ActivityManager.TaskDescription.ATTR_TASKDESCRIPTION_PREFIX;
29 import static android.app.ActivityOptions.ANIM_CLIP_REVEAL;
30 import static android.app.ActivityOptions.ANIM_CUSTOM;
31 import static android.app.ActivityOptions.ANIM_SCALE_UP;
32 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION;
33 import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN;
34 import static android.app.ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP;
35 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN;
36 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP;
37 import static android.app.AppOpsManager.MODE_ALLOWED;
38 import static android.app.AppOpsManager.OP_PICTURE_IN_PICTURE;
39 import static android.content.Intent.ACTION_MAIN;
40 import static android.content.Intent.CATEGORY_HOME;
41 import static android.content.Intent.CATEGORY_LAUNCHER;
42 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
43 import static android.content.Intent.FLAG_ACTIVITY_NO_HISTORY;
44 import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
45 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
46 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE;
47 import static android.content.pm.ActivityInfo.CONFIG_SMALLEST_SCREEN_SIZE;
48 import static android.content.pm.ActivityInfo.CONFIG_UI_MODE;
49 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
50 import static android.content.pm.ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
51 import static android.content.pm.ActivityInfo.FLAG_IMMERSIVE;
52 import static android.content.pm.ActivityInfo.FLAG_MULTIPROCESS;
53 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
54 import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
55 import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
56 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
57 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
58 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
59 import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
60 import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
61 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
62 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
63 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
64 import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
65 import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY;
66 import static android.content.pm.ActivityInfo.isFixedOrientationLandscape;
67 import static android.content.pm.ActivityInfo.isFixedOrientationPortrait;
68 import static android.content.res.Configuration.EMPTY;
69 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
70 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
71 import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
72 import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
73 import static android.os.Build.VERSION_CODES.HONEYCOMB;
74 import static android.os.Build.VERSION_CODES.O;
75 import static android.os.Process.SYSTEM_UID;
76 import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
77 
78 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
79 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SAVED_STATE;
80 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SCREENSHOTS;
81 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STATES;
82 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
83 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_THUMBNAILS;
84 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
85 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_CONFIGURATION;
86 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SAVED_STATE;
87 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SCREENSHOTS;
88 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
89 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
90 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_THUMBNAILS;
91 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
92 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
93 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
94 import static com.android.server.am.ActivityManagerService.IS_USER_BUILD;
95 import static com.android.server.am.ActivityManagerService.TAKE_FULLSCREEN_SCREENSHOTS;
96 import static com.android.server.am.ActivityStack.ActivityState.DESTROYED;
97 import static com.android.server.am.ActivityStack.ActivityState.DESTROYING;
98 import static com.android.server.am.ActivityStack.ActivityState.INITIALIZING;
99 import static com.android.server.am.ActivityStack.ActivityState.PAUSED;
100 import static com.android.server.am.ActivityStack.ActivityState.PAUSING;
101 import static com.android.server.am.ActivityStack.ActivityState.RESUMED;
102 import static com.android.server.am.ActivityStack.ActivityState.STOPPED;
103 import static com.android.server.am.ActivityStack.ActivityState.STOPPING;
104 import static com.android.server.am.ActivityStack.LAUNCH_TICK;
105 import static com.android.server.am.ActivityStack.LAUNCH_TICK_MSG;
106 import static com.android.server.am.ActivityStack.PAUSE_TIMEOUT_MSG;
107 import static com.android.server.am.ActivityStack.STACK_INVISIBLE;
108 import static com.android.server.am.ActivityStack.STOP_TIMEOUT_MSG;
109 import static com.android.server.am.EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME;
110 import static com.android.server.am.EventLogTags.AM_ACTIVITY_LAUNCH_TIME;
111 import static com.android.server.am.EventLogTags.AM_RELAUNCH_ACTIVITY;
112 import static com.android.server.am.EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY;
113 import static com.android.server.am.TaskPersister.DEBUG;
114 import static com.android.server.am.TaskPersister.IMAGE_EXTENSION;
115 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
116 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
117 import static org.xmlpull.v1.XmlPullParser.END_TAG;
118 import static org.xmlpull.v1.XmlPullParser.START_TAG;
119 
120 import android.annotation.NonNull;
121 import android.app.ActivityManager.TaskDescription;
122 import android.app.ActivityOptions;
123 import android.app.PendingIntent;
124 import android.app.PictureInPictureParams;
125 import android.app.ResultInfo;
126 import android.content.ComponentName;
127 import android.content.Intent;
128 import android.content.pm.ActivityInfo;
129 import android.content.pm.ApplicationInfo;
130 import android.content.res.CompatibilityInfo;
131 import android.content.res.Configuration;
132 import android.graphics.Bitmap;
133 import android.graphics.GraphicBuffer;
134 import android.graphics.Rect;
135 import android.os.Build;
136 import android.os.Bundle;
137 import android.os.Debug;
138 import android.os.IBinder;
139 import android.os.Message;
140 import android.os.PersistableBundle;
141 import android.os.Process;
142 import android.os.RemoteException;
143 import android.os.SystemClock;
144 import android.os.Trace;
145 import android.os.UserHandle;
146 import android.service.voice.IVoiceInteractionSession;
147 import android.util.EventLog;
148 import android.util.Log;
149 import android.util.MergedConfiguration;
150 import android.util.Slog;
151 import android.util.TimeUtils;
152 import android.view.AppTransitionAnimationSpec;
153 import android.view.IAppTransitionAnimationSpecsFuture;
154 import android.view.IApplicationToken;
155 import android.view.WindowManager.LayoutParams;
156 
157 import com.android.internal.app.ResolverActivity;
158 import com.android.internal.content.ReferrerIntent;
159 import com.android.internal.util.XmlUtils;
160 import com.android.server.AttributeCache;
161 import com.android.server.AttributeCache.Entry;
162 import com.android.server.am.ActivityStack.ActivityState;
163 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
164 import com.android.server.wm.AppWindowContainerController;
165 import com.android.server.wm.AppWindowContainerListener;
166 import com.android.server.wm.TaskWindowContainerController;
167 
168 import org.xmlpull.v1.XmlPullParser;
169 import org.xmlpull.v1.XmlPullParserException;
170 import org.xmlpull.v1.XmlSerializer;
171 
172 import java.io.File;
173 import java.io.IOException;
174 import java.io.PrintWriter;
175 import java.lang.ref.WeakReference;
176 import java.util.ArrayList;
177 import java.util.Arrays;
178 import java.util.HashSet;
179 import java.util.List;
180 import java.util.Objects;
181 
182 /**
183  * An entry in the history stack, representing an activity.
184  */
185 final class ActivityRecord extends ConfigurationContainer implements AppWindowContainerListener {
186     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM;
187     private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
188     private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE;
189     private static final String TAG_SCREENSHOTS = TAG + POSTFIX_SCREENSHOTS;
190     private static final String TAG_STATES = TAG + POSTFIX_STATES;
191     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
192     private static final String TAG_THUMBNAILS = TAG + POSTFIX_THUMBNAILS;
193     private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
194 
195     private static final boolean SHOW_ACTIVITY_START_TIME = true;
196     private static final String RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
197 
198     private static final String ATTR_ID = "id";
199     private static final String TAG_INTENT = "intent";
200     private static final String ATTR_USERID = "user_id";
201     private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
202     private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
203     private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
204     private static final String ATTR_RESOLVEDTYPE = "resolved_type";
205     private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
206     static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
207 
208     final ActivityManagerService service; // owner
209     final IApplicationToken.Stub appToken; // window manager token
210     AppWindowContainerController mWindowContainerController;
211     final ActivityInfo info; // all about me
212     final ApplicationInfo appInfo; // information about activity's app
213     final int launchedFromPid; // always the pid who started the activity.
214     final int launchedFromUid; // always the uid who started the activity.
215     final String launchedFromPackage; // always the package who started the activity.
216     final int userId;          // Which user is this running for?
217     final Intent intent;    // the original intent that generated us
218     final ComponentName realActivity;  // the intent component, or target of an alias.
219     final String shortComponentName; // the short component name of the intent
220     final String resolvedType; // as per original caller;
221     final String packageName; // the package implementing intent's component
222     final String processName; // process where this component wants to run
223     final String taskAffinity; // as per ActivityInfo.taskAffinity
224     final boolean stateNotNeeded; // As per ActivityInfo.flags
225     boolean fullscreen; // covers the full screen?
226     final boolean noDisplay;  // activity is not displayed?
227     private final boolean componentSpecified;  // did caller specify an explicit component?
228     final boolean rootVoiceInteraction;  // was this the root activity of a voice interaction?
229 
230     static final int APPLICATION_ACTIVITY_TYPE = 0;
231     static final int HOME_ACTIVITY_TYPE = 1;
232     static final int RECENTS_ACTIVITY_TYPE = 2;
233     static final int ASSISTANT_ACTIVITY_TYPE = 3;
234     int mActivityType;
235 
236     private CharSequence nonLocalizedLabel;  // the label information from the package mgr.
237     private int labelRes;           // the label information from the package mgr.
238     private int icon;               // resource identifier of activity's icon.
239     private int logo;               // resource identifier of activity's logo.
240     private int theme;              // resource identifier of activity's theme.
241     private int realTheme;          // actual theme resource we will use, never 0.
242     private int windowFlags;        // custom window flags for preview window.
243     private TaskRecord task;        // the task this is in.
244     private long createTime = System.currentTimeMillis();
245     long displayStartTime;  // when we started launching this activity
246     long fullyDrawnStartTime; // when we started launching this activity
247     private long startTime;         // last time this activity was started
248     long lastVisibleTime;   // last time this activity became visible
249     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
250     long pauseTime;         // last time we started pausing the activity
251     long launchTickTime;    // base time for launch tick messages
252     // Last configuration reported to the activity in the client process.
253     private MergedConfiguration mLastReportedConfiguration;
254     private int mLastReportedDisplayId;
255     private boolean mLastReportedMultiWindowMode;
256     private boolean mLastReportedPictureInPictureMode;
257     CompatibilityInfo compat;// last used compatibility mode
258     ActivityRecord resultTo; // who started this entry, so will get our reply
259     final String resultWho; // additional identifier for use by resultTo.
260     final int requestCode;  // code given by requester (resultTo)
261     ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
262     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
263     ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
264     ActivityOptions pendingOptions; // most recently given options
265     ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
266     AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
267     HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
268     UriPermissionOwner uriPermissions; // current special URI access perms.
269     ProcessRecord app;      // if non-null, hosting application
270     ActivityState state;    // current state we are in
271     Bundle  icicle;         // last saved activity state
272     PersistableBundle persistentState; // last persistently saved activity state
273     boolean frontOfTask;    // is this the root activity of its task?
274     boolean launchFailed;   // set if a launched failed, to abort on 2nd try
275     boolean haveState;      // have we gotten the last activity state?
276     boolean stopped;        // is activity pause finished?
277     boolean delayedResume;  // not yet resumed because of stopped app switches?
278     boolean finishing;      // activity in pending finish list?
279     boolean deferRelaunchUntilPaused;   // relaunch of activity is being deferred until pause is
280                                         // completed
281     boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
282     int configChangeFlags;  // which config values have changed
283     private boolean keysPaused;     // has key dispatching been paused for it?
284     int launchMode;         // the launch mode activity attribute.
285     boolean visible;        // does this activity's window need to be shown?
286     boolean visibleIgnoringKeyguard; // is this activity visible, ignoring the fact that Keyguard
287                                      // might hide this activity?
288     private boolean mDeferHidingClient; // If true we told WM to defer reporting to the client
289                                         // process that it is hidden.
290     boolean sleeping;       // have we told the activity to sleep?
291     boolean nowVisible;     // is this activity's window visible?
292     boolean idle;           // has the activity gone idle?
293     boolean hasBeenLaunched;// has this activity ever been launched?
294     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
295     boolean immersive;      // immersive mode (don't interrupt if possible)
296     boolean forceNewConfig; // force re-create with new config next time
297     boolean supportsPictureInPictureWhilePausing;  // This flag is set by the system to indicate
298         // that the activity can enter picture in picture while pausing (ie. only when another
299         // task is brought to front or started)
300     PictureInPictureParams pictureInPictureArgs = new PictureInPictureParams.Builder().build();
301         // The PiP params used when deferring the entering of picture-in-picture.
302     int launchCount;        // count of launches since last state
303     long lastLaunchTime;    // time of last launch of this activity
304     ComponentName requestedVrComponent; // the requested component for handling VR mode.
305     ArrayList<ActivityContainer> mChildContainers = new ArrayList<>();
306 
307     String stringName;      // for caching of toString().
308 
309     private boolean inHistory;  // are we in the history stack?
310     final ActivityStackSupervisor mStackSupervisor;
311 
312     static final int STARTING_WINDOW_NOT_SHOWN = 0;
313     static final int STARTING_WINDOW_SHOWN = 1;
314     static final int STARTING_WINDOW_REMOVED = 2;
315     int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
316     boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
317 
318     boolean mUpdateTaskThumbnailWhenHidden;
319     ActivityContainer mInitialActivityContainer;
320 
321     TaskDescription taskDescription; // the recents information for this activity
322     boolean mLaunchTaskBehind; // this activity is actively being launched with
323         // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed.
324 
325     // These configurations are collected from application's resources based on size-sensitive
326     // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
327     // and drawable-sw400dp will be added to both as 400.
328     private int[] mVerticalSizeConfigurations;
329     private int[] mHorizontalSizeConfigurations;
330     private int[] mSmallestSizeConfigurations;
331 
332     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
333     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
334 
335     // A hint to override the window specified rotation animation, or -1
336     // to use the window specified value. We use this so that
337     // we can select the right animation in the cases of starting
338     // windows, where the app hasn't had time to set a value
339     // on the window.
340     int mRotationAnimationHint = -1;
341 
342     // The bounds of this activity. Mainly used for aspect-ratio compatibility.
343     // TODO(b/36505427): Every level on ConfigurationContainer now has bounds information, which
344     // directly affects the configuration. We should probably move this into that class and have it
345     // handle calculating override configuration from the bounds.
346     private final Rect mBounds = new Rect();
347 
348     /**
349      * Temp configs used in {@link #ensureActivityConfigurationLocked(int, boolean)}
350      */
351     private final Configuration mTmpConfig = new Configuration();
352     private final Rect mTmpBounds = new Rect();
353 
startingWindowStateToString(int state)354     private static String startingWindowStateToString(int state) {
355         switch (state) {
356             case STARTING_WINDOW_NOT_SHOWN:
357                 return "STARTING_WINDOW_NOT_SHOWN";
358             case STARTING_WINDOW_SHOWN:
359                 return "STARTING_WINDOW_SHOWN";
360             case STARTING_WINDOW_REMOVED:
361                 return "STARTING_WINDOW_REMOVED";
362             default:
363                 return "unknown state=" + state;
364         }
365     }
366 
dump(PrintWriter pw, String prefix)367     void dump(PrintWriter pw, String prefix) {
368         final long now = SystemClock.uptimeMillis();
369         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
370                 pw.print(" processName="); pw.println(processName);
371         pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
372                 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
373                 pw.print(" userId="); pw.println(userId);
374         pw.print(prefix); pw.print("app="); pw.println(app);
375         pw.print(prefix); pw.println(intent.toInsecureStringWithClip());
376         pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
377                 pw.print(" task="); pw.println(task);
378         pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
379         pw.print(prefix); pw.print("realActivity=");
380                 pw.println(realActivity.flattenToShortString());
381         if (appInfo != null) {
382             pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
383             if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
384                 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
385             }
386             pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
387             if (appInfo.splitSourceDirs != null) {
388                 pw.print(prefix); pw.print("splitDir=");
389                         pw.println(Arrays.toString(appInfo.splitSourceDirs));
390             }
391         }
392         pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
393                 pw.print(" componentSpecified="); pw.print(componentSpecified);
394                 pw.print(" mActivityType="); pw.println(mActivityType);
395         if (rootVoiceInteraction) {
396             pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
397         }
398         pw.print(prefix); pw.print("compat="); pw.print(compat);
399                 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
400                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
401                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
402         pw.println(prefix + "mLastReportedConfigurations:");
403         mLastReportedConfiguration.dump(pw, prefix + " ");
404 
405         pw.print(prefix); pw.print("CurrentConfiguration="); pw.println(getConfiguration());
406         if (!getOverrideConfiguration().equals(EMPTY)) {
407             pw.println(prefix + "OverrideConfiguration=" + getOverrideConfiguration());
408         }
409         if (!mBounds.isEmpty()) {
410             pw.println(prefix + "mBounds=" + mBounds);
411         }
412         if (resultTo != null || resultWho != null) {
413             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
414                     pw.print(" resultWho="); pw.print(resultWho);
415                     pw.print(" resultCode="); pw.println(requestCode);
416         }
417         if (taskDescription != null) {
418             final String iconFilename = taskDescription.getIconFilename();
419             if (iconFilename != null || taskDescription.getLabel() != null ||
420                     taskDescription.getPrimaryColor() != 0) {
421                 pw.print(prefix); pw.print("taskDescription:");
422                         pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
423                         pw.print(" label=\""); pw.print(taskDescription.getLabel());
424                                 pw.print("\"");
425                         pw.print(" primaryColor=");
426                         pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
427                         pw.print(prefix + " backgroundColor=");
428                         pw.println(Integer.toHexString(taskDescription.getBackgroundColor()));
429                         pw.print(prefix + " statusBarColor=");
430                         pw.println(Integer.toHexString(taskDescription.getStatusBarColor()));
431                         pw.print(prefix + " navigationBarColor=");
432                         pw.println(Integer.toHexString(taskDescription.getNavigationBarColor()));
433             }
434             if (iconFilename == null && taskDescription.getIcon() != null) {
435                 pw.print(prefix); pw.println("taskDescription contains Bitmap");
436             }
437         }
438         if (results != null) {
439             pw.print(prefix); pw.print("results="); pw.println(results);
440         }
441         if (pendingResults != null && pendingResults.size() > 0) {
442             pw.print(prefix); pw.println("Pending Results:");
443             for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
444                 PendingIntentRecord pir = wpir != null ? wpir.get() : null;
445                 pw.print(prefix); pw.print("  - ");
446                 if (pir == null) {
447                     pw.println("null");
448                 } else {
449                     pw.println(pir);
450                     pir.dump(pw, prefix + "    ");
451                 }
452             }
453         }
454         if (newIntents != null && newIntents.size() > 0) {
455             pw.print(prefix); pw.println("Pending New Intents:");
456             for (int i=0; i<newIntents.size(); i++) {
457                 Intent intent = newIntents.get(i);
458                 pw.print(prefix); pw.print("  - ");
459                 if (intent == null) {
460                     pw.println("null");
461                 } else {
462                     pw.println(intent.toShortString(false, true, false, true));
463                 }
464             }
465         }
466         if (pendingOptions != null) {
467             pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
468         }
469         if (appTimeTracker != null) {
470             appTimeTracker.dumpWithHeader(pw, prefix, false);
471         }
472         if (uriPermissions != null) {
473             uriPermissions.dump(pw, prefix);
474         }
475         pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
476                 pw.print(" launchCount="); pw.print(launchCount);
477                 pw.print(" lastLaunchTime=");
478                 if (lastLaunchTime == 0) pw.print("0");
479                 else TimeUtils.formatDuration(lastLaunchTime, now, pw);
480                 pw.println();
481         pw.print(prefix); pw.print("haveState="); pw.print(haveState);
482                 pw.print(" icicle="); pw.println(icicle);
483         pw.print(prefix); pw.print("state="); pw.print(state);
484                 pw.print(" stopped="); pw.print(stopped);
485                 pw.print(" delayedResume="); pw.print(delayedResume);
486                 pw.print(" finishing="); pw.println(finishing);
487         pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
488                 pw.print(" inHistory="); pw.print(inHistory);
489                 pw.print(" visible="); pw.print(visible);
490                 pw.print(" sleeping="); pw.print(sleeping);
491                 pw.print(" idle="); pw.print(idle);
492                 pw.print(" mStartingWindowState=");
493                 pw.println(startingWindowStateToString(mStartingWindowState));
494         pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
495                 pw.print(" noDisplay="); pw.print(noDisplay);
496                 pw.print(" immersive="); pw.print(immersive);
497                 pw.print(" launchMode="); pw.println(launchMode);
498         pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
499                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
500         pw.print(prefix); pw.print("mActivityType=");
501                 pw.println(activityTypeToString(mActivityType));
502         if (requestedVrComponent != null) {
503             pw.print(prefix);
504             pw.print("requestedVrComponent=");
505             pw.println(requestedVrComponent);
506         }
507         if (displayStartTime != 0 || startTime != 0) {
508             pw.print(prefix); pw.print("displayStartTime=");
509                     if (displayStartTime == 0) pw.print("0");
510                     else TimeUtils.formatDuration(displayStartTime, now, pw);
511                     pw.print(" startTime=");
512                     if (startTime == 0) pw.print("0");
513                     else TimeUtils.formatDuration(startTime, now, pw);
514                     pw.println();
515         }
516         final boolean waitingVisible =
517                 mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this);
518         if (lastVisibleTime != 0 || waitingVisible || nowVisible) {
519             pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
520                     pw.print(" nowVisible="); pw.print(nowVisible);
521                     pw.print(" lastVisibleTime=");
522                     if (lastVisibleTime == 0) pw.print("0");
523                     else TimeUtils.formatDuration(lastVisibleTime, now, pw);
524                     pw.println();
525         }
526         if (mDeferHidingClient) {
527             pw.println(prefix + "mDeferHidingClient=" + mDeferHidingClient);
528         }
529         if (deferRelaunchUntilPaused || configChangeFlags != 0) {
530             pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused);
531                     pw.print(" configChangeFlags=");
532                     pw.println(Integer.toHexString(configChangeFlags));
533         }
534         if (connections != null) {
535             pw.print(prefix); pw.print("connections="); pw.println(connections);
536         }
537         if (info != null) {
538             pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
539             pw.println(prefix + "mLastReportedMultiWindowMode=" + mLastReportedMultiWindowMode
540                     + " mLastReportedPictureInPictureMode=" + mLastReportedPictureInPictureMode);
541             if (info.supportsPictureInPicture()) {
542                 pw.println(prefix + "supportsPictureInPicture=" + info.supportsPictureInPicture());
543                 pw.println(prefix + "supportsPictureInPictureWhilePausing: "
544                         + supportsPictureInPictureWhilePausing);
545             }
546             if (info.maxAspectRatio != 0) {
547                 pw.println(prefix + "maxAspectRatio=" + info.maxAspectRatio);
548             }
549         }
550     }
551 
crossesHorizontalSizeThreshold(int firstDp, int secondDp)552     private boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
553         return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
554     }
555 
crossesVerticalSizeThreshold(int firstDp, int secondDp)556     private boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
557         return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp);
558     }
559 
crossesSmallestSizeThreshold(int firstDp, int secondDp)560     private boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
561         return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp);
562     }
563 
564     /**
565      * The purpose of this method is to decide whether the activity needs to be relaunched upon
566      * changing its size. In most cases the activities don't need to be relaunched, if the resize
567      * is small, all the activity content has to do is relayout itself within new bounds. There are
568      * cases however, where the activity's content would be completely changed in the new size and
569      * the full relaunch is required.
570      *
571      * The activity will report to us vertical and horizontal thresholds after which a relaunch is
572      * required. These thresholds are collected from the application resource qualifiers. For
573      * example, if application has layout-w600dp resource directory, then it needs a relaunch when
574      * we resize from width of 650dp to 550dp, as it crosses the 600dp threshold. However, if
575      * it resizes width from 620dp to 700dp, it won't be relaunched as it stays on the same side
576      * of the threshold.
577      */
crossesSizeThreshold(int[] thresholds, int firstDp, int secondDp)578     private static boolean crossesSizeThreshold(int[] thresholds, int firstDp,
579             int secondDp) {
580         if (thresholds == null) {
581             return false;
582         }
583         for (int i = thresholds.length - 1; i >= 0; i--) {
584             final int threshold = thresholds[i];
585             if ((firstDp < threshold && secondDp >= threshold)
586                     || (firstDp >= threshold && secondDp < threshold)) {
587                 return true;
588             }
589         }
590         return false;
591     }
592 
setSizeConfigurations(int[] horizontalSizeConfiguration, int[] verticalSizeConfigurations, int[] smallestSizeConfigurations)593     void setSizeConfigurations(int[] horizontalSizeConfiguration,
594             int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
595         mHorizontalSizeConfigurations = horizontalSizeConfiguration;
596         mVerticalSizeConfigurations = verticalSizeConfigurations;
597         mSmallestSizeConfigurations = smallestSizeConfigurations;
598     }
599 
scheduleActivityMovedToDisplay(int displayId, Configuration config)600     private void scheduleActivityMovedToDisplay(int displayId, Configuration config) {
601         if (app == null || app.thread == null) {
602             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.w(TAG,
603                     "Can't report activity moved to display - client not running, activityRecord="
604                             + this + ", displayId=" + displayId);
605             return;
606         }
607         try {
608             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
609                     "Reporting activity moved to display" + ", activityRecord=" + this
610                             + ", displayId=" + displayId + ", config=" + config);
611 
612             app.thread.scheduleActivityMovedToDisplay(appToken, displayId,
613                     new Configuration(config));
614         } catch (RemoteException e) {
615             // If process died, whatever.
616         }
617     }
618 
scheduleConfigurationChanged(Configuration config)619     private void scheduleConfigurationChanged(Configuration config) {
620         if (app == null || app.thread == null) {
621             if (DEBUG_CONFIGURATION) Slog.w(TAG,
622                     "Can't report activity configuration update - client not running"
623                             + ", activityRecord=" + this);
624             return;
625         }
626         try {
627             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + ", config: "
628                     + config);
629 
630             app.thread.scheduleActivityConfigurationChanged(appToken, new Configuration(config));
631         } catch (RemoteException e) {
632             // If process died, whatever.
633         }
634     }
635 
updateMultiWindowMode()636     void updateMultiWindowMode() {
637         if (task == null || task.getStack() == null || app == null || app.thread == null) {
638             return;
639         }
640 
641         // An activity is considered to be in multi-window mode if its task isn't fullscreen.
642         final boolean inMultiWindowMode = !task.mFullscreen;
643         if (inMultiWindowMode != mLastReportedMultiWindowMode) {
644             mLastReportedMultiWindowMode = inMultiWindowMode;
645             scheduleMultiWindowModeChanged(getConfiguration());
646         }
647     }
648 
scheduleMultiWindowModeChanged(Configuration overrideConfig)649     private void scheduleMultiWindowModeChanged(Configuration overrideConfig) {
650         try {
651             app.thread.scheduleMultiWindowModeChanged(appToken, mLastReportedMultiWindowMode,
652                     overrideConfig);
653         } catch (Exception e) {
654             // If process died, I don't care.
655         }
656     }
657 
updatePictureInPictureMode(Rect targetStackBounds)658     void updatePictureInPictureMode(Rect targetStackBounds) {
659         if (task == null || task.getStack() == null || app == null || app.thread == null) {
660             return;
661         }
662 
663         final boolean inPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID) &&
664                 (targetStackBounds != null);
665         if (inPictureInPictureMode != mLastReportedPictureInPictureMode) {
666             // Picture-in-picture mode changes also trigger a multi-window mode change as well, so
667             // update that here in order
668             mLastReportedPictureInPictureMode = inPictureInPictureMode;
669             mLastReportedMultiWindowMode = inPictureInPictureMode;
670             final Configuration newConfig = task.computeNewOverrideConfigurationForBounds(
671                     targetStackBounds, null);
672             schedulePictureInPictureModeChanged(newConfig);
673             scheduleMultiWindowModeChanged(newConfig);
674         }
675     }
676 
schedulePictureInPictureModeChanged(Configuration overrideConfig)677     private void schedulePictureInPictureModeChanged(Configuration overrideConfig) {
678         try {
679             app.thread.schedulePictureInPictureModeChanged(appToken,
680                     mLastReportedPictureInPictureMode,
681                     overrideConfig);
682         } catch (Exception e) {
683             // If process died, no one cares.
684         }
685     }
686 
isFreeform()687     boolean isFreeform() {
688         return task != null && task.getStackId() == FREEFORM_WORKSPACE_STACK_ID;
689     }
690 
691     @Override
getChildCount()692     protected int getChildCount() {
693         // {@link ActivityRecord} is a leaf node and has no children.
694         return 0;
695     }
696 
697     @Override
getChildAt(int index)698     protected ConfigurationContainer getChildAt(int index) {
699         return null;
700     }
701 
702     @Override
getParent()703     protected ConfigurationContainer getParent() {
704         return getTask();
705     }
706 
getTask()707     TaskRecord getTask() {
708         return task;
709     }
710 
711     /**
712      * Sets reference to the {@link TaskRecord} the {@link ActivityRecord} will treat as its parent.
713      * Note that this does not actually add the {@link ActivityRecord} as a {@link TaskRecord}
714      * children. However, this method will clean up references to this {@link ActivityRecord} in
715      * {@link ActivityStack}.
716      * @param task The new parent {@link TaskRecord}.
717      */
setTask(TaskRecord task)718     void setTask(TaskRecord task) {
719         setTask(task, false /*reparenting*/);
720     }
721 
722     /**
723      * This method should only be called by {@link TaskRecord#removeActivity(ActivityRecord)}.
724      */
setTask(TaskRecord task, boolean reparenting)725     void setTask(TaskRecord task, boolean reparenting) {
726         // Do nothing if the {@link TaskRecord} is the same as the current {@link getTask}.
727         if (task != null && task == getTask()) {
728             return;
729         }
730 
731         final ActivityStack stack = getStack();
732 
733         // If the new {@link TaskRecord} is from a different {@link ActivityStack}, remove this
734         // {@link ActivityRecord} from its current {@link ActivityStack}.
735         if (!reparenting && stack != null && (task == null || stack != task.getStack())) {
736             stack.onActivityRemovedFromStack(this);
737         }
738 
739         this.task = task;
740 
741         if (!reparenting) {
742             onParentChanged();
743         }
744     }
745 
746     static class Token extends IApplicationToken.Stub {
747         private final WeakReference<ActivityRecord> weakActivity;
748 
Token(ActivityRecord activity)749         Token(ActivityRecord activity) {
750             weakActivity = new WeakReference<>(activity);
751         }
752 
tokenToActivityRecordLocked(Token token)753         private static ActivityRecord tokenToActivityRecordLocked(Token token) {
754             if (token == null) {
755                 return null;
756             }
757             ActivityRecord r = token.weakActivity.get();
758             if (r == null || r.getStack() == null) {
759                 return null;
760             }
761             return r;
762         }
763 
764         @Override
toString()765         public String toString() {
766             StringBuilder sb = new StringBuilder(128);
767             sb.append("Token{");
768             sb.append(Integer.toHexString(System.identityHashCode(this)));
769             sb.append(' ');
770             sb.append(weakActivity.get());
771             sb.append('}');
772             return sb.toString();
773         }
774     }
775 
forTokenLocked(IBinder token)776     static ActivityRecord forTokenLocked(IBinder token) {
777         try {
778             return Token.tokenToActivityRecordLocked((Token)token);
779         } catch (ClassCastException e) {
780             Slog.w(TAG, "Bad activity token: " + token, e);
781             return null;
782         }
783     }
784 
isResolverActivity()785     boolean isResolverActivity() {
786         return ResolverActivity.class.getName().equals(realActivity.getClassName());
787     }
788 
ActivityRecord(ActivityManagerService _service, ProcessRecord _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, ActivityContainer container, ActivityOptions options, ActivityRecord sourceRecord)789     ActivityRecord(ActivityManagerService _service, ProcessRecord _caller, int _launchedFromPid,
790             int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
791             ActivityInfo aInfo, Configuration _configuration,
792             ActivityRecord _resultTo, String _resultWho, int _reqCode,
793             boolean _componentSpecified, boolean _rootVoiceInteraction,
794             ActivityStackSupervisor supervisor,
795             ActivityContainer container, ActivityOptions options, ActivityRecord sourceRecord) {
796         service = _service;
797         appToken = new Token(this);
798         info = aInfo;
799         launchedFromPid = _launchedFromPid;
800         launchedFromUid = _launchedFromUid;
801         launchedFromPackage = _launchedFromPackage;
802         userId = UserHandle.getUserId(aInfo.applicationInfo.uid);
803         intent = _intent;
804         shortComponentName = _intent.getComponent().flattenToShortString();
805         resolvedType = _resolvedType;
806         componentSpecified = _componentSpecified;
807         rootVoiceInteraction = _rootVoiceInteraction;
808         mLastReportedConfiguration = new MergedConfiguration(_configuration);
809         resultTo = _resultTo;
810         resultWho = _resultWho;
811         requestCode = _reqCode;
812         state = INITIALIZING;
813         frontOfTask = false;
814         launchFailed = false;
815         stopped = false;
816         delayedResume = false;
817         finishing = false;
818         deferRelaunchUntilPaused = false;
819         keysPaused = false;
820         inHistory = false;
821         visible = false;
822         nowVisible = false;
823         idle = false;
824         hasBeenLaunched = false;
825         mStackSupervisor = supervisor;
826         mInitialActivityContainer = container;
827 
828         mRotationAnimationHint = aInfo.rotationAnimation;
829 
830         if (options != null) {
831             pendingOptions = options;
832             mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind();
833 
834             final int rotationAnimation = pendingOptions.getRotationAnimationHint();
835             // Only override manifest supplied option if set.
836             if (rotationAnimation >= 0) {
837                 mRotationAnimationHint = rotationAnimation;
838             }
839             PendingIntent usageReport = pendingOptions.getUsageTimeReport();
840             if (usageReport != null) {
841                 appTimeTracker = new AppTimeTracker(usageReport);
842             }
843         }
844 
845         // This starts out true, since the initial state of an activity is that we have everything,
846         // and we shouldn't never consider it lacking in state to be removed if it dies.
847         haveState = true;
848 
849         // If the class name in the intent doesn't match that of the target, this is
850         // probably an alias. We have to create a new ComponentName object to keep track
851         // of the real activity name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
852         if (aInfo.targetActivity == null
853                 || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
854                 && (aInfo.launchMode == LAUNCH_MULTIPLE
855                 || aInfo.launchMode == LAUNCH_SINGLE_TOP))) {
856             realActivity = _intent.getComponent();
857         } else {
858             realActivity = new ComponentName(aInfo.packageName, aInfo.targetActivity);
859         }
860         taskAffinity = aInfo.taskAffinity;
861         stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
862         appInfo = aInfo.applicationInfo;
863         nonLocalizedLabel = aInfo.nonLocalizedLabel;
864         labelRes = aInfo.labelRes;
865         if (nonLocalizedLabel == null && labelRes == 0) {
866             ApplicationInfo app = aInfo.applicationInfo;
867             nonLocalizedLabel = app.nonLocalizedLabel;
868             labelRes = app.labelRes;
869         }
870         icon = aInfo.getIconResource();
871         logo = aInfo.getLogoResource();
872         theme = aInfo.getThemeResource();
873         realTheme = theme;
874         if (realTheme == 0) {
875             realTheme = aInfo.applicationInfo.targetSdkVersion < HONEYCOMB
876                     ? android.R.style.Theme : android.R.style.Theme_Holo;
877         }
878         if ((aInfo.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
879             windowFlags |= LayoutParams.FLAG_HARDWARE_ACCELERATED;
880         }
881         if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
882                 && (aInfo.applicationInfo.uid == SYSTEM_UID
883                     || aInfo.applicationInfo.uid == _caller.info.uid)) {
884             processName = _caller.processName;
885         } else {
886             processName = aInfo.processName;
887         }
888 
889         if ((aInfo.flags & FLAG_EXCLUDE_FROM_RECENTS) != 0) {
890             intent.addFlags(FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
891         }
892 
893         packageName = aInfo.applicationInfo.packageName;
894         launchMode = aInfo.launchMode;
895 
896         Entry ent = AttributeCache.instance().get(packageName,
897                 realTheme, com.android.internal.R.styleable.Window, userId);
898         fullscreen = ent != null && !ActivityInfo.isTranslucentOrFloating(ent.array);
899         noDisplay = ent != null && ent.array.getBoolean(
900                 com.android.internal.R.styleable.Window_windowNoDisplay, false);
901 
902         setActivityType(_componentSpecified, _launchedFromUid, _intent, options, sourceRecord);
903 
904         immersive = (aInfo.flags & FLAG_IMMERSIVE) != 0;
905 
906         requestedVrComponent = (aInfo.requestedVrComponent == null) ?
907                 null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
908     }
909 
910     AppWindowContainerController getWindowContainerController() {
911         return mWindowContainerController;
912     }
913 
914     void createWindowContainer() {
915         if (mWindowContainerController != null) {
916             throw new IllegalArgumentException("Window container=" + mWindowContainerController
917                     + " already created for r=" + this);
918         }
919 
920         inHistory = true;
921 
922         final TaskWindowContainerController taskController = task.getWindowContainerController();
923 
924         // TODO(b/36505427): Maybe this call should be moved inside updateOverrideConfiguration()
925         task.updateOverrideConfigurationFromLaunchBounds();
926         // Make sure override configuration is up-to-date before using to create window controller.
927         updateOverrideConfiguration();
928 
929         mWindowContainerController = new AppWindowContainerController(taskController, appToken,
930                 this, Integer.MAX_VALUE /* add on top */, info.screenOrientation, fullscreen,
931                 (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0, info.configChanges,
932                 task.voiceSession != null, mLaunchTaskBehind, isAlwaysFocusable(),
933                 appInfo.targetSdkVersion, mRotationAnimationHint,
934                 ActivityManagerService.getInputDispatchingTimeoutLocked(this) * 1000000L,
935                 getOverrideConfiguration(), mBounds);
936 
937         task.addActivityToTop(this);
938 
939         // When an activity is started directly into a split-screen fullscreen stack, we need to
940         // update the initial multi-window modes so that the callbacks are scheduled correctly when
941         // the user leaves that mode.
942         mLastReportedMultiWindowMode = !task.mFullscreen;
943         mLastReportedPictureInPictureMode = (task.getStackId() == PINNED_STACK_ID);
944 
945         onOverrideConfigurationSent();
946     }
947 
948     void removeWindowContainer() {
949         // Resume key dispatching if it is currently paused before we remove the container.
950         resumeKeyDispatchingLocked();
951 
952         mWindowContainerController.removeContainer(getDisplayId());
953         mWindowContainerController = null;
954     }
955 
956     /**
957      * Reparents this activity into {@param newTask} at the provided {@param position}.  The caller
958      * should ensure that the {@param newTask} is not already the parent of this activity.
959      */
960     void reparent(TaskRecord newTask, int position, String reason) {
961         final TaskRecord prevTask = task;
962         if (prevTask == newTask) {
963             throw new IllegalArgumentException(reason + ": task=" + newTask
964                     + " is already the parent of r=" + this);
965         }
966 
967         // TODO: Ensure that we do not directly reparent activities across stacks, as that may leave
968         //       the stacks in strange states. For now, we should use Task.reparent() to ensure that
969         //       the stack is left in an OK state.
970         if (prevTask != null && newTask != null && prevTask.getStack() != newTask.getStack()) {
971             throw new IllegalArgumentException(reason + ": task=" + newTask
972                     + " is in a different stack (" + newTask.getStackId() + ") than the parent of"
973                     + " r=" + this + " (" + prevTask.getStackId() + ")");
974         }
975 
976         // Must reparent first in window manager
977         mWindowContainerController.reparent(newTask.getWindowContainerController(), position);
978 
979         // Remove the activity from the old task and add it to the new task.
980         prevTask.removeActivity(this, true /*reparenting*/);
981 
982         newTask.addActivityAtIndex(position, this);
983     }
984 
985     private boolean isHomeIntent(Intent intent) {
986         return ACTION_MAIN.equals(intent.getAction())
987                 && intent.hasCategory(CATEGORY_HOME)
988                 && intent.getCategories().size() == 1
989                 && intent.getData() == null
990                 && intent.getType() == null;
991     }
992 
993     static boolean isMainIntent(Intent intent) {
994         return ACTION_MAIN.equals(intent.getAction())
995                 && intent.hasCategory(CATEGORY_LAUNCHER)
996                 && intent.getCategories().size() == 1
997                 && intent.getData() == null
998                 && intent.getType() == null;
999     }
1000 
1001     private boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) {
1002         if (uid == Process.myUid() || uid == 0) {
1003             // System process can launch home activity.
1004             return true;
1005         }
1006         // Resolver activity can launch home activity.
1007         return sourceRecord != null && sourceRecord.isResolverActivity();
1008     }
1009 
1010     /**
1011      * @return whether the given package name can launch an assist activity.
1012      */
1013     private boolean canLaunchAssistActivity(String packageName) {
1014         if (service.mAssistUtils == null) {
1015             return false;
1016         }
1017 
1018         final ComponentName assistComponent = service.mAssistUtils.getActiveServiceComponentName();
1019         if (assistComponent != null) {
1020             return assistComponent.getPackageName().equals(packageName);
1021         }
1022         return false;
1023     }
1024 
1025     private void setActivityType(boolean componentSpecified, int launchedFromUid, Intent intent,
1026             ActivityOptions options, ActivityRecord sourceRecord) {
1027         if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
1028                 && isHomeIntent(intent) && !isResolverActivity()) {
1029             // This sure looks like a home activity!
1030             mActivityType = HOME_ACTIVITY_TYPE;
1031 
1032             if (info.resizeMode == RESIZE_MODE_FORCE_RESIZEABLE
1033                     || info.resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
1034                 // We only allow home activities to be resizeable if they explicitly requested it.
1035                 info.resizeMode = RESIZE_MODE_UNRESIZEABLE;
1036             }
1037         } else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
1038             mActivityType = RECENTS_ACTIVITY_TYPE;
1039         } else if (options != null && options.getLaunchStackId() == ASSISTANT_STACK_ID
1040                 && canLaunchAssistActivity(launchedFromPackage)) {
1041             mActivityType = ASSISTANT_ACTIVITY_TYPE;
1042         } else {
1043             mActivityType = APPLICATION_ACTIVITY_TYPE;
1044         }
1045     }
1046 
1047     void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
1048         if (launchMode != LAUNCH_SINGLE_INSTANCE && launchMode != LAUNCH_SINGLE_TASK) {
1049             task.setTaskToAffiliateWith(taskToAffiliateWith);
1050         }
1051     }
1052 
1053     /**
1054      * @return Stack value from current task, null if there is no task.
1055      */
1056     <T extends ActivityStack> T getStack() {
1057         return task != null ? (T) task.getStack() : null;
1058     }
1059 
1060     int getStackId() {
1061         return getStack() != null ? getStack().mStackId : INVALID_STACK_ID;
1062     }
1063 
1064     boolean changeWindowTranslucency(boolean toOpaque) {
1065         if (fullscreen == toOpaque) {
1066             return false;
1067         }
1068 
1069         // Keep track of the number of fullscreen activities in this task.
1070         task.numFullscreen += toOpaque ? +1 : -1;
1071 
1072         fullscreen = toOpaque;
1073         return true;
1074     }
1075 
1076     void takeFromHistory() {
1077         if (inHistory) {
1078             inHistory = false;
1079             if (task != null && !finishing) {
1080                 task = null;
1081             }
1082             clearOptionsLocked();
1083         }
1084     }
1085 
1086     boolean isInHistory() {
1087         return inHistory;
1088     }
1089 
1090     boolean isInStackLocked() {
1091         final ActivityStack stack = getStack();
1092         return stack != null && stack.isInStackLocked(this) != null;
1093     }
1094 
1095     boolean isHomeActivity() {
1096         return mActivityType == HOME_ACTIVITY_TYPE;
1097     }
1098 
1099     boolean isRecentsActivity() {
1100         return mActivityType == RECENTS_ACTIVITY_TYPE;
1101     }
1102 
1103     boolean isAssistantActivity() {
1104         return mActivityType == ASSISTANT_ACTIVITY_TYPE;
1105     }
1106 
1107     boolean isApplicationActivity() {
1108         return mActivityType == APPLICATION_ACTIVITY_TYPE;
1109     }
1110 
1111     boolean isPersistable() {
1112         return (info.persistableMode == PERSIST_ROOT_ONLY ||
1113                 info.persistableMode == PERSIST_ACROSS_REBOOTS) &&
1114                 (intent == null ||
1115                         (intent.getFlags() & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
1116     }
1117 
1118     boolean isFocusable() {
1119         return StackId.canReceiveKeys(task.getStackId()) || isAlwaysFocusable();
1120     }
1121 
1122     boolean isResizeable() {
1123         return ActivityInfo.isResizeableMode(info.resizeMode) || info.supportsPictureInPicture();
1124     }
1125 
1126     /**
1127      * @return whether this activity is non-resizeable or forced to be resizeable
1128      */
1129     boolean isNonResizableOrForcedResizable() {
1130         return info.resizeMode != RESIZE_MODE_RESIZEABLE
1131                 && info.resizeMode != RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
1132     }
1133 
1134     /**
1135      * @return whether this activity supports PiP multi-window and can be put in the pinned stack.
1136      */
1137     boolean supportsPictureInPicture() {
1138         return service.mSupportsPictureInPicture && !isHomeActivity()
1139                 && info.supportsPictureInPicture();
1140     }
1141 
1142     /**
1143      * @return whether this activity supports split-screen multi-window and can be put in the docked
1144      *         stack.
1145      */
1146     boolean supportsSplitScreen() {
1147         // An activity can not be docked even if it is considered resizeable because it only
1148         // supports picture-in-picture mode but has a non-resizeable resizeMode
1149         return service.mSupportsSplitScreenMultiWindow && supportsResizeableMultiWindow();
1150     }
1151 
1152     /**
1153      * @return whether this activity supports freeform multi-window and can be put in the freeform
1154      *         stack.
1155      */
1156     boolean supportsFreeform() {
1157         return service.mSupportsFreeformWindowManagement && supportsResizeableMultiWindow();
1158     }
1159 
1160     /**
1161      * @return whether this activity supports non-PiP multi-window.
1162      */
1163     private boolean supportsResizeableMultiWindow() {
1164         return service.mSupportsMultiWindow && !isHomeActivity()
1165                 && (ActivityInfo.isResizeableMode(info.resizeMode)
1166                         || service.mForceResizableActivities);
1167     }
1168 
1169     /**
1170      * Check whether this activity can be launched on the specified display.
1171      * @param displayId Target display id.
1172      * @return {@code true} if either it is the default display or this activity is resizeable and
1173      *         can be put a secondary screen.
1174      */
1175     boolean canBeLaunchedOnDisplay(int displayId) {
1176         return service.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
1177                 supportsResizeableMultiWindow());
1178     }
1179 
1180     /**
1181      * @param beforeStopping Whether this check is for an auto-enter-pip operation, that is to say
1182      *         the activity has requested to enter PiP when it would otherwise be stopped.
1183      *
1184      * @return whether this activity is currently allowed to enter PIP, throwing an exception if
1185      *         the activity is not currently visible and {@param noThrow} is not set.
1186      */
1187     boolean checkEnterPictureInPictureState(String caller, boolean noThrow, boolean beforeStopping) {
1188         if (!supportsPictureInPicture()) {
1189             return false;
1190         }
1191 
1192         // Check app-ops and see if PiP is supported for this package
1193         if (!checkEnterPictureInPictureAppOpsState()) {
1194             return false;
1195         }
1196 
1197         // Check to see if we are in VR mode, and disallow PiP if so
1198         if (service.shouldDisableNonVrUiLocked()) {
1199             return false;
1200         }
1201 
1202         boolean isKeyguardLocked = service.isKeyguardLocked();
1203         boolean isCurrentAppLocked = mStackSupervisor.getLockTaskModeState() != LOCK_TASK_MODE_NONE;
1204         boolean hasPinnedStack = mStackSupervisor.getStack(PINNED_STACK_ID) != null;
1205         // Don't return early if !isNotLocked, since we want to throw an exception if the activity
1206         // is in an incorrect state
1207         boolean isNotLockedOrOnKeyguard = !isKeyguardLocked && !isCurrentAppLocked;
1208 
1209         // We don't allow auto-PiP when something else is already pipped.
1210         if (beforeStopping && hasPinnedStack) {
1211             return false;
1212         }
1213 
1214         switch (state) {
1215             case RESUMED:
1216                 // When visible, allow entering PiP if the app is not locked.  If it is over the
1217                 // keyguard, then we will prompt to unlock in the caller before entering PiP.
1218                 return !isCurrentAppLocked &&
1219                         (supportsPictureInPictureWhilePausing || !beforeStopping);
1220             case PAUSING:
1221             case PAUSED:
1222                 // When pausing, then only allow enter PiP as in the resume state, and in addition,
1223                 // require that there is not an existing PiP activity and that the current system
1224                 // state supports entering PiP
1225                 return isNotLockedOrOnKeyguard && !hasPinnedStack
1226                         && supportsPictureInPictureWhilePausing;
1227             case STOPPING:
1228                 // When stopping in a valid state, then only allow enter PiP as in the pause state.
1229                 // Otherwise, fall through to throw an exception if the caller is trying to enter
1230                 // PiP in an invalid stopping state.
1231                 if (supportsPictureInPictureWhilePausing) {
1232                     return isNotLockedOrOnKeyguard && !hasPinnedStack;
1233                 }
1234             default:
1235                 if (noThrow) {
1236                     return false;
1237                 } else {
1238                     throw new IllegalStateException(caller
1239                             + ": Current activity is not visible (state=" + state.name() + ") "
1240                             + "r=" + this);
1241                 }
1242         }
1243     }
1244 
1245     /**
1246      * @return Whether AppOps allows this package to enter picture-in-picture.
1247      */
1248     private boolean checkEnterPictureInPictureAppOpsState() {
1249         try {
1250             return service.getAppOpsService().checkOperation(OP_PICTURE_IN_PICTURE,
1251                     appInfo.uid, packageName) == MODE_ALLOWED;
1252         } catch (RemoteException e) {
1253             // Local call
1254         }
1255         return false;
1256     }
1257 
1258     boolean isAlwaysFocusable() {
1259         return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
1260     }
1261 
1262     /**
1263      * @return true if the activity contains windows that have
1264      *         {@link LayoutParams#FLAG_SHOW_WHEN_LOCKED} set
1265      */
1266     boolean hasShowWhenLockedWindows() {
1267         return service.mWindowManager.containsShowWhenLockedWindow(appToken);
1268     }
1269 
1270     /**
1271      * @return true if the activity contains windows that have
1272      *         {@link LayoutParams#FLAG_DISMISS_KEYGUARD} set
1273      */
1274     boolean hasDismissKeyguardWindows() {
1275         return service.mWindowManager.containsDismissKeyguardWindow(appToken);
1276     }
1277 
1278     void makeFinishingLocked() {
1279         if (!finishing) {
1280             final ActivityStack stack = getStack();
1281             if (stack != null && this == stack.getVisibleBehindActivity()) {
1282                 // A finishing activity should not remain as visible in the background
1283                 mStackSupervisor.requestVisibleBehindLocked(this, false);
1284             }
1285             finishing = true;
1286             if (stopped) {
1287                 clearOptionsLocked();
1288             }
1289 
1290             if (service != null) {
1291                 service.mTaskChangeNotificationController.notifyTaskStackChanged();
1292             }
1293         }
1294     }
1295 
1296     UriPermissionOwner getUriPermissionsLocked() {
1297         if (uriPermissions == null) {
1298             uriPermissions = new UriPermissionOwner(service, this);
1299         }
1300         return uriPermissions;
1301     }
1302 
1303     void addResultLocked(ActivityRecord from, String resultWho,
1304             int requestCode, int resultCode,
1305             Intent resultData) {
1306         ActivityResult r = new ActivityResult(from, resultWho,
1307                 requestCode, resultCode, resultData);
1308         if (results == null) {
1309             results = new ArrayList<ResultInfo>();
1310         }
1311         results.add(r);
1312     }
1313 
1314     void removeResultsLocked(ActivityRecord from, String resultWho,
1315             int requestCode) {
1316         if (results != null) {
1317             for (int i=results.size()-1; i>=0; i--) {
1318                 ActivityResult r = (ActivityResult)results.get(i);
1319                 if (r.mFrom != from) continue;
1320                 if (r.mResultWho == null) {
1321                     if (resultWho != null) continue;
1322                 } else {
1323                     if (!r.mResultWho.equals(resultWho)) continue;
1324                 }
1325                 if (r.mRequestCode != requestCode) continue;
1326 
1327                 results.remove(i);
1328             }
1329         }
1330     }
1331 
addNewIntentLocked(ReferrerIntent intent)1332     private void addNewIntentLocked(ReferrerIntent intent) {
1333         if (newIntents == null) {
1334             newIntents = new ArrayList<>();
1335         }
1336         newIntents.add(intent);
1337     }
1338 
1339     /**
1340      * Deliver a new Intent to an existing activity, so that its onNewIntent()
1341      * method will be called at the proper time.
1342      */
deliverNewIntentLocked(int callingUid, Intent intent, String referrer)1343     final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
1344         // The activity now gets access to the data associated with this Intent.
1345         service.grantUriPermissionFromIntentLocked(callingUid, packageName,
1346                 intent, getUriPermissionsLocked(), userId);
1347         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
1348         boolean unsent = true;
1349         final ActivityStack stack = getStack();
1350         final boolean isTopActivityInStack =
1351                 stack != null && stack.topRunningActivityLocked() == this;
1352         final boolean isTopActivityWhileSleeping =
1353                 service.isSleepingLocked() && isTopActivityInStack;
1354 
1355         // We want to immediately deliver the intent to the activity if:
1356         // - It is currently resumed or paused. i.e. it is currently visible to the user and we want
1357         //   the user to see the visual effects caused by the intent delivery now.
1358         // - The device is sleeping and it is the top activity behind the lock screen (b/6700897).
1359         if ((state == RESUMED || state == PAUSED
1360                 || isTopActivityWhileSleeping) && app != null && app.thread != null) {
1361             try {
1362                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
1363                 ar.add(rintent);
1364                 app.thread.scheduleNewIntent(
1365                         ar, appToken, state == PAUSED /* andPause */);
1366                 unsent = false;
1367             } catch (RemoteException e) {
1368                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
1369             } catch (NullPointerException e) {
1370                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
1371             }
1372         }
1373         if (unsent) {
1374             addNewIntentLocked(rintent);
1375         }
1376     }
1377 
updateOptionsLocked(ActivityOptions options)1378     void updateOptionsLocked(ActivityOptions options) {
1379         if (options != null) {
1380             if (pendingOptions != null) {
1381                 pendingOptions.abort();
1382             }
1383             pendingOptions = options;
1384         }
1385     }
1386 
applyOptionsLocked()1387     void applyOptionsLocked() {
1388         if (pendingOptions != null
1389                 && pendingOptions.getAnimationType() != ANIM_SCENE_TRANSITION) {
1390             final int animationType = pendingOptions.getAnimationType();
1391             switch (animationType) {
1392                 case ANIM_CUSTOM:
1393                     service.mWindowManager.overridePendingAppTransition(
1394                             pendingOptions.getPackageName(),
1395                             pendingOptions.getCustomEnterResId(),
1396                             pendingOptions.getCustomExitResId(),
1397                             pendingOptions.getOnAnimationStartListener());
1398                     break;
1399                 case ANIM_CLIP_REVEAL:
1400                     service.mWindowManager.overridePendingAppTransitionClipReveal(
1401                             pendingOptions.getStartX(), pendingOptions.getStartY(),
1402                             pendingOptions.getWidth(), pendingOptions.getHeight());
1403                     if (intent.getSourceBounds() == null) {
1404                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1405                                 pendingOptions.getStartY(),
1406                                 pendingOptions.getStartX()+pendingOptions.getWidth(),
1407                                 pendingOptions.getStartY()+pendingOptions.getHeight()));
1408                     }
1409                     break;
1410                 case ANIM_SCALE_UP:
1411                     service.mWindowManager.overridePendingAppTransitionScaleUp(
1412                             pendingOptions.getStartX(), pendingOptions.getStartY(),
1413                             pendingOptions.getWidth(), pendingOptions.getHeight());
1414                     if (intent.getSourceBounds() == null) {
1415                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1416                                 pendingOptions.getStartY(),
1417                                 pendingOptions.getStartX()+pendingOptions.getWidth(),
1418                                 pendingOptions.getStartY()+pendingOptions.getHeight()));
1419                     }
1420                     break;
1421                 case ANIM_THUMBNAIL_SCALE_UP:
1422                 case ANIM_THUMBNAIL_SCALE_DOWN:
1423                     final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
1424                     final GraphicBuffer buffer = pendingOptions.getThumbnail();
1425                     service.mWindowManager.overridePendingAppTransitionThumb(buffer,
1426                             pendingOptions.getStartX(), pendingOptions.getStartY(),
1427                             pendingOptions.getOnAnimationStartListener(),
1428                             scaleUp);
1429                     if (intent.getSourceBounds() == null && buffer != null) {
1430                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1431                                 pendingOptions.getStartY(),
1432                                 pendingOptions.getStartX() + buffer.getWidth(),
1433                                 pendingOptions.getStartY() + buffer.getHeight()));
1434                     }
1435                     break;
1436                 case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
1437                 case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
1438                     final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
1439                     final IAppTransitionAnimationSpecsFuture specsFuture =
1440                             pendingOptions.getSpecsFuture();
1441                     if (specsFuture != null) {
1442                         service.mWindowManager.overridePendingAppTransitionMultiThumbFuture(
1443                                 specsFuture, pendingOptions.getOnAnimationStartListener(),
1444                                 animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP);
1445                     } else if (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
1446                             && specs != null) {
1447                         service.mWindowManager.overridePendingAppTransitionMultiThumb(
1448                                 specs, pendingOptions.getOnAnimationStartListener(),
1449                                 pendingOptions.getAnimationFinishedListener(), false);
1450                     } else {
1451                         service.mWindowManager.overridePendingAppTransitionAspectScaledThumb(
1452                                 pendingOptions.getThumbnail(),
1453                                 pendingOptions.getStartX(), pendingOptions.getStartY(),
1454                                 pendingOptions.getWidth(), pendingOptions.getHeight(),
1455                                 pendingOptions.getOnAnimationStartListener(),
1456                                 (animationType == ANIM_THUMBNAIL_ASPECT_SCALE_UP));
1457                         if (intent.getSourceBounds() == null) {
1458                             intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
1459                                     pendingOptions.getStartY(),
1460                                     pendingOptions.getStartX() + pendingOptions.getWidth(),
1461                                     pendingOptions.getStartY() + pendingOptions.getHeight()));
1462                         }
1463                     }
1464                     break;
1465                 default:
1466                     Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType);
1467                     break;
1468             }
1469             pendingOptions = null;
1470         }
1471     }
1472 
getOptionsForTargetActivityLocked()1473     ActivityOptions getOptionsForTargetActivityLocked() {
1474         return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
1475     }
1476 
clearOptionsLocked()1477     void clearOptionsLocked() {
1478         if (pendingOptions != null) {
1479             pendingOptions.abort();
1480             pendingOptions = null;
1481         }
1482     }
1483 
takeOptionsLocked()1484     ActivityOptions takeOptionsLocked() {
1485         ActivityOptions opts = pendingOptions;
1486         pendingOptions = null;
1487         return opts;
1488     }
1489 
removeUriPermissionsLocked()1490     void removeUriPermissionsLocked() {
1491         if (uriPermissions != null) {
1492             uriPermissions.removeUriPermissionsLocked();
1493             uriPermissions = null;
1494         }
1495     }
1496 
pauseKeyDispatchingLocked()1497     void pauseKeyDispatchingLocked() {
1498         if (!keysPaused) {
1499             keysPaused = true;
1500             mWindowContainerController.pauseKeyDispatching();
1501         }
1502     }
1503 
resumeKeyDispatchingLocked()1504     void resumeKeyDispatchingLocked() {
1505         if (keysPaused) {
1506             keysPaused = false;
1507             mWindowContainerController.resumeKeyDispatching();
1508         }
1509     }
1510 
updateThumbnailLocked(Bitmap newThumbnail, CharSequence description)1511     void updateThumbnailLocked(Bitmap newThumbnail, CharSequence description) {
1512         if (newThumbnail != null) {
1513             if (DEBUG_THUMBNAILS) Slog.i(TAG_THUMBNAILS,
1514                     "Setting thumbnail of " + this + " to " + newThumbnail);
1515             boolean thumbnailUpdated = task.setLastThumbnailLocked(newThumbnail);
1516             if (thumbnailUpdated && isPersistable()) {
1517                 service.notifyTaskPersisterLocked(task, false);
1518             }
1519         }
1520         task.lastDescription = description;
1521     }
1522 
screenshotActivityLocked()1523     final Bitmap screenshotActivityLocked() {
1524         if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "screenshotActivityLocked: " + this);
1525 
1526         if (ENABLE_TASK_SNAPSHOTS) {
1527             // No need to screenshot if snapshots are enabled.
1528             if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS,
1529                     "\tSnapshots are enabled, abort taking screenshot");
1530             return null;
1531         }
1532 
1533         if (noDisplay) {
1534             if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tNo display");
1535             return null;
1536         }
1537 
1538         final ActivityStack stack = getStack();
1539         if (stack.isHomeOrRecentsStack()) {
1540             // This is an optimization -- since we never show Home or Recents within Recents itself,
1541             // we can just go ahead and skip taking the screenshot if this is the home stack.
1542             if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, stack.getStackId() == HOME_STACK_ID ?
1543                         "\tHome stack" : "\tRecents stack");
1544             return null;
1545         }
1546 
1547         int w = service.mThumbnailWidth;
1548         int h = service.mThumbnailHeight;
1549 
1550         if (w <= 0) {
1551             Slog.e(TAG, "\tInvalid thumbnail dimensions: " + w + "x" + h);
1552             return null;
1553         }
1554 
1555         if (stack.mStackId == DOCKED_STACK_ID && mStackSupervisor.mIsDockMinimized) {
1556             // When the docked stack is minimized its app windows are cropped significantly so any
1557             // screenshot taken will not display the apps contain. So, we avoid taking a screenshot
1558             // in that case.
1559             if (DEBUG_SCREENSHOTS) Slog.e(TAG, "\tIn minimized docked stack");
1560             return null;
1561         }
1562 
1563         float scale = 0;
1564         if (DEBUG_SCREENSHOTS) Slog.d(TAG_SCREENSHOTS, "\tTaking screenshot");
1565 
1566         // When this flag is set, we currently take the fullscreen screenshot of the activity but
1567         // scaled to half the size. This gives us a "good-enough" fullscreen thumbnail to use within
1568         // SystemUI while keeping memory usage low.
1569         if (TAKE_FULLSCREEN_SCREENSHOTS) {
1570             w = h = -1;
1571             scale = service.mFullscreenThumbnailScale;
1572         }
1573 
1574         return mWindowContainerController.screenshotApplications(getDisplayId(), w, h, scale);
1575     }
1576 
setDeferHidingClient(boolean deferHidingClient)1577     void setDeferHidingClient(boolean deferHidingClient) {
1578         if (mDeferHidingClient == deferHidingClient) {
1579             return;
1580         }
1581         mDeferHidingClient = deferHidingClient;
1582         if (!mDeferHidingClient && !visible) {
1583             // Hiding the client is no longer deferred and the app isn't visible still, go ahead and
1584             // update the visibility.
1585             setVisibility(false);
1586         }
1587     }
1588 
setVisibility(boolean visible)1589     void setVisibility(boolean visible) {
1590         mWindowContainerController.setVisibility(visible, mDeferHidingClient);
1591         mStackSupervisor.mActivityMetricsLogger.notifyVisibilityChanged(this, visible);
1592     }
1593 
1594     // TODO: Look into merging with #setVisibility()
setVisible(boolean newVisible)1595     void setVisible(boolean newVisible) {
1596         visible = newVisible;
1597         mDeferHidingClient = !visible && mDeferHidingClient;
1598         if (!visible && mUpdateTaskThumbnailWhenHidden) {
1599             updateThumbnailLocked(screenshotActivityLocked(), null /* description */);
1600             mUpdateTaskThumbnailWhenHidden = false;
1601         }
1602         setVisibility(visible);
1603         final ArrayList<ActivityContainer> containers = mChildContainers;
1604         for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) {
1605             final ActivityContainer container = containers.get(containerNdx);
1606             container.setVisible(visible);
1607         }
1608         mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
1609     }
1610 
notifyAppResumed(boolean wasStopped)1611     void notifyAppResumed(boolean wasStopped) {
1612         mWindowContainerController.notifyAppResumed(wasStopped);
1613     }
1614 
notifyUnknownVisibilityLaunched()1615     void notifyUnknownVisibilityLaunched() {
1616         mWindowContainerController.notifyUnknownVisibilityLaunched();
1617     }
1618 
1619     /**
1620      * @return true if the input activity should be made visible, ignoring any effect Keyguard
1621      * might have on the visibility
1622      *
1623      * @see {@link ActivityStack#checkKeyguardVisibility}
1624      */
shouldBeVisibleIgnoringKeyguard(boolean behindTranslucentActivity, boolean stackVisibleBehind, ActivityRecord visibleBehind, boolean behindFullscreenActivity)1625     boolean shouldBeVisibleIgnoringKeyguard(boolean behindTranslucentActivity,
1626             boolean stackVisibleBehind, ActivityRecord visibleBehind,
1627             boolean behindFullscreenActivity) {
1628         if (!okToShowLocked()) {
1629             return false;
1630         }
1631 
1632         // mLaunchingBehind: Activities launching behind are at the back of the task stack
1633         // but must be drawn initially for the animation as though they were visible.
1634         final boolean activityVisibleBehind =
1635                 (behindTranslucentActivity || stackVisibleBehind) && visibleBehind == this;
1636 
1637         boolean isVisible =
1638                 !behindFullscreenActivity || mLaunchTaskBehind || activityVisibleBehind;
1639 
1640         if (service.mSupportsLeanbackOnly && isVisible && isRecentsActivity()) {
1641             // On devices that support leanback only (Android TV), Recents activity can only be
1642             // visible if the home stack is the focused stack or we are in split-screen mode.
1643             isVisible = mStackSupervisor.getStack(DOCKED_STACK_ID) != null
1644                     || mStackSupervisor.isFocusedStack(getStack());
1645         }
1646 
1647         return isVisible;
1648     }
1649 
makeVisibleIfNeeded(ActivityRecord starting)1650     void makeVisibleIfNeeded(ActivityRecord starting) {
1651         // This activity is not currently visible, but is running. Tell it to become visible.
1652         if (state == RESUMED || this == starting) {
1653             if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY,
1654                     "Not making visible, r=" + this + " state=" + state + " starting=" + starting);
1655             return;
1656         }
1657 
1658         // If this activity is paused, tell it to now show its window.
1659         if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY,
1660                 "Making visible and scheduling visibility: " + this);
1661         final ActivityStack stack = getStack();
1662         try {
1663             if (stack.mTranslucentActivityWaiting != null) {
1664                 updateOptionsLocked(returningOptions);
1665                 stack.mUndrawnActivitiesBelowTopTranslucent.add(this);
1666             }
1667             setVisible(true);
1668             sleeping = false;
1669             app.pendingUiClean = true;
1670             app.thread.scheduleWindowVisibility(appToken, true /* showWindow */);
1671             // The activity may be waiting for stop, but that is no longer appropriate for it.
1672             mStackSupervisor.mStoppingActivities.remove(this);
1673             mStackSupervisor.mGoingToSleepActivities.remove(this);
1674         } catch (Exception e) {
1675             // Just skip on any failure; we'll make it visible when it next restarts.
1676             Slog.w(TAG, "Exception thrown making visibile: " + intent.getComponent(), e);
1677         }
1678         handleAlreadyVisible();
1679     }
1680 
handleAlreadyVisible()1681     boolean handleAlreadyVisible() {
1682         stopFreezingScreenLocked(false);
1683         try {
1684             if (returningOptions != null) {
1685                 app.thread.scheduleOnNewActivityOptions(appToken, returningOptions.toBundle());
1686             }
1687         } catch(RemoteException e) {
1688         }
1689         return state == RESUMED;
1690     }
1691 
activityResumedLocked(IBinder token)1692     static void activityResumedLocked(IBinder token) {
1693         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1694         if (DEBUG_SAVED_STATE) Slog.i(TAG_STATES, "Resumed activity; dropping state of: " + r);
1695         if (r != null) {
1696             r.icicle = null;
1697             r.haveState = false;
1698         }
1699     }
1700 
1701     /**
1702      * Once we know that we have asked an application to put an activity in the resumed state
1703      * (either by launching it or explicitly telling it), this function updates the rest of our
1704      * state to match that fact.
1705      */
completeResumeLocked()1706     void completeResumeLocked() {
1707         final boolean wasVisible = visible;
1708         visible = true;
1709         if (!wasVisible) {
1710             // Visibility has changed, so take a note of it so we call the TaskStackChangedListener
1711             mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = true;
1712         }
1713         idle = false;
1714         results = null;
1715         newIntents = null;
1716         stopped = false;
1717 
1718         if (isHomeActivity()) {
1719             ProcessRecord app = task.mActivities.get(0).app;
1720             if (app != null && app != service.mHomeProcess) {
1721                 service.mHomeProcess = app;
1722             }
1723         }
1724 
1725         if (nowVisible) {
1726             // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now.
1727             mStackSupervisor.reportActivityVisibleLocked(this);
1728         }
1729 
1730         // Schedule an idle timeout in case the app doesn't do it for us.
1731         mStackSupervisor.scheduleIdleTimeoutLocked(this);
1732 
1733         mStackSupervisor.reportResumedActivityLocked(this);
1734 
1735         resumeKeyDispatchingLocked();
1736         final ActivityStack stack = getStack();
1737         stack.mNoAnimActivities.clear();
1738 
1739         // Mark the point when the activity is resuming
1740         // TODO: To be more accurate, the mark should be before the onCreate,
1741         //       not after the onResume. But for subsequent starts, onResume is fine.
1742         if (app != null) {
1743             cpuTimeAtResume = service.mProcessCpuTracker.getCpuTimeForPid(app.pid);
1744         } else {
1745             cpuTimeAtResume = 0; // Couldn't get the cpu time of process
1746         }
1747 
1748         returningOptions = null;
1749 
1750         if (stack.getVisibleBehindActivity() == this) {
1751             // When resuming an activity, require it to call requestVisibleBehind() again.
1752             stack.setVisibleBehindActivity(null /* ActivityRecord */);
1753         }
1754         mStackSupervisor.checkReadyForSleepLocked();
1755     }
1756 
activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState, CharSequence description)1757     final void activityStoppedLocked(Bundle newIcicle, PersistableBundle newPersistentState,
1758             CharSequence description) {
1759         final ActivityStack stack = getStack();
1760         if (state != STOPPING) {
1761             Slog.i(TAG, "Activity reported stop, but no longer stopping: " + this);
1762             stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
1763             return;
1764         }
1765         if (newPersistentState != null) {
1766             persistentState = newPersistentState;
1767             service.notifyTaskPersisterLocked(task, false);
1768         }
1769         if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, "Saving icicle of " + this + ": " + icicle);
1770 
1771         if (newIcicle != null) {
1772             // If icicle is null, this is happening due to a timeout, so we haven't really saved
1773             // the state.
1774             icicle = newIcicle;
1775             haveState = true;
1776             launchCount = 0;
1777             updateThumbnailLocked(null /* newThumbnail */, description);
1778         }
1779         if (!stopped) {
1780             if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPED: " + this + " (stop complete)");
1781             stack.mHandler.removeMessages(STOP_TIMEOUT_MSG, this);
1782             stopped = true;
1783             state = STOPPED;
1784 
1785             mWindowContainerController.notifyAppStopped();
1786 
1787             if (stack.getVisibleBehindActivity() == this) {
1788                 mStackSupervisor.requestVisibleBehindLocked(this, false /* visible */);
1789             }
1790             if (finishing) {
1791                 clearOptionsLocked();
1792             } else {
1793                 if (deferRelaunchUntilPaused) {
1794                     stack.destroyActivityLocked(this, true /* removeFromApp */, "stop-config");
1795                     mStackSupervisor.resumeFocusedStackTopActivityLocked();
1796                 } else {
1797                     mStackSupervisor.updatePreviousProcessLocked(this);
1798                 }
1799             }
1800         }
1801     }
1802 
startLaunchTickingLocked()1803     void startLaunchTickingLocked() {
1804         if (IS_USER_BUILD) {
1805             return;
1806         }
1807         if (launchTickTime == 0) {
1808             launchTickTime = SystemClock.uptimeMillis();
1809             continueLaunchTickingLocked();
1810         }
1811     }
1812 
continueLaunchTickingLocked()1813     boolean continueLaunchTickingLocked() {
1814         if (launchTickTime == 0) {
1815             return false;
1816         }
1817 
1818         final ActivityStack stack = getStack();
1819         if (stack == null) {
1820             return false;
1821         }
1822 
1823         Message msg = stack.mHandler.obtainMessage(LAUNCH_TICK_MSG, this);
1824         stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
1825         stack.mHandler.sendMessageDelayed(msg, LAUNCH_TICK);
1826         return true;
1827     }
1828 
finishLaunchTickingLocked()1829     void finishLaunchTickingLocked() {
1830         launchTickTime = 0;
1831         final ActivityStack stack = getStack();
1832         if (stack != null) {
1833             stack.mHandler.removeMessages(LAUNCH_TICK_MSG);
1834         }
1835     }
1836 
1837     // IApplicationToken
1838 
mayFreezeScreenLocked(ProcessRecord app)1839     public boolean mayFreezeScreenLocked(ProcessRecord app) {
1840         // Only freeze the screen if this activity is currently attached to
1841         // an application, and that application is not blocked or unresponding.
1842         // In any other case, we can't count on getting the screen unfrozen,
1843         // so it is best to leave as-is.
1844         return app != null && !app.crashing && !app.notResponding;
1845     }
1846 
startFreezingScreenLocked(ProcessRecord app, int configChanges)1847     public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
1848         if (mayFreezeScreenLocked(app)) {
1849             mWindowContainerController.startFreezingScreen(configChanges);
1850         }
1851     }
1852 
stopFreezingScreenLocked(boolean force)1853     public void stopFreezingScreenLocked(boolean force) {
1854         if (force || frozenBeforeDestroy) {
1855             frozenBeforeDestroy = false;
1856             mWindowContainerController.stopFreezingScreen(force);
1857         }
1858     }
1859 
reportFullyDrawnLocked()1860     public void reportFullyDrawnLocked() {
1861         final long curTime = SystemClock.uptimeMillis();
1862         if (displayStartTime != 0) {
1863             reportLaunchTimeLocked(curTime);
1864         }
1865         final ActivityStack stack = getStack();
1866         if (fullyDrawnStartTime != 0 && stack != null) {
1867             final long thisTime = curTime - fullyDrawnStartTime;
1868             final long totalTime = stack.mFullyDrawnStartTime != 0
1869                     ? (curTime - stack.mFullyDrawnStartTime) : thisTime;
1870             if (SHOW_ACTIVITY_START_TIME) {
1871                 Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
1872                 EventLog.writeEvent(AM_ACTIVITY_FULLY_DRAWN_TIME,
1873                         userId, System.identityHashCode(this), shortComponentName,
1874                         thisTime, totalTime);
1875                 StringBuilder sb = service.mStringBuilder;
1876                 sb.setLength(0);
1877                 sb.append("Fully drawn ");
1878                 sb.append(shortComponentName);
1879                 sb.append(": ");
1880                 TimeUtils.formatDuration(thisTime, sb);
1881                 if (thisTime != totalTime) {
1882                     sb.append(" (total ");
1883                     TimeUtils.formatDuration(totalTime, sb);
1884                     sb.append(")");
1885                 }
1886                 Log.i(TAG, sb.toString());
1887             }
1888             if (totalTime > 0) {
1889                 //service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime);
1890             }
1891             stack.mFullyDrawnStartTime = 0;
1892         }
1893         fullyDrawnStartTime = 0;
1894     }
1895 
reportLaunchTimeLocked(final long curTime)1896     private void reportLaunchTimeLocked(final long curTime) {
1897         final ActivityStack stack = getStack();
1898         if (stack == null) {
1899             return;
1900         }
1901         final long thisTime = curTime - displayStartTime;
1902         final long totalTime = stack.mLaunchStartTime != 0
1903                 ? (curTime - stack.mLaunchStartTime) : thisTime;
1904         if (SHOW_ACTIVITY_START_TIME) {
1905             Trace.asyncTraceEnd(TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
1906             EventLog.writeEvent(AM_ACTIVITY_LAUNCH_TIME,
1907                     userId, System.identityHashCode(this), shortComponentName,
1908                     thisTime, totalTime);
1909             StringBuilder sb = service.mStringBuilder;
1910             sb.setLength(0);
1911             sb.append("Displayed ");
1912             sb.append(shortComponentName);
1913             sb.append(": ");
1914             TimeUtils.formatDuration(thisTime, sb);
1915             if (thisTime != totalTime) {
1916                 sb.append(" (total ");
1917                 TimeUtils.formatDuration(totalTime, sb);
1918                 sb.append(")");
1919             }
1920             Log.i(TAG, sb.toString());
1921         }
1922         mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
1923         if (totalTime > 0) {
1924             //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
1925         }
1926         displayStartTime = 0;
1927         stack.mLaunchStartTime = 0;
1928     }
1929 
1930     @Override
onStartingWindowDrawn(long timestamp)1931     public void onStartingWindowDrawn(long timestamp) {
1932         synchronized (service) {
1933             mStackSupervisor.mActivityMetricsLogger.notifyStartingWindowDrawn(
1934                     getStackId(), timestamp);
1935         }
1936     }
1937 
1938     @Override
onWindowsDrawn(long timestamp)1939     public void onWindowsDrawn(long timestamp) {
1940         synchronized (service) {
1941             mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn(getStackId(), timestamp);
1942             if (displayStartTime != 0) {
1943                 reportLaunchTimeLocked(timestamp);
1944             }
1945             mStackSupervisor.sendWaitingVisibleReportLocked(this);
1946             startTime = 0;
1947             finishLaunchTickingLocked();
1948             if (task != null) {
1949                 task.hasBeenVisible = true;
1950             }
1951         }
1952     }
1953 
1954     @Override
onWindowsVisible()1955     public void onWindowsVisible() {
1956         synchronized (service) {
1957             mStackSupervisor.reportActivityVisibleLocked(this);
1958             if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
1959             if (!nowVisible) {
1960                 nowVisible = true;
1961                 lastVisibleTime = SystemClock.uptimeMillis();
1962                 if (idle || mStackSupervisor.isStoppingNoHistoryActivity()) {
1963                     // If this activity was already idle or there is an activity that must be
1964                     // stopped immediately after visible, then we now need to make sure we perform
1965                     // the full stop of any activities that are waiting to do so. This is because
1966                     // we won't do that while they are still waiting for this one to become visible.
1967                     final int size = mStackSupervisor.mActivitiesWaitingForVisibleActivity.size();
1968                     if (size > 0) {
1969                         for (int i = 0; i < size; i++) {
1970                             final ActivityRecord r =
1971                                     mStackSupervisor.mActivitiesWaitingForVisibleActivity.get(i);
1972                             if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r);
1973                         }
1974                         mStackSupervisor.mActivitiesWaitingForVisibleActivity.clear();
1975                         mStackSupervisor.scheduleIdleLocked();
1976                     }
1977                 } else {
1978                     // Instead of doing the full stop routine here, let's just hide any activities
1979                     // we now can, and let them stop when the normal idle happens.
1980                     mStackSupervisor.processStoppingActivitiesLocked(null /* idleActivity */,
1981                             false /* remove */, true /* processPausingActivities */);
1982                 }
1983                 service.scheduleAppGcsLocked();
1984             }
1985         }
1986     }
1987 
1988     @Override
onWindowsGone()1989     public void onWindowsGone() {
1990         synchronized (service) {
1991             if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + this);
1992             nowVisible = false;
1993         }
1994     }
1995 
1996     @Override
keyDispatchingTimedOut(String reason, int windowPid)1997     public boolean keyDispatchingTimedOut(String reason, int windowPid) {
1998         ActivityRecord anrActivity;
1999         ProcessRecord anrApp;
2000         boolean windowFromSameProcessAsActivity;
2001         synchronized (service) {
2002             anrActivity = getWaitingHistoryRecordLocked();
2003             anrApp = app;
2004             windowFromSameProcessAsActivity =
2005                     app == null || app.pid == windowPid || windowPid == -1;
2006         }
2007         if (windowFromSameProcessAsActivity) {
2008             return service.inputDispatchingTimedOut(anrApp, anrActivity, this, false, reason);
2009         } else {
2010             // In this case another process added windows using this activity token. So, we call the
2011             // generic service input dispatch timed out method so that the right process is blamed.
2012             return service.inputDispatchingTimedOut(windowPid, false /* aboveSystem */, reason) < 0;
2013         }
2014     }
2015 
getWaitingHistoryRecordLocked()2016     private ActivityRecord getWaitingHistoryRecordLocked() {
2017         // First find the real culprit...  if this activity is waiting for
2018         // another activity to start or has stopped, then the key dispatching
2019         // timeout should not be caused by this.
2020         if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.contains(this) || stopped) {
2021             final ActivityStack stack = mStackSupervisor.getFocusedStack();
2022             // Try to use the one which is closest to top.
2023             ActivityRecord r = stack.mResumedActivity;
2024             if (r == null) {
2025                 r = stack.mPausingActivity;
2026             }
2027             if (r != null) {
2028                 return r;
2029             }
2030         }
2031         return this;
2032     }
2033 
2034     /** Checks whether the activity should be shown for current user. */
okToShowLocked()2035     public boolean okToShowLocked() {
2036         return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0
2037                 || (mStackSupervisor.isCurrentProfileLocked(userId)
2038                 && !service.mUserController.isUserStoppingOrShuttingDownLocked(userId));
2039     }
2040 
2041     /**
2042      * This method will return true if the activity is either visible, is becoming visible, is
2043      * currently pausing, or is resumed.
2044      */
isInterestingToUserLocked()2045     public boolean isInterestingToUserLocked() {
2046         return visible || nowVisible || state == PAUSING ||
2047                 state == RESUMED;
2048     }
2049 
setSleeping(boolean _sleeping)2050     void setSleeping(boolean _sleeping) {
2051         setSleeping(_sleeping, false);
2052     }
2053 
setSleeping(boolean _sleeping, boolean force)2054     void setSleeping(boolean _sleeping, boolean force) {
2055         if (!force && sleeping == _sleeping) {
2056             return;
2057         }
2058         if (app != null && app.thread != null) {
2059             try {
2060                 app.thread.scheduleSleeping(appToken, _sleeping);
2061                 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
2062                     mStackSupervisor.mGoingToSleepActivities.add(this);
2063                 }
2064                 sleeping = _sleeping;
2065             } catch (RemoteException e) {
2066                 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
2067             }
2068         }
2069     }
2070 
getTaskForActivityLocked(IBinder token, boolean onlyRoot)2071     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
2072         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2073         if (r == null) {
2074             return INVALID_TASK_ID;
2075         }
2076         final TaskRecord task = r.task;
2077         final int activityNdx = task.mActivities.indexOf(r);
2078         if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) {
2079             return INVALID_TASK_ID;
2080         }
2081         return task.taskId;
2082     }
2083 
isInStackLocked(IBinder token)2084     static ActivityRecord isInStackLocked(IBinder token) {
2085         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2086         return (r != null) ? r.getStack().isInStackLocked(r) : null;
2087     }
2088 
getStackLocked(IBinder token)2089     static ActivityStack getStackLocked(IBinder token) {
2090         final ActivityRecord r = ActivityRecord.isInStackLocked(token);
2091         if (r != null) {
2092             return r.getStack();
2093         }
2094         return null;
2095     }
2096 
2097     /**
2098      * @return display id to which this record is attached, -1 if not attached.
2099      */
getDisplayId()2100     int getDisplayId() {
2101         final ActivityStack stack = getStack();
2102         if (stack == null) {
2103             return -1;
2104         }
2105         return stack.mDisplayId;
2106     }
2107 
isDestroyable()2108     final boolean isDestroyable() {
2109         if (finishing || app == null || state == DESTROYING
2110                 || state == DESTROYED) {
2111             // This would be redundant.
2112             return false;
2113         }
2114         final ActivityStack stack = getStack();
2115         if (stack == null || this == stack.mResumedActivity || this == stack.mPausingActivity
2116                 || !haveState || !stopped) {
2117             // We're not ready for this kind of thing.
2118             return false;
2119         }
2120         if (visible) {
2121             // The user would notice this!
2122             return false;
2123         }
2124         return true;
2125     }
2126 
createImageFilename(long createTime, int taskId)2127     private static String createImageFilename(long createTime, int taskId) {
2128         return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
2129                 IMAGE_EXTENSION;
2130     }
2131 
setTaskDescription(TaskDescription _taskDescription)2132     void setTaskDescription(TaskDescription _taskDescription) {
2133         Bitmap icon;
2134         if (_taskDescription.getIconFilename() == null &&
2135                 (icon = _taskDescription.getIcon()) != null) {
2136             final String iconFilename = createImageFilename(createTime, task.taskId);
2137             final File iconFile = new File(TaskPersister.getUserImagesDir(task.userId),
2138                     iconFilename);
2139             final String iconFilePath = iconFile.getAbsolutePath();
2140             service.mRecentTasks.saveImage(icon, iconFilePath);
2141             _taskDescription.setIconFilename(iconFilePath);
2142         }
2143         taskDescription = _taskDescription;
2144     }
2145 
setVoiceSessionLocked(IVoiceInteractionSession session)2146     void setVoiceSessionLocked(IVoiceInteractionSession session) {
2147         voiceSession = session;
2148         pendingVoiceInteractionStart = false;
2149     }
2150 
clearVoiceSessionLocked()2151     void clearVoiceSessionLocked() {
2152         voiceSession = null;
2153         pendingVoiceInteractionStart = false;
2154     }
2155 
showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch)2156     void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch) {
2157         showStartingWindow(prev, newTask, taskSwitch, false /* fromRecents */);
2158     }
2159 
showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch, boolean fromRecents)2160     void showStartingWindow(ActivityRecord prev, boolean newTask, boolean taskSwitch,
2161             boolean fromRecents) {
2162         if (mWindowContainerController == null) {
2163             return;
2164         }
2165         if (mTaskOverlay) {
2166             // We don't show starting window for overlay activities.
2167             return;
2168         }
2169 
2170         final CompatibilityInfo compatInfo =
2171                 service.compatibilityInfoForPackageLocked(info.applicationInfo);
2172         final boolean shown = mWindowContainerController.addStartingWindow(packageName, theme,
2173                 compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
2174                 prev != null ? prev.appToken : null, newTask, taskSwitch, isProcessRunning(),
2175                 allowTaskSnapshot(),
2176                 state.ordinal() >= RESUMED.ordinal() && state.ordinal() <= STOPPED.ordinal(),
2177                 fromRecents);
2178         if (shown) {
2179             mStartingWindowState = STARTING_WINDOW_SHOWN;
2180         }
2181     }
2182 
removeOrphanedStartingWindow(boolean behindFullscreenActivity)2183     void removeOrphanedStartingWindow(boolean behindFullscreenActivity) {
2184         if (mStartingWindowState == STARTING_WINDOW_SHOWN && behindFullscreenActivity) {
2185             if (DEBUG_VISIBILITY) Slog.w(TAG_VISIBILITY, "Found orphaned starting window " + this);
2186             mStartingWindowState = STARTING_WINDOW_REMOVED;
2187             mWindowContainerController.removeStartingWindow();
2188         }
2189     }
2190 
getRequestedOrientation()2191     int getRequestedOrientation() {
2192         return mWindowContainerController.getOrientation();
2193     }
2194 
setRequestedOrientation(int requestedOrientation)2195     void setRequestedOrientation(int requestedOrientation) {
2196         if (ActivityInfo.isFixedOrientation(requestedOrientation) && !fullscreen
2197                 && appInfo.targetSdkVersion > O) {
2198             throw new IllegalStateException("Only fullscreen activities can request orientation");
2199         }
2200 
2201         final int displayId = getDisplayId();
2202         final Configuration displayConfig =
2203                 mStackSupervisor.getDisplayOverrideConfiguration(displayId);
2204 
2205         final Configuration config = mWindowContainerController.setOrientation(requestedOrientation,
2206                 displayId, displayConfig, mayFreezeScreenLocked(app));
2207         if (config != null) {
2208             frozenBeforeDestroy = true;
2209             if (!service.updateDisplayOverrideConfigurationLocked(config, this,
2210                     false /* deferResume */, displayId)) {
2211                 mStackSupervisor.resumeFocusedStackTopActivityLocked();
2212             }
2213         }
2214         service.mTaskChangeNotificationController.notifyActivityRequestedOrientationChanged(
2215                 task.taskId, requestedOrientation);
2216     }
2217 
setDisablePreviewScreenshots(boolean disable)2218     void setDisablePreviewScreenshots(boolean disable) {
2219         mWindowContainerController.setDisablePreviewScreenshots(disable);
2220     }
2221 
2222     /**
2223      * Set the last reported global configuration to the client. Should be called whenever a new
2224      * global configuration is sent to the client for this activity.
2225      */
setLastReportedGlobalConfiguration(@onNull Configuration config)2226     void setLastReportedGlobalConfiguration(@NonNull Configuration config) {
2227         mLastReportedConfiguration.setGlobalConfiguration(config);
2228     }
2229 
2230     /**
2231      * Set the last reported configuration to the client. Should be called whenever
2232      * a new merged configuration is sent to the client for this activity.
2233      */
setLastReportedConfiguration(@onNull MergedConfiguration config)2234     void setLastReportedConfiguration(@NonNull MergedConfiguration config) {
2235         mLastReportedConfiguration.setTo(config);
2236     }
2237 
2238     /** Call when override config was sent to the Window Manager to update internal records. */
2239     // TODO(b/36505427): Why do we set last reported based on sending the config to WM? Seems like
2240     // we should only set this when we actually report to the activity which is what the method
2241     // setLastReportedMergedOverrideConfiguration() does. Investigate if this is really needed.
onOverrideConfigurationSent()2242     void onOverrideConfigurationSent() {
2243         mLastReportedConfiguration.setOverrideConfiguration(getMergedOverrideConfiguration());
2244     }
2245 
2246     @Override
onOverrideConfigurationChanged(Configuration newConfig)2247     void onOverrideConfigurationChanged(Configuration newConfig) {
2248         final Configuration currentConfig = getOverrideConfiguration();
2249         if (currentConfig.equals(newConfig)) {
2250             return;
2251         }
2252         super.onOverrideConfigurationChanged(newConfig);
2253         if (mWindowContainerController == null) {
2254             return;
2255         }
2256         mWindowContainerController.onOverrideConfigurationChanged(newConfig, mBounds);
2257         // TODO(b/36505427): Can we consolidate the call points of onOverrideConfigurationSent()
2258         // to just use this method instead?
2259         onOverrideConfigurationSent();
2260     }
2261 
2262     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
updateOverrideConfiguration()2263     private void updateOverrideConfiguration() {
2264         mTmpConfig.unset();
2265         computeBounds(mTmpBounds);
2266         if (mTmpBounds.equals(mBounds)) {
2267             final ActivityStack stack = getStack();
2268             if (!mBounds.isEmpty() || task == null || stack == null || !task.mFullscreen) {
2269                 // We don't want to influence the override configuration here if our task is in
2270                 // multi-window mode or there is a bounds specified to calculate the override
2271                 // config. In both of this cases the app should be compatible with whatever the
2272                 // current configuration is or will be.
2273                 return;
2274             }
2275 
2276             // Currently limited to the top activity for now to avoid situations where non-top
2277             // visible activity and top might have conflicting requests putting the non-top activity
2278             // windows in an odd state.
2279             final ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
2280             final Configuration parentConfig = getParent().getConfiguration();
2281             if (top != this || isConfigurationCompatible(parentConfig)) {
2282                 onOverrideConfigurationChanged(mTmpConfig);
2283             } else if (isConfigurationCompatible(
2284                     mLastReportedConfiguration.getMergedConfiguration())) {
2285                 onOverrideConfigurationChanged(mLastReportedConfiguration.getMergedConfiguration());
2286             }
2287             return;
2288         }
2289 
2290         mBounds.set(mTmpBounds);
2291         // Bounds changed...update configuration to match.
2292         if (!mBounds.isEmpty()) {
2293             task.computeOverrideConfiguration(mTmpConfig, mBounds, null /* insetBounds */,
2294                     false /* overrideWidth */, false /* overrideHeight */);
2295         }
2296         onOverrideConfigurationChanged(mTmpConfig);
2297     }
2298 
2299     /** Returns true if the configuration is compatible with this activity. */
isConfigurationCompatible(Configuration config)2300     boolean isConfigurationCompatible(Configuration config) {
2301         final int orientation = mWindowContainerController != null
2302                 ? mWindowContainerController.getOrientation() : info.screenOrientation;
2303         if (isFixedOrientationPortrait(orientation)
2304                 && config.orientation != ORIENTATION_PORTRAIT) {
2305             return false;
2306         }
2307         if (isFixedOrientationLandscape(orientation)
2308                 && config.orientation != ORIENTATION_LANDSCAPE) {
2309             return false;
2310         }
2311         return true;
2312     }
2313 
2314     /**
2315      * Computes the bounds to fit the Activity within the bounds of the {@link Configuration}.
2316      */
2317     // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
computeBounds(Rect outBounds)2318     private void computeBounds(Rect outBounds) {
2319         outBounds.setEmpty();
2320         final float maxAspectRatio = info.maxAspectRatio;
2321         final ActivityStack stack = getStack();
2322         if (task == null || stack == null || !task.mFullscreen || maxAspectRatio == 0) {
2323             // We don't set override configuration if that activity task isn't fullscreen. I.e. the
2324             // activity is in multi-window mode. Or, there isn't a max aspect ratio specified for
2325             // the activity. This is indicated by an empty {@link outBounds}.
2326             return;
2327         }
2328 
2329         // We must base this on the parent configuration, because we set our override
2330         // configuration's appBounds based on the result of this method. If we used our own
2331         // configuration, it would be influenced by past invocations.
2332         final Configuration configuration = getParent().getConfiguration();
2333         final int containingAppWidth = configuration.appBounds.width();
2334         final int containingAppHeight = configuration.appBounds.height();
2335         int maxActivityWidth = containingAppWidth;
2336         int maxActivityHeight = containingAppHeight;
2337 
2338         if (containingAppWidth < containingAppHeight) {
2339             // Width is the shorter side, so we use that to figure-out what the max. height
2340             // should be given the aspect ratio.
2341             maxActivityHeight = (int) ((maxActivityWidth * maxAspectRatio) + 0.5f);
2342         } else {
2343             // Height is the shorter side, so we use that to figure-out what the max. width
2344             // should be given the aspect ratio.
2345             maxActivityWidth = (int) ((maxActivityHeight * maxAspectRatio) + 0.5f);
2346         }
2347 
2348         if (containingAppWidth <= maxActivityWidth && containingAppHeight <= maxActivityHeight) {
2349             // The display matches or is less than the activity aspect ratio, so nothing else to do.
2350             // Return the existing bounds. If this method is running for the first time,
2351             // {@link mBounds} will be empty (representing no override). If the method has run
2352             // before, then effect of {@link mBounds} will already have been applied to the
2353             // value returned from {@link getConfiguration}. Refer to
2354             // {@link TaskRecord#computeOverrideConfiguration}.
2355             outBounds.set(mBounds);
2356             return;
2357         }
2358 
2359         // Compute configuration based on max supported width and height.
2360         outBounds.set(0, 0, maxActivityWidth, maxActivityHeight);
2361     }
2362 
2363     /**
2364      * Make sure the given activity matches the current configuration. Returns false if the activity
2365      * had to be destroyed.  Returns true if the configuration is the same, or the activity will
2366      * remain running as-is for whatever reason. Ensures the HistoryRecord is updated with the
2367      * correct configuration and all other bookkeeping is handled.
2368      */
ensureActivityConfigurationLocked(int globalChanges, boolean preserveWindow)2369     boolean ensureActivityConfigurationLocked(int globalChanges, boolean preserveWindow) {
2370         final ActivityStack stack = getStack();
2371         if (stack.mConfigWillChange) {
2372             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2373                     "Skipping config check (will change): " + this);
2374             return true;
2375         }
2376 
2377         // We don't worry about activities that are finishing.
2378         if (finishing) {
2379             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2380                     "Configuration doesn't matter in finishing " + this);
2381             stopFreezingScreenLocked(false);
2382             return true;
2383         }
2384 
2385         // Skip updating configuration for activity that are stopping or stopped.
2386         if (state == STOPPING || state == STOPPED) {
2387             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2388                     "Skipping config check stopped or stopping: " + this);
2389             return true;
2390         }
2391 
2392         // TODO: We should add ActivityRecord.shouldBeVisible() that checks if the activity should
2393         // be visible based on the stack, task, and lockscreen state and use that here instead. The
2394         // method should be based on the logic in ActivityStack.ensureActivitiesVisibleLocked().
2395         // Skip updating configuration for activity is a stack that shouldn't be visible.
2396         if (stack.shouldBeVisible(null /* starting */) == STACK_INVISIBLE) {
2397             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2398                     "Skipping config check invisible stack: " + this);
2399             return true;
2400         }
2401 
2402         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2403                 "Ensuring correct configuration: " + this);
2404 
2405         final int newDisplayId = getDisplayId();
2406         final boolean displayChanged = mLastReportedDisplayId != newDisplayId;
2407         if (displayChanged) {
2408             mLastReportedDisplayId = newDisplayId;
2409         }
2410         // TODO(b/36505427): Is there a better place to do this?
2411         updateOverrideConfiguration();
2412 
2413         // Short circuit: if the two full configurations are equal (the common case), then there is
2414         // nothing to do.  We test the full configuration instead of the global and merged override
2415         // configurations because there are cases (like moving a task to the pinned stack) where
2416         // the combine configurations are equal, but would otherwise differ in the override config
2417         mTmpConfig.setTo(mLastReportedConfiguration.getMergedConfiguration());
2418         if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) {
2419             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2420                     "Configuration & display unchanged in " + this);
2421             return true;
2422         }
2423 
2424         // Okay we now are going to make this activity have the new config.
2425         // But then we need to figure out how it needs to deal with that.
2426 
2427         // Find changes between last reported merged configuration and the current one. This is used
2428         // to decide whether to relaunch an activity or just report a configuration change.
2429         final int changes = getConfigurationChanges(mTmpConfig);
2430 
2431         // Update last reported values.
2432         final Configuration newMergedOverrideConfig = getMergedOverrideConfiguration();
2433         mLastReportedConfiguration.setConfiguration(service.getGlobalConfiguration(),
2434                 newMergedOverrideConfig);
2435 
2436         if (changes == 0 && !forceNewConfig) {
2437             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2438                     "Configuration no differences in " + this);
2439             // There are no significant differences, so we won't relaunch but should still deliver
2440             // the new configuration to the client process.
2441             if (displayChanged) {
2442                 scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
2443             } else {
2444                 scheduleConfigurationChanged(newMergedOverrideConfig);
2445             }
2446             return true;
2447         }
2448 
2449         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2450                 "Configuration changes for " + this + ", allChanges="
2451                         + Configuration.configurationDiffToString(changes));
2452 
2453         // If the activity isn't currently running, just leave the new configuration and it will
2454         // pick that up next time it starts.
2455         if (app == null || app.thread == null) {
2456             if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2457                     "Configuration doesn't matter not running " + this);
2458             stopFreezingScreenLocked(false);
2459             forceNewConfig = false;
2460             return true;
2461         }
2462 
2463         // Figure out how to handle the changes between the configurations.
2464         if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2465                 "Checking to restart " + info.name + ": changed=0x"
2466                         + Integer.toHexString(changes) + ", handles=0x"
2467                         + Integer.toHexString(info.getRealConfigChanged())
2468                         + ", mLastReportedConfiguration=" + mLastReportedConfiguration);
2469 
2470         if (shouldRelaunchLocked(changes, mTmpConfig) || forceNewConfig) {
2471             // Aha, the activity isn't handling the change, so DIE DIE DIE.
2472             configChangeFlags |= changes;
2473             startFreezingScreenLocked(app, globalChanges);
2474             forceNewConfig = false;
2475             preserveWindow &= isResizeOnlyChange(changes);
2476             if (app == null || app.thread == null) {
2477                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2478                         "Config is destroying non-running " + this);
2479                 stack.destroyActivityLocked(this, true, "config");
2480             } else if (state == PAUSING) {
2481                 // A little annoying: we are waiting for this activity to finish pausing. Let's not
2482                 // do anything now, but just flag that it needs to be restarted when done pausing.
2483                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2484                         "Config is skipping already pausing " + this);
2485                 deferRelaunchUntilPaused = true;
2486                 preserveWindowOnDeferredRelaunch = preserveWindow;
2487                 return true;
2488             } else if (state == RESUMED) {
2489                 // Try to optimize this case: the configuration is changing and we need to restart
2490                 // the top, resumed activity. Instead of doing the normal handshaking, just say
2491                 // "restart!".
2492                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2493                         "Config is relaunching resumed " + this);
2494 
2495                 if (DEBUG_STATES && !visible) {
2496                     Slog.v(TAG_STATES, "Config is relaunching resumed invisible activity " + this
2497                             + " called by " + Debug.getCallers(4));
2498                 }
2499 
2500                 relaunchActivityLocked(true /* andResume */, preserveWindow);
2501             } else {
2502                 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
2503                         "Config is relaunching non-resumed " + this);
2504                 relaunchActivityLocked(false /* andResume */, preserveWindow);
2505             }
2506 
2507             // All done...  tell the caller we weren't able to keep this activity around.
2508             return false;
2509         }
2510 
2511         // Default case: the activity can handle this new configuration, so hand it over.
2512         // NOTE: We only forward the override configuration as the system level configuration
2513         // changes is always sent to all processes when they happen so it can just use whatever
2514         // system level configuration it last got.
2515         if (displayChanged) {
2516             scheduleActivityMovedToDisplay(newDisplayId, newMergedOverrideConfig);
2517         } else {
2518             scheduleConfigurationChanged(newMergedOverrideConfig);
2519         }
2520         stopFreezingScreenLocked(false);
2521 
2522         return true;
2523     }
2524 
2525     /**
2526      * When assessing a configuration change, decide if the changes flags and the new configurations
2527      * should cause the Activity to relaunch.
2528      *
2529      * @param changes the changes due to the given configuration.
2530      * @param changesConfig the configuration that was used to calculate the given changes via a
2531      *        call to getConfigurationChanges.
2532      */
shouldRelaunchLocked(int changes, Configuration changesConfig)2533     private boolean shouldRelaunchLocked(int changes, Configuration changesConfig) {
2534         int configChanged = info.getRealConfigChanged();
2535         boolean onlyVrUiModeChanged = onlyVrUiModeChanged(changes, changesConfig);
2536 
2537         // Override for apps targeting pre-O sdks
2538         // If a device is in VR mode, and we're transitioning into VR ui mode, add ignore ui mode
2539         // to the config change.
2540         // For O and later, apps will be required to add configChanges="uimode" to their manifest.
2541         if (appInfo.targetSdkVersion < O
2542                 && requestedVrComponent != null
2543                 && onlyVrUiModeChanged) {
2544             configChanged |= CONFIG_UI_MODE;
2545         }
2546 
2547         return (changes&(~configChanged)) != 0;
2548     }
2549 
2550     /**
2551      * Returns true if the configuration change is solely due to the UI mode switching into or out
2552      * of UI_MODE_TYPE_VR_HEADSET.
2553      */
onlyVrUiModeChanged(int changes, Configuration lastReportedConfig)2554     private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
2555         final Configuration currentConfig = getConfiguration();
2556         return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
2557             != isInVrUiMode(lastReportedConfig));
2558     }
2559 
getConfigurationChanges(Configuration lastReportedConfig)2560     private int getConfigurationChanges(Configuration lastReportedConfig) {
2561         // Determine what has changed.  May be nothing, if this is a config that has come back from
2562         // the app after going idle.  In that case we just want to leave the official config object
2563         // now in the activity and do nothing else.
2564         final Configuration currentConfig = getConfiguration();
2565         int changes = lastReportedConfig.diff(currentConfig);
2566         // We don't want to use size changes if they don't cross boundaries that are important to
2567         // the app.
2568         if ((changes & CONFIG_SCREEN_SIZE) != 0) {
2569             final boolean crosses = crossesHorizontalSizeThreshold(lastReportedConfig.screenWidthDp,
2570                     currentConfig.screenWidthDp)
2571                     || crossesVerticalSizeThreshold(lastReportedConfig.screenHeightDp,
2572                     currentConfig.screenHeightDp);
2573             if (!crosses) {
2574                 changes &= ~CONFIG_SCREEN_SIZE;
2575             }
2576         }
2577         if ((changes & CONFIG_SMALLEST_SCREEN_SIZE) != 0) {
2578             final int oldSmallest = lastReportedConfig.smallestScreenWidthDp;
2579             final int newSmallest = currentConfig.smallestScreenWidthDp;
2580             if (!crossesSmallestSizeThreshold(oldSmallest, newSmallest)) {
2581                 changes &= ~CONFIG_SMALLEST_SCREEN_SIZE;
2582             }
2583         }
2584         return changes;
2585     }
2586 
isResizeOnlyChange(int change)2587     private static boolean isResizeOnlyChange(int change) {
2588         return (change & ~(CONFIG_SCREEN_SIZE | CONFIG_SMALLEST_SCREEN_SIZE | CONFIG_ORIENTATION
2589                 | CONFIG_SCREEN_LAYOUT)) == 0;
2590     }
2591 
relaunchActivityLocked(boolean andResume, boolean preserveWindow)2592     void relaunchActivityLocked(boolean andResume, boolean preserveWindow) {
2593         if (service.mSuppressResizeConfigChanges && preserveWindow) {
2594             configChangeFlags = 0;
2595             return;
2596         }
2597 
2598         List<ResultInfo> pendingResults = null;
2599         List<ReferrerIntent> pendingNewIntents = null;
2600         if (andResume) {
2601             pendingResults = results;
2602             pendingNewIntents = newIntents;
2603         }
2604         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
2605                 "Relaunching: " + this + " with results=" + pendingResults
2606                         + " newIntents=" + pendingNewIntents + " andResume=" + andResume
2607                         + " preserveWindow=" + preserveWindow);
2608         EventLog.writeEvent(andResume ? AM_RELAUNCH_RESUME_ACTIVITY
2609                         : AM_RELAUNCH_ACTIVITY, userId, System.identityHashCode(this),
2610                 task.taskId, shortComponentName);
2611 
2612         startFreezingScreenLocked(app, 0);
2613 
2614         mStackSupervisor.removeChildActivityContainers(this);
2615 
2616         try {
2617             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH,
2618                     "Moving to " + (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + this
2619                             + " callers=" + Debug.getCallers(6));
2620             forceNewConfig = false;
2621             mStackSupervisor.activityRelaunchingLocked(this);
2622             app.thread.scheduleRelaunchActivity(appToken, pendingResults, pendingNewIntents,
2623                     configChangeFlags, !andResume,
2624                     new Configuration(service.getGlobalConfiguration()),
2625                     new Configuration(getMergedOverrideConfiguration()), preserveWindow);
2626             // Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
2627             // pass in 'andResume' if this activity is currently resumed, which implies we aren't
2628             // sleeping.
2629         } catch (RemoteException e) {
2630             if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_SWITCH, "Relaunch failed", e);
2631         }
2632 
2633         if (andResume) {
2634             if (DEBUG_STATES) {
2635                 Slog.d(TAG_STATES, "Resumed after relaunch " + this);
2636             }
2637             results = null;
2638             newIntents = null;
2639             service.showUnsupportedZoomDialogIfNeededLocked(this);
2640             service.showAskCompatModeDialogLocked(this);
2641         } else {
2642             service.mHandler.removeMessages(PAUSE_TIMEOUT_MSG, this);
2643             state = PAUSED;
2644             // if the app is relaunched when it's stopped, and we're not resuming,
2645             // put it back into stopped state.
2646             if (stopped) {
2647                 getStack().addToStopping(this, true /* scheduleIdle */, false /* idleDelayed */);
2648             }
2649         }
2650 
2651         configChangeFlags = 0;
2652         deferRelaunchUntilPaused = false;
2653         preserveWindowOnDeferredRelaunch = false;
2654     }
2655 
isProcessRunning()2656     private boolean isProcessRunning() {
2657         ProcessRecord proc = app;
2658         if (proc == null) {
2659             proc = service.mProcessNames.get(processName, info.applicationInfo.uid);
2660         }
2661         return proc != null && proc.thread != null;
2662     }
2663 
2664     /**
2665      * @return Whether a task snapshot starting window may be shown.
2666      */
allowTaskSnapshot()2667     private boolean allowTaskSnapshot() {
2668         if (newIntents == null) {
2669             return true;
2670         }
2671 
2672         // Restrict task snapshot starting window to launcher start, or there is no intent at all
2673         // (eg. task being brought to front). If the intent is something else, likely the app is
2674         // going to show some specific page or view, instead of what's left last time.
2675         for (int i = newIntents.size() - 1; i >= 0; i--) {
2676             final Intent intent = newIntents.get(i);
2677             if (intent != null && !ActivityRecord.isMainIntent(intent)) {
2678                 return false;
2679             }
2680         }
2681         return true;
2682     }
2683 
2684     /**
2685      * Returns {@code true} if the associated activity has the no history flag set on it.
2686      * {@code false} otherwise.
2687      */
isNoHistory()2688     boolean isNoHistory() {
2689         return (intent.getFlags() & FLAG_ACTIVITY_NO_HISTORY) != 0
2690                 || (info.flags & FLAG_NO_HISTORY) != 0;
2691     }
2692 
saveToXml(XmlSerializer out)2693     void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
2694         out.attribute(null, ATTR_ID, String.valueOf(createTime));
2695         out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
2696         if (launchedFromPackage != null) {
2697             out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
2698         }
2699         if (resolvedType != null) {
2700             out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
2701         }
2702         out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
2703         out.attribute(null, ATTR_USERID, String.valueOf(userId));
2704 
2705         if (taskDescription != null) {
2706             taskDescription.saveToXml(out);
2707         }
2708 
2709         out.startTag(null, TAG_INTENT);
2710         intent.saveToXml(out);
2711         out.endTag(null, TAG_INTENT);
2712 
2713         if (isPersistable() && persistentState != null) {
2714             out.startTag(null, TAG_PERSISTABLEBUNDLE);
2715             persistentState.saveToXml(out);
2716             out.endTag(null, TAG_PERSISTABLEBUNDLE);
2717         }
2718     }
2719 
restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)2720     static ActivityRecord restoreFromXml(XmlPullParser in,
2721             ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
2722         Intent intent = null;
2723         PersistableBundle persistentState = null;
2724         int launchedFromUid = 0;
2725         String launchedFromPackage = null;
2726         String resolvedType = null;
2727         boolean componentSpecified = false;
2728         int userId = 0;
2729         long createTime = -1;
2730         final int outerDepth = in.getDepth();
2731         TaskDescription taskDescription = new TaskDescription();
2732 
2733         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
2734             final String attrName = in.getAttributeName(attrNdx);
2735             final String attrValue = in.getAttributeValue(attrNdx);
2736             if (DEBUG) Slog.d(TaskPersister.TAG,
2737                         "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
2738             if (ATTR_ID.equals(attrName)) {
2739                 createTime = Long.parseLong(attrValue);
2740             } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
2741                 launchedFromUid = Integer.parseInt(attrValue);
2742             } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
2743                 launchedFromPackage = attrValue;
2744             } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
2745                 resolvedType = attrValue;
2746             } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
2747                 componentSpecified = Boolean.parseBoolean(attrValue);
2748             } else if (ATTR_USERID.equals(attrName)) {
2749                 userId = Integer.parseInt(attrValue);
2750             } else if (attrName.startsWith(ATTR_TASKDESCRIPTION_PREFIX)) {
2751                 taskDescription.restoreFromXml(attrName, attrValue);
2752             } else {
2753                 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
2754             }
2755         }
2756 
2757         int event;
2758         while (((event = in.next()) != END_DOCUMENT) &&
2759                 (event != END_TAG || in.getDepth() >= outerDepth)) {
2760             if (event == START_TAG) {
2761                 final String name = in.getName();
2762                 if (DEBUG)
2763                         Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
2764                 if (TAG_INTENT.equals(name)) {
2765                     intent = Intent.restoreFromXml(in);
2766                     if (DEBUG)
2767                             Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
2768                 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
2769                     persistentState = PersistableBundle.restoreFromXml(in);
2770                     if (DEBUG) Slog.d(TaskPersister.TAG,
2771                             "ActivityRecord: persistentState=" + persistentState);
2772                 } else {
2773                     Slog.w(TAG, "restoreActivity: unexpected name=" + name);
2774                     XmlUtils.skipCurrentTag(in);
2775                 }
2776             }
2777         }
2778 
2779         if (intent == null) {
2780             throw new XmlPullParserException("restoreActivity error intent=" + intent);
2781         }
2782 
2783         final ActivityManagerService service = stackSupervisor.mService;
2784         final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
2785                 userId);
2786         if (aInfo == null) {
2787             throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
2788                     " resolvedType=" + resolvedType);
2789         }
2790         final ActivityRecord r = new ActivityRecord(service, null /* caller */,
2791                 0 /* launchedFromPid */, launchedFromUid, launchedFromPackage, intent, resolvedType,
2792                 aInfo, service.getConfiguration(), null /* resultTo */, null /* resultWho */,
2793                 0 /* reqCode */, componentSpecified, false /* rootVoiceInteraction */,
2794                 stackSupervisor, null /* container */, null /* options */, null /* sourceRecord */);
2795 
2796         r.persistentState = persistentState;
2797         r.taskDescription = taskDescription;
2798         r.createTime = createTime;
2799 
2800         return r;
2801     }
2802 
activityTypeToString(int type)2803     private static String activityTypeToString(int type) {
2804         switch (type) {
2805             case APPLICATION_ACTIVITY_TYPE: return "APPLICATION_ACTIVITY_TYPE";
2806             case HOME_ACTIVITY_TYPE: return "HOME_ACTIVITY_TYPE";
2807             case RECENTS_ACTIVITY_TYPE: return "RECENTS_ACTIVITY_TYPE";
2808             case ASSISTANT_ACTIVITY_TYPE: return "ASSISTANT_ACTIVITY_TYPE";
2809             default: return Integer.toString(type);
2810         }
2811     }
2812 
isInVrUiMode(Configuration config)2813     private static boolean isInVrUiMode(Configuration config) {
2814         return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
2815     }
2816 
getUid()2817     int getUid() {
2818         return info.applicationInfo.uid;
2819     }
2820 
2821     @Override
toString()2822     public String toString() {
2823         if (stringName != null) {
2824             return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) +
2825                     (finishing ? " f}" : "}");
2826         }
2827         StringBuilder sb = new StringBuilder(128);
2828         sb.append("ActivityRecord{");
2829         sb.append(Integer.toHexString(System.identityHashCode(this)));
2830         sb.append(" u");
2831         sb.append(userId);
2832         sb.append(' ');
2833         sb.append(intent.getComponent().flattenToShortString());
2834         stringName = sb.toString();
2835         return toString();
2836     }
2837 }
2838