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