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