[go: nahoru, domu]

Instrumentation.java revision 9ecebbfbf768fd63e9a6c9a09c86d81c7737ee2d
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
17package android.app;
18
19import android.content.ActivityNotFoundException;
20import android.content.ComponentName;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.content.pm.ActivityInfo;
25import android.content.res.Configuration;
26import android.os.Bundle;
27import android.os.PerformanceCollector;
28import android.os.RemoteException;
29import android.os.Debug;
30import android.os.IBinder;
31import android.os.MessageQueue;
32import android.os.Process;
33import android.os.SystemClock;
34import android.os.ServiceManager;
35import android.util.AndroidRuntimeException;
36import android.util.Log;
37import android.view.IWindowManager;
38import android.view.KeyCharacterMap;
39import android.view.KeyEvent;
40import android.view.MotionEvent;
41import android.view.ViewConfiguration;
42import android.view.Window;
43import android.view.inputmethod.InputMethodManager;
44
45import java.io.File;
46import java.util.ArrayList;
47import 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 */
58public 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