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