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