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