blob: 5d2f620310e003f97a3cc8d53579ad878b593eb1 [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;
Wale Ogunwale2632c972018-01-22 06:54:48 -080020import android.annotation.NonNull;
Wale Ogunwale828ff7e2017-11-14 01:01:29 +000021import android.annotation.Nullable;
Mathew Inwood4fb17d12018-08-14 14:25:44 +010022import android.annotation.UnsupportedAppUsage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.ActivityNotFoundException;
24import android.content.ComponentName;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.pm.ActivityInfo;
29import android.content.res.Configuration;
Jeff Brownac143512012-04-05 18:57:33 -070030import android.hardware.input.InputManager;
Dianne Hackborna3acdb32015-06-08 17:07:40 -070031import android.net.Uri;
Mathew Inwood55418ea2018-12-20 15:30:45 +000032import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.os.Debug;
35import android.os.IBinder;
Kristian Monsen0a303282013-01-18 14:50:07 -080036import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.os.MessageQueue;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080038import android.os.PerformanceCollector;
Craig Mautnera0026042014-04-23 11:45:37 -070039import android.os.PersistableBundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.os.Process;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080041import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.os.ServiceManager;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080043import android.os.SystemClock;
Jason Monk5be50f72017-03-10 10:57:34 -050044import android.os.TestLooperManager;
Dianne Hackbornf1c26e22012-08-23 13:54:58 -070045import android.os.UserHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.util.AndroidRuntimeException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.util.Log;
48import android.view.IWindowManager;
Jeff Brownac143512012-04-05 18:57:33 -070049import android.view.InputDevice;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.view.KeyCharacterMap;
51import android.view.KeyEvent;
52import android.view.MotionEvent;
53import android.view.ViewConfiguration;
54import android.view.Window;
Winson Chung298f95b2017-08-10 15:57:18 -070055
Dianne Hackborn85d558c2014-11-04 10:31:54 -080056import com.android.internal.content.ReferrerIntent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057
58import java.io.File;
Phil Weaver35841682016-03-09 09:52:51 -080059import java.lang.annotation.Retention;
60import java.lang.annotation.RetentionPolicy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import java.util.ArrayList;
62import java.util.List;
63
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064/**
65 * Base class for implementing application instrumentation code. When running
66 * with instrumentation turned on, this class will be instantiated for you
67 * before any of the application code, allowing you to monitor all of the
68 * interaction the system has with the application. An Instrumentation
69 * implementation is described to the system through an AndroidManifest.xml's
70 * <instrumentation> tag.
71 */
72public class Instrumentation {
Svetoslav Ganov80943d82013-01-02 10:25:37 -080073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 /**
75 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
76 * identifies the class that is writing the report. This can be used to provide more structured
77 * logging or reporting capabilities in the IInstrumentationWatcher.
78 */
79 public static final String REPORT_KEY_IDENTIFIER = "id";
80 /**
81 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
82 * identifies a string which can simply be printed to the output stream. Using these streams
83 * provides a "pretty printer" version of the status & final packets. Any bundles including
84 * this key should also include the complete set of raw key/value pairs, so that the
85 * instrumentation can also be launched, and results collected, by an automated system.
86 */
87 public static final String REPORT_KEY_STREAMRESULT = "stream";
Svetoslav Ganov80943d82013-01-02 10:25:37 -080088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 private static final String TAG = "Instrumentation";
Phil Weaver35841682016-03-09 09:52:51 -080090
91 /**
92 * @hide
93 */
94 @Retention(RetentionPolicy.SOURCE)
95 @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES})
96 public @interface UiAutomationFlags {};
97
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 private final Object mSync = new Object();
100 private ActivityThread mThread = null;
101 private MessageQueue mMessageQueue = null;
102 private Context mInstrContext;
103 private Context mAppContext;
104 private ComponentName mComponent;
105 private Thread mRunner;
106 private List<ActivityWaiter> mWaitingActivities;
107 private List<ActivityMonitor> mActivityMonitors;
108 private IInstrumentationWatcher mWatcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800109 private IUiAutomationConnection mUiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 private boolean mAutomaticPerformanceSnapshots = false;
Jack Wangff1df692009-08-26 17:19:13 -0700111 private PerformanceCollector mPerformanceCollector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 private Bundle mPerfMetrics = new Bundle();
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800113 private UiAutomation mUiAutomation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114
115 public Instrumentation() {
116 }
117
118 /**
Jason Monk5be50f72017-03-10 10:57:34 -0500119 * Called for methods that shouldn't be called by standard apps and
120 * should only be used in instrumentation environments. This is not
121 * security feature as these classes will still be accessible through
122 * reflection, but it will serve as noticeable discouragement from
123 * doing such a thing.
124 */
125 private void checkInstrumenting(String method) {
126 // Check if we have an instrumentation context, as init should only get called by
127 // the system in startup processes that are being instrumented.
128 if (mInstrContext == null) {
129 throw new RuntimeException(method +
130 " cannot be called outside of instrumented processes");
131 }
132 }
133
134 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 * Called when the instrumentation is starting, before any application code
136 * has been loaded. Usually this will be implemented to simply call
137 * {@link #start} to begin the instrumentation thread, which will then
138 * continue execution in {@link #onStart}.
139 *
140 * <p>If you do not need your own thread -- that is you are writing your
141 * instrumentation to be completely asynchronous (returning to the event
142 * loop so that the application can run), you can simply begin your
143 * instrumentation here, for example call {@link Context#startActivity} to
144 * begin the appropriate first activity of the application.
145 *
146 * @param arguments Any additional arguments that were supplied when the
147 * instrumentation was started.
148 */
149 public void onCreate(Bundle arguments) {
150 }
151
152 /**
153 * Create and start a new thread in which to run instrumentation. This new
154 * thread will call to {@link #onStart} where you can implement the
155 * instrumentation.
156 */
157 public void start() {
158 if (mRunner != null) {
159 throw new RuntimeException("Instrumentation already started");
160 }
161 mRunner = new InstrumentationThread("Instr: " + getClass().getName());
162 mRunner.start();
163 }
164
165 /**
166 * Method where the instrumentation thread enters execution. This allows
167 * you to run your instrumentation code in a separate thread than the
168 * application, so that it can perform blocking operation such as
169 * {@link #sendKeySync} or {@link #startActivitySync}.
170 *
171 * <p>You will typically want to call finish() when this function is done,
172 * to end your instrumentation.
173 */
174 public void onStart() {
175 }
176
177 /**
178 * This is called whenever the system captures an unhandled exception that
179 * was thrown by the application. The default implementation simply
180 * returns false, allowing normal system handling of the exception to take
181 * place.
182 *
183 * @param obj The client object that generated the exception. May be an
184 * Application, Activity, BroadcastReceiver, Service, or null.
185 * @param e The exception that was thrown.
186 *
187 * @return To allow normal system exception process to occur, return false.
188 * If true is returned, the system will proceed as if the exception
189 * didn't happen.
190 */
191 public boolean onException(Object obj, Throwable e) {
192 return false;
193 }
194
195 /**
196 * Provide a status report about the application.
197 *
198 * @param resultCode Current success/failure of instrumentation.
199 * @param results Any results to send back to the code that started the instrumentation.
200 */
201 public void sendStatus(int resultCode, Bundle results) {
202 if (mWatcher != null) {
203 try {
204 mWatcher.instrumentationStatus(mComponent, resultCode, results);
205 }
206 catch (RemoteException e) {
207 mWatcher = null;
208 }
209 }
210 }
Dianne Hackborn34041732017-01-31 15:27:13 -0800211
212 /**
213 * Report some results in the middle of instrumentation execution. Later results (including
214 * those provided by {@link #finish}) will be combined with {@link Bundle#putAll}.
215 */
216 public void addResults(Bundle results) {
217 IActivityManager am = ActivityManager.getService();
218 try {
219 am.addInstrumentationResults(mThread.getApplicationThread(), results);
220 } catch (RemoteException ex) {
221 throw ex.rethrowFromSystemServer();
222 }
223 }
224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 /**
226 * Terminate instrumentation of the application. This will cause the
227 * application process to exit, removing this instrumentation from the next
Dianne Hackborn34041732017-01-31 15:27:13 -0800228 * time the application is started. If multiple processes are currently running
229 * for this instrumentation, all of those processes will be killed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 *
231 * @param resultCode Overall success/failure of instrumentation.
232 * @param results Any results to send back to the code that started the
233 * instrumentation.
234 */
235 public void finish(int resultCode, Bundle results) {
236 if (mAutomaticPerformanceSnapshots) {
237 endPerformanceSnapshot();
238 }
239 if (mPerfMetrics != null) {
Dianne Hackbornb65ea7b2014-06-20 12:18:55 -0700240 if (results == null) {
241 results = new Bundle();
242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 results.putAll(mPerfMetrics);
244 }
Phil Weaverd8e88832016-03-28 17:26:25 -0700245 if ((mUiAutomation != null) && !mUiAutomation.isDestroyed()) {
Adam Momtaz8f6f1f42013-04-10 12:42:58 -0700246 mUiAutomation.disconnect();
247 mUiAutomation = null;
248 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800249 mThread.finishInstrumentation(resultCode, results);
250 }
251
252 public void setAutomaticPerformanceSnapshots() {
253 mAutomaticPerformanceSnapshots = true;
Jack Wangff1df692009-08-26 17:19:13 -0700254 mPerformanceCollector = new PerformanceCollector();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 }
256
257 public void startPerformanceSnapshot() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700259 mPerformanceCollector.beginSnapshot(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 }
261 }
262
263 public void endPerformanceSnapshot() {
264 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700265 mPerfMetrics = mPerformanceCollector.endSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800266 }
267 }
268
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 /**
270 * Called when the instrumented application is stopping, after all of the
271 * normal application cleanup has occurred.
272 */
273 public void onDestroy() {
274 }
275
276 /**
277 * Return the Context of this instrumentation's package. Note that this is
278 * often different than the Context of the application being
279 * instrumentated, since the instrumentation code often lives is a
280 * different package than that of the application it is running against.
281 * See {@link #getTargetContext} to retrieve a Context for the target
282 * application.
283 *
284 * @return The instrumentation's package context.
285 *
286 * @see #getTargetContext
287 */
288 public Context getContext() {
289 return mInstrContext;
290 }
291
292 /**
293 * Returns complete component name of this instrumentation.
294 *
295 * @return Returns the complete component name for this instrumentation.
296 */
297 public ComponentName getComponentName() {
298 return mComponent;
299 }
300
301 /**
302 * Return a Context for the target application being instrumented. Note
303 * that this is often different than the Context of the instrumentation
304 * code, since the instrumentation code often lives is a different package
305 * than that of the application it is running against. See
306 * {@link #getContext} to retrieve a Context for the instrumentation code.
307 *
308 * @return A Context in the target application.
309 *
310 * @see #getContext
311 */
312 public Context getTargetContext() {
313 return mAppContext;
314 }
315
316 /**
Dianne Hackborn34041732017-01-31 15:27:13 -0800317 * Return the name of the process this instrumentation is running in. Note this should
318 * only be used for testing and debugging. If you are thinking about using this to,
319 * for example, conditionalize what is initialized in an Application class, it is strongly
320 * recommended to instead use lazy initialization (such as a getter for the state that
321 * only creates it when requested). This can greatly reduce the work your process does
322 * when created for secondary things, such as to receive a broadcast.
323 */
324 public String getProcessName() {
325 return mThread.getProcessName();
326 }
327
328 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800329 * Check whether this instrumentation was started with profiling enabled.
330 *
331 * @return Returns true if profiling was enabled when starting, else false.
332 */
333 public boolean isProfiling() {
334 return mThread.isProfiling();
335 }
336
337 /**
338 * This method will start profiling if isProfiling() returns true. You should
339 * only call this method if you set the handleProfiling attribute in the
340 * manifest file for this Instrumentation to true.
341 */
342 public void startProfiling() {
343 if (mThread.isProfiling()) {
344 File file = new File(mThread.getProfileFilePath());
345 file.getParentFile().mkdirs();
346 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
347 }
348 }
349
350 /**
351 * Stops profiling if isProfiling() returns true.
352 */
353 public void stopProfiling() {
354 if (mThread.isProfiling()) {
355 Debug.stopMethodTracing();
356 }
357 }
358
359 /**
360 * Force the global system in or out of touch mode. This can be used if
361 * your instrumentation relies on the UI being in one more or the other
362 * when it starts.
363 *
364 * @param inTouch Set to true to be in touch mode, false to be in
365 * focus mode.
366 */
367 public void setInTouchMode(boolean inTouch) {
368 try {
369 IWindowManager.Stub.asInterface(
370 ServiceManager.getService("window")).setInTouchMode(inTouch);
371 } catch (RemoteException e) {
372 // Shouldn't happen!
373 }
374 }
375
376 /**
377 * Schedule a callback for when the application's main thread goes idle
378 * (has no more events to process).
379 *
380 * @param recipient Called the next time the thread's message queue is
381 * idle.
382 */
383 public void waitForIdle(Runnable recipient) {
384 mMessageQueue.addIdleHandler(new Idler(recipient));
385 mThread.getHandler().post(new EmptyRunnable());
386 }
387
388 /**
389 * Synchronously wait for the application to be idle. Can not be called
390 * from the main application thread -- use {@link #start} to execute
391 * instrumentation in its own thread.
392 */
393 public void waitForIdleSync() {
394 validateNotAppThread();
395 Idler idler = new Idler(null);
396 mMessageQueue.addIdleHandler(idler);
397 mThread.getHandler().post(new EmptyRunnable());
398 idler.waitForIdle();
399 }
400
401 /**
402 * Execute a call on the application's main thread, blocking until it is
403 * complete. Useful for doing things that are not thread-safe, such as
404 * looking at or modifying the view hierarchy.
405 *
406 * @param runner The code to run on the main thread.
407 */
408 public void runOnMainSync(Runnable runner) {
409 validateNotAppThread();
410 SyncRunnable sr = new SyncRunnable(runner);
411 mThread.getHandler().post(sr);
412 sr.waitForComplete();
413 }
414
415 /**
416 * Start a new activity and wait for it to begin running before returning.
417 * In addition to being synchronous, this method as some semantic
418 * differences from the standard {@link Context#startActivity} call: the
419 * activity component is resolved before talking with the activity manager
420 * (its class name is specified in the Intent that this method ultimately
421 * starts), and it does not allow you to start activities that run in a
422 * different process. In addition, if the given Intent resolves to
423 * multiple activities, instead of displaying a dialog for the user to
424 * select an activity, an exception will be thrown.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000425 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800426 * <p>The function returns as soon as the activity goes idle following the
427 * call to its {@link Activity#onCreate}. Generally this means it has gone
428 * through the full initialization including {@link Activity#onResume} and
429 * drawn and displayed its initial window.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000430 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 * @param intent Description of the activity to start.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000432 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 * @see Context#startActivity
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000434 * @see #startActivitySync(Intent, Bundle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800435 */
436 public Activity startActivitySync(Intent intent) {
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000437 return startActivitySync(intent, null /* options */);
438 }
439
440 /**
441 * Start a new activity and wait for it to begin running before returning.
442 * In addition to being synchronous, this method as some semantic
443 * differences from the standard {@link Context#startActivity} call: the
444 * activity component is resolved before talking with the activity manager
445 * (its class name is specified in the Intent that this method ultimately
446 * starts), and it does not allow you to start activities that run in a
447 * different process. In addition, if the given Intent resolves to
448 * multiple activities, instead of displaying a dialog for the user to
449 * select an activity, an exception will be thrown.
450 *
451 * <p>The function returns as soon as the activity goes idle following the
452 * call to its {@link Activity#onCreate}. Generally this means it has gone
453 * through the full initialization including {@link Activity#onResume} and
454 * drawn and displayed its initial window.
455 *
456 * @param intent Description of the activity to start.
457 * @param options Additional options for how the Activity should be started.
458 * May be null if there are no options. See {@link android.app.ActivityOptions}
459 * for how to build the Bundle supplied here; there are no supported definitions
460 * for building it manually.
461 *
462 * @see Context#startActivity(Intent, Bundle)
463 */
Wale Ogunwale2632c972018-01-22 06:54:48 -0800464 @NonNull
465 public Activity startActivitySync(@NonNull Intent intent, @Nullable Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800466 validateNotAppThread();
467
468 synchronized (mSync) {
469 intent = new Intent(intent);
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000470
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800471 ActivityInfo ai = intent.resolveActivityInfo(
472 getTargetContext().getPackageManager(), 0);
473 if (ai == null) {
474 throw new RuntimeException("Unable to resolve activity for: " + intent);
475 }
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700476 String myProc = mThread.getProcessName();
477 if (!ai.processName.equals(myProc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800478 // todo: if this intent is ambiguous, look here to see if
479 // there is a single match that is in our package.
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700480 throw new RuntimeException("Intent in process "
481 + myProc + " resolved to different process "
482 + ai.processName + ": " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 }
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000484
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800485 intent.setComponent(new ComponentName(
486 ai.applicationInfo.packageName, ai.name));
487 final ActivityWaiter aw = new ActivityWaiter(intent);
488
489 if (mWaitingActivities == null) {
490 mWaitingActivities = new ArrayList();
491 }
492 mWaitingActivities.add(aw);
493
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000494 getTargetContext().startActivity(intent, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800495
496 do {
497 try {
498 mSync.wait();
499 } catch (InterruptedException e) {
500 }
501 } while (mWaitingActivities.contains(aw));
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000502
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 return aw.activity;
504 }
505 }
506
507 /**
508 * Information about a particular kind of Intent that is being monitored.
509 * An instance of this class is added to the
510 * current instrumentation through {@link #addMonitor}; after being added,
511 * when a new activity is being started the monitor will be checked and, if
512 * matching, its hit count updated and (optionally) the call stopped and a
513 * canned result returned.
514 *
515 * <p>An ActivityMonitor can also be used to look for the creation of an
516 * activity, through the {@link #waitForActivity} method. This will return
517 * after a matching activity has been created with that activity object.
518 */
519 public static class ActivityMonitor {
520 private final IntentFilter mWhich;
521 private final String mClass;
522 private final ActivityResult mResult;
523 private final boolean mBlock;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800524 private final boolean mIgnoreMatchingSpecificIntents;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800525
526
527 // This is protected by 'Instrumentation.this.mSync'.
528 /*package*/ int mHits = 0;
529
530 // This is protected by 'this'.
531 /*package*/ Activity mLastActivity = null;
532
533 /**
534 * Create a new ActivityMonitor that looks for a particular kind of
535 * intent to be started.
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800536 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 * @param which The set of intents this monitor is responsible for.
538 * @param result A canned result to return if the monitor is hit; can
539 * be null.
540 * @param block Controls whether the monitor should block the activity
541 * start (returning its canned result) or let the call
542 * proceed.
543 *
544 * @see Instrumentation#addMonitor
545 */
546 public ActivityMonitor(
547 IntentFilter which, ActivityResult result, boolean block) {
548 mWhich = which;
549 mClass = null;
550 mResult = result;
551 mBlock = block;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800552 mIgnoreMatchingSpecificIntents = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553 }
554
555 /**
556 * Create a new ActivityMonitor that looks for a specific activity
557 * class to be started.
558 *
559 * @param cls The activity class this monitor is responsible for.
560 * @param result A canned result to return if the monitor is hit; can
561 * be null.
562 * @param block Controls whether the monitor should block the activity
563 * start (returning its canned result) or let the call
564 * proceed.
565 *
566 * @see Instrumentation#addMonitor
567 */
568 public ActivityMonitor(
569 String cls, ActivityResult result, boolean block) {
570 mWhich = null;
571 mClass = cls;
572 mResult = result;
573 mBlock = block;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800574 mIgnoreMatchingSpecificIntents = false;
575 }
576
577 /**
578 * Create a new ActivityMonitor that can be used for intercepting any activity to be
579 * started.
580 *
Sudheer Shanka34217512017-04-26 14:49:16 -0700581 * <p> When an activity is started, {@link #onStartActivity(Intent)} will be called on
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800582 * instances created using this constructor to see if it is a hit.
583 *
Sudheer Shanka34217512017-04-26 14:49:16 -0700584 * @see #onStartActivity(Intent)
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800585 */
586 public ActivityMonitor() {
587 mWhich = null;
588 mClass = null;
589 mResult = null;
590 mBlock = false;
591 mIgnoreMatchingSpecificIntents = true;
592 }
593
594 /**
595 * @return true if this monitor is used for intercepting any started activity by calling
Sudheer Shanka34217512017-04-26 14:49:16 -0700596 * into {@link #onStartActivity(Intent)}, false if this monitor is only used
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800597 * for specific intents corresponding to the intent filter or activity class
598 * passed in the constructor.
599 */
600 final boolean ignoreMatchingSpecificIntents() {
601 return mIgnoreMatchingSpecificIntents;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800602 }
603
604 /**
605 * Retrieve the filter associated with this ActivityMonitor.
606 */
607 public final IntentFilter getFilter() {
608 return mWhich;
609 }
610
611 /**
612 * Retrieve the result associated with this ActivityMonitor, or null if
613 * none.
614 */
615 public final ActivityResult getResult() {
616 return mResult;
617 }
618
619 /**
620 * Check whether this monitor blocks activity starts (not allowing the
621 * actual activity to run) or allows them to execute normally.
622 */
623 public final boolean isBlocking() {
624 return mBlock;
625 }
626
627 /**
628 * Retrieve the number of times the monitor has been hit so far.
629 */
630 public final int getHits() {
631 return mHits;
632 }
633
634 /**
635 * Retrieve the most recent activity class that was seen by this
636 * monitor.
637 */
638 public final Activity getLastActivity() {
639 return mLastActivity;
640 }
641
642 /**
643 * Block until an Activity is created that matches this monitor,
644 * returning the resulting activity.
645 *
646 * @return Activity
647 */
648 public final Activity waitForActivity() {
649 synchronized (this) {
650 while (mLastActivity == null) {
651 try {
652 wait();
653 } catch (InterruptedException e) {
654 }
655 }
656 Activity res = mLastActivity;
657 mLastActivity = null;
658 return res;
659 }
660 }
661
662 /**
663 * Block until an Activity is created that matches this monitor,
664 * returning the resulting activity or till the timeOut period expires.
665 * If the timeOut expires before the activity is started, return null.
666 *
Ben Gruver87904e82016-01-22 13:11:11 -0800667 * @param timeOut Time to wait in milliseconds before the activity is created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 *
669 * @return Activity
670 */
671 public final Activity waitForActivityWithTimeout(long timeOut) {
672 synchronized (this) {
Costin Manolacheb0935342011-07-15 11:20:42 -0700673 if (mLastActivity == null) {
674 try {
675 wait(timeOut);
676 } catch (InterruptedException e) {
677 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678 }
679 if (mLastActivity == null) {
680 return null;
681 } else {
682 Activity res = mLastActivity;
683 mLastActivity = null;
684 return res;
685 }
686 }
687 }
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800688
689 /**
690 * Used for intercepting any started activity.
691 *
692 * <p> A non-null return value here will be considered a hit for this monitor.
693 * By default this will return {@code null} and subclasses can override this to return
694 * a non-null value if the intent needs to be intercepted.
695 *
696 * <p> Whenever a new activity is started, this method will be called on instances created
697 * using {@link #Instrumentation.ActivityMonitor()} to check if there is a match. In case
698 * of a match, the activity start will be blocked and the returned result will be used.
699 *
700 * @param intent The intent used for starting the activity.
701 * @return The {@link ActivityResult} that needs to be used in case of a match.
702 */
Sudheer Shanka34217512017-04-26 14:49:16 -0700703 public ActivityResult onStartActivity(Intent intent) {
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800704 return null;
705 }
706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800707 final boolean match(Context who,
708 Activity activity,
709 Intent intent) {
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800710 if (mIgnoreMatchingSpecificIntents) {
711 return false;
712 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 synchronized (this) {
714 if (mWhich != null
715 && mWhich.match(who.getContentResolver(), intent,
716 true, "Instrumentation") < 0) {
717 return false;
718 }
719 if (mClass != null) {
720 String cls = null;
721 if (activity != null) {
722 cls = activity.getClass().getName();
723 } else if (intent.getComponent() != null) {
724 cls = intent.getComponent().getClassName();
725 }
726 if (cls == null || !mClass.equals(cls)) {
727 return false;
728 }
729 }
730 if (activity != null) {
731 mLastActivity = activity;
732 notifyAll();
733 }
734 return true;
735 }
736 }
737 }
738
739 /**
740 * Add a new {@link ActivityMonitor} that will be checked whenever an
741 * activity is started. The monitor is added
742 * after any existing ones; the monitor will be hit only if none of the
743 * existing monitors can themselves handle the Intent.
744 *
745 * @param monitor The new ActivityMonitor to see.
746 *
747 * @see #addMonitor(IntentFilter, ActivityResult, boolean)
748 * @see #checkMonitorHit
749 */
750 public void addMonitor(ActivityMonitor monitor) {
751 synchronized (mSync) {
752 if (mActivityMonitors == null) {
753 mActivityMonitors = new ArrayList();
754 }
755 mActivityMonitors.add(monitor);
756 }
757 }
758
759 /**
760 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
761 * creates an intent filter matching {@link ActivityMonitor} for you and
762 * returns it.
763 *
764 * @param filter The set of intents this monitor is responsible for.
765 * @param result A canned result to return if the monitor is hit; can
766 * be null.
767 * @param block Controls whether the monitor should block the activity
768 * start (returning its canned result) or let the call
769 * proceed.
770 *
771 * @return The newly created and added activity monitor.
772 *
773 * @see #addMonitor(ActivityMonitor)
774 * @see #checkMonitorHit
775 */
776 public ActivityMonitor addMonitor(
777 IntentFilter filter, ActivityResult result, boolean block) {
778 ActivityMonitor am = new ActivityMonitor(filter, result, block);
779 addMonitor(am);
780 return am;
781 }
782
783 /**
784 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
785 * creates a class matching {@link ActivityMonitor} for you and returns it.
786 *
787 * @param cls The activity class this monitor is responsible for.
788 * @param result A canned result to return if the monitor is hit; can
789 * be null.
790 * @param block Controls whether the monitor should block the activity
791 * start (returning its canned result) or let the call
792 * proceed.
793 *
794 * @return The newly created and added activity monitor.
795 *
796 * @see #addMonitor(ActivityMonitor)
797 * @see #checkMonitorHit
798 */
799 public ActivityMonitor addMonitor(
800 String cls, ActivityResult result, boolean block) {
801 ActivityMonitor am = new ActivityMonitor(cls, result, block);
802 addMonitor(am);
803 return am;
804 }
805
806 /**
807 * Test whether an existing {@link ActivityMonitor} has been hit. If the
808 * monitor has been hit at least <var>minHits</var> times, then it will be
809 * removed from the activity monitor list and true returned. Otherwise it
810 * is left as-is and false is returned.
811 *
812 * @param monitor The ActivityMonitor to check.
813 * @param minHits The minimum number of hits required.
814 *
815 * @return True if the hit count has been reached, else false.
816 *
817 * @see #addMonitor
818 */
819 public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
820 waitForIdleSync();
821 synchronized (mSync) {
822 if (monitor.getHits() < minHits) {
823 return false;
824 }
825 mActivityMonitors.remove(monitor);
826 }
827 return true;
828 }
829
830 /**
831 * Wait for an existing {@link ActivityMonitor} to be hit. Once the
832 * monitor has been hit, it is removed from the activity monitor list and
833 * the first created Activity object that matched it is returned.
834 *
835 * @param monitor The ActivityMonitor to wait for.
836 *
837 * @return The Activity object that matched the monitor.
838 */
839 public Activity waitForMonitor(ActivityMonitor monitor) {
840 Activity activity = monitor.waitForActivity();
841 synchronized (mSync) {
842 mActivityMonitors.remove(monitor);
843 }
844 return activity;
845 }
846
847 /**
848 * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
849 * expires. Once the monitor has been hit, it is removed from the activity
850 * monitor list and the first created Activity object that matched it is
851 * returned. If the timeout expires, a null object is returned.
852 *
853 * @param monitor The ActivityMonitor to wait for.
Nimrod Gileadic895a4b2017-03-31 13:21:47 +0100854 * @param timeOut The timeout value in milliseconds.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800855 *
856 * @return The Activity object that matched the monitor.
857 */
858 public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
859 Activity activity = monitor.waitForActivityWithTimeout(timeOut);
860 synchronized (mSync) {
861 mActivityMonitors.remove(monitor);
862 }
863 return activity;
864 }
865
866 /**
867 * Remove an {@link ActivityMonitor} that was previously added with
868 * {@link #addMonitor}.
869 *
870 * @param monitor The monitor to remove.
871 *
872 * @see #addMonitor
873 */
874 public void removeMonitor(ActivityMonitor monitor) {
875 synchronized (mSync) {
876 mActivityMonitors.remove(monitor);
877 }
878 }
879
880 /**
881 * Execute a particular menu item.
882 *
883 * @param targetActivity The activity in question.
884 * @param id The identifier associated with the menu item.
885 * @param flag Additional flags, if any.
886 * @return Whether the invocation was successful (for example, it could be
887 * false if item is disabled).
888 */
889 public boolean invokeMenuActionSync(Activity targetActivity,
890 int id, int flag) {
891 class MenuRunnable implements Runnable {
892 private final Activity activity;
893 private final int identifier;
894 private final int flags;
895 boolean returnValue;
896
897 public MenuRunnable(Activity _activity, int _identifier,
898 int _flags) {
899 activity = _activity;
900 identifier = _identifier;
901 flags = _flags;
902 }
903
904 public void run() {
905 Window win = activity.getWindow();
906
907 returnValue = win.performPanelIdentifierAction(
908 Window.FEATURE_OPTIONS_PANEL,
909 identifier,
910 flags);
911 }
912
913 }
914 MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
915 runOnMainSync(mr);
916 return mr.returnValue;
917 }
918
919 /**
920 * Show the context menu for the currently focused view and executes a
921 * particular context menu item.
922 *
923 * @param targetActivity The activity in question.
924 * @param id The identifier associated with the context menu item.
925 * @param flag Additional flags, if any.
926 * @return Whether the invocation was successful (for example, it could be
927 * false if item is disabled).
928 */
929 public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
930 validateNotAppThread();
931
932 // Bring up context menu for current focus.
933 // It'd be nice to do this through code, but currently ListView depends on
934 // long press to set metadata for its selected child
935
936 final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
937 sendKeySync(downEvent);
938
939 // Need to wait for long press
940 waitForIdleSync();
941 try {
942 Thread.sleep(ViewConfiguration.getLongPressTimeout());
943 } catch (InterruptedException e) {
944 Log.e(TAG, "Could not sleep for long press timeout", e);
945 return false;
946 }
947
948 final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
949 sendKeySync(upEvent);
950
951 // Wait for context menu to appear
952 waitForIdleSync();
953
954 class ContextMenuRunnable implements Runnable {
955 private final Activity activity;
956 private final int identifier;
957 private final int flags;
958 boolean returnValue;
959
960 public ContextMenuRunnable(Activity _activity, int _identifier,
961 int _flags) {
962 activity = _activity;
963 identifier = _identifier;
964 flags = _flags;
965 }
966
967 public void run() {
968 Window win = activity.getWindow();
969 returnValue = win.performContextMenuIdentifierAction(
970 identifier,
971 flags);
972 }
973
974 }
975
976 ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
977 runOnMainSync(cmr);
978 return cmr.returnValue;
979 }
980
981 /**
982 * Sends the key events corresponding to the text to the app being
983 * instrumented.
984 *
985 * @param text The text to be sent.
986 */
987 public void sendStringSync(String text) {
988 if (text == null) {
989 return;
990 }
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800991 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800994
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800995 if (events != null) {
996 for (int i = 0; i < events.length; i++) {
Svetoslav Ganovf434e372011-11-11 16:50:21 -0800997 // We have to change the time of an event before injecting it because
998 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
999 // time stamp and the system rejects too old events. Hence, it is
1000 // possible for an event to become stale before it is injected if it
1001 // takes too long to inject the preceding ones.
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001002 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001004 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001005 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001006
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 /**
1008 * Send a key event to the currently focused window/view and wait for it to
1009 * be processed. Finished at some point after the recipient has returned
1010 * from its event processing, though it may <em>not</em> have completely
1011 * finished reacting from the event -- for example, if it needs to update
1012 * its display as a result, it may still be in the process of doing that.
1013 *
1014 * @param event The event to send to the current focus.
1015 */
1016 public void sendKeySync(KeyEvent event) {
1017 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001018
1019 long downTime = event.getDownTime();
1020 long eventTime = event.getEventTime();
1021 int action = event.getAction();
1022 int code = event.getKeyCode();
1023 int repeatCount = event.getRepeatCount();
1024 int metaState = event.getMetaState();
1025 int deviceId = event.getDeviceId();
1026 int scancode = event.getScanCode();
1027 int source = event.getSource();
1028 int flags = event.getFlags();
1029 if (source == InputDevice.SOURCE_UNKNOWN) {
1030 source = InputDevice.SOURCE_KEYBOARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 }
Jeff Brownac143512012-04-05 18:57:33 -07001032 if (eventTime == 0) {
1033 eventTime = SystemClock.uptimeMillis();
1034 }
1035 if (downTime == 0) {
1036 downTime = eventTime;
1037 }
1038 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
1039 deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001040 InputManager.getInstance().injectInputEvent(newEvent,
Jeff Brownac143512012-04-05 18:57:33 -07001041 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 }
1043
1044 /**
1045 * Sends an up and down key event sync to the currently focused window.
1046 *
1047 * @param key The integer keycode for the event.
1048 */
1049 public void sendKeyDownUpSync(int key) {
1050 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
1051 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
1052 }
1053
1054 /**
1055 * Higher-level method for sending both the down and up key events for a
1056 * particular character key code. Equivalent to creating both KeyEvent
1057 * objects by hand and calling {@link #sendKeySync}. The event appears
1058 * as if it came from keyboard 0, the built in one.
1059 *
1060 * @param keyCode The key code of the character to send.
1061 */
1062 public void sendCharacterSync(int keyCode) {
1063 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
1064 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
1065 }
1066
1067 /**
1068 * Dispatch a pointer event. Finished at some point after the recipient has
1069 * returned from its event processing, though it may <em>not</em> have
1070 * completely finished reacting from the event -- for example, if it needs
1071 * to update its display as a result, it may still be in the process of
1072 * doing that.
1073 *
1074 * @param event A motion event describing the pointer action. (As noted in
1075 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
1076 * {@link SystemClock#uptimeMillis()} as the timebase.
1077 */
1078 public void sendPointerSync(MotionEvent event) {
1079 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001080 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
1081 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001082 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001083 InputManager.getInstance().injectInputEvent(event,
1084 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001085 }
1086
1087 /**
1088 * Dispatch a trackball event. Finished at some point after the recipient has
1089 * returned from its event processing, though it may <em>not</em> have
1090 * completely finished reacting from the event -- for example, if it needs
1091 * to update its display as a result, it may still be in the process of
1092 * doing that.
1093 *
1094 * @param event A motion event describing the trackball action. (As noted in
1095 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
1096 * {@link SystemClock#uptimeMillis()} as the timebase.
1097 */
1098 public void sendTrackballEventSync(MotionEvent event) {
1099 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001100 if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
1101 event.setSource(InputDevice.SOURCE_TRACKBALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001103 InputManager.getInstance().injectInputEvent(event,
1104 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 }
1106
1107 /**
1108 * Perform instantiation of the process's {@link Application} object. The
1109 * default implementation provides the normal system behavior.
1110 *
1111 * @param cl The ClassLoader with which to instantiate the object.
1112 * @param className The name of the class implementing the Application
1113 * object.
1114 * @param context The context to initialize the application with
1115 *
1116 * @return The newly instantiated Application object.
1117 */
1118 public Application newApplication(ClassLoader cl, String className, Context context)
1119 throws InstantiationException, IllegalAccessException,
1120 ClassNotFoundException {
Jason Monka80bfb52017-11-16 17:15:37 -05001121 Application app = getFactory(context.getPackageName())
1122 .instantiateApplication(cl, className);
1123 app.attach(context);
1124 return app;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001125 }
1126
1127 /**
1128 * Perform instantiation of the process's {@link Application} object. The
1129 * default implementation provides the normal system behavior.
1130 *
1131 * @param clazz The class used to create an Application object from.
1132 * @param context The context to initialize the application with
1133 *
1134 * @return The newly instantiated Application object.
1135 */
1136 static public Application newApplication(Class<?> clazz, Context context)
1137 throws InstantiationException, IllegalAccessException,
1138 ClassNotFoundException {
1139 Application app = (Application)clazz.newInstance();
1140 app.attach(context);
1141 return app;
1142 }
1143
1144 /**
1145 * Perform calling of the application's {@link Application#onCreate}
1146 * method. The default implementation simply calls through to that method.
Dianne Hackborn6ae8d182012-05-23 13:12:42 -07001147 *
1148 * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
1149 * Often instrumentation tests start their test thread in onCreate(); you
1150 * need to be careful of races between these. (Well between it and
1151 * everything else, but let's start here.)
1152 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 * @param app The application being created.
1154 */
1155 public void callApplicationOnCreate(Application app) {
1156 app.onCreate();
1157 }
1158
1159 /**
1160 * Perform instantiation of an {@link Activity} object. This method is intended for use with
1161 * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
Felipe Leme545569d2016-01-11 16:27:58 -08001162 * 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 -08001163 *
1164 * @param clazz The Class of the desired Activity
1165 * @param context The base context for the activity to use
1166 * @param token The token for this activity to communicate with
1167 * @param application The application object (if any)
1168 * @param intent The intent that started this Activity
1169 * @param info ActivityInfo from the manifest
1170 * @param title The title, typically retrieved from the ActivityInfo record
1171 * @param parent The parent Activity (if any)
1172 * @param id The embedded Id (if any)
1173 * @param lastNonConfigurationInstance Arbitrary object that will be
1174 * available via {@link Activity#getLastNonConfigurationInstance()
1175 * Activity.getLastNonConfigurationInstance()}.
1176 * @return Returns the instantiated activity
1177 * @throws InstantiationException
1178 * @throws IllegalAccessException
1179 */
1180 public Activity newActivity(Class<?> clazz, Context context,
1181 IBinder token, Application application, Intent intent, ActivityInfo info,
1182 CharSequence title, Activity parent, String id,
1183 Object lastNonConfigurationInstance) throws InstantiationException,
1184 IllegalAccessException {
1185 Activity activity = (Activity)clazz.newInstance();
1186 ActivityThread aThread = null;
Sudheer Shanka37820712018-04-11 15:47:35 -07001187 // Activity.attach expects a non-null Application Object.
1188 if (application == null) {
1189 application = new Application();
1190 }
Andrii Kulian51c1b672017-04-07 18:39:32 -07001191 activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001192 info, title, parent, id,
1193 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
Andrii Kulian51c1b672017-04-07 18:39:32 -07001194 new Configuration(), null /* referrer */, null /* voiceInteractor */,
1195 null /* window */, null /* activityConfigCallback */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001196 return activity;
1197 }
1198
1199 /**
1200 * Perform instantiation of the process's {@link Activity} object. The
1201 * default implementation provides the normal system behavior.
1202 *
1203 * @param cl The ClassLoader with which to instantiate the object.
1204 * @param className The name of the class implementing the Activity
1205 * object.
1206 * @param intent The Intent object that specified the activity class being
1207 * instantiated.
1208 *
1209 * @return The newly instantiated Activity object.
1210 */
1211 public Activity newActivity(ClassLoader cl, String className,
1212 Intent intent)
1213 throws InstantiationException, IllegalAccessException,
1214 ClassNotFoundException {
Jason Monke96443e2018-04-18 15:43:50 -04001215 String pkg = intent != null && intent.getComponent() != null
1216 ? intent.getComponent().getPackageName() : null;
Jason Monka80bfb52017-11-16 17:15:37 -05001217 return getFactory(pkg).instantiateActivity(cl, className, intent);
1218 }
1219
1220 private AppComponentFactory getFactory(String pkg) {
Jason Monke96443e2018-04-18 15:43:50 -04001221 if (pkg == null) {
1222 Log.e(TAG, "No pkg specified, disabling AppComponentFactory");
1223 return AppComponentFactory.DEFAULT;
1224 }
Jason Monk24d12a32017-12-21 10:39:17 -05001225 if (mThread == null) {
1226 Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
1227 + " disabling AppComponentFactory", new Throwable());
1228 return AppComponentFactory.DEFAULT;
1229 }
Todd Kennedy233a0b12018-01-29 20:30:24 +00001230 LoadedApk apk = mThread.peekPackageInfo(pkg, true);
Jason Monka80bfb52017-11-16 17:15:37 -05001231 // This is in the case of starting up "android".
Todd Kennedy233a0b12018-01-29 20:30:24 +00001232 if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
1233 return apk.getAppFactory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001234 }
1235
Craig Mautnera0026042014-04-23 11:45:37 -07001236 private void prePerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 if (mWaitingActivities != null) {
1238 synchronized (mSync) {
1239 final int N = mWaitingActivities.size();
1240 for (int i=0; i<N; i++) {
1241 final ActivityWaiter aw = mWaitingActivities.get(i);
1242 final Intent intent = aw.intent;
1243 if (intent.filterEquals(activity.getIntent())) {
1244 aw.activity = activity;
1245 mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1246 }
1247 }
1248 }
1249 }
Craig Mautnera0026042014-04-23 11:45:37 -07001250 }
1251
1252 private void postPerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 if (mActivityMonitors != null) {
1254 synchronized (mSync) {
1255 final int N = mActivityMonitors.size();
1256 for (int i=0; i<N; i++) {
1257 final ActivityMonitor am = mActivityMonitors.get(i);
1258 am.match(activity, activity, activity.getIntent());
1259 }
1260 }
1261 }
1262 }
Craig Mautnera0026042014-04-23 11:45:37 -07001263
1264 /**
1265 * Perform calling of an activity's {@link Activity#onCreate}
1266 * method. The default implementation simply calls through to that method.
1267 *
1268 * @param activity The activity being created.
1269 * @param icicle The previously frozen state (or null) to pass through to onCreate().
1270 */
1271 public void callActivityOnCreate(Activity activity, Bundle icicle) {
1272 prePerformCreate(activity);
1273 activity.performCreate(icicle);
1274 postPerformCreate(activity);
1275 }
1276
1277 /**
1278 * Perform calling of an activity's {@link Activity#onCreate}
1279 * method. The default implementation simply calls through to that method.
1280 * @param activity The activity being created.
1281 * @param icicle The previously frozen state (or null) to pass through to
1282 * @param persistentState The previously persisted state (or null)
1283 */
1284 public void callActivityOnCreate(Activity activity, Bundle icicle,
1285 PersistableBundle persistentState) {
1286 prePerformCreate(activity);
1287 activity.performCreate(icicle, persistentState);
1288 postPerformCreate(activity);
1289 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001290
1291 public void callActivityOnDestroy(Activity activity) {
Brett Chabot18f9ce02010-05-12 12:41:50 -07001292 // TODO: the following block causes intermittent hangs when using startActivity
1293 // temporarily comment out until root cause is fixed (bug 2630683)
1294// if (mWaitingActivities != null) {
1295// synchronized (mSync) {
1296// final int N = mWaitingActivities.size();
1297// for (int i=0; i<N; i++) {
1298// final ActivityWaiter aw = mWaitingActivities.get(i);
1299// final Intent intent = aw.intent;
1300// if (intent.filterEquals(activity.getIntent())) {
1301// aw.activity = activity;
1302// mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1303// }
1304// }
1305// }
1306// }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001307
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001308 activity.performDestroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001309 }
1310
1311 /**
1312 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1313 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001314 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001315 * @param activity The activity being restored.
1316 * @param savedInstanceState The previously saved state being restored.
1317 */
1318 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
1319 activity.performRestoreInstanceState(savedInstanceState);
1320 }
1321
1322 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001323 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1324 * method. The default implementation simply calls through to that method.
1325 *
1326 * @param activity The activity being restored.
1327 * @param savedInstanceState The previously saved state being restored.
1328 * @param persistentState The previously persisted state (or null)
1329 */
1330 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState,
1331 PersistableBundle persistentState) {
1332 activity.performRestoreInstanceState(savedInstanceState, persistentState);
1333 }
1334
1335 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001336 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1337 * The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001338 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001339 * @param activity The activity being created.
1340 * @param icicle The previously frozen state (or null) to pass through to
1341 * onPostCreate().
1342 */
1343 public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
1344 activity.onPostCreate(icicle);
1345 }
1346
1347 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001348 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1349 * The default implementation simply calls through to that method.
1350 *
1351 * @param activity The activity being created.
1352 * @param icicle The previously frozen state (or null) to pass through to
1353 * onPostCreate().
1354 */
1355 public void callActivityOnPostCreate(Activity activity, Bundle icicle,
1356 PersistableBundle persistentState) {
1357 activity.onPostCreate(icicle, persistentState);
1358 }
1359
1360 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001361 * Perform calling of an activity's {@link Activity#onNewIntent}
1362 * method. The default implementation simply calls through to that method.
1363 *
1364 * @param activity The activity receiving a new Intent.
1365 * @param intent The new intent being received.
1366 */
1367 public void callActivityOnNewIntent(Activity activity, Intent intent) {
Winson Chung298f95b2017-08-10 15:57:18 -07001368 activity.performNewIntent(intent);
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001369 }
1370
1371 /**
1372 * @hide
1373 */
Mathew Inwood4fb17d12018-08-14 14:25:44 +01001374 @UnsupportedAppUsage
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001375 public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001376 final String oldReferrer = activity.mReferrer;
1377 try {
Dianne Hackborn80b1c562014-12-09 20:22:08 -08001378 if (intent != null) {
1379 activity.mReferrer = intent.mReferrer;
1380 }
1381 callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001382 } finally {
1383 activity.mReferrer = oldReferrer;
1384 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001385 }
1386
1387 /**
1388 * Perform calling of an activity's {@link Activity#onStart}
1389 * method. The default implementation simply calls through to that method.
1390 *
1391 * @param activity The activity being started.
1392 */
1393 public void callActivityOnStart(Activity activity) {
1394 activity.onStart();
1395 }
1396
1397 /**
1398 * Perform calling of an activity's {@link Activity#onRestart}
1399 * method. The default implementation simply calls through to that method.
1400 *
1401 * @param activity The activity being restarted.
1402 */
1403 public void callActivityOnRestart(Activity activity) {
1404 activity.onRestart();
1405 }
1406
1407 /**
1408 * Perform calling of an activity's {@link Activity#onResume} method. The
1409 * default implementation simply calls through to that method.
1410 *
1411 * @param activity The activity being resumed.
1412 */
1413 public void callActivityOnResume(Activity activity) {
Jeff Hamilton52d32032011-01-08 15:31:26 -06001414 activity.mResumed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001415 activity.onResume();
1416
1417 if (mActivityMonitors != null) {
1418 synchronized (mSync) {
1419 final int N = mActivityMonitors.size();
1420 for (int i=0; i<N; i++) {
1421 final ActivityMonitor am = mActivityMonitors.get(i);
1422 am.match(activity, activity, activity.getIntent());
1423 }
1424 }
1425 }
1426 }
1427
1428 /**
1429 * Perform calling of an activity's {@link Activity#onStop}
1430 * method. The default implementation simply calls through to that method.
1431 *
1432 * @param activity The activity being stopped.
1433 */
1434 public void callActivityOnStop(Activity activity) {
1435 activity.onStop();
1436 }
1437
1438 /**
Newton Allenc5027442013-08-13 11:22:32 -07001439 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1440 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001441 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 * @param activity The activity being saved.
1443 * @param outState The bundle to pass to the call.
1444 */
1445 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
1446 activity.performSaveInstanceState(outState);
1447 }
1448
1449 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001450 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1451 * method. The default implementation simply calls through to that method.
1452 * @param activity The activity being saved.
1453 * @param outState The bundle to pass to the call.
1454 * @param outPersistentState The persistent bundle to pass to the call.
1455 */
1456 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
1457 PersistableBundle outPersistentState) {
1458 activity.performSaveInstanceState(outState, outPersistentState);
1459 }
1460
1461 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001462 * Perform calling of an activity's {@link Activity#onPause} method. The
1463 * default implementation simply calls through to that method.
1464 *
1465 * @param activity The activity being paused.
1466 */
1467 public void callActivityOnPause(Activity activity) {
1468 activity.performPause();
1469 }
1470
1471 /**
1472 * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
1473 * The default implementation simply calls through to that method.
1474 *
1475 * @param activity The activity being notified that the user has navigated away
1476 */
1477 public void callActivityOnUserLeaving(Activity activity) {
1478 activity.performUserLeaving();
1479 }
1480
1481 /*
1482 * Starts allocation counting. This triggers a gc and resets the counts.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001483 *
1484 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001485 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001486 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001487 public void startAllocCounting() {
1488 // Before we start trigger a GC and reset the debug counts. Run the
1489 // finalizers and another GC before starting and stopping the alloc
1490 // counts. This will free up any objects that were just sitting around
1491 // waiting for their finalizers to be run.
1492 Runtime.getRuntime().gc();
1493 Runtime.getRuntime().runFinalization();
1494 Runtime.getRuntime().gc();
1495
1496 Debug.resetAllCounts();
1497
1498 // start the counts
1499 Debug.startAllocCounting();
1500 }
1501
1502 /*
1503 * Stops allocation counting.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001504 *
1505 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001507 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001508 public void stopAllocCounting() {
1509 Runtime.getRuntime().gc();
1510 Runtime.getRuntime().runFinalization();
1511 Runtime.getRuntime().gc();
1512 Debug.stopAllocCounting();
1513 }
1514
1515 /**
1516 * If Results already contains Key, it appends Value to the key's ArrayList
1517 * associated with the key. If the key doesn't already exist in results, it
1518 * adds the key/value pair to results.
1519 */
1520 private void addValue(String key, int value, Bundle results) {
1521 if (results.containsKey(key)) {
1522 List<Integer> list = results.getIntegerArrayList(key);
1523 if (list != null) {
1524 list.add(value);
1525 }
1526 } else {
1527 ArrayList<Integer> list = new ArrayList<Integer>();
1528 list.add(value);
1529 results.putIntegerArrayList(key, list);
1530 }
1531 }
1532
1533 /**
1534 * Returns a bundle with the current results from the allocation counting.
1535 */
1536 public Bundle getAllocCounts() {
1537 Bundle results = new Bundle();
1538 results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
1539 results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
1540 results.putLong("global_freed_count", Debug.getGlobalFreedCount());
1541 results.putLong("global_freed_size", Debug.getGlobalFreedSize());
1542 results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
1543 return results;
1544 }
1545
1546 /**
1547 * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
1548 * reported are the number of send and the number of received transactions.
1549 */
1550 public Bundle getBinderCounts() {
1551 Bundle results = new Bundle();
1552 results.putLong("sent_transactions", Debug.getBinderSentTransactions());
1553 results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
1554 return results;
1555 }
1556
1557 /**
1558 * Description of a Activity execution result to return to the original
1559 * activity.
1560 */
1561 public static final class ActivityResult {
1562 /**
1563 * Create a new activity result. See {@link Activity#setResult} for
1564 * more information.
1565 *
1566 * @param resultCode The result code to propagate back to the
1567 * originating activity, often RESULT_CANCELED or RESULT_OK
1568 * @param resultData The data to propagate back to the originating
1569 * activity.
1570 */
1571 public ActivityResult(int resultCode, Intent resultData) {
1572 mResultCode = resultCode;
1573 mResultData = resultData;
1574 }
1575
1576 /**
1577 * Retrieve the result code contained in this result.
1578 */
1579 public int getResultCode() {
1580 return mResultCode;
1581 }
1582
1583 /**
1584 * Retrieve the data contained in this result.
1585 */
1586 public Intent getResultData() {
1587 return mResultData;
1588 }
1589
1590 private final int mResultCode;
1591 private final Intent mResultData;
1592 }
1593
1594 /**
1595 * Execute a startActivity call made by the application. The default
1596 * implementation takes care of updating any active {@link ActivityMonitor}
1597 * objects and dispatches this call to the system activity manager; you can
1598 * override this to watch for the application to start an activity, and
1599 * modify what happens when it does.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001600 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 * <p>This method returns an {@link ActivityResult} object, which you can
1602 * use when intercepting application calls to avoid performing the start
1603 * activity action but still return the result the application is
1604 * expecting. To do this, override this method to catch the call to start
1605 * activity so that it returns a new ActivityResult containing the results
1606 * you would like the application to see, and don't call up to the super
1607 * class. Note that an application is only expecting a result if
1608 * <var>requestCode</var> is &gt;= 0.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001609 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 * <p>This method throws {@link android.content.ActivityNotFoundException}
1611 * if there was no Activity found to run the given Intent.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001612 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001613 * @param who The Context from which the activity is being started.
1614 * @param contextThread The main thread of the Context from which the activity
1615 * is being started.
1616 * @param token Internal token identifying to the system who is starting
1617 * the activity; may be null.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001618 * @param target Which activity is performing the start (and thus receiving
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619 * any result); may be null if this call is not being made
1620 * from an activity.
1621 * @param intent The actual Intent to start.
1622 * @param requestCode Identifier for this request's result; less than zero
1623 * if the caller is not expecting a result.
Dianne Hackborna4972e92012-03-14 10:38:05 -07001624 * @param options Addition options.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001625 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626 * @return To force the return of a particular result, return an
1627 * ActivityResult object containing the desired data; otherwise
1628 * return null. The default implementation always returns null.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001629 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630 * @throws android.content.ActivityNotFoundException
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001631 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001632 * @see Activity#startActivity(Intent)
1633 * @see Activity#startActivityForResult(Intent, int)
1634 * @see Activity#startActivityFromChild
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001635 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636 * {@hide}
1637 */
Mathew Inwood4fb17d12018-08-14 14:25:44 +01001638 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001639 public ActivityResult execStartActivity(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001640 Context who, IBinder contextThread, IBinder token, Activity target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001641 Intent intent, int requestCode, Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 IApplicationThread whoThread = (IApplicationThread) contextThread;
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001643 Uri referrer = target != null ? target.onProvideReferrer() : null;
1644 if (referrer != null) {
1645 intent.putExtra(Intent.EXTRA_REFERRER, referrer);
1646 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 if (mActivityMonitors != null) {
1648 synchronized (mSync) {
1649 final int N = mActivityMonitors.size();
1650 for (int i=0; i<N; i++) {
1651 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001652 ActivityResult result = null;
1653 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001654 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001655 }
1656 if (result != null) {
1657 am.mHits++;
1658 return result;
1659 } else if (am.match(who, null, intent)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 am.mHits++;
1661 if (am.isBlocking()) {
1662 return requestCode >= 0 ? am.getResult() : null;
1663 }
1664 break;
1665 }
1666 }
1667 }
1668 }
1669 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001670 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001671 intent.prepareToLeaveProcess(who);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001672 int result = ActivityManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001673 .startActivity(whoThread, who.getBasePackageName(), intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 intent.resolveTypeIfNeeded(who.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07001675 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001676 requestCode, 0, null, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001677 checkStartActivityResult(result, intent);
1678 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001679 throw new RuntimeException("Failure from system", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001680 }
1681 return null;
1682 }
1683
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001684 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001685 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001686 * but accepts an array of activities to be started. Note that active
1687 * {@link ActivityMonitor} objects only match against the first activity in
1688 * the array.
1689 *
1690 * {@hide}
1691 */
Mathew Inwood4fb17d12018-08-14 14:25:44 +01001692 @UnsupportedAppUsage
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001693 public void execStartActivities(Context who, IBinder contextThread,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001694 IBinder token, Activity target, Intent[] intents, Bundle options) {
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001695 execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
Jeff Sharkeyad357d12018-02-02 13:25:31 -07001696 who.getUserId());
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001697 }
1698
1699 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001700 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001701 * but accepts an array of activities to be started. Note that active
1702 * {@link ActivityMonitor} objects only match against the first activity in
1703 * the array.
1704 *
Selim Cinek7fa385a2018-01-24 08:35:28 -08001705 * @return The corresponding flag {@link ActivityManager#START_CANCELED},
1706 * {@link ActivityManager#START_SUCCESS} etc. indicating whether the launch was
1707 * successful.
1708 *
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001709 * {@hide}
1710 */
Mathew Inwood4fb17d12018-08-14 14:25:44 +01001711 @UnsupportedAppUsage
Selim Cinek7fa385a2018-01-24 08:35:28 -08001712 public int execStartActivitiesAsUser(Context who, IBinder contextThread,
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001713 IBinder token, Activity target, Intent[] intents, Bundle options,
1714 int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001715 IApplicationThread whoThread = (IApplicationThread) contextThread;
1716 if (mActivityMonitors != null) {
1717 synchronized (mSync) {
1718 final int N = mActivityMonitors.size();
1719 for (int i=0; i<N; i++) {
1720 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001721 ActivityResult result = null;
1722 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001723 result = am.onStartActivity(intents[0]);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001724 }
1725 if (result != null) {
1726 am.mHits++;
Selim Cinek7fa385a2018-01-24 08:35:28 -08001727 return ActivityManager.START_CANCELED;
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001728 } else if (am.match(who, null, intents[0])) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001729 am.mHits++;
1730 if (am.isBlocking()) {
Selim Cinek7fa385a2018-01-24 08:35:28 -08001731 return ActivityManager.START_CANCELED;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001732 }
1733 break;
1734 }
1735 }
1736 }
1737 }
1738 try {
1739 String[] resolvedTypes = new String[intents.length];
1740 for (int i=0; i<intents.length; i++) {
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001741 intents[i].migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001742 intents[i].prepareToLeaveProcess(who);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001743 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
1744 }
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001745 int result = ActivityManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001746 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
1747 token, options, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001748 checkStartActivityResult(result, intents[0]);
Selim Cinek7fa385a2018-01-24 08:35:28 -08001749 return result;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001750 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001751 throw new RuntimeException("Failure from system", e);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001752 }
1753 }
1754
1755 /**
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001756 * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001757 * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)},
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001758 * but for calls from a {#link Fragment}.
1759 *
1760 * @param who The Context from which the activity is being started.
1761 * @param contextThread The main thread of the Context from which the activity
1762 * is being started.
1763 * @param token Internal token identifying to the system who is starting
1764 * the activity; may be null.
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001765 * @param target Which element is performing the start (and thus receiving
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001766 * any result).
1767 * @param intent The actual Intent to start.
1768 * @param requestCode Identifier for this request's result; less than zero
1769 * if the caller is not expecting a result.
1770 *
1771 * @return To force the return of a particular result, return an
1772 * ActivityResult object containing the desired data; otherwise
1773 * return null. The default implementation always returns null.
1774 *
1775 * @throws android.content.ActivityNotFoundException
1776 *
1777 * @see Activity#startActivity(Intent)
1778 * @see Activity#startActivityForResult(Intent, int)
1779 * @see Activity#startActivityFromChild
1780 *
1781 * {@hide}
1782 */
Mathew Inwood4fb17d12018-08-14 14:25:44 +01001783 @UnsupportedAppUsage
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001784 public ActivityResult execStartActivity(
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001785 Context who, IBinder contextThread, IBinder token, String target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001786 Intent intent, int requestCode, Bundle options) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001787 IApplicationThread whoThread = (IApplicationThread) contextThread;
1788 if (mActivityMonitors != null) {
1789 synchronized (mSync) {
1790 final int N = mActivityMonitors.size();
1791 for (int i=0; i<N; i++) {
1792 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001793 ActivityResult result = null;
1794 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001795 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001796 }
1797 if (result != null) {
1798 am.mHits++;
1799 return result;
1800 } else if (am.match(who, null, intent)) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001801 am.mHits++;
1802 if (am.isBlocking()) {
1803 return requestCode >= 0 ? am.getResult() : null;
1804 }
1805 break;
1806 }
1807 }
1808 }
1809 }
1810 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001811 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001812 intent.prepareToLeaveProcess(who);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001813 int result = ActivityManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001814 .startActivity(whoThread, who.getBasePackageName(), intent,
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001815 intent.resolveTypeIfNeeded(who.getContentResolver()),
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001816 token, target, requestCode, 0, null, options);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001817 checkStartActivityResult(result, intent);
1818 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001819 throw new RuntimeException("Failure from system", e);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001820 }
1821 return null;
1822 }
1823
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001824 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001825 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
1826 * but for starting as a particular user.
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001827 *
1828 * @param who The Context from which the activity is being started.
1829 * @param contextThread The main thread of the Context from which the activity
1830 * is being started.
1831 * @param token Internal token identifying to the system who is starting
1832 * the activity; may be null.
1833 * @param target Which fragment is performing the start (and thus receiving
1834 * any result).
1835 * @param intent The actual Intent to start.
1836 * @param requestCode Identifier for this request's result; less than zero
1837 * if the caller is not expecting a result.
1838 *
1839 * @return To force the return of a particular result, return an
1840 * ActivityResult object containing the desired data; otherwise
1841 * return null. The default implementation always returns null.
1842 *
1843 * @throws android.content.ActivityNotFoundException
1844 *
1845 * @see Activity#startActivity(Intent)
1846 * @see Activity#startActivityForResult(Intent, int)
1847 * @see Activity#startActivityFromChild
1848 *
1849 * {@hide}
1850 */
Mathew Inwood4fb17d12018-08-14 14:25:44 +01001851 @UnsupportedAppUsage
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001852 public ActivityResult execStartActivity(
Tony Mak96d26fe2017-04-11 20:05:39 +01001853 Context who, IBinder contextThread, IBinder token, String resultWho,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001854 Intent intent, int requestCode, Bundle options, UserHandle user) {
1855 IApplicationThread whoThread = (IApplicationThread) contextThread;
1856 if (mActivityMonitors != null) {
1857 synchronized (mSync) {
1858 final int N = mActivityMonitors.size();
1859 for (int i=0; i<N; i++) {
1860 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001861 ActivityResult result = null;
1862 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001863 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001864 }
1865 if (result != null) {
1866 am.mHits++;
1867 return result;
1868 } else if (am.match(who, null, intent)) {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001869 am.mHits++;
1870 if (am.isBlocking()) {
1871 return requestCode >= 0 ? am.getResult() : null;
1872 }
1873 break;
1874 }
1875 }
1876 }
1877 }
1878 try {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001879 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001880 intent.prepareToLeaveProcess(who);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001881 int result = ActivityManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001882 .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001883 intent.resolveTypeIfNeeded(who.getContentResolver()),
Tony Mak96d26fe2017-04-11 20:05:39 +01001884 token, resultWho,
Jeff Hao1b012d32014-08-20 10:35:34 -07001885 requestCode, 0, null, options, user.getIdentifier());
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001886 checkStartActivityResult(result, intent);
1887 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001888 throw new RuntimeException("Failure from system", e);
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001889 }
1890 return null;
1891 }
1892
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001893 /**
1894 * Special version!
1895 * @hide
1896 */
Mathew Inwood4fb17d12018-08-14 14:25:44 +01001897 @UnsupportedAppUsage
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001898 public ActivityResult execStartActivityAsCaller(
1899 Context who, IBinder contextThread, IBinder token, Activity target,
Alison Cichowlas76f0ccb2018-01-29 16:34:33 -05001900 Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity,
1901 int userId) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001902 IApplicationThread whoThread = (IApplicationThread) contextThread;
1903 if (mActivityMonitors != null) {
1904 synchronized (mSync) {
1905 final int N = mActivityMonitors.size();
1906 for (int i=0; i<N; i++) {
1907 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001908 ActivityResult result = null;
1909 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001910 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001911 }
1912 if (result != null) {
1913 am.mHits++;
1914 return result;
1915 } else if (am.match(who, null, intent)) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001916 am.mHits++;
1917 if (am.isBlocking()) {
1918 return requestCode >= 0 ? am.getResult() : null;
1919 }
1920 break;
1921 }
1922 }
1923 }
1924 }
1925 try {
1926 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001927 intent.prepareToLeaveProcess(who);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001928 int result = ActivityManager.getService()
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001929 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
1930 intent.resolveTypeIfNeeded(who.getContentResolver()),
1931 token, target != null ? target.mEmbeddedID : null,
Alison Cichowlas76f0ccb2018-01-29 16:34:33 -05001932 requestCode, 0, null, options, ignoreTargetSecurity, userId);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001933 checkStartActivityResult(result, intent);
1934 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001935 throw new RuntimeException("Failure from system", e);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001936 }
1937 return null;
1938 }
1939
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001940 /**
1941 * Special version!
1942 * @hide
1943 */
Mathew Inwood4fb17d12018-08-14 14:25:44 +01001944 @UnsupportedAppUsage
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001945 public void execStartActivityFromAppTask(
1946 Context who, IBinder contextThread, IAppTask appTask,
1947 Intent intent, Bundle options) {
1948 IApplicationThread whoThread = (IApplicationThread) contextThread;
1949 if (mActivityMonitors != null) {
1950 synchronized (mSync) {
1951 final int N = mActivityMonitors.size();
1952 for (int i=0; i<N; i++) {
1953 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001954 ActivityResult result = null;
1955 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001956 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001957 }
1958 if (result != null) {
1959 am.mHits++;
1960 return;
1961 } else if (am.match(who, null, intent)) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001962 am.mHits++;
1963 if (am.isBlocking()) {
1964 return;
1965 }
1966 break;
1967 }
1968 }
1969 }
1970 }
1971 try {
1972 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001973 intent.prepareToLeaveProcess(who);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001974 int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
1975 intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options);
1976 checkStartActivityResult(result, intent);
1977 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001978 throw new RuntimeException("Failure from system", e);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001979 }
1980 return;
1981 }
1982
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 /*package*/ final void init(ActivityThread thread,
1984 Context instrContext, Context appContext, ComponentName component,
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001985 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001986 mThread = thread;
1987 mMessageQueue = mThread.getLooper().myQueue();
1988 mInstrContext = instrContext;
1989 mAppContext = appContext;
1990 mComponent = component;
1991 mWatcher = watcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001992 mUiAutomationConnection = uiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 }
1994
Jason Monka80bfb52017-11-16 17:15:37 -05001995 /**
1996 * Only sets the ActivityThread up, keeps everything else null because app is not being
1997 * instrumented.
1998 */
1999 final void basicInit(ActivityThread thread) {
2000 mThread = thread;
2001 }
2002
Dianne Hackborn91097de2014-04-04 18:02:06 -07002003 /** @hide */
Mathew Inwood55418ea2018-12-20 15:30:45 +00002004 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Dianne Hackborn91097de2014-04-04 18:02:06 -07002005 public static void checkStartActivityResult(int res, Object intent) {
Bryce Lee7f936862017-05-09 15:33:18 -07002006 if (!ActivityManager.isStartResultFatalError(res)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002007 return;
2008 }
Amith Yamasani42449782016-04-19 11:45:51 -07002009
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002010 switch (res) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07002011 case ActivityManager.START_INTENT_NOT_RESOLVED:
2012 case ActivityManager.START_CLASS_NOT_FOUND:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002013 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002014 throw new ActivityNotFoundException(
2015 "Unable to find explicit activity class "
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002016 + ((Intent)intent).getComponent().toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002017 + "; have you declared this activity in your AndroidManifest.xml?");
2018 throw new ActivityNotFoundException(
2019 "No Activity found to handle " + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002020 case ActivityManager.START_PERMISSION_DENIED:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002021 throw new SecurityException("Not allowed to start activity "
2022 + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002023 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002024 throw new AndroidRuntimeException(
2025 "FORWARD_RESULT_FLAG used while also requesting a result");
Dianne Hackborna4972e92012-03-14 10:38:05 -07002026 case ActivityManager.START_NOT_ACTIVITY:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002027 throw new IllegalArgumentException(
2028 "PendingIntent is not an activity");
Dianne Hackborn91097de2014-04-04 18:02:06 -07002029 case ActivityManager.START_NOT_VOICE_COMPATIBLE:
2030 throw new SecurityException(
2031 "Starting under voice control not allowed for: " + intent);
Amith Yamasani42449782016-04-19 11:45:51 -07002032 case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
2033 throw new IllegalStateException(
2034 "Session calling startVoiceActivity does not match active session");
2035 case ActivityManager.START_VOICE_HIDDEN_SESSION:
2036 throw new IllegalStateException(
2037 "Cannot start voice activity on a hidden session");
Winson Chungfc3ec4c2017-06-01 15:35:48 -07002038 case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
2039 throw new IllegalStateException(
2040 "Session calling startAssistantActivity does not match active session");
2041 case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
2042 throw new IllegalStateException(
2043 "Cannot start assistant activity on a hidden session");
Amith Yamasani42449782016-04-19 11:45:51 -07002044 case ActivityManager.START_CANCELED:
2045 throw new AndroidRuntimeException("Activity could not be started for "
2046 + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 default:
2048 throw new AndroidRuntimeException("Unknown error code "
2049 + res + " when starting " + intent);
2050 }
2051 }
Chong Zhang45c25ce2015-08-10 22:18:26 -07002052
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 private final void validateNotAppThread() {
Kristian Monsen0a303282013-01-18 14:50:07 -08002054 if (Looper.myLooper() == Looper.getMainLooper()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002055 throw new RuntimeException(
2056 "This method can not be called from the main application thread");
2057 }
2058 }
2059
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002060 /**
Phil Weaverd8e88832016-03-28 17:26:25 -07002061 * Gets the {@link UiAutomation} instance with no flags set.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002062 * <p>
2063 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
2064 * work across application boundaries while the APIs exposed by the instrumentation
2065 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
2066 * not allow you to inject the event in an app different from the instrumentation
2067 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
2068 * will work regardless of the current application.
2069 * </p>
2070 * <p>
2071 * A typical test case should be using either the {@link UiAutomation} or
2072 * {@link Instrumentation} APIs. Using both APIs at the same time is not
2073 * a mistake by itself but a client has to be aware of the APIs limitations.
2074 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07002075 * <p>
2076 * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different
2077 * flags, the flags on that instance will be changed, and then it will be returned.
2078 * </p>
2079 * @return The UI automation instance.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002080 *
2081 * @see UiAutomation
2082 */
2083 public UiAutomation getUiAutomation() {
Phil Weaverd8e88832016-03-28 17:26:25 -07002084 return getUiAutomation(0);
Phil Weaver1dd87222016-01-26 17:15:15 -08002085 }
2086
2087 /**
2088 * Gets the {@link UiAutomation} instance with flags set.
2089 * <p>
Phil Weaver1dd87222016-01-26 17:15:15 -08002090 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
2091 * work across application boundaries while the APIs exposed by the instrumentation
2092 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
2093 * not allow you to inject the event in an app different from the instrumentation
2094 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
2095 * will work regardless of the current application.
2096 * </p>
2097 * <p>
2098 * A typical test case should be using either the {@link UiAutomation} or
2099 * {@link Instrumentation} APIs. Using both APIs at the same time is not
2100 * a mistake by itself but a client has to be aware of the APIs limitations.
2101 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07002102 * <p>
2103 * If a {@link UiAutomation} exists with different flags, the flags on that instance will be
2104 * changed, and then it will be returned.
2105 * </p>
Phil Weaver1dd87222016-01-26 17:15:15 -08002106 *
2107 * @param flags The flags to be passed to the UiAutomation, for example
2108 * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
2109 *
2110 * @return The UI automation instance.
2111 *
2112 * @see UiAutomation
2113 */
Phil Weaver35841682016-03-09 09:52:51 -08002114 public UiAutomation getUiAutomation(@UiAutomationFlags int flags) {
Phil Weaverd8e88832016-03-28 17:26:25 -07002115 boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed());
2116
Phil Weaver1dd87222016-01-26 17:15:15 -08002117 if (mUiAutomationConnection != null) {
Phil Weaverd8e88832016-03-28 17:26:25 -07002118 if (!mustCreateNewAutomation && (mUiAutomation.getFlags() == flags)) {
2119 return mUiAutomation;
2120 }
2121 if (mustCreateNewAutomation) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002122 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
2123 mUiAutomationConnection);
Phil Weaver1dd87222016-01-26 17:15:15 -08002124 } else {
Phil Weaverd8e88832016-03-28 17:26:25 -07002125 mUiAutomation.disconnect();
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002126 }
Phil Weaverd8e88832016-03-28 17:26:25 -07002127 mUiAutomation.connect(flags);
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002128 return mUiAutomation;
2129 }
2130 return null;
2131 }
2132
Jason Monk5be50f72017-03-10 10:57:34 -05002133 /**
2134 * Takes control of the execution of messages on the specified looper until
2135 * {@link TestLooperManager#release} is called.
2136 */
2137 public TestLooperManager acquireLooperManager(Looper looper) {
2138 checkInstrumenting("acquireLooperManager");
2139 return new TestLooperManager(looper);
2140 }
2141
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002142 private final class InstrumentationThread extends Thread {
2143 public InstrumentationThread(String name) {
2144 super(name);
2145 }
2146 public void run() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002147 try {
2148 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
2149 } catch (RuntimeException e) {
Phil Weaver1dd87222016-01-26 17:15:15 -08002150 Log.w(TAG, "Exception setting priority of instrumentation thread "
2151 + Process.myTid(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002152 }
2153 if (mAutomaticPerformanceSnapshots) {
2154 startPerformanceSnapshot();
2155 }
2156 onStart();
2157 }
2158 }
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002159
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002160 private static final class EmptyRunnable implements Runnable {
2161 public void run() {
2162 }
2163 }
2164
2165 private static final class SyncRunnable implements Runnable {
2166 private final Runnable mTarget;
2167 private boolean mComplete;
2168
2169 public SyncRunnable(Runnable target) {
2170 mTarget = target;
2171 }
2172
2173 public void run() {
2174 mTarget.run();
2175 synchronized (this) {
2176 mComplete = true;
2177 notifyAll();
2178 }
2179 }
2180
2181 public void waitForComplete() {
2182 synchronized (this) {
2183 while (!mComplete) {
2184 try {
2185 wait();
2186 } catch (InterruptedException e) {
2187 }
2188 }
2189 }
2190 }
2191 }
2192
2193 private static final class ActivityWaiter {
2194 public final Intent intent;
2195 public Activity activity;
2196
2197 public ActivityWaiter(Intent _intent) {
2198 intent = _intent;
2199 }
2200 }
2201
2202 private final class ActivityGoing implements MessageQueue.IdleHandler {
2203 private final ActivityWaiter mWaiter;
2204
2205 public ActivityGoing(ActivityWaiter waiter) {
2206 mWaiter = waiter;
2207 }
2208
2209 public final boolean queueIdle() {
2210 synchronized (mSync) {
2211 mWaitingActivities.remove(mWaiter);
2212 mSync.notifyAll();
2213 }
2214 return false;
2215 }
2216 }
2217
2218 private static final class Idler implements MessageQueue.IdleHandler {
2219 private final Runnable mCallback;
2220 private boolean mIdle;
2221
2222 public Idler(Runnable callback) {
2223 mCallback = callback;
2224 mIdle = false;
2225 }
2226
2227 public final boolean queueIdle() {
2228 if (mCallback != null) {
2229 mCallback.run();
2230 }
2231 synchronized (this) {
2232 mIdle = true;
2233 notifyAll();
2234 }
2235 return false;
2236 }
2237
2238 public void waitForIdle() {
2239 synchronized (this) {
2240 while (!mIdle) {
2241 try {
2242 wait();
2243 } catch (InterruptedException e) {
2244 }
2245 }
2246 }
2247 }
2248 }
2249}