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
17package com.android.server.am;
18
19import android.app.ActivityManager.TaskDescription;
20import android.os.PersistableBundle;
21import android.os.Trace;
22
23import com.android.internal.app.ResolverActivity;
24import com.android.internal.util.XmlUtils;
25import com.android.server.AttributeCache;
26import com.android.server.am.ActivityStack.ActivityState;
27import com.android.server.am.ActivityStackSupervisor.ActivityContainer;
28
29import android.app.ActivityOptions;
30import android.app.ResultInfo;
31import android.content.ComponentName;
32import android.content.Intent;
33import android.content.pm.ActivityInfo;
34import android.content.pm.ApplicationInfo;
35import android.content.res.CompatibilityInfo;
36import android.content.res.Configuration;
37import android.graphics.Bitmap;
38import android.graphics.Rect;
39import android.os.Build;
40import android.os.Bundle;
41import android.os.IBinder;
42import android.os.Message;
43import android.os.Process;
44import android.os.RemoteException;
45import android.os.SystemClock;
46import android.os.UserHandle;
47import android.util.EventLog;
48import android.util.Log;
49import android.util.Slog;
50import android.util.TimeUtils;
51import android.view.IApplicationToken;
52import android.view.WindowManager;
53
54import org.xmlpull.v1.XmlPullParser;
55import org.xmlpull.v1.XmlPullParserException;
56import org.xmlpull.v1.XmlSerializer;
57
58import java.io.IOException;
59import java.io.PrintWriter;
60import java.lang.ref.WeakReference;
61import java.util.ArrayList;
62import java.util.HashSet;
63import java.util.Objects;
64
65/**
66 * An entry in the history stack, representing an activity.
67 */
68final 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