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