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