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