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