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