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