Home | History | Annotate | Download | only in app
      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 android.app;
     18 
     19 import android.content.ActivityNotFoundException;
     20 import android.content.ComponentName;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.IntentFilter;
     24 import android.content.pm.ActivityInfo;
     25 import android.content.res.Configuration;
     26 import android.hardware.input.InputManager;
     27 import android.os.Bundle;
     28 import android.os.Debug;
     29 import android.os.IBinder;
     30 import android.os.Looper;
     31 import android.os.MessageQueue;
     32 import android.os.PerformanceCollector;
     33 import android.os.PersistableBundle;
     34 import android.os.Process;
     35 import android.os.RemoteException;
     36 import android.os.ServiceManager;
     37 import android.os.SystemClock;
     38 import android.os.UserHandle;
     39 import android.util.AndroidRuntimeException;
     40 import android.util.Log;
     41 import android.view.IWindowManager;
     42 import android.view.InputDevice;
     43 import android.view.KeyCharacterMap;
     44 import android.view.KeyEvent;
     45 import android.view.MotionEvent;
     46 import android.view.ViewConfiguration;
     47 import android.view.Window;
     48 import com.android.internal.content.ReferrerIntent;
     49 
     50 import java.io.File;
     51 import java.util.ArrayList;
     52 import java.util.List;
     53 
     54 /**
     55  * Base class for implementing application instrumentation code.  When running
     56  * with instrumentation turned on, this class will be instantiated for you
     57  * before any of the application code, allowing you to monitor all of the
     58  * interaction the system has with the application.  An Instrumentation
     59  * implementation is described to the system through an AndroidManifest.xml's
     60  * <instrumentation> tag.
     61  */
     62 public class Instrumentation {
     63 
     64     /**
     65      * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
     66      * identifies the class that is writing the report.  This can be used to provide more structured
     67      * logging or reporting capabilities in the IInstrumentationWatcher.
     68      */
     69     public static final String REPORT_KEY_IDENTIFIER = "id";
     70     /**
     71      * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
     72      * identifies a string which can simply be printed to the output stream.  Using these streams
     73      * provides a "pretty printer" version of the status & final packets.  Any bundles including
     74      * this key should also include the complete set of raw key/value pairs, so that the
     75      * instrumentation can also be launched, and results collected, by an automated system.
     76      */
     77     public static final String REPORT_KEY_STREAMRESULT = "stream";
     78 
     79     private static final String TAG = "Instrumentation";
     80 
     81     private final Object mSync = new Object();
     82     private ActivityThread mThread = null;
     83     private MessageQueue mMessageQueue = null;
     84     private Context mInstrContext;
     85     private Context mAppContext;
     86     private ComponentName mComponent;
     87     private Thread mRunner;
     88     private List<ActivityWaiter> mWaitingActivities;
     89     private List<ActivityMonitor> mActivityMonitors;
     90     private IInstrumentationWatcher mWatcher;
     91     private IUiAutomationConnection mUiAutomationConnection;
     92     private boolean mAutomaticPerformanceSnapshots = false;
     93     private PerformanceCollector mPerformanceCollector;
     94     private Bundle mPerfMetrics = new Bundle();
     95     private UiAutomation mUiAutomation;
     96 
     97     public Instrumentation() {
     98     }
     99 
    100     /**
    101      * Called when the instrumentation is starting, before any application code
    102      * has been loaded.  Usually this will be implemented to simply call
    103      * {@link #start} to begin the instrumentation thread, which will then
    104      * continue execution in {@link #onStart}.
    105      *
    106      * <p>If you do not need your own thread -- that is you are writing your
    107      * instrumentation to be completely asynchronous (returning to the event
    108      * loop so that the application can run), you can simply begin your
    109      * instrumentation here, for example call {@link Context#startActivity} to
    110      * begin the appropriate first activity of the application.
    111      *
    112      * @param arguments Any additional arguments that were supplied when the
    113      *                  instrumentation was started.
    114      */
    115     public void onCreate(Bundle arguments) {
    116     }
    117 
    118     /**
    119      * Create and start a new thread in which to run instrumentation.  This new
    120      * thread will call to {@link #onStart} where you can implement the
    121      * instrumentation.
    122      */
    123     public void start() {
    124         if (mRunner != null) {
    125             throw new RuntimeException("Instrumentation already started");
    126         }
    127         mRunner = new InstrumentationThread("Instr: " + getClass().getName());
    128         mRunner.start();
    129     }
    130 
    131     /**
    132      * Method where the instrumentation thread enters execution.  This allows
    133      * you to run your instrumentation code in a separate thread than the
    134      * application, so that it can perform blocking operation such as
    135      * {@link #sendKeySync} or {@link #startActivitySync}.
    136      *
    137      * <p>You will typically want to call finish() when this function is done,
    138      * to end your instrumentation.
    139      */
    140     public void onStart() {
    141     }
    142 
    143     /**
    144      * This is called whenever the system captures an unhandled exception that
    145      * was thrown by the application.  The default implementation simply
    146      * returns false, allowing normal system handling of the exception to take
    147      * place.
    148      *
    149      * @param obj The client object that generated the exception.  May be an
    150      *            Application, Activity, BroadcastReceiver, Service, or null.
    151      * @param e The exception that was thrown.
    152      *
    153      * @return To allow normal system exception process to occur, return false.
    154      *         If true is returned, the system will proceed as if the exception
    155      *         didn't happen.
    156      */
    157     public boolean onException(Object obj, Throwable e) {
    158         return false;
    159     }
    160 
    161     /**
    162      * Provide a status report about the application.
    163      *
    164      * @param resultCode Current success/failure of instrumentation.
    165      * @param results Any results to send back to the code that started the instrumentation.
    166      */
    167     public void sendStatus(int resultCode, Bundle results) {
    168         if (mWatcher != null) {
    169             try {
    170                 mWatcher.instrumentationStatus(mComponent, resultCode, results);
    171             }
    172             catch (RemoteException e) {
    173                 mWatcher = null;
    174             }
    175         }
    176     }
    177 
    178     /**
    179      * Terminate instrumentation of the application.  This will cause the
    180      * application process to exit, removing this instrumentation from the next
    181      * time the application is started.
    182      *
    183      * @param resultCode Overall success/failure of instrumentation.
    184      * @param results Any results to send back to the code that started the
    185      *                instrumentation.
    186      */
    187     public void finish(int resultCode, Bundle results) {
    188         if (mAutomaticPerformanceSnapshots) {
    189             endPerformanceSnapshot();
    190         }
    191         if (mPerfMetrics != null) {
    192             if (results == null) {
    193                 results = new Bundle();
    194             }
    195             results.putAll(mPerfMetrics);
    196         }
    197         if (mUiAutomation != null) {
    198             mUiAutomation.disconnect();
    199             mUiAutomation = null;
    200         }
    201         mThread.finishInstrumentation(resultCode, results);
    202     }
    203 
    204     public void setAutomaticPerformanceSnapshots() {
    205         mAutomaticPerformanceSnapshots = true;
    206         mPerformanceCollector = new PerformanceCollector();
    207     }
    208 
    209     public void startPerformanceSnapshot() {
    210         if (!isProfiling()) {
    211             mPerformanceCollector.beginSnapshot(null);
    212         }
    213     }
    214 
    215     public void endPerformanceSnapshot() {
    216         if (!isProfiling()) {
    217             mPerfMetrics = mPerformanceCollector.endSnapshot();
    218         }
    219     }
    220 
    221     /**
    222      * Called when the instrumented application is stopping, after all of the
    223      * normal application cleanup has occurred.
    224      */
    225     public void onDestroy() {
    226     }
    227 
    228     /**
    229      * Return the Context of this instrumentation's package.  Note that this is
    230      * often different than the Context of the application being
    231      * instrumentated, since the instrumentation code often lives is a
    232      * different package than that of the application it is running against.
    233      * See {@link #getTargetContext} to retrieve a Context for the target
    234      * application.
    235      *
    236      * @return The instrumentation's package context.
    237      *
    238      * @see #getTargetContext
    239      */
    240     public Context getContext() {
    241         return mInstrContext;
    242     }
    243 
    244     /**
    245      * Returns complete component name of this instrumentation.
    246      *
    247      * @return Returns the complete component name for this instrumentation.
    248      */
    249     public ComponentName getComponentName() {
    250         return mComponent;
    251     }
    252 
    253     /**
    254      * Return a Context for the target application being instrumented.  Note
    255      * that this is often different than the Context of the instrumentation
    256      * code, since the instrumentation code often lives is a different package
    257      * than that of the application it is running against. See
    258      * {@link #getContext} to retrieve a Context for the instrumentation code.
    259      *
    260      * @return A Context in the target application.
    261      *
    262      * @see #getContext
    263      */
    264     public Context getTargetContext() {
    265         return mAppContext;
    266     }
    267 
    268     /**
    269      * Check whether this instrumentation was started with profiling enabled.
    270      *
    271      * @return Returns true if profiling was enabled when starting, else false.
    272      */
    273     public boolean isProfiling() {
    274         return mThread.isProfiling();
    275     }
    276 
    277     /**
    278      * This method will start profiling if isProfiling() returns true. You should
    279      * only call this method if you set the handleProfiling attribute in the
    280      * manifest file for this Instrumentation to true.
    281      */
    282     public void startProfiling() {
    283         if (mThread.isProfiling()) {
    284             File file = new File(mThread.getProfileFilePath());
    285             file.getParentFile().mkdirs();
    286             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
    287         }
    288     }
    289 
    290     /**
    291      * Stops profiling if isProfiling() returns true.
    292      */
    293     public void stopProfiling() {
    294         if (mThread.isProfiling()) {
    295             Debug.stopMethodTracing();
    296         }
    297     }
    298 
    299     /**
    300      * Force the global system in or out of touch mode.  This can be used if
    301      * your instrumentation relies on the UI being in one more or the other
    302      * when it starts.
    303      *
    304      * @param inTouch Set to true to be in touch mode, false to be in
    305      * focus mode.
    306      */
    307     public void setInTouchMode(boolean inTouch) {
    308         try {
    309             IWindowManager.Stub.asInterface(
    310                     ServiceManager.getService("window")).setInTouchMode(inTouch);
    311         } catch (RemoteException e) {
    312             // Shouldn't happen!
    313         }
    314     }
    315 
    316     /**
    317      * Schedule a callback for when the application's main thread goes idle
    318      * (has no more events to process).
    319      *
    320      * @param recipient Called the next time the thread's message queue is
    321      *                  idle.
    322      */
    323     public void waitForIdle(Runnable recipient) {
    324         mMessageQueue.addIdleHandler(new Idler(recipient));
    325         mThread.getHandler().post(new EmptyRunnable());
    326     }
    327 
    328     /**
    329      * Synchronously wait for the application to be idle.  Can not be called
    330      * from the main application thread -- use {@link #start} to execute
    331      * instrumentation in its own thread.
    332      */
    333     public void waitForIdleSync() {
    334         validateNotAppThread();
    335         Idler idler = new Idler(null);
    336         mMessageQueue.addIdleHandler(idler);
    337         mThread.getHandler().post(new EmptyRunnable());
    338         idler.waitForIdle();
    339     }
    340 
    341     /**
    342      * Execute a call on the application's main thread, blocking until it is
    343      * complete.  Useful for doing things that are not thread-safe, such as
    344      * looking at or modifying the view hierarchy.
    345      *
    346      * @param runner The code to run on the main thread.
    347      */
    348     public void runOnMainSync(Runnable runner) {
    349         validateNotAppThread();
    350         SyncRunnable sr = new SyncRunnable(runner);
    351         mThread.getHandler().post(sr);
    352         sr.waitForComplete();
    353     }
    354 
    355     /**
    356      * Start a new activity and wait for it to begin running before returning.
    357      * In addition to being synchronous, this method as some semantic
    358      * differences from the standard {@link Context#startActivity} call: the
    359      * activity component is resolved before talking with the activity manager
    360      * (its class name is specified in the Intent that this method ultimately
    361      * starts), and it does not allow you to start activities that run in a
    362      * different process.  In addition, if the given Intent resolves to
    363      * multiple activities, instead of displaying a dialog for the user to
    364      * select an activity, an exception will be thrown.
    365      *
    366      * <p>The function returns as soon as the activity goes idle following the
    367      * call to its {@link Activity#onCreate}.  Generally this means it has gone
    368      * through the full initialization including {@link Activity#onResume} and
    369      * drawn and displayed its initial window.
    370      *
    371      * @param intent Description of the activity to start.
    372      *
    373      * @see Context#startActivity
    374      */
    375     public Activity startActivitySync(Intent intent) {
    376         validateNotAppThread();
    377 
    378         synchronized (mSync) {
    379             intent = new Intent(intent);
    380 
    381             ActivityInfo ai = intent.resolveActivityInfo(
    382                 getTargetContext().getPackageManager(), 0);
    383             if (ai == null) {
    384                 throw new RuntimeException("Unable to resolve activity for: " + intent);
    385             }
    386             String myProc = mThread.getProcessName();
    387             if (!ai.processName.equals(myProc)) {
    388                 // todo: if this intent is ambiguous, look here to see if
    389                 // there is a single match that is in our package.
    390                 throw new RuntimeException("Intent in process "
    391                         + myProc + " resolved to different process "
    392                         + ai.processName + ": " + intent);
    393             }
    394 
    395             intent.setComponent(new ComponentName(
    396                     ai.applicationInfo.packageName, ai.name));
    397             final ActivityWaiter aw = new ActivityWaiter(intent);
    398 
    399             if (mWaitingActivities == null) {
    400                 mWaitingActivities = new ArrayList();
    401             }
    402             mWaitingActivities.add(aw);
    403 
    404             getTargetContext().startActivity(intent);
    405 
    406             do {
    407                 try {
    408                     mSync.wait();
    409                 } catch (InterruptedException e) {
    410                 }
    411             } while (mWaitingActivities.contains(aw));
    412 
    413             return aw.activity;
    414         }
    415     }
    416 
    417     /**
    418      * Information about a particular kind of Intent that is being monitored.
    419      * An instance of this class is added to the
    420      * current instrumentation through {@link #addMonitor}; after being added,
    421      * when a new activity is being started the monitor will be checked and, if
    422      * matching, its hit count updated and (optionally) the call stopped and a
    423      * canned result returned.
    424      *
    425      * <p>An ActivityMonitor can also be used to look for the creation of an
    426      * activity, through the {@link #waitForActivity} method.  This will return
    427      * after a matching activity has been created with that activity object.
    428      */
    429     public static class ActivityMonitor {
    430         private final IntentFilter mWhich;
    431         private final String mClass;
    432         private final ActivityResult mResult;
    433         private final boolean mBlock;
    434 
    435 
    436         // This is protected by 'Instrumentation.this.mSync'.
    437         /*package*/ int mHits = 0;
    438 
    439         // This is protected by 'this'.
    440         /*package*/ Activity mLastActivity = null;
    441 
    442         /**
    443          * Create a new ActivityMonitor that looks for a particular kind of
    444          * intent to be started.
    445          *
    446          * @param which The set of intents this monitor is responsible for.
    447          * @param result A canned result to return if the monitor is hit; can
    448          *               be null.
    449          * @param block Controls whether the monitor should block the activity
    450          *              start (returning its canned result) or let the call
    451          *              proceed.
    452          *
    453          * @see Instrumentation#addMonitor
    454          */
    455         public ActivityMonitor(
    456             IntentFilter which, ActivityResult result, boolean block) {
    457             mWhich = which;
    458             mClass = null;
    459             mResult = result;
    460             mBlock = block;
    461         }
    462 
    463         /**
    464          * Create a new ActivityMonitor that looks for a specific activity
    465          * class to be started.
    466          *
    467          * @param cls The activity class this monitor is responsible for.
    468          * @param result A canned result to return if the monitor is hit; can
    469          *               be null.
    470          * @param block Controls whether the monitor should block the activity
    471          *              start (returning its canned result) or let the call
    472          *              proceed.
    473          *
    474          * @see Instrumentation#addMonitor
    475          */
    476         public ActivityMonitor(
    477             String cls, ActivityResult result, boolean block) {
    478             mWhich = null;
    479             mClass = cls;
    480             mResult = result;
    481             mBlock = block;
    482         }
    483 
    484         /**
    485          * Retrieve the filter associated with this ActivityMonitor.
    486          */
    487         public final IntentFilter getFilter() {
    488             return mWhich;
    489         }
    490 
    491         /**
    492          * Retrieve the result associated with this ActivityMonitor, or null if
    493          * none.
    494          */
    495         public final ActivityResult getResult() {
    496             return mResult;
    497         }
    498 
    499         /**
    500          * Check whether this monitor blocks activity starts (not allowing the
    501          * actual activity to run) or allows them to execute normally.
    502          */
    503         public final boolean isBlocking() {
    504             return mBlock;
    505         }
    506 
    507         /**
    508          * Retrieve the number of times the monitor has been hit so far.
    509          */
    510         public final int getHits() {
    511             return mHits;
    512         }
    513 
    514         /**
    515          * Retrieve the most recent activity class that was seen by this
    516          * monitor.
    517          */
    518         public final Activity getLastActivity() {
    519             return mLastActivity;
    520         }
    521 
    522         /**
    523          * Block until an Activity is created that matches this monitor,
    524          * returning the resulting activity.
    525          *
    526          * @return Activity
    527          */
    528         public final Activity waitForActivity() {
    529             synchronized (this) {
    530                 while (mLastActivity == null) {
    531                     try {
    532                         wait();
    533                     } catch (InterruptedException e) {
    534                     }
    535                 }
    536                 Activity res = mLastActivity;
    537                 mLastActivity = null;
    538                 return res;
    539             }
    540         }
    541 
    542         /**
    543          * Block until an Activity is created that matches this monitor,
    544          * returning the resulting activity or till the timeOut period expires.
    545          * If the timeOut expires before the activity is started, return null.
    546          *
    547          * @param timeOut Time to wait before the activity is created.
    548          *
    549          * @return Activity
    550          */
    551         public final Activity waitForActivityWithTimeout(long timeOut) {
    552             synchronized (this) {
    553                 if (mLastActivity == null) {
    554                     try {
    555                         wait(timeOut);
    556                     } catch (InterruptedException e) {
    557                     }
    558                 }
    559                 if (mLastActivity == null) {
    560                     return null;
    561                 } else {
    562                     Activity res = mLastActivity;
    563                     mLastActivity = null;
    564                     return res;
    565                 }
    566             }
    567         }
    568 
    569         final boolean match(Context who,
    570                             Activity activity,
    571                             Intent intent) {
    572             synchronized (this) {
    573                 if (mWhich != null
    574                     && mWhich.match(who.getContentResolver(), intent,
    575                                     true, "Instrumentation") < 0) {
    576                     return false;
    577                 }
    578                 if (mClass != null) {
    579                     String cls = null;
    580                     if (activity != null) {
    581                         cls = activity.getClass().getName();
    582                     } else if (intent.getComponent() != null) {
    583                         cls = intent.getComponent().getClassName();
    584                     }
    585                     if (cls == null || !mClass.equals(cls)) {
    586                         return false;
    587                     }
    588                 }
    589                 if (activity != null) {
    590                     mLastActivity = activity;
    591                     notifyAll();
    592                 }
    593                 return true;
    594             }
    595         }
    596     }
    597 
    598     /**
    599      * Add a new {@link ActivityMonitor} that will be checked whenever an
    600      * activity is started.  The monitor is added
    601      * after any existing ones; the monitor will be hit only if none of the
    602      * existing monitors can themselves handle the Intent.
    603      *
    604      * @param monitor The new ActivityMonitor to see.
    605      *
    606      * @see #addMonitor(IntentFilter, ActivityResult, boolean)
    607      * @see #checkMonitorHit
    608      */
    609     public void addMonitor(ActivityMonitor monitor) {
    610         synchronized (mSync) {
    611             if (mActivityMonitors == null) {
    612                 mActivityMonitors = new ArrayList();
    613             }
    614             mActivityMonitors.add(monitor);
    615         }
    616     }
    617 
    618     /**
    619      * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
    620      * creates an intent filter matching {@link ActivityMonitor} for you and
    621      * returns it.
    622      *
    623      * @param filter The set of intents this monitor is responsible for.
    624      * @param result A canned result to return if the monitor is hit; can
    625      *               be null.
    626      * @param block Controls whether the monitor should block the activity
    627      *              start (returning its canned result) or let the call
    628      *              proceed.
    629      *
    630      * @return The newly created and added activity monitor.
    631      *
    632      * @see #addMonitor(ActivityMonitor)
    633      * @see #checkMonitorHit
    634      */
    635     public ActivityMonitor addMonitor(
    636         IntentFilter filter, ActivityResult result, boolean block) {
    637         ActivityMonitor am = new ActivityMonitor(filter, result, block);
    638         addMonitor(am);
    639         return am;
    640     }
    641 
    642     /**
    643      * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
    644      * creates a class matching {@link ActivityMonitor} for you and returns it.
    645      *
    646      * @param cls The activity class this monitor is responsible for.
    647      * @param result A canned result to return if the monitor is hit; can
    648      *               be null.
    649      * @param block Controls whether the monitor should block the activity
    650      *              start (returning its canned result) or let the call
    651      *              proceed.
    652      *
    653      * @return The newly created and added activity monitor.
    654      *
    655      * @see #addMonitor(ActivityMonitor)
    656      * @see #checkMonitorHit
    657      */
    658     public ActivityMonitor addMonitor(
    659         String cls, ActivityResult result, boolean block) {
    660         ActivityMonitor am = new ActivityMonitor(cls, result, block);
    661         addMonitor(am);
    662         return am;
    663     }
    664 
    665     /**
    666      * Test whether an existing {@link ActivityMonitor} has been hit.  If the
    667      * monitor has been hit at least <var>minHits</var> times, then it will be
    668      * removed from the activity monitor list and true returned.  Otherwise it
    669      * is left as-is and false is returned.
    670      *
    671      * @param monitor The ActivityMonitor to check.
    672      * @param minHits The minimum number of hits required.
    673      *
    674      * @return True if the hit count has been reached, else false.
    675      *
    676      * @see #addMonitor
    677      */
    678     public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
    679         waitForIdleSync();
    680         synchronized (mSync) {
    681             if (monitor.getHits() < minHits) {
    682                 return false;
    683             }
    684             mActivityMonitors.remove(monitor);
    685         }
    686         return true;
    687     }
    688 
    689     /**
    690      * Wait for an existing {@link ActivityMonitor} to be hit.  Once the
    691      * monitor has been hit, it is removed from the activity monitor list and
    692      * the first created Activity object that matched it is returned.
    693      *
    694      * @param monitor The ActivityMonitor to wait for.
    695      *
    696      * @return The Activity object that matched the monitor.
    697      */
    698     public Activity waitForMonitor(ActivityMonitor monitor) {
    699         Activity activity = monitor.waitForActivity();
    700         synchronized (mSync) {
    701             mActivityMonitors.remove(monitor);
    702         }
    703         return activity;
    704     }
    705 
    706     /**
    707      * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
    708      * expires.  Once the monitor has been hit, it is removed from the activity
    709      * monitor list and the first created Activity object that matched it is
    710      * returned.  If the timeout expires, a null object is returned.
    711      *
    712      * @param monitor The ActivityMonitor to wait for.
    713      * @param timeOut The timeout value in secs.
    714      *
    715      * @return The Activity object that matched the monitor.
    716      */
    717     public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
    718         Activity activity = monitor.waitForActivityWithTimeout(timeOut);
    719         synchronized (mSync) {
    720             mActivityMonitors.remove(monitor);
    721         }
    722         return activity;
    723     }
    724 
    725     /**
    726      * Remove an {@link ActivityMonitor} that was previously added with
    727      * {@link #addMonitor}.
    728      *
    729      * @param monitor The monitor to remove.
    730      *
    731      * @see #addMonitor
    732      */
    733     public void removeMonitor(ActivityMonitor monitor) {
    734         synchronized (mSync) {
    735             mActivityMonitors.remove(monitor);
    736         }
    737     }
    738 
    739     /**
    740      * Execute a particular menu item.
    741      *
    742      * @param targetActivity The activity in question.
    743      * @param id The identifier associated with the menu item.
    744      * @param flag Additional flags, if any.
    745      * @return Whether the invocation was successful (for example, it could be
    746      *         false if item is disabled).
    747      */
    748     public boolean invokeMenuActionSync(Activity targetActivity,
    749                                     int id, int flag) {
    750         class MenuRunnable implements Runnable {
    751             private final Activity activity;
    752             private final int identifier;
    753             private final int flags;
    754             boolean returnValue;
    755 
    756             public MenuRunnable(Activity _activity, int _identifier,
    757                                     int _flags) {
    758                 activity = _activity;
    759                 identifier = _identifier;
    760                 flags = _flags;
    761             }
    762 
    763             public void run() {
    764                 Window win = activity.getWindow();
    765 
    766                 returnValue = win.performPanelIdentifierAction(
    767                             Window.FEATURE_OPTIONS_PANEL,
    768                             identifier,
    769                             flags);
    770             }
    771 
    772         }
    773         MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
    774         runOnMainSync(mr);
    775         return mr.returnValue;
    776     }
    777 
    778     /**
    779      * Show the context menu for the currently focused view and executes a
    780      * particular context menu item.
    781      *
    782      * @param targetActivity The activity in question.
    783      * @param id The identifier associated with the context menu item.
    784      * @param flag Additional flags, if any.
    785      * @return Whether the invocation was successful (for example, it could be
    786      *         false if item is disabled).
    787      */
    788     public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
    789         validateNotAppThread();
    790 
    791         // Bring up context menu for current focus.
    792         // It'd be nice to do this through code, but currently ListView depends on
    793         //   long press to set metadata for its selected child
    794 
    795         final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
    796         sendKeySync(downEvent);
    797 
    798         // Need to wait for long press
    799         waitForIdleSync();
    800         try {
    801             Thread.sleep(ViewConfiguration.getLongPressTimeout());
    802         } catch (InterruptedException e) {
    803             Log.e(TAG, "Could not sleep for long press timeout", e);
    804             return false;
    805         }
    806 
    807         final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
    808         sendKeySync(upEvent);
    809 
    810         // Wait for context menu to appear
    811         waitForIdleSync();
    812 
    813         class ContextMenuRunnable implements Runnable {
    814             private final Activity activity;
    815             private final int identifier;
    816             private final int flags;
    817             boolean returnValue;
    818 
    819             public ContextMenuRunnable(Activity _activity, int _identifier,
    820                                     int _flags) {
    821                 activity = _activity;
    822                 identifier = _identifier;
    823                 flags = _flags;
    824             }
    825 
    826             public void run() {
    827                 Window win = activity.getWindow();
    828                 returnValue = win.performContextMenuIdentifierAction(
    829                             identifier,
    830                             flags);
    831             }
    832 
    833         }
    834 
    835         ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
    836         runOnMainSync(cmr);
    837         return cmr.returnValue;
    838     }
    839 
    840     /**
    841      * Sends the key events corresponding to the text to the app being
    842      * instrumented.
    843      *
    844      * @param text The text to be sent.
    845      */
    846     public void sendStringSync(String text) {
    847         if (text == null) {
    848             return;
    849         }
    850         KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
    851 
    852         KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
    853 
    854         if (events != null) {
    855             for (int i = 0; i < events.length; i++) {
    856                 // We have to change the time of an event before injecting it because
    857                 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
    858                 // time stamp and the system rejects too old events. Hence, it is
    859                 // possible for an event to become stale before it is injected if it
    860                 // takes too long to inject the preceding ones.
    861                 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
    862             }
    863         }
    864     }
    865 
    866     /**
    867      * Send a key event to the currently focused window/view and wait for it to
    868      * be processed.  Finished at some point after the recipient has returned
    869      * from its event processing, though it may <em>not</em> have completely
    870      * finished reacting from the event -- for example, if it needs to update
    871      * its display as a result, it may still be in the process of doing that.
    872      *
    873      * @param event The event to send to the current focus.
    874      */
    875     public void sendKeySync(KeyEvent event) {
    876         validateNotAppThread();
    877 
    878         long downTime = event.getDownTime();
    879         long eventTime = event.getEventTime();
    880         int action = event.getAction();
    881         int code = event.getKeyCode();
    882         int repeatCount = event.getRepeatCount();
    883         int metaState = event.getMetaState();
    884         int deviceId = event.getDeviceId();
    885         int scancode = event.getScanCode();
    886         int source = event.getSource();
    887         int flags = event.getFlags();
    888         if (source == InputDevice.SOURCE_UNKNOWN) {
    889             source = InputDevice.SOURCE_KEYBOARD;
    890         }
    891         if (eventTime == 0) {
    892             eventTime = SystemClock.uptimeMillis();
    893         }
    894         if (downTime == 0) {
    895             downTime = eventTime;
    896         }
    897         KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
    898                 deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
    899         InputManager.getInstance().injectInputEvent(newEvent,
    900                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
    901     }
    902 
    903     /**
    904      * Sends an up and down key event sync to the currently focused window.
    905      *
    906      * @param key The integer keycode for the event.
    907      */
    908     public void sendKeyDownUpSync(int key) {
    909         sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
    910         sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
    911     }
    912 
    913     /**
    914      * Higher-level method for sending both the down and up key events for a
    915      * particular character key code.  Equivalent to creating both KeyEvent
    916      * objects by hand and calling {@link #sendKeySync}.  The event appears
    917      * as if it came from keyboard 0, the built in one.
    918      *
    919      * @param keyCode The key code of the character to send.
    920      */
    921     public void sendCharacterSync(int keyCode) {
    922         sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
    923         sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
    924     }
    925 
    926     /**
    927      * Dispatch a pointer event. Finished at some point after the recipient has
    928      * returned from its event processing, though it may <em>not</em> have
    929      * completely finished reacting from the event -- for example, if it needs
    930      * to update its display as a result, it may still be in the process of
    931      * doing that.
    932      *
    933      * @param event A motion event describing the pointer action.  (As noted in
    934      * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
    935      * {@link SystemClock#uptimeMillis()} as the timebase.
    936      */
    937     public void sendPointerSync(MotionEvent event) {
    938         validateNotAppThread();
    939         if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
    940             event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
    941         }
    942         InputManager.getInstance().injectInputEvent(event,
    943                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
    944     }
    945 
    946     /**
    947      * Dispatch a trackball event. Finished at some point after the recipient has
    948      * returned from its event processing, though it may <em>not</em> have
    949      * completely finished reacting from the event -- for example, if it needs
    950      * to update its display as a result, it may still be in the process of
    951      * doing that.
    952      *
    953      * @param event A motion event describing the trackball action.  (As noted in
    954      * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
    955      * {@link SystemClock#uptimeMillis()} as the timebase.
    956      */
    957     public void sendTrackballEventSync(MotionEvent event) {
    958         validateNotAppThread();
    959         if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
    960             event.setSource(InputDevice.SOURCE_TRACKBALL);
    961         }
    962         InputManager.getInstance().injectInputEvent(event,
    963                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
    964     }
    965 
    966     /**
    967      * Perform instantiation of the process's {@link Application} object.  The
    968      * default implementation provides the normal system behavior.
    969      *
    970      * @param cl The ClassLoader with which to instantiate the object.
    971      * @param className The name of the class implementing the Application
    972      *                  object.
    973      * @param context The context to initialize the application with
    974      *
    975      * @return The newly instantiated Application object.
    976      */
    977     public Application newApplication(ClassLoader cl, String className, Context context)
    978             throws InstantiationException, IllegalAccessException,
    979             ClassNotFoundException {
    980         return newApplication(cl.loadClass(className), context);
    981     }
    982 
    983     /**
    984      * Perform instantiation of the process's {@link Application} object.  The
    985      * default implementation provides the normal system behavior.
    986      *
    987      * @param clazz The class used to create an Application object from.
    988      * @param context The context to initialize the application with
    989      *
    990      * @return The newly instantiated Application object.
    991      */
    992     static public Application newApplication(Class<?> clazz, Context context)
    993             throws InstantiationException, IllegalAccessException,
    994             ClassNotFoundException {
    995         Application app = (Application)clazz.newInstance();
    996         app.attach(context);
    997         return app;
    998     }
    999 
   1000     /**
   1001      * Perform calling of the application's {@link Application#onCreate}
   1002      * method.  The default implementation simply calls through to that method.
   1003      *
   1004      * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
   1005      * Often instrumentation tests start their test thread in onCreate(); you
   1006      * need to be careful of races between these.  (Well between it and
   1007      * everything else, but let's start here.)
   1008      *
   1009      * @param app The application being created.
   1010      */
   1011     public void callApplicationOnCreate(Application app) {
   1012         app.onCreate();
   1013     }
   1014 
   1015     /**
   1016      * Perform instantiation of an {@link Activity} object.  This method is intended for use with
   1017      * unit tests, such as android.test.ActivityUnitTestCase.  The activity will be useable
   1018      * locally but will be missing some of the linkages necessary for use within the sytem.
   1019      *
   1020      * @param clazz The Class of the desired Activity
   1021      * @param context The base context for the activity to use
   1022      * @param token The token for this activity to communicate with
   1023      * @param application The application object (if any)
   1024      * @param intent The intent that started this Activity
   1025      * @param info ActivityInfo from the manifest
   1026      * @param title The title, typically retrieved from the ActivityInfo record
   1027      * @param parent The parent Activity (if any)
   1028      * @param id The embedded Id (if any)
   1029      * @param lastNonConfigurationInstance Arbitrary object that will be
   1030      * available via {@link Activity#getLastNonConfigurationInstance()
   1031      * Activity.getLastNonConfigurationInstance()}.
   1032      * @return Returns the instantiated activity
   1033      * @throws InstantiationException
   1034      * @throws IllegalAccessException
   1035      */
   1036     public Activity newActivity(Class<?> clazz, Context context,
   1037             IBinder token, Application application, Intent intent, ActivityInfo info,
   1038             CharSequence title, Activity parent, String id,
   1039             Object lastNonConfigurationInstance) throws InstantiationException,
   1040             IllegalAccessException {
   1041         Activity activity = (Activity)clazz.newInstance();
   1042         ActivityThread aThread = null;
   1043         activity.attach(context, aThread, this, token, 0, application, intent,
   1044                 info, title, parent, id,
   1045                 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
   1046                 new Configuration(), null, null);
   1047         return activity;
   1048     }
   1049 
   1050     /**
   1051      * Perform instantiation of the process's {@link Activity} object.  The
   1052      * default implementation provides the normal system behavior.
   1053      *
   1054      * @param cl The ClassLoader with which to instantiate the object.
   1055      * @param className The name of the class implementing the Activity
   1056      *                  object.
   1057      * @param intent The Intent object that specified the activity class being
   1058      *               instantiated.
   1059      *
   1060      * @return The newly instantiated Activity object.
   1061      */
   1062     public Activity newActivity(ClassLoader cl, String className,
   1063             Intent intent)
   1064             throws InstantiationException, IllegalAccessException,
   1065             ClassNotFoundException {
   1066         return (Activity)cl.loadClass(className).newInstance();
   1067     }
   1068 
   1069     private void prePerformCreate(Activity activity) {
   1070         if (mWaitingActivities != null) {
   1071             synchronized (mSync) {
   1072                 final int N = mWaitingActivities.size();
   1073                 for (int i=0; i<N; i++) {
   1074                     final ActivityWaiter aw = mWaitingActivities.get(i);
   1075                     final Intent intent = aw.intent;
   1076                     if (intent.filterEquals(activity.getIntent())) {
   1077                         aw.activity = activity;
   1078                         mMessageQueue.addIdleHandler(new ActivityGoing(aw));
   1079                     }
   1080                 }
   1081             }
   1082         }
   1083     }
   1084 
   1085     private void postPerformCreate(Activity activity) {
   1086         if (mActivityMonitors != null) {
   1087             synchronized (mSync) {
   1088                 final int N = mActivityMonitors.size();
   1089                 for (int i=0; i<N; i++) {
   1090                     final ActivityMonitor am = mActivityMonitors.get(i);
   1091                     am.match(activity, activity, activity.getIntent());
   1092                 }
   1093             }
   1094         }
   1095     }
   1096 
   1097     /**
   1098      * Perform calling of an activity's {@link Activity#onCreate}
   1099      * method.  The default implementation simply calls through to that method.
   1100      *
   1101      * @param activity The activity being created.
   1102      * @param icicle The previously frozen state (or null) to pass through to onCreate().
   1103      */
   1104     public void callActivityOnCreate(Activity activity, Bundle icicle) {
   1105         prePerformCreate(activity);
   1106         activity.performCreate(icicle);
   1107         postPerformCreate(activity);
   1108     }
   1109 
   1110     /**
   1111      * Perform calling of an activity's {@link Activity#onCreate}
   1112      * method.  The default implementation simply calls through to that method.
   1113      *  @param activity The activity being created.
   1114      * @param icicle The previously frozen state (or null) to pass through to
   1115      * @param persistentState The previously persisted state (or null)
   1116      */
   1117     public void callActivityOnCreate(Activity activity, Bundle icicle,
   1118             PersistableBundle persistentState) {
   1119         prePerformCreate(activity);
   1120         activity.performCreate(icicle, persistentState);
   1121         postPerformCreate(activity);
   1122     }
   1123 
   1124     public void callActivityOnDestroy(Activity activity) {
   1125       // TODO: the following block causes intermittent hangs when using startActivity
   1126       // temporarily comment out until root cause is fixed (bug 2630683)
   1127 //      if (mWaitingActivities != null) {
   1128 //          synchronized (mSync) {
   1129 //              final int N = mWaitingActivities.size();
   1130 //              for (int i=0; i<N; i++) {
   1131 //                  final ActivityWaiter aw = mWaitingActivities.get(i);
   1132 //                  final Intent intent = aw.intent;
   1133 //                  if (intent.filterEquals(activity.getIntent())) {
   1134 //                      aw.activity = activity;
   1135 //                      mMessageQueue.addIdleHandler(new ActivityGoing(aw));
   1136 //                  }
   1137 //              }
   1138 //          }
   1139 //      }
   1140 
   1141       activity.performDestroy();
   1142 
   1143       if (mActivityMonitors != null) {
   1144           synchronized (mSync) {
   1145               final int N = mActivityMonitors.size();
   1146               for (int i=0; i<N; i++) {
   1147                   final ActivityMonitor am = mActivityMonitors.get(i);
   1148                   am.match(activity, activity, activity.getIntent());
   1149               }
   1150           }
   1151       }
   1152   }
   1153 
   1154     /**
   1155      * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
   1156      * method.  The default implementation simply calls through to that method.
   1157      *
   1158      * @param activity The activity being restored.
   1159      * @param savedInstanceState The previously saved state being restored.
   1160      */
   1161     public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
   1162         activity.performRestoreInstanceState(savedInstanceState);
   1163     }
   1164 
   1165     /**
   1166      * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
   1167      * method.  The default implementation simply calls through to that method.
   1168      *
   1169      * @param activity The activity being restored.
   1170      * @param savedInstanceState The previously saved state being restored.
   1171      * @param persistentState The previously persisted state (or null)
   1172      */
   1173     public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState,
   1174             PersistableBundle persistentState) {
   1175         activity.performRestoreInstanceState(savedInstanceState, persistentState);
   1176     }
   1177 
   1178     /**
   1179      * Perform calling of an activity's {@link Activity#onPostCreate} method.
   1180      * The default implementation simply calls through to that method.
   1181      *
   1182      * @param activity The activity being created.
   1183      * @param icicle The previously frozen state (or null) to pass through to
   1184      *               onPostCreate().
   1185      */
   1186     public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
   1187         activity.onPostCreate(icicle);
   1188     }
   1189 
   1190     /**
   1191      * Perform calling of an activity's {@link Activity#onPostCreate} method.
   1192      * The default implementation simply calls through to that method.
   1193      *
   1194      * @param activity The activity being created.
   1195      * @param icicle The previously frozen state (or null) to pass through to
   1196      *               onPostCreate().
   1197      */
   1198     public void callActivityOnPostCreate(Activity activity, Bundle icicle,
   1199             PersistableBundle persistentState) {
   1200         activity.onPostCreate(icicle, persistentState);
   1201     }
   1202 
   1203     /**
   1204      * Perform calling of an activity's {@link Activity#onNewIntent}
   1205      * method.  The default implementation simply calls through to that method.
   1206      *
   1207      * @param activity The activity receiving a new Intent.
   1208      * @param intent The new intent being received.
   1209      */
   1210     public void callActivityOnNewIntent(Activity activity, Intent intent) {
   1211         activity.onNewIntent(intent);
   1212     }
   1213 
   1214     /**
   1215      * @hide
   1216      */
   1217     public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
   1218         final String oldReferrer = activity.mReferrer;
   1219         try {
   1220             if (intent != null) {
   1221                 activity.mReferrer = intent.mReferrer;
   1222             }
   1223             callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
   1224         } finally {
   1225             activity.mReferrer = oldReferrer;
   1226         }
   1227     }
   1228 
   1229     /**
   1230      * Perform calling of an activity's {@link Activity#onStart}
   1231      * method.  The default implementation simply calls through to that method.
   1232      *
   1233      * @param activity The activity being started.
   1234      */
   1235     public void callActivityOnStart(Activity activity) {
   1236         activity.onStart();
   1237     }
   1238 
   1239     /**
   1240      * Perform calling of an activity's {@link Activity#onRestart}
   1241      * method.  The default implementation simply calls through to that method.
   1242      *
   1243      * @param activity The activity being restarted.
   1244      */
   1245     public void callActivityOnRestart(Activity activity) {
   1246         activity.onRestart();
   1247     }
   1248 
   1249     /**
   1250      * Perform calling of an activity's {@link Activity#onResume} method.  The
   1251      * default implementation simply calls through to that method.
   1252      *
   1253      * @param activity The activity being resumed.
   1254      */
   1255     public void callActivityOnResume(Activity activity) {
   1256         activity.mResumed = true;
   1257         activity.onResume();
   1258 
   1259         if (mActivityMonitors != null) {
   1260             synchronized (mSync) {
   1261                 final int N = mActivityMonitors.size();
   1262                 for (int i=0; i<N; i++) {
   1263                     final ActivityMonitor am = mActivityMonitors.get(i);
   1264                     am.match(activity, activity, activity.getIntent());
   1265                 }
   1266             }
   1267         }
   1268     }
   1269 
   1270     /**
   1271      * Perform calling of an activity's {@link Activity#onStop}
   1272      * method.  The default implementation simply calls through to that method.
   1273      *
   1274      * @param activity The activity being stopped.
   1275      */
   1276     public void callActivityOnStop(Activity activity) {
   1277         activity.onStop();
   1278     }
   1279 
   1280     /**
   1281      * Perform calling of an activity's {@link Activity#onSaveInstanceState}
   1282      * method.  The default implementation simply calls through to that method.
   1283      *
   1284      * @param activity The activity being saved.
   1285      * @param outState The bundle to pass to the call.
   1286      */
   1287     public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
   1288         activity.performSaveInstanceState(outState);
   1289     }
   1290 
   1291     /**
   1292      * Perform calling of an activity's {@link Activity#onSaveInstanceState}
   1293      * method.  The default implementation simply calls through to that method.
   1294      *  @param activity The activity being saved.
   1295      * @param outState The bundle to pass to the call.
   1296      * @param outPersistentState The persistent bundle to pass to the call.
   1297      */
   1298     public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
   1299             PersistableBundle outPersistentState) {
   1300         activity.performSaveInstanceState(outState, outPersistentState);
   1301     }
   1302 
   1303     /**
   1304      * Perform calling of an activity's {@link Activity#onPause} method.  The
   1305      * default implementation simply calls through to that method.
   1306      *
   1307      * @param activity The activity being paused.
   1308      */
   1309     public void callActivityOnPause(Activity activity) {
   1310         activity.performPause();
   1311     }
   1312 
   1313     /**
   1314      * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
   1315      * The default implementation simply calls through to that method.
   1316      *
   1317      * @param activity The activity being notified that the user has navigated away
   1318      */
   1319     public void callActivityOnUserLeaving(Activity activity) {
   1320         activity.performUserLeaving();
   1321     }
   1322 
   1323     /*
   1324      * Starts allocation counting. This triggers a gc and resets the counts.
   1325      */
   1326     public void startAllocCounting() {
   1327         // Before we start trigger a GC and reset the debug counts. Run the
   1328         // finalizers and another GC before starting and stopping the alloc
   1329         // counts. This will free up any objects that were just sitting around
   1330         // waiting for their finalizers to be run.
   1331         Runtime.getRuntime().gc();
   1332         Runtime.getRuntime().runFinalization();
   1333         Runtime.getRuntime().gc();
   1334 
   1335         Debug.resetAllCounts();
   1336 
   1337         // start the counts
   1338         Debug.startAllocCounting();
   1339     }
   1340 
   1341     /*
   1342      * Stops allocation counting.
   1343      */
   1344     public void stopAllocCounting() {
   1345         Runtime.getRuntime().gc();
   1346         Runtime.getRuntime().runFinalization();
   1347         Runtime.getRuntime().gc();
   1348         Debug.stopAllocCounting();
   1349     }
   1350 
   1351     /**
   1352      * If Results already contains Key, it appends Value to the key's ArrayList
   1353      * associated with the key. If the key doesn't already exist in results, it
   1354      * adds the key/value pair to results.
   1355      */
   1356     private void addValue(String key, int value, Bundle results) {
   1357         if (results.containsKey(key)) {
   1358             List<Integer> list = results.getIntegerArrayList(key);
   1359             if (list != null) {
   1360                 list.add(value);
   1361             }
   1362         } else {
   1363             ArrayList<Integer> list = new ArrayList<Integer>();
   1364             list.add(value);
   1365             results.putIntegerArrayList(key, list);
   1366         }
   1367     }
   1368 
   1369     /**
   1370      * Returns a bundle with the current results from the allocation counting.
   1371      */
   1372     public Bundle getAllocCounts() {
   1373         Bundle results = new Bundle();
   1374         results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
   1375         results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
   1376         results.putLong("global_freed_count", Debug.getGlobalFreedCount());
   1377         results.putLong("global_freed_size", Debug.getGlobalFreedSize());
   1378         results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
   1379         return results;
   1380     }
   1381 
   1382     /**
   1383      * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
   1384      * reported are the number of send and the number of received transactions.
   1385      */
   1386     public Bundle getBinderCounts() {
   1387         Bundle results = new Bundle();
   1388         results.putLong("sent_transactions", Debug.getBinderSentTransactions());
   1389         results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
   1390         return results;
   1391     }
   1392 
   1393     /**
   1394      * Description of a Activity execution result to return to the original
   1395      * activity.
   1396      */
   1397     public static final class ActivityResult {
   1398         /**
   1399          * Create a new activity result.  See {@link Activity#setResult} for
   1400          * more information.
   1401          *
   1402          * @param resultCode The result code to propagate back to the
   1403          * originating activity, often RESULT_CANCELED or RESULT_OK
   1404          * @param resultData The data to propagate back to the originating
   1405          * activity.
   1406          */
   1407         public ActivityResult(int resultCode, Intent resultData) {
   1408             mResultCode = resultCode;
   1409             mResultData = resultData;
   1410         }
   1411 
   1412         /**
   1413          * Retrieve the result code contained in this result.
   1414          */
   1415         public int getResultCode() {
   1416             return mResultCode;
   1417         }
   1418 
   1419         /**
   1420          * Retrieve the data contained in this result.
   1421          */
   1422         public Intent getResultData() {
   1423             return mResultData;
   1424         }
   1425 
   1426         private final int mResultCode;
   1427         private final Intent mResultData;
   1428     }
   1429 
   1430     /**
   1431      * Execute a startActivity call made by the application.  The default
   1432      * implementation takes care of updating any active {@link ActivityMonitor}
   1433      * objects and dispatches this call to the system activity manager; you can
   1434      * override this to watch for the application to start an activity, and
   1435      * modify what happens when it does.
   1436      *
   1437      * <p>This method returns an {@link ActivityResult} object, which you can
   1438      * use when intercepting application calls to avoid performing the start
   1439      * activity action but still return the result the application is
   1440      * expecting.  To do this, override this method to catch the call to start
   1441      * activity so that it returns a new ActivityResult containing the results
   1442      * you would like the application to see, and don't call up to the super
   1443      * class.  Note that an application is only expecting a result if
   1444      * <var>requestCode</var> is &gt;= 0.
   1445      *
   1446      * <p>This method throws {@link android.content.ActivityNotFoundException}
   1447      * if there was no Activity found to run the given Intent.
   1448      *
   1449      * @param who The Context from which the activity is being started.
   1450      * @param contextThread The main thread of the Context from which the activity
   1451      *                      is being started.
   1452      * @param token Internal token identifying to the system who is starting
   1453      *              the activity; may be null.
   1454      * @param target Which activity is performing the start (and thus receiving
   1455      *               any result); may be null if this call is not being made
   1456      *               from an activity.
   1457      * @param intent The actual Intent to start.
   1458      * @param requestCode Identifier for this request's result; less than zero
   1459      *                    if the caller is not expecting a result.
   1460      * @param options Addition options.
   1461      *
   1462      * @return To force the return of a particular result, return an
   1463      *         ActivityResult object containing the desired data; otherwise
   1464      *         return null.  The default implementation always returns null.
   1465      *
   1466      * @throws android.content.ActivityNotFoundException
   1467      *
   1468      * @see Activity#startActivity(Intent)
   1469      * @see Activity#startActivityForResult(Intent, int)
   1470      * @see Activity#startActivityFromChild
   1471      *
   1472      * {@hide}
   1473      */
   1474     public ActivityResult execStartActivity(
   1475             Context who, IBinder contextThread, IBinder token, Activity target,
   1476             Intent intent, int requestCode, Bundle options) {
   1477         IApplicationThread whoThread = (IApplicationThread) contextThread;
   1478         if (mActivityMonitors != null) {
   1479             synchronized (mSync) {
   1480                 final int N = mActivityMonitors.size();
   1481                 for (int i=0; i<N; i++) {
   1482                     final ActivityMonitor am = mActivityMonitors.get(i);
   1483                     if (am.match(who, null, intent)) {
   1484                         am.mHits++;
   1485                         if (am.isBlocking()) {
   1486                             return requestCode >= 0 ? am.getResult() : null;
   1487                         }
   1488                         break;
   1489                     }
   1490                 }
   1491             }
   1492         }
   1493         try {
   1494             intent.migrateExtraStreamToClipData();
   1495             intent.prepareToLeaveProcess();
   1496             int result = ActivityManagerNative.getDefault()
   1497                 .startActivity(whoThread, who.getBasePackageName(), intent,
   1498                         intent.resolveTypeIfNeeded(who.getContentResolver()),
   1499                         token, target != null ? target.mEmbeddedID : null,
   1500                         requestCode, 0, null, options);
   1501             checkStartActivityResult(result, intent);
   1502         } catch (RemoteException e) {
   1503         }
   1504         return null;
   1505     }
   1506 
   1507     /**
   1508      * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
   1509      * but accepts an array of activities to be started.  Note that active
   1510      * {@link ActivityMonitor} objects only match against the first activity in
   1511      * the array.
   1512      *
   1513      * {@hide}
   1514      */
   1515     public void execStartActivities(Context who, IBinder contextThread,
   1516             IBinder token, Activity target, Intent[] intents, Bundle options) {
   1517         execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
   1518                 UserHandle.myUserId());
   1519     }
   1520 
   1521     /**
   1522      * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
   1523      * but accepts an array of activities to be started.  Note that active
   1524      * {@link ActivityMonitor} objects only match against the first activity in
   1525      * the array.
   1526      *
   1527      * {@hide}
   1528      */
   1529     public void execStartActivitiesAsUser(Context who, IBinder contextThread,
   1530             IBinder token, Activity target, Intent[] intents, Bundle options,
   1531             int userId) {
   1532         IApplicationThread whoThread = (IApplicationThread) contextThread;
   1533         if (mActivityMonitors != null) {
   1534             synchronized (mSync) {
   1535                 final int N = mActivityMonitors.size();
   1536                 for (int i=0; i<N; i++) {
   1537                     final ActivityMonitor am = mActivityMonitors.get(i);
   1538                     if (am.match(who, null, intents[0])) {
   1539                         am.mHits++;
   1540                         if (am.isBlocking()) {
   1541                             return;
   1542                         }
   1543                         break;
   1544                     }
   1545                 }
   1546             }
   1547         }
   1548         try {
   1549             String[] resolvedTypes = new String[intents.length];
   1550             for (int i=0; i<intents.length; i++) {
   1551                 intents[i].migrateExtraStreamToClipData();
   1552                 intents[i].prepareToLeaveProcess();
   1553                 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
   1554             }
   1555             int result = ActivityManagerNative.getDefault()
   1556                 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
   1557                         token, options, userId);
   1558             checkStartActivityResult(result, intents[0]);
   1559         } catch (RemoteException e) {
   1560         }
   1561     }
   1562 
   1563     /**
   1564      * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
   1565      * android.os.IBinder, Fragment, android.content.Intent, int, android.os.Bundle)},
   1566      * but for calls from a {#link Fragment}.
   1567      *
   1568      * @param who The Context from which the activity is being started.
   1569      * @param contextThread The main thread of the Context from which the activity
   1570      *                      is being started.
   1571      * @param token Internal token identifying to the system who is starting
   1572      *              the activity; may be null.
   1573      * @param target Which fragment is performing the start (and thus receiving
   1574      *               any result).
   1575      * @param intent The actual Intent to start.
   1576      * @param requestCode Identifier for this request's result; less than zero
   1577      *                    if the caller is not expecting a result.
   1578      *
   1579      * @return To force the return of a particular result, return an
   1580      *         ActivityResult object containing the desired data; otherwise
   1581      *         return null.  The default implementation always returns null.
   1582      *
   1583      * @throws android.content.ActivityNotFoundException
   1584      *
   1585      * @see Activity#startActivity(Intent)
   1586      * @see Activity#startActivityForResult(Intent, int)
   1587      * @see Activity#startActivityFromChild
   1588      *
   1589      * {@hide}
   1590      */
   1591     public ActivityResult execStartActivity(
   1592         Context who, IBinder contextThread, IBinder token, Fragment target,
   1593         Intent intent, int requestCode, Bundle options) {
   1594         IApplicationThread whoThread = (IApplicationThread) contextThread;
   1595         if (mActivityMonitors != null) {
   1596             synchronized (mSync) {
   1597                 final int N = mActivityMonitors.size();
   1598                 for (int i=0; i<N; i++) {
   1599                     final ActivityMonitor am = mActivityMonitors.get(i);
   1600                     if (am.match(who, null, intent)) {
   1601                         am.mHits++;
   1602                         if (am.isBlocking()) {
   1603                             return requestCode >= 0 ? am.getResult() : null;
   1604                         }
   1605                         break;
   1606                     }
   1607                 }
   1608             }
   1609         }
   1610         try {
   1611             intent.migrateExtraStreamToClipData();
   1612             intent.prepareToLeaveProcess();
   1613             int result = ActivityManagerNative.getDefault()
   1614                 .startActivity(whoThread, who.getBasePackageName(), intent,
   1615                         intent.resolveTypeIfNeeded(who.getContentResolver()),
   1616                         token, target != null ? target.mWho : null,
   1617                         requestCode, 0, null, options);
   1618             checkStartActivityResult(result, intent);
   1619         } catch (RemoteException e) {
   1620         }
   1621         return null;
   1622     }
   1623 
   1624     /**
   1625      * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
   1626      * but for starting as a particular user.
   1627      *
   1628      * @param who The Context from which the activity is being started.
   1629      * @param contextThread The main thread of the Context from which the activity
   1630      *                      is being started.
   1631      * @param token Internal token identifying to the system who is starting
   1632      *              the activity; may be null.
   1633      * @param target Which fragment is performing the start (and thus receiving
   1634      *               any result).
   1635      * @param intent The actual Intent to start.
   1636      * @param requestCode Identifier for this request's result; less than zero
   1637      *                    if the caller is not expecting a result.
   1638      *
   1639      * @return To force the return of a particular result, return an
   1640      *         ActivityResult object containing the desired data; otherwise
   1641      *         return null.  The default implementation always returns null.
   1642      *
   1643      * @throws android.content.ActivityNotFoundException
   1644      *
   1645      * @see Activity#startActivity(Intent)
   1646      * @see Activity#startActivityForResult(Intent, int)
   1647      * @see Activity#startActivityFromChild
   1648      *
   1649      * {@hide}
   1650      */
   1651     public ActivityResult execStartActivity(
   1652             Context who, IBinder contextThread, IBinder token, Activity target,
   1653             Intent intent, int requestCode, Bundle options, UserHandle user) {
   1654         IApplicationThread whoThread = (IApplicationThread) contextThread;
   1655         if (mActivityMonitors != null) {
   1656             synchronized (mSync) {
   1657                 final int N = mActivityMonitors.size();
   1658                 for (int i=0; i<N; i++) {
   1659                     final ActivityMonitor am = mActivityMonitors.get(i);
   1660                     if (am.match(who, null, intent)) {
   1661                         am.mHits++;
   1662                         if (am.isBlocking()) {
   1663                             return requestCode >= 0 ? am.getResult() : null;
   1664                         }
   1665                         break;
   1666                     }
   1667                 }
   1668             }
   1669         }
   1670         try {
   1671             intent.migrateExtraStreamToClipData();
   1672             intent.prepareToLeaveProcess();
   1673             int result = ActivityManagerNative.getDefault()
   1674                 .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
   1675                         intent.resolveTypeIfNeeded(who.getContentResolver()),
   1676                         token, target != null ? target.mEmbeddedID : null,
   1677                         requestCode, 0, null, options, user.getIdentifier());
   1678             checkStartActivityResult(result, intent);
   1679         } catch (RemoteException e) {
   1680         }
   1681         return null;
   1682     }
   1683 
   1684     /**
   1685      * Special version!
   1686      * @hide
   1687      */
   1688     public ActivityResult execStartActivityAsCaller(
   1689             Context who, IBinder contextThread, IBinder token, Activity target,
   1690             Intent intent, int requestCode, Bundle options, int userId) {
   1691         IApplicationThread whoThread = (IApplicationThread) contextThread;
   1692         if (mActivityMonitors != null) {
   1693             synchronized (mSync) {
   1694                 final int N = mActivityMonitors.size();
   1695                 for (int i=0; i<N; i++) {
   1696                     final ActivityMonitor am = mActivityMonitors.get(i);
   1697                     if (am.match(who, null, intent)) {
   1698                         am.mHits++;
   1699                         if (am.isBlocking()) {
   1700                             return requestCode >= 0 ? am.getResult() : null;
   1701                         }
   1702                         break;
   1703                     }
   1704                 }
   1705             }
   1706         }
   1707         try {
   1708             intent.migrateExtraStreamToClipData();
   1709             intent.prepareToLeaveProcess();
   1710             int result = ActivityManagerNative.getDefault()
   1711                 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
   1712                         intent.resolveTypeIfNeeded(who.getContentResolver()),
   1713                         token, target != null ? target.mEmbeddedID : null,
   1714                         requestCode, 0, null, options, userId);
   1715             checkStartActivityResult(result, intent);
   1716         } catch (RemoteException e) {
   1717         }
   1718         return null;
   1719     }
   1720 
   1721     /**
   1722      * Special version!
   1723      * @hide
   1724      */
   1725     public void execStartActivityFromAppTask(
   1726             Context who, IBinder contextThread, IAppTask appTask,
   1727             Intent intent, Bundle options) {
   1728         IApplicationThread whoThread = (IApplicationThread) contextThread;
   1729         if (mActivityMonitors != null) {
   1730             synchronized (mSync) {
   1731                 final int N = mActivityMonitors.size();
   1732                 for (int i=0; i<N; i++) {
   1733                     final ActivityMonitor am = mActivityMonitors.get(i);
   1734                     if (am.match(who, null, intent)) {
   1735                         am.mHits++;
   1736                         if (am.isBlocking()) {
   1737                             return;
   1738                         }
   1739                         break;
   1740                     }
   1741                 }
   1742             }
   1743         }
   1744         try {
   1745             intent.migrateExtraStreamToClipData();
   1746             intent.prepareToLeaveProcess();
   1747             int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
   1748                     intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options);
   1749             checkStartActivityResult(result, intent);
   1750         } catch (RemoteException e) {
   1751         }
   1752         return;
   1753     }
   1754 
   1755     /*package*/ final void init(ActivityThread thread,
   1756             Context instrContext, Context appContext, ComponentName component,
   1757             IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
   1758         mThread = thread;
   1759         mMessageQueue = mThread.getLooper().myQueue();
   1760         mInstrContext = instrContext;
   1761         mAppContext = appContext;
   1762         mComponent = component;
   1763         mWatcher = watcher;
   1764         mUiAutomationConnection = uiAutomationConnection;
   1765     }
   1766 
   1767     /** @hide */
   1768     public static void checkStartActivityResult(int res, Object intent) {
   1769         if (res >= ActivityManager.START_SUCCESS) {
   1770             return;
   1771         }
   1772 
   1773         switch (res) {
   1774             case ActivityManager.START_INTENT_NOT_RESOLVED:
   1775             case ActivityManager.START_CLASS_NOT_FOUND:
   1776                 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
   1777                     throw new ActivityNotFoundException(
   1778                             "Unable to find explicit activity class "
   1779                             + ((Intent)intent).getComponent().toShortString()
   1780                             + "; have you declared this activity in your AndroidManifest.xml?");
   1781                 throw new ActivityNotFoundException(
   1782                         "No Activity found to handle " + intent);
   1783             case ActivityManager.START_PERMISSION_DENIED:
   1784                 throw new SecurityException("Not allowed to start activity "
   1785                         + intent);
   1786             case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
   1787                 throw new AndroidRuntimeException(
   1788                         "FORWARD_RESULT_FLAG used while also requesting a result");
   1789             case ActivityManager.START_NOT_ACTIVITY:
   1790                 throw new IllegalArgumentException(
   1791                         "PendingIntent is not an activity");
   1792             case ActivityManager.START_NOT_VOICE_COMPATIBLE:
   1793                 throw new SecurityException(
   1794                         "Starting under voice control not allowed for: " + intent);
   1795             default:
   1796                 throw new AndroidRuntimeException("Unknown error code "
   1797                         + res + " when starting " + intent);
   1798         }
   1799     }
   1800 
   1801     private final void validateNotAppThread() {
   1802         if (Looper.myLooper() == Looper.getMainLooper()) {
   1803             throw new RuntimeException(
   1804                 "This method can not be called from the main application thread");
   1805         }
   1806     }
   1807 
   1808     /**
   1809      * Gets the {@link UiAutomation} instance.
   1810      * <p>
   1811      * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
   1812      * work across application boundaries while the APIs exposed by the instrumentation
   1813      * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
   1814      * not allow you to inject the event in an app different from the instrumentation
   1815      * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
   1816      * will work regardless of the current application.
   1817      * </p>
   1818      * <p>
   1819      * A typical test case should be using either the {@link UiAutomation} or
   1820      * {@link Instrumentation} APIs. Using both APIs at the same time is not
   1821      * a mistake by itself but a client has to be aware of the APIs limitations.
   1822      * </p>
   1823      * @return The UI automation instance.
   1824      *
   1825      * @see UiAutomation
   1826      */
   1827     public UiAutomation getUiAutomation() {
   1828         if (mUiAutomationConnection != null) {
   1829             if (mUiAutomation == null) {
   1830                 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
   1831                         mUiAutomationConnection);
   1832                 mUiAutomation.connect();
   1833             }
   1834             return mUiAutomation;
   1835         }
   1836         return null;
   1837     }
   1838 
   1839     private final class InstrumentationThread extends Thread {
   1840         public InstrumentationThread(String name) {
   1841             super(name);
   1842         }
   1843         public void run() {
   1844             try {
   1845                 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
   1846             } catch (RuntimeException e) {
   1847                 Log.w(TAG, "Exception setting priority of instrumentation thread "
   1848                         + Process.myTid(), e);
   1849             }
   1850             if (mAutomaticPerformanceSnapshots) {
   1851                 startPerformanceSnapshot();
   1852             }
   1853             onStart();
   1854         }
   1855     }
   1856 
   1857     private static final class EmptyRunnable implements Runnable {
   1858         public void run() {
   1859         }
   1860     }
   1861 
   1862     private static final class SyncRunnable implements Runnable {
   1863         private final Runnable mTarget;
   1864         private boolean mComplete;
   1865 
   1866         public SyncRunnable(Runnable target) {
   1867             mTarget = target;
   1868         }
   1869 
   1870         public void run() {
   1871             mTarget.run();
   1872             synchronized (this) {
   1873                 mComplete = true;
   1874                 notifyAll();
   1875             }
   1876         }
   1877 
   1878         public void waitForComplete() {
   1879             synchronized (this) {
   1880                 while (!mComplete) {
   1881                     try {
   1882                         wait();
   1883                     } catch (InterruptedException e) {
   1884                     }
   1885                 }
   1886             }
   1887         }
   1888     }
   1889 
   1890     private static final class ActivityWaiter {
   1891         public final Intent intent;
   1892         public Activity activity;
   1893 
   1894         public ActivityWaiter(Intent _intent) {
   1895             intent = _intent;
   1896         }
   1897     }
   1898 
   1899     private final class ActivityGoing implements MessageQueue.IdleHandler {
   1900         private final ActivityWaiter mWaiter;
   1901 
   1902         public ActivityGoing(ActivityWaiter waiter) {
   1903             mWaiter = waiter;
   1904         }
   1905 
   1906         public final boolean queueIdle() {
   1907             synchronized (mSync) {
   1908                 mWaitingActivities.remove(mWaiter);
   1909                 mSync.notifyAll();
   1910             }
   1911             return false;
   1912         }
   1913     }
   1914 
   1915     private static final class Idler implements MessageQueue.IdleHandler {
   1916         private final Runnable mCallback;
   1917         private boolean mIdle;
   1918 
   1919         public Idler(Runnable callback) {
   1920             mCallback = callback;
   1921             mIdle = false;
   1922         }
   1923 
   1924         public final boolean queueIdle() {
   1925             if (mCallback != null) {
   1926                 mCallback.run();
   1927             }
   1928             synchronized (this) {
   1929                 mIdle = true;
   1930                 notifyAll();
   1931             }
   1932             return false;
   1933         }
   1934 
   1935         public void waitForIdle() {
   1936             synchronized (this) {
   1937                 while (!mIdle) {
   1938                     try {
   1939                         wait();
   1940                     } catch (InterruptedException e) {
   1941                     }
   1942                 }
   1943             }
   1944         }
   1945     }
   1946 }
   1947