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