OSDN Git Service

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