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