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.StackId;
     20 import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
     21 import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
     22 import static android.content.pm.ActivityInfo.RESIZE_MODE_CROP_WINDOWS;
     23 import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
     24 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
     25 import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
     26 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
     27 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
     28 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_THUMBNAILS;
     29 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STATES;
     30 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
     31 import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_THUMBNAILS;
     32 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
     33 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
     34 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
     35 
     36 import android.app.ActivityManager.TaskDescription;
     37 import android.app.ActivityOptions;
     38 import android.app.PendingIntent;
     39 import android.app.ResultInfo;
     40 import android.content.ComponentName;
     41 import android.content.Intent;
     42 import android.content.pm.ActivityInfo;
     43 import android.content.pm.ApplicationInfo;
     44 import android.content.res.CompatibilityInfo;
     45 import android.content.res.Configuration;
     46 import android.graphics.Bitmap;
     47 import android.graphics.Rect;
     48 import android.os.Build;
     49 import android.os.Bundle;
     50 import android.os.IBinder;
     51 import android.os.Message;
     52 import android.os.PersistableBundle;
     53 import android.os.Process;
     54 import android.os.RemoteException;
     55 import android.os.SystemClock;
     56 import android.os.Trace;
     57 import android.os.UserHandle;
     58 import android.service.voice.IVoiceInteractionSession;
     59 import android.util.EventLog;
     60 import android.util.Log;
     61 import android.util.Slog;
     62 import android.util.TimeUtils;
     63 import android.view.AppTransitionAnimationSpec;
     64 import android.view.IApplicationToken;
     65 import android.view.WindowManager;
     66 
     67 import com.android.internal.app.ResolverActivity;
     68 import com.android.internal.content.ReferrerIntent;
     69 import com.android.internal.util.XmlUtils;
     70 import com.android.server.AttributeCache;
     71 import com.android.server.am.ActivityStack.ActivityState;
     72 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
     73 
     74 import java.io.File;
     75 import java.io.IOException;
     76 import java.io.PrintWriter;
     77 import java.lang.ref.WeakReference;
     78 import java.util.ArrayList;
     79 import java.util.Arrays;
     80 import java.util.HashSet;
     81 import java.util.Objects;
     82 
     83 import org.xmlpull.v1.XmlPullParser;
     84 import org.xmlpull.v1.XmlPullParserException;
     85 import org.xmlpull.v1.XmlSerializer;
     86 
     87 /**
     88  * An entry in the history stack, representing an activity.
     89  */
     90 final class ActivityRecord {
     91     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityRecord" : TAG_AM;
     92     private static final String TAG_STATES = TAG + POSTFIX_STATES;
     93     private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
     94     private static final String TAG_THUMBNAILS = TAG + POSTFIX_THUMBNAILS;
     95 
     96     private static final boolean SHOW_ACTIVITY_START_TIME = true;
     97     final public static String RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
     98 
     99     private static final String ATTR_ID = "id";
    100     private static final String TAG_INTENT = "intent";
    101     private static final String ATTR_USERID = "user_id";
    102     private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
    103     private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
    104     private static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
    105     private static final String ATTR_RESOLVEDTYPE = "resolved_type";
    106     private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
    107     static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
    108 
    109     final ActivityManagerService service; // owner
    110     final IApplicationToken.Stub appToken; // window manager token
    111     final ActivityInfo info; // all about me
    112     final ApplicationInfo appInfo; // information about activity's app
    113     final int launchedFromUid; // always the uid who started the activity.
    114     final String launchedFromPackage; // always the package who started the activity.
    115     final int userId;          // Which user is this running for?
    116     final Intent intent;    // the original intent that generated us
    117     final ComponentName realActivity;  // the intent component, or target of an alias.
    118     final String shortComponentName; // the short component name of the intent
    119     final String resolvedType; // as per original caller;
    120     final String packageName; // the package implementing intent's component
    121     final String processName; // process where this component wants to run
    122     final String taskAffinity; // as per ActivityInfo.taskAffinity
    123     final boolean stateNotNeeded; // As per ActivityInfo.flags
    124     boolean fullscreen; // covers the full screen?
    125     final boolean noDisplay;  // activity is not displayed?
    126     final boolean componentSpecified;  // did caller specify an explicit component?
    127     final boolean rootVoiceInteraction;  // was this the root activity of a voice interaction?
    128 
    129     static final int APPLICATION_ACTIVITY_TYPE = 0;
    130     static final int HOME_ACTIVITY_TYPE = 1;
    131     static final int RECENTS_ACTIVITY_TYPE = 2;
    132     int mActivityType;
    133 
    134     CharSequence nonLocalizedLabel;  // the label information from the package mgr.
    135     int labelRes;           // the label information from the package mgr.
    136     int icon;               // resource identifier of activity's icon.
    137     int logo;               // resource identifier of activity's logo.
    138     int theme;              // resource identifier of activity's theme.
    139     int realTheme;          // actual theme resource we will use, never 0.
    140     int windowFlags;        // custom window flags for preview window.
    141     TaskRecord task;        // the task this is in.
    142     long createTime = System.currentTimeMillis();
    143     long displayStartTime;  // when we started launching this activity
    144     long fullyDrawnStartTime; // when we started launching this activity
    145     long startTime;         // last time this activity was started
    146     long lastVisibleTime;   // last time this activity became visible
    147     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
    148     long pauseTime;         // last time we started pausing the activity
    149     long launchTickTime;    // base time for launch tick messages
    150     Configuration configuration; // configuration activity was last running in
    151     // Overridden configuration by the activity task
    152     // WARNING: Reference points to {@link TaskRecord#mOverrideConfig}, so its internal state
    153     // should never be altered directly.
    154     Configuration taskConfigOverride;
    155     CompatibilityInfo compat;// last used compatibility mode
    156     ActivityRecord resultTo; // who started this entry, so will get our reply
    157     final String resultWho; // additional identifier for use by resultTo.
    158     final int requestCode;  // code given by requester (resultTo)
    159     ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
    160     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
    161     ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
    162     ActivityOptions pendingOptions; // most recently given options
    163     ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
    164     AppTimeTracker appTimeTracker; // set if we are tracking the time in this app/task/activity
    165     HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
    166     UriPermissionOwner uriPermissions; // current special URI access perms.
    167     ProcessRecord app;      // if non-null, hosting application
    168     ActivityState state;    // current state we are in
    169     Bundle  icicle;         // last saved activity state
    170     PersistableBundle persistentState; // last persistently saved activity state
    171     boolean frontOfTask;    // is this the root activity of its task?
    172     boolean launchFailed;   // set if a launched failed, to abort on 2nd try
    173     boolean haveState;      // have we gotten the last activity state?
    174     boolean stopped;        // is activity pause finished?
    175     boolean delayedResume;  // not yet resumed because of stopped app switches?
    176     boolean finishing;      // activity in pending finish list?
    177     boolean deferRelaunchUntilPaused;   // relaunch of activity is being deferred until pause is
    178                                         // completed
    179     boolean preserveWindowOnDeferredRelaunch; // activity windows are preserved on deferred relaunch
    180     int configChangeFlags;  // which config values have changed
    181     boolean keysPaused;     // has key dispatching been paused for it?
    182     int launchMode;         // the launch mode activity attribute.
    183     boolean visible;        // does this activity's window need to be shown?
    184     boolean sleeping;       // have we told the activity to sleep?
    185     boolean nowVisible;     // is this activity's window visible?
    186     boolean idle;           // has the activity gone idle?
    187     boolean hasBeenLaunched;// has this activity ever been launched?
    188     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
    189     boolean immersive;      // immersive mode (don't interrupt if possible)
    190     boolean forceNewConfig; // force re-create with new config next time
    191     int launchCount;        // count of launches since last state
    192     long lastLaunchTime;    // time of last launch of this activity
    193     ComponentName requestedVrComponent; // the requested component for handling VR mode.
    194     ArrayList<ActivityContainer> mChildContainers = new ArrayList<>();
    195 
    196     String stringName;      // for caching of toString().
    197 
    198     private boolean inHistory;  // are we in the history stack?
    199     final ActivityStackSupervisor mStackSupervisor;
    200 
    201     static final int STARTING_WINDOW_NOT_SHOWN = 0;
    202     static final int STARTING_WINDOW_SHOWN = 1;
    203     static final int STARTING_WINDOW_REMOVED = 2;
    204     int mStartingWindowState = STARTING_WINDOW_NOT_SHOWN;
    205     boolean mTaskOverlay = false; // Task is always on-top of other activities in the task.
    206 
    207     boolean mUpdateTaskThumbnailWhenHidden;
    208     ActivityContainer mInitialActivityContainer;
    209 
    210     TaskDescription taskDescription; // the recents information for this activity
    211     boolean mLaunchTaskBehind; // this activity is actively being launched with
    212         // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed.
    213 
    214     // These configurations are collected from application's resources based on size-sensitive
    215     // qualifiers. For example, layout-w800dp will be added to mHorizontalSizeConfigurations as 800
    216     // and drawable-sw400dp will be added to both as 400.
    217     private int[] mVerticalSizeConfigurations;
    218     private int[] mHorizontalSizeConfigurations;
    219     private int[] mSmallestSizeConfigurations;
    220 
    221     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
    222     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
    223 
    224     private static String startingWindowStateToString(int state) {
    225         switch (state) {
    226             case STARTING_WINDOW_NOT_SHOWN:
    227                 return "STARTING_WINDOW_NOT_SHOWN";
    228             case STARTING_WINDOW_SHOWN:
    229                 return "STARTING_WINDOW_SHOWN";
    230             case STARTING_WINDOW_REMOVED:
    231                 return "STARTING_WINDOW_REMOVED";
    232             default:
    233                 return "unknown state=" + state;
    234         }
    235     }
    236 
    237     void dump(PrintWriter pw, String prefix) {
    238         final long now = SystemClock.uptimeMillis();
    239         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
    240                 pw.print(" processName="); pw.println(processName);
    241         pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
    242                 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
    243                 pw.print(" userId="); pw.println(userId);
    244         pw.print(prefix); pw.print("app="); pw.println(app);
    245         pw.print(prefix); pw.println(intent.toInsecureStringWithClip());
    246         pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
    247                 pw.print(" task="); pw.println(task);
    248         pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
    249         pw.print(prefix); pw.print("realActivity=");
    250                 pw.println(realActivity.flattenToShortString());
    251         if (appInfo != null) {
    252             pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
    253             if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
    254                 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
    255             }
    256             pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
    257             if (appInfo.splitSourceDirs != null) {
    258                 pw.print(prefix); pw.print("splitDir=");
    259                         pw.println(Arrays.toString(appInfo.splitSourceDirs));
    260             }
    261         }
    262         pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
    263                 pw.print(" componentSpecified="); pw.print(componentSpecified);
    264                 pw.print(" mActivityType="); pw.println(mActivityType);
    265         if (rootVoiceInteraction) {
    266             pw.print(prefix); pw.print("rootVoiceInteraction="); pw.println(rootVoiceInteraction);
    267         }
    268         pw.print(prefix); pw.print("compat="); pw.print(compat);
    269                 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
    270                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
    271                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
    272         pw.print(prefix); pw.print("config="); pw.println(configuration);
    273         pw.print(prefix); pw.print("taskConfigOverride="); pw.println(taskConfigOverride);
    274         if (resultTo != null || resultWho != null) {
    275             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
    276                     pw.print(" resultWho="); pw.print(resultWho);
    277                     pw.print(" resultCode="); pw.println(requestCode);
    278         }
    279         if (taskDescription != null) {
    280             final String iconFilename = taskDescription.getIconFilename();
    281             if (iconFilename != null || taskDescription.getLabel() != null ||
    282                     taskDescription.getPrimaryColor() != 0) {
    283                 pw.print(prefix); pw.print("taskDescription:");
    284                         pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
    285                         pw.print(" label=\""); pw.print(taskDescription.getLabel());
    286                                 pw.print("\"");
    287                         pw.print(" color=");
    288                         pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
    289             }
    290             if (iconFilename == null && taskDescription.getIcon() != null) {
    291                 pw.print(prefix); pw.println("taskDescription contains Bitmap");
    292             }
    293         }
    294         if (results != null) {
    295             pw.print(prefix); pw.print("results="); pw.println(results);
    296         }
    297         if (pendingResults != null && pendingResults.size() > 0) {
    298             pw.print(prefix); pw.println("Pending Results:");
    299             for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
    300                 PendingIntentRecord pir = wpir != null ? wpir.get() : null;
    301                 pw.print(prefix); pw.print("  - ");
    302                 if (pir == null) {
    303                     pw.println("null");
    304                 } else {
    305                     pw.println(pir);
    306                     pir.dump(pw, prefix + "    ");
    307                 }
    308             }
    309         }
    310         if (newIntents != null && newIntents.size() > 0) {
    311             pw.print(prefix); pw.println("Pending New Intents:");
    312             for (int i=0; i<newIntents.size(); i++) {
    313                 Intent intent = newIntents.get(i);
    314                 pw.print(prefix); pw.print("  - ");
    315                 if (intent == null) {
    316                     pw.println("null");
    317                 } else {
    318                     pw.println(intent.toShortString(false, true, false, true));
    319                 }
    320             }
    321         }
    322         if (pendingOptions != null) {
    323             pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
    324         }
    325         if (appTimeTracker != null) {
    326             appTimeTracker.dumpWithHeader(pw, prefix, false);
    327         }
    328         if (uriPermissions != null) {
    329             uriPermissions.dump(pw, prefix);
    330         }
    331         pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
    332                 pw.print(" launchCount="); pw.print(launchCount);
    333                 pw.print(" lastLaunchTime=");
    334                 if (lastLaunchTime == 0) pw.print("0");
    335                 else TimeUtils.formatDuration(lastLaunchTime, now, pw);
    336                 pw.println();
    337         pw.print(prefix); pw.print("haveState="); pw.print(haveState);
    338                 pw.print(" icicle="); pw.println(icicle);
    339         pw.print(prefix); pw.print("state="); pw.print(state);
    340                 pw.print(" stopped="); pw.print(stopped);
    341                 pw.print(" delayedResume="); pw.print(delayedResume);
    342                 pw.print(" finishing="); pw.println(finishing);
    343         pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
    344                 pw.print(" inHistory="); pw.print(inHistory);
    345                 pw.print(" visible="); pw.print(visible);
    346                 pw.print(" sleeping="); pw.print(sleeping);
    347                 pw.print(" idle="); pw.print(idle);
    348                 pw.print(" mStartingWindowState=");
    349                 pw.println(startingWindowStateToString(mStartingWindowState));
    350         pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
    351                 pw.print(" noDisplay="); pw.print(noDisplay);
    352                 pw.print(" immersive="); pw.print(immersive);
    353                 pw.print(" launchMode="); pw.println(launchMode);
    354         pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
    355                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
    356         pw.print(prefix); pw.print("mActivityType=");
    357                 pw.println(activityTypeToString(mActivityType));
    358         if (requestedVrComponent != null) {
    359             pw.print(prefix);
    360             pw.print("requestedVrComponent=");
    361             pw.println(requestedVrComponent);
    362         }
    363         if (displayStartTime != 0 || startTime != 0) {
    364             pw.print(prefix); pw.print("displayStartTime=");
    365                     if (displayStartTime == 0) pw.print("0");
    366                     else TimeUtils.formatDuration(displayStartTime, now, pw);
    367                     pw.print(" startTime=");
    368                     if (startTime == 0) pw.print("0");
    369                     else TimeUtils.formatDuration(startTime, now, pw);
    370                     pw.println();
    371         }
    372         final boolean waitingVisible = mStackSupervisor.mWaitingVisibleActivities.contains(this);
    373         if (lastVisibleTime != 0 || waitingVisible || nowVisible) {
    374             pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
    375                     pw.print(" nowVisible="); pw.print(nowVisible);
    376                     pw.print(" lastVisibleTime=");
    377                     if (lastVisibleTime == 0) pw.print("0");
    378                     else TimeUtils.formatDuration(lastVisibleTime, now, pw);
    379                     pw.println();
    380         }
    381         if (deferRelaunchUntilPaused || configChangeFlags != 0) {
    382             pw.print(prefix); pw.print("deferRelaunchUntilPaused="); pw.print(deferRelaunchUntilPaused);
    383                     pw.print(" configChangeFlags=");
    384                     pw.println(Integer.toHexString(configChangeFlags));
    385         }
    386         if (connections != null) {
    387             pw.print(prefix); pw.print("connections="); pw.println(connections);
    388         }
    389         if (info != null) {
    390             pw.println(prefix + "resizeMode=" + ActivityInfo.resizeModeToString(info.resizeMode));
    391         }
    392     }
    393 
    394     public boolean crossesHorizontalSizeThreshold(int firstDp, int secondDp) {
    395         return crossesSizeThreshold(mHorizontalSizeConfigurations, firstDp, secondDp);
    396     }
    397 
    398     public boolean crossesVerticalSizeThreshold(int firstDp, int secondDp) {
    399         return crossesSizeThreshold(mVerticalSizeConfigurations, firstDp, secondDp);
    400     }
    401 
    402     public boolean crossesSmallestSizeThreshold(int firstDp, int secondDp) {
    403         return crossesSizeThreshold(mSmallestSizeConfigurations, firstDp, secondDp);
    404     }
    405 
    406     /**
    407      * The purpose of this method is to decide whether the activity needs to be relaunched upon
    408      * changing its size. In most cases the activities don't need to be relaunched, if the resize
    409      * is small, all the activity content has to do is relayout itself within new bounds. There are
    410      * cases however, where the activity's content would be completely changed in the new size and
    411      * the full relaunch is required.
    412      *
    413      * The activity will report to us vertical and horizontal thresholds after which a relaunch is
    414      * required. These thresholds are collected from the application resource qualifiers. For
    415      * example, if application has layout-w600dp resource directory, then it needs a relaunch when
    416      * we resize from width of 650dp to 550dp, as it crosses the 600dp threshold. However, if
    417      * it resizes width from 620dp to 700dp, it won't be relaunched as it stays on the same side
    418      * of the threshold.
    419      */
    420     private static boolean crossesSizeThreshold(int[] thresholds, int firstDp,
    421             int secondDp) {
    422         if (thresholds == null) {
    423             return false;
    424         }
    425         for (int i = thresholds.length - 1; i >= 0; i--) {
    426             final int threshold = thresholds[i];
    427             if ((firstDp < threshold && secondDp >= threshold)
    428                     || (firstDp >= threshold && secondDp < threshold)) {
    429                 return true;
    430             }
    431         }
    432         return false;
    433     }
    434 
    435     public void setSizeConfigurations(int[] horizontalSizeConfiguration,
    436             int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
    437         mHorizontalSizeConfigurations = horizontalSizeConfiguration;
    438         mVerticalSizeConfigurations = verticalSizeConfigurations;
    439         mSmallestSizeConfigurations = smallestSizeConfigurations;
    440     }
    441 
    442     void scheduleConfigurationChanged(Configuration config, boolean reportToActivity) {
    443         if (app == null || app.thread == null) {
    444             return;
    445         }
    446         try {
    447             // Make sure fontScale is always equal to global. For fullscreen apps, config is
    448             // the shared EMPTY config, which has default fontScale of 1.0. We don't want it
    449             // to be applied as an override config.
    450             Configuration overrideConfig = new Configuration(config);
    451             overrideConfig.fontScale = service.mConfiguration.fontScale;
    452 
    453             if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + this + " " +
    454                     "reportToActivity=" + reportToActivity + " and config: " + overrideConfig);
    455 
    456             app.thread.scheduleActivityConfigurationChanged(
    457                     appToken, overrideConfig, reportToActivity);
    458         } catch (RemoteException e) {
    459             // If process died, whatever.
    460         }
    461     }
    462 
    463     void scheduleMultiWindowModeChanged() {
    464         if (task == null || task.stack == null || app == null || app.thread == null) {
    465             return;
    466         }
    467         try {
    468             // An activity is considered to be in multi-window mode if its task isn't fullscreen.
    469             app.thread.scheduleMultiWindowModeChanged(appToken, !task.mFullscreen);
    470         } catch (Exception e) {
    471             // If process died, I don't care.
    472         }
    473     }
    474 
    475     void schedulePictureInPictureModeChanged() {
    476         if (task == null || task.stack == null || app == null || app.thread == null) {
    477             return;
    478         }
    479         try {
    480             app.thread.schedulePictureInPictureModeChanged(
    481                     appToken, task.stack.mStackId == PINNED_STACK_ID);
    482         } catch (Exception e) {
    483             // If process died, no one cares.
    484         }
    485     }
    486 
    487     boolean isFreeform() {
    488         return task != null && task.stack != null
    489                 && task.stack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
    490     }
    491 
    492     static class Token extends IApplicationToken.Stub {
    493         private final WeakReference<ActivityRecord> weakActivity;
    494         private final ActivityManagerService mService;
    495 
    496         Token(ActivityRecord activity, ActivityManagerService service) {
    497             weakActivity = new WeakReference<>(activity);
    498             mService = service;
    499         }
    500 
    501         @Override
    502         public void windowsDrawn() {
    503             synchronized (mService) {
    504                 ActivityRecord r = tokenToActivityRecordLocked(this);
    505                 if (r != null) {
    506                     r.windowsDrawnLocked();
    507                 }
    508             }
    509         }
    510 
    511         @Override
    512         public void windowsVisible() {
    513             synchronized (mService) {
    514                 ActivityRecord r = tokenToActivityRecordLocked(this);
    515                 if (r != null) {
    516                     r.windowsVisibleLocked();
    517                 }
    518             }
    519         }
    520 
    521         @Override
    522         public void windowsGone() {
    523             synchronized (mService) {
    524                 ActivityRecord r = tokenToActivityRecordLocked(this);
    525                 if (r != null) {
    526                     if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsGone(): " + r);
    527                     r.nowVisible = false;
    528                     return;
    529                 }
    530             }
    531         }
    532 
    533         @Override
    534         public boolean keyDispatchingTimedOut(String reason) {
    535             ActivityRecord r;
    536             ActivityRecord anrActivity;
    537             ProcessRecord anrApp;
    538             synchronized (mService) {
    539                 r = tokenToActivityRecordLocked(this);
    540                 if (r == null) {
    541                     return false;
    542                 }
    543                 anrActivity = r.getWaitingHistoryRecordLocked();
    544                 anrApp = r != null ? r.app : null;
    545             }
    546             return mService.inputDispatchingTimedOut(anrApp, anrActivity, r, false, reason);
    547         }
    548 
    549         @Override
    550         public long getKeyDispatchingTimeout() {
    551             synchronized (mService) {
    552                 ActivityRecord r = tokenToActivityRecordLocked(this);
    553                 if (r == null) {
    554                     return 0;
    555                 }
    556                 r = r.getWaitingHistoryRecordLocked();
    557                 return ActivityManagerService.getInputDispatchingTimeoutLocked(r);
    558             }
    559         }
    560 
    561         private static final ActivityRecord tokenToActivityRecordLocked(Token token) {
    562             if (token == null) {
    563                 return null;
    564             }
    565             ActivityRecord r = token.weakActivity.get();
    566             if (r == null || r.task == null || r.task.stack == null) {
    567                 return null;
    568             }
    569             return r;
    570         }
    571 
    572         @Override
    573         public String toString() {
    574             StringBuilder sb = new StringBuilder(128);
    575             sb.append("Token{");
    576             sb.append(Integer.toHexString(System.identityHashCode(this)));
    577             sb.append(' ');
    578             sb.append(weakActivity.get());
    579             sb.append('}');
    580             return sb.toString();
    581         }
    582     }
    583 
    584     static ActivityRecord forTokenLocked(IBinder token) {
    585         try {
    586             return Token.tokenToActivityRecordLocked((Token)token);
    587         } catch (ClassCastException e) {
    588             Slog.w(TAG, "Bad activity token: " + token, e);
    589             return null;
    590         }
    591     }
    592 
    593     boolean isResolverActivity() {
    594         return ResolverActivity.class.getName().equals(realActivity.getClassName());
    595     }
    596 
    597     ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
    598             int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
    599             ActivityInfo aInfo, Configuration _configuration,
    600             ActivityRecord _resultTo, String _resultWho, int _reqCode,
    601             boolean _componentSpecified, boolean _rootVoiceInteraction,
    602             ActivityStackSupervisor supervisor,
    603             ActivityContainer container, ActivityOptions options, ActivityRecord sourceRecord) {
    604         service = _service;
    605         appToken = new Token(this, service);
    606         info = aInfo;
    607         launchedFromUid = _launchedFromUid;
    608         launchedFromPackage = _launchedFromPackage;
    609         userId = UserHandle.getUserId(aInfo.applicationInfo.uid);
    610         intent = _intent;
    611         shortComponentName = _intent.getComponent().flattenToShortString();
    612         resolvedType = _resolvedType;
    613         componentSpecified = _componentSpecified;
    614         rootVoiceInteraction = _rootVoiceInteraction;
    615         configuration = _configuration;
    616         taskConfigOverride = Configuration.EMPTY;
    617         resultTo = _resultTo;
    618         resultWho = _resultWho;
    619         requestCode = _reqCode;
    620         state = ActivityState.INITIALIZING;
    621         frontOfTask = false;
    622         launchFailed = false;
    623         stopped = false;
    624         delayedResume = false;
    625         finishing = false;
    626         deferRelaunchUntilPaused = false;
    627         keysPaused = false;
    628         inHistory = false;
    629         visible = false;
    630         nowVisible = false;
    631         idle = false;
    632         hasBeenLaunched = false;
    633         mStackSupervisor = supervisor;
    634         mInitialActivityContainer = container;
    635         if (options != null) {
    636             pendingOptions = options;
    637             mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind();
    638             PendingIntent usageReport = pendingOptions.getUsageTimeReport();
    639             if (usageReport != null) {
    640                 appTimeTracker = new AppTimeTracker(usageReport);
    641             }
    642         }
    643 
    644         // This starts out true, since the initial state of an activity
    645         // is that we have everything, and we shouldn't never consider it
    646         // lacking in state to be removed if it dies.
    647         haveState = true;
    648 
    649         if (aInfo != null) {
    650             // If the class name in the intent doesn't match that of the target, this is
    651             // probably an alias. We have to create a new ComponentName object to keep track
    652             // of the real activity name, so that FLAG_ACTIVITY_CLEAR_TOP is handled properly.
    653             if (aInfo.targetActivity == null
    654                     || (aInfo.targetActivity.equals(_intent.getComponent().getClassName())
    655                     && (aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
    656                     || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP))) {
    657                 realActivity = _intent.getComponent();
    658             } else {
    659                 realActivity = new ComponentName(aInfo.packageName, aInfo.targetActivity);
    660             }
    661             taskAffinity = aInfo.taskAffinity;
    662             stateNotNeeded = (aInfo.flags&
    663                     ActivityInfo.FLAG_STATE_NOT_NEEDED) != 0;
    664             appInfo = aInfo.applicationInfo;
    665             nonLocalizedLabel = aInfo.nonLocalizedLabel;
    666             labelRes = aInfo.labelRes;
    667             if (nonLocalizedLabel == null && labelRes == 0) {
    668                 ApplicationInfo app = aInfo.applicationInfo;
    669                 nonLocalizedLabel = app.nonLocalizedLabel;
    670                 labelRes = app.labelRes;
    671             }
    672             icon = aInfo.getIconResource();
    673             logo = aInfo.getLogoResource();
    674             theme = aInfo.getThemeResource();
    675             realTheme = theme;
    676             if (realTheme == 0) {
    677                 realTheme = aInfo.applicationInfo.targetSdkVersion
    678                         < Build.VERSION_CODES.HONEYCOMB
    679                         ? android.R.style.Theme
    680                         : android.R.style.Theme_Holo;
    681             }
    682             if ((aInfo.flags&ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
    683                 windowFlags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
    684             }
    685             if ((aInfo.flags&ActivityInfo.FLAG_MULTIPROCESS) != 0
    686                     && _caller != null
    687                     && (aInfo.applicationInfo.uid == Process.SYSTEM_UID
    688                             || aInfo.applicationInfo.uid == _caller.info.uid)) {
    689                 processName = _caller.processName;
    690             } else {
    691                 processName = aInfo.processName;
    692             }
    693 
    694             if (intent != null && (aInfo.flags & ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS) != 0) {
    695                 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    696             }
    697 
    698             packageName = aInfo.applicationInfo.packageName;
    699             launchMode = aInfo.launchMode;
    700 
    701             AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
    702                     realTheme, com.android.internal.R.styleable.Window, userId);
    703             final boolean translucent = ent != null && (ent.array.getBoolean(
    704                     com.android.internal.R.styleable.Window_windowIsTranslucent, false)
    705                     || (!ent.array.hasValue(
    706                             com.android.internal.R.styleable.Window_windowIsTranslucent)
    707                             && ent.array.getBoolean(
    708                                     com.android.internal.R.styleable.Window_windowSwipeToDismiss,
    709                                             false)));
    710             fullscreen = ent != null && !ent.array.getBoolean(
    711                     com.android.internal.R.styleable.Window_windowIsFloating, false)
    712                     && !translucent;
    713             noDisplay = ent != null && ent.array.getBoolean(
    714                     com.android.internal.R.styleable.Window_windowNoDisplay, false);
    715 
    716             setActivityType(_componentSpecified, _launchedFromUid, _intent, sourceRecord);
    717 
    718             immersive = (aInfo.flags & ActivityInfo.FLAG_IMMERSIVE) != 0;
    719 
    720             requestedVrComponent = (aInfo.requestedVrComponent == null) ?
    721                     null : ComponentName.unflattenFromString(aInfo.requestedVrComponent);
    722         } else {
    723             realActivity = null;
    724             taskAffinity = null;
    725             stateNotNeeded = false;
    726             appInfo = null;
    727             processName = null;
    728             packageName = null;
    729             fullscreen = true;
    730             noDisplay = false;
    731             mActivityType = APPLICATION_ACTIVITY_TYPE;
    732             immersive = false;
    733             requestedVrComponent  = null;
    734         }
    735     }
    736 
    737     private boolean isHomeIntent(Intent intent) {
    738         return Intent.ACTION_MAIN.equals(intent.getAction())
    739                 && intent.hasCategory(Intent.CATEGORY_HOME)
    740                 && intent.getCategories().size() == 1
    741                 && intent.getData() == null
    742                 && intent.getType() == null;
    743     }
    744 
    745     private boolean canLaunchHomeActivity(int uid, ActivityRecord sourceRecord) {
    746         if (uid == Process.myUid() || uid == 0) {
    747             // System process can launch home activity.
    748             return true;
    749         }
    750         // Resolver activity can launch home activity.
    751         return sourceRecord != null && sourceRecord.isResolverActivity();
    752     }
    753 
    754     private void setActivityType(boolean componentSpecified,
    755             int launchedFromUid, Intent intent, ActivityRecord sourceRecord) {
    756         if ((!componentSpecified || canLaunchHomeActivity(launchedFromUid, sourceRecord))
    757                 && isHomeIntent(intent) && !isResolverActivity()) {
    758             // This sure looks like a home activity!
    759             mActivityType = HOME_ACTIVITY_TYPE;
    760         } else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
    761             mActivityType = RECENTS_ACTIVITY_TYPE;
    762         } else {
    763             mActivityType = APPLICATION_ACTIVITY_TYPE;
    764         }
    765     }
    766 
    767     void setTask(TaskRecord newTask, TaskRecord taskToAffiliateWith) {
    768         if (task != null && task.removeActivity(this) && task != newTask && task.stack != null) {
    769             task.stack.removeTask(task, "setTask");
    770         }
    771         task = newTask;
    772         setTaskToAffiliateWith(taskToAffiliateWith);
    773     }
    774 
    775     void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
    776         if (taskToAffiliateWith != null &&
    777                 launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE &&
    778                 launchMode != ActivityInfo.LAUNCH_SINGLE_TASK) {
    779             task.setTaskToAffiliateWith(taskToAffiliateWith);
    780         }
    781     }
    782 
    783     boolean changeWindowTranslucency(boolean toOpaque) {
    784         if (fullscreen == toOpaque) {
    785             return false;
    786         }
    787 
    788         // Keep track of the number of fullscreen activities in this task.
    789         task.numFullscreen += toOpaque ? +1 : -1;
    790 
    791         fullscreen = toOpaque;
    792         return true;
    793     }
    794 
    795     void putInHistory() {
    796         if (!inHistory) {
    797             inHistory = true;
    798         }
    799     }
    800 
    801     void takeFromHistory() {
    802         if (inHistory) {
    803             inHistory = false;
    804             if (task != null && !finishing) {
    805                 task = null;
    806             }
    807             clearOptionsLocked();
    808         }
    809     }
    810 
    811     boolean isInHistory() {
    812         return inHistory;
    813     }
    814 
    815     boolean isInStackLocked() {
    816         return task != null && task.stack != null && task.stack.isInStackLocked(this) != null;
    817     }
    818 
    819     boolean isHomeActivity() {
    820         return mActivityType == HOME_ACTIVITY_TYPE;
    821     }
    822 
    823     boolean isRecentsActivity() {
    824         return mActivityType == RECENTS_ACTIVITY_TYPE;
    825     }
    826 
    827     boolean isApplicationActivity() {
    828         return mActivityType == APPLICATION_ACTIVITY_TYPE;
    829     }
    830 
    831     boolean isPersistable() {
    832         return (info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY ||
    833                 info.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS) &&
    834                 (intent == null ||
    835                         (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
    836     }
    837 
    838     boolean isFocusable() {
    839         return StackId.canReceiveKeys(task.stack.mStackId) || isAlwaysFocusable();
    840     }
    841 
    842     boolean isResizeable() {
    843         return !isHomeActivity() && ActivityInfo.isResizeableMode(info.resizeMode);
    844     }
    845 
    846     boolean isResizeableOrForced() {
    847         return !isHomeActivity() && (isResizeable() || service.mForceResizableActivities);
    848     }
    849 
    850     boolean isNonResizableOrForced() {
    851         return !isHomeActivity() && info.resizeMode != RESIZE_MODE_RESIZEABLE
    852                 && info.resizeMode != RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
    853     }
    854 
    855     boolean supportsPictureInPicture() {
    856         return !isHomeActivity() && info.resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE;
    857     }
    858 
    859     boolean canGoInDockedStack() {
    860         return !isHomeActivity()
    861                 && (isResizeableOrForced() || info.resizeMode == RESIZE_MODE_CROP_WINDOWS);
    862     }
    863 
    864     boolean isAlwaysFocusable() {
    865         return (info.flags & FLAG_ALWAYS_FOCUSABLE) != 0;
    866     }
    867 
    868     void makeFinishingLocked() {
    869         if (!finishing) {
    870             if (task != null && task.stack != null
    871                     && this == task.stack.getVisibleBehindActivity()) {
    872                 // A finishing activity should not remain as visible in the background
    873                 mStackSupervisor.requestVisibleBehindLocked(this, false);
    874             }
    875             finishing = true;
    876             if (stopped) {
    877                 clearOptionsLocked();
    878             }
    879         }
    880     }
    881 
    882     UriPermissionOwner getUriPermissionsLocked() {
    883         if (uriPermissions == null) {
    884             uriPermissions = new UriPermissionOwner(service, this);
    885         }
    886         return uriPermissions;
    887     }
    888 
    889     void addResultLocked(ActivityRecord from, String resultWho,
    890             int requestCode, int resultCode,
    891             Intent resultData) {
    892         ActivityResult r = new ActivityResult(from, resultWho,
    893                 requestCode, resultCode, resultData);
    894         if (results == null) {
    895             results = new ArrayList<ResultInfo>();
    896         }
    897         results.add(r);
    898     }
    899 
    900     void removeResultsLocked(ActivityRecord from, String resultWho,
    901             int requestCode) {
    902         if (results != null) {
    903             for (int i=results.size()-1; i>=0; i--) {
    904                 ActivityResult r = (ActivityResult)results.get(i);
    905                 if (r.mFrom != from) continue;
    906                 if (r.mResultWho == null) {
    907                     if (resultWho != null) continue;
    908                 } else {
    909                     if (!r.mResultWho.equals(resultWho)) continue;
    910                 }
    911                 if (r.mRequestCode != requestCode) continue;
    912 
    913                 results.remove(i);
    914             }
    915         }
    916     }
    917 
    918     void addNewIntentLocked(ReferrerIntent intent) {
    919         if (newIntents == null) {
    920             newIntents = new ArrayList<>();
    921         }
    922         newIntents.add(intent);
    923     }
    924 
    925     /**
    926      * Deliver a new Intent to an existing activity, so that its onNewIntent()
    927      * method will be called at the proper time.
    928      */
    929     final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
    930         // The activity now gets access to the data associated with this Intent.
    931         service.grantUriPermissionFromIntentLocked(callingUid, packageName,
    932                 intent, getUriPermissionsLocked(), userId);
    933         // We want to immediately deliver the intent to the activity if
    934         // it is currently the top resumed activity...  however, if the
    935         // device is sleeping, then all activities are stopped, so in that
    936         // case we will deliver it if this is the current top activity on its
    937         // stack.
    938         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
    939         boolean unsent = true;
    940         if ((state == ActivityState.RESUMED
    941                 || (service.isSleepingLocked() && task.stack != null
    942                     && task.stack.topRunningActivityLocked() == this))
    943                 && app != null && app.thread != null) {
    944             try {
    945                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
    946                 ar.add(rintent);
    947                 app.thread.scheduleNewIntent(ar, appToken);
    948                 unsent = false;
    949             } catch (RemoteException e) {
    950                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
    951             } catch (NullPointerException e) {
    952                 Slog.w(TAG, "Exception thrown sending new intent to " + this, e);
    953             }
    954         }
    955         if (unsent) {
    956             addNewIntentLocked(rintent);
    957         }
    958     }
    959 
    960     void updateOptionsLocked(ActivityOptions options) {
    961         if (options != null) {
    962             if (pendingOptions != null) {
    963                 pendingOptions.abort();
    964             }
    965             pendingOptions = options;
    966         }
    967     }
    968 
    969     void applyOptionsLocked() {
    970         if (pendingOptions != null
    971                 && pendingOptions.getAnimationType() != ActivityOptions.ANIM_SCENE_TRANSITION) {
    972             final int animationType = pendingOptions.getAnimationType();
    973             switch (animationType) {
    974                 case ActivityOptions.ANIM_CUSTOM:
    975                     service.mWindowManager.overridePendingAppTransition(
    976                             pendingOptions.getPackageName(),
    977                             pendingOptions.getCustomEnterResId(),
    978                             pendingOptions.getCustomExitResId(),
    979                             pendingOptions.getOnAnimationStartListener());
    980                     break;
    981                 case ActivityOptions.ANIM_CLIP_REVEAL:
    982                     service.mWindowManager.overridePendingAppTransitionClipReveal(
    983                             pendingOptions.getStartX(), pendingOptions.getStartY(),
    984                             pendingOptions.getWidth(), pendingOptions.getHeight());
    985                     if (intent.getSourceBounds() == null) {
    986                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
    987                                 pendingOptions.getStartY(),
    988                                 pendingOptions.getStartX()+pendingOptions.getWidth(),
    989                                 pendingOptions.getStartY()+pendingOptions.getHeight()));
    990                     }
    991                     break;
    992                 case ActivityOptions.ANIM_SCALE_UP:
    993                     service.mWindowManager.overridePendingAppTransitionScaleUp(
    994                             pendingOptions.getStartX(), pendingOptions.getStartY(),
    995                             pendingOptions.getWidth(), pendingOptions.getHeight());
    996                     if (intent.getSourceBounds() == null) {
    997                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
    998                                 pendingOptions.getStartY(),
    999                                 pendingOptions.getStartX()+pendingOptions.getWidth(),
   1000                                 pendingOptions.getStartY()+pendingOptions.getHeight()));
   1001                     }
   1002                     break;
   1003                 case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
   1004                 case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
   1005                     boolean scaleUp = (animationType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
   1006                     service.mWindowManager.overridePendingAppTransitionThumb(
   1007                             pendingOptions.getThumbnail(),
   1008                             pendingOptions.getStartX(), pendingOptions.getStartY(),
   1009                             pendingOptions.getOnAnimationStartListener(),
   1010                             scaleUp);
   1011                     if (intent.getSourceBounds() == null) {
   1012                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
   1013                                 pendingOptions.getStartY(),
   1014                                 pendingOptions.getStartX()
   1015                                         + pendingOptions.getThumbnail().getWidth(),
   1016                                 pendingOptions.getStartY()
   1017                                         + pendingOptions.getThumbnail().getHeight()));
   1018                     }
   1019                     break;
   1020                 case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP:
   1021                 case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
   1022                     final AppTransitionAnimationSpec[] specs = pendingOptions.getAnimSpecs();
   1023                     if (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN
   1024                             && specs != null) {
   1025                         service.mWindowManager.overridePendingAppTransitionMultiThumb(
   1026                                 specs, pendingOptions.getOnAnimationStartListener(),
   1027                                 pendingOptions.getAnimationFinishedListener(), false);
   1028                     } else {
   1029                         service.mWindowManager.overridePendingAppTransitionAspectScaledThumb(
   1030                                 pendingOptions.getThumbnail(),
   1031                                 pendingOptions.getStartX(), pendingOptions.getStartY(),
   1032                                 pendingOptions.getWidth(), pendingOptions.getHeight(),
   1033                                 pendingOptions.getOnAnimationStartListener(),
   1034                                 (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
   1035                         if (intent.getSourceBounds() == null) {
   1036                             intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
   1037                                     pendingOptions.getStartY(),
   1038                                     pendingOptions.getStartX() + pendingOptions.getWidth(),
   1039                                     pendingOptions.getStartY() + pendingOptions.getHeight()));
   1040                         }
   1041                     }
   1042                     break;
   1043                 default:
   1044                     Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType);
   1045                     break;
   1046             }
   1047             pendingOptions = null;
   1048         }
   1049     }
   1050 
   1051     ActivityOptions getOptionsForTargetActivityLocked() {
   1052         return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
   1053     }
   1054 
   1055     void clearOptionsLocked() {
   1056         if (pendingOptions != null) {
   1057             pendingOptions.abort();
   1058             pendingOptions = null;
   1059         }
   1060     }
   1061 
   1062     ActivityOptions takeOptionsLocked() {
   1063         ActivityOptions opts = pendingOptions;
   1064         pendingOptions = null;
   1065         return opts;
   1066     }
   1067 
   1068     void removeUriPermissionsLocked() {
   1069         if (uriPermissions != null) {
   1070             uriPermissions.removeUriPermissionsLocked();
   1071             uriPermissions = null;
   1072         }
   1073     }
   1074 
   1075     void pauseKeyDispatchingLocked() {
   1076         if (!keysPaused) {
   1077             keysPaused = true;
   1078             service.mWindowManager.pauseKeyDispatching(appToken);
   1079         }
   1080     }
   1081 
   1082     void resumeKeyDispatchingLocked() {
   1083         if (keysPaused) {
   1084             keysPaused = false;
   1085             service.mWindowManager.resumeKeyDispatching(appToken);
   1086         }
   1087     }
   1088 
   1089     void updateThumbnailLocked(Bitmap newThumbnail, CharSequence description) {
   1090         if (newThumbnail != null) {
   1091             if (DEBUG_THUMBNAILS) Slog.i(TAG_THUMBNAILS,
   1092                     "Setting thumbnail of " + this + " to " + newThumbnail);
   1093             boolean thumbnailUpdated = task.setLastThumbnailLocked(newThumbnail);
   1094             if (thumbnailUpdated && isPersistable()) {
   1095                 mStackSupervisor.mService.notifyTaskPersisterLocked(task, false);
   1096             }
   1097         }
   1098         task.lastDescription = description;
   1099     }
   1100 
   1101     void startLaunchTickingLocked() {
   1102         if (ActivityManagerService.IS_USER_BUILD) {
   1103             return;
   1104         }
   1105         if (launchTickTime == 0) {
   1106             launchTickTime = SystemClock.uptimeMillis();
   1107             continueLaunchTickingLocked();
   1108         }
   1109     }
   1110 
   1111     boolean continueLaunchTickingLocked() {
   1112         if (launchTickTime == 0) {
   1113             return false;
   1114         }
   1115 
   1116         final ActivityStack stack = task.stack;
   1117         if (stack == null) {
   1118             return false;
   1119         }
   1120 
   1121         Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG, this);
   1122         stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
   1123         stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
   1124         return true;
   1125     }
   1126 
   1127     void finishLaunchTickingLocked() {
   1128         launchTickTime = 0;
   1129         final ActivityStack stack = task.stack;
   1130         if (stack != null) {
   1131             stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
   1132         }
   1133     }
   1134 
   1135     // IApplicationToken
   1136 
   1137     public boolean mayFreezeScreenLocked(ProcessRecord app) {
   1138         // Only freeze the screen if this activity is currently attached to
   1139         // an application, and that application is not blocked or unresponding.
   1140         // In any other case, we can't count on getting the screen unfrozen,
   1141         // so it is best to leave as-is.
   1142         return app != null && !app.crashing && !app.notResponding;
   1143     }
   1144 
   1145     public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
   1146         if (mayFreezeScreenLocked(app)) {
   1147             service.mWindowManager.startAppFreezingScreen(appToken, configChanges);
   1148         }
   1149     }
   1150 
   1151     public void stopFreezingScreenLocked(boolean force) {
   1152         if (force || frozenBeforeDestroy) {
   1153             frozenBeforeDestroy = false;
   1154             service.mWindowManager.stopAppFreezingScreen(appToken, force);
   1155         }
   1156     }
   1157 
   1158     public void reportFullyDrawnLocked() {
   1159         final long curTime = SystemClock.uptimeMillis();
   1160         if (displayStartTime != 0) {
   1161             reportLaunchTimeLocked(curTime);
   1162         }
   1163         final ActivityStack stack = task.stack;
   1164         if (fullyDrawnStartTime != 0 && stack != null) {
   1165             final long thisTime = curTime - fullyDrawnStartTime;
   1166             final long totalTime = stack.mFullyDrawnStartTime != 0
   1167                     ? (curTime - stack.mFullyDrawnStartTime) : thisTime;
   1168             if (SHOW_ACTIVITY_START_TIME) {
   1169                 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
   1170                 EventLog.writeEvent(EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME,
   1171                         userId, System.identityHashCode(this), shortComponentName,
   1172                         thisTime, totalTime);
   1173                 StringBuilder sb = service.mStringBuilder;
   1174                 sb.setLength(0);
   1175                 sb.append("Fully drawn ");
   1176                 sb.append(shortComponentName);
   1177                 sb.append(": ");
   1178                 TimeUtils.formatDuration(thisTime, sb);
   1179                 if (thisTime != totalTime) {
   1180                     sb.append(" (total ");
   1181                     TimeUtils.formatDuration(totalTime, sb);
   1182                     sb.append(")");
   1183                 }
   1184                 Log.i(TAG, sb.toString());
   1185             }
   1186             if (totalTime > 0) {
   1187                 //service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime);
   1188             }
   1189             stack.mFullyDrawnStartTime = 0;
   1190         }
   1191         fullyDrawnStartTime = 0;
   1192     }
   1193 
   1194     private void reportLaunchTimeLocked(final long curTime) {
   1195         final ActivityStack stack = task.stack;
   1196         if (stack == null) {
   1197             return;
   1198         }
   1199         final long thisTime = curTime - displayStartTime;
   1200         final long totalTime = stack.mLaunchStartTime != 0
   1201                 ? (curTime - stack.mLaunchStartTime) : thisTime;
   1202         if (SHOW_ACTIVITY_START_TIME) {
   1203             Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching: " + packageName, 0);
   1204             EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME,
   1205                     userId, System.identityHashCode(this), shortComponentName,
   1206                     thisTime, totalTime);
   1207             StringBuilder sb = service.mStringBuilder;
   1208             sb.setLength(0);
   1209             sb.append("Displayed ");
   1210             sb.append(shortComponentName);
   1211             sb.append(": ");
   1212             TimeUtils.formatDuration(thisTime, sb);
   1213             if (thisTime != totalTime) {
   1214                 sb.append(" (total ");
   1215                 TimeUtils.formatDuration(totalTime, sb);
   1216                 sb.append(")");
   1217             }
   1218             Log.i(TAG, sb.toString());
   1219         }
   1220         mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
   1221         if (totalTime > 0) {
   1222             //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
   1223         }
   1224         displayStartTime = 0;
   1225         stack.mLaunchStartTime = 0;
   1226     }
   1227 
   1228     void windowsDrawnLocked() {
   1229         mStackSupervisor.mActivityMetricsLogger.notifyWindowsDrawn();
   1230         if (displayStartTime != 0) {
   1231             reportLaunchTimeLocked(SystemClock.uptimeMillis());
   1232         }
   1233         mStackSupervisor.sendWaitingVisibleReportLocked(this);
   1234         startTime = 0;
   1235         finishLaunchTickingLocked();
   1236         if (task != null) {
   1237             task.hasBeenVisible = true;
   1238         }
   1239     }
   1240 
   1241     void windowsVisibleLocked() {
   1242         mStackSupervisor.reportActivityVisibleLocked(this);
   1243         if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "windowsVisibleLocked(): " + this);
   1244         if (!nowVisible) {
   1245             nowVisible = true;
   1246             lastVisibleTime = SystemClock.uptimeMillis();
   1247             if (!idle) {
   1248                 // Instead of doing the full stop routine here, let's just hide any activities
   1249                 // we now can, and let them stop when the normal idle happens.
   1250                 mStackSupervisor.processStoppingActivitiesLocked(false);
   1251             } else {
   1252                 // If this activity was already idle, then we now need to make sure we perform
   1253                 // the full stop of any activities that are waiting to do so. This is because
   1254                 // we won't do that while they are still waiting for this one to become visible.
   1255                 final int size = mStackSupervisor.mWaitingVisibleActivities.size();
   1256                 if (size > 0) {
   1257                     for (int i = 0; i < size; i++) {
   1258                         ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
   1259                         if (DEBUG_SWITCH) Log.v(TAG_SWITCH, "Was waiting for visible: " + r);
   1260                     }
   1261                     mStackSupervisor.mWaitingVisibleActivities.clear();
   1262                     mStackSupervisor.scheduleIdleLocked();
   1263                 }
   1264             }
   1265             service.scheduleAppGcsLocked();
   1266         }
   1267     }
   1268 
   1269     ActivityRecord getWaitingHistoryRecordLocked() {
   1270         // First find the real culprit...  if this activity is waiting for
   1271         // another activity to start or has stopped, then the key dispatching
   1272         // timeout should not be caused by this.
   1273         if (mStackSupervisor.mWaitingVisibleActivities.contains(this) || stopped) {
   1274             final ActivityStack stack = mStackSupervisor.getFocusedStack();
   1275             // Try to use the one which is closest to top.
   1276             ActivityRecord r = stack.mResumedActivity;
   1277             if (r == null) {
   1278                 r = stack.mPausingActivity;
   1279             }
   1280             if (r != null) {
   1281                 return r;
   1282             }
   1283         }
   1284         return this;
   1285     }
   1286 
   1287     /**
   1288      * This method will return true if the activity is either visible, is becoming visible, is
   1289      * currently pausing, or is resumed.
   1290      */
   1291     public boolean isInterestingToUserLocked() {
   1292         return visible || nowVisible || state == ActivityState.PAUSING ||
   1293                 state == ActivityState.RESUMED;
   1294     }
   1295 
   1296     public void setSleeping(boolean _sleeping) {
   1297         if (sleeping == _sleeping) {
   1298             return;
   1299         }
   1300         if (app != null && app.thread != null) {
   1301             try {
   1302                 app.thread.scheduleSleeping(appToken, _sleeping);
   1303                 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
   1304                     mStackSupervisor.mGoingToSleepActivities.add(this);
   1305                 }
   1306                 sleeping = _sleeping;
   1307             } catch (RemoteException e) {
   1308                 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
   1309             }
   1310         }
   1311     }
   1312 
   1313     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
   1314         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
   1315         if (r == null) {
   1316             return INVALID_TASK_ID;
   1317         }
   1318         final TaskRecord task = r.task;
   1319         final int activityNdx = task.mActivities.indexOf(r);
   1320         if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) {
   1321             return INVALID_TASK_ID;
   1322         }
   1323         return task.taskId;
   1324     }
   1325 
   1326     static ActivityRecord isInStackLocked(IBinder token) {
   1327         final ActivityRecord r = ActivityRecord.forTokenLocked(token);
   1328         return (r != null) ? r.task.stack.isInStackLocked(r) : null;
   1329     }
   1330 
   1331     static ActivityStack getStackLocked(IBinder token) {
   1332         final ActivityRecord r = ActivityRecord.isInStackLocked(token);
   1333         if (r != null) {
   1334             return r.task.stack;
   1335         }
   1336         return null;
   1337     }
   1338 
   1339     final boolean isDestroyable() {
   1340         if (finishing || app == null || state == ActivityState.DESTROYING
   1341                 || state == ActivityState.DESTROYED) {
   1342             // This would be redundant.
   1343             return false;
   1344         }
   1345         if (task == null || task.stack == null || this == task.stack.mResumedActivity
   1346                 || this == task.stack.mPausingActivity || !haveState || !stopped) {
   1347             // We're not ready for this kind of thing.
   1348             return false;
   1349         }
   1350         if (visible) {
   1351             // The user would notice this!
   1352             return false;
   1353         }
   1354         return true;
   1355     }
   1356 
   1357     private static String createImageFilename(long createTime, int taskId) {
   1358         return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
   1359                 TaskPersister.IMAGE_EXTENSION;
   1360     }
   1361 
   1362     void setTaskDescription(TaskDescription _taskDescription) {
   1363         Bitmap icon;
   1364         if (_taskDescription.getIconFilename() == null &&
   1365                 (icon = _taskDescription.getIcon()) != null) {
   1366             final String iconFilename = createImageFilename(createTime, task.taskId);
   1367             final File iconFile = new File(TaskPersister.getUserImagesDir(userId), iconFilename);
   1368             final String iconFilePath = iconFile.getAbsolutePath();
   1369             service.mRecentTasks.saveImage(icon, iconFilePath);
   1370             _taskDescription.setIconFilename(iconFilePath);
   1371         }
   1372         taskDescription = _taskDescription;
   1373     }
   1374 
   1375     void setVoiceSessionLocked(IVoiceInteractionSession session) {
   1376         voiceSession = session;
   1377         pendingVoiceInteractionStart = false;
   1378     }
   1379 
   1380     void clearVoiceSessionLocked() {
   1381         voiceSession = null;
   1382         pendingVoiceInteractionStart = false;
   1383     }
   1384 
   1385     void showStartingWindow(ActivityRecord prev, boolean createIfNeeded) {
   1386         final CompatibilityInfo compatInfo =
   1387                 service.compatibilityInfoForPackageLocked(info.applicationInfo);
   1388         final boolean shown = service.mWindowManager.setAppStartingWindow(
   1389                 appToken, packageName, theme, compatInfo, nonLocalizedLabel, labelRes, icon,
   1390                 logo, windowFlags, prev != null ? prev.appToken : null, createIfNeeded);
   1391         if (shown) {
   1392             mStartingWindowState = STARTING_WINDOW_SHOWN;
   1393         }
   1394     }
   1395 
   1396     void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
   1397         out.attribute(null, ATTR_ID, String.valueOf(createTime));
   1398         out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
   1399         if (launchedFromPackage != null) {
   1400             out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
   1401         }
   1402         if (resolvedType != null) {
   1403             out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
   1404         }
   1405         out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
   1406         out.attribute(null, ATTR_USERID, String.valueOf(userId));
   1407 
   1408         if (taskDescription != null) {
   1409             taskDescription.saveToXml(out);
   1410         }
   1411 
   1412         out.startTag(null, TAG_INTENT);
   1413         intent.saveToXml(out);
   1414         out.endTag(null, TAG_INTENT);
   1415 
   1416         if (isPersistable() && persistentState != null) {
   1417             out.startTag(null, TAG_PERSISTABLEBUNDLE);
   1418             persistentState.saveToXml(out);
   1419             out.endTag(null, TAG_PERSISTABLEBUNDLE);
   1420         }
   1421     }
   1422 
   1423     static ActivityRecord restoreFromXml(XmlPullParser in,
   1424             ActivityStackSupervisor stackSupervisor) throws IOException, XmlPullParserException {
   1425         Intent intent = null;
   1426         PersistableBundle persistentState = null;
   1427         int launchedFromUid = 0;
   1428         String launchedFromPackage = null;
   1429         String resolvedType = null;
   1430         boolean componentSpecified = false;
   1431         int userId = 0;
   1432         long createTime = -1;
   1433         final int outerDepth = in.getDepth();
   1434         TaskDescription taskDescription = new TaskDescription();
   1435 
   1436         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
   1437             final String attrName = in.getAttributeName(attrNdx);
   1438             final String attrValue = in.getAttributeValue(attrNdx);
   1439             if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
   1440                         "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
   1441             if (ATTR_ID.equals(attrName)) {
   1442                 createTime = Long.valueOf(attrValue);
   1443             } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
   1444                 launchedFromUid = Integer.parseInt(attrValue);
   1445             } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
   1446                 launchedFromPackage = attrValue;
   1447             } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
   1448                 resolvedType = attrValue;
   1449             } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
   1450                 componentSpecified = Boolean.valueOf(attrValue);
   1451             } else if (ATTR_USERID.equals(attrName)) {
   1452                 userId = Integer.parseInt(attrValue);
   1453             } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
   1454                 taskDescription.restoreFromXml(attrName, attrValue);
   1455             } else {
   1456                 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
   1457             }
   1458         }
   1459 
   1460         int event;
   1461         while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
   1462                 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
   1463             if (event == XmlPullParser.START_TAG) {
   1464                 final String name = in.getName();
   1465                 if (TaskPersister.DEBUG)
   1466                         Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
   1467                 if (TAG_INTENT.equals(name)) {
   1468                     intent = Intent.restoreFromXml(in);
   1469                     if (TaskPersister.DEBUG)
   1470                             Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
   1471                 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
   1472                     persistentState = PersistableBundle.restoreFromXml(in);
   1473                     if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG,
   1474                             "ActivityRecord: persistentState=" + persistentState);
   1475                 } else {
   1476                     Slog.w(TAG, "restoreActivity: unexpected name=" + name);
   1477                     XmlUtils.skipCurrentTag(in);
   1478                 }
   1479             }
   1480         }
   1481 
   1482         if (intent == null) {
   1483             throw new XmlPullParserException("restoreActivity error intent=" + intent);
   1484         }
   1485 
   1486         final ActivityManagerService service = stackSupervisor.mService;
   1487         final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
   1488                 userId);
   1489         if (aInfo == null) {
   1490             throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
   1491                     " resolvedType=" + resolvedType);
   1492         }
   1493         final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid,
   1494                 launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(),
   1495                 null, null, 0, componentSpecified, false, stackSupervisor, null, null, null);
   1496 
   1497         r.persistentState = persistentState;
   1498         r.taskDescription = taskDescription;
   1499         r.createTime = createTime;
   1500 
   1501         return r;
   1502     }
   1503 
   1504     private static String activityTypeToString(int type) {
   1505         switch (type) {
   1506             case APPLICATION_ACTIVITY_TYPE: return "APPLICATION_ACTIVITY_TYPE";
   1507             case HOME_ACTIVITY_TYPE: return "HOME_ACTIVITY_TYPE";
   1508             case RECENTS_ACTIVITY_TYPE: return "RECENTS_ACTIVITY_TYPE";
   1509             default: return Integer.toString(type);
   1510         }
   1511     }
   1512 
   1513     @Override
   1514     public String toString() {
   1515         if (stringName != null) {
   1516             return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) +
   1517                     (finishing ? " f}" : "}");
   1518         }
   1519         StringBuilder sb = new StringBuilder(128);
   1520         sb.append("ActivityRecord{");
   1521         sb.append(Integer.toHexString(System.identityHashCode(this)));
   1522         sb.append(" u");
   1523         sb.append(userId);
   1524         sb.append(' ');
   1525         sb.append(intent.getComponent().flattenToShortString());
   1526         stringName = sb.toString();
   1527         return toString();
   1528     }
   1529 }
   1530