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