blob: fc9646486b1fe39dc8ebfde42dae35fd58fb9d49 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package android.app;
18
19import android.content.ActivityNotFoundException;
20import android.content.ComponentName;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
24import android.content.pm.ActivityInfo;
25import android.content.res.Configuration;
Jeff Brownac143512012-04-05 18:57:33 -070026import android.hardware.input.InputManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.os.Debug;
29import android.os.IBinder;
Kristian Monsen0a303282013-01-18 14:50:07 -080030import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.os.MessageQueue;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080032import android.os.PerformanceCollector;
Craig Mautnera0026042014-04-23 11:45:37 -070033import android.os.PersistableBundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.os.Process;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080035import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.os.ServiceManager;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080037import android.os.SystemClock;
Dianne Hackbornf1c26e22012-08-23 13:54:58 -070038import android.os.UserHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039import android.util.AndroidRuntimeException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.util.Log;
41import android.view.IWindowManager;
Jeff Brownac143512012-04-05 18:57:33 -070042import android.view.InputDevice;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043import android.view.KeyCharacterMap;
44import android.view.KeyEvent;
45import android.view.MotionEvent;
46import android.view.ViewConfiguration;
47import android.view.Window;
Dianne Hackborn85d558c2014-11-04 10:31:54 -080048import com.android.internal.content.ReferrerIntent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049
50import java.io.File;
51import java.util.ArrayList;
52import java.util.List;
53
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054/**
55 * Base class for implementing application instrumentation code. When running
56 * with instrumentation turned on, this class will be instantiated for you
57 * before any of the application code, allowing you to monitor all of the
58 * interaction the system has with the application. An Instrumentation
59 * implementation is described to the system through an AndroidManifest.xml's
60 * <instrumentation> tag.
61 */
62public class Instrumentation {
Svetoslav Ganov80943d82013-01-02 10:25:37 -080063
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064 /**
65 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
66 * identifies the class that is writing the report. This can be used to provide more structured
67 * logging or reporting capabilities in the IInstrumentationWatcher.
68 */
69 public static final String REPORT_KEY_IDENTIFIER = "id";
70 /**
71 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
72 * identifies a string which can simply be printed to the output stream. Using these streams
73 * provides a "pretty printer" version of the status & final packets. Any bundles including
74 * this key should also include the complete set of raw key/value pairs, so that the
75 * instrumentation can also be launched, and results collected, by an automated system.
76 */
77 public static final String REPORT_KEY_STREAMRESULT = "stream";
Svetoslav Ganov80943d82013-01-02 10:25:37 -080078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 private static final String TAG = "Instrumentation";
80
81 private final Object mSync = new Object();
82 private ActivityThread mThread = null;
83 private MessageQueue mMessageQueue = null;
84 private Context mInstrContext;
85 private Context mAppContext;
86 private ComponentName mComponent;
87 private Thread mRunner;
88 private List<ActivityWaiter> mWaitingActivities;
89 private List<ActivityMonitor> mActivityMonitors;
90 private IInstrumentationWatcher mWatcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -080091 private IUiAutomationConnection mUiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 private boolean mAutomaticPerformanceSnapshots = false;
Jack Wangff1df692009-08-26 17:19:13 -070093 private PerformanceCollector mPerformanceCollector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 private Bundle mPerfMetrics = new Bundle();
Svetoslav Ganov80943d82013-01-02 10:25:37 -080095 private UiAutomation mUiAutomation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096
97 public Instrumentation() {
98 }
99
100 /**
101 * Called when the instrumentation is starting, before any application code
102 * has been loaded. Usually this will be implemented to simply call
103 * {@link #start} to begin the instrumentation thread, which will then
104 * continue execution in {@link #onStart}.
105 *
106 * <p>If you do not need your own thread -- that is you are writing your
107 * instrumentation to be completely asynchronous (returning to the event
108 * loop so that the application can run), you can simply begin your
109 * instrumentation here, for example call {@link Context#startActivity} to
110 * begin the appropriate first activity of the application.
111 *
112 * @param arguments Any additional arguments that were supplied when the
113 * instrumentation was started.
114 */
115 public void onCreate(Bundle arguments) {
116 }
117
118 /**
119 * Create and start a new thread in which to run instrumentation. This new
120 * thread will call to {@link #onStart} where you can implement the
121 * instrumentation.
122 */
123 public void start() {
124 if (mRunner != null) {
125 throw new RuntimeException("Instrumentation already started");
126 }
127 mRunner = new InstrumentationThread("Instr: " + getClass().getName());
128 mRunner.start();
129 }
130
131 /**
132 * Method where the instrumentation thread enters execution. This allows
133 * you to run your instrumentation code in a separate thread than the
134 * application, so that it can perform blocking operation such as
135 * {@link #sendKeySync} or {@link #startActivitySync}.
136 *
137 * <p>You will typically want to call finish() when this function is done,
138 * to end your instrumentation.
139 */
140 public void onStart() {
141 }
142
143 /**
144 * This is called whenever the system captures an unhandled exception that
145 * was thrown by the application. The default implementation simply
146 * returns false, allowing normal system handling of the exception to take
147 * place.
148 *
149 * @param obj The client object that generated the exception. May be an
150 * Application, Activity, BroadcastReceiver, Service, or null.
151 * @param e The exception that was thrown.
152 *
153 * @return To allow normal system exception process to occur, return false.
154 * If true is returned, the system will proceed as if the exception
155 * didn't happen.
156 */
157 public boolean onException(Object obj, Throwable e) {
158 return false;
159 }
160
161 /**
162 * Provide a status report about the application.
163 *
164 * @param resultCode Current success/failure of instrumentation.
165 * @param results Any results to send back to the code that started the instrumentation.
166 */
167 public void sendStatus(int resultCode, Bundle results) {
168 if (mWatcher != null) {
169 try {
170 mWatcher.instrumentationStatus(mComponent, resultCode, results);
171 }
172 catch (RemoteException e) {
173 mWatcher = null;
174 }
175 }
176 }
177
178 /**
179 * Terminate instrumentation of the application. This will cause the
180 * application process to exit, removing this instrumentation from the next
181 * time the application is started.
182 *
183 * @param resultCode Overall success/failure of instrumentation.
184 * @param results Any results to send back to the code that started the
185 * instrumentation.
186 */
187 public void finish(int resultCode, Bundle results) {
188 if (mAutomaticPerformanceSnapshots) {
189 endPerformanceSnapshot();
190 }
191 if (mPerfMetrics != null) {
Dianne Hackbornb65ea7b2014-06-20 12:18:55 -0700192 if (results == null) {
193 results = new Bundle();
194 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 results.putAll(mPerfMetrics);
196 }
Adam Momtaz8f6f1f42013-04-10 12:42:58 -0700197 if (mUiAutomation != null) {
198 mUiAutomation.disconnect();
199 mUiAutomation = null;
200 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 mThread.finishInstrumentation(resultCode, results);
202 }
203
204 public void setAutomaticPerformanceSnapshots() {
205 mAutomaticPerformanceSnapshots = true;
Jack Wangff1df692009-08-26 17:19:13 -0700206 mPerformanceCollector = new PerformanceCollector();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 }
208
209 public void startPerformanceSnapshot() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700211 mPerformanceCollector.beginSnapshot(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 }
213 }
214
215 public void endPerformanceSnapshot() {
216 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700217 mPerfMetrics = mPerformanceCollector.endSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800218 }
219 }
220
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 /**
222 * Called when the instrumented application is stopping, after all of the
223 * normal application cleanup has occurred.
224 */
225 public void onDestroy() {
226 }
227
228 /**
229 * Return the Context of this instrumentation's package. Note that this is
230 * often different than the Context of the application being
231 * instrumentated, since the instrumentation code often lives is a
232 * different package than that of the application it is running against.
233 * See {@link #getTargetContext} to retrieve a Context for the target
234 * application.
235 *
236 * @return The instrumentation's package context.
237 *
238 * @see #getTargetContext
239 */
240 public Context getContext() {
241 return mInstrContext;
242 }
243
244 /**
245 * Returns complete component name of this instrumentation.
246 *
247 * @return Returns the complete component name for this instrumentation.
248 */
249 public ComponentName getComponentName() {
250 return mComponent;
251 }
252
253 /**
254 * Return a Context for the target application being instrumented. Note
255 * that this is often different than the Context of the instrumentation
256 * code, since the instrumentation code often lives is a different package
257 * than that of the application it is running against. See
258 * {@link #getContext} to retrieve a Context for the instrumentation code.
259 *
260 * @return A Context in the target application.
261 *
262 * @see #getContext
263 */
264 public Context getTargetContext() {
265 return mAppContext;
266 }
267
268 /**
269 * Check whether this instrumentation was started with profiling enabled.
270 *
271 * @return Returns true if profiling was enabled when starting, else false.
272 */
273 public boolean isProfiling() {
274 return mThread.isProfiling();
275 }
276
277 /**
278 * This method will start profiling if isProfiling() returns true. You should
279 * only call this method if you set the handleProfiling attribute in the
280 * manifest file for this Instrumentation to true.
281 */
282 public void startProfiling() {
283 if (mThread.isProfiling()) {
284 File file = new File(mThread.getProfileFilePath());
285 file.getParentFile().mkdirs();
286 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
287 }
288 }
289
290 /**
291 * Stops profiling if isProfiling() returns true.
292 */
293 public void stopProfiling() {
294 if (mThread.isProfiling()) {
295 Debug.stopMethodTracing();
296 }
297 }
298
299 /**
300 * Force the global system in or out of touch mode. This can be used if
301 * your instrumentation relies on the UI being in one more or the other
302 * when it starts.
303 *
304 * @param inTouch Set to true to be in touch mode, false to be in
305 * focus mode.
306 */
307 public void setInTouchMode(boolean inTouch) {
308 try {
309 IWindowManager.Stub.asInterface(
310 ServiceManager.getService("window")).setInTouchMode(inTouch);
311 } catch (RemoteException e) {
312 // Shouldn't happen!
313 }
314 }
315
316 /**
317 * Schedule a callback for when the application's main thread goes idle
318 * (has no more events to process).
319 *
320 * @param recipient Called the next time the thread's message queue is
321 * idle.
322 */
323 public void waitForIdle(Runnable recipient) {
324 mMessageQueue.addIdleHandler(new Idler(recipient));
325 mThread.getHandler().post(new EmptyRunnable());
326 }
327
328 /**
329 * Synchronously wait for the application to be idle. Can not be called
330 * from the main application thread -- use {@link #start} to execute
331 * instrumentation in its own thread.
332 */
333 public void waitForIdleSync() {
334 validateNotAppThread();
335 Idler idler = new Idler(null);
336 mMessageQueue.addIdleHandler(idler);
337 mThread.getHandler().post(new EmptyRunnable());
338 idler.waitForIdle();
339 }
340
341 /**
342 * Execute a call on the application's main thread, blocking until it is
343 * complete. Useful for doing things that are not thread-safe, such as
344 * looking at or modifying the view hierarchy.
345 *
346 * @param runner The code to run on the main thread.
347 */
348 public void runOnMainSync(Runnable runner) {
349 validateNotAppThread();
350 SyncRunnable sr = new SyncRunnable(runner);
351 mThread.getHandler().post(sr);
352 sr.waitForComplete();
353 }
354
355 /**
356 * Start a new activity and wait for it to begin running before returning.
357 * In addition to being synchronous, this method as some semantic
358 * differences from the standard {@link Context#startActivity} call: the
359 * activity component is resolved before talking with the activity manager
360 * (its class name is specified in the Intent that this method ultimately
361 * starts), and it does not allow you to start activities that run in a
362 * different process. In addition, if the given Intent resolves to
363 * multiple activities, instead of displaying a dialog for the user to
364 * select an activity, an exception will be thrown.
365 *
366 * <p>The function returns as soon as the activity goes idle following the
367 * call to its {@link Activity#onCreate}. Generally this means it has gone
368 * through the full initialization including {@link Activity#onResume} and
369 * drawn and displayed its initial window.
370 *
371 * @param intent Description of the activity to start.
372 *
373 * @see Context#startActivity
374 */
375 public Activity startActivitySync(Intent intent) {
376 validateNotAppThread();
377
378 synchronized (mSync) {
379 intent = new Intent(intent);
380
381 ActivityInfo ai = intent.resolveActivityInfo(
382 getTargetContext().getPackageManager(), 0);
383 if (ai == null) {
384 throw new RuntimeException("Unable to resolve activity for: " + intent);
385 }
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700386 String myProc = mThread.getProcessName();
387 if (!ai.processName.equals(myProc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800388 // todo: if this intent is ambiguous, look here to see if
389 // there is a single match that is in our package.
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700390 throw new RuntimeException("Intent in process "
391 + myProc + " resolved to different process "
392 + ai.processName + ": " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 }
394
395 intent.setComponent(new ComponentName(
396 ai.applicationInfo.packageName, ai.name));
397 final ActivityWaiter aw = new ActivityWaiter(intent);
398
399 if (mWaitingActivities == null) {
400 mWaitingActivities = new ArrayList();
401 }
402 mWaitingActivities.add(aw);
403
404 getTargetContext().startActivity(intent);
405
406 do {
407 try {
408 mSync.wait();
409 } catch (InterruptedException e) {
410 }
411 } while (mWaitingActivities.contains(aw));
412
413 return aw.activity;
414 }
415 }
416
417 /**
418 * Information about a particular kind of Intent that is being monitored.
419 * An instance of this class is added to the
420 * current instrumentation through {@link #addMonitor}; after being added,
421 * when a new activity is being started the monitor will be checked and, if
422 * matching, its hit count updated and (optionally) the call stopped and a
423 * canned result returned.
424 *
425 * <p>An ActivityMonitor can also be used to look for the creation of an
426 * activity, through the {@link #waitForActivity} method. This will return
427 * after a matching activity has been created with that activity object.
428 */
429 public static class ActivityMonitor {
430 private final IntentFilter mWhich;
431 private final String mClass;
432 private final ActivityResult mResult;
433 private final boolean mBlock;
434
435
436 // This is protected by 'Instrumentation.this.mSync'.
437 /*package*/ int mHits = 0;
438
439 // This is protected by 'this'.
440 /*package*/ Activity mLastActivity = null;
441
442 /**
443 * Create a new ActivityMonitor that looks for a particular kind of
444 * intent to be started.
445 *
446 * @param which The set of intents this monitor is responsible for.
447 * @param result A canned result to return if the monitor is hit; can
448 * be null.
449 * @param block Controls whether the monitor should block the activity
450 * start (returning its canned result) or let the call
451 * proceed.
452 *
453 * @see Instrumentation#addMonitor
454 */
455 public ActivityMonitor(
456 IntentFilter which, ActivityResult result, boolean block) {
457 mWhich = which;
458 mClass = null;
459 mResult = result;
460 mBlock = block;
461 }
462
463 /**
464 * Create a new ActivityMonitor that looks for a specific activity
465 * class to be started.
466 *
467 * @param cls The activity class this monitor is responsible for.
468 * @param result A canned result to return if the monitor is hit; can
469 * be null.
470 * @param block Controls whether the monitor should block the activity
471 * start (returning its canned result) or let the call
472 * proceed.
473 *
474 * @see Instrumentation#addMonitor
475 */
476 public ActivityMonitor(
477 String cls, ActivityResult result, boolean block) {
478 mWhich = null;
479 mClass = cls;
480 mResult = result;
481 mBlock = block;
482 }
483
484 /**
485 * Retrieve the filter associated with this ActivityMonitor.
486 */
487 public final IntentFilter getFilter() {
488 return mWhich;
489 }
490
491 /**
492 * Retrieve the result associated with this ActivityMonitor, or null if
493 * none.
494 */
495 public final ActivityResult getResult() {
496 return mResult;
497 }
498
499 /**
500 * Check whether this monitor blocks activity starts (not allowing the
501 * actual activity to run) or allows them to execute normally.
502 */
503 public final boolean isBlocking() {
504 return mBlock;
505 }
506
507 /**
508 * Retrieve the number of times the monitor has been hit so far.
509 */
510 public final int getHits() {
511 return mHits;
512 }
513
514 /**
515 * Retrieve the most recent activity class that was seen by this
516 * monitor.
517 */
518 public final Activity getLastActivity() {
519 return mLastActivity;
520 }
521
522 /**
523 * Block until an Activity is created that matches this monitor,
524 * returning the resulting activity.
525 *
526 * @return Activity
527 */
528 public final Activity waitForActivity() {
529 synchronized (this) {
530 while (mLastActivity == null) {
531 try {
532 wait();
533 } catch (InterruptedException e) {
534 }
535 }
536 Activity res = mLastActivity;
537 mLastActivity = null;
538 return res;
539 }
540 }
541
542 /**
543 * Block until an Activity is created that matches this monitor,
544 * returning the resulting activity or till the timeOut period expires.
545 * If the timeOut expires before the activity is started, return null.
546 *
547 * @param timeOut Time to wait before the activity is created.
548 *
549 * @return Activity
550 */
551 public final Activity waitForActivityWithTimeout(long timeOut) {
552 synchronized (this) {
Costin Manolacheb0935342011-07-15 11:20:42 -0700553 if (mLastActivity == null) {
554 try {
555 wait(timeOut);
556 } catch (InterruptedException e) {
557 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 }
559 if (mLastActivity == null) {
560 return null;
561 } else {
562 Activity res = mLastActivity;
563 mLastActivity = null;
564 return res;
565 }
566 }
567 }
568
569 final boolean match(Context who,
570 Activity activity,
571 Intent intent) {
572 synchronized (this) {
573 if (mWhich != null
574 && mWhich.match(who.getContentResolver(), intent,
575 true, "Instrumentation") < 0) {
576 return false;
577 }
578 if (mClass != null) {
579 String cls = null;
580 if (activity != null) {
581 cls = activity.getClass().getName();
582 } else if (intent.getComponent() != null) {
583 cls = intent.getComponent().getClassName();
584 }
585 if (cls == null || !mClass.equals(cls)) {
586 return false;
587 }
588 }
589 if (activity != null) {
590 mLastActivity = activity;
591 notifyAll();
592 }
593 return true;
594 }
595 }
596 }
597
598 /**
599 * Add a new {@link ActivityMonitor} that will be checked whenever an
600 * activity is started. The monitor is added
601 * after any existing ones; the monitor will be hit only if none of the
602 * existing monitors can themselves handle the Intent.
603 *
604 * @param monitor The new ActivityMonitor to see.
605 *
606 * @see #addMonitor(IntentFilter, ActivityResult, boolean)
607 * @see #checkMonitorHit
608 */
609 public void addMonitor(ActivityMonitor monitor) {
610 synchronized (mSync) {
611 if (mActivityMonitors == null) {
612 mActivityMonitors = new ArrayList();
613 }
614 mActivityMonitors.add(monitor);
615 }
616 }
617
618 /**
619 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
620 * creates an intent filter matching {@link ActivityMonitor} for you and
621 * returns it.
622 *
623 * @param filter The set of intents this monitor is responsible for.
624 * @param result A canned result to return if the monitor is hit; can
625 * be null.
626 * @param block Controls whether the monitor should block the activity
627 * start (returning its canned result) or let the call
628 * proceed.
629 *
630 * @return The newly created and added activity monitor.
631 *
632 * @see #addMonitor(ActivityMonitor)
633 * @see #checkMonitorHit
634 */
635 public ActivityMonitor addMonitor(
636 IntentFilter filter, ActivityResult result, boolean block) {
637 ActivityMonitor am = new ActivityMonitor(filter, result, block);
638 addMonitor(am);
639 return am;
640 }
641
642 /**
643 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
644 * creates a class matching {@link ActivityMonitor} for you and returns it.
645 *
646 * @param cls The activity class this monitor is responsible for.
647 * @param result A canned result to return if the monitor is hit; can
648 * be null.
649 * @param block Controls whether the monitor should block the activity
650 * start (returning its canned result) or let the call
651 * proceed.
652 *
653 * @return The newly created and added activity monitor.
654 *
655 * @see #addMonitor(ActivityMonitor)
656 * @see #checkMonitorHit
657 */
658 public ActivityMonitor addMonitor(
659 String cls, ActivityResult result, boolean block) {
660 ActivityMonitor am = new ActivityMonitor(cls, result, block);
661 addMonitor(am);
662 return am;
663 }
664
665 /**
666 * Test whether an existing {@link ActivityMonitor} has been hit. If the
667 * monitor has been hit at least <var>minHits</var> times, then it will be
668 * removed from the activity monitor list and true returned. Otherwise it
669 * is left as-is and false is returned.
670 *
671 * @param monitor The ActivityMonitor to check.
672 * @param minHits The minimum number of hits required.
673 *
674 * @return True if the hit count has been reached, else false.
675 *
676 * @see #addMonitor
677 */
678 public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
679 waitForIdleSync();
680 synchronized (mSync) {
681 if (monitor.getHits() < minHits) {
682 return false;
683 }
684 mActivityMonitors.remove(monitor);
685 }
686 return true;
687 }
688
689 /**
690 * Wait for an existing {@link ActivityMonitor} to be hit. Once the
691 * monitor has been hit, it is removed from the activity monitor list and
692 * the first created Activity object that matched it is returned.
693 *
694 * @param monitor The ActivityMonitor to wait for.
695 *
696 * @return The Activity object that matched the monitor.
697 */
698 public Activity waitForMonitor(ActivityMonitor monitor) {
699 Activity activity = monitor.waitForActivity();
700 synchronized (mSync) {
701 mActivityMonitors.remove(monitor);
702 }
703 return activity;
704 }
705
706 /**
707 * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
708 * expires. Once the monitor has been hit, it is removed from the activity
709 * monitor list and the first created Activity object that matched it is
710 * returned. If the timeout expires, a null object is returned.
711 *
712 * @param monitor The ActivityMonitor to wait for.
713 * @param timeOut The timeout value in secs.
714 *
715 * @return The Activity object that matched the monitor.
716 */
717 public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
718 Activity activity = monitor.waitForActivityWithTimeout(timeOut);
719 synchronized (mSync) {
720 mActivityMonitors.remove(monitor);
721 }
722 return activity;
723 }
724
725 /**
726 * Remove an {@link ActivityMonitor} that was previously added with
727 * {@link #addMonitor}.
728 *
729 * @param monitor The monitor to remove.
730 *
731 * @see #addMonitor
732 */
733 public void removeMonitor(ActivityMonitor monitor) {
734 synchronized (mSync) {
735 mActivityMonitors.remove(monitor);
736 }
737 }
738
739 /**
740 * Execute a particular menu item.
741 *
742 * @param targetActivity The activity in question.
743 * @param id The identifier associated with the menu item.
744 * @param flag Additional flags, if any.
745 * @return Whether the invocation was successful (for example, it could be
746 * false if item is disabled).
747 */
748 public boolean invokeMenuActionSync(Activity targetActivity,
749 int id, int flag) {
750 class MenuRunnable implements Runnable {
751 private final Activity activity;
752 private final int identifier;
753 private final int flags;
754 boolean returnValue;
755
756 public MenuRunnable(Activity _activity, int _identifier,
757 int _flags) {
758 activity = _activity;
759 identifier = _identifier;
760 flags = _flags;
761 }
762
763 public void run() {
764 Window win = activity.getWindow();
765
766 returnValue = win.performPanelIdentifierAction(
767 Window.FEATURE_OPTIONS_PANEL,
768 identifier,
769 flags);
770 }
771
772 }
773 MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
774 runOnMainSync(mr);
775 return mr.returnValue;
776 }
777
778 /**
779 * Show the context menu for the currently focused view and executes a
780 * particular context menu item.
781 *
782 * @param targetActivity The activity in question.
783 * @param id The identifier associated with the context menu item.
784 * @param flag Additional flags, if any.
785 * @return Whether the invocation was successful (for example, it could be
786 * false if item is disabled).
787 */
788 public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
789 validateNotAppThread();
790
791 // Bring up context menu for current focus.
792 // It'd be nice to do this through code, but currently ListView depends on
793 // long press to set metadata for its selected child
794
795 final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
796 sendKeySync(downEvent);
797
798 // Need to wait for long press
799 waitForIdleSync();
800 try {
801 Thread.sleep(ViewConfiguration.getLongPressTimeout());
802 } catch (InterruptedException e) {
803 Log.e(TAG, "Could not sleep for long press timeout", e);
804 return false;
805 }
806
807 final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
808 sendKeySync(upEvent);
809
810 // Wait for context menu to appear
811 waitForIdleSync();
812
813 class ContextMenuRunnable implements Runnable {
814 private final Activity activity;
815 private final int identifier;
816 private final int flags;
817 boolean returnValue;
818
819 public ContextMenuRunnable(Activity _activity, int _identifier,
820 int _flags) {
821 activity = _activity;
822 identifier = _identifier;
823 flags = _flags;
824 }
825
826 public void run() {
827 Window win = activity.getWindow();
828 returnValue = win.performContextMenuIdentifierAction(
829 identifier,
830 flags);
831 }
832
833 }
834
835 ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
836 runOnMainSync(cmr);
837 return cmr.returnValue;
838 }
839
840 /**
841 * Sends the key events corresponding to the text to the app being
842 * instrumented.
843 *
844 * @param text The text to be sent.
845 */
846 public void sendStringSync(String text) {
847 if (text == null) {
848 return;
849 }
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800850 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800851
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800853
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800854 if (events != null) {
855 for (int i = 0; i < events.length; i++) {
Svetoslav Ganovf434e372011-11-11 16:50:21 -0800856 // We have to change the time of an event before injecting it because
857 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
858 // time stamp and the system rejects too old events. Hence, it is
859 // possible for an event to become stale before it is injected if it
860 // takes too long to inject the preceding ones.
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800861 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800862 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800863 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 /**
867 * Send a key event to the currently focused window/view and wait for it to
868 * be processed. Finished at some point after the recipient has returned
869 * from its event processing, though it may <em>not</em> have completely
870 * finished reacting from the event -- for example, if it needs to update
871 * its display as a result, it may still be in the process of doing that.
872 *
873 * @param event The event to send to the current focus.
874 */
875 public void sendKeySync(KeyEvent event) {
876 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -0700877
878 long downTime = event.getDownTime();
879 long eventTime = event.getEventTime();
880 int action = event.getAction();
881 int code = event.getKeyCode();
882 int repeatCount = event.getRepeatCount();
883 int metaState = event.getMetaState();
884 int deviceId = event.getDeviceId();
885 int scancode = event.getScanCode();
886 int source = event.getSource();
887 int flags = event.getFlags();
888 if (source == InputDevice.SOURCE_UNKNOWN) {
889 source = InputDevice.SOURCE_KEYBOARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800890 }
Jeff Brownac143512012-04-05 18:57:33 -0700891 if (eventTime == 0) {
892 eventTime = SystemClock.uptimeMillis();
893 }
894 if (downTime == 0) {
895 downTime = eventTime;
896 }
897 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
898 deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700899 InputManager.getInstance().injectInputEvent(newEvent,
Jeff Brownac143512012-04-05 18:57:33 -0700900 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 }
902
903 /**
904 * Sends an up and down key event sync to the currently focused window.
905 *
906 * @param key The integer keycode for the event.
907 */
908 public void sendKeyDownUpSync(int key) {
909 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
910 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
911 }
912
913 /**
914 * Higher-level method for sending both the down and up key events for a
915 * particular character key code. Equivalent to creating both KeyEvent
916 * objects by hand and calling {@link #sendKeySync}. The event appears
917 * as if it came from keyboard 0, the built in one.
918 *
919 * @param keyCode The key code of the character to send.
920 */
921 public void sendCharacterSync(int keyCode) {
922 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
923 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
924 }
925
926 /**
927 * Dispatch a pointer event. Finished at some point after the recipient has
928 * returned from its event processing, though it may <em>not</em> have
929 * completely finished reacting from the event -- for example, if it needs
930 * to update its display as a result, it may still be in the process of
931 * doing that.
932 *
933 * @param event A motion event describing the pointer action. (As noted in
934 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
935 * {@link SystemClock#uptimeMillis()} as the timebase.
936 */
937 public void sendPointerSync(MotionEvent event) {
938 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -0700939 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
940 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700942 InputManager.getInstance().injectInputEvent(event,
943 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 }
945
946 /**
947 * Dispatch a trackball event. Finished at some point after the recipient has
948 * returned from its event processing, though it may <em>not</em> have
949 * completely finished reacting from the event -- for example, if it needs
950 * to update its display as a result, it may still be in the process of
951 * doing that.
952 *
953 * @param event A motion event describing the trackball action. (As noted in
954 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
955 * {@link SystemClock#uptimeMillis()} as the timebase.
956 */
957 public void sendTrackballEventSync(MotionEvent event) {
958 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -0700959 if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
960 event.setSource(InputDevice.SOURCE_TRACKBALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800961 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700962 InputManager.getInstance().injectInputEvent(event,
963 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800964 }
965
966 /**
967 * Perform instantiation of the process's {@link Application} object. The
968 * default implementation provides the normal system behavior.
969 *
970 * @param cl The ClassLoader with which to instantiate the object.
971 * @param className The name of the class implementing the Application
972 * object.
973 * @param context The context to initialize the application with
974 *
975 * @return The newly instantiated Application object.
976 */
977 public Application newApplication(ClassLoader cl, String className, Context context)
978 throws InstantiationException, IllegalAccessException,
979 ClassNotFoundException {
980 return newApplication(cl.loadClass(className), context);
981 }
982
983 /**
984 * Perform instantiation of the process's {@link Application} object. The
985 * default implementation provides the normal system behavior.
986 *
987 * @param clazz The class used to create an Application object from.
988 * @param context The context to initialize the application with
989 *
990 * @return The newly instantiated Application object.
991 */
992 static public Application newApplication(Class<?> clazz, Context context)
993 throws InstantiationException, IllegalAccessException,
994 ClassNotFoundException {
995 Application app = (Application)clazz.newInstance();
996 app.attach(context);
997 return app;
998 }
999
1000 /**
1001 * Perform calling of the application's {@link Application#onCreate}
1002 * method. The default implementation simply calls through to that method.
Dianne Hackborn6ae8d182012-05-23 13:12:42 -07001003 *
1004 * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
1005 * Often instrumentation tests start their test thread in onCreate(); you
1006 * need to be careful of races between these. (Well between it and
1007 * everything else, but let's start here.)
1008 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001009 * @param app The application being created.
1010 */
1011 public void callApplicationOnCreate(Application app) {
1012 app.onCreate();
1013 }
1014
1015 /**
1016 * Perform instantiation of an {@link Activity} object. This method is intended for use with
1017 * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
1018 * locally but will be missing some of the linkages necessary for use within the sytem.
1019 *
1020 * @param clazz The Class of the desired Activity
1021 * @param context The base context for the activity to use
1022 * @param token The token for this activity to communicate with
1023 * @param application The application object (if any)
1024 * @param intent The intent that started this Activity
1025 * @param info ActivityInfo from the manifest
1026 * @param title The title, typically retrieved from the ActivityInfo record
1027 * @param parent The parent Activity (if any)
1028 * @param id The embedded Id (if any)
1029 * @param lastNonConfigurationInstance Arbitrary object that will be
1030 * available via {@link Activity#getLastNonConfigurationInstance()
1031 * Activity.getLastNonConfigurationInstance()}.
1032 * @return Returns the instantiated activity
1033 * @throws InstantiationException
1034 * @throws IllegalAccessException
1035 */
1036 public Activity newActivity(Class<?> clazz, Context context,
1037 IBinder token, Application application, Intent intent, ActivityInfo info,
1038 CharSequence title, Activity parent, String id,
1039 Object lastNonConfigurationInstance) throws InstantiationException,
1040 IllegalAccessException {
1041 Activity activity = (Activity)clazz.newInstance();
1042 ActivityThread aThread = null;
Craig Mautner233ceee2014-05-09 17:05:11 -07001043 activity.attach(context, aThread, this, token, 0, application, intent,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001044 info, title, parent, id,
1045 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001046 new Configuration(), null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 return activity;
1048 }
1049
1050 /**
1051 * Perform instantiation of the process's {@link Activity} object. The
1052 * default implementation provides the normal system behavior.
1053 *
1054 * @param cl The ClassLoader with which to instantiate the object.
1055 * @param className The name of the class implementing the Activity
1056 * object.
1057 * @param intent The Intent object that specified the activity class being
1058 * instantiated.
1059 *
1060 * @return The newly instantiated Activity object.
1061 */
1062 public Activity newActivity(ClassLoader cl, String className,
1063 Intent intent)
1064 throws InstantiationException, IllegalAccessException,
1065 ClassNotFoundException {
1066 return (Activity)cl.loadClass(className).newInstance();
1067 }
1068
Craig Mautnera0026042014-04-23 11:45:37 -07001069 private void prePerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001070 if (mWaitingActivities != null) {
1071 synchronized (mSync) {
1072 final int N = mWaitingActivities.size();
1073 for (int i=0; i<N; i++) {
1074 final ActivityWaiter aw = mWaitingActivities.get(i);
1075 final Intent intent = aw.intent;
1076 if (intent.filterEquals(activity.getIntent())) {
1077 aw.activity = activity;
1078 mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1079 }
1080 }
1081 }
1082 }
Craig Mautnera0026042014-04-23 11:45:37 -07001083 }
1084
1085 private void postPerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001086 if (mActivityMonitors != null) {
1087 synchronized (mSync) {
1088 final int N = mActivityMonitors.size();
1089 for (int i=0; i<N; i++) {
1090 final ActivityMonitor am = mActivityMonitors.get(i);
1091 am.match(activity, activity, activity.getIntent());
1092 }
1093 }
1094 }
1095 }
Craig Mautnera0026042014-04-23 11:45:37 -07001096
1097 /**
1098 * Perform calling of an activity's {@link Activity#onCreate}
1099 * method. The default implementation simply calls through to that method.
1100 *
1101 * @param activity The activity being created.
1102 * @param icicle The previously frozen state (or null) to pass through to onCreate().
1103 */
1104 public void callActivityOnCreate(Activity activity, Bundle icicle) {
1105 prePerformCreate(activity);
1106 activity.performCreate(icicle);
1107 postPerformCreate(activity);
1108 }
1109
1110 /**
1111 * Perform calling of an activity's {@link Activity#onCreate}
1112 * method. The default implementation simply calls through to that method.
1113 * @param activity The activity being created.
1114 * @param icicle The previously frozen state (or null) to pass through to
1115 * @param persistentState The previously persisted state (or null)
1116 */
1117 public void callActivityOnCreate(Activity activity, Bundle icicle,
1118 PersistableBundle persistentState) {
1119 prePerformCreate(activity);
1120 activity.performCreate(icicle, persistentState);
1121 postPerformCreate(activity);
1122 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123
1124 public void callActivityOnDestroy(Activity activity) {
Brett Chabot18f9ce02010-05-12 12:41:50 -07001125 // TODO: the following block causes intermittent hangs when using startActivity
1126 // temporarily comment out until root cause is fixed (bug 2630683)
1127// if (mWaitingActivities != null) {
1128// synchronized (mSync) {
1129// final int N = mWaitingActivities.size();
1130// for (int i=0; i<N; i++) {
1131// final ActivityWaiter aw = mWaitingActivities.get(i);
1132// final Intent intent = aw.intent;
1133// if (intent.filterEquals(activity.getIntent())) {
1134// aw.activity = activity;
1135// mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1136// }
1137// }
1138// }
1139// }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001140
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001141 activity.performDestroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001142
1143 if (mActivityMonitors != null) {
1144 synchronized (mSync) {
1145 final int N = mActivityMonitors.size();
1146 for (int i=0; i<N; i++) {
1147 final ActivityMonitor am = mActivityMonitors.get(i);
1148 am.match(activity, activity, activity.getIntent());
1149 }
1150 }
1151 }
1152 }
1153
1154 /**
1155 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1156 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001157 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 * @param activity The activity being restored.
1159 * @param savedInstanceState The previously saved state being restored.
1160 */
1161 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
1162 activity.performRestoreInstanceState(savedInstanceState);
1163 }
1164
1165 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001166 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1167 * method. The default implementation simply calls through to that method.
1168 *
1169 * @param activity The activity being restored.
1170 * @param savedInstanceState The previously saved state being restored.
1171 * @param persistentState The previously persisted state (or null)
1172 */
1173 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState,
1174 PersistableBundle persistentState) {
1175 activity.performRestoreInstanceState(savedInstanceState, persistentState);
1176 }
1177
1178 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1180 * The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001181 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 * @param activity The activity being created.
1183 * @param icicle The previously frozen state (or null) to pass through to
1184 * onPostCreate().
1185 */
1186 public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
1187 activity.onPostCreate(icicle);
1188 }
1189
1190 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001191 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1192 * The default implementation simply calls through to that method.
1193 *
1194 * @param activity The activity being created.
1195 * @param icicle The previously frozen state (or null) to pass through to
1196 * onPostCreate().
1197 */
1198 public void callActivityOnPostCreate(Activity activity, Bundle icicle,
1199 PersistableBundle persistentState) {
1200 activity.onPostCreate(icicle, persistentState);
1201 }
1202
1203 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204 * Perform calling of an activity's {@link Activity#onNewIntent}
1205 * method. The default implementation simply calls through to that method.
1206 *
1207 * @param activity The activity receiving a new Intent.
1208 * @param intent The new intent being received.
1209 */
1210 public void callActivityOnNewIntent(Activity activity, Intent intent) {
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001211 activity.onNewIntent(intent);
1212 }
1213
1214 /**
1215 * @hide
1216 */
1217 public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001218 final String oldReferrer = activity.mReferrer;
1219 try {
Dianne Hackborn80b1c562014-12-09 20:22:08 -08001220 if (intent != null) {
1221 activity.mReferrer = intent.mReferrer;
1222 }
1223 callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001224 } finally {
1225 activity.mReferrer = oldReferrer;
1226 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001227 }
1228
1229 /**
1230 * Perform calling of an activity's {@link Activity#onStart}
1231 * method. The default implementation simply calls through to that method.
1232 *
1233 * @param activity The activity being started.
1234 */
1235 public void callActivityOnStart(Activity activity) {
1236 activity.onStart();
1237 }
1238
1239 /**
1240 * Perform calling of an activity's {@link Activity#onRestart}
1241 * method. The default implementation simply calls through to that method.
1242 *
1243 * @param activity The activity being restarted.
1244 */
1245 public void callActivityOnRestart(Activity activity) {
1246 activity.onRestart();
1247 }
1248
1249 /**
1250 * Perform calling of an activity's {@link Activity#onResume} method. The
1251 * default implementation simply calls through to that method.
1252 *
1253 * @param activity The activity being resumed.
1254 */
1255 public void callActivityOnResume(Activity activity) {
Jeff Hamilton52d32032011-01-08 15:31:26 -06001256 activity.mResumed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 activity.onResume();
1258
1259 if (mActivityMonitors != null) {
1260 synchronized (mSync) {
1261 final int N = mActivityMonitors.size();
1262 for (int i=0; i<N; i++) {
1263 final ActivityMonitor am = mActivityMonitors.get(i);
1264 am.match(activity, activity, activity.getIntent());
1265 }
1266 }
1267 }
1268 }
1269
1270 /**
1271 * Perform calling of an activity's {@link Activity#onStop}
1272 * method. The default implementation simply calls through to that method.
1273 *
1274 * @param activity The activity being stopped.
1275 */
1276 public void callActivityOnStop(Activity activity) {
1277 activity.onStop();
1278 }
1279
1280 /**
Newton Allenc5027442013-08-13 11:22:32 -07001281 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1282 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001283 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 * @param activity The activity being saved.
1285 * @param outState The bundle to pass to the call.
1286 */
1287 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
1288 activity.performSaveInstanceState(outState);
1289 }
1290
1291 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001292 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1293 * method. The default implementation simply calls through to that method.
1294 * @param activity The activity being saved.
1295 * @param outState The bundle to pass to the call.
1296 * @param outPersistentState The persistent bundle to pass to the call.
1297 */
1298 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
1299 PersistableBundle outPersistentState) {
1300 activity.performSaveInstanceState(outState, outPersistentState);
1301 }
1302
1303 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 * Perform calling of an activity's {@link Activity#onPause} method. The
1305 * default implementation simply calls through to that method.
1306 *
1307 * @param activity The activity being paused.
1308 */
1309 public void callActivityOnPause(Activity activity) {
1310 activity.performPause();
1311 }
1312
1313 /**
1314 * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
1315 * The default implementation simply calls through to that method.
1316 *
1317 * @param activity The activity being notified that the user has navigated away
1318 */
1319 public void callActivityOnUserLeaving(Activity activity) {
1320 activity.performUserLeaving();
1321 }
1322
1323 /*
1324 * Starts allocation counting. This triggers a gc and resets the counts.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001325 *
1326 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001327 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001328 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 public void startAllocCounting() {
1330 // Before we start trigger a GC and reset the debug counts. Run the
1331 // finalizers and another GC before starting and stopping the alloc
1332 // counts. This will free up any objects that were just sitting around
1333 // waiting for their finalizers to be run.
1334 Runtime.getRuntime().gc();
1335 Runtime.getRuntime().runFinalization();
1336 Runtime.getRuntime().gc();
1337
1338 Debug.resetAllCounts();
1339
1340 // start the counts
1341 Debug.startAllocCounting();
1342 }
1343
1344 /*
1345 * Stops allocation counting.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001346 *
1347 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001348 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001349 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 public void stopAllocCounting() {
1351 Runtime.getRuntime().gc();
1352 Runtime.getRuntime().runFinalization();
1353 Runtime.getRuntime().gc();
1354 Debug.stopAllocCounting();
1355 }
1356
1357 /**
1358 * If Results already contains Key, it appends Value to the key's ArrayList
1359 * associated with the key. If the key doesn't already exist in results, it
1360 * adds the key/value pair to results.
1361 */
1362 private void addValue(String key, int value, Bundle results) {
1363 if (results.containsKey(key)) {
1364 List<Integer> list = results.getIntegerArrayList(key);
1365 if (list != null) {
1366 list.add(value);
1367 }
1368 } else {
1369 ArrayList<Integer> list = new ArrayList<Integer>();
1370 list.add(value);
1371 results.putIntegerArrayList(key, list);
1372 }
1373 }
1374
1375 /**
1376 * Returns a bundle with the current results from the allocation counting.
1377 */
1378 public Bundle getAllocCounts() {
1379 Bundle results = new Bundle();
1380 results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
1381 results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
1382 results.putLong("global_freed_count", Debug.getGlobalFreedCount());
1383 results.putLong("global_freed_size", Debug.getGlobalFreedSize());
1384 results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
1385 return results;
1386 }
1387
1388 /**
1389 * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
1390 * reported are the number of send and the number of received transactions.
1391 */
1392 public Bundle getBinderCounts() {
1393 Bundle results = new Bundle();
1394 results.putLong("sent_transactions", Debug.getBinderSentTransactions());
1395 results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
1396 return results;
1397 }
1398
1399 /**
1400 * Description of a Activity execution result to return to the original
1401 * activity.
1402 */
1403 public static final class ActivityResult {
1404 /**
1405 * Create a new activity result. See {@link Activity#setResult} for
1406 * more information.
1407 *
1408 * @param resultCode The result code to propagate back to the
1409 * originating activity, often RESULT_CANCELED or RESULT_OK
1410 * @param resultData The data to propagate back to the originating
1411 * activity.
1412 */
1413 public ActivityResult(int resultCode, Intent resultData) {
1414 mResultCode = resultCode;
1415 mResultData = resultData;
1416 }
1417
1418 /**
1419 * Retrieve the result code contained in this result.
1420 */
1421 public int getResultCode() {
1422 return mResultCode;
1423 }
1424
1425 /**
1426 * Retrieve the data contained in this result.
1427 */
1428 public Intent getResultData() {
1429 return mResultData;
1430 }
1431
1432 private final int mResultCode;
1433 private final Intent mResultData;
1434 }
1435
1436 /**
1437 * Execute a startActivity call made by the application. The default
1438 * implementation takes care of updating any active {@link ActivityMonitor}
1439 * objects and dispatches this call to the system activity manager; you can
1440 * override this to watch for the application to start an activity, and
1441 * modify what happens when it does.
1442 *
1443 * <p>This method returns an {@link ActivityResult} object, which you can
1444 * use when intercepting application calls to avoid performing the start
1445 * activity action but still return the result the application is
1446 * expecting. To do this, override this method to catch the call to start
1447 * activity so that it returns a new ActivityResult containing the results
1448 * you would like the application to see, and don't call up to the super
1449 * class. Note that an application is only expecting a result if
1450 * <var>requestCode</var> is &gt;= 0.
1451 *
1452 * <p>This method throws {@link android.content.ActivityNotFoundException}
1453 * if there was no Activity found to run the given Intent.
1454 *
1455 * @param who The Context from which the activity is being started.
1456 * @param contextThread The main thread of the Context from which the activity
1457 * is being started.
1458 * @param token Internal token identifying to the system who is starting
1459 * the activity; may be null.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001460 * @param target Which activity is performing the start (and thus receiving
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001461 * any result); may be null if this call is not being made
1462 * from an activity.
1463 * @param intent The actual Intent to start.
1464 * @param requestCode Identifier for this request's result; less than zero
1465 * if the caller is not expecting a result.
Dianne Hackborna4972e92012-03-14 10:38:05 -07001466 * @param options Addition options.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001467 *
1468 * @return To force the return of a particular result, return an
1469 * ActivityResult object containing the desired data; otherwise
1470 * return null. The default implementation always returns null.
1471 *
1472 * @throws android.content.ActivityNotFoundException
1473 *
1474 * @see Activity#startActivity(Intent)
1475 * @see Activity#startActivityForResult(Intent, int)
1476 * @see Activity#startActivityFromChild
1477 *
1478 * {@hide}
1479 */
1480 public ActivityResult execStartActivity(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001481 Context who, IBinder contextThread, IBinder token, Activity target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001482 Intent intent, int requestCode, Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 IApplicationThread whoThread = (IApplicationThread) contextThread;
1484 if (mActivityMonitors != null) {
1485 synchronized (mSync) {
1486 final int N = mActivityMonitors.size();
1487 for (int i=0; i<N; i++) {
1488 final ActivityMonitor am = mActivityMonitors.get(i);
1489 if (am.match(who, null, intent)) {
1490 am.mHits++;
1491 if (am.isBlocking()) {
1492 return requestCode >= 0 ? am.getResult() : null;
1493 }
1494 break;
1495 }
1496 }
1497 }
1498 }
1499 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001500 intent.migrateExtraStreamToClipData();
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001501 intent.prepareToLeaveProcess();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001502 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001503 .startActivity(whoThread, who.getBasePackageName(), intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 intent.resolveTypeIfNeeded(who.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07001505 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001506 requestCode, 0, null, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 checkStartActivityResult(result, intent);
1508 } catch (RemoteException e) {
1509 }
1510 return null;
1511 }
1512
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001513 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001514 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001515 * but accepts an array of activities to be started. Note that active
1516 * {@link ActivityMonitor} objects only match against the first activity in
1517 * the array.
1518 *
1519 * {@hide}
1520 */
1521 public void execStartActivities(Context who, IBinder contextThread,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001522 IBinder token, Activity target, Intent[] intents, Bundle options) {
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001523 execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
1524 UserHandle.myUserId());
1525 }
1526
1527 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001528 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001529 * but accepts an array of activities to be started. Note that active
1530 * {@link ActivityMonitor} objects only match against the first activity in
1531 * the array.
1532 *
1533 * {@hide}
1534 */
1535 public void execStartActivitiesAsUser(Context who, IBinder contextThread,
1536 IBinder token, Activity target, Intent[] intents, Bundle options,
1537 int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001538 IApplicationThread whoThread = (IApplicationThread) contextThread;
1539 if (mActivityMonitors != null) {
1540 synchronized (mSync) {
1541 final int N = mActivityMonitors.size();
1542 for (int i=0; i<N; i++) {
1543 final ActivityMonitor am = mActivityMonitors.get(i);
1544 if (am.match(who, null, intents[0])) {
1545 am.mHits++;
1546 if (am.isBlocking()) {
1547 return;
1548 }
1549 break;
1550 }
1551 }
1552 }
1553 }
1554 try {
1555 String[] resolvedTypes = new String[intents.length];
1556 for (int i=0; i<intents.length; i++) {
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001557 intents[i].migrateExtraStreamToClipData();
1558 intents[i].prepareToLeaveProcess();
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001559 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
1560 }
1561 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001562 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
1563 token, options, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001564 checkStartActivityResult(result, intents[0]);
1565 } catch (RemoteException e) {
1566 }
1567 }
1568
1569 /**
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001570 * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001571 * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)},
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001572 * but for calls from a {#link Fragment}.
1573 *
1574 * @param who The Context from which the activity is being started.
1575 * @param contextThread The main thread of the Context from which the activity
1576 * is being started.
1577 * @param token Internal token identifying to the system who is starting
1578 * the activity; may be null.
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001579 * @param target Which element is performing the start (and thus receiving
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001580 * any result).
1581 * @param intent The actual Intent to start.
1582 * @param requestCode Identifier for this request's result; less than zero
1583 * if the caller is not expecting a result.
1584 *
1585 * @return To force the return of a particular result, return an
1586 * ActivityResult object containing the desired data; otherwise
1587 * return null. The default implementation always returns null.
1588 *
1589 * @throws android.content.ActivityNotFoundException
1590 *
1591 * @see Activity#startActivity(Intent)
1592 * @see Activity#startActivityForResult(Intent, int)
1593 * @see Activity#startActivityFromChild
1594 *
1595 * {@hide}
1596 */
1597 public ActivityResult execStartActivity(
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001598 Context who, IBinder contextThread, IBinder token, String target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001599 Intent intent, int requestCode, Bundle options) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001600 IApplicationThread whoThread = (IApplicationThread) contextThread;
1601 if (mActivityMonitors != null) {
1602 synchronized (mSync) {
1603 final int N = mActivityMonitors.size();
1604 for (int i=0; i<N; i++) {
1605 final ActivityMonitor am = mActivityMonitors.get(i);
1606 if (am.match(who, null, intent)) {
1607 am.mHits++;
1608 if (am.isBlocking()) {
1609 return requestCode >= 0 ? am.getResult() : null;
1610 }
1611 break;
1612 }
1613 }
1614 }
1615 }
1616 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001617 intent.migrateExtraStreamToClipData();
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001618 intent.prepareToLeaveProcess();
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001619 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001620 .startActivity(whoThread, who.getBasePackageName(), intent,
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001621 intent.resolveTypeIfNeeded(who.getContentResolver()),
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001622 token, target, requestCode, 0, null, options);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001623 checkStartActivityResult(result, intent);
1624 } catch (RemoteException e) {
1625 }
1626 return null;
1627 }
1628
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001629 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001630 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
1631 * but for starting as a particular user.
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001632 *
1633 * @param who The Context from which the activity is being started.
1634 * @param contextThread The main thread of the Context from which the activity
1635 * is being started.
1636 * @param token Internal token identifying to the system who is starting
1637 * the activity; may be null.
1638 * @param target Which fragment is performing the start (and thus receiving
1639 * any result).
1640 * @param intent The actual Intent to start.
1641 * @param requestCode Identifier for this request's result; less than zero
1642 * if the caller is not expecting a result.
1643 *
1644 * @return To force the return of a particular result, return an
1645 * ActivityResult object containing the desired data; otherwise
1646 * return null. The default implementation always returns null.
1647 *
1648 * @throws android.content.ActivityNotFoundException
1649 *
1650 * @see Activity#startActivity(Intent)
1651 * @see Activity#startActivityForResult(Intent, int)
1652 * @see Activity#startActivityFromChild
1653 *
1654 * {@hide}
1655 */
1656 public ActivityResult execStartActivity(
1657 Context who, IBinder contextThread, IBinder token, Activity target,
1658 Intent intent, int requestCode, Bundle options, UserHandle user) {
1659 IApplicationThread whoThread = (IApplicationThread) contextThread;
1660 if (mActivityMonitors != null) {
1661 synchronized (mSync) {
1662 final int N = mActivityMonitors.size();
1663 for (int i=0; i<N; i++) {
1664 final ActivityMonitor am = mActivityMonitors.get(i);
1665 if (am.match(who, null, intent)) {
1666 am.mHits++;
1667 if (am.isBlocking()) {
1668 return requestCode >= 0 ? am.getResult() : null;
1669 }
1670 break;
1671 }
1672 }
1673 }
1674 }
1675 try {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001676 intent.migrateExtraStreamToClipData();
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001677 intent.prepareToLeaveProcess();
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001678 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001679 .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001680 intent.resolveTypeIfNeeded(who.getContentResolver()),
1681 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001682 requestCode, 0, null, options, user.getIdentifier());
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001683 checkStartActivityResult(result, intent);
1684 } catch (RemoteException e) {
1685 }
1686 return null;
1687 }
1688
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001689 /**
1690 * Special version!
1691 * @hide
1692 */
1693 public ActivityResult execStartActivityAsCaller(
1694 Context who, IBinder contextThread, IBinder token, Activity target,
Jeff Sharkey97978802014-10-14 10:48:18 -07001695 Intent intent, int requestCode, Bundle options, int userId) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001696 IApplicationThread whoThread = (IApplicationThread) contextThread;
1697 if (mActivityMonitors != null) {
1698 synchronized (mSync) {
1699 final int N = mActivityMonitors.size();
1700 for (int i=0; i<N; i++) {
1701 final ActivityMonitor am = mActivityMonitors.get(i);
1702 if (am.match(who, null, intent)) {
1703 am.mHits++;
1704 if (am.isBlocking()) {
1705 return requestCode >= 0 ? am.getResult() : null;
1706 }
1707 break;
1708 }
1709 }
1710 }
1711 }
1712 try {
1713 intent.migrateExtraStreamToClipData();
1714 intent.prepareToLeaveProcess();
1715 int result = ActivityManagerNative.getDefault()
1716 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
1717 intent.resolveTypeIfNeeded(who.getContentResolver()),
1718 token, target != null ? target.mEmbeddedID : null,
Jeff Sharkey97978802014-10-14 10:48:18 -07001719 requestCode, 0, null, options, userId);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001720 checkStartActivityResult(result, intent);
1721 } catch (RemoteException e) {
1722 }
1723 return null;
1724 }
1725
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001726 /**
1727 * Special version!
1728 * @hide
1729 */
1730 public void execStartActivityFromAppTask(
1731 Context who, IBinder contextThread, IAppTask appTask,
1732 Intent intent, Bundle options) {
1733 IApplicationThread whoThread = (IApplicationThread) contextThread;
1734 if (mActivityMonitors != null) {
1735 synchronized (mSync) {
1736 final int N = mActivityMonitors.size();
1737 for (int i=0; i<N; i++) {
1738 final ActivityMonitor am = mActivityMonitors.get(i);
1739 if (am.match(who, null, intent)) {
1740 am.mHits++;
1741 if (am.isBlocking()) {
1742 return;
1743 }
1744 break;
1745 }
1746 }
1747 }
1748 }
1749 try {
1750 intent.migrateExtraStreamToClipData();
1751 intent.prepareToLeaveProcess();
1752 int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
1753 intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options);
1754 checkStartActivityResult(result, intent);
1755 } catch (RemoteException e) {
1756 }
1757 return;
1758 }
1759
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001760 /*package*/ final void init(ActivityThread thread,
1761 Context instrContext, Context appContext, ComponentName component,
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001762 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001763 mThread = thread;
1764 mMessageQueue = mThread.getLooper().myQueue();
1765 mInstrContext = instrContext;
1766 mAppContext = appContext;
1767 mComponent = component;
1768 mWatcher = watcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001769 mUiAutomationConnection = uiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001770 }
1771
Dianne Hackborn91097de2014-04-04 18:02:06 -07001772 /** @hide */
1773 public static void checkStartActivityResult(int res, Object intent) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07001774 if (res >= ActivityManager.START_SUCCESS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001775 return;
1776 }
1777
1778 switch (res) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07001779 case ActivityManager.START_INTENT_NOT_RESOLVED:
1780 case ActivityManager.START_CLASS_NOT_FOUND:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001781 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 throw new ActivityNotFoundException(
1783 "Unable to find explicit activity class "
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001784 + ((Intent)intent).getComponent().toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001785 + "; have you declared this activity in your AndroidManifest.xml?");
1786 throw new ActivityNotFoundException(
1787 "No Activity found to handle " + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07001788 case ActivityManager.START_PERMISSION_DENIED:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001789 throw new SecurityException("Not allowed to start activity "
1790 + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07001791 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001792 throw new AndroidRuntimeException(
1793 "FORWARD_RESULT_FLAG used while also requesting a result");
Dianne Hackborna4972e92012-03-14 10:38:05 -07001794 case ActivityManager.START_NOT_ACTIVITY:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001795 throw new IllegalArgumentException(
1796 "PendingIntent is not an activity");
Dianne Hackborn91097de2014-04-04 18:02:06 -07001797 case ActivityManager.START_NOT_VOICE_COMPATIBLE:
1798 throw new SecurityException(
1799 "Starting under voice control not allowed for: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001800 default:
1801 throw new AndroidRuntimeException("Unknown error code "
1802 + res + " when starting " + intent);
1803 }
1804 }
1805
1806 private final void validateNotAppThread() {
Kristian Monsen0a303282013-01-18 14:50:07 -08001807 if (Looper.myLooper() == Looper.getMainLooper()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001808 throw new RuntimeException(
1809 "This method can not be called from the main application thread");
1810 }
1811 }
1812
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001813 /**
1814 * Gets the {@link UiAutomation} instance.
1815 * <p>
1816 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
1817 * work across application boundaries while the APIs exposed by the instrumentation
1818 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
1819 * not allow you to inject the event in an app different from the instrumentation
1820 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
1821 * will work regardless of the current application.
1822 * </p>
1823 * <p>
1824 * A typical test case should be using either the {@link UiAutomation} or
1825 * {@link Instrumentation} APIs. Using both APIs at the same time is not
1826 * a mistake by itself but a client has to be aware of the APIs limitations.
1827 * </p>
1828 * @return The UI automation instance.
1829 *
1830 * @see UiAutomation
1831 */
1832 public UiAutomation getUiAutomation() {
1833 if (mUiAutomationConnection != null) {
1834 if (mUiAutomation == null) {
1835 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
1836 mUiAutomationConnection);
1837 mUiAutomation.connect();
1838 }
1839 return mUiAutomation;
1840 }
1841 return null;
1842 }
1843
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001844 private final class InstrumentationThread extends Thread {
1845 public InstrumentationThread(String name) {
1846 super(name);
1847 }
1848 public void run() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001849 try {
1850 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
1851 } catch (RuntimeException e) {
1852 Log.w(TAG, "Exception setting priority of instrumentation thread "
1853 + Process.myTid(), e);
1854 }
1855 if (mAutomaticPerformanceSnapshots) {
1856 startPerformanceSnapshot();
1857 }
1858 onStart();
1859 }
1860 }
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001861
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001862 private static final class EmptyRunnable implements Runnable {
1863 public void run() {
1864 }
1865 }
1866
1867 private static final class SyncRunnable implements Runnable {
1868 private final Runnable mTarget;
1869 private boolean mComplete;
1870
1871 public SyncRunnable(Runnable target) {
1872 mTarget = target;
1873 }
1874
1875 public void run() {
1876 mTarget.run();
1877 synchronized (this) {
1878 mComplete = true;
1879 notifyAll();
1880 }
1881 }
1882
1883 public void waitForComplete() {
1884 synchronized (this) {
1885 while (!mComplete) {
1886 try {
1887 wait();
1888 } catch (InterruptedException e) {
1889 }
1890 }
1891 }
1892 }
1893 }
1894
1895 private static final class ActivityWaiter {
1896 public final Intent intent;
1897 public Activity activity;
1898
1899 public ActivityWaiter(Intent _intent) {
1900 intent = _intent;
1901 }
1902 }
1903
1904 private final class ActivityGoing implements MessageQueue.IdleHandler {
1905 private final ActivityWaiter mWaiter;
1906
1907 public ActivityGoing(ActivityWaiter waiter) {
1908 mWaiter = waiter;
1909 }
1910
1911 public final boolean queueIdle() {
1912 synchronized (mSync) {
1913 mWaitingActivities.remove(mWaiter);
1914 mSync.notifyAll();
1915 }
1916 return false;
1917 }
1918 }
1919
1920 private static final class Idler implements MessageQueue.IdleHandler {
1921 private final Runnable mCallback;
1922 private boolean mIdle;
1923
1924 public Idler(Runnable callback) {
1925 mCallback = callback;
1926 mIdle = false;
1927 }
1928
1929 public final boolean queueIdle() {
1930 if (mCallback != null) {
1931 mCallback.run();
1932 }
1933 synchronized (this) {
1934 mIdle = true;
1935 notifyAll();
1936 }
1937 return false;
1938 }
1939
1940 public void waitForIdle() {
1941 synchronized (this) {
1942 while (!mIdle) {
1943 try {
1944 wait();
1945 } catch (InterruptedException e) {
1946 }
1947 }
1948 }
1949 }
1950 }
1951}