ActivityRecord.java revision a228ae95ea2f842c0e84f237c64bf032689410dd
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    HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
134    UriPermissionOwner uriPermissions; // current special URI access perms.
135    ProcessRecord app;      // if non-null, hosting application
136    ActivityState state;    // current state we are in
137    Bundle  icicle;         // last saved activity state
138    PersistableBundle persistentState; // last persistently saved activity state
139    boolean frontOfTask;    // is this the root activity of its task?
140    boolean launchFailed;   // set if a launched failed, to abort on 2nd try
141    boolean haveState;      // have we gotten the last activity state?
142    boolean stopped;        // is activity pause finished?
143    boolean delayedResume;  // not yet resumed because of stopped app switches?
144    boolean finishing;      // activity in pending finish list?
145    boolean configDestroy;  // need to destroy due to config change?
146    int configChangeFlags;  // which config values have changed
147    boolean keysPaused;     // has key dispatching been paused for it?
148    int launchMode;         // the launch mode activity attribute.
149    boolean visible;        // does this activity's window need to be shown?
150    boolean sleeping;       // have we told the activity to sleep?
151    boolean waitingVisible; // true if waiting for a new act to become vis
152    boolean nowVisible;     // is this activity's window visible?
153    boolean idle;           // has the activity gone idle?
154    boolean hasBeenLaunched;// has this activity ever been launched?
155    boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
156    boolean immersive;      // immersive mode (don't interrupt if possible)
157    boolean forceNewConfig; // force re-create with new config next time
158    int launchCount;        // count of launches since last state
159    long lastLaunchTime;    // time of last lauch of this activity
160    ArrayList<ActivityContainer> mChildContainers = new ArrayList<ActivityContainer>();
161
162    String stringName;      // for caching of toString().
163
164    private boolean inHistory;  // are we in the history stack?
165    final ActivityStackSupervisor mStackSupervisor;
166    boolean mStartingWindowShown = false;
167    ActivityContainer mInitialActivityContainer;
168
169    TaskDescription taskDescription; // the recents information for this activity
170
171    void dump(PrintWriter pw, String prefix) {
172        final long now = SystemClock.uptimeMillis();
173        pw.print(prefix); pw.print("packageName="); pw.print(packageName);
174                pw.print(" processName="); pw.println(processName);
175        pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
176                pw.print(" launchedFromPackage="); pw.print(launchedFromPackage);
177                pw.print(" userId="); pw.println(userId);
178        pw.print(prefix); pw.print("app="); pw.println(app);
179        pw.print(prefix); pw.println(intent.toInsecureStringWithClip());
180        pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
181                pw.print(" task="); pw.println(task);
182        pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
183        pw.print(prefix); pw.print("realActivity=");
184                pw.println(realActivity.flattenToShortString());
185        if (appInfo != null) {
186            pw.print(prefix); pw.print("baseDir="); pw.println(appInfo.sourceDir);
187            if (!Objects.equals(appInfo.sourceDir, appInfo.publicSourceDir)) {
188                pw.print(prefix); pw.print("resDir="); pw.println(appInfo.publicSourceDir);
189            }
190            pw.print(prefix); pw.print("dataDir="); pw.println(appInfo.dataDir);
191        }
192        pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
193                pw.print(" componentSpecified="); pw.print(componentSpecified);
194                pw.print(" mActivityType="); pw.println(mActivityType);
195        pw.print(prefix); pw.print("compat="); pw.print(compat);
196                pw.print(" labelRes=0x"); pw.print(Integer.toHexString(labelRes));
197                pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
198                pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
199        pw.print(prefix); pw.print("config="); pw.println(configuration);
200        if (resultTo != null || resultWho != null) {
201            pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
202                    pw.print(" resultWho="); pw.print(resultWho);
203                    pw.print(" resultCode="); pw.println(requestCode);
204        }
205        if (taskDescription.getIcon() != null || taskDescription.getLabel() != null ||
206                taskDescription.getPrimaryColor() != 0) {
207            pw.print(prefix); pw.print("taskDescription:");
208                    pw.print(" icon="); pw.print(taskDescription.getIcon());
209                    pw.print(" label=\""); pw.print(taskDescription.getLabel()); pw.print("\"");
210                    pw.print(" color=");
211                    pw.println(Integer.toHexString(taskDescription.getPrimaryColor()));
212        }
213        if (results != null) {
214            pw.print(prefix); pw.print("results="); pw.println(results);
215        }
216        if (pendingResults != null && pendingResults.size() > 0) {
217            pw.print(prefix); pw.println("Pending Results:");
218            for (WeakReference<PendingIntentRecord> wpir : pendingResults) {
219                PendingIntentRecord pir = wpir != null ? wpir.get() : null;
220                pw.print(prefix); pw.print("  - ");
221                if (pir == null) {
222                    pw.println("null");
223                } else {
224                    pw.println(pir);
225                    pir.dump(pw, prefix + "    ");
226                }
227            }
228        }
229        if (newIntents != null && newIntents.size() > 0) {
230            pw.print(prefix); pw.println("Pending New Intents:");
231            for (int i=0; i<newIntents.size(); i++) {
232                Intent intent = newIntents.get(i);
233                pw.print(prefix); pw.print("  - ");
234                if (intent == null) {
235                    pw.println("null");
236                } else {
237                    pw.println(intent.toShortString(false, true, false, true));
238                }
239            }
240        }
241        if (pendingOptions != null) {
242            pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
243        }
244        if (uriPermissions != null) {
245            uriPermissions.dump(pw, prefix);
246        }
247        pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
248                pw.print(" launchCount="); pw.print(launchCount);
249                pw.print(" lastLaunchTime=");
250                if (lastLaunchTime == 0) pw.print("0");
251                else TimeUtils.formatDuration(lastLaunchTime, now, pw);
252                pw.println();
253        pw.print(prefix); pw.print("haveState="); pw.print(haveState);
254                pw.print(" icicle="); pw.println(icicle);
255        pw.print(prefix); pw.print("state="); pw.print(state);
256                pw.print(" stopped="); pw.print(stopped);
257                pw.print(" delayedResume="); pw.print(delayedResume);
258                pw.print(" finishing="); pw.println(finishing);
259        pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
260                pw.print(" inHistory="); pw.print(inHistory);
261                pw.print(" visible="); pw.print(visible);
262                pw.print(" sleeping="); pw.print(sleeping);
263                pw.print(" idle="); pw.println(idle);
264        pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
265                pw.print(" noDisplay="); pw.print(noDisplay);
266                pw.print(" immersive="); pw.print(immersive);
267                pw.print(" launchMode="); pw.println(launchMode);
268        pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
269                pw.print(" forceNewConfig="); pw.println(forceNewConfig);
270        pw.print(prefix); pw.print("mActivityType=");
271                pw.println(activityTypeToString(mActivityType));
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, TaskRecord taskToAffiliateWith) {
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        task = newTask;
510        setTaskToAffiliateWith(taskToAffiliateWith);
511    }
512
513    void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
514        if (taskToAffiliateWith != null &&
515                launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE &&
516                launchMode != ActivityInfo.LAUNCH_SINGLE_TASK) {
517            task.setTaskToAffiliateWith(taskToAffiliateWith);
518        }
519    }
520
521    boolean changeWindowTranslucency(boolean toOpaque) {
522        if (fullscreen == toOpaque) {
523            return false;
524        }
525
526        // Keep track of the number of fullscreen activities in this task.
527        task.numFullscreen += toOpaque ? +1 : -1;
528
529        fullscreen = toOpaque;
530        return true;
531    }
532
533    void putInHistory() {
534        if (!inHistory) {
535            inHistory = true;
536        }
537    }
538
539    void takeFromHistory() {
540        if (inHistory) {
541            inHistory = false;
542            if (task != null && !finishing) {
543                task = null;
544            }
545            clearOptionsLocked();
546        }
547    }
548
549    boolean isInHistory() {
550        return inHistory;
551    }
552
553    boolean isHomeActivity() {
554        return mActivityType == HOME_ACTIVITY_TYPE;
555    }
556
557    boolean isRecentsActivity() {
558        return mActivityType == RECENTS_ACTIVITY_TYPE;
559    }
560
561    boolean isApplicationActivity() {
562        return mActivityType == APPLICATION_ACTIVITY_TYPE;
563    }
564
565    boolean isPersistable() {
566        return (info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY ||
567                info.persistableMode == ActivityInfo.PERSIST_ACROSS_REBOOTS) &&
568                (intent == null ||
569                        (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) == 0);
570    }
571
572    void makeFinishing() {
573        if (!finishing) {
574            finishing = true;
575            if (stopped) {
576                clearOptionsLocked();
577            }
578        }
579    }
580
581    UriPermissionOwner getUriPermissionsLocked() {
582        if (uriPermissions == null) {
583            uriPermissions = new UriPermissionOwner(service, this);
584        }
585        return uriPermissions;
586    }
587
588    void addResultLocked(ActivityRecord from, String resultWho,
589            int requestCode, int resultCode,
590            Intent resultData) {
591        ActivityResult r = new ActivityResult(from, resultWho,
592                requestCode, resultCode, resultData);
593        if (results == null) {
594            results = new ArrayList<ResultInfo>();
595        }
596        results.add(r);
597    }
598
599    void removeResultsLocked(ActivityRecord from, String resultWho,
600            int requestCode) {
601        if (results != null) {
602            for (int i=results.size()-1; i>=0; i--) {
603                ActivityResult r = (ActivityResult)results.get(i);
604                if (r.mFrom != from) continue;
605                if (r.mResultWho == null) {
606                    if (resultWho != null) continue;
607                } else {
608                    if (!r.mResultWho.equals(resultWho)) continue;
609                }
610                if (r.mRequestCode != requestCode) continue;
611
612                results.remove(i);
613            }
614        }
615    }
616
617    void addNewIntentLocked(Intent intent) {
618        if (newIntents == null) {
619            newIntents = new ArrayList<Intent>();
620        }
621        newIntents.add(intent);
622    }
623
624    /**
625     * Deliver a new Intent to an existing activity, so that its onNewIntent()
626     * method will be called at the proper time.
627     */
628    final void deliverNewIntentLocked(int callingUid, Intent intent) {
629        // The activity now gets access to the data associated with this Intent.
630        service.grantUriPermissionFromIntentLocked(callingUid, packageName,
631                intent, getUriPermissionsLocked(), userId);
632        // We want to immediately deliver the intent to the activity if
633        // it is currently the top resumed activity...  however, if the
634        // device is sleeping, then all activities are stopped, so in that
635        // case we will deliver it if this is the current top activity on its
636        // stack.
637        boolean unsent = true;
638        if ((state == ActivityState.RESUMED || (service.isSleeping()
639                        && task.stack.topRunningActivityLocked(null) == this))
640                && app != null && app.thread != null) {
641            try {
642                ArrayList<Intent> ar = new ArrayList<Intent>();
643                intent = new Intent(intent);
644                ar.add(intent);
645                app.thread.scheduleNewIntent(ar, appToken);
646                unsent = false;
647            } catch (RemoteException e) {
648                Slog.w(ActivityManagerService.TAG,
649                        "Exception thrown sending new intent to " + this, e);
650            } catch (NullPointerException e) {
651                Slog.w(ActivityManagerService.TAG,
652                        "Exception thrown sending new intent to " + this, e);
653            }
654        }
655        if (unsent) {
656            addNewIntentLocked(new Intent(intent));
657        }
658    }
659
660    void updateOptionsLocked(Bundle options) {
661        if (options != null) {
662            if (pendingOptions != null) {
663                pendingOptions.abort();
664            }
665            pendingOptions = new ActivityOptions(options);
666        }
667    }
668
669    void updateOptionsLocked(ActivityOptions options) {
670        if (options != null) {
671            if (pendingOptions != null) {
672                pendingOptions.abort();
673            }
674            pendingOptions = options;
675        }
676    }
677
678    void applyOptionsLocked() {
679        if (pendingOptions != null
680                && pendingOptions.getAnimationType() != ActivityOptions.ANIM_SCENE_TRANSITION) {
681            final int animationType = pendingOptions.getAnimationType();
682            switch (animationType) {
683                case ActivityOptions.ANIM_CUSTOM:
684                    service.mWindowManager.overridePendingAppTransition(
685                            pendingOptions.getPackageName(),
686                            pendingOptions.getCustomEnterResId(),
687                            pendingOptions.getCustomExitResId(),
688                            pendingOptions.getOnAnimationStartListener());
689                    break;
690                case ActivityOptions.ANIM_SCALE_UP:
691                    service.mWindowManager.overridePendingAppTransitionScaleUp(
692                            pendingOptions.getStartX(), pendingOptions.getStartY(),
693                            pendingOptions.getStartWidth(), pendingOptions.getStartHeight());
694                    if (intent.getSourceBounds() == null) {
695                        intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
696                                pendingOptions.getStartY(),
697                                pendingOptions.getStartX()+pendingOptions.getStartWidth(),
698                                pendingOptions.getStartY()+pendingOptions.getStartHeight()));
699                    }
700                    break;
701                case ActivityOptions.ANIM_THUMBNAIL_SCALE_UP:
702                case ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN:
703                    boolean scaleUp = (animationType == ActivityOptions.ANIM_THUMBNAIL_SCALE_UP);
704                    service.mWindowManager.overridePendingAppTransitionThumb(
705                            pendingOptions.getThumbnail(),
706                            pendingOptions.getStartX(), pendingOptions.getStartY(),
707                            pendingOptions.getOnAnimationStartListener(),
708                            scaleUp);
709                    if (intent.getSourceBounds() == null) {
710                        intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
711                                pendingOptions.getStartY(),
712                                pendingOptions.getStartX()
713                                        + pendingOptions.getThumbnail().getWidth(),
714                                pendingOptions.getStartY()
715                                        + pendingOptions.getThumbnail().getHeight()));
716                    }
717                    break;
718                default:
719                    Slog.e(TAG, "applyOptionsLocked: Unknown animationType=" + animationType);
720                    break;
721            }
722            pendingOptions = null;
723        }
724    }
725
726    ActivityOptions getOptionsForTargetActivityLocked() {
727        return pendingOptions != null ? pendingOptions.forTargetActivity() : null;
728    }
729
730    void clearOptionsLocked() {
731        if (pendingOptions != null) {
732            pendingOptions.abort();
733            pendingOptions = null;
734        }
735    }
736
737    ActivityOptions takeOptionsLocked() {
738        ActivityOptions opts = pendingOptions;
739        pendingOptions = null;
740        return opts;
741    }
742
743    void removeUriPermissionsLocked() {
744        if (uriPermissions != null) {
745            uriPermissions.removeUriPermissionsLocked();
746            uriPermissions = null;
747        }
748    }
749
750    void pauseKeyDispatchingLocked() {
751        if (!keysPaused) {
752            keysPaused = true;
753            service.mWindowManager.pauseKeyDispatching(appToken);
754        }
755    }
756
757    void resumeKeyDispatchingLocked() {
758        if (keysPaused) {
759            keysPaused = false;
760            service.mWindowManager.resumeKeyDispatching(appToken);
761        }
762    }
763
764    void updateThumbnail(Bitmap newThumbnail, CharSequence description) {
765        if (newThumbnail != null) {
766            if (ActivityManagerService.DEBUG_THUMBNAILS) Slog.i(ActivityManagerService.TAG,
767                    "Setting thumbnail of " + this + " to " + newThumbnail);
768            task.setLastThumbnail(newThumbnail);
769            if (isPersistable()) {
770                mStackSupervisor.mService.notifyTaskPersisterLocked(task, false);
771            }
772        }
773        task.lastDescription = description;
774    }
775
776    void startLaunchTickingLocked() {
777        if (ActivityManagerService.IS_USER_BUILD) {
778            return;
779        }
780        if (launchTickTime == 0) {
781            launchTickTime = SystemClock.uptimeMillis();
782            continueLaunchTickingLocked();
783        }
784    }
785
786    boolean continueLaunchTickingLocked() {
787        if (launchTickTime != 0) {
788            final ActivityStack stack = task.stack;
789            Message msg = stack.mHandler.obtainMessage(ActivityStack.LAUNCH_TICK_MSG, this);
790            stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
791            stack.mHandler.sendMessageDelayed(msg, ActivityStack.LAUNCH_TICK);
792            return true;
793        }
794        return false;
795    }
796
797    void finishLaunchTickingLocked() {
798        launchTickTime = 0;
799        task.stack.mHandler.removeMessages(ActivityStack.LAUNCH_TICK_MSG);
800    }
801
802    // IApplicationToken
803
804    public boolean mayFreezeScreenLocked(ProcessRecord app) {
805        // Only freeze the screen if this activity is currently attached to
806        // an application, and that application is not blocked or unresponding.
807        // In any other case, we can't count on getting the screen unfrozen,
808        // so it is best to leave as-is.
809        return app != null && !app.crashing && !app.notResponding;
810    }
811
812    public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
813        if (mayFreezeScreenLocked(app)) {
814            service.mWindowManager.startAppFreezingScreen(appToken, configChanges);
815        }
816    }
817
818    public void stopFreezingScreenLocked(boolean force) {
819        if (force || frozenBeforeDestroy) {
820            frozenBeforeDestroy = false;
821            service.mWindowManager.stopAppFreezingScreen(appToken, force);
822        }
823    }
824
825    public void reportFullyDrawnLocked() {
826        final long curTime = SystemClock.uptimeMillis();
827        if (displayStartTime != 0) {
828            reportLaunchTimeLocked(curTime);
829        }
830        if (fullyDrawnStartTime != 0) {
831            final ActivityStack stack = task.stack;
832            final long thisTime = curTime - fullyDrawnStartTime;
833            final long totalTime = stack.mFullyDrawnStartTime != 0
834                    ? (curTime - stack.mFullyDrawnStartTime) : thisTime;
835            if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
836                Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
837                EventLog.writeEvent(EventLogTags.AM_ACTIVITY_FULLY_DRAWN_TIME,
838                        userId, System.identityHashCode(this), shortComponentName,
839                        thisTime, totalTime);
840                StringBuilder sb = service.mStringBuilder;
841                sb.setLength(0);
842                sb.append("Fully drawn ");
843                sb.append(shortComponentName);
844                sb.append(": ");
845                TimeUtils.formatDuration(thisTime, sb);
846                if (thisTime != totalTime) {
847                    sb.append(" (total ");
848                    TimeUtils.formatDuration(totalTime, sb);
849                    sb.append(")");
850                }
851                Log.i(ActivityManagerService.TAG, sb.toString());
852            }
853            if (totalTime > 0) {
854                service.mUsageStatsService.noteFullyDrawnTime(realActivity, (int) totalTime);
855            }
856            fullyDrawnStartTime = 0;
857            stack.mFullyDrawnStartTime = 0;
858        }
859    }
860
861    private void reportLaunchTimeLocked(final long curTime) {
862        final ActivityStack stack = task.stack;
863        final long thisTime = curTime - displayStartTime;
864        final long totalTime = stack.mLaunchStartTime != 0
865                ? (curTime - stack.mLaunchStartTime) : thisTime;
866        if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
867            Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching", 0);
868            EventLog.writeEvent(EventLogTags.AM_ACTIVITY_LAUNCH_TIME,
869                    userId, System.identityHashCode(this), shortComponentName,
870                    thisTime, totalTime);
871            StringBuilder sb = service.mStringBuilder;
872            sb.setLength(0);
873            sb.append("Displayed ");
874            sb.append(shortComponentName);
875            sb.append(": ");
876            TimeUtils.formatDuration(thisTime, sb);
877            if (thisTime != totalTime) {
878                sb.append(" (total ");
879                TimeUtils.formatDuration(totalTime, sb);
880                sb.append(")");
881            }
882            Log.i(ActivityManagerService.TAG, sb.toString());
883        }
884        mStackSupervisor.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
885        if (totalTime > 0) {
886            service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
887        }
888        displayStartTime = 0;
889        stack.mLaunchStartTime = 0;
890    }
891
892    public void windowsDrawn() {
893        synchronized(service) {
894            if (displayStartTime != 0) {
895                reportLaunchTimeLocked(SystemClock.uptimeMillis());
896            }
897            startTime = 0;
898            finishLaunchTickingLocked();
899            if (task != null) {
900                task.hasBeenVisible = true;
901            }
902        }
903    }
904
905    public void windowsVisible() {
906        synchronized(service) {
907            mStackSupervisor.reportActivityVisibleLocked(this);
908            if (ActivityManagerService.DEBUG_SWITCH) Log.v(
909                    ActivityManagerService.TAG, "windowsVisible(): " + this);
910            if (!nowVisible) {
911                nowVisible = true;
912                lastVisibleTime = SystemClock.uptimeMillis();
913                if (!idle) {
914                    // Instead of doing the full stop routine here, let's just
915                    // hide any activities we now can, and let them stop when
916                    // the normal idle happens.
917                    mStackSupervisor.processStoppingActivitiesLocked(false);
918                } else {
919                    // If this activity was already idle, then we now need to
920                    // make sure we perform the full stop of any activities
921                    // that are waiting to do so.  This is because we won't
922                    // do that while they are still waiting for this one to
923                    // become visible.
924                    final int N = mStackSupervisor.mWaitingVisibleActivities.size();
925                    if (N > 0) {
926                        for (int i=0; i<N; i++) {
927                            ActivityRecord r = mStackSupervisor.mWaitingVisibleActivities.get(i);
928                            r.waitingVisible = false;
929                            if (ActivityManagerService.DEBUG_SWITCH) Log.v(
930                                    ActivityManagerService.TAG,
931                                    "Was waiting for visible: " + r);
932                        }
933                        mStackSupervisor.mWaitingVisibleActivities.clear();
934                        mStackSupervisor.scheduleIdleLocked();
935                    }
936                }
937                service.scheduleAppGcsLocked();
938            }
939        }
940    }
941
942    public void windowsGone() {
943        if (ActivityManagerService.DEBUG_SWITCH) Log.v(
944                ActivityManagerService.TAG, "windowsGone(): " + this);
945        nowVisible = false;
946    }
947
948    private ActivityRecord getWaitingHistoryRecordLocked() {
949        // First find the real culprit...  if we are waiting
950        // for another app to start, then we have paused dispatching
951        // for this activity.
952        ActivityRecord r = this;
953        if (r.waitingVisible) {
954            final ActivityStack stack = mStackSupervisor.getFocusedStack();
955            // Hmmm, who might we be waiting for?
956            r = stack.mResumedActivity;
957            if (r == null) {
958                r = stack.mPausingActivity;
959            }
960            // Both of those null?  Fall back to 'this' again
961            if (r == null) {
962                r = this;
963            }
964        }
965
966        return r;
967    }
968
969    public boolean keyDispatchingTimedOut(String reason) {
970        ActivityRecord r;
971        ProcessRecord anrApp;
972        synchronized(service) {
973            r = getWaitingHistoryRecordLocked();
974            anrApp = r != null ? r.app : null;
975        }
976        return service.inputDispatchingTimedOut(anrApp, r, this, false, reason);
977    }
978
979    /** Returns the key dispatching timeout for this application token. */
980    public long getKeyDispatchingTimeout() {
981        synchronized(service) {
982            ActivityRecord r = getWaitingHistoryRecordLocked();
983            return ActivityManagerService.getInputDispatchingTimeoutLocked(r);
984        }
985    }
986
987    /**
988     * This method will return true if the activity is either visible, is becoming visible, is
989     * currently pausing, or is resumed.
990     */
991    public boolean isInterestingToUserLocked() {
992        return visible || nowVisible || state == ActivityState.PAUSING ||
993                state == ActivityState.RESUMED;
994    }
995
996    public void setSleeping(boolean _sleeping) {
997        if (sleeping == _sleeping) {
998            return;
999        }
1000        if (app != null && app.thread != null) {
1001            try {
1002                app.thread.scheduleSleeping(appToken, _sleeping);
1003                if (_sleeping && !mStackSupervisor.mGoingToSleepActivities.contains(this)) {
1004                    mStackSupervisor.mGoingToSleepActivities.add(this);
1005                }
1006                sleeping = _sleeping;
1007            } catch (RemoteException e) {
1008                Slog.w(TAG, "Exception thrown when sleeping: " + intent.getComponent(), e);
1009            }
1010        }
1011    }
1012
1013    static void activityResumedLocked(IBinder token) {
1014        final ActivityRecord r = ActivityRecord.forToken(token);
1015        if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; dropping state of: " + r);
1016        r.icicle = null;
1017        r.haveState = false;
1018    }
1019
1020    static int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
1021        final ActivityRecord r = ActivityRecord.forToken(token);
1022        if (r == null) {
1023            return -1;
1024        }
1025        final TaskRecord task = r.task;
1026        final int activityNdx = task.mActivities.indexOf(r);
1027        if (activityNdx < 0 || (onlyRoot && activityNdx > task.findEffectiveRootIndex())) {
1028            return -1;
1029        }
1030        return task.taskId;
1031    }
1032
1033    static ActivityRecord isInStackLocked(IBinder token) {
1034        final ActivityRecord r = ActivityRecord.forToken(token);
1035        if (r != null) {
1036            return r.task.stack.isInStackLocked(token);
1037        }
1038        return null;
1039    }
1040
1041    static ActivityStack getStackLocked(IBinder token) {
1042        final ActivityRecord r = ActivityRecord.isInStackLocked(token);
1043        if (r != null) {
1044            return r.task.stack;
1045        }
1046        return null;
1047    }
1048
1049    private static String createImageFilename(ActivityRecord r, int taskId) {
1050        return String.valueOf(taskId) + ACTIVITY_ICON_SUFFIX + r.createTime +
1051                TaskPersister.IMAGE_EXTENSION;
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            task.saveTaskDescription(taskDescription, createImageFilename(this, task.taskId),
1068                    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 (TaskRecord.readTaskDescriptionAttribute(taskDescription, attrName,
1113                    attrValue)) {
1114                // Completed in TaskRecord.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(createImageFilename(r, taskId)));
1161        }
1162        r.taskDescription = taskDescription;
1163        r.createTime = createTime;
1164
1165        return r;
1166    }
1167
1168    private static String activityTypeToString(int type) {
1169        switch (type) {
1170            case APPLICATION_ACTIVITY_TYPE: return "APPLICATION_ACTIVITY_TYPE";
1171            case HOME_ACTIVITY_TYPE: return "HOME_ACTIVITY_TYPE";
1172            case RECENTS_ACTIVITY_TYPE: return "RECENTS_ACTIVITY_TYPE";
1173            default: return Integer.toString(type);
1174        }
1175    }
1176
1177    @Override
1178    public String toString() {
1179        if (stringName != null) {
1180            return stringName + " t" + (task == null ? -1 : task.taskId) +
1181                    (finishing ? " f}" : "}");
1182        }
1183        StringBuilder sb = new StringBuilder(128);
1184        sb.append("ActivityRecord{");
1185        sb.append(Integer.toHexString(System.identityHashCode(this)));
1186        sb.append(" u");
1187        sb.append(userId);
1188        sb.append(' ');
1189        sb.append(intent.getComponent().flattenToShortString());
1190        stringName = sb.toString();
1191        return toString();
1192    }
1193}
1194