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