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