blob: f934a9f5d826994e6c2890f979b8f0978dbfe251 [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
Phil Weaver35841682016-03-09 09:52:51 -080019import android.annotation.IntDef;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.ActivityNotFoundException;
21import android.content.ComponentName;
22import android.content.Context;
23import android.content.Intent;
24import android.content.IntentFilter;
25import android.content.pm.ActivityInfo;
26import android.content.res.Configuration;
Jeff Brownac143512012-04-05 18:57:33 -070027import android.hardware.input.InputManager;
Dianne Hackborna3acdb32015-06-08 17:07:40 -070028import android.net.Uri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.os.Debug;
31import android.os.IBinder;
Kristian Monsen0a303282013-01-18 14:50:07 -080032import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.os.MessageQueue;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080034import android.os.PerformanceCollector;
Craig Mautnera0026042014-04-23 11:45:37 -070035import android.os.PersistableBundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036import android.os.Process;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080037import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.os.ServiceManager;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080039import android.os.SystemClock;
Dianne Hackbornf1c26e22012-08-23 13:54:58 -070040import android.os.UserHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041import android.util.AndroidRuntimeException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.util.Log;
43import android.view.IWindowManager;
Jeff Brownac143512012-04-05 18:57:33 -070044import android.view.InputDevice;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.view.KeyCharacterMap;
46import android.view.KeyEvent;
47import android.view.MotionEvent;
48import android.view.ViewConfiguration;
49import android.view.Window;
Dianne Hackborn85d558c2014-11-04 10:31:54 -080050import com.android.internal.content.ReferrerIntent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051
52import java.io.File;
Phil Weaver35841682016-03-09 09:52:51 -080053import java.lang.annotation.Retention;
54import java.lang.annotation.RetentionPolicy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import java.util.ArrayList;
56import java.util.List;
57
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058/**
59 * Base class for implementing application instrumentation code. When running
60 * with instrumentation turned on, this class will be instantiated for you
61 * before any of the application code, allowing you to monitor all of the
62 * interaction the system has with the application. An Instrumentation
63 * implementation is described to the system through an AndroidManifest.xml's
64 * <instrumentation> tag.
65 */
66public class Instrumentation {
Svetoslav Ganov80943d82013-01-02 10:25:37 -080067
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 /**
69 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
70 * identifies the class that is writing the report. This can be used to provide more structured
71 * logging or reporting capabilities in the IInstrumentationWatcher.
72 */
73 public static final String REPORT_KEY_IDENTIFIER = "id";
74 /**
75 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
76 * identifies a string which can simply be printed to the output stream. Using these streams
77 * provides a "pretty printer" version of the status & final packets. Any bundles including
78 * this key should also include the complete set of raw key/value pairs, so that the
79 * instrumentation can also be launched, and results collected, by an automated system.
80 */
81 public static final String REPORT_KEY_STREAMRESULT = "stream";
Svetoslav Ganov80943d82013-01-02 10:25:37 -080082
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 private static final String TAG = "Instrumentation";
Phil Weaver35841682016-03-09 09:52:51 -080084
85 /**
86 * @hide
87 */
88 @Retention(RetentionPolicy.SOURCE)
89 @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES})
90 public @interface UiAutomationFlags {};
91
92
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 private final Object mSync = new Object();
94 private ActivityThread mThread = null;
95 private MessageQueue mMessageQueue = null;
96 private Context mInstrContext;
97 private Context mAppContext;
98 private ComponentName mComponent;
99 private Thread mRunner;
100 private List<ActivityWaiter> mWaitingActivities;
101 private List<ActivityMonitor> mActivityMonitors;
102 private IInstrumentationWatcher mWatcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800103 private IUiAutomationConnection mUiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 private boolean mAutomaticPerformanceSnapshots = false;
Jack Wangff1df692009-08-26 17:19:13 -0700105 private PerformanceCollector mPerformanceCollector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800106 private Bundle mPerfMetrics = new Bundle();
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800107 private UiAutomation mUiAutomation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108
109 public Instrumentation() {
110 }
111
112 /**
113 * Called when the instrumentation is starting, before any application code
114 * has been loaded. Usually this will be implemented to simply call
115 * {@link #start} to begin the instrumentation thread, which will then
116 * continue execution in {@link #onStart}.
117 *
118 * <p>If you do not need your own thread -- that is you are writing your
119 * instrumentation to be completely asynchronous (returning to the event
120 * loop so that the application can run), you can simply begin your
121 * instrumentation here, for example call {@link Context#startActivity} to
122 * begin the appropriate first activity of the application.
123 *
124 * @param arguments Any additional arguments that were supplied when the
125 * instrumentation was started.
126 */
127 public void onCreate(Bundle arguments) {
128 }
129
130 /**
131 * Create and start a new thread in which to run instrumentation. This new
132 * thread will call to {@link #onStart} where you can implement the
133 * instrumentation.
134 */
135 public void start() {
136 if (mRunner != null) {
137 throw new RuntimeException("Instrumentation already started");
138 }
139 mRunner = new InstrumentationThread("Instr: " + getClass().getName());
140 mRunner.start();
141 }
142
143 /**
144 * Method where the instrumentation thread enters execution. This allows
145 * you to run your instrumentation code in a separate thread than the
146 * application, so that it can perform blocking operation such as
147 * {@link #sendKeySync} or {@link #startActivitySync}.
148 *
149 * <p>You will typically want to call finish() when this function is done,
150 * to end your instrumentation.
151 */
152 public void onStart() {
153 }
154
155 /**
156 * This is called whenever the system captures an unhandled exception that
157 * was thrown by the application. The default implementation simply
158 * returns false, allowing normal system handling of the exception to take
159 * place.
160 *
161 * @param obj The client object that generated the exception. May be an
162 * Application, Activity, BroadcastReceiver, Service, or null.
163 * @param e The exception that was thrown.
164 *
165 * @return To allow normal system exception process to occur, return false.
166 * If true is returned, the system will proceed as if the exception
167 * didn't happen.
168 */
169 public boolean onException(Object obj, Throwable e) {
170 return false;
171 }
172
173 /**
174 * Provide a status report about the application.
175 *
176 * @param resultCode Current success/failure of instrumentation.
177 * @param results Any results to send back to the code that started the instrumentation.
178 */
179 public void sendStatus(int resultCode, Bundle results) {
180 if (mWatcher != null) {
181 try {
182 mWatcher.instrumentationStatus(mComponent, resultCode, results);
183 }
184 catch (RemoteException e) {
185 mWatcher = null;
186 }
187 }
188 }
189
190 /**
191 * Terminate instrumentation of the application. This will cause the
192 * application process to exit, removing this instrumentation from the next
193 * time the application is started.
194 *
195 * @param resultCode Overall success/failure of instrumentation.
196 * @param results Any results to send back to the code that started the
197 * instrumentation.
198 */
199 public void finish(int resultCode, Bundle results) {
200 if (mAutomaticPerformanceSnapshots) {
201 endPerformanceSnapshot();
202 }
203 if (mPerfMetrics != null) {
Dianne Hackbornb65ea7b2014-06-20 12:18:55 -0700204 if (results == null) {
205 results = new Bundle();
206 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 results.putAll(mPerfMetrics);
208 }
Phil Weaverd8e88832016-03-28 17:26:25 -0700209 if ((mUiAutomation != null) && !mUiAutomation.isDestroyed()) {
Adam Momtaz8f6f1f42013-04-10 12:42:58 -0700210 mUiAutomation.disconnect();
211 mUiAutomation = null;
212 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 mThread.finishInstrumentation(resultCode, results);
214 }
215
216 public void setAutomaticPerformanceSnapshots() {
217 mAutomaticPerformanceSnapshots = true;
Jack Wangff1df692009-08-26 17:19:13 -0700218 mPerformanceCollector = new PerformanceCollector();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 }
220
221 public void startPerformanceSnapshot() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800222 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700223 mPerformanceCollector.beginSnapshot(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 }
225 }
226
227 public void endPerformanceSnapshot() {
228 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700229 mPerfMetrics = mPerformanceCollector.endSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 }
231 }
232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 /**
234 * Called when the instrumented application is stopping, after all of the
235 * normal application cleanup has occurred.
236 */
237 public void onDestroy() {
238 }
239
240 /**
241 * Return the Context of this instrumentation's package. Note that this is
242 * often different than the Context of the application being
243 * instrumentated, since the instrumentation code often lives is a
244 * different package than that of the application it is running against.
245 * See {@link #getTargetContext} to retrieve a Context for the target
246 * application.
247 *
248 * @return The instrumentation's package context.
249 *
250 * @see #getTargetContext
251 */
252 public Context getContext() {
253 return mInstrContext;
254 }
255
256 /**
257 * Returns complete component name of this instrumentation.
258 *
259 * @return Returns the complete component name for this instrumentation.
260 */
261 public ComponentName getComponentName() {
262 return mComponent;
263 }
264
265 /**
266 * Return a Context for the target application being instrumented. Note
267 * that this is often different than the Context of the instrumentation
268 * code, since the instrumentation code often lives is a different package
269 * than that of the application it is running against. See
270 * {@link #getContext} to retrieve a Context for the instrumentation code.
271 *
272 * @return A Context in the target application.
273 *
274 * @see #getContext
275 */
276 public Context getTargetContext() {
277 return mAppContext;
278 }
279
280 /**
281 * Check whether this instrumentation was started with profiling enabled.
282 *
283 * @return Returns true if profiling was enabled when starting, else false.
284 */
285 public boolean isProfiling() {
286 return mThread.isProfiling();
287 }
288
289 /**
290 * This method will start profiling if isProfiling() returns true. You should
291 * only call this method if you set the handleProfiling attribute in the
292 * manifest file for this Instrumentation to true.
293 */
294 public void startProfiling() {
295 if (mThread.isProfiling()) {
296 File file = new File(mThread.getProfileFilePath());
297 file.getParentFile().mkdirs();
298 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
299 }
300 }
301
302 /**
303 * Stops profiling if isProfiling() returns true.
304 */
305 public void stopProfiling() {
306 if (mThread.isProfiling()) {
307 Debug.stopMethodTracing();
308 }
309 }
310
311 /**
312 * Force the global system in or out of touch mode. This can be used if
313 * your instrumentation relies on the UI being in one more or the other
314 * when it starts.
315 *
316 * @param inTouch Set to true to be in touch mode, false to be in
317 * focus mode.
318 */
319 public void setInTouchMode(boolean inTouch) {
320 try {
321 IWindowManager.Stub.asInterface(
322 ServiceManager.getService("window")).setInTouchMode(inTouch);
323 } catch (RemoteException e) {
324 // Shouldn't happen!
325 }
326 }
327
328 /**
329 * Schedule a callback for when the application's main thread goes idle
330 * (has no more events to process).
331 *
332 * @param recipient Called the next time the thread's message queue is
333 * idle.
334 */
335 public void waitForIdle(Runnable recipient) {
336 mMessageQueue.addIdleHandler(new Idler(recipient));
337 mThread.getHandler().post(new EmptyRunnable());
338 }
339
340 /**
341 * Synchronously wait for the application to be idle. Can not be called
342 * from the main application thread -- use {@link #start} to execute
343 * instrumentation in its own thread.
344 */
345 public void waitForIdleSync() {
346 validateNotAppThread();
347 Idler idler = new Idler(null);
348 mMessageQueue.addIdleHandler(idler);
349 mThread.getHandler().post(new EmptyRunnable());
350 idler.waitForIdle();
351 }
352
353 /**
354 * Execute a call on the application's main thread, blocking until it is
355 * complete. Useful for doing things that are not thread-safe, such as
356 * looking at or modifying the view hierarchy.
357 *
358 * @param runner The code to run on the main thread.
359 */
360 public void runOnMainSync(Runnable runner) {
361 validateNotAppThread();
362 SyncRunnable sr = new SyncRunnable(runner);
363 mThread.getHandler().post(sr);
364 sr.waitForComplete();
365 }
366
367 /**
368 * Start a new activity and wait for it to begin running before returning.
369 * In addition to being synchronous, this method as some semantic
370 * differences from the standard {@link Context#startActivity} call: the
371 * activity component is resolved before talking with the activity manager
372 * (its class name is specified in the Intent that this method ultimately
373 * starts), and it does not allow you to start activities that run in a
374 * different process. In addition, if the given Intent resolves to
375 * multiple activities, instead of displaying a dialog for the user to
376 * select an activity, an exception will be thrown.
377 *
378 * <p>The function returns as soon as the activity goes idle following the
379 * call to its {@link Activity#onCreate}. Generally this means it has gone
380 * through the full initialization including {@link Activity#onResume} and
381 * drawn and displayed its initial window.
382 *
383 * @param intent Description of the activity to start.
384 *
385 * @see Context#startActivity
386 */
387 public Activity startActivitySync(Intent intent) {
388 validateNotAppThread();
389
390 synchronized (mSync) {
391 intent = new Intent(intent);
392
393 ActivityInfo ai = intent.resolveActivityInfo(
394 getTargetContext().getPackageManager(), 0);
395 if (ai == null) {
396 throw new RuntimeException("Unable to resolve activity for: " + intent);
397 }
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700398 String myProc = mThread.getProcessName();
399 if (!ai.processName.equals(myProc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 // todo: if this intent is ambiguous, look here to see if
401 // there is a single match that is in our package.
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700402 throw new RuntimeException("Intent in process "
403 + myProc + " resolved to different process "
404 + ai.processName + ": " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 }
406
407 intent.setComponent(new ComponentName(
408 ai.applicationInfo.packageName, ai.name));
409 final ActivityWaiter aw = new ActivityWaiter(intent);
410
411 if (mWaitingActivities == null) {
412 mWaitingActivities = new ArrayList();
413 }
414 mWaitingActivities.add(aw);
415
416 getTargetContext().startActivity(intent);
417
418 do {
419 try {
420 mSync.wait();
421 } catch (InterruptedException e) {
422 }
423 } while (mWaitingActivities.contains(aw));
424
425 return aw.activity;
426 }
427 }
428
429 /**
430 * Information about a particular kind of Intent that is being monitored.
431 * An instance of this class is added to the
432 * current instrumentation through {@link #addMonitor}; after being added,
433 * when a new activity is being started the monitor will be checked and, if
434 * matching, its hit count updated and (optionally) the call stopped and a
435 * canned result returned.
436 *
437 * <p>An ActivityMonitor can also be used to look for the creation of an
438 * activity, through the {@link #waitForActivity} method. This will return
439 * after a matching activity has been created with that activity object.
440 */
441 public static class ActivityMonitor {
442 private final IntentFilter mWhich;
443 private final String mClass;
444 private final ActivityResult mResult;
445 private final boolean mBlock;
446
447
448 // This is protected by 'Instrumentation.this.mSync'.
449 /*package*/ int mHits = 0;
450
451 // This is protected by 'this'.
452 /*package*/ Activity mLastActivity = null;
453
454 /**
455 * Create a new ActivityMonitor that looks for a particular kind of
456 * intent to be started.
457 *
458 * @param which The set of intents this monitor is responsible for.
459 * @param result A canned result to return if the monitor is hit; can
460 * be null.
461 * @param block Controls whether the monitor should block the activity
462 * start (returning its canned result) or let the call
463 * proceed.
464 *
465 * @see Instrumentation#addMonitor
466 */
467 public ActivityMonitor(
468 IntentFilter which, ActivityResult result, boolean block) {
469 mWhich = which;
470 mClass = null;
471 mResult = result;
472 mBlock = block;
473 }
474
475 /**
476 * Create a new ActivityMonitor that looks for a specific activity
477 * class to be started.
478 *
479 * @param cls The activity class this monitor is responsible for.
480 * @param result A canned result to return if the monitor is hit; can
481 * be null.
482 * @param block Controls whether the monitor should block the activity
483 * start (returning its canned result) or let the call
484 * proceed.
485 *
486 * @see Instrumentation#addMonitor
487 */
488 public ActivityMonitor(
489 String cls, ActivityResult result, boolean block) {
490 mWhich = null;
491 mClass = cls;
492 mResult = result;
493 mBlock = block;
494 }
495
496 /**
497 * Retrieve the filter associated with this ActivityMonitor.
498 */
499 public final IntentFilter getFilter() {
500 return mWhich;
501 }
502
503 /**
504 * Retrieve the result associated with this ActivityMonitor, or null if
505 * none.
506 */
507 public final ActivityResult getResult() {
508 return mResult;
509 }
510
511 /**
512 * Check whether this monitor blocks activity starts (not allowing the
513 * actual activity to run) or allows them to execute normally.
514 */
515 public final boolean isBlocking() {
516 return mBlock;
517 }
518
519 /**
520 * Retrieve the number of times the monitor has been hit so far.
521 */
522 public final int getHits() {
523 return mHits;
524 }
525
526 /**
527 * Retrieve the most recent activity class that was seen by this
528 * monitor.
529 */
530 public final Activity getLastActivity() {
531 return mLastActivity;
532 }
533
534 /**
535 * Block until an Activity is created that matches this monitor,
536 * returning the resulting activity.
537 *
538 * @return Activity
539 */
540 public final Activity waitForActivity() {
541 synchronized (this) {
542 while (mLastActivity == null) {
543 try {
544 wait();
545 } catch (InterruptedException e) {
546 }
547 }
548 Activity res = mLastActivity;
549 mLastActivity = null;
550 return res;
551 }
552 }
553
554 /**
555 * Block until an Activity is created that matches this monitor,
556 * returning the resulting activity or till the timeOut period expires.
557 * If the timeOut expires before the activity is started, return null.
558 *
Ben Gruver87904e82016-01-22 13:11:11 -0800559 * @param timeOut Time to wait in milliseconds before the activity is created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 *
561 * @return Activity
562 */
563 public final Activity waitForActivityWithTimeout(long timeOut) {
564 synchronized (this) {
Costin Manolacheb0935342011-07-15 11:20:42 -0700565 if (mLastActivity == null) {
566 try {
567 wait(timeOut);
568 } catch (InterruptedException e) {
569 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800570 }
571 if (mLastActivity == null) {
572 return null;
573 } else {
574 Activity res = mLastActivity;
575 mLastActivity = null;
576 return res;
577 }
578 }
579 }
580
581 final boolean match(Context who,
582 Activity activity,
583 Intent intent) {
584 synchronized (this) {
585 if (mWhich != null
586 && mWhich.match(who.getContentResolver(), intent,
587 true, "Instrumentation") < 0) {
588 return false;
589 }
590 if (mClass != null) {
591 String cls = null;
592 if (activity != null) {
593 cls = activity.getClass().getName();
594 } else if (intent.getComponent() != null) {
595 cls = intent.getComponent().getClassName();
596 }
597 if (cls == null || !mClass.equals(cls)) {
598 return false;
599 }
600 }
601 if (activity != null) {
602 mLastActivity = activity;
603 notifyAll();
604 }
605 return true;
606 }
607 }
608 }
609
610 /**
611 * Add a new {@link ActivityMonitor} that will be checked whenever an
612 * activity is started. The monitor is added
613 * after any existing ones; the monitor will be hit only if none of the
614 * existing monitors can themselves handle the Intent.
615 *
616 * @param monitor The new ActivityMonitor to see.
617 *
618 * @see #addMonitor(IntentFilter, ActivityResult, boolean)
619 * @see #checkMonitorHit
620 */
621 public void addMonitor(ActivityMonitor monitor) {
622 synchronized (mSync) {
623 if (mActivityMonitors == null) {
624 mActivityMonitors = new ArrayList();
625 }
626 mActivityMonitors.add(monitor);
627 }
628 }
629
630 /**
631 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
632 * creates an intent filter matching {@link ActivityMonitor} for you and
633 * returns it.
634 *
635 * @param filter The set of intents this monitor is responsible for.
636 * @param result A canned result to return if the monitor is hit; can
637 * be null.
638 * @param block Controls whether the monitor should block the activity
639 * start (returning its canned result) or let the call
640 * proceed.
641 *
642 * @return The newly created and added activity monitor.
643 *
644 * @see #addMonitor(ActivityMonitor)
645 * @see #checkMonitorHit
646 */
647 public ActivityMonitor addMonitor(
648 IntentFilter filter, ActivityResult result, boolean block) {
649 ActivityMonitor am = new ActivityMonitor(filter, result, block);
650 addMonitor(am);
651 return am;
652 }
653
654 /**
655 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
656 * creates a class matching {@link ActivityMonitor} for you and returns it.
657 *
658 * @param cls The activity class this monitor is responsible for.
659 * @param result A canned result to return if the monitor is hit; can
660 * be null.
661 * @param block Controls whether the monitor should block the activity
662 * start (returning its canned result) or let the call
663 * proceed.
664 *
665 * @return The newly created and added activity monitor.
666 *
667 * @see #addMonitor(ActivityMonitor)
668 * @see #checkMonitorHit
669 */
670 public ActivityMonitor addMonitor(
671 String cls, ActivityResult result, boolean block) {
672 ActivityMonitor am = new ActivityMonitor(cls, result, block);
673 addMonitor(am);
674 return am;
675 }
676
677 /**
678 * Test whether an existing {@link ActivityMonitor} has been hit. If the
679 * monitor has been hit at least <var>minHits</var> times, then it will be
680 * removed from the activity monitor list and true returned. Otherwise it
681 * is left as-is and false is returned.
682 *
683 * @param monitor The ActivityMonitor to check.
684 * @param minHits The minimum number of hits required.
685 *
686 * @return True if the hit count has been reached, else false.
687 *
688 * @see #addMonitor
689 */
690 public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
691 waitForIdleSync();
692 synchronized (mSync) {
693 if (monitor.getHits() < minHits) {
694 return false;
695 }
696 mActivityMonitors.remove(monitor);
697 }
698 return true;
699 }
700
701 /**
702 * Wait for an existing {@link ActivityMonitor} to be hit. Once the
703 * monitor has been hit, it is removed from the activity monitor list and
704 * the first created Activity object that matched it is returned.
705 *
706 * @param monitor The ActivityMonitor to wait for.
707 *
708 * @return The Activity object that matched the monitor.
709 */
710 public Activity waitForMonitor(ActivityMonitor monitor) {
711 Activity activity = monitor.waitForActivity();
712 synchronized (mSync) {
713 mActivityMonitors.remove(monitor);
714 }
715 return activity;
716 }
717
718 /**
719 * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
720 * expires. Once the monitor has been hit, it is removed from the activity
721 * monitor list and the first created Activity object that matched it is
722 * returned. If the timeout expires, a null object is returned.
723 *
724 * @param monitor The ActivityMonitor to wait for.
725 * @param timeOut The timeout value in secs.
726 *
727 * @return The Activity object that matched the monitor.
728 */
729 public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
730 Activity activity = monitor.waitForActivityWithTimeout(timeOut);
731 synchronized (mSync) {
732 mActivityMonitors.remove(monitor);
733 }
734 return activity;
735 }
736
737 /**
738 * Remove an {@link ActivityMonitor} that was previously added with
739 * {@link #addMonitor}.
740 *
741 * @param monitor The monitor to remove.
742 *
743 * @see #addMonitor
744 */
745 public void removeMonitor(ActivityMonitor monitor) {
746 synchronized (mSync) {
747 mActivityMonitors.remove(monitor);
748 }
749 }
750
751 /**
752 * Execute a particular menu item.
753 *
754 * @param targetActivity The activity in question.
755 * @param id The identifier associated with the menu item.
756 * @param flag Additional flags, if any.
757 * @return Whether the invocation was successful (for example, it could be
758 * false if item is disabled).
759 */
760 public boolean invokeMenuActionSync(Activity targetActivity,
761 int id, int flag) {
762 class MenuRunnable implements Runnable {
763 private final Activity activity;
764 private final int identifier;
765 private final int flags;
766 boolean returnValue;
767
768 public MenuRunnable(Activity _activity, int _identifier,
769 int _flags) {
770 activity = _activity;
771 identifier = _identifier;
772 flags = _flags;
773 }
774
775 public void run() {
776 Window win = activity.getWindow();
777
778 returnValue = win.performPanelIdentifierAction(
779 Window.FEATURE_OPTIONS_PANEL,
780 identifier,
781 flags);
782 }
783
784 }
785 MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
786 runOnMainSync(mr);
787 return mr.returnValue;
788 }
789
790 /**
791 * Show the context menu for the currently focused view and executes a
792 * particular context menu item.
793 *
794 * @param targetActivity The activity in question.
795 * @param id The identifier associated with the context menu item.
796 * @param flag Additional flags, if any.
797 * @return Whether the invocation was successful (for example, it could be
798 * false if item is disabled).
799 */
800 public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
801 validateNotAppThread();
802
803 // Bring up context menu for current focus.
804 // It'd be nice to do this through code, but currently ListView depends on
805 // long press to set metadata for its selected child
806
807 final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
808 sendKeySync(downEvent);
809
810 // Need to wait for long press
811 waitForIdleSync();
812 try {
813 Thread.sleep(ViewConfiguration.getLongPressTimeout());
814 } catch (InterruptedException e) {
815 Log.e(TAG, "Could not sleep for long press timeout", e);
816 return false;
817 }
818
819 final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
820 sendKeySync(upEvent);
821
822 // Wait for context menu to appear
823 waitForIdleSync();
824
825 class ContextMenuRunnable implements Runnable {
826 private final Activity activity;
827 private final int identifier;
828 private final int flags;
829 boolean returnValue;
830
831 public ContextMenuRunnable(Activity _activity, int _identifier,
832 int _flags) {
833 activity = _activity;
834 identifier = _identifier;
835 flags = _flags;
836 }
837
838 public void run() {
839 Window win = activity.getWindow();
840 returnValue = win.performContextMenuIdentifierAction(
841 identifier,
842 flags);
843 }
844
845 }
846
847 ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
848 runOnMainSync(cmr);
849 return cmr.returnValue;
850 }
851
852 /**
853 * Sends the key events corresponding to the text to the app being
854 * instrumented.
855 *
856 * @param text The text to be sent.
857 */
858 public void sendStringSync(String text) {
859 if (text == null) {
860 return;
861 }
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800862 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800864 KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800865
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800866 if (events != null) {
867 for (int i = 0; i < events.length; i++) {
Svetoslav Ganovf434e372011-11-11 16:50:21 -0800868 // We have to change the time of an event before injecting it because
869 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
870 // time stamp and the system rejects too old events. Hence, it is
871 // possible for an event to become stale before it is injected if it
872 // takes too long to inject the preceding ones.
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800873 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800874 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800875 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800876 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800877
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800878 /**
879 * Send a key event to the currently focused window/view and wait for it to
880 * be processed. Finished at some point after the recipient has returned
881 * from its event processing, though it may <em>not</em> have completely
882 * finished reacting from the event -- for example, if it needs to update
883 * its display as a result, it may still be in the process of doing that.
884 *
885 * @param event The event to send to the current focus.
886 */
887 public void sendKeySync(KeyEvent event) {
888 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -0700889
890 long downTime = event.getDownTime();
891 long eventTime = event.getEventTime();
892 int action = event.getAction();
893 int code = event.getKeyCode();
894 int repeatCount = event.getRepeatCount();
895 int metaState = event.getMetaState();
896 int deviceId = event.getDeviceId();
897 int scancode = event.getScanCode();
898 int source = event.getSource();
899 int flags = event.getFlags();
900 if (source == InputDevice.SOURCE_UNKNOWN) {
901 source = InputDevice.SOURCE_KEYBOARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800902 }
Jeff Brownac143512012-04-05 18:57:33 -0700903 if (eventTime == 0) {
904 eventTime = SystemClock.uptimeMillis();
905 }
906 if (downTime == 0) {
907 downTime = eventTime;
908 }
909 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
910 deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700911 InputManager.getInstance().injectInputEvent(newEvent,
Jeff Brownac143512012-04-05 18:57:33 -0700912 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800913 }
914
915 /**
916 * Sends an up and down key event sync to the currently focused window.
917 *
918 * @param key The integer keycode for the event.
919 */
920 public void sendKeyDownUpSync(int key) {
921 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
922 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
923 }
924
925 /**
926 * Higher-level method for sending both the down and up key events for a
927 * particular character key code. Equivalent to creating both KeyEvent
928 * objects by hand and calling {@link #sendKeySync}. The event appears
929 * as if it came from keyboard 0, the built in one.
930 *
931 * @param keyCode The key code of the character to send.
932 */
933 public void sendCharacterSync(int keyCode) {
934 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
935 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
936 }
937
938 /**
939 * Dispatch a pointer event. Finished at some point after the recipient has
940 * returned from its event processing, though it may <em>not</em> have
941 * completely finished reacting from the event -- for example, if it needs
942 * to update its display as a result, it may still be in the process of
943 * doing that.
944 *
945 * @param event A motion event describing the pointer action. (As noted in
946 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
947 * {@link SystemClock#uptimeMillis()} as the timebase.
948 */
949 public void sendPointerSync(MotionEvent event) {
950 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -0700951 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
952 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800953 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700954 InputManager.getInstance().injectInputEvent(event,
955 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800956 }
957
958 /**
959 * Dispatch a trackball event. Finished at some point after the recipient has
960 * returned from its event processing, though it may <em>not</em> have
961 * completely finished reacting from the event -- for example, if it needs
962 * to update its display as a result, it may still be in the process of
963 * doing that.
964 *
965 * @param event A motion event describing the trackball action. (As noted in
966 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
967 * {@link SystemClock#uptimeMillis()} as the timebase.
968 */
969 public void sendTrackballEventSync(MotionEvent event) {
970 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -0700971 if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
972 event.setSource(InputDevice.SOURCE_TRACKBALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800973 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -0700974 InputManager.getInstance().injectInputEvent(event,
975 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 }
977
978 /**
979 * Perform instantiation of the process's {@link Application} object. The
980 * default implementation provides the normal system behavior.
981 *
982 * @param cl The ClassLoader with which to instantiate the object.
983 * @param className The name of the class implementing the Application
984 * object.
985 * @param context The context to initialize the application with
986 *
987 * @return The newly instantiated Application object.
988 */
989 public Application newApplication(ClassLoader cl, String className, Context context)
990 throws InstantiationException, IllegalAccessException,
991 ClassNotFoundException {
992 return newApplication(cl.loadClass(className), context);
993 }
994
995 /**
996 * Perform instantiation of the process's {@link Application} object. The
997 * default implementation provides the normal system behavior.
998 *
999 * @param clazz The class used to create an Application object from.
1000 * @param context The context to initialize the application with
1001 *
1002 * @return The newly instantiated Application object.
1003 */
1004 static public Application newApplication(Class<?> clazz, Context context)
1005 throws InstantiationException, IllegalAccessException,
1006 ClassNotFoundException {
1007 Application app = (Application)clazz.newInstance();
1008 app.attach(context);
1009 return app;
1010 }
1011
1012 /**
1013 * Perform calling of the application's {@link Application#onCreate}
1014 * method. The default implementation simply calls through to that method.
Dianne Hackborn6ae8d182012-05-23 13:12:42 -07001015 *
1016 * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
1017 * Often instrumentation tests start their test thread in onCreate(); you
1018 * need to be careful of races between these. (Well between it and
1019 * everything else, but let's start here.)
1020 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 * @param app The application being created.
1022 */
1023 public void callApplicationOnCreate(Application app) {
1024 app.onCreate();
1025 }
1026
1027 /**
1028 * Perform instantiation of an {@link Activity} object. This method is intended for use with
1029 * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
Felipe Leme545569d2016-01-11 16:27:58 -08001030 * locally but will be missing some of the linkages necessary for use within the system.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 *
1032 * @param clazz The Class of the desired Activity
1033 * @param context The base context for the activity to use
1034 * @param token The token for this activity to communicate with
1035 * @param application The application object (if any)
1036 * @param intent The intent that started this Activity
1037 * @param info ActivityInfo from the manifest
1038 * @param title The title, typically retrieved from the ActivityInfo record
1039 * @param parent The parent Activity (if any)
1040 * @param id The embedded Id (if any)
1041 * @param lastNonConfigurationInstance Arbitrary object that will be
1042 * available via {@link Activity#getLastNonConfigurationInstance()
1043 * Activity.getLastNonConfigurationInstance()}.
1044 * @return Returns the instantiated activity
1045 * @throws InstantiationException
1046 * @throws IllegalAccessException
1047 */
1048 public Activity newActivity(Class<?> clazz, Context context,
1049 IBinder token, Application application, Intent intent, ActivityInfo info,
1050 CharSequence title, Activity parent, String id,
1051 Object lastNonConfigurationInstance) throws InstantiationException,
1052 IllegalAccessException {
1053 Activity activity = (Activity)clazz.newInstance();
1054 ActivityThread aThread = null;
Craig Mautner233ceee2014-05-09 17:05:11 -07001055 activity.attach(context, aThread, this, token, 0, application, intent,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001056 info, title, parent, id,
1057 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
Filip Gruszczynskia59ac9c2015-09-10 18:28:48 -07001058 new Configuration(), null, null, null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001059 return activity;
1060 }
1061
1062 /**
1063 * Perform instantiation of the process's {@link Activity} object. The
1064 * default implementation provides the normal system behavior.
1065 *
1066 * @param cl The ClassLoader with which to instantiate the object.
1067 * @param className The name of the class implementing the Activity
1068 * object.
1069 * @param intent The Intent object that specified the activity class being
1070 * instantiated.
1071 *
1072 * @return The newly instantiated Activity object.
1073 */
1074 public Activity newActivity(ClassLoader cl, String className,
1075 Intent intent)
1076 throws InstantiationException, IllegalAccessException,
1077 ClassNotFoundException {
1078 return (Activity)cl.loadClass(className).newInstance();
1079 }
1080
Craig Mautnera0026042014-04-23 11:45:37 -07001081 private void prePerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 if (mWaitingActivities != null) {
1083 synchronized (mSync) {
1084 final int N = mWaitingActivities.size();
1085 for (int i=0; i<N; i++) {
1086 final ActivityWaiter aw = mWaitingActivities.get(i);
1087 final Intent intent = aw.intent;
1088 if (intent.filterEquals(activity.getIntent())) {
1089 aw.activity = activity;
1090 mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1091 }
1092 }
1093 }
1094 }
Craig Mautnera0026042014-04-23 11:45:37 -07001095 }
1096
1097 private void postPerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 if (mActivityMonitors != null) {
1099 synchronized (mSync) {
1100 final int N = mActivityMonitors.size();
1101 for (int i=0; i<N; i++) {
1102 final ActivityMonitor am = mActivityMonitors.get(i);
1103 am.match(activity, activity, activity.getIntent());
1104 }
1105 }
1106 }
1107 }
Craig Mautnera0026042014-04-23 11:45:37 -07001108
1109 /**
1110 * Perform calling of an activity's {@link Activity#onCreate}
1111 * method. The default implementation simply calls through to that method.
1112 *
1113 * @param activity The activity being created.
1114 * @param icicle The previously frozen state (or null) to pass through to onCreate().
1115 */
1116 public void callActivityOnCreate(Activity activity, Bundle icicle) {
1117 prePerformCreate(activity);
1118 activity.performCreate(icicle);
1119 postPerformCreate(activity);
1120 }
1121
1122 /**
1123 * Perform calling of an activity's {@link Activity#onCreate}
1124 * method. The default implementation simply calls through to that method.
1125 * @param activity The activity being created.
1126 * @param icicle The previously frozen state (or null) to pass through to
1127 * @param persistentState The previously persisted state (or null)
1128 */
1129 public void callActivityOnCreate(Activity activity, Bundle icicle,
1130 PersistableBundle persistentState) {
1131 prePerformCreate(activity);
1132 activity.performCreate(icicle, persistentState);
1133 postPerformCreate(activity);
1134 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001135
1136 public void callActivityOnDestroy(Activity activity) {
Brett Chabot18f9ce02010-05-12 12:41:50 -07001137 // TODO: the following block causes intermittent hangs when using startActivity
1138 // temporarily comment out until root cause is fixed (bug 2630683)
1139// if (mWaitingActivities != null) {
1140// synchronized (mSync) {
1141// final int N = mWaitingActivities.size();
1142// for (int i=0; i<N; i++) {
1143// final ActivityWaiter aw = mWaitingActivities.get(i);
1144// final Intent intent = aw.intent;
1145// if (intent.filterEquals(activity.getIntent())) {
1146// aw.activity = activity;
1147// mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1148// }
1149// }
1150// }
1151// }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001153 activity.performDestroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001154 }
1155
1156 /**
1157 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1158 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001159 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 * @param activity The activity being restored.
1161 * @param savedInstanceState The previously saved state being restored.
1162 */
1163 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
1164 activity.performRestoreInstanceState(savedInstanceState);
1165 }
1166
1167 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001168 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1169 * method. The default implementation simply calls through to that method.
1170 *
1171 * @param activity The activity being restored.
1172 * @param savedInstanceState The previously saved state being restored.
1173 * @param persistentState The previously persisted state (or null)
1174 */
1175 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState,
1176 PersistableBundle persistentState) {
1177 activity.performRestoreInstanceState(savedInstanceState, persistentState);
1178 }
1179
1180 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1182 * The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001183 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001184 * @param activity The activity being created.
1185 * @param icicle The previously frozen state (or null) to pass through to
1186 * onPostCreate().
1187 */
1188 public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
1189 activity.onPostCreate(icicle);
1190 }
1191
1192 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001193 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1194 * The default implementation simply calls through to that method.
1195 *
1196 * @param activity The activity being created.
1197 * @param icicle The previously frozen state (or null) to pass through to
1198 * onPostCreate().
1199 */
1200 public void callActivityOnPostCreate(Activity activity, Bundle icicle,
1201 PersistableBundle persistentState) {
1202 activity.onPostCreate(icicle, persistentState);
1203 }
1204
1205 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 * Perform calling of an activity's {@link Activity#onNewIntent}
1207 * method. The default implementation simply calls through to that method.
1208 *
1209 * @param activity The activity receiving a new Intent.
1210 * @param intent The new intent being received.
1211 */
1212 public void callActivityOnNewIntent(Activity activity, Intent intent) {
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001213 activity.onNewIntent(intent);
1214 }
1215
1216 /**
1217 * @hide
1218 */
1219 public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001220 final String oldReferrer = activity.mReferrer;
1221 try {
Dianne Hackborn80b1c562014-12-09 20:22:08 -08001222 if (intent != null) {
1223 activity.mReferrer = intent.mReferrer;
1224 }
1225 callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001226 } finally {
1227 activity.mReferrer = oldReferrer;
1228 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 }
1230
1231 /**
1232 * Perform calling of an activity's {@link Activity#onStart}
1233 * method. The default implementation simply calls through to that method.
1234 *
1235 * @param activity The activity being started.
1236 */
1237 public void callActivityOnStart(Activity activity) {
1238 activity.onStart();
1239 }
1240
1241 /**
1242 * Perform calling of an activity's {@link Activity#onRestart}
1243 * method. The default implementation simply calls through to that method.
1244 *
1245 * @param activity The activity being restarted.
1246 */
1247 public void callActivityOnRestart(Activity activity) {
1248 activity.onRestart();
1249 }
1250
1251 /**
1252 * Perform calling of an activity's {@link Activity#onResume} method. The
1253 * default implementation simply calls through to that method.
1254 *
1255 * @param activity The activity being resumed.
1256 */
1257 public void callActivityOnResume(Activity activity) {
Jeff Hamilton52d32032011-01-08 15:31:26 -06001258 activity.mResumed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 activity.onResume();
1260
1261 if (mActivityMonitors != null) {
1262 synchronized (mSync) {
1263 final int N = mActivityMonitors.size();
1264 for (int i=0; i<N; i++) {
1265 final ActivityMonitor am = mActivityMonitors.get(i);
1266 am.match(activity, activity, activity.getIntent());
1267 }
1268 }
1269 }
1270 }
1271
1272 /**
1273 * Perform calling of an activity's {@link Activity#onStop}
1274 * method. The default implementation simply calls through to that method.
1275 *
1276 * @param activity The activity being stopped.
1277 */
1278 public void callActivityOnStop(Activity activity) {
1279 activity.onStop();
1280 }
1281
1282 /**
Newton Allenc5027442013-08-13 11:22:32 -07001283 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1284 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001285 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001286 * @param activity The activity being saved.
1287 * @param outState The bundle to pass to the call.
1288 */
1289 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
1290 activity.performSaveInstanceState(outState);
1291 }
1292
1293 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001294 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1295 * method. The default implementation simply calls through to that method.
1296 * @param activity The activity being saved.
1297 * @param outState The bundle to pass to the call.
1298 * @param outPersistentState The persistent bundle to pass to the call.
1299 */
1300 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
1301 PersistableBundle outPersistentState) {
1302 activity.performSaveInstanceState(outState, outPersistentState);
1303 }
1304
1305 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001306 * Perform calling of an activity's {@link Activity#onPause} method. The
1307 * default implementation simply calls through to that method.
1308 *
1309 * @param activity The activity being paused.
1310 */
1311 public void callActivityOnPause(Activity activity) {
1312 activity.performPause();
1313 }
1314
1315 /**
1316 * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
1317 * The default implementation simply calls through to that method.
1318 *
1319 * @param activity The activity being notified that the user has navigated away
1320 */
1321 public void callActivityOnUserLeaving(Activity activity) {
1322 activity.performUserLeaving();
1323 }
1324
1325 /*
1326 * Starts allocation counting. This triggers a gc and resets the counts.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001327 *
1328 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001330 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 public void startAllocCounting() {
1332 // Before we start trigger a GC and reset the debug counts. Run the
1333 // finalizers and another GC before starting and stopping the alloc
1334 // counts. This will free up any objects that were just sitting around
1335 // waiting for their finalizers to be run.
1336 Runtime.getRuntime().gc();
1337 Runtime.getRuntime().runFinalization();
1338 Runtime.getRuntime().gc();
1339
1340 Debug.resetAllCounts();
1341
1342 // start the counts
1343 Debug.startAllocCounting();
1344 }
1345
1346 /*
1347 * Stops allocation counting.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001348 *
1349 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001351 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001352 public void stopAllocCounting() {
1353 Runtime.getRuntime().gc();
1354 Runtime.getRuntime().runFinalization();
1355 Runtime.getRuntime().gc();
1356 Debug.stopAllocCounting();
1357 }
1358
1359 /**
1360 * If Results already contains Key, it appends Value to the key's ArrayList
1361 * associated with the key. If the key doesn't already exist in results, it
1362 * adds the key/value pair to results.
1363 */
1364 private void addValue(String key, int value, Bundle results) {
1365 if (results.containsKey(key)) {
1366 List<Integer> list = results.getIntegerArrayList(key);
1367 if (list != null) {
1368 list.add(value);
1369 }
1370 } else {
1371 ArrayList<Integer> list = new ArrayList<Integer>();
1372 list.add(value);
1373 results.putIntegerArrayList(key, list);
1374 }
1375 }
1376
1377 /**
1378 * Returns a bundle with the current results from the allocation counting.
1379 */
1380 public Bundle getAllocCounts() {
1381 Bundle results = new Bundle();
1382 results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
1383 results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
1384 results.putLong("global_freed_count", Debug.getGlobalFreedCount());
1385 results.putLong("global_freed_size", Debug.getGlobalFreedSize());
1386 results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
1387 return results;
1388 }
1389
1390 /**
1391 * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
1392 * reported are the number of send and the number of received transactions.
1393 */
1394 public Bundle getBinderCounts() {
1395 Bundle results = new Bundle();
1396 results.putLong("sent_transactions", Debug.getBinderSentTransactions());
1397 results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
1398 return results;
1399 }
1400
1401 /**
1402 * Description of a Activity execution result to return to the original
1403 * activity.
1404 */
1405 public static final class ActivityResult {
1406 /**
1407 * Create a new activity result. See {@link Activity#setResult} for
1408 * more information.
1409 *
1410 * @param resultCode The result code to propagate back to the
1411 * originating activity, often RESULT_CANCELED or RESULT_OK
1412 * @param resultData The data to propagate back to the originating
1413 * activity.
1414 */
1415 public ActivityResult(int resultCode, Intent resultData) {
1416 mResultCode = resultCode;
1417 mResultData = resultData;
1418 }
1419
1420 /**
1421 * Retrieve the result code contained in this result.
1422 */
1423 public int getResultCode() {
1424 return mResultCode;
1425 }
1426
1427 /**
1428 * Retrieve the data contained in this result.
1429 */
1430 public Intent getResultData() {
1431 return mResultData;
1432 }
1433
1434 private final int mResultCode;
1435 private final Intent mResultData;
1436 }
1437
1438 /**
1439 * Execute a startActivity call made by the application. The default
1440 * implementation takes care of updating any active {@link ActivityMonitor}
1441 * objects and dispatches this call to the system activity manager; you can
1442 * override this to watch for the application to start an activity, and
1443 * modify what happens when it does.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001444 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001445 * <p>This method returns an {@link ActivityResult} object, which you can
1446 * use when intercepting application calls to avoid performing the start
1447 * activity action but still return the result the application is
1448 * expecting. To do this, override this method to catch the call to start
1449 * activity so that it returns a new ActivityResult containing the results
1450 * you would like the application to see, and don't call up to the super
1451 * class. Note that an application is only expecting a result if
1452 * <var>requestCode</var> is &gt;= 0.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001453 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001454 * <p>This method throws {@link android.content.ActivityNotFoundException}
1455 * if there was no Activity found to run the given Intent.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001456 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001457 * @param who The Context from which the activity is being started.
1458 * @param contextThread The main thread of the Context from which the activity
1459 * is being started.
1460 * @param token Internal token identifying to the system who is starting
1461 * the activity; may be null.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001462 * @param target Which activity is performing the start (and thus receiving
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001463 * any result); may be null if this call is not being made
1464 * from an activity.
1465 * @param intent The actual Intent to start.
1466 * @param requestCode Identifier for this request's result; less than zero
1467 * if the caller is not expecting a result.
Dianne Hackborna4972e92012-03-14 10:38:05 -07001468 * @param options Addition options.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001469 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001470 * @return To force the return of a particular result, return an
1471 * ActivityResult object containing the desired data; otherwise
1472 * return null. The default implementation always returns null.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001473 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 * @throws android.content.ActivityNotFoundException
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001475 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001476 * @see Activity#startActivity(Intent)
1477 * @see Activity#startActivityForResult(Intent, int)
1478 * @see Activity#startActivityFromChild
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001479 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001480 * {@hide}
1481 */
1482 public ActivityResult execStartActivity(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001483 Context who, IBinder contextThread, IBinder token, Activity target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001484 Intent intent, int requestCode, Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 IApplicationThread whoThread = (IApplicationThread) contextThread;
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001486 Uri referrer = target != null ? target.onProvideReferrer() : null;
1487 if (referrer != null) {
1488 intent.putExtra(Intent.EXTRA_REFERRER, referrer);
1489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 if (mActivityMonitors != null) {
1491 synchronized (mSync) {
1492 final int N = mActivityMonitors.size();
1493 for (int i=0; i<N; i++) {
1494 final ActivityMonitor am = mActivityMonitors.get(i);
1495 if (am.match(who, null, intent)) {
1496 am.mHits++;
1497 if (am.isBlocking()) {
1498 return requestCode >= 0 ? am.getResult() : null;
1499 }
1500 break;
1501 }
1502 }
1503 }
1504 }
1505 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001506 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001507 intent.prepareToLeaveProcess(who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001509 .startActivity(whoThread, who.getBasePackageName(), intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001510 intent.resolveTypeIfNeeded(who.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07001511 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001512 requestCode, 0, null, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 checkStartActivityResult(result, intent);
1514 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001515 throw new RuntimeException("Failure from system", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001516 }
1517 return null;
1518 }
1519
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001520 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001521 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001522 * but accepts an array of activities to be started. Note that active
1523 * {@link ActivityMonitor} objects only match against the first activity in
1524 * the array.
1525 *
1526 * {@hide}
1527 */
1528 public void execStartActivities(Context who, IBinder contextThread,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001529 IBinder token, Activity target, Intent[] intents, Bundle options) {
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001530 execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
1531 UserHandle.myUserId());
1532 }
1533
1534 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001535 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001536 * but accepts an array of activities to be started. Note that active
1537 * {@link ActivityMonitor} objects only match against the first activity in
1538 * the array.
1539 *
1540 * {@hide}
1541 */
1542 public void execStartActivitiesAsUser(Context who, IBinder contextThread,
1543 IBinder token, Activity target, Intent[] intents, Bundle options,
1544 int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001545 IApplicationThread whoThread = (IApplicationThread) contextThread;
1546 if (mActivityMonitors != null) {
1547 synchronized (mSync) {
1548 final int N = mActivityMonitors.size();
1549 for (int i=0; i<N; i++) {
1550 final ActivityMonitor am = mActivityMonitors.get(i);
1551 if (am.match(who, null, intents[0])) {
1552 am.mHits++;
1553 if (am.isBlocking()) {
1554 return;
1555 }
1556 break;
1557 }
1558 }
1559 }
1560 }
1561 try {
1562 String[] resolvedTypes = new String[intents.length];
1563 for (int i=0; i<intents.length; i++) {
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001564 intents[i].migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001565 intents[i].prepareToLeaveProcess(who);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001566 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
1567 }
1568 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001569 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
1570 token, options, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001571 checkStartActivityResult(result, intents[0]);
1572 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001573 throw new RuntimeException("Failure from system", e);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001574 }
1575 }
1576
1577 /**
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001578 * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001579 * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)},
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001580 * but for calls from a {#link Fragment}.
1581 *
1582 * @param who The Context from which the activity is being started.
1583 * @param contextThread The main thread of the Context from which the activity
1584 * is being started.
1585 * @param token Internal token identifying to the system who is starting
1586 * the activity; may be null.
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001587 * @param target Which element is performing the start (and thus receiving
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001588 * any result).
1589 * @param intent The actual Intent to start.
1590 * @param requestCode Identifier for this request's result; less than zero
1591 * if the caller is not expecting a result.
1592 *
1593 * @return To force the return of a particular result, return an
1594 * ActivityResult object containing the desired data; otherwise
1595 * return null. The default implementation always returns null.
1596 *
1597 * @throws android.content.ActivityNotFoundException
1598 *
1599 * @see Activity#startActivity(Intent)
1600 * @see Activity#startActivityForResult(Intent, int)
1601 * @see Activity#startActivityFromChild
1602 *
1603 * {@hide}
1604 */
1605 public ActivityResult execStartActivity(
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001606 Context who, IBinder contextThread, IBinder token, String target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001607 Intent intent, int requestCode, Bundle options) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001608 IApplicationThread whoThread = (IApplicationThread) contextThread;
1609 if (mActivityMonitors != null) {
1610 synchronized (mSync) {
1611 final int N = mActivityMonitors.size();
1612 for (int i=0; i<N; i++) {
1613 final ActivityMonitor am = mActivityMonitors.get(i);
1614 if (am.match(who, null, intent)) {
1615 am.mHits++;
1616 if (am.isBlocking()) {
1617 return requestCode >= 0 ? am.getResult() : null;
1618 }
1619 break;
1620 }
1621 }
1622 }
1623 }
1624 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001625 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001626 intent.prepareToLeaveProcess(who);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001627 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001628 .startActivity(whoThread, who.getBasePackageName(), intent,
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001629 intent.resolveTypeIfNeeded(who.getContentResolver()),
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001630 token, target, requestCode, 0, null, options);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001631 checkStartActivityResult(result, intent);
1632 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001633 throw new RuntimeException("Failure from system", e);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001634 }
1635 return null;
1636 }
1637
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001638 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001639 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
1640 * but for starting as a particular user.
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001641 *
1642 * @param who The Context from which the activity is being started.
1643 * @param contextThread The main thread of the Context from which the activity
1644 * is being started.
1645 * @param token Internal token identifying to the system who is starting
1646 * the activity; may be null.
1647 * @param target Which fragment is performing the start (and thus receiving
1648 * any result).
1649 * @param intent The actual Intent to start.
1650 * @param requestCode Identifier for this request's result; less than zero
1651 * if the caller is not expecting a result.
1652 *
1653 * @return To force the return of a particular result, return an
1654 * ActivityResult object containing the desired data; otherwise
1655 * return null. The default implementation always returns null.
1656 *
1657 * @throws android.content.ActivityNotFoundException
1658 *
1659 * @see Activity#startActivity(Intent)
1660 * @see Activity#startActivityForResult(Intent, int)
1661 * @see Activity#startActivityFromChild
1662 *
1663 * {@hide}
1664 */
1665 public ActivityResult execStartActivity(
1666 Context who, IBinder contextThread, IBinder token, Activity target,
1667 Intent intent, int requestCode, Bundle options, UserHandle user) {
1668 IApplicationThread whoThread = (IApplicationThread) contextThread;
1669 if (mActivityMonitors != null) {
1670 synchronized (mSync) {
1671 final int N = mActivityMonitors.size();
1672 for (int i=0; i<N; i++) {
1673 final ActivityMonitor am = mActivityMonitors.get(i);
1674 if (am.match(who, null, intent)) {
1675 am.mHits++;
1676 if (am.isBlocking()) {
1677 return requestCode >= 0 ? am.getResult() : null;
1678 }
1679 break;
1680 }
1681 }
1682 }
1683 }
1684 try {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001685 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001686 intent.prepareToLeaveProcess(who);
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001687 int result = ActivityManagerNative.getDefault()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001688 .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001689 intent.resolveTypeIfNeeded(who.getContentResolver()),
1690 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001691 requestCode, 0, null, options, user.getIdentifier());
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001692 checkStartActivityResult(result, intent);
1693 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001694 throw new RuntimeException("Failure from system", e);
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001695 }
1696 return null;
1697 }
1698
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001699 /**
1700 * Special version!
1701 * @hide
1702 */
1703 public ActivityResult execStartActivityAsCaller(
1704 Context who, IBinder contextThread, IBinder token, Activity target,
Dianne Hackborna7cfbe02015-07-16 10:52:52 -07001705 Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity,
1706 int userId) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001707 IApplicationThread whoThread = (IApplicationThread) contextThread;
1708 if (mActivityMonitors != null) {
1709 synchronized (mSync) {
1710 final int N = mActivityMonitors.size();
1711 for (int i=0; i<N; i++) {
1712 final ActivityMonitor am = mActivityMonitors.get(i);
1713 if (am.match(who, null, intent)) {
1714 am.mHits++;
1715 if (am.isBlocking()) {
1716 return requestCode >= 0 ? am.getResult() : null;
1717 }
1718 break;
1719 }
1720 }
1721 }
1722 }
1723 try {
1724 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001725 intent.prepareToLeaveProcess(who);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001726 int result = ActivityManagerNative.getDefault()
1727 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
1728 intent.resolveTypeIfNeeded(who.getContentResolver()),
1729 token, target != null ? target.mEmbeddedID : null,
Dianne Hackborna7cfbe02015-07-16 10:52:52 -07001730 requestCode, 0, null, options, ignoreTargetSecurity, userId);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001731 checkStartActivityResult(result, intent);
1732 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001733 throw new RuntimeException("Failure from system", e);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001734 }
1735 return null;
1736 }
1737
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001738 /**
1739 * Special version!
1740 * @hide
1741 */
1742 public void execStartActivityFromAppTask(
1743 Context who, IBinder contextThread, IAppTask appTask,
1744 Intent intent, Bundle options) {
1745 IApplicationThread whoThread = (IApplicationThread) contextThread;
1746 if (mActivityMonitors != null) {
1747 synchronized (mSync) {
1748 final int N = mActivityMonitors.size();
1749 for (int i=0; i<N; i++) {
1750 final ActivityMonitor am = mActivityMonitors.get(i);
1751 if (am.match(who, null, intent)) {
1752 am.mHits++;
1753 if (am.isBlocking()) {
1754 return;
1755 }
1756 break;
1757 }
1758 }
1759 }
1760 }
1761 try {
1762 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001763 intent.prepareToLeaveProcess(who);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001764 int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
1765 intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options);
1766 checkStartActivityResult(result, intent);
1767 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001768 throw new RuntimeException("Failure from system", e);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001769 }
1770 return;
1771 }
1772
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001773 /*package*/ final void init(ActivityThread thread,
1774 Context instrContext, Context appContext, ComponentName component,
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001775 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001776 mThread = thread;
1777 mMessageQueue = mThread.getLooper().myQueue();
1778 mInstrContext = instrContext;
1779 mAppContext = appContext;
1780 mComponent = component;
1781 mWatcher = watcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001782 mUiAutomationConnection = uiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001783 }
1784
Dianne Hackborn91097de2014-04-04 18:02:06 -07001785 /** @hide */
1786 public static void checkStartActivityResult(int res, Object intent) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07001787 if (res >= ActivityManager.START_SUCCESS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001788 return;
1789 }
Amith Yamasani42449782016-04-19 11:45:51 -07001790
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001791 switch (res) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07001792 case ActivityManager.START_INTENT_NOT_RESOLVED:
1793 case ActivityManager.START_CLASS_NOT_FOUND:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001794 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001795 throw new ActivityNotFoundException(
1796 "Unable to find explicit activity class "
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001797 + ((Intent)intent).getComponent().toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001798 + "; have you declared this activity in your AndroidManifest.xml?");
1799 throw new ActivityNotFoundException(
1800 "No Activity found to handle " + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07001801 case ActivityManager.START_PERMISSION_DENIED:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001802 throw new SecurityException("Not allowed to start activity "
1803 + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07001804 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001805 throw new AndroidRuntimeException(
1806 "FORWARD_RESULT_FLAG used while also requesting a result");
Dianne Hackborna4972e92012-03-14 10:38:05 -07001807 case ActivityManager.START_NOT_ACTIVITY:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001808 throw new IllegalArgumentException(
1809 "PendingIntent is not an activity");
Dianne Hackborn91097de2014-04-04 18:02:06 -07001810 case ActivityManager.START_NOT_VOICE_COMPATIBLE:
1811 throw new SecurityException(
1812 "Starting under voice control not allowed for: " + intent);
Amith Yamasani42449782016-04-19 11:45:51 -07001813 case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
1814 throw new IllegalStateException(
1815 "Session calling startVoiceActivity does not match active session");
1816 case ActivityManager.START_VOICE_HIDDEN_SESSION:
1817 throw new IllegalStateException(
1818 "Cannot start voice activity on a hidden session");
1819 case ActivityManager.START_CANCELED:
1820 throw new AndroidRuntimeException("Activity could not be started for "
1821 + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001822 default:
1823 throw new AndroidRuntimeException("Unknown error code "
1824 + res + " when starting " + intent);
1825 }
1826 }
Chong Zhang45c25ce2015-08-10 22:18:26 -07001827
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001828 private final void validateNotAppThread() {
Kristian Monsen0a303282013-01-18 14:50:07 -08001829 if (Looper.myLooper() == Looper.getMainLooper()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001830 throw new RuntimeException(
1831 "This method can not be called from the main application thread");
1832 }
1833 }
1834
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001835 /**
Phil Weaverd8e88832016-03-28 17:26:25 -07001836 * Gets the {@link UiAutomation} instance with no flags set.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001837 * <p>
1838 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
1839 * work across application boundaries while the APIs exposed by the instrumentation
1840 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
1841 * not allow you to inject the event in an app different from the instrumentation
1842 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
1843 * will work regardless of the current application.
1844 * </p>
1845 * <p>
1846 * A typical test case should be using either the {@link UiAutomation} or
1847 * {@link Instrumentation} APIs. Using both APIs at the same time is not
1848 * a mistake by itself but a client has to be aware of the APIs limitations.
1849 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07001850 * <p>
1851 * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different
1852 * flags, the flags on that instance will be changed, and then it will be returned.
1853 * </p>
1854 * @return The UI automation instance.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001855 *
1856 * @see UiAutomation
1857 */
1858 public UiAutomation getUiAutomation() {
Phil Weaverd8e88832016-03-28 17:26:25 -07001859 return getUiAutomation(0);
Phil Weaver1dd87222016-01-26 17:15:15 -08001860 }
1861
1862 /**
1863 * Gets the {@link UiAutomation} instance with flags set.
1864 * <p>
Phil Weaver1dd87222016-01-26 17:15:15 -08001865 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
1866 * work across application boundaries while the APIs exposed by the instrumentation
1867 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
1868 * not allow you to inject the event in an app different from the instrumentation
1869 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
1870 * will work regardless of the current application.
1871 * </p>
1872 * <p>
1873 * A typical test case should be using either the {@link UiAutomation} or
1874 * {@link Instrumentation} APIs. Using both APIs at the same time is not
1875 * a mistake by itself but a client has to be aware of the APIs limitations.
1876 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07001877 * <p>
1878 * If a {@link UiAutomation} exists with different flags, the flags on that instance will be
1879 * changed, and then it will be returned.
1880 * </p>
Phil Weaver1dd87222016-01-26 17:15:15 -08001881 *
1882 * @param flags The flags to be passed to the UiAutomation, for example
1883 * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
1884 *
1885 * @return The UI automation instance.
1886 *
1887 * @see UiAutomation
1888 */
Phil Weaver35841682016-03-09 09:52:51 -08001889 public UiAutomation getUiAutomation(@UiAutomationFlags int flags) {
Phil Weaverd8e88832016-03-28 17:26:25 -07001890 boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed());
1891
Phil Weaver1dd87222016-01-26 17:15:15 -08001892 if (mUiAutomationConnection != null) {
Phil Weaverd8e88832016-03-28 17:26:25 -07001893 if (!mustCreateNewAutomation && (mUiAutomation.getFlags() == flags)) {
1894 return mUiAutomation;
1895 }
1896 if (mustCreateNewAutomation) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001897 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
1898 mUiAutomationConnection);
Phil Weaver1dd87222016-01-26 17:15:15 -08001899 } else {
Phil Weaverd8e88832016-03-28 17:26:25 -07001900 mUiAutomation.disconnect();
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001901 }
Phil Weaverd8e88832016-03-28 17:26:25 -07001902 mUiAutomation.connect(flags);
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001903 return mUiAutomation;
1904 }
1905 return null;
1906 }
1907
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001908 private final class InstrumentationThread extends Thread {
1909 public InstrumentationThread(String name) {
1910 super(name);
1911 }
1912 public void run() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001913 try {
1914 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
1915 } catch (RuntimeException e) {
Phil Weaver1dd87222016-01-26 17:15:15 -08001916 Log.w(TAG, "Exception setting priority of instrumentation thread "
1917 + Process.myTid(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001918 }
1919 if (mAutomaticPerformanceSnapshots) {
1920 startPerformanceSnapshot();
1921 }
1922 onStart();
1923 }
1924 }
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001925
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001926 private static final class EmptyRunnable implements Runnable {
1927 public void run() {
1928 }
1929 }
1930
1931 private static final class SyncRunnable implements Runnable {
1932 private final Runnable mTarget;
1933 private boolean mComplete;
1934
1935 public SyncRunnable(Runnable target) {
1936 mTarget = target;
1937 }
1938
1939 public void run() {
1940 mTarget.run();
1941 synchronized (this) {
1942 mComplete = true;
1943 notifyAll();
1944 }
1945 }
1946
1947 public void waitForComplete() {
1948 synchronized (this) {
1949 while (!mComplete) {
1950 try {
1951 wait();
1952 } catch (InterruptedException e) {
1953 }
1954 }
1955 }
1956 }
1957 }
1958
1959 private static final class ActivityWaiter {
1960 public final Intent intent;
1961 public Activity activity;
1962
1963 public ActivityWaiter(Intent _intent) {
1964 intent = _intent;
1965 }
1966 }
1967
1968 private final class ActivityGoing implements MessageQueue.IdleHandler {
1969 private final ActivityWaiter mWaiter;
1970
1971 public ActivityGoing(ActivityWaiter waiter) {
1972 mWaiter = waiter;
1973 }
1974
1975 public final boolean queueIdle() {
1976 synchronized (mSync) {
1977 mWaitingActivities.remove(mWaiter);
1978 mSync.notifyAll();
1979 }
1980 return false;
1981 }
1982 }
1983
1984 private static final class Idler implements MessageQueue.IdleHandler {
1985 private final Runnable mCallback;
1986 private boolean mIdle;
1987
1988 public Idler(Runnable callback) {
1989 mCallback = callback;
1990 mIdle = false;
1991 }
1992
1993 public final boolean queueIdle() {
1994 if (mCallback != null) {
1995 mCallback.run();
1996 }
1997 synchronized (this) {
1998 mIdle = true;
1999 notifyAll();
2000 }
2001 return false;
2002 }
2003
2004 public void waitForIdle() {
2005 synchronized (this) {
2006 while (!mIdle) {
2007 try {
2008 wait();
2009 } catch (InterruptedException e) {
2010 }
2011 }
2012 }
2013 }
2014 }
2015}