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