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