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