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