• 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.os.Bundle;
27 import android.os.PerformanceCollector;
28 import android.os.RemoteException;
29 import android.os.Debug;
30 import android.os.IBinder;
31 import android.os.MessageQueue;
32 import android.os.Process;
33 import android.os.SystemClock;
34 import android.os.ServiceManager;
35 import android.util.AndroidRuntimeException;
36 import android.util.Config;
37 import android.util.Log;
38 import android.view.IWindowManager;
39 import android.view.KeyCharacterMap;
40 import android.view.KeyEvent;
41 import android.view.MotionEvent;
42 import android.view.ViewConfiguration;
43 import android.view.Window;
44 import android.view.inputmethod.InputMethodManager;
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                 try {
541                     wait(timeOut);
542                 } catch (InterruptedException e) {
543                 }
544                 if (mLastActivity == null) {
545                     return null;
546                 } else {
547                     Activity res = mLastActivity;
548                     mLastActivity = null;
549                     return res;
550                 }
551             }
552         }
553 
match(Context who, Activity activity, Intent intent)554         final boolean match(Context who,
555                             Activity activity,
556                             Intent intent) {
557             synchronized (this) {
558                 if (mWhich != null
559                     && mWhich.match(who.getContentResolver(), intent,
560                                     true, "Instrumentation") < 0) {
561                     return false;
562                 }
563                 if (mClass != null) {
564                     String cls = null;
565                     if (activity != null) {
566                         cls = activity.getClass().getName();
567                     } else if (intent.getComponent() != null) {
568                         cls = intent.getComponent().getClassName();
569                     }
570                     if (cls == null || !mClass.equals(cls)) {
571                         return false;
572                     }
573                 }
574                 if (activity != null) {
575                     mLastActivity = activity;
576                     notifyAll();
577                 }
578                 return true;
579             }
580         }
581     }
582 
583     /**
584      * Add a new {@link ActivityMonitor} that will be checked whenever an
585      * activity is started.  The monitor is added
586      * after any existing ones; the monitor will be hit only if none of the
587      * existing monitors can themselves handle the Intent.
588      *
589      * @param monitor The new ActivityMonitor to see.
590      *
591      * @see #addMonitor(IntentFilter, ActivityResult, boolean)
592      * @see #checkMonitorHit
593      */
addMonitor(ActivityMonitor monitor)594     public void addMonitor(ActivityMonitor monitor) {
595         synchronized (mSync) {
596             if (mActivityMonitors == null) {
597                 mActivityMonitors = new ArrayList();
598             }
599             mActivityMonitors.add(monitor);
600         }
601     }
602 
603     /**
604      * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
605      * creates an intent filter matching {@link ActivityMonitor} for you and
606      * returns it.
607      *
608      * @param filter The set of intents this monitor is responsible for.
609      * @param result A canned result to return if the monitor is hit; can
610      *               be null.
611      * @param block Controls whether the monitor should block the activity
612      *              start (returning its canned result) or let the call
613      *              proceed.
614      *
615      * @return The newly created and added activity monitor.
616      *
617      * @see #addMonitor(ActivityMonitor)
618      * @see #checkMonitorHit
619      */
addMonitor( IntentFilter filter, ActivityResult result, boolean block)620     public ActivityMonitor addMonitor(
621         IntentFilter filter, ActivityResult result, boolean block) {
622         ActivityMonitor am = new ActivityMonitor(filter, result, block);
623         addMonitor(am);
624         return am;
625     }
626 
627     /**
628      * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
629      * creates a class matching {@link ActivityMonitor} for you and returns it.
630      *
631      * @param cls The activity class this monitor is responsible for.
632      * @param result A canned result to return if the monitor is hit; can
633      *               be null.
634      * @param block Controls whether the monitor should block the activity
635      *              start (returning its canned result) or let the call
636      *              proceed.
637      *
638      * @return The newly created and added activity monitor.
639      *
640      * @see #addMonitor(ActivityMonitor)
641      * @see #checkMonitorHit
642      */
addMonitor( String cls, ActivityResult result, boolean block)643     public ActivityMonitor addMonitor(
644         String cls, ActivityResult result, boolean block) {
645         ActivityMonitor am = new ActivityMonitor(cls, result, block);
646         addMonitor(am);
647         return am;
648     }
649 
650     /**
651      * Test whether an existing {@link ActivityMonitor} has been hit.  If the
652      * monitor has been hit at least <var>minHits</var> times, then it will be
653      * removed from the activity monitor list and true returned.  Otherwise it
654      * is left as-is and false is returned.
655      *
656      * @param monitor The ActivityMonitor to check.
657      * @param minHits The minimum number of hits required.
658      *
659      * @return True if the hit count has been reached, else false.
660      *
661      * @see #addMonitor
662      */
checkMonitorHit(ActivityMonitor monitor, int minHits)663     public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
664         waitForIdleSync();
665         synchronized (mSync) {
666             if (monitor.getHits() < minHits) {
667                 return false;
668             }
669             mActivityMonitors.remove(monitor);
670         }
671         return true;
672     }
673 
674     /**
675      * Wait for an existing {@link ActivityMonitor} to be hit.  Once the
676      * monitor has been hit, it is removed from the activity monitor list and
677      * the first created Activity object that matched it is returned.
678      *
679      * @param monitor The ActivityMonitor to wait for.
680      *
681      * @return The Activity object that matched the monitor.
682      */
waitForMonitor(ActivityMonitor monitor)683     public Activity waitForMonitor(ActivityMonitor monitor) {
684         Activity activity = monitor.waitForActivity();
685         synchronized (mSync) {
686             mActivityMonitors.remove(monitor);
687         }
688         return activity;
689     }
690 
691     /**
692      * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
693      * expires.  Once the monitor has been hit, it is removed from the activity
694      * monitor list and the first created Activity object that matched it is
695      * returned.  If the timeout expires, a null object is returned.
696      *
697      * @param monitor The ActivityMonitor to wait for.
698      * @param timeOut The timeout value in secs.
699      *
700      * @return The Activity object that matched the monitor.
701      */
waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut)702     public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
703         Activity activity = monitor.waitForActivityWithTimeout(timeOut);
704         synchronized (mSync) {
705             mActivityMonitors.remove(monitor);
706         }
707         return activity;
708     }
709 
710     /**
711      * Remove an {@link ActivityMonitor} that was previously added with
712      * {@link #addMonitor}.
713      *
714      * @param monitor The monitor to remove.
715      *
716      * @see #addMonitor
717      */
removeMonitor(ActivityMonitor monitor)718     public void removeMonitor(ActivityMonitor monitor) {
719         synchronized (mSync) {
720             mActivityMonitors.remove(monitor);
721         }
722     }
723 
724     /**
725      * Execute a particular menu item.
726      *
727      * @param targetActivity The activity in question.
728      * @param id The identifier associated with the menu item.
729      * @param flag Additional flags, if any.
730      * @return Whether the invocation was successful (for example, it could be
731      *         false if item is disabled).
732      */
invokeMenuActionSync(Activity targetActivity, int id, int flag)733     public boolean invokeMenuActionSync(Activity targetActivity,
734                                     int id, int flag) {
735         class MenuRunnable implements Runnable {
736             private final Activity activity;
737             private final int identifier;
738             private final int flags;
739             boolean returnValue;
740 
741             public MenuRunnable(Activity _activity, int _identifier,
742                                     int _flags) {
743                 activity = _activity;
744                 identifier = _identifier;
745                 flags = _flags;
746             }
747 
748             public void run() {
749                 Window win = activity.getWindow();
750 
751                 returnValue = win.performPanelIdentifierAction(
752                             Window.FEATURE_OPTIONS_PANEL,
753                             identifier,
754                             flags);
755             }
756 
757         }
758         MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
759         runOnMainSync(mr);
760         return mr.returnValue;
761     }
762 
763     /**
764      * Show the context menu for the currently focused view and executes a
765      * particular context menu item.
766      *
767      * @param targetActivity The activity in question.
768      * @param id The identifier associated with the context menu item.
769      * @param flag Additional flags, if any.
770      * @return Whether the invocation was successful (for example, it could be
771      *         false if item is disabled).
772      */
invokeContextMenuAction(Activity targetActivity, int id, int flag)773     public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
774         validateNotAppThread();
775 
776         // Bring up context menu for current focus.
777         // It'd be nice to do this through code, but currently ListView depends on
778         //   long press to set metadata for its selected child
779 
780         final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
781         sendKeySync(downEvent);
782 
783         // Need to wait for long press
784         waitForIdleSync();
785         try {
786             Thread.sleep(ViewConfiguration.getLongPressTimeout());
787         } catch (InterruptedException e) {
788             Log.e(TAG, "Could not sleep for long press timeout", e);
789             return false;
790         }
791 
792         final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
793         sendKeySync(upEvent);
794 
795         // Wait for context menu to appear
796         waitForIdleSync();
797 
798         class ContextMenuRunnable implements Runnable {
799             private final Activity activity;
800             private final int identifier;
801             private final int flags;
802             boolean returnValue;
803 
804             public ContextMenuRunnable(Activity _activity, int _identifier,
805                                     int _flags) {
806                 activity = _activity;
807                 identifier = _identifier;
808                 flags = _flags;
809             }
810 
811             public void run() {
812                 Window win = activity.getWindow();
813                 returnValue = win.performContextMenuIdentifierAction(
814                             identifier,
815                             flags);
816             }
817 
818         }
819 
820         ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
821         runOnMainSync(cmr);
822         return cmr.returnValue;
823     }
824 
825     /**
826      * Sends the key events corresponding to the text to the app being
827      * instrumented.
828      *
829      * @param text The text to be sent.
830      */
sendStringSync(String text)831     public void sendStringSync(String text) {
832         if (text == null) {
833             return;
834         }
835         KeyCharacterMap keyCharacterMap =
836             KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
837 
838         KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
839 
840         if (events != null) {
841             for (int i = 0; i < events.length; i++) {
842                 sendKeySync(events[i]);
843             }
844         }
845     }
846 
847     /**
848      * Send a key event to the currently focused window/view and wait for it to
849      * be processed.  Finished at some point after the recipient has returned
850      * from its event processing, though it may <em>not</em> have completely
851      * finished reacting from the event -- for example, if it needs to update
852      * its display as a result, it may still be in the process of doing that.
853      *
854      * @param event The event to send to the current focus.
855      */
sendKeySync(KeyEvent event)856     public void sendKeySync(KeyEvent event) {
857         validateNotAppThread();
858         try {
859             (IWindowManager.Stub.asInterface(ServiceManager.getService("window")))
860                 .injectKeyEvent(event, true);
861         } catch (RemoteException e) {
862         }
863     }
864 
865     /**
866      * Sends an up and down key event sync to the currently focused window.
867      *
868      * @param key The integer keycode for the event.
869      */
sendKeyDownUpSync(int key)870     public void sendKeyDownUpSync(int key) {
871         sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
872         sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
873     }
874 
875     /**
876      * Higher-level method for sending both the down and up key events for a
877      * particular character key code.  Equivalent to creating both KeyEvent
878      * objects by hand and calling {@link #sendKeySync}.  The event appears
879      * as if it came from keyboard 0, the built in one.
880      *
881      * @param keyCode The key code of the character to send.
882      */
sendCharacterSync(int keyCode)883     public void sendCharacterSync(int keyCode) {
884         sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
885         sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
886     }
887 
888     /**
889      * Dispatch a pointer event. Finished at some point after the recipient has
890      * returned from its event processing, though it may <em>not</em> have
891      * completely finished reacting from the event -- for example, if it needs
892      * to update its display as a result, it may still be in the process of
893      * doing that.
894      *
895      * @param event A motion event describing the pointer action.  (As noted in
896      * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
897      * {@link SystemClock#uptimeMillis()} as the timebase.
898      */
sendPointerSync(MotionEvent event)899     public void sendPointerSync(MotionEvent event) {
900         validateNotAppThread();
901         try {
902             (IWindowManager.Stub.asInterface(ServiceManager.getService("window")))
903                 .injectPointerEvent(event, true);
904         } catch (RemoteException e) {
905         }
906     }
907 
908     /**
909      * Dispatch a trackball event. Finished at some point after the recipient has
910      * returned from its event processing, though it may <em>not</em> have
911      * completely finished reacting from the event -- for example, if it needs
912      * to update its display as a result, it may still be in the process of
913      * doing that.
914      *
915      * @param event A motion event describing the trackball action.  (As noted in
916      * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
917      * {@link SystemClock#uptimeMillis()} as the timebase.
918      */
sendTrackballEventSync(MotionEvent event)919     public void sendTrackballEventSync(MotionEvent event) {
920         validateNotAppThread();
921         try {
922             (IWindowManager.Stub.asInterface(ServiceManager.getService("window")))
923                 .injectTrackballEvent(event, true);
924         } catch (RemoteException e) {
925         }
926     }
927 
928     /**
929      * Perform instantiation of the process's {@link Application} object.  The
930      * default implementation provides the normal system behavior.
931      *
932      * @param cl The ClassLoader with which to instantiate the object.
933      * @param className The name of the class implementing the Application
934      *                  object.
935      * @param context The context to initialize the application with
936      *
937      * @return The newly instantiated Application object.
938      */
newApplication(ClassLoader cl, String className, Context context)939     public Application newApplication(ClassLoader cl, String className, Context context)
940             throws InstantiationException, IllegalAccessException,
941             ClassNotFoundException {
942         return newApplication(cl.loadClass(className), context);
943     }
944 
945     /**
946      * Perform instantiation of the process's {@link Application} object.  The
947      * default implementation provides the normal system behavior.
948      *
949      * @param clazz The class used to create an Application object from.
950      * @param context The context to initialize the application with
951      *
952      * @return The newly instantiated Application object.
953      */
newApplication(Class<?> clazz, Context context)954     static public Application newApplication(Class<?> clazz, Context context)
955             throws InstantiationException, IllegalAccessException,
956             ClassNotFoundException {
957         Application app = (Application)clazz.newInstance();
958         app.attach(context);
959         return app;
960     }
961 
962     /**
963      * Perform calling of the application's {@link Application#onCreate}
964      * method.  The default implementation simply calls through to that method.
965      *
966      * @param app The application being created.
967      */
callApplicationOnCreate(Application app)968     public void callApplicationOnCreate(Application app) {
969         app.onCreate();
970     }
971 
972     /**
973      * Perform instantiation of an {@link Activity} object.  This method is intended for use with
974      * unit tests, such as android.test.ActivityUnitTestCase.  The activity will be useable
975      * locally but will be missing some of the linkages necessary for use within the sytem.
976      *
977      * @param clazz The Class of the desired Activity
978      * @param context The base context for the activity to use
979      * @param token The token for this activity to communicate with
980      * @param application The application object (if any)
981      * @param intent The intent that started this Activity
982      * @param info ActivityInfo from the manifest
983      * @param title The title, typically retrieved from the ActivityInfo record
984      * @param parent The parent Activity (if any)
985      * @param id The embedded Id (if any)
986      * @param lastNonConfigurationInstance Arbitrary object that will be
987      * available via {@link Activity#getLastNonConfigurationInstance()
988      * Activity.getLastNonConfigurationInstance()}.
989      * @return Returns the instantiated activity
990      * @throws InstantiationException
991      * @throws IllegalAccessException
992      */
newActivity(Class<?> clazz, Context context, IBinder token, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, Object lastNonConfigurationInstance)993     public Activity newActivity(Class<?> clazz, Context context,
994             IBinder token, Application application, Intent intent, ActivityInfo info,
995             CharSequence title, Activity parent, String id,
996             Object lastNonConfigurationInstance) throws InstantiationException,
997             IllegalAccessException {
998         Activity activity = (Activity)clazz.newInstance();
999         ActivityThread aThread = null;
1000         activity.attach(context, aThread, this, token, application, intent, info, title,
1001                 parent, id, lastNonConfigurationInstance, new Configuration());
1002         return activity;
1003     }
1004 
1005     /**
1006      * Perform instantiation of the process's {@link Activity} object.  The
1007      * default implementation provides the normal system behavior.
1008      *
1009      * @param cl The ClassLoader with which to instantiate the object.
1010      * @param className The name of the class implementing the Activity
1011      *                  object.
1012      * @param intent The Intent object that specified the activity class being
1013      *               instantiated.
1014      *
1015      * @return The newly instantiated Activity object.
1016      */
newActivity(ClassLoader cl, String className, Intent intent)1017     public Activity newActivity(ClassLoader cl, String className,
1018             Intent intent)
1019             throws InstantiationException, IllegalAccessException,
1020             ClassNotFoundException {
1021         return (Activity)cl.loadClass(className).newInstance();
1022     }
1023 
1024     /**
1025      * Perform calling of an activity's {@link Activity#onCreate}
1026      * method.  The default implementation simply calls through to that method.
1027      *
1028      * @param activity The activity being created.
1029      * @param icicle The previously frozen state (or null) to pass through to
1030      *               onCreate().
1031      */
callActivityOnCreate(Activity activity, Bundle icicle)1032     public void callActivityOnCreate(Activity activity, Bundle icicle) {
1033         if (mWaitingActivities != null) {
1034             synchronized (mSync) {
1035                 final int N = mWaitingActivities.size();
1036                 for (int i=0; i<N; i++) {
1037                     final ActivityWaiter aw = mWaitingActivities.get(i);
1038                     final Intent intent = aw.intent;
1039                     if (intent.filterEquals(activity.getIntent())) {
1040                         aw.activity = activity;
1041                         mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1042                     }
1043                 }
1044             }
1045         }
1046 
1047         activity.onCreate(icicle);
1048 
1049         if (mActivityMonitors != null) {
1050             synchronized (mSync) {
1051                 final int N = mActivityMonitors.size();
1052                 for (int i=0; i<N; i++) {
1053                     final ActivityMonitor am = mActivityMonitors.get(i);
1054                     am.match(activity, activity, activity.getIntent());
1055                 }
1056             }
1057         }
1058     }
1059 
callActivityOnDestroy(Activity activity)1060     public void callActivityOnDestroy(Activity activity) {
1061       if (mWaitingActivities != null) {
1062           synchronized (mSync) {
1063               final int N = mWaitingActivities.size();
1064               for (int i=0; i<N; i++) {
1065                   final ActivityWaiter aw = mWaitingActivities.get(i);
1066                   final Intent intent = aw.intent;
1067                   if (intent.filterEquals(activity.getIntent())) {
1068                       aw.activity = activity;
1069                       mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1070                   }
1071               }
1072           }
1073       }
1074 
1075       activity.onDestroy();
1076 
1077       if (mActivityMonitors != null) {
1078           synchronized (mSync) {
1079               final int N = mActivityMonitors.size();
1080               for (int i=0; i<N; i++) {
1081                   final ActivityMonitor am = mActivityMonitors.get(i);
1082                   am.match(activity, activity, activity.getIntent());
1083               }
1084           }
1085       }
1086   }
1087 
1088     /**
1089      * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1090      * method.  The default implementation simply calls through to that method.
1091      *
1092      * @param activity The activity being restored.
1093      * @param savedInstanceState The previously saved state being restored.
1094      */
callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState)1095     public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
1096         activity.performRestoreInstanceState(savedInstanceState);
1097     }
1098 
1099     /**
1100      * Perform calling of an activity's {@link Activity#onPostCreate} method.
1101      * The default implementation simply calls through to that method.
1102      *
1103      * @param activity The activity being created.
1104      * @param icicle The previously frozen state (or null) to pass through to
1105      *               onPostCreate().
1106      */
callActivityOnPostCreate(Activity activity, Bundle icicle)1107     public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
1108         activity.onPostCreate(icicle);
1109     }
1110 
1111     /**
1112      * Perform calling of an activity's {@link Activity#onNewIntent}
1113      * method.  The default implementation simply calls through to that method.
1114      *
1115      * @param activity The activity receiving a new Intent.
1116      * @param intent The new intent being received.
1117      */
callActivityOnNewIntent(Activity activity, Intent intent)1118     public void callActivityOnNewIntent(Activity activity, Intent intent) {
1119         activity.onNewIntent(intent);
1120     }
1121 
1122     /**
1123      * Perform calling of an activity's {@link Activity#onStart}
1124      * method.  The default implementation simply calls through to that method.
1125      *
1126      * @param activity The activity being started.
1127      */
callActivityOnStart(Activity activity)1128     public void callActivityOnStart(Activity activity) {
1129         activity.onStart();
1130     }
1131 
1132     /**
1133      * Perform calling of an activity's {@link Activity#onRestart}
1134      * method.  The default implementation simply calls through to that method.
1135      *
1136      * @param activity The activity being restarted.
1137      */
callActivityOnRestart(Activity activity)1138     public void callActivityOnRestart(Activity activity) {
1139         activity.onRestart();
1140     }
1141 
1142     /**
1143      * Perform calling of an activity's {@link Activity#onResume} method.  The
1144      * default implementation simply calls through to that method.
1145      *
1146      * @param activity The activity being resumed.
1147      */
callActivityOnResume(Activity activity)1148     public void callActivityOnResume(Activity activity) {
1149         activity.onResume();
1150 
1151         if (mActivityMonitors != null) {
1152             synchronized (mSync) {
1153                 final int N = mActivityMonitors.size();
1154                 for (int i=0; i<N; i++) {
1155                     final ActivityMonitor am = mActivityMonitors.get(i);
1156                     am.match(activity, activity, activity.getIntent());
1157                 }
1158             }
1159         }
1160     }
1161 
1162     /**
1163      * Perform calling of an activity's {@link Activity#onStop}
1164      * method.  The default implementation simply calls through to that method.
1165      *
1166      * @param activity The activity being stopped.
1167      */
callActivityOnStop(Activity activity)1168     public void callActivityOnStop(Activity activity) {
1169         activity.onStop();
1170     }
1171 
1172     /**
1173      * Perform calling of an activity's {@link Activity#onPause} method.  The
1174      * default implementation simply calls through to that method.
1175      *
1176      * @param activity The activity being saved.
1177      * @param outState The bundle to pass to the call.
1178      */
callActivityOnSaveInstanceState(Activity activity, Bundle outState)1179     public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
1180         activity.performSaveInstanceState(outState);
1181     }
1182 
1183     /**
1184      * Perform calling of an activity's {@link Activity#onPause} method.  The
1185      * default implementation simply calls through to that method.
1186      *
1187      * @param activity The activity being paused.
1188      */
callActivityOnPause(Activity activity)1189     public void callActivityOnPause(Activity activity) {
1190         activity.performPause();
1191     }
1192 
1193     /**
1194      * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
1195      * The default implementation simply calls through to that method.
1196      *
1197      * @param activity The activity being notified that the user has navigated away
1198      */
callActivityOnUserLeaving(Activity activity)1199     public void callActivityOnUserLeaving(Activity activity) {
1200         activity.performUserLeaving();
1201     }
1202 
1203     /*
1204      * Starts allocation counting. This triggers a gc and resets the counts.
1205      */
startAllocCounting()1206     public void startAllocCounting() {
1207         // Before we start trigger a GC and reset the debug counts. Run the
1208         // finalizers and another GC before starting and stopping the alloc
1209         // counts. This will free up any objects that were just sitting around
1210         // waiting for their finalizers to be run.
1211         Runtime.getRuntime().gc();
1212         Runtime.getRuntime().runFinalization();
1213         Runtime.getRuntime().gc();
1214 
1215         Debug.resetAllCounts();
1216 
1217         // start the counts
1218         Debug.startAllocCounting();
1219     }
1220 
1221     /*
1222      * Stops allocation counting.
1223      */
stopAllocCounting()1224     public void stopAllocCounting() {
1225         Runtime.getRuntime().gc();
1226         Runtime.getRuntime().runFinalization();
1227         Runtime.getRuntime().gc();
1228         Debug.stopAllocCounting();
1229     }
1230 
1231     /**
1232      * If Results already contains Key, it appends Value to the key's ArrayList
1233      * associated with the key. If the key doesn't already exist in results, it
1234      * adds the key/value pair to results.
1235      */
addValue(String key, int value, Bundle results)1236     private void addValue(String key, int value, Bundle results) {
1237         if (results.containsKey(key)) {
1238             List<Integer> list = results.getIntegerArrayList(key);
1239             if (list != null) {
1240                 list.add(value);
1241             }
1242         } else {
1243             ArrayList<Integer> list = new ArrayList<Integer>();
1244             list.add(value);
1245             results.putIntegerArrayList(key, list);
1246         }
1247     }
1248 
1249     /**
1250      * Returns a bundle with the current results from the allocation counting.
1251      */
getAllocCounts()1252     public Bundle getAllocCounts() {
1253         Bundle results = new Bundle();
1254         results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
1255         results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
1256         results.putLong("global_freed_count", Debug.getGlobalFreedCount());
1257         results.putLong("global_freed_size", Debug.getGlobalFreedSize());
1258         results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
1259         return results;
1260     }
1261 
1262     /**
1263      * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
1264      * reported are the number of send and the number of received transactions.
1265      */
getBinderCounts()1266     public Bundle getBinderCounts() {
1267         Bundle results = new Bundle();
1268         results.putLong("sent_transactions", Debug.getBinderSentTransactions());
1269         results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
1270         return results;
1271     }
1272 
1273     /**
1274      * Description of a Activity execution result to return to the original
1275      * activity.
1276      */
1277     public static final class ActivityResult {
1278         /**
1279          * Create a new activity result.  See {@link Activity#setResult} for
1280          * more information.
1281          *
1282          * @param resultCode The result code to propagate back to the
1283          * originating activity, often RESULT_CANCELED or RESULT_OK
1284          * @param resultData The data to propagate back to the originating
1285          * activity.
1286          */
ActivityResult(int resultCode, Intent resultData)1287         public ActivityResult(int resultCode, Intent resultData) {
1288             mResultCode = resultCode;
1289             mResultData = resultData;
1290         }
1291 
1292         /**
1293          * Retrieve the result code contained in this result.
1294          */
getResultCode()1295         public int getResultCode() {
1296             return mResultCode;
1297         }
1298 
1299         /**
1300          * Retrieve the data contained in this result.
1301          */
getResultData()1302         public Intent getResultData() {
1303             return mResultData;
1304         }
1305 
1306         private final int mResultCode;
1307         private final Intent mResultData;
1308     }
1309 
1310     /**
1311      * Execute a startActivity call made by the application.  The default
1312      * implementation takes care of updating any active {@link ActivityMonitor}
1313      * objects and dispatches this call to the system activity manager; you can
1314      * override this to watch for the application to start an activity, and
1315      * modify what happens when it does.
1316      *
1317      * <p>This method returns an {@link ActivityResult} object, which you can
1318      * use when intercepting application calls to avoid performing the start
1319      * activity action but still return the result the application is
1320      * expecting.  To do this, override this method to catch the call to start
1321      * activity so that it returns a new ActivityResult containing the results
1322      * you would like the application to see, and don't call up to the super
1323      * class.  Note that an application is only expecting a result if
1324      * <var>requestCode</var> is &gt;= 0.
1325      *
1326      * <p>This method throws {@link android.content.ActivityNotFoundException}
1327      * if there was no Activity found to run the given Intent.
1328      *
1329      * @param who The Context from which the activity is being started.
1330      * @param contextThread The main thread of the Context from which the activity
1331      *                      is being started.
1332      * @param token Internal token identifying to the system who is starting
1333      *              the activity; may be null.
1334      * @param target Which activity is perform the start (and thus receiving
1335      *               any result); may be null if this call is not being made
1336      *               from an activity.
1337      * @param intent The actual Intent to start.
1338      * @param requestCode Identifier for this request's result; less than zero
1339      *                    if the caller is not expecting a result.
1340      *
1341      * @return To force the return of a particular result, return an
1342      *         ActivityResult object containing the desired data; otherwise
1343      *         return null.  The default implementation always returns null.
1344      *
1345      * @throws android.content.ActivityNotFoundException
1346      *
1347      * @see Activity#startActivity(Intent)
1348      * @see Activity#startActivityForResult(Intent, int)
1349      * @see Activity#startActivityFromChild
1350      *
1351      * {@hide}
1352      */
execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode)1353     public ActivityResult execStartActivity(
1354         Context who, IBinder contextThread, IBinder token, Activity target,
1355         Intent intent, int requestCode) {
1356         IApplicationThread whoThread = (IApplicationThread) contextThread;
1357         if (mActivityMonitors != null) {
1358             synchronized (mSync) {
1359                 final int N = mActivityMonitors.size();
1360                 for (int i=0; i<N; i++) {
1361                     final ActivityMonitor am = mActivityMonitors.get(i);
1362                     if (am.match(who, null, intent)) {
1363                         am.mHits++;
1364                         if (am.isBlocking()) {
1365                             return requestCode >= 0 ? am.getResult() : null;
1366                         }
1367                         break;
1368                     }
1369                 }
1370             }
1371         }
1372         try {
1373             int result = ActivityManagerNative.getDefault()
1374                 .startActivity(whoThread, intent,
1375                         intent.resolveTypeIfNeeded(who.getContentResolver()),
1376                         null, 0, token, target != null ? target.mEmbeddedID : null,
1377                         requestCode, false, false);
1378             checkStartActivityResult(result, intent);
1379         } catch (RemoteException e) {
1380         }
1381         return null;
1382     }
1383 
init(ActivityThread thread, Context instrContext, Context appContext, ComponentName component, IInstrumentationWatcher watcher)1384     /*package*/ final void init(ActivityThread thread,
1385             Context instrContext, Context appContext, ComponentName component,
1386             IInstrumentationWatcher watcher) {
1387         mThread = thread;
1388         mMessageQueue = mThread.getLooper().myQueue();
1389         mInstrContext = instrContext;
1390         mAppContext = appContext;
1391         mComponent = component;
1392         mWatcher = watcher;
1393     }
1394 
checkStartActivityResult(int res, Object intent)1395     /*package*/ static void checkStartActivityResult(int res, Object intent) {
1396         if (res >= IActivityManager.START_SUCCESS) {
1397             return;
1398         }
1399 
1400         switch (res) {
1401             case IActivityManager.START_INTENT_NOT_RESOLVED:
1402             case IActivityManager.START_CLASS_NOT_FOUND:
1403                 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
1404                     throw new ActivityNotFoundException(
1405                             "Unable to find explicit activity class "
1406                             + ((Intent)intent).getComponent().toShortString()
1407                             + "; have you declared this activity in your AndroidManifest.xml?");
1408                 throw new ActivityNotFoundException(
1409                         "No Activity found to handle " + intent);
1410             case IActivityManager.START_PERMISSION_DENIED:
1411                 throw new SecurityException("Not allowed to start activity "
1412                         + intent);
1413             case IActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
1414                 throw new AndroidRuntimeException(
1415                         "FORWARD_RESULT_FLAG used while also requesting a result");
1416             case IActivityManager.START_NOT_ACTIVITY:
1417                 throw new IllegalArgumentException(
1418                         "PendingIntent is not an activity");
1419             default:
1420                 throw new AndroidRuntimeException("Unknown error code "
1421                         + res + " when starting " + intent);
1422         }
1423     }
1424 
validateNotAppThread()1425     private final void validateNotAppThread() {
1426         if (ActivityThread.currentActivityThread() != null) {
1427             throw new RuntimeException(
1428                 "This method can not be called from the main application thread");
1429         }
1430     }
1431 
1432     private final class InstrumentationThread extends Thread {
InstrumentationThread(String name)1433         public InstrumentationThread(String name) {
1434             super(name);
1435         }
run()1436         public void run() {
1437             IActivityManager am = ActivityManagerNative.getDefault();
1438             try {
1439                 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
1440             } catch (RuntimeException e) {
1441                 Log.w(TAG, "Exception setting priority of instrumentation thread "
1442                         + Process.myTid(), e);
1443             }
1444             if (mAutomaticPerformanceSnapshots) {
1445                 startPerformanceSnapshot();
1446             }
1447             onStart();
1448         }
1449     }
1450 
1451     private static final class EmptyRunnable implements Runnable {
run()1452         public void run() {
1453         }
1454     }
1455 
1456     private static final class SyncRunnable implements Runnable {
1457         private final Runnable mTarget;
1458         private boolean mComplete;
1459 
SyncRunnable(Runnable target)1460         public SyncRunnable(Runnable target) {
1461             mTarget = target;
1462         }
1463 
run()1464         public void run() {
1465             mTarget.run();
1466             synchronized (this) {
1467                 mComplete = true;
1468                 notifyAll();
1469             }
1470         }
1471 
waitForComplete()1472         public void waitForComplete() {
1473             synchronized (this) {
1474                 while (!mComplete) {
1475                     try {
1476                         wait();
1477                     } catch (InterruptedException e) {
1478                     }
1479                 }
1480             }
1481         }
1482     }
1483 
1484     private static final class ActivityWaiter {
1485         public final Intent intent;
1486         public Activity activity;
1487 
ActivityWaiter(Intent _intent)1488         public ActivityWaiter(Intent _intent) {
1489             intent = _intent;
1490         }
1491     }
1492 
1493     private final class ActivityGoing implements MessageQueue.IdleHandler {
1494         private final ActivityWaiter mWaiter;
1495 
ActivityGoing(ActivityWaiter waiter)1496         public ActivityGoing(ActivityWaiter waiter) {
1497             mWaiter = waiter;
1498         }
1499 
queueIdle()1500         public final boolean queueIdle() {
1501             synchronized (mSync) {
1502                 mWaitingActivities.remove(mWaiter);
1503                 mSync.notifyAll();
1504             }
1505             return false;
1506         }
1507     }
1508 
1509     private static final class Idler implements MessageQueue.IdleHandler {
1510         private final Runnable mCallback;
1511         private boolean mIdle;
1512 
Idler(Runnable callback)1513         public Idler(Runnable callback) {
1514             mCallback = callback;
1515             mIdle = false;
1516         }
1517 
queueIdle()1518         public final boolean queueIdle() {
1519             if (mCallback != null) {
1520                 mCallback.run();
1521             }
1522             synchronized (this) {
1523                 mIdle = true;
1524                 notifyAll();
1525             }
1526             return false;
1527         }
1528 
waitForIdle()1529         public void waitForIdle() {
1530             synchronized (this) {
1531                 while (!mIdle) {
1532                     try {
1533                         wait();
1534                     } catch (InterruptedException e) {
1535                     }
1536                 }
1537             }
1538         }
1539     }
1540 }
1541