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 com.android.server.am.TaskPersister.DEBUG_PERSISTER;
     20 import static com.android.server.am.TaskPersister.DEBUG_RESTORER;
     21 import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
     22 
     23 import android.app.ActivityManager.TaskDescription;
     24 import android.os.PersistableBundle;
     25 import android.os.Trace;
     26 
     27 import com.android.internal.app.ResolverActivity;
     28 import com.android.internal.content.ReferrerIntent;
     29 import com.android.internal.util.XmlUtils;
     30 import com.android.server.AttributeCache;
     31 import com.android.server.am.ActivityStack.ActivityState;
     32 import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
     33 
     34 import android.app.ActivityOptions;
     35 import android.app.ResultInfo;
     36 import android.content.ComponentName;
     37 import android.content.Intent;
     38 import android.content.pm.ActivityInfo;
     39 import android.content.pm.ApplicationInfo;
     40 import android.content.res.CompatibilityInfo;
     41 import android.content.res.Configuration;
     42 import android.graphics.Bitmap;
     43 import android.graphics.Rect;
     44 import android.os.Build;
     45 import android.os.Bundle;
     46 import android.os.IBinder;
     47 import android.os.Message;
     48 import android.os.Process;
     49 import android.os.RemoteException;
     50 import android.os.SystemClock;
     51 import android.os.UserHandle;
     52 import android.util.EventLog;
     53 import android.util.Log;
     54 import android.util.Slog;
     55 import android.util.TimeUtils;
     56 import android.view.IApplicationToken;
     57 import android.view.WindowManager;
     58 
     59 import org.xmlpull.v1.XmlPullParser;
     60 import org.xmlpull.v1.XmlPullParserException;
     61 import org.xmlpull.v1.XmlSerializer;
     62 
     63 import java.io.IOException;
     64 import java.io.PrintWriter;
     65 import java.lang.ref.WeakReference;
     66 import java.util.ArrayList;
     67 import java.util.HashSet;
     68 import java.util.Objects;
     69 
     70 /**
     71  * An entry in the history stack, representing an activity.
     72  */
     73 final class ActivityRecord {
     74     static final String TAG = ActivityManagerService.TAG;
     75     static final boolean DEBUG_SAVED_STATE = ActivityStackSupervisor.DEBUG_SAVED_STATE;
     76     final public static String RECENTS_PACKAGE_NAME = "com.android.systemui.recents";
     77 
     78     private static final String TAG_ACTIVITY = "activity";
     79     private static final String ATTR_ID = "id";
     80     private static final String TAG_INTENT = "intent";
     81     private static final String ATTR_USERID = "user_id";
     82     private static final String TAG_PERSISTABLEBUNDLE = "persistable_bundle";
     83     private static final String ATTR_LAUNCHEDFROMUID = "launched_from_uid";
     84     static final String ATTR_LAUNCHEDFROMPACKAGE = "launched_from_package";
     85     private static final String ATTR_RESOLVEDTYPE = "resolved_type";
     86     private static final String ATTR_COMPONENTSPECIFIED = "component_specified";
     87     static final String ACTIVITY_ICON_SUFFIX = "_activity_icon_";
     88 
     89     final ActivityManagerService service; // owner
     90     final IApplicationToken.Stub appToken; // window manager token
     91     final ActivityInfo info; // all about me
     92     final ApplicationInfo appInfo; // information about activity's app
     93     int launchedFromUid; // always the uid who started the activity.
     94     final String launchedFromPackage; // always the package who started the activity.
     95     final int userId;          // Which user is this running for?
     96     final Intent intent;    // the original intent that generated us
     97     final ComponentName realActivity;  // the intent component, or target of an alias.
     98     final String shortComponentName; // the short component name of the intent
     99     final String resolvedType; // as per original caller;
    100     final String packageName; // the package implementing intent's component
    101     final String processName; // process where this component wants to run
    102     final String taskAffinity; // as per ActivityInfo.taskAffinity
    103     final boolean stateNotNeeded; // As per ActivityInfo.flags
    104     boolean fullscreen; // covers the full screen?
    105     final boolean noDisplay;  // activity is not displayed?
    106     final boolean componentSpecified;  // did caller specifiy an explicit component?
    107 
    108     static final int APPLICATION_ACTIVITY_TYPE = 0;
    109     static final int HOME_ACTIVITY_TYPE = 1;
    110     static final int RECENTS_ACTIVITY_TYPE = 2;
    111     int mActivityType;
    112 
    113     CharSequence nonLocalizedLabel;  // the label information from the package mgr.
    114     int labelRes;           // the label information from the package mgr.
    115     int icon;               // resource identifier of activity's icon.
    116     int logo;               // resource identifier of activity's logo.
    117     int theme;              // resource identifier of activity's theme.
    118     int realTheme;          // actual theme resource we will use, never 0.
    119     int windowFlags;        // custom window flags for preview window.
    120     TaskRecord task;        // the task this is in.
    121     long createTime = System.currentTimeMillis();
    122     long displayStartTime;  // when we started launching this activity
    123     long fullyDrawnStartTime; // when we started launching this activity
    124     long startTime;         // last time this activity was started
    125     long lastVisibleTime;   // last time this activity became visible
    126     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
    127     long pauseTime;         // last time we started pausing the activity
    128     long launchTickTime;    // base time for launch tick messages
    129     Configuration configuration; // configuration activity was last running in
    130     CompatibilityInfo compat;// last used compatibility mode
    131     ActivityRecord resultTo; // who started this entry, so will get our reply
    132     final String resultWho; // additional identifier for use by resultTo.
    133     final int requestCode;  // code given by requester (resultTo)
    134     ArrayList<ResultInfo> results; // pending ActivityResult objs we have received
    135     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
    136     ArrayList<ReferrerIntent> newIntents; // any pending new intents for single-top mode
    137     ActivityOptions pendingOptions; // most recently given options
    138     ActivityOptions returningOptions; // options that are coming back via convertToTranslucent
    139     HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
    140     UriPermissionOwner uriPermissions; // current special URI access perms.
    141     ProcessRecord app;      // if non-null, hosting application
    142     ActivityState state;    // current state we are in
    143     Bundle  icicle;         // last saved activity state
    144     PersistableBundle persistentState; // last persistently saved activity state
    145     boolean frontOfTask;    // is this the root activity of its task?
    146     boolean launchFailed;   // set if a launched failed, to abort on 2nd try
    147     boolean haveState;      // have we gotten the last activity state?
    148     boolean stopped;        // is activity pause finished?
    149     boolean delayedResume;  // not yet resumed because of stopped app switches?
    150     boolean finishing;      // activity in pending finish list?
    151     boolean configDestroy;  // need to destroy due to config change?
    152     int configChangeFlags;  // which config values have changed
    153     boolean keysPaused;     // has key dispatching been paused for it?
    154     int launchMode;         // the launch mode activity attribute.
    155     boolean visible;        // does this activity's window need to be shown?
    156     boolean sleeping;       // have we told the activity to sleep?
    157     boolean waitingVisible; // true if waiting for a new act to become vis
    158     boolean nowVisible;     // is this activity's window visible?
    159     boolean idle;           // has the activity gone idle?
    160     boolean hasBeenLaunched;// has this activity ever been launched?
    161     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
    162     boolean immersive;      // immersive mode (don't interrupt if possible)
    163     boolean forceNewConfig; // force re-create with new config next time
    164     int launchCount;        // count of launches since last state
    165     long lastLaunchTime;    // time of last lauch of this activity
    166     ArrayList<ActivityContainer> mChildContainers = new ArrayList<ActivityContainer>();
    167 
    168     String stringName;      // for caching of toString().
    169 
    170     private boolean inHistory;  // are we in the history stack?
    171     final ActivityStackSupervisor mStackSupervisor;
    172     boolean mStartingWindowShown = false;
    173     ActivityContainer mInitialActivityContainer;
    174 
    175     TaskDescription taskDescription; // the recents information for this activity
    176     boolean mLaunchTaskBehind; // this activity is actively being launched with
    177         // ActivityOptions.setLaunchTaskBehind, will be cleared once launch is completed.
    178 
    179     void dump(PrintWriter pw, String prefix) {
    180         final long now = SystemClock.uptimeMillis();
    181         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
    182                 pw.print(" processName="); pw.println(processName);
    183         pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
    184                 pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
    185                 pw.print(" userId="); pw.println(userId);
    186         pw.print(prefix); pw.print("app="); pw.println(app);
    187         pw.print(prefix); pw.println(intent.toInsecureStringWithClip());
    188         pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
    189                 pw.print(" task="); pw.println(task);
    190         pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
    191         pw.print(prefix); pw.print("realActivity=");
    192                 pw.println(realActivity.flattenToShortString());
    193         if (appInfo != null) {
    194             pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
    195             if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
    196                 pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
    197             }
    198             pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
    199         }
    200         pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
    201                 pw.print(" componentSpecified="); pw.print(componentSpecified);
    202                 pw.print(" mActivityType="); pw.println(mActivityType);
    203         pw.print(prefix); pw.print("compat="); pw.print(compat);
    204                 pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
    205                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
    206                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
    207         pw.print(prefix); pw.print("config="); pw.println(configuration);
    208         if (resultTo != null || resultWho != null) {
    209             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
    210                     pw.print(" resultWho="); pw.print(resultWho);
    211                     pw.print(" resultCode="); pw.println(requestCode);
    212         }
    213         if (taskDescription != null) {
    214             final String iconFilename = taskDescription.getIconFilename();
    215             if (iconFilename != null || taskDescription.getLabel() != null ||
    216                     taskDescription.getPrimaryColor() != 0) {
    217                 pw.print(prefix); pw.print("taskDescription:");
    218                         pw.print(" iconFilename="); pw.print(taskDescription.getIconFilename());
    219                         pw.print(" label=\""); pw.print(taskDescription.getLabel());
    220                                 pw.print("\"");
    221                         pw.print(" color=");
    222                         pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
    223             }
    224             if (iconFilename == null && taskDescription.getIcon() != null) {
    225                 pw.print(prefix); pw.println("taskDescription contains Bitmap");
    226             }
    227         }
    228         if (results != null) {
    229             pw.print(prefix); pw.print("results="); pw.println(results);
    230         }
    231         if (pendingResults != null && pendingResults.size() > 0) {
    232             pw.print(prefix); pw.println("Pending Results:");
    233             for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
    234                 PendingIntentRecord pir = wpir != null ? wpir.get() : null;
    235                 pw.print(prefix); pw.print("  - ");
    236                 if (pir == null) {
    237                     pw.println("null");
    238                 } else {
    239                     pw.println(pir);
    240                     pir.dump(pw, prefix + "    ");
    241                 }
    242             }
    243         }
    244         if (newIntents != null && newIntents.size() > 0) {
    245             pw.print(prefix); pw.println("Pending New Intents:");
    246             for (int i=0; i<newIntents.size(); i++) {
    247                 Intent intent = newIntents.get(i);
    248                 pw.print(prefix); pw.print("  - ");
    249                 if (intent == null) {
    250                     pw.println("null");
    251                 } else {
    252                     pw.println(intent.toShortString(false, true, false, true));
    253                 }
    254             }
    255         }
    256         if (pendingOptions != null) {
    257             pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
    258         }
    259         if (uriPermissions != null) {
    260             uriPermissions.dump(pw, prefix);
    261         }
    262         pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
    263                 pw.print(" launchCount="); pw.print(launchCount);
    264                 pw.print(" lastLaunchTime=");
    265                 if (lastLaunchTime == 0) pw.print("0");
    266                 else TimeUtils.formatDuration(lastLaunchTime, now, pw);
    267                 pw.println();
    268         pw.print(prefix); pw.print("haveState="); pw.print(haveState);
    269                 pw.print(" icicle="); pw.println(icicle);
    270         pw.print(prefix); pw.print("state="); pw.print(state);
    271                 pw.print(" stopped="); pw.print(stopped);
    272                 pw.print(" delayedResume="); pw.print(delayedResume);
    273                 pw.print(" finishing="); pw.println(finishing);
    274         pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
    275                 pw.print(" inHistory="); pw.print(inHistory);
    276                 pw.print(" visible="); pw.print(visible);
    277                 pw.print(" sleeping="); pw.print(sleeping);
    278                 pw.print(" idle="); pw.println(idle);
    279         pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
    280                 pw.print(" noDisplay="); pw.print(noDisplay);
    281                 pw.print(" immersive="); pw.print(immersive);
    282                 pw.print(" launchMode="); pw.println(launchMode);
    283         pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
    284                 pw.print(" forceNewConfig="); pw.println(forceNewConfig);
    285         pw.print(prefix); pw.print("mActivityType=");
    286                 pw.println(activityTypeToString(mActivityType));
    287         if (displayStartTime != 0 || startTime != 0) {
    288             pw.print(prefix); pw.print("displayStartTime=");
    289                     if (displayStartTime == 0) pw.print("0");
    290                     else TimeUtils.formatDuration(displayStartTime, now, pw);
    291                     pw.print(" startTime=");
    292                     if (startTime == 0) pw.print("0");
    293                     else TimeUtils.formatDuration(startTime, now, pw);
    294                     pw.println();
    295         }
    296         if (lastVisibleTime != 0 || waitingVisible || nowVisible) {
    297             pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
    298                     pw.print(" nowVisible="); pw.print(nowVisible);
    299                     pw.print(" lastVisibleTime=");
    300                     if (lastVisibleTime == 0) pw.print("0");
    301                     else TimeUtils.formatDuration(lastVisibleTime, now, pw);
    302                     pw.println();
    303         }
    304         if (configDestroy || configChangeFlags != 0) {
    305             pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
    306                     pw.print(" configChangeFlags=");
    307                     pw.println(Integer.toHexString(configChangeFlags));
    308         }
    309         if (connections != null) {
    310             pw.print(prefix); pw.print("connections="); pw.println(connections);
    311         }
    312     }
    313 
    314     static class Token extends IApplicationToken.Stub {
    315         final WeakReference<ActivityRecord> weakActivity;
    316 
    317         Token(ActivityRecord activity) {
    318             weakActivity = new WeakReference<ActivityRecord>(activity);
    319         }
    320 
    321         @Override public void windowsDrawn() {
    322             ActivityRecord activity = weakActivity.get();
    323             if (activity != null) {
    324                 activity.windowsDrawn();
    325             }
    326         }
    327 
    328         @Override public void windowsVisible() {
    329             ActivityRecord activity = weakActivity.get();
    330             if (activity != null) {
    331                 activity.windowsVisible();
    332             }
    333         }
    334 
    335         @Override public void windowsGone() {
    336             ActivityRecord activity = weakActivity.get();
    337             if (activity != null) {
    338                 activity.windowsGone();
    339             }
    340         }
    341 
    342         @Override public boolean keyDispatchingTimedOut(String reason) {
    343             ActivityRecord activity = weakActivity.get();
    344             return activity != null && activity.keyDispatchingTimedOut(reason);
    345         }
    346 
    347         @Override public long getKeyDispatchingTimeout() {
    348             ActivityRecord activity = weakActivity.get();
    349             if (activity != null) {
    350                 return activity.getKeyDispatchingTimeout();
    351             }
    352             return 0;
    353         }
    354 
    355         @Override
    356         public String toString() {
    357             StringBuilder sb = new StringBuilder(128);
    358             sb.append("Token{");
    359             sb.append(Integer.toHexString(System.identityHashCode(this)));
    360             sb.append(' ');
    361             sb.append(weakActivity.get());
    362             sb.append('}');
    363             return sb.toString();
    364         }
    365     }
    366 
    367     static ActivityRecord forToken(IBinder token) {
    368         try {
    369             return token != null ? ((Token)token).weakActivity.get() : null;
    370         } catch (ClassCastException e) {
    371             Slog.w(ActivityManagerService.TAG, "Bad activity token: " + token, e);
    372             return null;
    373         }
    374     }
    375 
    376     boolean isNotResolverActivity() {
    377         return !ResolverActivity.class.getName().equals(realActivity.getClassName());
    378     }
    379 
    380     ActivityRecord(ActivityManagerService _service, ProcessRecord _caller,
    381             int _launchedFromUid, String _launchedFromPackage, Intent _intent, String _resolvedType,
    382             ActivityInfo aInfo, Configuration _configuration,
    383             ActivityRecord _resultTo, String _resultWho, int _reqCode,
    384             boolean _componentSpecified, ActivityStackSupervisor supervisor,
    385             ActivityContainer container, Bundle options) {
    386         service = _service;
    387         appToken = new Token(this);
    388         info = aInfo;
    389         launchedFromUid = _launchedFromUid;
    390         launchedFromPackage = _launchedFromPackage;
    391         userId = UserHandle.getUserId(aInfo.applicationInfo.uid);
    392         intent = _intent;
    393         shortComponentName = _intent.getComponent().flattenToShortString();
    394         resolvedType = _resolvedType;
    395         componentSpecified = _componentSpecified;
    396         configuration = _configuration;
    397         resultTo = _resultTo;
    398         resultWho = _resultWho;
    399         requestCode = _reqCode;
    400         state = ActivityState.INITIALIZING;
    401         frontOfTask = false;
    402         launchFailed = false;
    403         stopped = false;
    404         delayedResume = false;
    405         finishing = false;
    406         configDestroy = false;
    407         keysPaused = false;
    408         inHistory = false;
    409         visible = true;
    410         waitingVisible = false;
    411         nowVisible = false;
    412         idle = false;
    413         hasBeenLaunched = false;
    414         mStackSupervisor = supervisor;
    415         mInitialActivityContainer = container;
    416         if (options != null) {
    417             pendingOptions = new ActivityOptions(options);
    418             mLaunchTaskBehind = pendingOptions.getLaunchTaskBehind();
    419         }
    420 
    421         // This starts out true, since the initial state of an activity
    422         // is that we have everything, and we shouldn't never consider it
    423         // lacking in state to be removed if it dies.
    424         haveState = true;
    425 
    426         if (aInfo != null) {
    427             if (aInfo.targetActivity == null
    428                     || aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
    429                     || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
    430                 realActivity = _intent.getComponent();
    431             } else {
    432                 realActivity = new ComponentName(aInfo.packageName,
    433                         aInfo.targetActivity);
    434             }
    435             taskAffinity = aInfo.taskAffinity;
    436             stateNotNeeded = (aInfo.flags&
    437                     ActivityInfo.FLAG_STATE_NOT_NEEDED) != 0;
    438             appInfo = aInfo.applicationInfo;
    439             nonLocalizedLabel = aInfo.nonLocalizedLabel;
    440             labelRes = aInfo.labelRes;
    441             if (nonLocalizedLabel == null && labelRes == 0) {
    442                 ApplicationInfo app = aInfo.applicationInfo;
    443                 nonLocalizedLabel = app.nonLocalizedLabel;
    444                 labelRes = app.labelRes;
    445             }
    446             icon = aInfo.getIconResource();
    447             logo = aInfo.getLogoResource();
    448             theme = aInfo.getThemeResource();
    449             realTheme = theme;
    450             if (realTheme == 0) {
    451                 realTheme = aInfo.applicationInfo.targetSdkVersion
    452                         < Build.VERSION_CODES.HONEYCOMB
    453                         ? android.R.style.Theme
    454                         : android.R.style.Theme_Holo;
    455             }
    456             if ((aInfo.flags&ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0) {
    457                 windowFlags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
    458             }
    459             if ((aInfo.flags&ActivityInfo.FLAG_MULTIPROCESS) != 0
    460                     && _caller != null
    461                     && (aInfo.applicationInfo.uid == Process.SYSTEM_UID
    462                             || aInfo.applicationInfo.uid == _caller.info.uid)) {
    463                 processName = _caller.processName;
    464             } else {
    465                 processName = aInfo.processName;
    466             }
    467 
    468             if (intent != null && (aInfo.flags & ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS) != 0) {
    469                 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    470             }
    471 
    472             packageName = aInfo.applicationInfo.packageName;
    473             launchMode = aInfo.launchMode;
    474 
    475             AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
    476                     realTheme, com.android.internal.R.styleable.Window, userId);
    477             fullscreen = ent != null && !ent.array.getBoolean(
    478                     com.android.internal.R.styleable.Window_windowIsFloating, false)
    479                     && !ent.array.getBoolean(
    480                     com.android.internal.R.styleable.Window_windowIsTranslucent, false);
    481             noDisplay = ent != null && ent.array.getBoolean(
    482                     com.android.internal.R.styleable.Window_windowNoDisplay, false);
    483 
    484             if ((!_componentSpecified || _launchedFromUid == Process.myUid()
    485                     || _launchedFromUid == 0) &&
    486                     Intent.ACTION_MAIN.equals(_intent.getAction()) &&
    487                     _intent.hasCategory(Intent.CATEGORY_HOME) &&
    488                     _intent.getCategories().size() == 1 &&
    489                     _intent.getData() == null &&
    490                     _intent.getType() == null &&
    491                     (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
    492                     isNotResolverActivity()) {
    493                 // This sure looks like a home activity!
    494                 mActivityType = HOME_ACTIVITY_TYPE;
    495             } else if (realActivity.getClassName().contains(RECENTS_PACKAGE_NAME)) {
    496                 mActivityType = RECENTS_ACTIVITY_TYPE;
    497             } else {
    498                 mActivityType = APPLICATION_ACTIVITY_TYPE;
    499             }
    500 
    501             immersive = (aInfo.flags & ActivityInfo.FLAG_IMMERSIVE) != 0;
    502         } else {
    503             realActivity = null;
    504             taskAffinity = null;
    505             stateNotNeeded = false;
    506             appInfo = null;
    507             processName = null;
    508             packageName = null;
    509             fullscreen = true;
    510             noDisplay = false;
    511             mActivityType = APPLICATION_ACTIVITY_TYPE;
    512             immersive = false;
    513         }
    514     }
    515 
    516     void setTask(TaskRecord newTask, TaskRecord taskToAffiliateWith) {
    517         if (task != null && task.removeActivity(this)) {
    518             if (task != newTask) {
    519                 task.stack.removeTask(task, "setTask");
    520             } else {
    521                 Slog.d(TAG, "!!! REMOVE THIS LOG !!! setTask: nearly removed stack=" +
    522                         (newTask == null ? null : newTask.stack));
    523             }
    524         }
    525         task = newTask;
    526         setTaskToAffiliateWith(taskToAffiliateWith);
    527     }
    528 
    529     void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
    530         if (taskToAffiliateWith != null &&
    531                 launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE &&
    532                 launchMode != ActivityInfo.LAUNCH_SINGLE_TASK) {
    533             task.setTaskToAffiliateWith(taskToAffiliateWith);
    534         }
    535     }
    536 
    537     boolean changeWindowTranslucency(boolean toOpaque) {
    538         if (fullscreen == toOpaque) {
    539             return false;
    540         }
    541 
    542         // Keep track of the number of fullscreen activities in this task.
    543         task.numFullscreen += toOpaque ? +1 : -1;
    544 
    545         fullscreen = toOpaque;
    546         return true;
    547     }
    548 
    549     void putInHistory() {
    550         if (!inHistory) {
    551             inHistory = true;
    552         }
    553     }
    554 
    555     void takeFromHistory() {
    556         if (inHistory) {
    557             inHistory = false;
    558             if (task != null && !finishing) {
    559                 task = null;
    560             }
    561             clearOptionsLocked();
    562         }
    563     }
    564 
    565     boolean isInHistory() {
    566         return inHistory;
    567     }
    568 
    569     boolean isHomeActivity() {
    570         return mActivityType == HOME_ACTIVITY_TYPE;
    571     }
    572 
    573     boolean isRecentsActivity() {
    574         return mActivityType == RECENTS_ACTIVITY_TYPE;
    575     }
    576 
    577     boolean isApplicationActivity() {
    578         return mActivityType == APPLICATION_ACTIVITY_TYPE;
    579     }
    580 
    581     boolean isPersistable() {
    582         return (info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY ||
    583                 info.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS) &&
    584                 (intent == null ||
    585                         (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
    586     }
    587 
    588     void makeFinishing() {
    589         if (!finishing) {
    590             if (this == task.stack.getVisibleBehindActivity()) {
    591                 // A finishing activity should not remain as visible in the background
    592                 mStackSupervisor.requestVisibleBehindLocked(this, false);
    593             }
    594             finishing = true;
    595             if (stopped) {
    596                 clearOptionsLocked();
    597             }
    598         }
    599     }
    600 
    601     UriPermissionOwner getUriPermissionsLocked() {
    602         if (uriPermissions == null) {
    603             uriPermissions = new UriPermissionOwner(service, this);
    604         }
    605         return uriPermissions;
    606     }
    607 
    608     void addResultLocked(ActivityRecord from, String resultWho,
    609             int requestCode, int resultCode,
    610             Intent resultData) {
    611         ActivityResult r = new ActivityResult(from, resultWho,
    612                 requestCode, resultCode, resultData);
    613         if (results == null) {
    614             results = new ArrayList<ResultInfo>();
    615         }
    616         results.add(r);
    617     }
    618 
    619     void removeResultsLocked(ActivityRecord from, String resultWho,
    620             int requestCode) {
    621         if (results != null) {
    622             for (int i=results.size()-1; i>=0; i--) {
    623                 ActivityResult r = (ActivityResult)results.get(i);
    624                 if (r.mFrom != from) continue;
    625                 if (r.mResultWho == null) {
    626                     if (resultWho != null) continue;
    627                 } else {
    628                     if (!r.mResultWho.equals(resultWho)) continue;
    629                 }
    630                 if (r.mRequestCode != requestCode) continue;
    631 
    632                 results.remove(i);
    633             }
    634         }
    635     }
    636 
    637     void addNewIntentLocked(ReferrerIntent intent) {
    638         if (newIntents == null) {
    639             newIntents = new ArrayList<>();
    640         }
    641         newIntents.add(intent);
    642     }
    643 
    644     /**
    645      * Deliver a new Intent to an existing activity, so that its onNewIntent()
    646      * method will be called at the proper time.
    647      */
    648     final void deliverNewIntentLocked(int callingUid, Intent intent, String referrer) {
    649         // The activity now gets access to the data associated with this Intent.
    650         service.grantUriPermissionFromIntentLocked(callingUid, packageName,
    651                 intent, getUriPermissionsLocked(), userId);
    652         // We want to immediately deliver the intent to the activity if
    653         // it is currently the top resumed activity...  however, if the
    654         // device is sleeping, then all activities are stopped, so in that
    655         // case we will deliver it if this is the current top activity on its
    656         // stack.
    657         final ReferrerIntent rintent = new ReferrerIntent(intent, referrer);
    658         boolean unsent = true;
    659         if ((state == ActivityState.RESUMED || (service.isSleeping()
    660                         && task.stack.topRunningActivityLocked(null) == this))
    661                 && app != null && app.thread != null) {
    662             try {
    663                 ArrayList<ReferrerIntent> ar = new ArrayList<>(1);
    664                 ar.add(rintent);
    665                 app.thread.scheduleNewIntent(ar, appToken);
    666                 unsent = false;
    667             } catch (RemoteException e) {
    668                 Slog.w(ActivityManagerService.TAG,
    669                         "Exception thrown sending new intent to " + this, e);
    670             } catch (NullPointerException e) {
    671                 Slog.w(ActivityManagerService.TAG,
    672                         "Exception thrown sending new intent to " + this, e);
    673             }
    674         }
    675         if (unsent) {
    676             addNewIntentLocked(rintent);
    677         }
    678     }
    679 
    680     void updateOptionsLocked(Bundle options) {
    681         if (options != null) {
    682             if (pendingOptions != null) {
    683                 pendingOptions.abort();
    684             }
    685             pendingOptions = new ActivityOptions(options);
    686         }
    687     }
    688 
    689     void updateOptionsLocked(ActivityOptions options) {
    690         if (options != null) {
    691             if (pendingOptions != null) {
    692                 pendingOptions.abort();
    693             }
    694             pendingOptions = options;
    695         }
    696     }
    697 
    698     void applyOptionsLocked() {
    699         if (pendingOptions != null
    700                 && pendingOptions.getAnimationType() != ActivityOptions.ANIM_SCENE_TRANSITION) {
    701             final int animationType = pendingOptions.getAnimationType();
    702             switch (animationType) {
    703                 case ActivityOptions.ANIM_CUSTOM:
    704                     service.mWindowManager.overridePendingAppTransition(
    705                             pendingOptions.getPackageName(),
    706                             pendingOptions.getCustomEnterResId(),
    707                             pendingOptions.getCustomExitResId(),
    708                             pendingOptions.getOnAnimationStartListener());
    709                     break;
    710                 case ActivityOptions.ANIM_SCALE_UP:
    711                     service.mWindowManager.overridePendingAppTransitionScaleUp(
    712                             pendingOptions.getStartX(), pendingOptions.getStartY(),
    713                             pendingOptions.getWidth(), pendingOptions.getHeight());
    714                     if (intent.getSourceBounds() == null) {
    715                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
    716                                 pendingOptions.getStartY(),
    717                                 pendingOptions.getStartX()+pendingOptions.getWidth(),
    718                                 pendingOptions.getStartY()+pendingOptions.getHeight()));
    719                     }
    720                     break;
    721                 case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
    722                 case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
    723                     boolean scaleUp = (animationType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
    724                     service.mWindowManager.overridePendingAppTransitionThumb(
    725                             pendingOptions.getThumbnail(),
    726                             pendingOptions.getStartX(), pendingOptions.getStartY(),
    727                             pendingOptions.getOnAnimationStartListener(),
    728                             scaleUp);
    729                     if (intent.getSourceBounds() == null) {
    730                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
    731                                 pendingOptions.getStartY(),
    732                                 pendingOptions.getStartX()
    733                                         + pendingOptions.getThumbnail().getWidth(),
    734                                 pendingOptions.getStartY()
    735                                         + pendingOptions.getThumbnail().getHeight()));
    736                     }
    737                     break;
    738                 case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP:
    739                 case ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
    740                     service.mWindowManager.overridePendingAppTransitionAspectScaledThumb(
    741                             pendingOptions.getThumbnail(),
    742                             pendingOptions.getStartX(), pendingOptions.getStartY(),
    743                             pendingOptions.getWidth(), pendingOptions.getHeight(),
    744                             pendingOptions.getOnAnimationStartListener(),
    745                             (animationType == ActivityOptions.ANIM_THUMBNAIL_ASPECT_SCALE_UP));
    746                     if (intent.getSourceBounds() == null) {
    747                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
    748                                 pendingOptions.getStartY(),
    749                                 pendingOptions.getStartX() + pendingOptions.getWidth(),
    750                                 pendingOptions.getStartY() + pendingOptions.getHeight()));
    751                     }
    752                     break;
    753                 default:
    754                     Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType);
    755                     break;
    756             }
    757             pendingOptions = null;
    758         }
    759     }
    760 
    761     ActivityOptions getOptionsForTargetActivityLocked() {
    762         return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
    763     }
    764 
    765     void clearOptionsLocked() {
    766         if (pendingOptions != null) {
    767             pendingOptions.abort();
    768             pendingOptions = null;
    769         }
    770     }
    771 
    772     ActivityOptions takeOptionsLocked() {
    773         ActivityOptions opts = pendingOptions;
    774         pendingOptions = null;
    775         return opts;
    776     }
    777 
    778     void removeUriPermissionsLocked() {
    779         if (uriPermissions != null) {
    780             uriPermissions.removeUriPermissionsLocked();
    781             uriPermissions = null;
    782         }
    783     }
    784 
    785     void pauseKeyDispatchingLocked() {
    786         if (!keysPaused) {
    787             keysPaused = true;
    788             service.mWindowManager.pauseKeyDispatching(appToken);
    789         }
    790     }
    791 
    792     void resumeKeyDispatchingLocked() {
    793         if (keysPaused) {
    794             keysPaused = false;
    795             service.mWindowManager.resumeKeyDispatching(appToken);
    796         }
    797     }
    798 
    799     void updateThumbnailLocked(Bitmap newThumbnail, CharSequence description) {
    800         if (newThumbnail != null) {
    801             if (ActivityManagerService.DEBUG_THUMBNAILS) Slog.i(ActivityManagerService.TAG,
    802                     "Setting thumbnail of " + this + " to " + newThumbnail);
    803             boolean thumbnailUpdated = task.setLastThumbnail(newThumbnail);
    804             if (thumbnailUpdated && isPersistable()) {
    805                 mStackSupervisor.mService.notifyTaskPersisterLocked(task, false);
    806             }
    807         }
    808         task.lastDescription = description;
    809     }
    810 
    811     void startLaunchTickingLocked() {
    812         if (ActivityManagerService.IS_USER_BUILD) {
    813             return;
    814         }
    815         if (launchTickTime == 0) {
    816             launchTickTime = SystemClock.uptimeMillis();
    817             continueLaunchTickingLocked();
    818         }
    819     }
    820 
    821     boolean continueLaunchTickingLocked() {
    822         if (launchTickTime != 0) {
    823             final ActivityStack stack = task.stack;
    824             Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG, this);
    825             stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
    826             stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
    827             return true;
    828         }
    829         return false;
    830     }
    831 
    832     void finishLaunchTickingLocked() {
    833         launchTickTime = 0;
    834         task.stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
    835     }
    836 
    837     // IApplicationToken
    838 
    839     public boolean mayFreezeScreenLocked(ProcessRecord app) {
    840         // Only freeze the screen if this activity is currently attached to
    841         // an application, and that application is not blocked or unresponding.
    842         // In any other case, we can't count on getting the screen unfrozen,
    843         // so it is best to leave as-is.
    844         return app != null && !app.crashing && !app.notResponding;
    845     }
    846 
    847     public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
    848         if (mayFreezeScreenLocked(app)) {
    849             service.mWindowManager.startAppFreezingScreen(appToken, configChanges);
    850         }
    851     }
    852 
    853     public void stopFreezingScreenLocked(boolean force) {
    854         if (force || frozenBeforeDestroy) {
    855             frozenBeforeDestroy = false;
    856             service.mWindowManager.stopAppFreezingScreen(appToken, force);
    857         }
    858     }
    859 
    860     public void reportFullyDrawnLocked() {
    861         final long curTime = SystemClock.uptimeMillis();
    862         if (displayStartTime != 0) {
    863             reportLaunchTimeLocked(curTime);
    864         }
    865         if (fullyDrawnStartTime != 0) {
    866             final ActivityStack stack = task.stack;
    867             final long thisTime = curTime - fullyDrawnStartTime;
    868             final long totalTime = stack.mFullyDrawnStartTime != 0
    869                     ? (curTime - stack.mFullyDrawnStartTime) : thisTime;
    870             if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
    871                 Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
    872                 EventLog.writeEvent(EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME,
    873                         userId, System.identityHashCode(this), shortComponentName,
    874                         thisTime, totalTime);
    875                 StringBuilder sb = service.mStringBuilder;
    876                 sb.setLength(0);
    877                 sb.append("Fully drawn ");
    878                 sb.append(shortComponentName);
    879                 sb.append(": ");
    880                 TimeUtils.formatDuration(thisTime, sb);
    881                 if (thisTime != totalTime) {
    882                     sb.append(" (total ");
    883                     TimeUtils.formatDuration(totalTime, sb);
    884                     sb.append(")");
    885                 }
    886                 Log.i(ActivityManagerService.TAG, sb.toString());
    887             }
    888             if (totalTime > 0) {
    889                 //service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime);
    890             }
    891             fullyDrawnStartTime = 0;
    892             stack.mFullyDrawnStartTime = 0;
    893         }
    894     }
    895 
    896     private void reportLaunchTimeLocked(final long curTime) {
    897         final ActivityStack stack = task.stack;
    898         final long thisTime = curTime - displayStartTime;
    899         final long totalTime = stack.mLaunchStartTime != 0
    900                 ? (curTime - stack.mLaunchStartTime) : thisTime;
    901         if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
    902             Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching", 0);
    903             EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME,
    904                     userId, System.identityHashCode(this), shortComponentName,
    905                     thisTime, totalTime);
    906             StringBuilder sb = service.mStringBuilder;
    907             sb.setLength(0);
    908             sb.append("Displayed ");
    909             sb.append(shortComponentName);
    910             sb.append(": ");
    911             TimeUtils.formatDuration(thisTime, sb);
    912             if (thisTime != totalTime) {
    913                 sb.append(" (total ");
    914                 TimeUtils.formatDuration(totalTime, sb);
    915                 sb.append(")");
    916             }
    917             Log.i(ActivityManagerService.TAG, sb.toString());
    918         }
    919         mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
    920         if (totalTime > 0) {
    921             //service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
    922         }
    923         displayStartTime = 0;
    924         stack.mLaunchStartTime = 0;
    925     }
    926 
    927     public void windowsDrawn() {
    928         synchronized(service) {
    929             if (displayStartTime != 0) {
    930                 reportLaunchTimeLocked(SystemClock.uptimeMillis());
    931             }
    932             mStackSupervisor.sendWaitingVisibleReportLocked(this);
    933             startTime = 0;
    934             finishLaunchTickingLocked();
    935             if (task != null) {
    936                 task.hasBeenVisible = true;
    937             }
    938         }
    939     }
    940 
    941     public void windowsVisible() {
    942         synchronized(service) {
    943             mStackSupervisor.reportActivityVisibleLocked(this);
    944             if (ActivityManagerService.DEBUG_SWITCH) Log.v(
    945                     ActivityManagerService.TAG, "windowsVisible(): " + this);
    946             if (!nowVisible) {
    947                 nowVisible = true;
    948                 lastVisibleTime = SystemClock.uptimeMillis();
    949                 if (!idle) {
    950                     // Instead of doing the full stop routine here, let's just
    951                     // hide any activities we now can, and let them stop when
    952                     // the normal idle happens.
    953                     mStackSupervisor.processStoppingActivitiesLocked(false);
    954                 } else {
    955                     // If this activity was already idle, then we now need to
    956                     // make sure we perform the full stop of any activities
    957                     // that are waiting to do so.  This is because we won't
    958                     // do that while they are still waiting for this one to
    959                     // become visible.
    960                     final int N = mStackSupervisor.mWaitingVisibleActivities.size();
    961                     if (N > 0) {
    962                         for (int i=0; i<N; i++) {
    963                             ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
    964                             r.waitingVisible = false;
    965                             if (ActivityManagerService.DEBUG_SWITCH) Log.v(
    966                                     ActivityManagerService.TAG,
    967                                     "Was waiting for visible: " + r);
    968                         }
    969                         mStackSupervisor.mWaitingVisibleActivities.clear();
    970                         mStackSupervisor.scheduleIdleLocked();
    971                     }
    972                 }
    973                 service.scheduleAppGcsLocked();
    974             }
    975         }
    976     }
    977 
    978     public void windowsGone() {
    979         if (ActivityManagerService.DEBUG_SWITCH) Log.v(
    980                 ActivityManagerService.TAG, "windowsGone(): " + this);
    981         nowVisible = false;
    982     }
    983 
    984     private ActivityRecord getWaitingHistoryRecordLocked() {
    985         // First find the real culprit...  if we are waiting
    986         // for another app to start, then we have paused dispatching
    987         // for this activity.
    988         ActivityRecord r = this;
    989         if (r.waitingVisible) {
    990             final ActivityStack stack = mStackSupervisor.getFocusedStack();
    991             // Hmmm, who might we be waiting for?
    992             r = stack.mResumedActivity;
    993             if (r == null) {
    994                 r = stack.mPausingActivity;
    995             }
    996             // Both of those null?  Fall back to 'this' again
    997             if (r == null) {
    998                 r = this;
    999             }
   1000         }
   1001 
   1002         return r;
   1003     }
   1004 
   1005     public boolean keyDispatchingTimedOut(String reason) {
   1006         ActivityRecord r;
   1007         ProcessRecord anrApp;
   1008         synchronized(service) {
   1009             r = getWaitingHistoryRecordLocked();
   1010             anrApp = r != null ? r.app : null;
   1011         }
   1012         return service.inputDispatchingTimedOut(anrApp, r, this, false, reason);
   1013     }
   1014 
   1015     /** Returns the key dispatching timeout for this application token. */
   1016     public long getKeyDispatchingTimeout() {
   1017         synchronized(service) {
   1018             ActivityRecord r = getWaitingHistoryRecordLocked();
   1019             return ActivityManagerService.getInputDispatchingTimeoutLocked(r);
   1020         }
   1021     }
   1022 
   1023     /**
   1024      * This method will return true if the activity is either visible, is becoming visible, is
   1025      * currently pausing, or is resumed.
   1026      */
   1027     public boolean isInterestingToUserLocked() {
   1028         return visible || nowVisible || state == ActivityState.PAUSING ||
   1029                 state == ActivityState.RESUMED;
   1030     }
   1031 
   1032     public void setSleeping(boolean _sleeping) {
   1033         if (sleeping == _sleeping) {
   1034             return;
   1035         }
   1036         if (app != null && app.thread != null) {
   1037             try {
   1038                 app.thread.scheduleSleeping(appToken, _sleeping);
   1039                 if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
   1040                     mStackSupervisor.mGoingToSleepActivities.add(this);
   1041                 }
   1042                 sleeping = _sleeping;
   1043             } catch (RemoteException e) {
   1044                 Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
   1045             }
   1046         }
   1047     }
   1048 
   1049     static void activityResumedLocked(IBinder token) {
   1050         final ActivityRecord r = ActivityRecord.forToken(token);
   1051         if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; dropping state of: " + r);
   1052         r.icicle = null;
   1053         r.haveState = false;
   1054     }
   1055 
   1056     static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
   1057         final ActivityRecord r = ActivityRecord.forToken(token);
   1058         if (r == null) {
   1059             return INVALID_TASK_ID;
   1060         }
   1061         final TaskRecord task = r.task;
   1062         final int activityNdx = task.mActivities.indexOf(r);
   1063         if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) {
   1064             return INVALID_TASK_ID;
   1065         }
   1066         return task.taskId;
   1067     }
   1068 
   1069     static ActivityRecord isInStackLocked(IBinder token) {
   1070         final ActivityRecord r = ActivityRecord.forToken(token);
   1071         if (r != null) {
   1072             return r.task.stack.isInStackLocked(token);
   1073         }
   1074         return null;
   1075     }
   1076 
   1077     static ActivityStack getStackLocked(IBinder token) {
   1078         final ActivityRecord r = ActivityRecord.isInStackLocked(token);
   1079         if (r != null) {
   1080             return r.task.stack;
   1081         }
   1082         return null;
   1083     }
   1084 
   1085     final boolean isDestroyable() {
   1086         if (finishing || app == null || state == ActivityState.DESTROYING
   1087                 || state == ActivityState.DESTROYED) {
   1088             // This would be redundant.
   1089             return false;
   1090         }
   1091         if (task == null || task.stack == null || this == task.stack.mResumedActivity
   1092                 || this == task.stack.mPausingActivity || !haveState || !stopped) {
   1093             // We're not ready for this kind of thing.
   1094             return false;
   1095         }
   1096         if (visible) {
   1097             // The user would notice this!
   1098             return false;
   1099         }
   1100         return true;
   1101     }
   1102 
   1103     private static String createImageFilename(long createTime, int taskId) {
   1104         return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + createTime +
   1105                 TaskPersister.IMAGE_EXTENSION;
   1106     }
   1107 
   1108     void setTaskDescription(TaskDescription _taskDescription) {
   1109         Bitmap icon;
   1110         if (_taskDescription.getIconFilename() == null &&
   1111                 (icon = _taskDescription.getIcon()) != null) {
   1112             final String iconFilename = createImageFilename(createTime, task.taskId);
   1113             mStackSupervisor.mService.mTaskPersister.saveImage(icon, iconFilename);
   1114             _taskDescription.setIconFilename(iconFilename);
   1115         }
   1116         taskDescription = _taskDescription;
   1117     }
   1118 
   1119     void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
   1120         out.attribute(null, ATTR_ID, String.valueOf(createTime));
   1121         out.attribute(null, ATTR_LAUNCHEDFROMUID, String.valueOf(launchedFromUid));
   1122         if (launchedFromPackage != null) {
   1123             out.attribute(null, ATTR_LAUNCHEDFROMPACKAGE, launchedFromPackage);
   1124         }
   1125         if (resolvedType != null) {
   1126             out.attribute(null, ATTR_RESOLVEDTYPE, resolvedType);
   1127         }
   1128         out.attribute(null, ATTR_COMPONENTSPECIFIED, String.valueOf(componentSpecified));
   1129         out.attribute(null, ATTR_USERID, String.valueOf(userId));
   1130 
   1131         if (taskDescription != null) {
   1132             taskDescription.saveToXml(out);
   1133         }
   1134 
   1135         out.startTag(null, TAG_INTENT);
   1136         intent.saveToXml(out);
   1137         out.endTag(null, TAG_INTENT);
   1138 
   1139         if (isPersistable() && persistentState != null) {
   1140             out.startTag(null, TAG_PERSISTABLEBUNDLE);
   1141             persistentState.saveToXml(out);
   1142             out.endTag(null, TAG_PERSISTABLEBUNDLE);
   1143         }
   1144     }
   1145 
   1146     static ActivityRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
   1147             throws IOException, XmlPullParserException {
   1148         Intent intent = null;
   1149         PersistableBundle persistentState = null;
   1150         int launchedFromUid = 0;
   1151         String launchedFromPackage = null;
   1152         String resolvedType = null;
   1153         boolean componentSpecified = false;
   1154         int userId = 0;
   1155         long createTime = -1;
   1156         final int outerDepth = in.getDepth();
   1157         TaskDescription taskDescription = new TaskDescription();
   1158 
   1159         for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
   1160             final String attrName = in.getAttributeName(attrNdx);
   1161             final String attrValue = in.getAttributeValue(attrNdx);
   1162             if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
   1163                         "ActivityRecord: attribute name=" + attrName + " value=" + attrValue);
   1164             if (ATTR_ID.equals(attrName)) {
   1165                 createTime = Long.valueOf(attrValue);
   1166             } else if (ATTR_LAUNCHEDFROMUID.equals(attrName)) {
   1167                 launchedFromUid = Integer.valueOf(attrValue);
   1168             } else if (ATTR_LAUNCHEDFROMPACKAGE.equals(attrName)) {
   1169                 launchedFromPackage = attrValue;
   1170             } else if (ATTR_RESOLVEDTYPE.equals(attrName)) {
   1171                 resolvedType = attrValue;
   1172             } else if (ATTR_COMPONENTSPECIFIED.equals(attrName)) {
   1173                 componentSpecified = Boolean.valueOf(attrValue);
   1174             } else if (ATTR_USERID.equals(attrName)) {
   1175                 userId = Integer.valueOf(attrValue);
   1176             } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
   1177                 taskDescription.restoreFromXml(attrName, attrValue);
   1178             } else {
   1179                 Log.d(TAG, "Unknown ActivityRecord attribute=" + attrName);
   1180             }
   1181         }
   1182 
   1183         int event;
   1184         while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
   1185                 (event != XmlPullParser.END_TAG || in.getDepth() < outerDepth)) {
   1186             if (event == XmlPullParser.START_TAG) {
   1187                 final String name = in.getName();
   1188                 if (DEBUG_PERSISTER || DEBUG_RESTORER)
   1189                         Slog.d(TaskPersister.TAG, "ActivityRecord: START_TAG name=" + name);
   1190                 if (TAG_INTENT.equals(name)) {
   1191                     intent = Intent.restoreFromXml(in);
   1192                     if (DEBUG_PERSISTER || DEBUG_RESTORER)
   1193                             Slog.d(TaskPersister.TAG, "ActivityRecord: intent=" + intent);
   1194                 } else if (TAG_PERSISTABLEBUNDLE.equals(name)) {
   1195                     persistentState = PersistableBundle.restoreFromXml(in);
   1196                     if (DEBUG_PERSISTER || DEBUG_RESTORER) Slog.d(TaskPersister.TAG,
   1197                             "ActivityRecord: persistentState=" + persistentState);
   1198                 } else {
   1199                     Slog.w(TAG, "restoreActivity: unexpected name=" + name);
   1200                     XmlUtils.skipCurrentTag(in);
   1201                 }
   1202             }
   1203         }
   1204 
   1205         if (intent == null) {
   1206             throw new XmlPullParserException("restoreActivity error intent=" + intent);
   1207         }
   1208 
   1209         final ActivityManagerService service = stackSupervisor.mService;
   1210         final ActivityInfo aInfo = stackSupervisor.resolveActivity(intent, resolvedType, 0, null,
   1211                 userId);
   1212         if (aInfo == null) {
   1213             throw new XmlPullParserException("restoreActivity resolver error. Intent=" + intent +
   1214                     " resolvedType=" + resolvedType);
   1215         }
   1216         final ActivityRecord r = new ActivityRecord(service, /*caller*/null, launchedFromUid,
   1217                 launchedFromPackage, intent, resolvedType, aInfo, service.getConfiguration(),
   1218                 null, null, 0, componentSpecified, stackSupervisor, null, null);
   1219 
   1220         r.persistentState = persistentState;
   1221         r.taskDescription = taskDescription;
   1222         r.createTime = createTime;
   1223 
   1224         return r;
   1225     }
   1226 
   1227     private static String activityTypeToString(int type) {
   1228         switch (type) {
   1229             case APPLICATION_ACTIVITY_TYPE: return "APPLICATION_ACTIVITY_TYPE";
   1230             case HOME_ACTIVITY_TYPE: return "HOME_ACTIVITY_TYPE";
   1231             case RECENTS_ACTIVITY_TYPE: return "RECENTS_ACTIVITY_TYPE";
   1232             default: return Integer.toString(type);
   1233         }
   1234     }
   1235 
   1236     @Override
   1237     public String toString() {
   1238         if (stringName != null) {
   1239             return stringName + " t" + (task == null ? INVALID_TASK_ID : task.taskId) +
   1240                     (finishing ? " f}" : "}");
   1241         }
   1242         StringBuilder sb = new StringBuilder(128);
   1243         sb.append("ActivityRecord{");
   1244         sb.append(Integer.toHexString(System.identityHashCode(this)));
   1245         sb.append(" u");
   1246         sb.append(userId);
   1247         sb.append(' ');
   1248         sb.append(intent.getComponent().flattenToShortString());
   1249         stringName = sb.toString();
   1250         return toString();
   1251     }
   1252 }
   1253