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