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