Home | History | Annotate | Download | only in am
      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 
     17 package com.android.server.am;
     18 
     19 import com.android.server.AttributeCache;
     20 import com.android.server.am.ActivityStack.ActivityState;
     21 
     22 import android.app.Activity;
     23 import android.content.ComponentName;
     24 import android.content.Intent;
     25 import android.content.pm.ActivityInfo;
     26 import android.content.pm.ApplicationInfo;
     27 import android.content.res.Configuration;
     28 import android.graphics.Bitmap;
     29 import android.os.Bundle;
     30 import android.os.Message;
     31 import android.os.Process;
     32 import android.os.RemoteException;
     33 import android.os.SystemClock;
     34 import android.util.EventLog;
     35 import android.util.Log;
     36 import android.util.Slog;
     37 import android.util.TimeUtils;
     38 import android.view.IApplicationToken;
     39 
     40 import java.io.PrintWriter;
     41 import java.lang.ref.WeakReference;
     42 import java.util.ArrayList;
     43 import java.util.HashSet;
     44 
     45 /**
     46  * An entry in the history stack, representing an activity.
     47  */
     48 class ActivityRecord extends IApplicationToken.Stub {
     49     final ActivityManagerService service; // owner
     50     final ActivityStack stack; // owner
     51     final ActivityInfo info; // all about me
     52     final int launchedFromUid; // always the uid who started the activity.
     53     final Intent intent;    // the original intent that generated us
     54     final ComponentName realActivity;  // the intent component, or target of an alias.
     55     final String shortComponentName; // the short component name of the intent
     56     final String resolvedType; // as per original caller;
     57     final String packageName; // the package implementing intent's component
     58     final String processName; // process where this component wants to run
     59     final String taskAffinity; // as per ActivityInfo.taskAffinity
     60     final boolean stateNotNeeded; // As per ActivityInfo.flags
     61     final boolean fullscreen;     // covers the full screen?
     62     final boolean componentSpecified;  // did caller specifiy an explicit component?
     63     final boolean isHomeActivity; // do we consider this to be a home activity?
     64     final String baseDir;   // where activity source (resources etc) located
     65     final String resDir;   // where public activity source (public resources etc) located
     66     final String dataDir;   // where activity data should go
     67     CharSequence nonLocalizedLabel;  // the label information from the package mgr.
     68     int labelRes;           // the label information from the package mgr.
     69     int icon;               // resource identifier of activity's icon.
     70     int theme;              // resource identifier of activity's theme.
     71     TaskRecord task;        // the task this is in.
     72     long launchTime;        // when we starting launching this activity
     73     long startTime;         // last time this activity was started
     74     long cpuTimeAtResume;   // the cpu time of host process at the time of resuming activity
     75     Configuration configuration; // configuration activity was last running in
     76     ActivityRecord resultTo; // who started this entry, so will get our reply
     77     final String resultWho; // additional identifier for use by resultTo.
     78     final int requestCode;  // code given by requester (resultTo)
     79     ArrayList results;      // pending ActivityResult objs we have received
     80     HashSet<WeakReference<PendingIntentRecord>> pendingResults; // all pending intents for this act
     81     ArrayList newIntents;   // any pending new intents for single-top mode
     82     HashSet<ConnectionRecord> connections; // All ConnectionRecord we hold
     83     UriPermissionOwner uriPermissions; // current special URI access perms.
     84     ProcessRecord app;  // if non-null, hosting application
     85     Bitmap thumbnail;       // icon representation of paused screen
     86     CharSequence description; // textual description of paused screen
     87     ActivityState state;    // current state we are in
     88     Bundle  icicle;         // last saved activity state
     89     boolean frontOfTask;    // is this the root activity of its task?
     90     boolean launchFailed;   // set if a launched failed, to abort on 2nd try
     91     boolean haveState;      // have we gotten the last activity state?
     92     boolean stopped;        // is activity pause finished?
     93     boolean delayedResume;  // not yet resumed because of stopped app switches?
     94     boolean finishing;      // activity in pending finish list?
     95     boolean configDestroy;  // need to destroy due to config change?
     96     int configChangeFlags;  // which config values have changed
     97     boolean keysPaused;     // has key dispatching been paused for it?
     98     boolean inHistory;      // are we in the history stack?
     99     int launchMode;         // the launch mode activity attribute.
    100     boolean visible;        // does this activity's window need to be shown?
    101     boolean waitingVisible; // true if waiting for a new act to become vis
    102     boolean nowVisible;     // is this activity's window visible?
    103     boolean thumbnailNeeded;// has someone requested a thumbnail?
    104     boolean idle;           // has the activity gone idle?
    105     boolean hasBeenLaunched;// has this activity ever been launched?
    106     boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
    107 
    108     String stringName;      // for caching of toString().
    109 
    110     void dump(PrintWriter pw, String prefix) {
    111         pw.print(prefix); pw.print("packageName="); pw.print(packageName);
    112                 pw.print(" processName="); pw.println(processName);
    113         pw.print(prefix); pw.print("launchedFromUid="); pw.print(launchedFromUid);
    114                 pw.print(" app="); pw.println(app);
    115         pw.print(prefix); pw.println(intent);
    116         pw.print(prefix); pw.print("frontOfTask="); pw.print(frontOfTask);
    117                 pw.print(" task="); pw.println(task);
    118         pw.print(prefix); pw.print("taskAffinity="); pw.println(taskAffinity);
    119         pw.print(prefix); pw.print("realActivity=");
    120                 pw.println(realActivity.flattenToShortString());
    121         pw.print(prefix); pw.print("base="); pw.print(baseDir);
    122                 if (!resDir.equals(baseDir)) pw.print(" res="); pw.print(resDir);
    123                 pw.print(" data="); pw.println(dataDir);
    124         pw.print(prefix); pw.print("labelRes=0x");
    125                 pw.print(Integer.toHexString(labelRes));
    126                 pw.print(" icon=0x"); pw.print(Integer.toHexString(icon));
    127                 pw.print(" theme=0x"); pw.println(Integer.toHexString(theme));
    128         pw.print(prefix); pw.print("stateNotNeeded="); pw.print(stateNotNeeded);
    129                 pw.print(" componentSpecified="); pw.print(componentSpecified);
    130                 pw.print(" isHomeActivity="); pw.println(isHomeActivity);
    131         pw.print(prefix); pw.print("configuration="); pw.println(configuration);
    132         if (resultTo != null || resultWho != null) {
    133             pw.print(prefix); pw.print("resultTo="); pw.print(resultTo);
    134                     pw.print(" resultWho="); pw.print(resultWho);
    135                     pw.print(" resultCode="); pw.println(requestCode);
    136         }
    137         if (results != null) {
    138             pw.print(prefix); pw.print("results="); pw.println(results);
    139         }
    140         if (pendingResults != null) {
    141             pw.print(prefix); pw.print("pendingResults="); pw.println(pendingResults);
    142         }
    143         if (uriPermissions != null) {
    144             if (uriPermissions.readUriPermissions != null) {
    145                 pw.print(prefix); pw.print("readUriPermissions=");
    146                         pw.println(uriPermissions.readUriPermissions);
    147             }
    148             if (uriPermissions.writeUriPermissions != null) {
    149                 pw.print(prefix); pw.print("writeUriPermissions=");
    150                         pw.println(uriPermissions.writeUriPermissions);
    151             }
    152         }
    153         pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
    154                 pw.print(" haveState="); pw.print(haveState);
    155                 pw.print(" icicle="); pw.println(icicle);
    156         pw.print(prefix); pw.print("state="); pw.print(state);
    157                 pw.print(" stopped="); pw.print(stopped);
    158                 pw.print(" delayedResume="); pw.print(delayedResume);
    159                 pw.print(" finishing="); pw.println(finishing);
    160         pw.print(prefix); pw.print("keysPaused="); pw.print(keysPaused);
    161                 pw.print(" inHistory="); pw.print(inHistory);
    162                 pw.print(" launchMode="); pw.println(launchMode);
    163         pw.print(prefix); pw.print("fullscreen="); pw.print(fullscreen);
    164                 pw.print(" visible="); pw.print(visible);
    165                 pw.print(" frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
    166                 pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
    167                 pw.print(" idle="); pw.println(idle);
    168         if (launchTime != 0 || startTime != 0) {
    169             pw.print(prefix); pw.print("launchTime=");
    170                     TimeUtils.formatDuration(launchTime, pw); pw.print(" startTime=");
    171                     TimeUtils.formatDuration(startTime, pw); pw.println("");
    172         }
    173         if (waitingVisible || nowVisible) {
    174             pw.print(prefix); pw.print("waitingVisible="); pw.print(waitingVisible);
    175                     pw.print(" nowVisible="); pw.println(nowVisible);
    176         }
    177         if (configDestroy || configChangeFlags != 0) {
    178             pw.print(prefix); pw.print("configDestroy="); pw.print(configDestroy);
    179                     pw.print(" configChangeFlags=");
    180                     pw.println(Integer.toHexString(configChangeFlags));
    181         }
    182         if (connections != null) {
    183             pw.print(prefix); pw.print("connections="); pw.println(connections);
    184         }
    185     }
    186 
    187     ActivityRecord(ActivityManagerService _service, ActivityStack _stack, ProcessRecord _caller,
    188             int _launchedFromUid, Intent _intent, String _resolvedType,
    189             ActivityInfo aInfo, Configuration _configuration,
    190             ActivityRecord _resultTo, String _resultWho, int _reqCode,
    191             boolean _componentSpecified) {
    192         service = _service;
    193         stack = _stack;
    194         info = aInfo;
    195         launchedFromUid = _launchedFromUid;
    196         intent = _intent;
    197         shortComponentName = _intent.getComponent().flattenToShortString();
    198         resolvedType = _resolvedType;
    199         componentSpecified = _componentSpecified;
    200         configuration = _configuration;
    201         resultTo = _resultTo;
    202         resultWho = _resultWho;
    203         requestCode = _reqCode;
    204         state = ActivityState.INITIALIZING;
    205         frontOfTask = false;
    206         launchFailed = false;
    207         haveState = false;
    208         stopped = false;
    209         delayedResume = false;
    210         finishing = false;
    211         configDestroy = false;
    212         keysPaused = false;
    213         inHistory = false;
    214         visible = true;
    215         waitingVisible = false;
    216         nowVisible = false;
    217         thumbnailNeeded = false;
    218         idle = false;
    219         hasBeenLaunched = false;
    220 
    221         if (aInfo != null) {
    222             if (aInfo.targetActivity == null
    223                     || aInfo.launchMode == ActivityInfo.LAUNCH_MULTIPLE
    224                     || aInfo.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
    225                 realActivity = _intent.getComponent();
    226             } else {
    227                 realActivity = new ComponentName(aInfo.packageName,
    228                         aInfo.targetActivity);
    229             }
    230             taskAffinity = aInfo.taskAffinity;
    231             stateNotNeeded = (aInfo.flags&
    232                     ActivityInfo.FLAG_STATE_NOT_NEEDED) != 0;
    233             baseDir = aInfo.applicationInfo.sourceDir;
    234             resDir = aInfo.applicationInfo.publicSourceDir;
    235             dataDir = aInfo.applicationInfo.dataDir;
    236             nonLocalizedLabel = aInfo.nonLocalizedLabel;
    237             labelRes = aInfo.labelRes;
    238             if (nonLocalizedLabel == null && labelRes == 0) {
    239                 ApplicationInfo app = aInfo.applicationInfo;
    240                 nonLocalizedLabel = app.nonLocalizedLabel;
    241                 labelRes = app.labelRes;
    242             }
    243             icon = aInfo.getIconResource();
    244             theme = aInfo.getThemeResource();
    245             if ((aInfo.flags&ActivityInfo.FLAG_MULTIPROCESS) != 0
    246                     && _caller != null
    247                     && (aInfo.applicationInfo.uid == Process.SYSTEM_UID
    248                             || aInfo.applicationInfo.uid == _caller.info.uid)) {
    249                 processName = _caller.processName;
    250             } else {
    251                 processName = aInfo.processName;
    252             }
    253 
    254             if (intent != null && (aInfo.flags & ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS) != 0) {
    255                 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
    256             }
    257 
    258             packageName = aInfo.applicationInfo.packageName;
    259             launchMode = aInfo.launchMode;
    260 
    261             AttributeCache.Entry ent = AttributeCache.instance().get(packageName,
    262                     theme != 0 ? theme : android.R.style.Theme,
    263                     com.android.internal.R.styleable.Window);
    264             fullscreen = ent != null && !ent.array.getBoolean(
    265                     com.android.internal.R.styleable.Window_windowIsFloating, false)
    266                     && !ent.array.getBoolean(
    267                     com.android.internal.R.styleable.Window_windowIsTranslucent, false);
    268 
    269             if (!_componentSpecified || _launchedFromUid == Process.myUid()
    270                     || _launchedFromUid == 0) {
    271                 // If we know the system has determined the component, then
    272                 // we can consider this to be a home activity...
    273                 if (Intent.ACTION_MAIN.equals(_intent.getAction()) &&
    274                         _intent.hasCategory(Intent.CATEGORY_HOME) &&
    275                         _intent.getCategories().size() == 1 &&
    276                         _intent.getData() == null &&
    277                         _intent.getType() == null &&
    278                         (intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
    279                         !"android".equals(realActivity.getClassName())) {
    280                     // This sure looks like a home activity!
    281                     // Note the last check is so we don't count the resolver
    282                     // activity as being home...  really, we don't care about
    283                     // doing anything special with something that comes from
    284                     // the core framework package.
    285                     isHomeActivity = true;
    286                 } else {
    287                     isHomeActivity = false;
    288                 }
    289             } else {
    290                 isHomeActivity = false;
    291             }
    292         } else {
    293             realActivity = null;
    294             taskAffinity = null;
    295             stateNotNeeded = false;
    296             baseDir = null;
    297             resDir = null;
    298             dataDir = null;
    299             processName = null;
    300             packageName = null;
    301             fullscreen = true;
    302             isHomeActivity = false;
    303         }
    304     }
    305 
    306     UriPermissionOwner getUriPermissionsLocked() {
    307         if (uriPermissions == null) {
    308             uriPermissions = new UriPermissionOwner(service, this);
    309         }
    310         return uriPermissions;
    311     }
    312 
    313     void addResultLocked(ActivityRecord from, String resultWho,
    314             int requestCode, int resultCode,
    315             Intent resultData) {
    316         ActivityResult r = new ActivityResult(from, resultWho,
    317         		requestCode, resultCode, resultData);
    318         if (results == null) {
    319             results = new ArrayList();
    320         }
    321         results.add(r);
    322     }
    323 
    324     void removeResultsLocked(ActivityRecord from, String resultWho,
    325             int requestCode) {
    326         if (results != null) {
    327             for (int i=results.size()-1; i>=0; i--) {
    328                 ActivityResult r = (ActivityResult)results.get(i);
    329                 if (r.mFrom != from) continue;
    330                 if (r.mResultWho == null) {
    331                     if (resultWho != null) continue;
    332                 } else {
    333                     if (!r.mResultWho.equals(resultWho)) continue;
    334                 }
    335                 if (r.mRequestCode != requestCode) continue;
    336 
    337                 results.remove(i);
    338             }
    339         }
    340     }
    341 
    342     void addNewIntentLocked(Intent intent) {
    343         if (newIntents == null) {
    344             newIntents = new ArrayList();
    345         }
    346         newIntents.add(intent);
    347     }
    348 
    349     /**
    350      * Deliver a new Intent to an existing activity, so that its onNewIntent()
    351      * method will be called at the proper time.
    352      */
    353     final void deliverNewIntentLocked(int callingUid, Intent intent) {
    354         boolean sent = false;
    355         if (state == ActivityState.RESUMED
    356                 && app != null && app.thread != null) {
    357             try {
    358                 ArrayList<Intent> ar = new ArrayList<Intent>();
    359                 intent = new Intent(intent);
    360                 ar.add(intent);
    361                 service.grantUriPermissionFromIntentLocked(callingUid, packageName,
    362                         intent, getUriPermissionsLocked());
    363                 app.thread.scheduleNewIntent(ar, this);
    364                 sent = true;
    365             } catch (RemoteException e) {
    366                 Slog.w(ActivityManagerService.TAG,
    367                         "Exception thrown sending new intent to " + this, e);
    368             } catch (NullPointerException e) {
    369                 Slog.w(ActivityManagerService.TAG,
    370                         "Exception thrown sending new intent to " + this, e);
    371             }
    372         }
    373         if (!sent) {
    374             addNewIntentLocked(new Intent(intent));
    375         }
    376     }
    377 
    378     void removeUriPermissionsLocked() {
    379         if (uriPermissions != null) {
    380             uriPermissions.removeUriPermissionsLocked();
    381             uriPermissions = null;
    382         }
    383     }
    384 
    385     void pauseKeyDispatchingLocked() {
    386         if (!keysPaused) {
    387             keysPaused = true;
    388             service.mWindowManager.pauseKeyDispatching(this);
    389         }
    390     }
    391 
    392     void resumeKeyDispatchingLocked() {
    393         if (keysPaused) {
    394             keysPaused = false;
    395             service.mWindowManager.resumeKeyDispatching(this);
    396         }
    397     }
    398 
    399     // IApplicationToken
    400 
    401     public boolean mayFreezeScreenLocked(ProcessRecord app) {
    402         // Only freeze the screen if this activity is currently attached to
    403         // an application, and that application is not blocked or unresponding.
    404         // In any other case, we can't count on getting the screen unfrozen,
    405         // so it is best to leave as-is.
    406         return app == null || (!app.crashing && !app.notResponding);
    407     }
    408 
    409     public void startFreezingScreenLocked(ProcessRecord app, int configChanges) {
    410         if (mayFreezeScreenLocked(app)) {
    411             service.mWindowManager.startAppFreezingScreen(this, configChanges);
    412         }
    413     }
    414 
    415     public void stopFreezingScreenLocked(boolean force) {
    416         if (force || frozenBeforeDestroy) {
    417             frozenBeforeDestroy = false;
    418             service.mWindowManager.stopAppFreezingScreen(this, force);
    419         }
    420     }
    421 
    422     public void windowsVisible() {
    423         synchronized(service) {
    424             if (launchTime != 0) {
    425                 final long curTime = SystemClock.uptimeMillis();
    426                 final long thisTime = curTime - launchTime;
    427                 final long totalTime = stack.mInitialStartTime != 0
    428                         ? (curTime - stack.mInitialStartTime) : thisTime;
    429                 if (ActivityManagerService.SHOW_ACTIVITY_START_TIME) {
    430                     EventLog.writeEvent(EventLogTags.ACTIVITY_LAUNCH_TIME,
    431                             System.identityHashCode(this), shortComponentName,
    432                             thisTime, totalTime);
    433                     StringBuilder sb = service.mStringBuilder;
    434                     sb.setLength(0);
    435                     sb.append("Displayed ");
    436                     sb.append(shortComponentName);
    437                     sb.append(": ");
    438                     TimeUtils.formatDuration(thisTime, sb);
    439                     if (thisTime != totalTime) {
    440                         sb.append(" (total ");
    441                         TimeUtils.formatDuration(totalTime, sb);
    442                         sb.append(")");
    443                     }
    444                     Log.i(ActivityManagerService.TAG, sb.toString());
    445                 }
    446                 stack.reportActivityLaunchedLocked(false, this, thisTime, totalTime);
    447                 if (totalTime > 0) {
    448                     service.mUsageStatsService.noteLaunchTime(realActivity, (int)totalTime);
    449                 }
    450                 launchTime = 0;
    451                 stack.mInitialStartTime = 0;
    452             }
    453             startTime = 0;
    454             stack.reportActivityVisibleLocked(this);
    455             if (ActivityManagerService.DEBUG_SWITCH) Log.v(
    456                     ActivityManagerService.TAG, "windowsVisible(): " + this);
    457             if (!nowVisible) {
    458                 nowVisible = true;
    459                 if (!idle) {
    460                     // Instead of doing the full stop routine here, let's just
    461                     // hide any activities we now can, and let them stop when
    462                     // the normal idle happens.
    463                     stack.processStoppingActivitiesLocked(false);
    464                 } else {
    465                     // If this activity was already idle, then we now need to
    466                     // make sure we perform the full stop of any activities
    467                     // that are waiting to do so.  This is because we won't
    468                     // do that while they are still waiting for this one to
    469                     // become visible.
    470                     final int N = stack.mWaitingVisibleActivities.size();
    471                     if (N > 0) {
    472                         for (int i=0; i<N; i++) {
    473                             ActivityRecord r = (ActivityRecord)
    474                                 stack.mWaitingVisibleActivities.get(i);
    475                             r.waitingVisible = false;
    476                             if (ActivityManagerService.DEBUG_SWITCH) Log.v(
    477                                     ActivityManagerService.TAG,
    478                                     "Was waiting for visible: " + r);
    479                         }
    480                         stack.mWaitingVisibleActivities.clear();
    481                         Message msg = Message.obtain();
    482                         msg.what = ActivityStack.IDLE_NOW_MSG;
    483                         stack.mHandler.sendMessage(msg);
    484                     }
    485                 }
    486                 service.scheduleAppGcsLocked();
    487             }
    488         }
    489     }
    490 
    491     public void windowsGone() {
    492         if (ActivityManagerService.DEBUG_SWITCH) Log.v(
    493                 ActivityManagerService.TAG, "windowsGone(): " + this);
    494         nowVisible = false;
    495     }
    496 
    497     private ActivityRecord getWaitingHistoryRecordLocked() {
    498         // First find the real culprit...  if we are waiting
    499         // for another app to start, then we have paused dispatching
    500         // for this activity.
    501         ActivityRecord r = this;
    502         if (r.waitingVisible) {
    503             // Hmmm, who might we be waiting for?
    504             r = stack.mResumedActivity;
    505             if (r == null) {
    506                 r = stack.mPausingActivity;
    507             }
    508             // Both of those null?  Fall back to 'this' again
    509             if (r == null) {
    510                 r = this;
    511             }
    512         }
    513 
    514         return r;
    515     }
    516 
    517     public boolean keyDispatchingTimedOut() {
    518         ActivityRecord r;
    519         ProcessRecord anrApp = null;
    520         synchronized(service) {
    521             r = getWaitingHistoryRecordLocked();
    522             if (r != null && r.app != null) {
    523                 if (r.app.debugging) {
    524                     return false;
    525                 }
    526 
    527                 if (service.mDidDexOpt) {
    528                     // Give more time since we were dexopting.
    529                     service.mDidDexOpt = false;
    530                     return false;
    531                 }
    532 
    533                 if (r.app.instrumentationClass == null) {
    534                     anrApp = r.app;
    535                 } else {
    536                     Bundle info = new Bundle();
    537                     info.putString("shortMsg", "keyDispatchingTimedOut");
    538                     info.putString("longMsg", "Timed out while dispatching key event");
    539                     service.finishInstrumentationLocked(
    540                             r.app, Activity.RESULT_CANCELED, info);
    541                 }
    542             }
    543         }
    544 
    545         if (anrApp != null) {
    546             service.appNotResponding(anrApp, r, this,
    547                     "keyDispatchingTimedOut");
    548         }
    549 
    550         return true;
    551     }
    552 
    553     /** Returns the key dispatching timeout for this application token. */
    554     public long getKeyDispatchingTimeout() {
    555         synchronized(service) {
    556             ActivityRecord r = getWaitingHistoryRecordLocked();
    557             if (r == null || r.app == null
    558                     || r.app.instrumentationClass == null) {
    559                 return ActivityManagerService.KEY_DISPATCHING_TIMEOUT;
    560             }
    561 
    562             return ActivityManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT;
    563         }
    564     }
    565 
    566     /**
    567      * This method will return true if the activity is either visible, is becoming visible, is
    568      * currently pausing, or is resumed.
    569      */
    570     public boolean isInterestingToUserLocked() {
    571         return visible || nowVisible || state == ActivityState.PAUSING ||
    572                 state == ActivityState.RESUMED;
    573      }
    574 
    575     public String toString() {
    576         if (stringName != null) {
    577             return stringName;
    578         }
    579         StringBuilder sb = new StringBuilder(128);
    580         sb.append("HistoryRecord{");
    581         sb.append(Integer.toHexString(System.identityHashCode(this)));
    582         sb.append(' ');
    583         sb.append(intent.getComponent().flattenToShortString());
    584         sb.append('}');
    585         return stringName = sb.toString();
    586     }
    587 }
    588