blob: 33fd1dbda63db2e12c0fa33a6c430ae398d1e2ec [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;
Dianne Hackborna3acdb32015-06-08 17:07:40 -070027import android.net.Uri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.os.Debug;
30import android.os.IBinder;
Kristian Monsen0a303282013-01-18 14:50:07 -080031import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.os.MessageQueue;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080033import android.os.PerformanceCollector;
Craig Mautnera0026042014-04-23 11:45:37 -070034import android.os.PersistableBundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.os.Process;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080036import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.os.ServiceManager;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080038import android.os.SystemClock;
Dianne Hackbornf1c26e22012-08-23 13:54:58 -070039import android.os.UserHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.util.AndroidRuntimeException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.util.Log;
42import android.view.IWindowManager;
Jeff Brownac143512012-04-05 18:57:33 -070043import android.view.InputDevice;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.view.KeyCharacterMap;
45import android.view.KeyEvent;
46import android.view.MotionEvent;
47import android.view.ViewConfiguration;
48import android.view.Window;
Dianne Hackborn85d558c2014-11-04 10:31:54 -080049import com.android.internal.content.ReferrerIntent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050
51import java.io.File;
52import java.util.ArrayList;
53import java.util.List;
54
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055/**
56 * Base class for implementing application instrumentation code. When running
57 * with instrumentation turned on, this class will be instantiated for you
58 * before any of the application code, allowing you to monitor all of the
59 * interaction the system has with the application. An Instrumentation
60 * implementation is described to the system through an AndroidManifest.xml's
61 * <instrumentation> tag.
62 */
63public class Instrumentation {
Svetoslav Ganov80943d82013-01-02 10:25:37 -080064
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065 /**
66 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
67 * identifies the class that is writing the report. This can be used to provide more structured
68 * logging or reporting capabilities in the IInstrumentationWatcher.
69 */
70 public static final String REPORT_KEY_IDENTIFIER = "id";
71 /**
72 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
73 * identifies a string which can simply be printed to the output stream. Using these streams
74 * provides a "pretty printer" version of the status & final packets. Any bundles including
75 * this key should also include the complete set of raw key/value pairs, so that the
76 * instrumentation can also be launched, and results collected, by an automated system.
77 */
78 public static final String REPORT_KEY_STREAMRESULT = "stream";
Svetoslav Ganov80943d82013-01-02 10:25:37 -080079
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080080 private static final String TAG = "Instrumentation";
81
82 private final Object mSync = new Object();
83 private ActivityThread mThread = null;
84 private MessageQueue mMessageQueue = null;
85 private Context mInstrContext;
86 private Context mAppContext;
87 private ComponentName mComponent;
88 private Thread mRunner;
89 private List<ActivityWaiter> mWaitingActivities;
90 private List<ActivityMonitor> mActivityMonitors;
91 private IInstrumentationWatcher mWatcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -080092 private IUiAutomationConnection mUiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 private boolean mAutomaticPerformanceSnapshots = false;
Jack Wangff1df692009-08-26 17:19:13 -070094 private PerformanceCollector mPerformanceCollector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095 private Bundle mPerfMetrics = new Bundle();
Svetoslav Ganov80943d82013-01-02 10:25:37 -080096 private UiAutomation mUiAutomation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097
98 public Instrumentation() {
99 }
100
101 /**
102 * Called when the instrumentation is starting, before any application code
103 * has been loaded. Usually this will be implemented to simply call
104 * {@link #start} to begin the instrumentation thread, which will then
105 * continue execution in {@link #onStart}.
106 *
107 * <p>If you do not need your own thread -- that is you are writing your
108 * instrumentation to be completely asynchronous (returning to the event
109 * loop so that the application can run), you can simply begin your
110 * instrumentation here, for example call {@link Context#startActivity} to
111 * begin the appropriate first activity of the application.
112 *
113 * @param arguments Any additional arguments that were supplied when the
114 * instrumentation was started.
115 */
116 public void onCreate(Bundle arguments) {
117 }
118
119 /**
120 * Create and start a new thread in which to run instrumentation. This new
121 * thread will call to {@link #onStart} where you can implement the
122 * instrumentation.
123 */
124 public void start() {
125 if (mRunner != null) {
126 throw new RuntimeException("Instrumentation already started");
127 }
128 mRunner = new InstrumentationThread("Instr: " + getClass().getName());
129 mRunner.start();
130 }
131
132 /**
133 * Method where the instrumentation thread enters execution. This allows
134 * you to run your instrumentation code in a separate thread than the
135 * application, so that it can perform blocking operation such as
136 * {@link #sendKeySync} or {@link #startActivitySync}.
137 *
138 * <p>You will typically want to call finish() when this function is done,
139 * to end your instrumentation.
140 */
141 public void onStart() {
142 }
143
144 /**
145 * This is called whenever the system captures an unhandled exception that
146 * was thrown by the application. The default implementation simply
147 * returns false, allowing normal system handling of the exception to take
148 * place.
149 *
150 * @param obj The client object that generated the exception. May be an
151 * Application, Activity, BroadcastReceiver, Service, or null.
152 * @param e The exception that was thrown.
153 *
154 * @return To allow normal system exception process to occur, return false.
155 * If true is returned, the system will proceed as if the exception
156 * didn't happen.
157 */
158 public boolean onException(Object obj, Throwable e) {
159 return false;
160 }
161
162 /**
163 * Provide a status report about the application.
164 *
165 * @param resultCode Current success/failure of instrumentation.
166 * @param results Any results to send back to the code that started the instrumentation.
167 */
168 public void sendStatus(int resultCode, Bundle results) {
169 if (mWatcher != null) {
170 try {
171 mWatcher.instrumentationStatus(mComponent, resultCode, results);
172 }
173 catch (RemoteException e) {
174 mWatcher = null;
175 }
176 }
177 }
178
179 /**
180 * Terminate instrumentation of the application. This will cause the
181 * application process to exit, removing this instrumentation from the next
182 * time the application is started.
183 *
184 * @param resultCode Overall success/failure of instrumentation.
185 * @param results Any results to send back to the code that started the
186 * instrumentation.
187 */
188 public void finish(int resultCode, Bundle results) {
189 if (mAutomaticPerformanceSnapshots) {
190 endPerformanceSnapshot();
191 }
192 if (mPerfMetrics != null) {
Dianne Hackbornb65ea7b2014-06-20 12:18:55 -0700193 if (results == null) {
194 results = new Bundle();
195 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 results.putAll(mPerfMetrics);
197 }
Adam Momtaz8f6f1f42013-04-10 12:42:58 -0700198 if (mUiAutomation != null) {
199 mUiAutomation.disconnect();
200 mUiAutomation = null;
201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 mThread.finishInstrumentation(resultCode, results);
203 }
204
205 public void setAutomaticPerformanceSnapshots() {
206 mAutomaticPerformanceSnapshots = true;
Jack Wangff1df692009-08-26 17:19:13 -0700207 mPerformanceCollector = new PerformanceCollector();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 }
209
210 public void startPerformanceSnapshot() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700212 mPerformanceCollector.beginSnapshot(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 }
214 }
215
216 public void endPerformanceSnapshot() {
217 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700218 mPerfMetrics = mPerformanceCollector.endSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 }
220 }
221
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 /**
223 * Called when the instrumented application is stopping, after all of the
224 * normal application cleanup has occurred.
225 */
226 public void onDestroy() {
227 }
228
229 /**
230 * Return the Context of this instrumentation's package. Note that this is
231 * often different than the Context of the application being
232 * instrumentated, since the instrumentation code often lives is a
233 * different package than that of the application it is running against.
234 * See {@link #getTargetContext} to retrieve a Context for the target
235 * application.
236 *
237 * @return The instrumentation's package context.
238 *
239 * @see #getTargetContext
240 */
241 public Context getContext() {
242 return mInstrContext;
243 }
244
245 /**
246 * Returns complete component name of this instrumentation.
247 *
248 * @return Returns the complete component name for this instrumentation.
249 */
250 public ComponentName getComponentName() {
251 return mComponent;
252 }
253
254 /**
255 * Return a Context for the target application being instrumented. Note
256 * that this is often different than the Context of the instrumentation
257 * code, since the instrumentation code often lives is a different package
258 * than that of the application it is running against. See
259 * {@link #getContext} to retrieve a Context for the instrumentation code.
260 *
261 * @return A Context in the target application.
262 *
263 * @see #getContext
264 */
265 public Context getTargetContext() {
266 return mAppContext;
267 }
268
269 /**
270 * Check whether this instrumentation was started with profiling enabled.
271 *
272 * @return Returns true if profiling was enabled when starting, else false.
273 */
274 public boolean isProfiling() {
275 return mThread.isProfiling();
276 }
277
278 /**
279 * This method will start profiling if isProfiling() returns true. You should
280 * only call this method if you set the handleProfiling attribute in the
281 * manifest file for this Instrumentation to true.
282 */
283 public void startProfiling() {
284 if (mThread.isProfiling()) {
285 File file = new File(mThread.getProfileFilePath());
286 file.getParentFile().mkdirs();
287 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
288 }
289 }
290
291 /**
292 * Stops profiling if isProfiling() returns true.
293 */
294 public void stopProfiling() {
295 if (mThread.isProfiling()) {
296 Debug.stopMethodTracing();
297 }
298 }
299
300 /**
301 * Force the global system in or out of touch mode. This can be used if
302 * your instrumentation relies on the UI being in one more or the other
303 * when it starts.
304 *
305 * @param inTouch Set to true to be in touch mode, false to be in
306 * focus mode.
307 */
308 public void setInTouchMode(boolean inTouch) {
309 try {
310 IWindowManager.Stub.asInterface(
311 ServiceManager.getService("window")).setInTouchMode(inTouch);
312 } catch (RemoteException e) {
313 // Shouldn't happen!
314 }
315 }
316
317 /**
318 * Schedule a callback for when the application's main thread goes idle
319 * (has no more events to process).
320 *
321 * @param recipient Called the next time the thread's message queue is
322 * idle.
323 */
324 public void waitForIdle(Runnable recipient) {
325 mMessageQueue.addIdleHandler(new Idler(recipient));
326 mThread.getHandler().post(new EmptyRunnable());
327 }
328
329 /**
330 * Synchronously wait for the application to be idle. Can not be called
331 * from the main application thread -- use {@link #start} to execute
332 * instrumentation in its own thread.
333 */
334 public void waitForIdleSync() {
335 validateNotAppThread();
336 Idler idler = new Idler(null);
337 mMessageQueue.addIdleHandler(idler);
338 mThread.getHandler().post(new EmptyRunnable());
339 idler.waitForIdle();
340 }
341
342 /**
343 * Execute a call on the application's main thread, blocking until it is
344 * complete. Useful for doing things that are not thread-safe, such as
345 * looking at or modifying the view hierarchy.
346 *
347 * @param runner The code to run on the main thread.
348 */
349 public void runOnMainSync(Runnable runner) {
350 validateNotAppThread();
351 SyncRunnable sr = new SyncRunnable(runner);
352 mThread.getHandler().post(sr);
353 sr.waitForComplete();
354 }
355
356 /**
357 * Start a new activity and wait for it to begin running before returning.
358 * In addition to being synchronous, this method as some semantic
359 * differences from the standard {@link Context#startActivity} call: the
360 * activity component is resolved before talking with the activity manager
361 * (its class name is specified in the Intent that this method ultimately
362 * starts), and it does not allow you to start activities that run in a
363 * different process. In addition, if the given Intent resolves to
364 * multiple activities, instead of displaying a dialog for the user to
365 * select an activity, an exception will be thrown.
366 *
367 * <p>The function returns as soon as the activity goes idle following the
368 * call to its {@link Activity#onCreate}. Generally this means it has gone
369 * through the full initialization including {@link Activity#onResume} and
370 * drawn and displayed its initial window.
371 *
372 * @param intent Description of the activity to start.
373 *
374 * @see Context#startActivity
375 */
376 public Activity startActivitySync(Intent intent) {
377 validateNotAppThread();
378
379 synchronized (mSync) {
380 intent = new Intent(intent);
381
382 ActivityInfo ai = intent.resolveActivityInfo(
383 getTargetContext().getPackageManager(), 0);
384 if (ai == null) {
385 throw new RuntimeException("Unable to resolve activity for: " + intent);
386 }
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700387 String myProc = mThread.getProcessName();
388 if (!ai.processName.equals(myProc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 // todo: if this intent is ambiguous, look here to see if
390 // there is a single match that is in our package.
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700391 throw new RuntimeException("Intent in process "
392 + myProc + " resolved to different process "
393 + ai.processName + ": " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800394 }
395
396 intent.setComponent(new ComponentName(
397 ai.applicationInfo.packageName, ai.name));
398 final ActivityWaiter aw = new ActivityWaiter(intent);
399
400 if (mWaitingActivities == null) {
401 mWaitingActivities = new ArrayList();
402 }
403 mWaitingActivities.add(aw);
404
405 getTargetContext().startActivity(intent);
406
407 do {
408 try {
409 mSync.wait();
410 } catch (InterruptedException e) {
411 }
412 } while (mWaitingActivities.contains(aw));
413
414 return aw.activity;
415 }
416 }
417
418 /**
419 * Information about a particular kind of Intent that is being monitored.
420 * An instance of this class is added to the
421 * current instrumentation through {@link #addMonitor}; after being added,
422 * when a new activity is being started the monitor will be checked and, if
423 * matching, its hit count updated and (optionally) the call stopped and a
424 * canned result returned.
425 *
426 * <p>An ActivityMonitor can also be used to look for the creation of an
427 * activity, through the {@link #waitForActivity} method. This will return
428 * after a matching activity has been created with that activity object.
429 */
430 public static class ActivityMonitor {
431 private final IntentFilter mWhich;
432 private final String mClass;
433 private final ActivityResult mResult;
434 private final boolean mBlock;
435
436
437 // This is protected by 'Instrumentation.this.mSync'.
438 /*package*/ int mHits = 0;
439
440 // This is protected by 'this'.
441 /*package*/ Activity mLastActivity = null;
442
443 /**
444 * Create a new ActivityMonitor that looks for a particular kind of
445 * intent to be started.
446 *
447 * @param which The set of intents this monitor is responsible for.
448 * @param result A canned result to return if the monitor is hit; can
449 * be null.
450 * @param block Controls whether the monitor should block the activity
451 * start (returning its canned result) or let the call
452 * proceed.
453 *
454 * @see Instrumentation#addMonitor
455 */
456 public ActivityMonitor(
457 IntentFilter which, ActivityResult result, boolean block) {
458 mWhich = which;
459 mClass = null;
460 mResult = result;
461 mBlock = block;
462 }
463
464 /**
465 * Create a new ActivityMonitor that looks for a specific activity
466 * class to be started.
467 *
468 * @param cls The activity class this monitor is responsible for.
469 * @param result A canned result to return if the monitor is hit; can
470 * be null.
471 * @param block Controls whether the monitor should block the activity
472 * start (returning its canned result) or let the call
473 * proceed.
474 *
475 * @see Instrumentation#addMonitor
476 */
477 public ActivityMonitor(
478 String cls, ActivityResult result, boolean block) {
479 mWhich = null;
480 mClass = cls;
481 mResult = result;
482 mBlock = block;
483 }
484
485 /**
486 * Retrieve the filter associated with this ActivityMonitor.
487 */
488 public final IntentFilter getFilter() {
489 return mWhich;
490 }
491
492 /**
493 * Retrieve the result associated with this ActivityMonitor, or null if
494 * none.
495 */
496 public final ActivityResult getResult() {
497 return mResult;
498 }
499
500 /**
501 * Check whether this monitor blocks activity starts (not allowing the
502 * actual activity to run) or allows them to execute normally.
503 */
504 public final boolean isBlocking() {
505 return mBlock;
506 }
507
508 /**
509 * Retrieve the number of times the monitor has been hit so far.
510 */
511 public final int getHits() {
512 return mHits;
513 }
514
515 /**
516 * Retrieve the most recent activity class that was seen by this
517 * monitor.
518 */
519 public final Activity getLastActivity() {
520 return mLastActivity;
521 }
522
523 /**
524 * Block until an Activity is created that matches this monitor,
525 * returning the resulting activity.
526 *
527 * @return Activity
528 */
529 public final Activity waitForActivity() {
530 synchronized (this) {
531 while (mLastActivity == null) {
532 try {
533 wait();
534 } catch (InterruptedException e) {
535 }
536 }
537 Activity res = mLastActivity;
538 mLastActivity = null;
539 return res;
540 }
541 }
542
543 /**
544 * Block until an Activity is created that matches this monitor,
545 * returning the resulting activity or till the timeOut period expires.
546 * If the timeOut expires before the activity is started, return null.
547 *
Ben Gruver87904e82016-01-22 13:11:11 -0800548 * @param timeOut Time to wait in milliseconds before the activity is created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800549 *
550 * @return Activity
551 */
552 public final Activity waitForActivityWithTimeout(long timeOut) {
553 synchronized (this) {
Costin Manolacheb0935342011-07-15 11:20:42 -0700554 if (mLastActivity == null) {
555 try {
556 wait(timeOut);
557 } catch (InterruptedException e) {
558 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 }
560 if (mLastActivity == null) {
561 return null;
562 } else {
563 Activity res = mLastActivity;
564 mLastActivity = null;
565 return res;
566 }
567 }
568 }
569
570 final boolean match(Context who,
571 Activity activity,
572 Intent intent) {
573 synchronized (this) {
574 if (mWhich != null
575 && mWhich.match(who.getContentResolver(), intent,
576 true, "Instrumentation") < 0) {
577 return false;
578 }
579 if (mClass != null) {
580 String cls = null;
581 if (activity != null) {
582 cls = activity.getClass().getName();
583 } else if (intent.getComponent() != null) {
584 cls = intent.getComponent().getClassName();
585 }
586 if (cls == null || !mClass.equals(cls)) {
587 return false;
588 }
589 }
590 if (activity != null) {
591 mLastActivity = activity;
592 notifyAll();
593 }
594 return true;
595 }
596 }
597 }
598
599 /**
600 * Add a new {@link ActivityMonitor} that will be checked whenever an
601 * activity is started. The monitor is added
602 * after any existing ones; the monitor will be hit only if none of the
603 * existing monitors can themselves handle the Intent.
604 *
605 * @param monitor The new ActivityMonitor to see.
606 *
607 * @see #addMonitor(IntentFilter, ActivityResult, boolean)
608 * @see #checkMonitorHit
609 */
610 public void addMonitor(ActivityMonitor monitor) {
611 synchronized (mSync) {
612 if (mActivityMonitors == null) {
613 mActivityMonitors = new ArrayList();
614 }
615 mActivityMonitors.add(monitor);
616 }
617 }
618
619 /**
620 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
621 * creates an intent filter matching {@link ActivityMonitor} for you and
622 * returns it.
623 *
624 * @param filter The set of intents this monitor is responsible for.
625 * @param result A canned result to return if the monitor is hit; can
626 * be null.
627 * @param block Controls whether the monitor should block the activity
628 * start (returning its canned result) or let the call
629 * proceed.
630 *
631 * @return The newly created and added activity monitor.
632 *
633 * @see #addMonitor(ActivityMonitor)
634 * @see #checkMonitorHit
635 */
636 public ActivityMonitor addMonitor(
637 IntentFilter filter, ActivityResult result, boolean block) {
638 ActivityMonitor am = new ActivityMonitor(filter, result, block);
639 addMonitor(am);
640 return am;
641 }
642
643 /**
644 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
645 * creates a class matching {@link ActivityMonitor} for you and returns it.
646 *
647 * @param cls The activity class this monitor is responsible for.
648 * @param result A canned result to return if the monitor is hit; can
649 * be null.
650 * @param block Controls whether the monitor should block the activity
651 * start (returning its canned result) or let the call
652 * proceed.
653 *
654 * @return The newly created and added activity monitor.
655 *
656 * @see #addMonitor(ActivityMonitor)
657 * @see #checkMonitorHit
658 */
659 public ActivityMonitor addMonitor(
660 String cls, ActivityResult result, boolean block) {
661 ActivityMonitor am = new ActivityMonitor(cls, result, block);
662 addMonitor(am);
663 return am;
664 }
665
666 /**
667 * Test whether an existing {@link ActivityMonitor} has been hit. If the
668 * monitor has been hit at least <var>minHits</var> times, then it will be
669 * removed from the activity monitor list and true returned. Otherwise it
670 * is left as-is and false is returned.
671 *
672 * @param monitor The ActivityMonitor to check.
673 * @param minHits The minimum number of hits required.
674 *
675 * @return True if the hit count has been reached, else false.
676 *
677 * @see #addMonitor
678 */
679 public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
680 waitForIdleSync();
681 synchronized (mSync) {
682 if (monitor.getHits() < minHits) {
683 return false;
684 }
685 mActivityMonitors.remove(monitor);
686 }
687 return true;
688 }
689
690 /**
691 * Wait for an existing {@link ActivityMonitor} to be hit. Once the
692 * monitor has been hit, it is removed from the activity monitor list and
693 * the first created Activity object that matched it is returned.
694 *
695 * @param monitor The ActivityMonitor to wait for.
696 *
697 * @return The Activity object that matched the monitor.
698 */
699 public Activity waitForMonitor(ActivityMonitor monitor) {
700 Activity activity = monitor.waitForActivity();
701 synchronized (mSync) {
702 mActivityMonitors.remove(monitor);
703 }
704 return activity;
705 }
706
707 /**
708 * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
709 * expires. Once the monitor has been hit, it is removed from the activity
710 * monitor list and the first created Activity object that matched it is
711 * returned. If the timeout expires, a null object is returned.
712 *
713 * @param monitor The ActivityMonitor to wait for.
714 * @param timeOut The timeout value in secs.
715 *
716 * @return The Activity object that matched the monitor.
717 */
718 public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
719 Activity activity = monitor.waitForActivityWithTimeout(timeOut);
720 synchronized (mSync) {
721 mActivityMonitors.remove(monitor);
722 }
723 return activity;
724 }
725
726 /**
727 * Remove an {@link ActivityMonitor} that was previously added with
728 * {@link #addMonitor}.
729 *
730 * @param monitor The monitor to remove.
731 *
732 * @see #addMonitor
733 */
734 public void removeMonitor(ActivityMonitor monitor) {
735 synchronized (mSync) {
736 mActivityMonitors.remove(monitor);
737 }
738 }
739
740 /**
741 * Execute a particular menu item.
742 *
743 * @param targetActivity The activity in question.
744 * @param id The identifier associated with the menu item.
745 * @param flag Additional flags, if any.
746 * @return Whether the invocation was successful (for example, it could be
747 * false if item is disabled).
748 */
749 public boolean invokeMenuActionSync(Activity targetActivity,
750 int id, int flag) {
751 class MenuRunnable implements Runnable {
752 private final Activity activity;
753 private final int identifier;
754 private final int flags;
755 boolean returnValue;
756
757 public MenuRunnable(Activity _activity, int _identifier,
758 int _flags) {
759 activity = _activity;
760 identifier = _identifier;
761 flags = _flags;
762 }
763
764 public void run() {
765 Window win = activity.getWindow();
766
767 returnValue = win.performPanelIdentifierAction(
768 Window.FEATURE_OPTIONS_PANEL,
769 identifier,
770 flags);
771 }
772
773 }
774 MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
775 runOnMainSync(mr);
776 return mr.returnValue;
777 }
778
779 /**
780 * Show the context menu for the currently focused view and executes a
781 * particular context menu item.
782 *
783 * @param targetActivity The activity in question.
784 * @param id The identifier associated with the context menu item.
785 * @param flag Additional flags, if any.
786 * @return Whether the invocation was successful (for example, it could be
787 * false if item is disabled).
788 */
789 public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
790 validateNotAppThread();
791
792 // Bring up context menu for current focus.
793 // It'd be nice to do this through code, but currently ListView depends on
794 // long press to set metadata for its selected child
795
796 final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
797 sendKeySync(downEvent);
798
799 // Need to wait for long press
800 waitForIdleSync();
801 try {
802 Thread.sleep(ViewConfiguration.getLongPressTimeout());
803 } catch (InterruptedException e) {
804 Log.e(TAG, "Could not sleep for long press timeout", e);
805 return false;
806 }
807
808 final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
809 sendKeySync(upEvent);
810
811 // Wait for context menu to appear
812 waitForIdleSync();
813
814 class ContextMenuRunnable implements Runnable {
815 private final Activity activity;
816 private final int identifier;
817 private final int flags;
818 boolean returnValue;
819
820 public ContextMenuRunnable(Activity _activity, int _identifier,
821 int _flags) {
822 activity = _activity;
823 identifier = _identifier;
824 flags = _flags;
825 }
826
827 public void run() {
828 Window win = activity.getWindow();
829 returnValue = win.performContextMenuIdentifierAction(
830 identifier,
831 flags);
832 }
833
834 }
835
836 ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
837 runOnMainSync(cmr);
838 return cmr.returnValue;
839 }
840
841 /**
842 * Sends the key events corresponding to the text to the app being
843 * instrumented.
844 *
845 * @param text The text to be sent.
846 */
847 public void sendStringSync(String text) {
848 if (text == null) {
849 return;
850 }
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800851 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800852
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 if (events != null) {
856 for (int i = 0; i < events.length; i++) {
Svetoslav Ganovf434e372011-11-11 16:50:21 -0800857 // We have to change the time of an event before injecting it because
858 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
859 // time stamp and the system rejects too old events. Hence, it is
860 // possible for an event to become stale before it is injected if it
861 // takes too long to inject the preceding ones.
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800862 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800863 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800864 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800865 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800866
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800867 /**
868 * Send a key event to the currently focused window/view and wait for it to
869 * be processed. Finished at some point after the recipient has returned
870 * from its event processing, though it may <em>not</em> have completely
871 * finished reacting from the event -- for example, if it needs to update
872 * its display as a result, it may still be in the process of doing that.
873 *
874 * @param event The event to send to the current focus.
875 */
876 public void sendKeySync(KeyEvent event) {
877 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -0700878
879 long downTime = event.getDownTime();
880 long eventTime = event.getEventTime();
881 int action = event.getAction();
882 int code = event.getKeyCode();
883 int repeatCount = event.getRepeatCount();
884 int metaState = event.getMetaState();
885 int deviceId = event.getDeviceId();
886 int scancode = event.getScanCode();
887 int source = event.getSource();
888 int flags = event.getFlags();
889 if (source == InputDevice.SOURCE_UNKNOWN) {
890 source = InputDevice.SOURCE_KEYBOARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800891 }
Jeff Brownac143512012-04-05 18:57:33 -0700892 if (eventTime == 0) {
893 eventTime = SystemClock.uptimeMillis();
894 }
895 if (downTime == 0) {
896 downTime = eventTime;
897 }
898 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
899 deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700900 InputManager.getInstance().injectInputEvent(newEvent,
Jeff Brownac143512012-04-05 18:57:33 -0700901 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 }
903
904 /**
905 * Sends an up and down key event sync to the currently focused window.
906 *
907 * @param key The integer keycode for the event.
908 */
909 public void sendKeyDownUpSync(int key) {
910 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
911 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
912 }
913
914 /**
915 * Higher-level method for sending both the down and up key events for a
916 * particular character key code. Equivalent to creating both KeyEvent
917 * objects by hand and calling {@link #sendKeySync}. The event appears
918 * as if it came from keyboard 0, the built in one.
919 *
920 * @param keyCode The key code of the character to send.
921 */
922 public void sendCharacterSync(int keyCode) {
923 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
924 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
925 }
926
927 /**
928 * Dispatch a pointer event. Finished at some point after the recipient has
929 * returned from its event processing, though it may <em>not</em> have
930 * completely finished reacting from the event -- for example, if it needs
931 * to update its display as a result, it may still be in the process of
932 * doing that.
933 *
934 * @param event A motion event describing the pointer action. (As noted in
935 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
936 * {@link SystemClock#uptimeMillis()} as the timebase.
937 */
938 public void sendPointerSync(MotionEvent event) {
939 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -0700940 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
941 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800942 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700943 InputManager.getInstance().injectInputEvent(event,
944 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800945 }
946
947 /**
948 * Dispatch a trackball event. Finished at some point after the recipient has
949 * returned from its event processing, though it may <em>not</em> have
950 * completely finished reacting from the event -- for example, if it needs
951 * to update its display as a result, it may still be in the process of
952 * doing that.
953 *
954 * @param event A motion event describing the trackball action. (As noted in
955 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
956 * {@link SystemClock#uptimeMillis()} as the timebase.
957 */
958 public void sendTrackballEventSync(MotionEvent event) {
959 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -0700960 if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
961 event.setSource(InputDevice.SOURCE_TRACKBALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800962 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700963 InputManager.getInstance().injectInputEvent(event,
964 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800965 }
966
967 /**
968 * Perform instantiation of the process's {@link Application} object. The
969 * default implementation provides the normal system behavior.
970 *
971 * @param cl The ClassLoader with which to instantiate the object.
972 * @param className The name of the class implementing the Application
973 * object.
974 * @param context The context to initialize the application with
975 *
976 * @return The newly instantiated Application object.
977 */
978 public Application newApplication(ClassLoader cl, String className, Context context)
979 throws InstantiationException, IllegalAccessException,
980 ClassNotFoundException {
981 return newApplication(cl.loadClass(className), context);
982 }
983
984 /**
985 * Perform instantiation of the process's {@link Application} object. The
986 * default implementation provides the normal system behavior.
987 *
988 * @param clazz The class used to create an Application object from.
989 * @param context The context to initialize the application with
990 *
991 * @return The newly instantiated Application object.
992 */
993 static public Application newApplication(Class<?> clazz, Context context)
994 throws InstantiationException, IllegalAccessException,
995 ClassNotFoundException {
996 Application app = (Application)clazz.newInstance();
997 app.attach(context);
998 return app;
999 }
1000
1001 /**
1002 * Perform calling of the application's {@link Application#onCreate}
1003 * method. The default implementation simply calls through to that method.
Dianne Hackborn6ae8d182012-05-23 13:12:42 -07001004 *
1005 * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
1006 * Often instrumentation tests start their test thread in onCreate(); you
1007 * need to be careful of races between these. (Well between it and
1008 * everything else, but let's start here.)
1009 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001010 * @param app The application being created.
1011 */
1012 public void callApplicationOnCreate(Application app) {
1013 app.onCreate();
1014 }
1015
1016 /**
1017 * Perform instantiation of an {@link Activity} object. This method is intended for use with
1018 * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
1019 * locally but will be missing some of the linkages necessary for use within the sytem.
1020 *
1021 * @param clazz The Class of the desired Activity
1022 * @param context The base context for the activity to use
1023 * @param token The token for this activity to communicate with
1024 * @param application The application object (if any)
1025 * @param intent The intent that started this Activity
1026 * @param info ActivityInfo from the manifest
1027 * @param title The title, typically retrieved from the ActivityInfo record
1028 * @param parent The parent Activity (if any)
1029 * @param id The embedded Id (if any)
1030 * @param lastNonConfigurationInstance Arbitrary object that will be
1031 * available via {@link Activity#getLastNonConfigurationInstance()
1032 * Activity.getLastNonConfigurationInstance()}.
1033 * @return Returns the instantiated activity
1034 * @throws InstantiationException
1035 * @throws IllegalAccessException
1036 */
1037 public Activity newActivity(Class<?> clazz, Context context,
1038 IBinder token, Application application, Intent intent, ActivityInfo info,
1039 CharSequence title, Activity parent, String id,
1040 Object lastNonConfigurationInstance) throws InstantiationException,
1041 IllegalAccessException {
1042 Activity activity = (Activity)clazz.newInstance();
1043 ActivityThread aThread = null;
Craig Mautner233ceee2014-05-09 17:05:11 -07001044 activity.attach(context, aThread, this, token, 0, application, intent,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001045 info, title, parent, id,
1046 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07001047 new Configuration(), null, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 return activity;
1049 }
1050
1051 /**
1052 * Perform instantiation of the process's {@link Activity} object. The
1053 * default implementation provides the normal system behavior.
1054 *
1055 * @param cl The ClassLoader with which to instantiate the object.
1056 * @param className The name of the class implementing the Activity
1057 * object.
1058 * @param intent The Intent object that specified the activity class being
1059 * instantiated.
1060 *
1061 * @return The newly instantiated Activity object.
1062 */
1063 public Activity newActivity(ClassLoader cl, String className,
1064 Intent intent)
1065 throws InstantiationException, IllegalAccessException,
1066 ClassNotFoundException {
1067 return (Activity)cl.loadClass(className).newInstance();
1068 }
1069
Craig Mautnera0026042014-04-23 11:45:37 -07001070 private void prePerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 if (mWaitingActivities != null) {
1072 synchronized (mSync) {
1073 final int N = mWaitingActivities.size();
1074 for (int i=0; i<N; i++) {
1075 final ActivityWaiter aw = mWaitingActivities.get(i);
1076 final Intent intent = aw.intent;
1077 if (intent.filterEquals(activity.getIntent())) {
1078 aw.activity = activity;
1079 mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1080 }
1081 }
1082 }
1083 }
Craig Mautnera0026042014-04-23 11:45:37 -07001084 }
1085
1086 private void postPerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087 if (mActivityMonitors != null) {
1088 synchronized (mSync) {
1089 final int N = mActivityMonitors.size();
1090 for (int i=0; i<N; i++) {
1091 final ActivityMonitor am = mActivityMonitors.get(i);
1092 am.match(activity, activity, activity.getIntent());
1093 }
1094 }
1095 }
1096 }
Craig Mautnera0026042014-04-23 11:45:37 -07001097
1098 /**
1099 * Perform calling of an activity's {@link Activity#onCreate}
1100 * method. The default implementation simply calls through to that method.
1101 *
1102 * @param activity The activity being created.
1103 * @param icicle The previously frozen state (or null) to pass through to onCreate().
1104 */
1105 public void callActivityOnCreate(Activity activity, Bundle icicle) {
1106 prePerformCreate(activity);
1107 activity.performCreate(icicle);
1108 postPerformCreate(activity);
1109 }
1110
1111 /**
1112 * Perform calling of an activity's {@link Activity#onCreate}
1113 * method. The default implementation simply calls through to that method.
1114 * @param activity The activity being created.
1115 * @param icicle The previously frozen state (or null) to pass through to
1116 * @param persistentState The previously persisted state (or null)
1117 */
1118 public void callActivityOnCreate(Activity activity, Bundle icicle,
1119 PersistableBundle persistentState) {
1120 prePerformCreate(activity);
1121 activity.performCreate(icicle, persistentState);
1122 postPerformCreate(activity);
1123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124
1125 public void callActivityOnDestroy(Activity activity) {
Brett Chabot18f9ce02010-05-12 12:41:50 -07001126 // TODO: the following block causes intermittent hangs when using startActivity
1127 // temporarily comment out until root cause is fixed (bug 2630683)
1128// if (mWaitingActivities != null) {
1129// synchronized (mSync) {
1130// final int N = mWaitingActivities.size();
1131// for (int i=0; i<N; i++) {
1132// final ActivityWaiter aw = mWaitingActivities.get(i);
1133// final Intent intent = aw.intent;
1134// if (intent.filterEquals(activity.getIntent())) {
1135// aw.activity = activity;
1136// mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1137// }
1138// }
1139// }
1140// }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001142 activity.performDestroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001143
1144 if (mActivityMonitors != null) {
1145 synchronized (mSync) {
1146 final int N = mActivityMonitors.size();
1147 for (int i=0; i<N; i++) {
1148 final ActivityMonitor am = mActivityMonitors.get(i);
1149 am.match(activity, activity, activity.getIntent());
1150 }
1151 }
1152 }
1153 }
1154
1155 /**
1156 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1157 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001158 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 * @param activity The activity being restored.
1160 * @param savedInstanceState The previously saved state being restored.
1161 */
1162 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
1163 activity.performRestoreInstanceState(savedInstanceState);
1164 }
1165
1166 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001167 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1168 * method. The default implementation simply calls through to that method.
1169 *
1170 * @param activity The activity being restored.
1171 * @param savedInstanceState The previously saved state being restored.
1172 * @param persistentState The previously persisted state (or null)
1173 */
1174 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState,
1175 PersistableBundle persistentState) {
1176 activity.performRestoreInstanceState(savedInstanceState, persistentState);
1177 }
1178
1179 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1181 * The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001182 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001183 * @param activity The activity being created.
1184 * @param icicle The previously frozen state (or null) to pass through to
1185 * onPostCreate().
1186 */
1187 public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
1188 activity.onPostCreate(icicle);
1189 }
1190
1191 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001192 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1193 * The default implementation simply calls through to that method.
1194 *
1195 * @param activity The activity being created.
1196 * @param icicle The previously frozen state (or null) to pass through to
1197 * onPostCreate().
1198 */
1199 public void callActivityOnPostCreate(Activity activity, Bundle icicle,
1200 PersistableBundle persistentState) {
1201 activity.onPostCreate(icicle, persistentState);
1202 }
1203
1204 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 * Perform calling of an activity's {@link Activity#onNewIntent}
1206 * method. The default implementation simply calls through to that method.
1207 *
1208 * @param activity The activity receiving a new Intent.
1209 * @param intent The new intent being received.
1210 */
1211 public void callActivityOnNewIntent(Activity activity, Intent intent) {
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001212 activity.onNewIntent(intent);
1213 }
1214
1215 /**
1216 * @hide
1217 */
1218 public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001219 final String oldReferrer = activity.mReferrer;
1220 try {
Dianne Hackborn80b1c562014-12-09 20:22:08 -08001221 if (intent != null) {
1222 activity.mReferrer = intent.mReferrer;
1223 }
1224 callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001225 } finally {
1226 activity.mReferrer = oldReferrer;
1227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 }
1229
1230 /**
1231 * Perform calling of an activity's {@link Activity#onStart}
1232 * method. The default implementation simply calls through to that method.
1233 *
1234 * @param activity The activity being started.
1235 */
1236 public void callActivityOnStart(Activity activity) {
1237 activity.onStart();
1238 }
1239
1240 /**
1241 * Perform calling of an activity's {@link Activity#onRestart}
1242 * method. The default implementation simply calls through to that method.
1243 *
1244 * @param activity The activity being restarted.
1245 */
1246 public void callActivityOnRestart(Activity activity) {
1247 activity.onRestart();
1248 }
1249
1250 /**
1251 * Perform calling of an activity's {@link Activity#onResume} method. The
1252 * default implementation simply calls through to that method.
1253 *
1254 * @param activity The activity being resumed.
1255 */
1256 public void callActivityOnResume(Activity activity) {
Jeff Hamilton52d32032011-01-08 15:31:26 -06001257 activity.mResumed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001258 activity.onResume();
1259
1260 if (mActivityMonitors != null) {
1261 synchronized (mSync) {
1262 final int N = mActivityMonitors.size();
1263 for (int i=0; i<N; i++) {
1264 final ActivityMonitor am = mActivityMonitors.get(i);
1265 am.match(activity, activity, activity.getIntent());
1266 }
1267 }
1268 }
1269 }
1270
1271 /**
1272 * Perform calling of an activity's {@link Activity#onStop}
1273 * method. The default implementation simply calls through to that method.
1274 *
1275 * @param activity The activity being stopped.
1276 */
1277 public void callActivityOnStop(Activity activity) {
1278 activity.onStop();
1279 }
1280
1281 /**
Newton Allenc5027442013-08-13 11:22:32 -07001282 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1283 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001284 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 * @param activity The activity being saved.
1286 * @param outState The bundle to pass to the call.
1287 */
1288 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
1289 activity.performSaveInstanceState(outState);
1290 }
1291
1292 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001293 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1294 * method. The default implementation simply calls through to that method.
1295 * @param activity The activity being saved.
1296 * @param outState The bundle to pass to the call.
1297 * @param outPersistentState The persistent bundle to pass to the call.
1298 */
1299 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
1300 PersistableBundle outPersistentState) {
1301 activity.performSaveInstanceState(outState, outPersistentState);
1302 }
1303
1304 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001305 * Perform calling of an activity's {@link Activity#onPause} method. The
1306 * default implementation simply calls through to that method.
1307 *
1308 * @param activity The activity being paused.
1309 */
1310 public void callActivityOnPause(Activity activity) {
1311 activity.performPause();
1312 }
1313
1314 /**
1315 * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
1316 * The default implementation simply calls through to that method.
1317 *
1318 * @param activity The activity being notified that the user has navigated away
1319 */
1320 public void callActivityOnUserLeaving(Activity activity) {
1321 activity.performUserLeaving();
1322 }
1323
1324 /*
1325 * Starts allocation counting. This triggers a gc and resets the counts.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001326 *
1327 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001329 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 public void startAllocCounting() {
1331 // Before we start trigger a GC and reset the debug counts. Run the
1332 // finalizers and another GC before starting and stopping the alloc
1333 // counts. This will free up any objects that were just sitting around
1334 // waiting for their finalizers to be run.
1335 Runtime.getRuntime().gc();
1336 Runtime.getRuntime().runFinalization();
1337 Runtime.getRuntime().gc();
1338
1339 Debug.resetAllCounts();
1340
1341 // start the counts
1342 Debug.startAllocCounting();
1343 }
1344
1345 /*
1346 * Stops allocation counting.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001347 *
1348 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001349 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001350 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 public void stopAllocCounting() {
1352 Runtime.getRuntime().gc();
1353 Runtime.getRuntime().runFinalization();
1354 Runtime.getRuntime().gc();
1355 Debug.stopAllocCounting();
1356 }
1357
1358 /**
1359 * If Results already contains Key, it appends Value to the key's ArrayList
1360 * associated with the key. If the key doesn't already exist in results, it
1361 * adds the key/value pair to results.
1362 */
1363 private void addValue(String key, int value, Bundle results) {
1364 if (results.containsKey(key)) {
1365 List<Integer> list = results.getIntegerArrayList(key);
1366 if (list != null) {
1367 list.add(value);
1368 }
1369 } else {
1370 ArrayList<Integer> list = new ArrayList<Integer>();
1371 list.add(value);
1372 results.putIntegerArrayList(key, list);
1373 }
1374 }
1375
1376 /**
1377 * Returns a bundle with the current results from the allocation counting.
1378 */
1379 public Bundle getAllocCounts() {
1380 Bundle results = new Bundle();
1381 results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
1382 results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
1383 results.putLong("global_freed_count", Debug.getGlobalFreedCount());
1384 results.putLong("global_freed_size", Debug.getGlobalFreedSize());
1385 results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
1386 return results;
1387 }
1388
1389 /**
1390 * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
1391 * reported are the number of send and the number of received transactions.
1392 */
1393 public Bundle getBinderCounts() {
1394 Bundle results = new Bundle();
1395 results.putLong("sent_transactions", Debug.getBinderSentTransactions());
1396 results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
1397 return results;
1398 }
1399
1400 /**
1401 * Description of a Activity execution result to return to the original
1402 * activity.
1403 */
1404 public static final class ActivityResult {
1405 /**
1406 * Create a new activity result. See {@link Activity#setResult} for
1407 * more information.
1408 *
1409 * @param resultCode The result code to propagate back to the
1410 * originating activity, often RESULT_CANCELED or RESULT_OK
1411 * @param resultData The data to propagate back to the originating
1412 * activity.
1413 */
1414 public ActivityResult(int resultCode, Intent resultData) {
1415 mResultCode = resultCode;
1416 mResultData = resultData;
1417 }
1418
1419 /**
1420 * Retrieve the result code contained in this result.
1421 */
1422 public int getResultCode() {
1423 return mResultCode;
1424 }
1425
1426 /**
1427 * Retrieve the data contained in this result.
1428 */
1429 public Intent getResultData() {
1430 return mResultData;
1431 }
1432
1433 private final int mResultCode;
1434 private final Intent mResultData;
1435 }
1436
1437 /**
1438 * Execute a startActivity call made by the application. The default
1439 * implementation takes care of updating any active {@link ActivityMonitor}
1440 * objects and dispatches this call to the system activity manager; you can
1441 * override this to watch for the application to start an activity, and
1442 * modify what happens when it does.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001443 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001444 * <p>This method returns an {@link ActivityResult} object, which you can
1445 * use when intercepting application calls to avoid performing the start
1446 * activity action but still return the result the application is
1447 * expecting. To do this, override this method to catch the call to start
1448 * activity so that it returns a new ActivityResult containing the results
1449 * you would like the application to see, and don't call up to the super
1450 * class. Note that an application is only expecting a result if
1451 * <var>requestCode</var> is &gt;= 0.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001452 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001453 * <p>This method throws {@link android.content.ActivityNotFoundException}
1454 * if there was no Activity found to run the given Intent.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001455 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 * @param who The Context from which the activity is being started.
1457 * @param contextThread The main thread of the Context from which the activity
1458 * is being started.
1459 * @param token Internal token identifying to the system who is starting
1460 * the activity; may be null.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001461 * @param target Which activity is performing the start (and thus receiving
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 * any result); may be null if this call is not being made
1463 * from an activity.
1464 * @param intent The actual Intent to start.
1465 * @param requestCode Identifier for this request's result; less than zero
1466 * if the caller is not expecting a result.
Dianne Hackborna4972e92012-03-14 10:38:05 -07001467 * @param options Addition options.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001468 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 * @return To force the return of a particular result, return an
1470 * ActivityResult object containing the desired data; otherwise
1471 * return null. The default implementation always returns null.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001472 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 * @throws android.content.ActivityNotFoundException
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001474 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 * @see Activity#startActivity(Intent)
1476 * @see Activity#startActivityForResult(Intent, int)
1477 * @see Activity#startActivityFromChild
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001478 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001479 * {@hide}
1480 */
1481 public ActivityResult execStartActivity(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001482 Context who, IBinder contextThread, IBinder token, Activity target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001483 Intent intent, int requestCode, Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001484 IApplicationThread whoThread = (IApplicationThread) contextThread;
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001485 Uri referrer = target != null ? target.onProvideReferrer() : null;
1486 if (referrer != null) {
1487 intent.putExtra(Intent.EXTRA_REFERRER, referrer);
1488 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001489 if (mActivityMonitors != null) {
1490 synchronized (mSync) {
1491 final int N = mActivityMonitors.size();
1492 for (int i=0; i<N; i++) {
1493 final ActivityMonitor am = mActivityMonitors.get(i);
1494 if (am.match(who, null, intent)) {
1495 am.mHits++;
1496 if (am.isBlocking()) {
1497 return requestCode >= 0 ? am.getResult() : null;
1498 }
1499 break;
1500 }
1501 }
1502 }
1503 }
1504 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001505 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001506 intent.prepareToLeaveProcess(who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001507 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001508 .startActivity(whoThread, who.getBasePackageName(), intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001509 intent.resolveTypeIfNeeded(who.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07001510 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001511 requestCode, 0, null, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 checkStartActivityResult(result, intent);
1513 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001514 throw new RuntimeException("Failure from system", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 }
1516 return null;
1517 }
1518
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001519 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001520 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001521 * but accepts an array of activities to be started. Note that active
1522 * {@link ActivityMonitor} objects only match against the first activity in
1523 * the array.
1524 *
1525 * {@hide}
1526 */
1527 public void execStartActivities(Context who, IBinder contextThread,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001528 IBinder token, Activity target, Intent[] intents, Bundle options) {
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001529 execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
1530 UserHandle.myUserId());
1531 }
1532
1533 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001534 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001535 * but accepts an array of activities to be started. Note that active
1536 * {@link ActivityMonitor} objects only match against the first activity in
1537 * the array.
1538 *
1539 * {@hide}
1540 */
1541 public void execStartActivitiesAsUser(Context who, IBinder contextThread,
1542 IBinder token, Activity target, Intent[] intents, Bundle options,
1543 int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001544 IApplicationThread whoThread = (IApplicationThread) contextThread;
1545 if (mActivityMonitors != null) {
1546 synchronized (mSync) {
1547 final int N = mActivityMonitors.size();
1548 for (int i=0; i<N; i++) {
1549 final ActivityMonitor am = mActivityMonitors.get(i);
1550 if (am.match(who, null, intents[0])) {
1551 am.mHits++;
1552 if (am.isBlocking()) {
1553 return;
1554 }
1555 break;
1556 }
1557 }
1558 }
1559 }
1560 try {
1561 String[] resolvedTypes = new String[intents.length];
1562 for (int i=0; i<intents.length; i++) {
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001563 intents[i].migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001564 intents[i].prepareToLeaveProcess(who);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001565 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
1566 }
1567 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001568 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
1569 token, options, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001570 checkStartActivityResult(result, intents[0]);
1571 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001572 throw new RuntimeException("Failure from system", e);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001573 }
1574 }
1575
1576 /**
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001577 * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001578 * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)},
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001579 * but for calls from a {#link Fragment}.
1580 *
1581 * @param who The Context from which the activity is being started.
1582 * @param contextThread The main thread of the Context from which the activity
1583 * is being started.
1584 * @param token Internal token identifying to the system who is starting
1585 * the activity; may be null.
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001586 * @param target Which element is performing the start (and thus receiving
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001587 * any result).
1588 * @param intent The actual Intent to start.
1589 * @param requestCode Identifier for this request's result; less than zero
1590 * if the caller is not expecting a result.
1591 *
1592 * @return To force the return of a particular result, return an
1593 * ActivityResult object containing the desired data; otherwise
1594 * return null. The default implementation always returns null.
1595 *
1596 * @throws android.content.ActivityNotFoundException
1597 *
1598 * @see Activity#startActivity(Intent)
1599 * @see Activity#startActivityForResult(Intent, int)
1600 * @see Activity#startActivityFromChild
1601 *
1602 * {@hide}
1603 */
1604 public ActivityResult execStartActivity(
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001605 Context who, IBinder contextThread, IBinder token, String target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001606 Intent intent, int requestCode, Bundle options) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001607 IApplicationThread whoThread = (IApplicationThread) contextThread;
1608 if (mActivityMonitors != null) {
1609 synchronized (mSync) {
1610 final int N = mActivityMonitors.size();
1611 for (int i=0; i<N; i++) {
1612 final ActivityMonitor am = mActivityMonitors.get(i);
1613 if (am.match(who, null, intent)) {
1614 am.mHits++;
1615 if (am.isBlocking()) {
1616 return requestCode >= 0 ? am.getResult() : null;
1617 }
1618 break;
1619 }
1620 }
1621 }
1622 }
1623 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001624 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001625 intent.prepareToLeaveProcess(who);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001626 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001627 .startActivity(whoThread, who.getBasePackageName(), intent,
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001628 intent.resolveTypeIfNeeded(who.getContentResolver()),
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001629 token, target, requestCode, 0, null, options);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001630 checkStartActivityResult(result, intent);
1631 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001632 throw new RuntimeException("Failure from system", e);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001633 }
1634 return null;
1635 }
1636
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001637 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001638 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
1639 * but for starting as a particular user.
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001640 *
1641 * @param who The Context from which the activity is being started.
1642 * @param contextThread The main thread of the Context from which the activity
1643 * is being started.
1644 * @param token Internal token identifying to the system who is starting
1645 * the activity; may be null.
1646 * @param target Which fragment is performing the start (and thus receiving
1647 * any result).
1648 * @param intent The actual Intent to start.
1649 * @param requestCode Identifier for this request's result; less than zero
1650 * if the caller is not expecting a result.
1651 *
1652 * @return To force the return of a particular result, return an
1653 * ActivityResult object containing the desired data; otherwise
1654 * return null. The default implementation always returns null.
1655 *
1656 * @throws android.content.ActivityNotFoundException
1657 *
1658 * @see Activity#startActivity(Intent)
1659 * @see Activity#startActivityForResult(Intent, int)
1660 * @see Activity#startActivityFromChild
1661 *
1662 * {@hide}
1663 */
1664 public ActivityResult execStartActivity(
1665 Context who, IBinder contextThread, IBinder token, Activity target,
1666 Intent intent, int requestCode, Bundle options, UserHandle user) {
1667 IApplicationThread whoThread = (IApplicationThread) contextThread;
1668 if (mActivityMonitors != null) {
1669 synchronized (mSync) {
1670 final int N = mActivityMonitors.size();
1671 for (int i=0; i<N; i++) {
1672 final ActivityMonitor am = mActivityMonitors.get(i);
1673 if (am.match(who, null, intent)) {
1674 am.mHits++;
1675 if (am.isBlocking()) {
1676 return requestCode >= 0 ? am.getResult() : null;
1677 }
1678 break;
1679 }
1680 }
1681 }
1682 }
1683 try {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001684 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001685 intent.prepareToLeaveProcess(who);
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001686 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001687 .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001688 intent.resolveTypeIfNeeded(who.getContentResolver()),
1689 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001690 requestCode, 0, null, options, user.getIdentifier());
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001691 checkStartActivityResult(result, intent);
1692 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001693 throw new RuntimeException("Failure from system", e);
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001694 }
1695 return null;
1696 }
1697
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001698 /**
1699 * Special version!
1700 * @hide
1701 */
1702 public ActivityResult execStartActivityAsCaller(
1703 Context who, IBinder contextThread, IBinder token, Activity target,
Dianne Hackborna7cfbe02015-07-16 10:52:52 -07001704 Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity,
1705 int userId) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001706 IApplicationThread whoThread = (IApplicationThread) contextThread;
1707 if (mActivityMonitors != null) {
1708 synchronized (mSync) {
1709 final int N = mActivityMonitors.size();
1710 for (int i=0; i<N; i++) {
1711 final ActivityMonitor am = mActivityMonitors.get(i);
1712 if (am.match(who, null, intent)) {
1713 am.mHits++;
1714 if (am.isBlocking()) {
1715 return requestCode >= 0 ? am.getResult() : null;
1716 }
1717 break;
1718 }
1719 }
1720 }
1721 }
1722 try {
1723 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001724 intent.prepareToLeaveProcess(who);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001725 int result = ActivityManagerNative.getDefault()
1726 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
1727 intent.resolveTypeIfNeeded(who.getContentResolver()),
1728 token, target != null ? target.mEmbeddedID : null,
Dianne Hackborna7cfbe02015-07-16 10:52:52 -07001729 requestCode, 0, null, options, ignoreTargetSecurity, userId);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001730 checkStartActivityResult(result, intent);
1731 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001732 throw new RuntimeException("Failure from system", e);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001733 }
1734 return null;
1735 }
1736
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001737 /**
1738 * Special version!
1739 * @hide
1740 */
1741 public void execStartActivityFromAppTask(
1742 Context who, IBinder contextThread, IAppTask appTask,
1743 Intent intent, Bundle options) {
1744 IApplicationThread whoThread = (IApplicationThread) contextThread;
1745 if (mActivityMonitors != null) {
1746 synchronized (mSync) {
1747 final int N = mActivityMonitors.size();
1748 for (int i=0; i<N; i++) {
1749 final ActivityMonitor am = mActivityMonitors.get(i);
1750 if (am.match(who, null, intent)) {
1751 am.mHits++;
1752 if (am.isBlocking()) {
1753 return;
1754 }
1755 break;
1756 }
1757 }
1758 }
1759 }
1760 try {
1761 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001762 intent.prepareToLeaveProcess(who);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001763 int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
1764 intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options);
1765 checkStartActivityResult(result, intent);
1766 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001767 throw new RuntimeException("Failure from system", e);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001768 }
1769 return;
1770 }
1771
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001772 /*package*/ final void init(ActivityThread thread,
1773 Context instrContext, Context appContext, ComponentName component,
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001774 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001775 mThread = thread;
1776 mMessageQueue = mThread.getLooper().myQueue();
1777 mInstrContext = instrContext;
1778 mAppContext = appContext;
1779 mComponent = component;
1780 mWatcher = watcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001781 mUiAutomationConnection = uiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001782 }
1783
Dianne Hackborn91097de2014-04-04 18:02:06 -07001784 /** @hide */
1785 public static void checkStartActivityResult(int res, Object intent) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07001786 if (res >= ActivityManager.START_SUCCESS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001787 return;
1788 }
1789
1790 switch (res) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07001791 case ActivityManager.START_INTENT_NOT_RESOLVED:
1792 case ActivityManager.START_CLASS_NOT_FOUND:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001793 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001794 throw new ActivityNotFoundException(
1795 "Unable to find explicit activity class "
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001796 + ((Intent)intent).getComponent().toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001797 + "; have you declared this activity in your AndroidManifest.xml?");
1798 throw new ActivityNotFoundException(
1799 "No Activity found to handle " + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07001800 case ActivityManager.START_PERMISSION_DENIED:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001801 throw new SecurityException("Not allowed to start activity "
1802 + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07001803 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001804 throw new AndroidRuntimeException(
1805 "FORWARD_RESULT_FLAG used while also requesting a result");
Dianne Hackborna4972e92012-03-14 10:38:05 -07001806 case ActivityManager.START_NOT_ACTIVITY:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001807 throw new IllegalArgumentException(
1808 "PendingIntent is not an activity");
Dianne Hackborn91097de2014-04-04 18:02:06 -07001809 case ActivityManager.START_NOT_VOICE_COMPATIBLE:
1810 throw new SecurityException(
1811 "Starting under voice control not allowed for: " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001812 default:
1813 throw new AndroidRuntimeException("Unknown error code "
1814 + res + " when starting " + intent);
1815 }
1816 }
Chong Zhang45c25ce2015-08-10 22:18:26 -07001817
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001818 private final void validateNotAppThread() {
Kristian Monsen0a303282013-01-18 14:50:07 -08001819 if (Looper.myLooper() == Looper.getMainLooper()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001820 throw new RuntimeException(
1821 "This method can not be called from the main application thread");
1822 }
1823 }
1824
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001825 /**
1826 * Gets the {@link UiAutomation} instance.
1827 * <p>
1828 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
1829 * work across application boundaries while the APIs exposed by the instrumentation
1830 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
1831 * not allow you to inject the event in an app different from the instrumentation
1832 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
1833 * will work regardless of the current application.
1834 * </p>
1835 * <p>
1836 * A typical test case should be using either the {@link UiAutomation} or
1837 * {@link Instrumentation} APIs. Using both APIs at the same time is not
1838 * a mistake by itself but a client has to be aware of the APIs limitations.
1839 * </p>
Phil Weaver1dd87222016-01-26 17:15:15 -08001840 * @return The UI automation instance. If none exists, a new one is created with no flags set.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001841 *
1842 * @see UiAutomation
1843 */
1844 public UiAutomation getUiAutomation() {
Phil Weaver846522c2016-02-01 17:01:44 -08001845 if ((mUiAutomation == null) || (mUiAutomation.isDestroyed())) {
1846 return getUiAutomation(0);
Phil Weaver1dd87222016-01-26 17:15:15 -08001847 }
Phil Weaver846522c2016-02-01 17:01:44 -08001848 return mUiAutomation;
Phil Weaver1dd87222016-01-26 17:15:15 -08001849 }
1850
1851 /**
1852 * Gets the {@link UiAutomation} instance with flags set.
1853 * <p>
1854 * <strong>Note:</strong> Only one UiAutomation can be obtained. Calling this method
1855 * twice with different flags will fail unless the UiAutomation obtained in the first call
1856 * is released with {@link UiAutomation#destroy()}.
1857 * </p>
1858 * <p>
1859 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
1860 * work across application boundaries while the APIs exposed by the instrumentation
1861 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
1862 * not allow you to inject the event in an app different from the instrumentation
1863 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
1864 * will work regardless of the current application.
1865 * </p>
1866 * <p>
1867 * A typical test case should be using either the {@link UiAutomation} or
1868 * {@link Instrumentation} APIs. Using both APIs at the same time is not
1869 * a mistake by itself but a client has to be aware of the APIs limitations.
1870 * </p>
1871 *
1872 * @param flags The flags to be passed to the UiAutomation, for example
1873 * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
1874 *
1875 * @return The UI automation instance.
1876 *
1877 * @see UiAutomation
1878 */
1879 public UiAutomation getUiAutomation(int flags) {
1880 if (mUiAutomationConnection != null) {
1881 if ((mUiAutomation == null) || (mUiAutomation.isDestroyed())) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001882 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
1883 mUiAutomationConnection);
Phil Weaver1dd87222016-01-26 17:15:15 -08001884 mUiAutomation.connect(flags);
1885 } else {
1886 if (mUiAutomation.getFlags() != flags) {
1887 throw new RuntimeException(
1888 "Cannot get a UiAutomation with different flags from the existing one");
1889 }
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001890 }
1891 return mUiAutomation;
1892 }
1893 return null;
1894 }
1895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001896 private final class InstrumentationThread extends Thread {
1897 public InstrumentationThread(String name) {
1898 super(name);
1899 }
1900 public void run() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001901 try {
1902 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
1903 } catch (RuntimeException e) {
Phil Weaver1dd87222016-01-26 17:15:15 -08001904 Log.w(TAG, "Exception setting priority of instrumentation thread "
1905 + Process.myTid(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001906 }
1907 if (mAutomaticPerformanceSnapshots) {
1908 startPerformanceSnapshot();
1909 }
1910 onStart();
1911 }
1912 }
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001913
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001914 private static final class EmptyRunnable implements Runnable {
1915 public void run() {
1916 }
1917 }
1918
1919 private static final class SyncRunnable implements Runnable {
1920 private final Runnable mTarget;
1921 private boolean mComplete;
1922
1923 public SyncRunnable(Runnable target) {
1924 mTarget = target;
1925 }
1926
1927 public void run() {
1928 mTarget.run();
1929 synchronized (this) {
1930 mComplete = true;
1931 notifyAll();
1932 }
1933 }
1934
1935 public void waitForComplete() {
1936 synchronized (this) {
1937 while (!mComplete) {
1938 try {
1939 wait();
1940 } catch (InterruptedException e) {
1941 }
1942 }
1943 }
1944 }
1945 }
1946
1947 private static final class ActivityWaiter {
1948 public final Intent intent;
1949 public Activity activity;
1950
1951 public ActivityWaiter(Intent _intent) {
1952 intent = _intent;
1953 }
1954 }
1955
1956 private final class ActivityGoing implements MessageQueue.IdleHandler {
1957 private final ActivityWaiter mWaiter;
1958
1959 public ActivityGoing(ActivityWaiter waiter) {
1960 mWaiter = waiter;
1961 }
1962
1963 public final boolean queueIdle() {
1964 synchronized (mSync) {
1965 mWaitingActivities.remove(mWaiter);
1966 mSync.notifyAll();
1967 }
1968 return false;
1969 }
1970 }
1971
1972 private static final class Idler implements MessageQueue.IdleHandler {
1973 private final Runnable mCallback;
1974 private boolean mIdle;
1975
1976 public Idler(Runnable callback) {
1977 mCallback = callback;
1978 mIdle = false;
1979 }
1980
1981 public final boolean queueIdle() {
1982 if (mCallback != null) {
1983 mCallback.run();
1984 }
1985 synchronized (this) {
1986 mIdle = true;
1987 notifyAll();
1988 }
1989 return false;
1990 }
1991
1992 public void waitForIdle() {
1993 synchronized (this) {
1994 while (!mIdle) {
1995 try {
1996 wait();
1997 } catch (InterruptedException e) {
1998 }
1999 }
2000 }
2001 }
2002 }
2003}