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