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