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