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