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