• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app;
18 
19 import android.content.ActivityNotFoundException;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.content.pm.ActivityInfo;
25 import android.content.res.Configuration;
26 import android.hardware.input.InputManager;
27 import android.os.Bundle;
28 import android.os.Debug;
29 import android.os.IBinder;
30 import android.os.MessageQueue;
31 import android.os.PerformanceCollector;
32 import android.os.Process;
33 import android.os.RemoteException;
34 import android.os.ServiceManager;
35 import android.os.SystemClock;
36 import android.os.UserHandle;
37 import android.util.AndroidRuntimeException;
38 import android.util.Log;
39 import android.view.IWindowManager;
40 import android.view.InputDevice;
41 import android.view.KeyCharacterMap;
42 import android.view.KeyEvent;
43 import android.view.MotionEvent;
44 import android.view.ViewConfiguration;
45 import android.view.Window;
46 
47 import java.io.File;
48 import java.util.ArrayList;
49 import java.util.List;
50 
51 
52 /**
53  * Base class for implementing application instrumentation code.  When running
54  * with instrumentation turned on, this class will be instantiated for you
55  * before any of the application code, allowing you to monitor all of the
56  * interaction the system has with the application.  An Instrumentation
57  * implementation is described to the system through an AndroidManifest.xml's
58  * <instrumentation> tag.
59  */
60 public class Instrumentation {
61     /**
62      * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
63      * identifies the class that is writing the report.  This can be used to provide more structured
64      * logging or reporting capabilities in the IInstrumentationWatcher.
65      */
66     public static final String REPORT_KEY_IDENTIFIER = "id";
67     /**
68      * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
69      * identifies a string which can simply be printed to the output stream.  Using these streams
70      * provides a "pretty printer" version of the status & final packets.  Any bundles including
71      * this key should also include the complete set of raw key/value pairs, so that the
72      * instrumentation can also be launched, and results collected, by an automated system.
73      */
74     public static final String REPORT_KEY_STREAMRESULT = "stream";
75 
76     private static final String TAG = "Instrumentation";
77 
78     private final Object mSync = new Object();
79     private ActivityThread mThread = null;
80     private MessageQueue mMessageQueue = null;
81     private Context mInstrContext;
82     private Context mAppContext;
83     private ComponentName mComponent;
84     private Thread mRunner;
85     private List<ActivityWaiter> mWaitingActivities;
86     private List<ActivityMonitor> mActivityMonitors;
87     private IInstrumentationWatcher mWatcher;
88     private boolean mAutomaticPerformanceSnapshots = false;
89     private PerformanceCollector mPerformanceCollector;
90     private Bundle mPerfMetrics = new Bundle();
91 
Instrumentation()92     public Instrumentation() {
93     }
94 
95     /**
96      * Called when the instrumentation is starting, before any application code
97      * has been loaded.  Usually this will be implemented to simply call
98      * {@link #start} to begin the instrumentation thread, which will then
99      * continue execution in {@link #onStart}.
100      *
101      * <p>If you do not need your own thread -- that is you are writing your
102      * instrumentation to be completely asynchronous (returning to the event
103      * loop so that the application can run), you can simply begin your
104      * instrumentation here, for example call {@link Context#startActivity} to
105      * begin the appropriate first activity of the application.
106      *
107      * @param arguments Any additional arguments that were supplied when the
108      *                  instrumentation was started.
109      */
onCreate(Bundle arguments)110     public void onCreate(Bundle arguments) {
111     }
112 
113     /**
114      * Create and start a new thread in which to run instrumentation.  This new
115      * thread will call to {@link #onStart} where you can implement the
116      * instrumentation.
117      */
start()118     public void start() {
119         if (mRunner != null) {
120             throw new RuntimeException("Instrumentation already started");
121         }
122         mRunner = new InstrumentationThread("Instr: " + getClass().getName());
123         mRunner.start();
124     }
125 
126     /**
127      * Method where the instrumentation thread enters execution.  This allows
128      * you to run your instrumentation code in a separate thread than the
129      * application, so that it can perform blocking operation such as
130      * {@link #sendKeySync} or {@link #startActivitySync}.
131      *
132      * <p>You will typically want to call finish() when this function is done,
133      * to end your instrumentation.
134      */
onStart()135     public void onStart() {
136     }
137 
138     /**
139      * This is called whenever the system captures an unhandled exception that
140      * was thrown by the application.  The default implementation simply
141      * returns false, allowing normal system handling of the exception to take
142      * place.
143      *
144      * @param obj The client object that generated the exception.  May be an
145      *            Application, Activity, BroadcastReceiver, Service, or null.
146      * @param e The exception that was thrown.
147      *
148      * @return To allow normal system exception process to occur, return false.
149      *         If true is returned, the system will proceed as if the exception
150      *         didn't happen.
151      */
onException(Object obj, Throwable e)152     public boolean onException(Object obj, Throwable e) {
153         return false;
154     }
155 
156     /**
157      * Provide a status report about the application.
158      *
159      * @param resultCode Current success/failure of instrumentation.
160      * @param results Any results to send back to the code that started the instrumentation.
161      */
sendStatus(int resultCode, Bundle results)162     public void sendStatus(int resultCode, Bundle results) {
163         if (mWatcher != null) {
164             try {
165                 mWatcher.instrumentationStatus(mComponent, resultCode, results);
166             }
167             catch (RemoteException e) {
168                 mWatcher = null;
169             }
170         }
171     }
172 
173     /**
174      * Terminate instrumentation of the application.  This will cause the
175      * application process to exit, removing this instrumentation from the next
176      * time the application is started.
177      *
178      * @param resultCode Overall success/failure of instrumentation.
179      * @param results Any results to send back to the code that started the
180      *                instrumentation.
181      */
finish(int resultCode, Bundle results)182     public void finish(int resultCode, Bundle results) {
183         if (mAutomaticPerformanceSnapshots) {
184             endPerformanceSnapshot();
185         }
186         if (mPerfMetrics != null) {
187             results.putAll(mPerfMetrics);
188         }
189         mThread.finishInstrumentation(resultCode, results);
190     }
191 
setAutomaticPerformanceSnapshots()192     public void setAutomaticPerformanceSnapshots() {
193         mAutomaticPerformanceSnapshots = true;
194         mPerformanceCollector = new PerformanceCollector();
195     }
196 
startPerformanceSnapshot()197     public void startPerformanceSnapshot() {
198         if (!isProfiling()) {
199             mPerformanceCollector.beginSnapshot(null);
200         }
201     }
202 
endPerformanceSnapshot()203     public void endPerformanceSnapshot() {
204         if (!isProfiling()) {
205             mPerfMetrics = mPerformanceCollector.endSnapshot();
206         }
207     }
208 
209     /**
210      * Called when the instrumented application is stopping, after all of the
211      * normal application cleanup has occurred.
212      */
onDestroy()213     public void onDestroy() {
214     }
215 
216     /**
217      * Return the Context of this instrumentation's package.  Note that this is
218      * often different than the Context of the application being
219      * instrumentated, since the instrumentation code often lives is a
220      * different package than that of the application it is running against.
221      * See {@link #getTargetContext} to retrieve a Context for the target
222      * application.
223      *
224      * @return The instrumentation's package context.
225      *
226      * @see #getTargetContext
227      */
getContext()228     public Context getContext() {
229         return mInstrContext;
230     }
231 
232     /**
233      * Returns complete component name of this instrumentation.
234      *
235      * @return Returns the complete component name for this instrumentation.
236      */
getComponentName()237     public ComponentName getComponentName() {
238         return mComponent;
239     }
240 
241     /**
242      * Return a Context for the target application being instrumented.  Note
243      * that this is often different than the Context of the instrumentation
244      * code, since the instrumentation code often lives is a different package
245      * than that of the application it is running against. See
246      * {@link #getContext} to retrieve a Context for the instrumentation code.
247      *
248      * @return A Context in the target application.
249      *
250      * @see #getContext
251      */
getTargetContext()252     public Context getTargetContext() {
253         return mAppContext;
254     }
255 
256     /**
257      * Check whether this instrumentation was started with profiling enabled.
258      *
259      * @return Returns true if profiling was enabled when starting, else false.
260      */
isProfiling()261     public boolean isProfiling() {
262         return mThread.isProfiling();
263     }
264 
265     /**
266      * This method will start profiling if isProfiling() returns true. You should
267      * only call this method if you set the handleProfiling attribute in the
268      * manifest file for this Instrumentation to true.
269      */
startProfiling()270     public void startProfiling() {
271         if (mThread.isProfiling()) {
272             File file = new File(mThread.getProfileFilePath());
273             file.getParentFile().mkdirs();
274             Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
275         }
276     }
277 
278     /**
279      * Stops profiling if isProfiling() returns true.
280      */
stopProfiling()281     public void stopProfiling() {
282         if (mThread.isProfiling()) {
283             Debug.stopMethodTracing();
284         }
285     }
286 
287     /**
288      * Force the global system in or out of touch mode.  This can be used if
289      * your instrumentation relies on the UI being in one more or the other
290      * when it starts.
291      *
292      * @param inTouch Set to true to be in touch mode, false to be in
293      * focus mode.
294      */
setInTouchMode(boolean inTouch)295     public void setInTouchMode(boolean inTouch) {
296         try {
297             IWindowManager.Stub.asInterface(
298                     ServiceManager.getService("window")).setInTouchMode(inTouch);
299         } catch (RemoteException e) {
300             // Shouldn't happen!
301         }
302     }
303 
304     /**
305      * Schedule a callback for when the application's main thread goes idle
306      * (has no more events to process).
307      *
308      * @param recipient Called the next time the thread's message queue is
309      *                  idle.
310      */
waitForIdle(Runnable recipient)311     public void waitForIdle(Runnable recipient) {
312         mMessageQueue.addIdleHandler(new Idler(recipient));
313         mThread.getHandler().post(new EmptyRunnable());
314     }
315 
316     /**
317      * Synchronously wait for the application to be idle.  Can not be called
318      * from the main application thread -- use {@link #start} to execute
319      * instrumentation in its own thread.
320      */
waitForIdleSync()321     public void waitForIdleSync() {
322         validateNotAppThread();
323         Idler idler = new Idler(null);
324         mMessageQueue.addIdleHandler(idler);
325         mThread.getHandler().post(new EmptyRunnable());
326         idler.waitForIdle();
327     }
328 
329     /**
330      * Execute a call on the application's main thread, blocking until it is
331      * complete.  Useful for doing things that are not thread-safe, such as
332      * looking at or modifying the view hierarchy.
333      *
334      * @param runner The code to run on the main thread.
335      */
runOnMainSync(Runnable runner)336     public void runOnMainSync(Runnable runner) {
337         validateNotAppThread();
338         SyncRunnable sr = new SyncRunnable(runner);
339         mThread.getHandler().post(sr);
340         sr.waitForComplete();
341     }
342 
343     /**
344      * Start a new activity and wait for it to begin running before returning.
345      * In addition to being synchronous, this method as some semantic
346      * differences from the standard {@link Context#startActivity} call: the
347      * activity component is resolved before talking with the activity manager
348      * (its class name is specified in the Intent that this method ultimately
349      * starts), and it does not allow you to start activities that run in a
350      * different process.  In addition, if the given Intent resolves to
351      * multiple activities, instead of displaying a dialog for the user to
352      * select an activity, an exception will be thrown.
353      *
354      * <p>The function returns as soon as the activity goes idle following the
355      * call to its {@link Activity#onCreate}.  Generally this means it has gone
356      * through the full initialization including {@link Activity#onResume} and
357      * drawn and displayed its initial window.
358      *
359      * @param intent Description of the activity to start.
360      *
361      * @see Context#startActivity
362      */
startActivitySync(Intent intent)363     public Activity startActivitySync(Intent intent) {
364         validateNotAppThread();
365 
366         synchronized (mSync) {
367             intent = new Intent(intent);
368 
369             ActivityInfo ai = intent.resolveActivityInfo(
370                 getTargetContext().getPackageManager(), 0);
371             if (ai == null) {
372                 throw new RuntimeException("Unable to resolve activity for: " + intent);
373             }
374             String myProc = mThread.getProcessName();
375             if (!ai.processName.equals(myProc)) {
376                 // todo: if this intent is ambiguous, look here to see if
377                 // there is a single match that is in our package.
378                 throw new RuntimeException("Intent in process "
379                         + myProc + " resolved to different process "
380                         + ai.processName + ": " + intent);
381             }
382 
383             intent.setComponent(new ComponentName(
384                     ai.applicationInfo.packageName, ai.name));
385             final ActivityWaiter aw = new ActivityWaiter(intent);
386 
387             if (mWaitingActivities == null) {
388                 mWaitingActivities = new ArrayList();
389             }
390             mWaitingActivities.add(aw);
391 
392             getTargetContext().startActivity(intent);
393 
394             do {
395                 try {
396                     mSync.wait();
397                 } catch (InterruptedException e) {
398                 }
399             } while (mWaitingActivities.contains(aw));
400 
401             return aw.activity;
402         }
403     }
404 
405     /**
406      * Information about a particular kind of Intent that is being monitored.
407      * An instance of this class is added to the
408      * current instrumentation through {@link #addMonitor}; after being added,
409      * when a new activity is being started the monitor will be checked and, if
410      * matching, its hit count updated and (optionally) the call stopped and a
411      * canned result returned.
412      *
413      * <p>An ActivityMonitor can also be used to look for the creation of an
414      * activity, through the {@link #waitForActivity} method.  This will return
415      * after a matching activity has been created with that activity object.
416      */
417     public static class ActivityMonitor {
418         private final IntentFilter mWhich;
419         private final String mClass;
420         private final ActivityResult mResult;
421         private final boolean mBlock;
422 
423 
424         // This is protected by 'Instrumentation.this.mSync'.
425         /*package*/ int mHits = 0;
426 
427         // This is protected by 'this'.
428         /*package*/ Activity mLastActivity = null;
429 
430         /**
431          * Create a new ActivityMonitor that looks for a particular kind of
432          * intent to be started.
433          *
434          * @param which The set of intents this monitor is responsible for.
435          * @param result A canned result to return if the monitor is hit; can
436          *               be null.
437          * @param block Controls whether the monitor should block the activity
438          *              start (returning its canned result) or let the call
439          *              proceed.
440          *
441          * @see Instrumentation#addMonitor
442          */
ActivityMonitor( IntentFilter which, ActivityResult result, boolean block)443         public ActivityMonitor(
444             IntentFilter which, ActivityResult result, boolean block) {
445             mWhich = which;
446             mClass = null;
447             mResult = result;
448             mBlock = block;
449         }
450 
451         /**
452          * Create a new ActivityMonitor that looks for a specific activity
453          * class to be started.
454          *
455          * @param cls The activity class this monitor is responsible for.
456          * @param result A canned result to return if the monitor is hit; can
457          *               be null.
458          * @param block Controls whether the monitor should block the activity
459          *              start (returning its canned result) or let the call
460          *              proceed.
461          *
462          * @see Instrumentation#addMonitor
463          */
ActivityMonitor( String cls, ActivityResult result, boolean block)464         public ActivityMonitor(
465             String cls, ActivityResult result, boolean block) {
466             mWhich = null;
467             mClass = cls;
468             mResult = result;
469             mBlock = block;
470         }
471 
472         /**
473          * Retrieve the filter associated with this ActivityMonitor.
474          */
getFilter()475         public final IntentFilter getFilter() {
476             return mWhich;
477         }
478 
479         /**
480          * Retrieve the result associated with this ActivityMonitor, or null if
481          * none.
482          */
getResult()483         public final ActivityResult getResult() {
484             return mResult;
485         }
486 
487         /**
488          * Check whether this monitor blocks activity starts (not allowing the
489          * actual activity to run) or allows them to execute normally.
490          */
isBlocking()491         public final boolean isBlocking() {
492             return mBlock;
493         }
494 
495         /**
496          * Retrieve the number of times the monitor has been hit so far.
497          */
getHits()498         public final int getHits() {
499             return mHits;
500         }
501 
502         /**
503          * Retrieve the most recent activity class that was seen by this
504          * monitor.
505          */
getLastActivity()506         public final Activity getLastActivity() {
507             return mLastActivity;
508         }
509 
510         /**
511          * Block until an Activity is created that matches this monitor,
512          * returning the resulting activity.
513          *
514          * @return Activity
515          */
waitForActivity()516         public final Activity waitForActivity() {
517             synchronized (this) {
518                 while (mLastActivity == null) {
519                     try {
520                         wait();
521                     } catch (InterruptedException e) {
522                     }
523                 }
524                 Activity res = mLastActivity;
525                 mLastActivity = null;
526                 return res;
527             }
528         }
529 
530         /**
531          * Block until an Activity is created that matches this monitor,
532          * returning the resulting activity or till the timeOut period expires.
533          * If the timeOut expires before the activity is started, return null.
534          *
535          * @param timeOut Time to wait before the activity is created.
536          *
537          * @return Activity
538          */
waitForActivityWithTimeout(long timeOut)539         public final Activity waitForActivityWithTimeout(long timeOut) {
540             synchronized (this) {
541                 if (mLastActivity == null) {
542                     try {
543                         wait(timeOut);
544                     } catch (InterruptedException e) {
545                     }
546                 }
547                 if (mLastActivity == null) {
548                     return null;
549                 } else {
550                     Activity res = mLastActivity;
551                     mLastActivity = null;
552                     return res;
553                 }
554             }
555         }
556 
match(Context who, Activity activity, Intent intent)557         final boolean match(Context who,
558                             Activity activity,
559                             Intent intent) {
560             synchronized (this) {
561                 if (mWhich != null
562                     && mWhich.match(who.getContentResolver(), intent,
563                                     true, "Instrumentation") < 0) {
564                     return false;
565                 }
566                 if (mClass != null) {
567                     String cls = null;
568                     if (activity != null) {
569                         cls = activity.getClass().getName();
570                     } else if (intent.getComponent() != null) {
571                         cls = intent.getComponent().getClassName();
572                     }
573                     if (cls == null || !mClass.equals(cls)) {
574                         return false;
575                     }
576                 }
577                 if (activity != null) {
578                     mLastActivity = activity;
579                     notifyAll();
580                 }
581                 return true;
582             }
583         }
584     }
585 
586     /**
587      * Add a new {@link ActivityMonitor} that will be checked whenever an
588      * activity is started.  The monitor is added
589      * after any existing ones; the monitor will be hit only if none of the
590      * existing monitors can themselves handle the Intent.
591      *
592      * @param monitor The new ActivityMonitor to see.
593      *
594      * @see #addMonitor(IntentFilter, ActivityResult, boolean)
595      * @see #checkMonitorHit
596      */
addMonitor(ActivityMonitor monitor)597     public void addMonitor(ActivityMonitor monitor) {
598         synchronized (mSync) {
599             if (mActivityMonitors == null) {
600                 mActivityMonitors = new ArrayList();
601             }
602             mActivityMonitors.add(monitor);
603         }
604     }
605 
606     /**
607      * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
608      * creates an intent filter matching {@link ActivityMonitor} for you and
609      * returns it.
610      *
611      * @param filter The set of intents this monitor is responsible for.
612      * @param result A canned result to return if the monitor is hit; can
613      *               be null.
614      * @param block Controls whether the monitor should block the activity
615      *              start (returning its canned result) or let the call
616      *              proceed.
617      *
618      * @return The newly created and added activity monitor.
619      *
620      * @see #addMonitor(ActivityMonitor)
621      * @see #checkMonitorHit
622      */
addMonitor( IntentFilter filter, ActivityResult result, boolean block)623     public ActivityMonitor addMonitor(
624         IntentFilter filter, ActivityResult result, boolean block) {
625         ActivityMonitor am = new ActivityMonitor(filter, result, block);
626         addMonitor(am);
627         return am;
628     }
629 
630     /**
631      * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
632      * creates a class matching {@link ActivityMonitor} for you and returns it.
633      *
634      * @param cls The activity class this monitor is responsible for.
635      * @param result A canned result to return if the monitor is hit; can
636      *               be null.
637      * @param block Controls whether the monitor should block the activity
638      *              start (returning its canned result) or let the call
639      *              proceed.
640      *
641      * @return The newly created and added activity monitor.
642      *
643      * @see #addMonitor(ActivityMonitor)
644      * @see #checkMonitorHit
645      */
addMonitor( String cls, ActivityResult result, boolean block)646     public ActivityMonitor addMonitor(
647         String cls, ActivityResult result, boolean block) {
648         ActivityMonitor am = new ActivityMonitor(cls, result, block);
649         addMonitor(am);
650         return am;
651     }
652 
653     /**
654      * Test whether an existing {@link ActivityMonitor} has been hit.  If the
655      * monitor has been hit at least <var>minHits</var> times, then it will be
656      * removed from the activity monitor list and true returned.  Otherwise it
657      * is left as-is and false is returned.
658      *
659      * @param monitor The ActivityMonitor to check.
660      * @param minHits The minimum number of hits required.
661      *
662      * @return True if the hit count has been reached, else false.
663      *
664      * @see #addMonitor
665      */
checkMonitorHit(ActivityMonitor monitor, int minHits)666     public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
667         waitForIdleSync();
668         synchronized (mSync) {
669             if (monitor.getHits() < minHits) {
670                 return false;
671             }
672             mActivityMonitors.remove(monitor);
673         }
674         return true;
675     }
676 
677     /**
678      * Wait for an existing {@link ActivityMonitor} to be hit.  Once the
679      * monitor has been hit, it is removed from the activity monitor list and
680      * the first created Activity object that matched it is returned.
681      *
682      * @param monitor The ActivityMonitor to wait for.
683      *
684      * @return The Activity object that matched the monitor.
685      */
waitForMonitor(ActivityMonitor monitor)686     public Activity waitForMonitor(ActivityMonitor monitor) {
687         Activity activity = monitor.waitForActivity();
688         synchronized (mSync) {
689             mActivityMonitors.remove(monitor);
690         }
691         return activity;
692     }
693 
694     /**
695      * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
696      * expires.  Once the monitor has been hit, it is removed from the activity
697      * monitor list and the first created Activity object that matched it is
698      * returned.  If the timeout expires, a null object is returned.
699      *
700      * @param monitor The ActivityMonitor to wait for.
701      * @param timeOut The timeout value in secs.
702      *
703      * @return The Activity object that matched the monitor.
704      */
waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut)705     public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
706         Activity activity = monitor.waitForActivityWithTimeout(timeOut);
707         synchronized (mSync) {
708             mActivityMonitors.remove(monitor);
709         }
710         return activity;
711     }
712 
713     /**
714      * Remove an {@link ActivityMonitor} that was previously added with
715      * {@link #addMonitor}.
716      *
717      * @param monitor The monitor to remove.
718      *
719      * @see #addMonitor
720      */
removeMonitor(ActivityMonitor monitor)721     public void removeMonitor(ActivityMonitor monitor) {
722         synchronized (mSync) {
723             mActivityMonitors.remove(monitor);
724         }
725     }
726 
727     /**
728      * Execute a particular menu item.
729      *
730      * @param targetActivity The activity in question.
731      * @param id The identifier associated with the menu item.
732      * @param flag Additional flags, if any.
733      * @return Whether the invocation was successful (for example, it could be
734      *         false if item is disabled).
735      */
invokeMenuActionSync(Activity targetActivity, int id, int flag)736     public boolean invokeMenuActionSync(Activity targetActivity,
737                                     int id, int flag) {
738         class MenuRunnable implements Runnable {
739             private final Activity activity;
740             private final int identifier;
741             private final int flags;
742             boolean returnValue;
743 
744             public MenuRunnable(Activity _activity, int _identifier,
745                                     int _flags) {
746                 activity = _activity;
747                 identifier = _identifier;
748                 flags = _flags;
749             }
750 
751             public void run() {
752                 Window win = activity.getWindow();
753 
754                 returnValue = win.performPanelIdentifierAction(
755                             Window.FEATURE_OPTIONS_PANEL,
756                             identifier,
757                             flags);
758             }
759 
760         }
761         MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
762         runOnMainSync(mr);
763         return mr.returnValue;
764     }
765 
766     /**
767      * Show the context menu for the currently focused view and executes a
768      * particular context menu item.
769      *
770      * @param targetActivity The activity in question.
771      * @param id The identifier associated with the context menu item.
772      * @param flag Additional flags, if any.
773      * @return Whether the invocation was successful (for example, it could be
774      *         false if item is disabled).
775      */
invokeContextMenuAction(Activity targetActivity, int id, int flag)776     public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
777         validateNotAppThread();
778 
779         // Bring up context menu for current focus.
780         // It'd be nice to do this through code, but currently ListView depends on
781         //   long press to set metadata for its selected child
782 
783         final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
784         sendKeySync(downEvent);
785 
786         // Need to wait for long press
787         waitForIdleSync();
788         try {
789             Thread.sleep(ViewConfiguration.getLongPressTimeout());
790         } catch (InterruptedException e) {
791             Log.e(TAG, "Could not sleep for long press timeout", e);
792             return false;
793         }
794 
795         final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
796         sendKeySync(upEvent);
797 
798         // Wait for context menu to appear
799         waitForIdleSync();
800 
801         class ContextMenuRunnable implements Runnable {
802             private final Activity activity;
803             private final int identifier;
804             private final int flags;
805             boolean returnValue;
806 
807             public ContextMenuRunnable(Activity _activity, int _identifier,
808                                     int _flags) {
809                 activity = _activity;
810                 identifier = _identifier;
811                 flags = _flags;
812             }
813 
814             public void run() {
815                 Window win = activity.getWindow();
816                 returnValue = win.performContextMenuIdentifierAction(
817                             identifier,
818                             flags);
819             }
820 
821         }
822 
823         ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
824         runOnMainSync(cmr);
825         return cmr.returnValue;
826     }
827 
828     /**
829      * Sends the key events corresponding to the text to the app being
830      * instrumented.
831      *
832      * @param text The text to be sent.
833      */
sendStringSync(String text)834     public void sendStringSync(String text) {
835         if (text == null) {
836             return;
837         }
838         KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
839 
840         KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
841 
842         if (events != null) {
843             for (int i = 0; i < events.length; i++) {
844                 // We have to change the time of an event before injecting it because
845                 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
846                 // time stamp and the system rejects too old events. Hence, it is
847                 // possible for an event to become stale before it is injected if it
848                 // takes too long to inject the preceding ones.
849                 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
850             }
851         }
852     }
853 
854     /**
855      * Send a key event to the currently focused window/view and wait for it to
856      * be processed.  Finished at some point after the recipient has returned
857      * from its event processing, though it may <em>not</em> have completely
858      * finished reacting from the event -- for example, if it needs to update
859      * its display as a result, it may still be in the process of doing that.
860      *
861      * @param event The event to send to the current focus.
862      */
sendKeySync(KeyEvent event)863     public void sendKeySync(KeyEvent event) {
864         validateNotAppThread();
865 
866         long downTime = event.getDownTime();
867         long eventTime = event.getEventTime();
868         int action = event.getAction();
869         int code = event.getKeyCode();
870         int repeatCount = event.getRepeatCount();
871         int metaState = event.getMetaState();
872         int deviceId = event.getDeviceId();
873         int scancode = event.getScanCode();
874         int source = event.getSource();
875         int flags = event.getFlags();
876         if (source == InputDevice.SOURCE_UNKNOWN) {
877             source = InputDevice.SOURCE_KEYBOARD;
878         }
879         if (eventTime == 0) {
880             eventTime = SystemClock.uptimeMillis();
881         }
882         if (downTime == 0) {
883             downTime = eventTime;
884         }
885         KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
886                 deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
887         InputManager.getInstance().injectInputEvent(newEvent,
888                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
889     }
890 
891     /**
892      * Sends an up and down key event sync to the currently focused window.
893      *
894      * @param key The integer keycode for the event.
895      */
sendKeyDownUpSync(int key)896     public void sendKeyDownUpSync(int key) {
897         sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
898         sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
899     }
900 
901     /**
902      * Higher-level method for sending both the down and up key events for a
903      * particular character key code.  Equivalent to creating both KeyEvent
904      * objects by hand and calling {@link #sendKeySync}.  The event appears
905      * as if it came from keyboard 0, the built in one.
906      *
907      * @param keyCode The key code of the character to send.
908      */
sendCharacterSync(int keyCode)909     public void sendCharacterSync(int keyCode) {
910         sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
911         sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
912     }
913 
914     /**
915      * Dispatch a pointer event. Finished at some point after the recipient has
916      * returned from its event processing, though it may <em>not</em> have
917      * completely finished reacting from the event -- for example, if it needs
918      * to update its display as a result, it may still be in the process of
919      * doing that.
920      *
921      * @param event A motion event describing the pointer action.  (As noted in
922      * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
923      * {@link SystemClock#uptimeMillis()} as the timebase.
924      */
sendPointerSync(MotionEvent event)925     public void sendPointerSync(MotionEvent event) {
926         validateNotAppThread();
927         if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
928             event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
929         }
930         InputManager.getInstance().injectInputEvent(event,
931                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
932     }
933 
934     /**
935      * Dispatch a trackball event. Finished at some point after the recipient has
936      * returned from its event processing, though it may <em>not</em> have
937      * completely finished reacting from the event -- for example, if it needs
938      * to update its display as a result, it may still be in the process of
939      * doing that.
940      *
941      * @param event A motion event describing the trackball action.  (As noted in
942      * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
943      * {@link SystemClock#uptimeMillis()} as the timebase.
944      */
sendTrackballEventSync(MotionEvent event)945     public void sendTrackballEventSync(MotionEvent event) {
946         validateNotAppThread();
947         if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
948             event.setSource(InputDevice.SOURCE_TRACKBALL);
949         }
950         InputManager.getInstance().injectInputEvent(event,
951                 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
952     }
953 
954     /**
955      * Perform instantiation of the process's {@link Application} object.  The
956      * default implementation provides the normal system behavior.
957      *
958      * @param cl The ClassLoader with which to instantiate the object.
959      * @param className The name of the class implementing the Application
960      *                  object.
961      * @param context The context to initialize the application with
962      *
963      * @return The newly instantiated Application object.
964      */
newApplication(ClassLoader cl, String className, Context context)965     public Application newApplication(ClassLoader cl, String className, Context context)
966             throws InstantiationException, IllegalAccessException,
967             ClassNotFoundException {
968         return newApplication(cl.loadClass(className), context);
969     }
970 
971     /**
972      * Perform instantiation of the process's {@link Application} object.  The
973      * default implementation provides the normal system behavior.
974      *
975      * @param clazz The class used to create an Application object from.
976      * @param context The context to initialize the application with
977      *
978      * @return The newly instantiated Application object.
979      */
newApplication(Class<?> clazz, Context context)980     static public Application newApplication(Class<?> clazz, Context context)
981             throws InstantiationException, IllegalAccessException,
982             ClassNotFoundException {
983         Application app = (Application)clazz.newInstance();
984         app.attach(context);
985         return app;
986     }
987 
988     /**
989      * Perform calling of the application's {@link Application#onCreate}
990      * method.  The default implementation simply calls through to that method.
991      *
992      * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
993      * Often instrumentation tests start their test thread in onCreate(); you
994      * need to be careful of races between these.  (Well between it and
995      * everything else, but let's start here.)
996      *
997      * @param app The application being created.
998      */
callApplicationOnCreate(Application app)999     public void callApplicationOnCreate(Application app) {
1000         app.onCreate();
1001     }
1002 
1003     /**
1004      * Perform instantiation of an {@link Activity} object.  This method is intended for use with
1005      * unit tests, such as android.test.ActivityUnitTestCase.  The activity will be useable
1006      * locally but will be missing some of the linkages necessary for use within the sytem.
1007      *
1008      * @param clazz The Class of the desired Activity
1009      * @param context The base context for the activity to use
1010      * @param token The token for this activity to communicate with
1011      * @param application The application object (if any)
1012      * @param intent The intent that started this Activity
1013      * @param info ActivityInfo from the manifest
1014      * @param title The title, typically retrieved from the ActivityInfo record
1015      * @param parent The parent Activity (if any)
1016      * @param id The embedded Id (if any)
1017      * @param lastNonConfigurationInstance Arbitrary object that will be
1018      * available via {@link Activity#getLastNonConfigurationInstance()
1019      * Activity.getLastNonConfigurationInstance()}.
1020      * @return Returns the instantiated activity
1021      * @throws InstantiationException
1022      * @throws IllegalAccessException
1023      */
newActivity(Class<?> clazz, Context context, IBinder token, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, Object lastNonConfigurationInstance)1024     public Activity newActivity(Class<?> clazz, Context context,
1025             IBinder token, Application application, Intent intent, ActivityInfo info,
1026             CharSequence title, Activity parent, String id,
1027             Object lastNonConfigurationInstance) throws InstantiationException,
1028             IllegalAccessException {
1029         Activity activity = (Activity)clazz.newInstance();
1030         ActivityThread aThread = null;
1031         activity.attach(context, aThread, this, token, application, intent,
1032                 info, title, parent, id,
1033                 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
1034                 new Configuration());
1035         return activity;
1036     }
1037 
1038     /**
1039      * Perform instantiation of the process's {@link Activity} object.  The
1040      * default implementation provides the normal system behavior.
1041      *
1042      * @param cl The ClassLoader with which to instantiate the object.
1043      * @param className The name of the class implementing the Activity
1044      *                  object.
1045      * @param intent The Intent object that specified the activity class being
1046      *               instantiated.
1047      *
1048      * @return The newly instantiated Activity object.
1049      */
newActivity(ClassLoader cl, String className, Intent intent)1050     public Activity newActivity(ClassLoader cl, String className,
1051             Intent intent)
1052             throws InstantiationException, IllegalAccessException,
1053             ClassNotFoundException {
1054         return (Activity)cl.loadClass(className).newInstance();
1055     }
1056 
1057     /**
1058      * Perform calling of an activity's {@link Activity#onCreate}
1059      * method.  The default implementation simply calls through to that method.
1060      *
1061      * @param activity The activity being created.
1062      * @param icicle The previously frozen state (or null) to pass through to
1063      *               onCreate().
1064      */
callActivityOnCreate(Activity activity, Bundle icicle)1065     public void callActivityOnCreate(Activity activity, Bundle icicle) {
1066         if (mWaitingActivities != null) {
1067             synchronized (mSync) {
1068                 final int N = mWaitingActivities.size();
1069                 for (int i=0; i<N; i++) {
1070                     final ActivityWaiter aw = mWaitingActivities.get(i);
1071                     final Intent intent = aw.intent;
1072                     if (intent.filterEquals(activity.getIntent())) {
1073                         aw.activity = activity;
1074                         mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1075                     }
1076                 }
1077             }
1078         }
1079 
1080         activity.performCreate(icicle);
1081 
1082         if (mActivityMonitors != null) {
1083             synchronized (mSync) {
1084                 final int N = mActivityMonitors.size();
1085                 for (int i=0; i<N; i++) {
1086                     final ActivityMonitor am = mActivityMonitors.get(i);
1087                     am.match(activity, activity, activity.getIntent());
1088                 }
1089             }
1090         }
1091     }
1092 
callActivityOnDestroy(Activity activity)1093     public void callActivityOnDestroy(Activity activity) {
1094       // TODO: the following block causes intermittent hangs when using startActivity
1095       // temporarily comment out until root cause is fixed (bug 2630683)
1096 //      if (mWaitingActivities != null) {
1097 //          synchronized (mSync) {
1098 //              final int N = mWaitingActivities.size();
1099 //              for (int i=0; i<N; i++) {
1100 //                  final ActivityWaiter aw = mWaitingActivities.get(i);
1101 //                  final Intent intent = aw.intent;
1102 //                  if (intent.filterEquals(activity.getIntent())) {
1103 //                      aw.activity = activity;
1104 //                      mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1105 //                  }
1106 //              }
1107 //          }
1108 //      }
1109 
1110       activity.performDestroy();
1111 
1112       if (mActivityMonitors != null) {
1113           synchronized (mSync) {
1114               final int N = mActivityMonitors.size();
1115               for (int i=0; i<N; i++) {
1116                   final ActivityMonitor am = mActivityMonitors.get(i);
1117                   am.match(activity, activity, activity.getIntent());
1118               }
1119           }
1120       }
1121   }
1122 
1123     /**
1124      * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1125      * method.  The default implementation simply calls through to that method.
1126      *
1127      * @param activity The activity being restored.
1128      * @param savedInstanceState The previously saved state being restored.
1129      */
callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState)1130     public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
1131         activity.performRestoreInstanceState(savedInstanceState);
1132     }
1133 
1134     /**
1135      * Perform calling of an activity's {@link Activity#onPostCreate} method.
1136      * The default implementation simply calls through to that method.
1137      *
1138      * @param activity The activity being created.
1139      * @param icicle The previously frozen state (or null) to pass through to
1140      *               onPostCreate().
1141      */
callActivityOnPostCreate(Activity activity, Bundle icicle)1142     public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
1143         activity.onPostCreate(icicle);
1144     }
1145 
1146     /**
1147      * Perform calling of an activity's {@link Activity#onNewIntent}
1148      * method.  The default implementation simply calls through to that method.
1149      *
1150      * @param activity The activity receiving a new Intent.
1151      * @param intent The new intent being received.
1152      */
callActivityOnNewIntent(Activity activity, Intent intent)1153     public void callActivityOnNewIntent(Activity activity, Intent intent) {
1154         activity.onNewIntent(intent);
1155     }
1156 
1157     /**
1158      * Perform calling of an activity's {@link Activity#onStart}
1159      * method.  The default implementation simply calls through to that method.
1160      *
1161      * @param activity The activity being started.
1162      */
callActivityOnStart(Activity activity)1163     public void callActivityOnStart(Activity activity) {
1164         activity.onStart();
1165     }
1166 
1167     /**
1168      * Perform calling of an activity's {@link Activity#onRestart}
1169      * method.  The default implementation simply calls through to that method.
1170      *
1171      * @param activity The activity being restarted.
1172      */
callActivityOnRestart(Activity activity)1173     public void callActivityOnRestart(Activity activity) {
1174         activity.onRestart();
1175     }
1176 
1177     /**
1178      * Perform calling of an activity's {@link Activity#onResume} method.  The
1179      * default implementation simply calls through to that method.
1180      *
1181      * @param activity The activity being resumed.
1182      */
callActivityOnResume(Activity activity)1183     public void callActivityOnResume(Activity activity) {
1184         activity.mResumed = true;
1185         activity.onResume();
1186 
1187         if (mActivityMonitors != null) {
1188             synchronized (mSync) {
1189                 final int N = mActivityMonitors.size();
1190                 for (int i=0; i<N; i++) {
1191                     final ActivityMonitor am = mActivityMonitors.get(i);
1192                     am.match(activity, activity, activity.getIntent());
1193                 }
1194             }
1195         }
1196     }
1197 
1198     /**
1199      * Perform calling of an activity's {@link Activity#onStop}
1200      * method.  The default implementation simply calls through to that method.
1201      *
1202      * @param activity The activity being stopped.
1203      */
callActivityOnStop(Activity activity)1204     public void callActivityOnStop(Activity activity) {
1205         activity.onStop();
1206     }
1207 
1208     /**
1209      * Perform calling of an activity's {@link Activity#onPause} method.  The
1210      * default implementation simply calls through to that method.
1211      *
1212      * @param activity The activity being saved.
1213      * @param outState The bundle to pass to the call.
1214      */
callActivityOnSaveInstanceState(Activity activity, Bundle outState)1215     public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
1216         activity.performSaveInstanceState(outState);
1217     }
1218 
1219     /**
1220      * Perform calling of an activity's {@link Activity#onPause} method.  The
1221      * default implementation simply calls through to that method.
1222      *
1223      * @param activity The activity being paused.
1224      */
callActivityOnPause(Activity activity)1225     public void callActivityOnPause(Activity activity) {
1226         activity.performPause();
1227     }
1228 
1229     /**
1230      * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
1231      * The default implementation simply calls through to that method.
1232      *
1233      * @param activity The activity being notified that the user has navigated away
1234      */
callActivityOnUserLeaving(Activity activity)1235     public void callActivityOnUserLeaving(Activity activity) {
1236         activity.performUserLeaving();
1237     }
1238 
1239     /*
1240      * Starts allocation counting. This triggers a gc and resets the counts.
1241      */
startAllocCounting()1242     public void startAllocCounting() {
1243         // Before we start trigger a GC and reset the debug counts. Run the
1244         // finalizers and another GC before starting and stopping the alloc
1245         // counts. This will free up any objects that were just sitting around
1246         // waiting for their finalizers to be run.
1247         Runtime.getRuntime().gc();
1248         Runtime.getRuntime().runFinalization();
1249         Runtime.getRuntime().gc();
1250 
1251         Debug.resetAllCounts();
1252 
1253         // start the counts
1254         Debug.startAllocCounting();
1255     }
1256 
1257     /*
1258      * Stops allocation counting.
1259      */
stopAllocCounting()1260     public void stopAllocCounting() {
1261         Runtime.getRuntime().gc();
1262         Runtime.getRuntime().runFinalization();
1263         Runtime.getRuntime().gc();
1264         Debug.stopAllocCounting();
1265     }
1266 
1267     /**
1268      * If Results already contains Key, it appends Value to the key's ArrayList
1269      * associated with the key. If the key doesn't already exist in results, it
1270      * adds the key/value pair to results.
1271      */
addValue(String key, int value, Bundle results)1272     private void addValue(String key, int value, Bundle results) {
1273         if (results.containsKey(key)) {
1274             List<Integer> list = results.getIntegerArrayList(key);
1275             if (list != null) {
1276                 list.add(value);
1277             }
1278         } else {
1279             ArrayList<Integer> list = new ArrayList<Integer>();
1280             list.add(value);
1281             results.putIntegerArrayList(key, list);
1282         }
1283     }
1284 
1285     /**
1286      * Returns a bundle with the current results from the allocation counting.
1287      */
getAllocCounts()1288     public Bundle getAllocCounts() {
1289         Bundle results = new Bundle();
1290         results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
1291         results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
1292         results.putLong("global_freed_count", Debug.getGlobalFreedCount());
1293         results.putLong("global_freed_size", Debug.getGlobalFreedSize());
1294         results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
1295         return results;
1296     }
1297 
1298     /**
1299      * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
1300      * reported are the number of send and the number of received transactions.
1301      */
getBinderCounts()1302     public Bundle getBinderCounts() {
1303         Bundle results = new Bundle();
1304         results.putLong("sent_transactions", Debug.getBinderSentTransactions());
1305         results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
1306         return results;
1307     }
1308 
1309     /**
1310      * Description of a Activity execution result to return to the original
1311      * activity.
1312      */
1313     public static final class ActivityResult {
1314         /**
1315          * Create a new activity result.  See {@link Activity#setResult} for
1316          * more information.
1317          *
1318          * @param resultCode The result code to propagate back to the
1319          * originating activity, often RESULT_CANCELED or RESULT_OK
1320          * @param resultData The data to propagate back to the originating
1321          * activity.
1322          */
ActivityResult(int resultCode, Intent resultData)1323         public ActivityResult(int resultCode, Intent resultData) {
1324             mResultCode = resultCode;
1325             mResultData = resultData;
1326         }
1327 
1328         /**
1329          * Retrieve the result code contained in this result.
1330          */
getResultCode()1331         public int getResultCode() {
1332             return mResultCode;
1333         }
1334 
1335         /**
1336          * Retrieve the data contained in this result.
1337          */
getResultData()1338         public Intent getResultData() {
1339             return mResultData;
1340         }
1341 
1342         private final int mResultCode;
1343         private final Intent mResultData;
1344     }
1345 
1346     /**
1347      * Execute a startActivity call made by the application.  The default
1348      * implementation takes care of updating any active {@link ActivityMonitor}
1349      * objects and dispatches this call to the system activity manager; you can
1350      * override this to watch for the application to start an activity, and
1351      * modify what happens when it does.
1352      *
1353      * <p>This method returns an {@link ActivityResult} object, which you can
1354      * use when intercepting application calls to avoid performing the start
1355      * activity action but still return the result the application is
1356      * expecting.  To do this, override this method to catch the call to start
1357      * activity so that it returns a new ActivityResult containing the results
1358      * you would like the application to see, and don't call up to the super
1359      * class.  Note that an application is only expecting a result if
1360      * <var>requestCode</var> is &gt;= 0.
1361      *
1362      * <p>This method throws {@link android.content.ActivityNotFoundException}
1363      * if there was no Activity found to run the given Intent.
1364      *
1365      * @param who The Context from which the activity is being started.
1366      * @param contextThread The main thread of the Context from which the activity
1367      *                      is being started.
1368      * @param token Internal token identifying to the system who is starting
1369      *              the activity; may be null.
1370      * @param target Which activity is performing the start (and thus receiving
1371      *               any result); may be null if this call is not being made
1372      *               from an activity.
1373      * @param intent The actual Intent to start.
1374      * @param requestCode Identifier for this request's result; less than zero
1375      *                    if the caller is not expecting a result.
1376      * @param options Addition options.
1377      *
1378      * @return To force the return of a particular result, return an
1379      *         ActivityResult object containing the desired data; otherwise
1380      *         return null.  The default implementation always returns null.
1381      *
1382      * @throws android.content.ActivityNotFoundException
1383      *
1384      * @see Activity#startActivity(Intent)
1385      * @see Activity#startActivityForResult(Intent, int)
1386      * @see Activity#startActivityFromChild
1387      *
1388      * {@hide}
1389      */
execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options)1390     public ActivityResult execStartActivity(
1391             Context who, IBinder contextThread, IBinder token, Activity target,
1392             Intent intent, int requestCode, Bundle options) {
1393         IApplicationThread whoThread = (IApplicationThread) contextThread;
1394         if (mActivityMonitors != null) {
1395             synchronized (mSync) {
1396                 final int N = mActivityMonitors.size();
1397                 for (int i=0; i<N; i++) {
1398                     final ActivityMonitor am = mActivityMonitors.get(i);
1399                     if (am.match(who, null, intent)) {
1400                         am.mHits++;
1401                         if (am.isBlocking()) {
1402                             return requestCode >= 0 ? am.getResult() : null;
1403                         }
1404                         break;
1405                     }
1406                 }
1407             }
1408         }
1409         try {
1410             intent.setAllowFds(false);
1411             intent.migrateExtraStreamToClipData();
1412             int result = ActivityManagerNative.getDefault()
1413                 .startActivity(whoThread, intent,
1414                         intent.resolveTypeIfNeeded(who.getContentResolver()),
1415                         token, target != null ? target.mEmbeddedID : null,
1416                         requestCode, 0, null, null, options);
1417             checkStartActivityResult(result, intent);
1418         } catch (RemoteException e) {
1419         }
1420         return null;
1421     }
1422 
1423     /**
1424      * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)},
1425      * but accepts an array of activities to be started.  Note that active
1426      * {@link ActivityMonitor} objects only match against the first activity in
1427      * the array.
1428      *
1429      * {@hide}
1430      */
execStartActivities(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options)1431     public void execStartActivities(Context who, IBinder contextThread,
1432             IBinder token, Activity target, Intent[] intents, Bundle options) {
1433         execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
1434                 UserHandle.myUserId());
1435     }
1436 
1437     /**
1438      * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)},
1439      * but accepts an array of activities to be started.  Note that active
1440      * {@link ActivityMonitor} objects only match against the first activity in
1441      * the array.
1442      *
1443      * {@hide}
1444      */
execStartActivitiesAsUser(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options, int userId)1445     public void execStartActivitiesAsUser(Context who, IBinder contextThread,
1446             IBinder token, Activity target, Intent[] intents, Bundle options,
1447             int userId) {
1448         IApplicationThread whoThread = (IApplicationThread) contextThread;
1449         if (mActivityMonitors != null) {
1450             synchronized (mSync) {
1451                 final int N = mActivityMonitors.size();
1452                 for (int i=0; i<N; i++) {
1453                     final ActivityMonitor am = mActivityMonitors.get(i);
1454                     if (am.match(who, null, intents[0])) {
1455                         am.mHits++;
1456                         if (am.isBlocking()) {
1457                             return;
1458                         }
1459                         break;
1460                     }
1461                 }
1462             }
1463         }
1464         try {
1465             String[] resolvedTypes = new String[intents.length];
1466             for (int i=0; i<intents.length; i++) {
1467                 intents[i].setAllowFds(false);
1468                 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
1469             }
1470             int result = ActivityManagerNative.getDefault()
1471                 .startActivities(whoThread, intents, resolvedTypes, token, options,
1472                         userId);
1473             checkStartActivityResult(result, intents[0]);
1474         } catch (RemoteException e) {
1475         }
1476     }
1477 
1478     /**
1479      * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)},
1480      * but for calls from a {#link Fragment}.
1481      *
1482      * @param who The Context from which the activity is being started.
1483      * @param contextThread The main thread of the Context from which the activity
1484      *                      is being started.
1485      * @param token Internal token identifying to the system who is starting
1486      *              the activity; may be null.
1487      * @param target Which fragment is performing the start (and thus receiving
1488      *               any result).
1489      * @param intent The actual Intent to start.
1490      * @param requestCode Identifier for this request's result; less than zero
1491      *                    if the caller is not expecting a result.
1492      *
1493      * @return To force the return of a particular result, return an
1494      *         ActivityResult object containing the desired data; otherwise
1495      *         return null.  The default implementation always returns null.
1496      *
1497      * @throws android.content.ActivityNotFoundException
1498      *
1499      * @see Activity#startActivity(Intent)
1500      * @see Activity#startActivityForResult(Intent, int)
1501      * @see Activity#startActivityFromChild
1502      *
1503      * {@hide}
1504      */
execStartActivity( Context who, IBinder contextThread, IBinder token, Fragment target, Intent intent, int requestCode, Bundle options)1505     public ActivityResult execStartActivity(
1506         Context who, IBinder contextThread, IBinder token, Fragment target,
1507         Intent intent, int requestCode, Bundle options) {
1508         IApplicationThread whoThread = (IApplicationThread) contextThread;
1509         if (mActivityMonitors != null) {
1510             synchronized (mSync) {
1511                 final int N = mActivityMonitors.size();
1512                 for (int i=0; i<N; i++) {
1513                     final ActivityMonitor am = mActivityMonitors.get(i);
1514                     if (am.match(who, null, intent)) {
1515                         am.mHits++;
1516                         if (am.isBlocking()) {
1517                             return requestCode >= 0 ? am.getResult() : null;
1518                         }
1519                         break;
1520                     }
1521                 }
1522             }
1523         }
1524         try {
1525             intent.setAllowFds(false);
1526             intent.migrateExtraStreamToClipData();
1527             int result = ActivityManagerNative.getDefault()
1528                 .startActivity(whoThread, intent,
1529                         intent.resolveTypeIfNeeded(who.getContentResolver()),
1530                         token, target != null ? target.mWho : null,
1531                         requestCode, 0, null, null, options);
1532             checkStartActivityResult(result, intent);
1533         } catch (RemoteException e) {
1534         }
1535         return null;
1536     }
1537 
1538     /**
1539      * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)},
1540      * but for starting as a particular user.
1541      *
1542      * @param who The Context from which the activity is being started.
1543      * @param contextThread The main thread of the Context from which the activity
1544      *                      is being started.
1545      * @param token Internal token identifying to the system who is starting
1546      *              the activity; may be null.
1547      * @param target Which fragment is performing the start (and thus receiving
1548      *               any result).
1549      * @param intent The actual Intent to start.
1550      * @param requestCode Identifier for this request's result; less than zero
1551      *                    if the caller is not expecting a result.
1552      *
1553      * @return To force the return of a particular result, return an
1554      *         ActivityResult object containing the desired data; otherwise
1555      *         return null.  The default implementation always returns null.
1556      *
1557      * @throws android.content.ActivityNotFoundException
1558      *
1559      * @see Activity#startActivity(Intent)
1560      * @see Activity#startActivityForResult(Intent, int)
1561      * @see Activity#startActivityFromChild
1562      *
1563      * {@hide}
1564      */
execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options, UserHandle user)1565     public ActivityResult execStartActivity(
1566             Context who, IBinder contextThread, IBinder token, Activity target,
1567             Intent intent, int requestCode, Bundle options, UserHandle user) {
1568         IApplicationThread whoThread = (IApplicationThread) contextThread;
1569         if (mActivityMonitors != null) {
1570             synchronized (mSync) {
1571                 final int N = mActivityMonitors.size();
1572                 for (int i=0; i<N; i++) {
1573                     final ActivityMonitor am = mActivityMonitors.get(i);
1574                     if (am.match(who, null, intent)) {
1575                         am.mHits++;
1576                         if (am.isBlocking()) {
1577                             return requestCode >= 0 ? am.getResult() : null;
1578                         }
1579                         break;
1580                     }
1581                 }
1582             }
1583         }
1584         try {
1585             intent.setAllowFds(false);
1586             intent.migrateExtraStreamToClipData();
1587             int result = ActivityManagerNative.getDefault()
1588                 .startActivityAsUser(whoThread, intent,
1589                         intent.resolveTypeIfNeeded(who.getContentResolver()),
1590                         token, target != null ? target.mEmbeddedID : null,
1591                         requestCode, 0, null, null, options, user.getIdentifier());
1592             checkStartActivityResult(result, intent);
1593         } catch (RemoteException e) {
1594         }
1595         return null;
1596     }
1597 
init(ActivityThread thread, Context instrContext, Context appContext, ComponentName component, IInstrumentationWatcher watcher)1598     /*package*/ final void init(ActivityThread thread,
1599             Context instrContext, Context appContext, ComponentName component,
1600             IInstrumentationWatcher watcher) {
1601         mThread = thread;
1602         mMessageQueue = mThread.getLooper().myQueue();
1603         mInstrContext = instrContext;
1604         mAppContext = appContext;
1605         mComponent = component;
1606         mWatcher = watcher;
1607     }
1608 
checkStartActivityResult(int res, Object intent)1609     /*package*/ static void checkStartActivityResult(int res, Object intent) {
1610         if (res >= ActivityManager.START_SUCCESS) {
1611             return;
1612         }
1613 
1614         switch (res) {
1615             case ActivityManager.START_INTENT_NOT_RESOLVED:
1616             case ActivityManager.START_CLASS_NOT_FOUND:
1617                 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
1618                     throw new ActivityNotFoundException(
1619                             "Unable to find explicit activity class "
1620                             + ((Intent)intent).getComponent().toShortString()
1621                             + "; have you declared this activity in your AndroidManifest.xml?");
1622                 throw new ActivityNotFoundException(
1623                         "No Activity found to handle " + intent);
1624             case ActivityManager.START_PERMISSION_DENIED:
1625                 throw new SecurityException("Not allowed to start activity "
1626                         + intent);
1627             case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
1628                 throw new AndroidRuntimeException(
1629                         "FORWARD_RESULT_FLAG used while also requesting a result");
1630             case ActivityManager.START_NOT_ACTIVITY:
1631                 throw new IllegalArgumentException(
1632                         "PendingIntent is not an activity");
1633             default:
1634                 throw new AndroidRuntimeException("Unknown error code "
1635                         + res + " when starting " + intent);
1636         }
1637     }
1638 
validateNotAppThread()1639     private final void validateNotAppThread() {
1640         if (ActivityThread.currentActivityThread() != null) {
1641             throw new RuntimeException(
1642                 "This method can not be called from the main application thread");
1643         }
1644     }
1645 
1646     private final class InstrumentationThread extends Thread {
InstrumentationThread(String name)1647         public InstrumentationThread(String name) {
1648             super(name);
1649         }
run()1650         public void run() {
1651             IActivityManager am = ActivityManagerNative.getDefault();
1652             try {
1653                 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
1654             } catch (RuntimeException e) {
1655                 Log.w(TAG, "Exception setting priority of instrumentation thread "
1656                         + Process.myTid(), e);
1657             }
1658             if (mAutomaticPerformanceSnapshots) {
1659                 startPerformanceSnapshot();
1660             }
1661             onStart();
1662         }
1663     }
1664 
1665     private static final class EmptyRunnable implements Runnable {
run()1666         public void run() {
1667         }
1668     }
1669 
1670     private static final class SyncRunnable implements Runnable {
1671         private final Runnable mTarget;
1672         private boolean mComplete;
1673 
SyncRunnable(Runnable target)1674         public SyncRunnable(Runnable target) {
1675             mTarget = target;
1676         }
1677 
run()1678         public void run() {
1679             mTarget.run();
1680             synchronized (this) {
1681                 mComplete = true;
1682                 notifyAll();
1683             }
1684         }
1685 
waitForComplete()1686         public void waitForComplete() {
1687             synchronized (this) {
1688                 while (!mComplete) {
1689                     try {
1690                         wait();
1691                     } catch (InterruptedException e) {
1692                     }
1693                 }
1694             }
1695         }
1696     }
1697 
1698     private static final class ActivityWaiter {
1699         public final Intent intent;
1700         public Activity activity;
1701 
ActivityWaiter(Intent _intent)1702         public ActivityWaiter(Intent _intent) {
1703             intent = _intent;
1704         }
1705     }
1706 
1707     private final class ActivityGoing implements MessageQueue.IdleHandler {
1708         private final ActivityWaiter mWaiter;
1709 
ActivityGoing(ActivityWaiter waiter)1710         public ActivityGoing(ActivityWaiter waiter) {
1711             mWaiter = waiter;
1712         }
1713 
queueIdle()1714         public final boolean queueIdle() {
1715             synchronized (mSync) {
1716                 mWaitingActivities.remove(mWaiter);
1717                 mSync.notifyAll();
1718             }
1719             return false;
1720         }
1721     }
1722 
1723     private static final class Idler implements MessageQueue.IdleHandler {
1724         private final Runnable mCallback;
1725         private boolean mIdle;
1726 
Idler(Runnable callback)1727         public Idler(Runnable callback) {
1728             mCallback = callback;
1729             mIdle = false;
1730         }
1731 
queueIdle()1732         public final boolean queueIdle() {
1733             if (mCallback != null) {
1734                 mCallback.run();
1735             }
1736             synchronized (this) {
1737                 mIdle = true;
1738                 notifyAll();
1739             }
1740             return false;
1741         }
1742 
waitForIdle()1743         public void waitForIdle() {
1744             synchronized (this) {
1745                 while (!mIdle) {
1746                     try {
1747                         wait();
1748                     } catch (InterruptedException e) {
1749                     }
1750                 }
1751             }
1752         }
1753     }
1754 }
1755