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