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