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