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