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