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