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