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