blob: 3c38a4ec5fe43e77b914524e7e55251d8a5ab265 [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;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.ActivityNotFoundException;
23import android.content.ComponentName;
24import android.content.Context;
25import android.content.Intent;
26import android.content.IntentFilter;
27import android.content.pm.ActivityInfo;
28import android.content.res.Configuration;
Jeff Brownac143512012-04-05 18:57:33 -070029import android.hardware.input.InputManager;
Dianne Hackborna3acdb32015-06-08 17:07:40 -070030import android.net.Uri;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032import android.os.Debug;
33import android.os.IBinder;
Kristian Monsen0a303282013-01-18 14:50:07 -080034import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080035import android.os.MessageQueue;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080036import android.os.PerformanceCollector;
Craig Mautnera0026042014-04-23 11:45:37 -070037import android.os.PersistableBundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.os.Process;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080039import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.os.ServiceManager;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080041import android.os.SystemClock;
Jason Monk5be50f72017-03-10 10:57:34 -050042import android.os.TestLooperManager;
Dianne Hackbornf1c26e22012-08-23 13:54:58 -070043import android.os.UserHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.util.AndroidRuntimeException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.util.Log;
46import android.view.IWindowManager;
Jeff Brownac143512012-04-05 18:57:33 -070047import android.view.InputDevice;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048import android.view.KeyCharacterMap;
49import android.view.KeyEvent;
50import android.view.MotionEvent;
51import android.view.ViewConfiguration;
52import android.view.Window;
Winson Chung298f95b2017-08-10 15:57:18 -070053
Dianne Hackborn85d558c2014-11-04 10:31:54 -080054import com.android.internal.content.ReferrerIntent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
56import java.io.File;
Phil Weaver35841682016-03-09 09:52:51 -080057import java.lang.annotation.Retention;
58import java.lang.annotation.RetentionPolicy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059import java.util.ArrayList;
60import java.util.List;
61
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062/**
63 * Base class for implementing application instrumentation code. When running
64 * with instrumentation turned on, this class will be instantiated for you
65 * before any of the application code, allowing you to monitor all of the
66 * interaction the system has with the application. An Instrumentation
67 * implementation is described to the system through an AndroidManifest.xml's
68 * <instrumentation> tag.
69 */
70public class Instrumentation {
Svetoslav Ganov80943d82013-01-02 10:25:37 -080071
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072 /**
73 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
74 * identifies the class that is writing the report. This can be used to provide more structured
75 * logging or reporting capabilities in the IInstrumentationWatcher.
76 */
77 public static final String REPORT_KEY_IDENTIFIER = "id";
78 /**
79 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
80 * identifies a string which can simply be printed to the output stream. Using these streams
81 * provides a "pretty printer" version of the status & final packets. Any bundles including
82 * this key should also include the complete set of raw key/value pairs, so that the
83 * instrumentation can also be launched, and results collected, by an automated system.
84 */
85 public static final String REPORT_KEY_STREAMRESULT = "stream";
Svetoslav Ganov80943d82013-01-02 10:25:37 -080086
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 private static final String TAG = "Instrumentation";
Phil Weaver35841682016-03-09 09:52:51 -080088
89 /**
90 * @hide
91 */
92 @Retention(RetentionPolicy.SOURCE)
93 @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES})
94 public @interface UiAutomationFlags {};
95
96
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080097 private final Object mSync = new Object();
98 private ActivityThread mThread = null;
99 private MessageQueue mMessageQueue = null;
100 private Context mInstrContext;
101 private Context mAppContext;
102 private ComponentName mComponent;
103 private Thread mRunner;
104 private List<ActivityWaiter> mWaitingActivities;
105 private List<ActivityMonitor> mActivityMonitors;
106 private IInstrumentationWatcher mWatcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800107 private IUiAutomationConnection mUiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 private boolean mAutomaticPerformanceSnapshots = false;
Jack Wangff1df692009-08-26 17:19:13 -0700109 private PerformanceCollector mPerformanceCollector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 private Bundle mPerfMetrics = new Bundle();
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800111 private UiAutomation mUiAutomation;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112
113 public Instrumentation() {
114 }
115
116 /**
Jason Monk5be50f72017-03-10 10:57:34 -0500117 * Called for methods that shouldn't be called by standard apps and
118 * should only be used in instrumentation environments. This is not
119 * security feature as these classes will still be accessible through
120 * reflection, but it will serve as noticeable discouragement from
121 * doing such a thing.
122 */
123 private void checkInstrumenting(String method) {
124 // Check if we have an instrumentation context, as init should only get called by
125 // the system in startup processes that are being instrumented.
126 if (mInstrContext == null) {
127 throw new RuntimeException(method +
128 " cannot be called outside of instrumented processes");
129 }
130 }
131
132 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 * Called when the instrumentation is starting, before any application code
134 * has been loaded. Usually this will be implemented to simply call
135 * {@link #start} to begin the instrumentation thread, which will then
136 * continue execution in {@link #onStart}.
137 *
138 * <p>If you do not need your own thread -- that is you are writing your
139 * instrumentation to be completely asynchronous (returning to the event
140 * loop so that the application can run), you can simply begin your
141 * instrumentation here, for example call {@link Context#startActivity} to
142 * begin the appropriate first activity of the application.
143 *
144 * @param arguments Any additional arguments that were supplied when the
145 * instrumentation was started.
146 */
147 public void onCreate(Bundle arguments) {
148 }
149
150 /**
151 * Create and start a new thread in which to run instrumentation. This new
152 * thread will call to {@link #onStart} where you can implement the
153 * instrumentation.
154 */
155 public void start() {
156 if (mRunner != null) {
157 throw new RuntimeException("Instrumentation already started");
158 }
159 mRunner = new InstrumentationThread("Instr: " + getClass().getName());
160 mRunner.start();
161 }
162
163 /**
164 * Method where the instrumentation thread enters execution. This allows
165 * you to run your instrumentation code in a separate thread than the
166 * application, so that it can perform blocking operation such as
167 * {@link #sendKeySync} or {@link #startActivitySync}.
168 *
169 * <p>You will typically want to call finish() when this function is done,
170 * to end your instrumentation.
171 */
172 public void onStart() {
173 }
174
175 /**
176 * This is called whenever the system captures an unhandled exception that
177 * was thrown by the application. The default implementation simply
178 * returns false, allowing normal system handling of the exception to take
179 * place.
180 *
181 * @param obj The client object that generated the exception. May be an
182 * Application, Activity, BroadcastReceiver, Service, or null.
183 * @param e The exception that was thrown.
184 *
185 * @return To allow normal system exception process to occur, return false.
186 * If true is returned, the system will proceed as if the exception
187 * didn't happen.
188 */
189 public boolean onException(Object obj, Throwable e) {
190 return false;
191 }
192
193 /**
194 * Provide a status report about the application.
195 *
196 * @param resultCode Current success/failure of instrumentation.
197 * @param results Any results to send back to the code that started the instrumentation.
198 */
199 public void sendStatus(int resultCode, Bundle results) {
200 if (mWatcher != null) {
201 try {
202 mWatcher.instrumentationStatus(mComponent, resultCode, results);
203 }
204 catch (RemoteException e) {
205 mWatcher = null;
206 }
207 }
208 }
Dianne Hackborn34041732017-01-31 15:27:13 -0800209
210 /**
211 * Report some results in the middle of instrumentation execution. Later results (including
212 * those provided by {@link #finish}) will be combined with {@link Bundle#putAll}.
213 */
214 public void addResults(Bundle results) {
215 IActivityManager am = ActivityManager.getService();
216 try {
217 am.addInstrumentationResults(mThread.getApplicationThread(), results);
218 } catch (RemoteException ex) {
219 throw ex.rethrowFromSystemServer();
220 }
221 }
222
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 /**
224 * Terminate instrumentation of the application. This will cause the
225 * application process to exit, removing this instrumentation from the next
Dianne Hackborn34041732017-01-31 15:27:13 -0800226 * time the application is started. If multiple processes are currently running
227 * for this instrumentation, all of those processes will be killed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 *
229 * @param resultCode Overall success/failure of instrumentation.
230 * @param results Any results to send back to the code that started the
231 * instrumentation.
232 */
233 public void finish(int resultCode, Bundle results) {
234 if (mAutomaticPerformanceSnapshots) {
235 endPerformanceSnapshot();
236 }
237 if (mPerfMetrics != null) {
Dianne Hackbornb65ea7b2014-06-20 12:18:55 -0700238 if (results == null) {
239 results = new Bundle();
240 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800241 results.putAll(mPerfMetrics);
242 }
Phil Weaverd8e88832016-03-28 17:26:25 -0700243 if ((mUiAutomation != null) && !mUiAutomation.isDestroyed()) {
Adam Momtaz8f6f1f42013-04-10 12:42:58 -0700244 mUiAutomation.disconnect();
245 mUiAutomation = null;
246 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800247 mThread.finishInstrumentation(resultCode, results);
248 }
249
250 public void setAutomaticPerformanceSnapshots() {
251 mAutomaticPerformanceSnapshots = true;
Jack Wangff1df692009-08-26 17:19:13 -0700252 mPerformanceCollector = new PerformanceCollector();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 }
254
255 public void startPerformanceSnapshot() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700257 mPerformanceCollector.beginSnapshot(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 }
259 }
260
261 public void endPerformanceSnapshot() {
262 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700263 mPerfMetrics = mPerformanceCollector.endSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 }
265 }
266
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 /**
268 * Called when the instrumented application is stopping, after all of the
269 * normal application cleanup has occurred.
270 */
271 public void onDestroy() {
272 }
273
274 /**
275 * Return the Context of this instrumentation's package. Note that this is
276 * often different than the Context of the application being
277 * instrumentated, since the instrumentation code often lives is a
278 * different package than that of the application it is running against.
279 * See {@link #getTargetContext} to retrieve a Context for the target
280 * application.
281 *
282 * @return The instrumentation's package context.
283 *
284 * @see #getTargetContext
285 */
286 public Context getContext() {
287 return mInstrContext;
288 }
289
290 /**
291 * Returns complete component name of this instrumentation.
292 *
293 * @return Returns the complete component name for this instrumentation.
294 */
295 public ComponentName getComponentName() {
296 return mComponent;
297 }
298
299 /**
300 * Return a Context for the target application being instrumented. Note
301 * that this is often different than the Context of the instrumentation
302 * code, since the instrumentation code often lives is a different package
303 * than that of the application it is running against. See
304 * {@link #getContext} to retrieve a Context for the instrumentation code.
305 *
306 * @return A Context in the target application.
307 *
308 * @see #getContext
309 */
310 public Context getTargetContext() {
311 return mAppContext;
312 }
313
314 /**
Dianne Hackborn34041732017-01-31 15:27:13 -0800315 * Return the name of the process this instrumentation is running in. Note this should
316 * only be used for testing and debugging. If you are thinking about using this to,
317 * for example, conditionalize what is initialized in an Application class, it is strongly
318 * recommended to instead use lazy initialization (such as a getter for the state that
319 * only creates it when requested). This can greatly reduce the work your process does
320 * when created for secondary things, such as to receive a broadcast.
321 */
322 public String getProcessName() {
323 return mThread.getProcessName();
324 }
325
326 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 * Check whether this instrumentation was started with profiling enabled.
328 *
329 * @return Returns true if profiling was enabled when starting, else false.
330 */
331 public boolean isProfiling() {
332 return mThread.isProfiling();
333 }
334
335 /**
336 * This method will start profiling if isProfiling() returns true. You should
337 * only call this method if you set the handleProfiling attribute in the
338 * manifest file for this Instrumentation to true.
339 */
340 public void startProfiling() {
341 if (mThread.isProfiling()) {
342 File file = new File(mThread.getProfileFilePath());
343 file.getParentFile().mkdirs();
344 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
345 }
346 }
347
348 /**
349 * Stops profiling if isProfiling() returns true.
350 */
351 public void stopProfiling() {
352 if (mThread.isProfiling()) {
353 Debug.stopMethodTracing();
354 }
355 }
356
357 /**
358 * Force the global system in or out of touch mode. This can be used if
359 * your instrumentation relies on the UI being in one more or the other
360 * when it starts.
361 *
362 * @param inTouch Set to true to be in touch mode, false to be in
363 * focus mode.
364 */
365 public void setInTouchMode(boolean inTouch) {
366 try {
367 IWindowManager.Stub.asInterface(
368 ServiceManager.getService("window")).setInTouchMode(inTouch);
369 } catch (RemoteException e) {
370 // Shouldn't happen!
371 }
372 }
373
374 /**
375 * Schedule a callback for when the application's main thread goes idle
376 * (has no more events to process).
377 *
378 * @param recipient Called the next time the thread's message queue is
379 * idle.
380 */
381 public void waitForIdle(Runnable recipient) {
382 mMessageQueue.addIdleHandler(new Idler(recipient));
383 mThread.getHandler().post(new EmptyRunnable());
384 }
385
386 /**
387 * Synchronously wait for the application to be idle. Can not be called
388 * from the main application thread -- use {@link #start} to execute
389 * instrumentation in its own thread.
390 */
391 public void waitForIdleSync() {
392 validateNotAppThread();
393 Idler idler = new Idler(null);
394 mMessageQueue.addIdleHandler(idler);
395 mThread.getHandler().post(new EmptyRunnable());
396 idler.waitForIdle();
397 }
398
399 /**
400 * Execute a call on the application's main thread, blocking until it is
401 * complete. Useful for doing things that are not thread-safe, such as
402 * looking at or modifying the view hierarchy.
403 *
404 * @param runner The code to run on the main thread.
405 */
406 public void runOnMainSync(Runnable runner) {
407 validateNotAppThread();
408 SyncRunnable sr = new SyncRunnable(runner);
409 mThread.getHandler().post(sr);
410 sr.waitForComplete();
411 }
412
413 /**
414 * Start a new activity and wait for it to begin running before returning.
415 * In addition to being synchronous, this method as some semantic
416 * differences from the standard {@link Context#startActivity} call: the
417 * activity component is resolved before talking with the activity manager
418 * (its class name is specified in the Intent that this method ultimately
419 * starts), and it does not allow you to start activities that run in a
420 * different process. In addition, if the given Intent resolves to
421 * multiple activities, instead of displaying a dialog for the user to
422 * select an activity, an exception will be thrown.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000423 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800424 * <p>The function returns as soon as the activity goes idle following the
425 * call to its {@link Activity#onCreate}. Generally this means it has gone
426 * through the full initialization including {@link Activity#onResume} and
427 * drawn and displayed its initial window.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000428 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 * @param intent Description of the activity to start.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000430 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800431 * @see Context#startActivity
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000432 * @see #startActivitySync(Intent, Bundle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 */
434 public Activity startActivitySync(Intent intent) {
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000435 return startActivitySync(intent, null /* options */);
436 }
437
438 /**
439 * Start a new activity and wait for it to begin running before returning.
440 * In addition to being synchronous, this method as some semantic
441 * differences from the standard {@link Context#startActivity} call: the
442 * activity component is resolved before talking with the activity manager
443 * (its class name is specified in the Intent that this method ultimately
444 * starts), and it does not allow you to start activities that run in a
445 * different process. In addition, if the given Intent resolves to
446 * multiple activities, instead of displaying a dialog for the user to
447 * select an activity, an exception will be thrown.
448 *
449 * <p>The function returns as soon as the activity goes idle following the
450 * call to its {@link Activity#onCreate}. Generally this means it has gone
451 * through the full initialization including {@link Activity#onResume} and
452 * drawn and displayed its initial window.
453 *
454 * @param intent Description of the activity to start.
455 * @param options Additional options for how the Activity should be started.
456 * May be null if there are no options. See {@link android.app.ActivityOptions}
457 * for how to build the Bundle supplied here; there are no supported definitions
458 * for building it manually.
459 *
460 * @see Context#startActivity(Intent, Bundle)
461 */
Wale Ogunwale2632c972018-01-22 06:54:48 -0800462 @NonNull
463 public Activity startActivitySync(@NonNull Intent intent, @Nullable Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800464 validateNotAppThread();
465
466 synchronized (mSync) {
467 intent = new Intent(intent);
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000468
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 ActivityInfo ai = intent.resolveActivityInfo(
470 getTargetContext().getPackageManager(), 0);
471 if (ai == null) {
472 throw new RuntimeException("Unable to resolve activity for: " + intent);
473 }
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700474 String myProc = mThread.getProcessName();
475 if (!ai.processName.equals(myProc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 // todo: if this intent is ambiguous, look here to see if
477 // there is a single match that is in our package.
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700478 throw new RuntimeException("Intent in process "
479 + myProc + " resolved to different process "
480 + ai.processName + ": " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800481 }
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000482
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800483 intent.setComponent(new ComponentName(
484 ai.applicationInfo.packageName, ai.name));
485 final ActivityWaiter aw = new ActivityWaiter(intent);
486
487 if (mWaitingActivities == null) {
488 mWaitingActivities = new ArrayList();
489 }
490 mWaitingActivities.add(aw);
491
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000492 getTargetContext().startActivity(intent, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493
494 do {
495 try {
496 mSync.wait();
497 } catch (InterruptedException e) {
498 }
499 } while (mWaitingActivities.contains(aw));
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000500
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 return aw.activity;
502 }
503 }
504
505 /**
506 * Information about a particular kind of Intent that is being monitored.
507 * An instance of this class is added to the
508 * current instrumentation through {@link #addMonitor}; after being added,
509 * when a new activity is being started the monitor will be checked and, if
510 * matching, its hit count updated and (optionally) the call stopped and a
511 * canned result returned.
512 *
513 * <p>An ActivityMonitor can also be used to look for the creation of an
514 * activity, through the {@link #waitForActivity} method. This will return
515 * after a matching activity has been created with that activity object.
516 */
517 public static class ActivityMonitor {
518 private final IntentFilter mWhich;
519 private final String mClass;
520 private final ActivityResult mResult;
521 private final boolean mBlock;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800522 private final boolean mIgnoreMatchingSpecificIntents;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800523
524
525 // This is protected by 'Instrumentation.this.mSync'.
526 /*package*/ int mHits = 0;
527
528 // This is protected by 'this'.
529 /*package*/ Activity mLastActivity = null;
530
531 /**
532 * Create a new ActivityMonitor that looks for a particular kind of
533 * intent to be started.
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800534 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 * @param which The set of intents this monitor is responsible for.
536 * @param result A canned result to return if the monitor is hit; can
537 * be null.
538 * @param block Controls whether the monitor should block the activity
539 * start (returning its canned result) or let the call
540 * proceed.
541 *
542 * @see Instrumentation#addMonitor
543 */
544 public ActivityMonitor(
545 IntentFilter which, ActivityResult result, boolean block) {
546 mWhich = which;
547 mClass = null;
548 mResult = result;
549 mBlock = block;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800550 mIgnoreMatchingSpecificIntents = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800551 }
552
553 /**
554 * Create a new ActivityMonitor that looks for a specific activity
555 * class to be started.
556 *
557 * @param cls The activity class this monitor is responsible for.
558 * @param result A canned result to return if the monitor is hit; can
559 * be null.
560 * @param block Controls whether the monitor should block the activity
561 * start (returning its canned result) or let the call
562 * proceed.
563 *
564 * @see Instrumentation#addMonitor
565 */
566 public ActivityMonitor(
567 String cls, ActivityResult result, boolean block) {
568 mWhich = null;
569 mClass = cls;
570 mResult = result;
571 mBlock = block;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800572 mIgnoreMatchingSpecificIntents = false;
573 }
574
575 /**
576 * Create a new ActivityMonitor that can be used for intercepting any activity to be
577 * started.
578 *
Sudheer Shanka34217512017-04-26 14:49:16 -0700579 * <p> When an activity is started, {@link #onStartActivity(Intent)} will be called on
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800580 * instances created using this constructor to see if it is a hit.
581 *
Sudheer Shanka34217512017-04-26 14:49:16 -0700582 * @see #onStartActivity(Intent)
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800583 */
584 public ActivityMonitor() {
585 mWhich = null;
586 mClass = null;
587 mResult = null;
588 mBlock = false;
589 mIgnoreMatchingSpecificIntents = true;
590 }
591
592 /**
593 * @return true if this monitor is used for intercepting any started activity by calling
Sudheer Shanka34217512017-04-26 14:49:16 -0700594 * into {@link #onStartActivity(Intent)}, false if this monitor is only used
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800595 * for specific intents corresponding to the intent filter or activity class
596 * passed in the constructor.
597 */
598 final boolean ignoreMatchingSpecificIntents() {
599 return mIgnoreMatchingSpecificIntents;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800600 }
601
602 /**
603 * Retrieve the filter associated with this ActivityMonitor.
604 */
605 public final IntentFilter getFilter() {
606 return mWhich;
607 }
608
609 /**
610 * Retrieve the result associated with this ActivityMonitor, or null if
611 * none.
612 */
613 public final ActivityResult getResult() {
614 return mResult;
615 }
616
617 /**
618 * Check whether this monitor blocks activity starts (not allowing the
619 * actual activity to run) or allows them to execute normally.
620 */
621 public final boolean isBlocking() {
622 return mBlock;
623 }
624
625 /**
626 * Retrieve the number of times the monitor has been hit so far.
627 */
628 public final int getHits() {
629 return mHits;
630 }
631
632 /**
633 * Retrieve the most recent activity class that was seen by this
634 * monitor.
635 */
636 public final Activity getLastActivity() {
637 return mLastActivity;
638 }
639
640 /**
641 * Block until an Activity is created that matches this monitor,
642 * returning the resulting activity.
643 *
644 * @return Activity
645 */
646 public final Activity waitForActivity() {
647 synchronized (this) {
648 while (mLastActivity == null) {
649 try {
650 wait();
651 } catch (InterruptedException e) {
652 }
653 }
654 Activity res = mLastActivity;
655 mLastActivity = null;
656 return res;
657 }
658 }
659
660 /**
661 * Block until an Activity is created that matches this monitor,
662 * returning the resulting activity or till the timeOut period expires.
663 * If the timeOut expires before the activity is started, return null.
664 *
Ben Gruver87904e82016-01-22 13:11:11 -0800665 * @param timeOut Time to wait in milliseconds before the activity is created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800666 *
667 * @return Activity
668 */
669 public final Activity waitForActivityWithTimeout(long timeOut) {
670 synchronized (this) {
Costin Manolacheb0935342011-07-15 11:20:42 -0700671 if (mLastActivity == null) {
672 try {
673 wait(timeOut);
674 } catch (InterruptedException e) {
675 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 }
677 if (mLastActivity == null) {
678 return null;
679 } else {
680 Activity res = mLastActivity;
681 mLastActivity = null;
682 return res;
683 }
684 }
685 }
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800686
687 /**
688 * Used for intercepting any started activity.
689 *
690 * <p> A non-null return value here will be considered a hit for this monitor.
691 * By default this will return {@code null} and subclasses can override this to return
692 * a non-null value if the intent needs to be intercepted.
693 *
694 * <p> Whenever a new activity is started, this method will be called on instances created
695 * using {@link #Instrumentation.ActivityMonitor()} to check if there is a match. In case
696 * of a match, the activity start will be blocked and the returned result will be used.
697 *
698 * @param intent The intent used for starting the activity.
699 * @return The {@link ActivityResult} that needs to be used in case of a match.
700 */
Sudheer Shanka34217512017-04-26 14:49:16 -0700701 public ActivityResult onStartActivity(Intent intent) {
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800702 return null;
703 }
704
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 final boolean match(Context who,
706 Activity activity,
707 Intent intent) {
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800708 if (mIgnoreMatchingSpecificIntents) {
709 return false;
710 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800711 synchronized (this) {
712 if (mWhich != null
713 && mWhich.match(who.getContentResolver(), intent,
714 true, "Instrumentation") < 0) {
715 return false;
716 }
717 if (mClass != null) {
718 String cls = null;
719 if (activity != null) {
720 cls = activity.getClass().getName();
721 } else if (intent.getComponent() != null) {
722 cls = intent.getComponent().getClassName();
723 }
724 if (cls == null || !mClass.equals(cls)) {
725 return false;
726 }
727 }
728 if (activity != null) {
729 mLastActivity = activity;
730 notifyAll();
731 }
732 return true;
733 }
734 }
735 }
736
737 /**
738 * Add a new {@link ActivityMonitor} that will be checked whenever an
739 * activity is started. The monitor is added
740 * after any existing ones; the monitor will be hit only if none of the
741 * existing monitors can themselves handle the Intent.
742 *
743 * @param monitor The new ActivityMonitor to see.
744 *
745 * @see #addMonitor(IntentFilter, ActivityResult, boolean)
746 * @see #checkMonitorHit
747 */
748 public void addMonitor(ActivityMonitor monitor) {
749 synchronized (mSync) {
750 if (mActivityMonitors == null) {
751 mActivityMonitors = new ArrayList();
752 }
753 mActivityMonitors.add(monitor);
754 }
755 }
756
757 /**
758 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
759 * creates an intent filter matching {@link ActivityMonitor} for you and
760 * returns it.
761 *
762 * @param filter The set of intents this monitor is responsible for.
763 * @param result A canned result to return if the monitor is hit; can
764 * be null.
765 * @param block Controls whether the monitor should block the activity
766 * start (returning its canned result) or let the call
767 * proceed.
768 *
769 * @return The newly created and added activity monitor.
770 *
771 * @see #addMonitor(ActivityMonitor)
772 * @see #checkMonitorHit
773 */
774 public ActivityMonitor addMonitor(
775 IntentFilter filter, ActivityResult result, boolean block) {
776 ActivityMonitor am = new ActivityMonitor(filter, result, block);
777 addMonitor(am);
778 return am;
779 }
780
781 /**
782 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
783 * creates a class matching {@link ActivityMonitor} for you and returns it.
784 *
785 * @param cls The activity class this monitor is responsible for.
786 * @param result A canned result to return if the monitor is hit; can
787 * be null.
788 * @param block Controls whether the monitor should block the activity
789 * start (returning its canned result) or let the call
790 * proceed.
791 *
792 * @return The newly created and added activity monitor.
793 *
794 * @see #addMonitor(ActivityMonitor)
795 * @see #checkMonitorHit
796 */
797 public ActivityMonitor addMonitor(
798 String cls, ActivityResult result, boolean block) {
799 ActivityMonitor am = new ActivityMonitor(cls, result, block);
800 addMonitor(am);
801 return am;
802 }
803
804 /**
805 * Test whether an existing {@link ActivityMonitor} has been hit. If the
806 * monitor has been hit at least <var>minHits</var> times, then it will be
807 * removed from the activity monitor list and true returned. Otherwise it
808 * is left as-is and false is returned.
809 *
810 * @param monitor The ActivityMonitor to check.
811 * @param minHits The minimum number of hits required.
812 *
813 * @return True if the hit count has been reached, else false.
814 *
815 * @see #addMonitor
816 */
817 public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
818 waitForIdleSync();
819 synchronized (mSync) {
820 if (monitor.getHits() < minHits) {
821 return false;
822 }
823 mActivityMonitors.remove(monitor);
824 }
825 return true;
826 }
827
828 /**
829 * Wait for an existing {@link ActivityMonitor} to be hit. Once the
830 * monitor has been hit, it is removed from the activity monitor list and
831 * the first created Activity object that matched it is returned.
832 *
833 * @param monitor The ActivityMonitor to wait for.
834 *
835 * @return The Activity object that matched the monitor.
836 */
837 public Activity waitForMonitor(ActivityMonitor monitor) {
838 Activity activity = monitor.waitForActivity();
839 synchronized (mSync) {
840 mActivityMonitors.remove(monitor);
841 }
842 return activity;
843 }
844
845 /**
846 * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
847 * expires. Once the monitor has been hit, it is removed from the activity
848 * monitor list and the first created Activity object that matched it is
849 * returned. If the timeout expires, a null object is returned.
850 *
851 * @param monitor The ActivityMonitor to wait for.
Nimrod Gileadic895a4b2017-03-31 13:21:47 +0100852 * @param timeOut The timeout value in milliseconds.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800853 *
854 * @return The Activity object that matched the monitor.
855 */
856 public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
857 Activity activity = monitor.waitForActivityWithTimeout(timeOut);
858 synchronized (mSync) {
859 mActivityMonitors.remove(monitor);
860 }
861 return activity;
862 }
863
864 /**
865 * Remove an {@link ActivityMonitor} that was previously added with
866 * {@link #addMonitor}.
867 *
868 * @param monitor The monitor to remove.
869 *
870 * @see #addMonitor
871 */
872 public void removeMonitor(ActivityMonitor monitor) {
873 synchronized (mSync) {
874 mActivityMonitors.remove(monitor);
875 }
876 }
877
878 /**
879 * Execute a particular menu item.
880 *
881 * @param targetActivity The activity in question.
882 * @param id The identifier associated with the menu item.
883 * @param flag Additional flags, if any.
884 * @return Whether the invocation was successful (for example, it could be
885 * false if item is disabled).
886 */
887 public boolean invokeMenuActionSync(Activity targetActivity,
888 int id, int flag) {
889 class MenuRunnable implements Runnable {
890 private final Activity activity;
891 private final int identifier;
892 private final int flags;
893 boolean returnValue;
894
895 public MenuRunnable(Activity _activity, int _identifier,
896 int _flags) {
897 activity = _activity;
898 identifier = _identifier;
899 flags = _flags;
900 }
901
902 public void run() {
903 Window win = activity.getWindow();
904
905 returnValue = win.performPanelIdentifierAction(
906 Window.FEATURE_OPTIONS_PANEL,
907 identifier,
908 flags);
909 }
910
911 }
912 MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
913 runOnMainSync(mr);
914 return mr.returnValue;
915 }
916
917 /**
918 * Show the context menu for the currently focused view and executes a
919 * particular context menu item.
920 *
921 * @param targetActivity The activity in question.
922 * @param id The identifier associated with the context menu item.
923 * @param flag Additional flags, if any.
924 * @return Whether the invocation was successful (for example, it could be
925 * false if item is disabled).
926 */
927 public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
928 validateNotAppThread();
929
930 // Bring up context menu for current focus.
931 // It'd be nice to do this through code, but currently ListView depends on
932 // long press to set metadata for its selected child
933
934 final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
935 sendKeySync(downEvent);
936
937 // Need to wait for long press
938 waitForIdleSync();
939 try {
940 Thread.sleep(ViewConfiguration.getLongPressTimeout());
941 } catch (InterruptedException e) {
942 Log.e(TAG, "Could not sleep for long press timeout", e);
943 return false;
944 }
945
946 final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
947 sendKeySync(upEvent);
948
949 // Wait for context menu to appear
950 waitForIdleSync();
951
952 class ContextMenuRunnable implements Runnable {
953 private final Activity activity;
954 private final int identifier;
955 private final int flags;
956 boolean returnValue;
957
958 public ContextMenuRunnable(Activity _activity, int _identifier,
959 int _flags) {
960 activity = _activity;
961 identifier = _identifier;
962 flags = _flags;
963 }
964
965 public void run() {
966 Window win = activity.getWindow();
967 returnValue = win.performContextMenuIdentifierAction(
968 identifier,
969 flags);
970 }
971
972 }
973
974 ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
975 runOnMainSync(cmr);
976 return cmr.returnValue;
977 }
978
979 /**
980 * Sends the key events corresponding to the text to the app being
981 * instrumented.
982 *
983 * @param text The text to be sent.
984 */
985 public void sendStringSync(String text) {
986 if (text == null) {
987 return;
988 }
Jeff Brown6b53e8d2010-11-10 16:03:06 -0800989 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800990
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800991 KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
Svetoslav Ganovc350f162011-11-10 17:54:24 -0800992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800993 if (events != null) {
994 for (int i = 0; i < events.length; i++) {
Svetoslav Ganovf434e372011-11-11 16:50:21 -0800995 // We have to change the time of an event before injecting it because
996 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
997 // time stamp and the system rejects too old events. Hence, it is
998 // possible for an event to become stale before it is injected if it
999 // takes too long to inject the preceding ones.
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001000 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001002 }
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 /**
1006 * Send a key event to the currently focused window/view and wait for it to
1007 * be processed. Finished at some point after the recipient has returned
1008 * from its event processing, though it may <em>not</em> have completely
1009 * finished reacting from the event -- for example, if it needs to update
1010 * its display as a result, it may still be in the process of doing that.
1011 *
1012 * @param event The event to send to the current focus.
1013 */
1014 public void sendKeySync(KeyEvent event) {
1015 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001016
1017 long downTime = event.getDownTime();
1018 long eventTime = event.getEventTime();
1019 int action = event.getAction();
1020 int code = event.getKeyCode();
1021 int repeatCount = event.getRepeatCount();
1022 int metaState = event.getMetaState();
1023 int deviceId = event.getDeviceId();
1024 int scancode = event.getScanCode();
1025 int source = event.getSource();
1026 int flags = event.getFlags();
1027 if (source == InputDevice.SOURCE_UNKNOWN) {
1028 source = InputDevice.SOURCE_KEYBOARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001029 }
Jeff Brownac143512012-04-05 18:57:33 -07001030 if (eventTime == 0) {
1031 eventTime = SystemClock.uptimeMillis();
1032 }
1033 if (downTime == 0) {
1034 downTime = eventTime;
1035 }
1036 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
1037 deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source);
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001038 InputManager.getInstance().injectInputEvent(newEvent,
Jeff Brownac143512012-04-05 18:57:33 -07001039 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 }
1041
1042 /**
1043 * Sends an up and down key event sync to the currently focused window.
1044 *
1045 * @param key The integer keycode for the event.
1046 */
1047 public void sendKeyDownUpSync(int key) {
1048 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
1049 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
1050 }
1051
1052 /**
1053 * Higher-level method for sending both the down and up key events for a
1054 * particular character key code. Equivalent to creating both KeyEvent
1055 * objects by hand and calling {@link #sendKeySync}. The event appears
1056 * as if it came from keyboard 0, the built in one.
1057 *
1058 * @param keyCode The key code of the character to send.
1059 */
1060 public void sendCharacterSync(int keyCode) {
1061 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
1062 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
1063 }
1064
1065 /**
1066 * Dispatch a pointer event. Finished at some point after the recipient has
1067 * returned from its event processing, though it may <em>not</em> have
1068 * completely finished reacting from the event -- for example, if it needs
1069 * to update its display as a result, it may still be in the process of
1070 * doing that.
1071 *
1072 * @param event A motion event describing the pointer action. (As noted in
1073 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
1074 * {@link SystemClock#uptimeMillis()} as the timebase.
1075 */
1076 public void sendPointerSync(MotionEvent event) {
1077 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001078 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
1079 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001080 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001081 InputManager.getInstance().injectInputEvent(event,
1082 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 }
1084
1085 /**
1086 * Dispatch a trackball event. Finished at some point after the recipient has
1087 * returned from its event processing, though it may <em>not</em> have
1088 * completely finished reacting from the event -- for example, if it needs
1089 * to update its display as a result, it may still be in the process of
1090 * doing that.
1091 *
1092 * @param event A motion event describing the trackball action. (As noted in
1093 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
1094 * {@link SystemClock#uptimeMillis()} as the timebase.
1095 */
1096 public void sendTrackballEventSync(MotionEvent event) {
1097 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001098 if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
1099 event.setSource(InputDevice.SOURCE_TRACKBALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001100 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001101 InputManager.getInstance().injectInputEvent(event,
1102 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001103 }
1104
1105 /**
1106 * Perform instantiation of the process's {@link Application} object. The
1107 * default implementation provides the normal system behavior.
1108 *
1109 * @param cl The ClassLoader with which to instantiate the object.
1110 * @param className The name of the class implementing the Application
1111 * object.
1112 * @param context The context to initialize the application with
1113 *
1114 * @return The newly instantiated Application object.
1115 */
1116 public Application newApplication(ClassLoader cl, String className, Context context)
1117 throws InstantiationException, IllegalAccessException,
1118 ClassNotFoundException {
Jason Monka80bfb52017-11-16 17:15:37 -05001119 Application app = getFactory(context.getPackageName())
1120 .instantiateApplication(cl, className);
1121 app.attach(context);
1122 return app;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001123 }
1124
1125 /**
1126 * Perform instantiation of the process's {@link Application} object. The
1127 * default implementation provides the normal system behavior.
1128 *
1129 * @param clazz The class used to create an Application object from.
1130 * @param context The context to initialize the application with
1131 *
1132 * @return The newly instantiated Application object.
1133 */
1134 static public Application newApplication(Class<?> clazz, Context context)
1135 throws InstantiationException, IllegalAccessException,
1136 ClassNotFoundException {
1137 Application app = (Application)clazz.newInstance();
1138 app.attach(context);
1139 return app;
1140 }
1141
1142 /**
1143 * Perform calling of the application's {@link Application#onCreate}
1144 * method. The default implementation simply calls through to that method.
Dianne Hackborn6ae8d182012-05-23 13:12:42 -07001145 *
1146 * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
1147 * Often instrumentation tests start their test thread in onCreate(); you
1148 * need to be careful of races between these. (Well between it and
1149 * everything else, but let's start here.)
1150 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 * @param app The application being created.
1152 */
1153 public void callApplicationOnCreate(Application app) {
1154 app.onCreate();
1155 }
1156
1157 /**
1158 * Perform instantiation of an {@link Activity} object. This method is intended for use with
1159 * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
Felipe Leme545569d2016-01-11 16:27:58 -08001160 * 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 -08001161 *
1162 * @param clazz The Class of the desired Activity
1163 * @param context The base context for the activity to use
1164 * @param token The token for this activity to communicate with
1165 * @param application The application object (if any)
1166 * @param intent The intent that started this Activity
1167 * @param info ActivityInfo from the manifest
1168 * @param title The title, typically retrieved from the ActivityInfo record
1169 * @param parent The parent Activity (if any)
1170 * @param id The embedded Id (if any)
1171 * @param lastNonConfigurationInstance Arbitrary object that will be
1172 * available via {@link Activity#getLastNonConfigurationInstance()
1173 * Activity.getLastNonConfigurationInstance()}.
1174 * @return Returns the instantiated activity
1175 * @throws InstantiationException
1176 * @throws IllegalAccessException
1177 */
1178 public Activity newActivity(Class<?> clazz, Context context,
1179 IBinder token, Application application, Intent intent, ActivityInfo info,
1180 CharSequence title, Activity parent, String id,
1181 Object lastNonConfigurationInstance) throws InstantiationException,
1182 IllegalAccessException {
1183 Activity activity = (Activity)clazz.newInstance();
1184 ActivityThread aThread = null;
Andrii Kulian51c1b672017-04-07 18:39:32 -07001185 activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001186 info, title, parent, id,
1187 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
Andrii Kulian51c1b672017-04-07 18:39:32 -07001188 new Configuration(), null /* referrer */, null /* voiceInteractor */,
1189 null /* window */, null /* activityConfigCallback */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 return activity;
1191 }
1192
1193 /**
1194 * Perform instantiation of the process's {@link Activity} object. The
1195 * default implementation provides the normal system behavior.
1196 *
1197 * @param cl The ClassLoader with which to instantiate the object.
1198 * @param className The name of the class implementing the Activity
1199 * object.
1200 * @param intent The Intent object that specified the activity class being
1201 * instantiated.
1202 *
1203 * @return The newly instantiated Activity object.
1204 */
1205 public Activity newActivity(ClassLoader cl, String className,
1206 Intent intent)
1207 throws InstantiationException, IllegalAccessException,
1208 ClassNotFoundException {
Jason Monka80bfb52017-11-16 17:15:37 -05001209 String pkg = intent.getComponent().getPackageName();
1210 return getFactory(pkg).instantiateActivity(cl, className, intent);
1211 }
1212
1213 private AppComponentFactory getFactory(String pkg) {
Jason Monk24d12a32017-12-21 10:39:17 -05001214 if (mThread == null) {
1215 Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
1216 + " disabling AppComponentFactory", new Throwable());
1217 return AppComponentFactory.DEFAULT;
1218 }
Jeff Hamilton7541ca4d2017-10-24 15:20:43 -04001219 LoadedApk loadedApk = mThread.peekLoadedApk(pkg, true);
Jason Monka80bfb52017-11-16 17:15:37 -05001220 // This is in the case of starting up "android".
Jeff Hamilton7541ca4d2017-10-24 15:20:43 -04001221 if (loadedApk == null) loadedApk = mThread.getSystemContext().mLoadedApk;
1222 return loadedApk.getAppFactory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 }
1224
Craig Mautnera0026042014-04-23 11:45:37 -07001225 private void prePerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 if (mWaitingActivities != null) {
1227 synchronized (mSync) {
1228 final int N = mWaitingActivities.size();
1229 for (int i=0; i<N; i++) {
1230 final ActivityWaiter aw = mWaitingActivities.get(i);
1231 final Intent intent = aw.intent;
1232 if (intent.filterEquals(activity.getIntent())) {
1233 aw.activity = activity;
1234 mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1235 }
1236 }
1237 }
1238 }
Craig Mautnera0026042014-04-23 11:45:37 -07001239 }
1240
1241 private void postPerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001242 if (mActivityMonitors != null) {
1243 synchronized (mSync) {
1244 final int N = mActivityMonitors.size();
1245 for (int i=0; i<N; i++) {
1246 final ActivityMonitor am = mActivityMonitors.get(i);
1247 am.match(activity, activity, activity.getIntent());
1248 }
1249 }
1250 }
1251 }
Craig Mautnera0026042014-04-23 11:45:37 -07001252
1253 /**
1254 * Perform calling of an activity's {@link Activity#onCreate}
1255 * method. The default implementation simply calls through to that method.
1256 *
1257 * @param activity The activity being created.
1258 * @param icicle The previously frozen state (or null) to pass through to onCreate().
1259 */
1260 public void callActivityOnCreate(Activity activity, Bundle icicle) {
1261 prePerformCreate(activity);
1262 activity.performCreate(icicle);
1263 postPerformCreate(activity);
1264 }
1265
1266 /**
1267 * Perform calling of an activity's {@link Activity#onCreate}
1268 * method. The default implementation simply calls through to that method.
1269 * @param activity The activity being created.
1270 * @param icicle The previously frozen state (or null) to pass through to
1271 * @param persistentState The previously persisted state (or null)
1272 */
1273 public void callActivityOnCreate(Activity activity, Bundle icicle,
1274 PersistableBundle persistentState) {
1275 prePerformCreate(activity);
1276 activity.performCreate(icicle, persistentState);
1277 postPerformCreate(activity);
1278 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279
1280 public void callActivityOnDestroy(Activity activity) {
Brett Chabot18f9ce02010-05-12 12:41:50 -07001281 // TODO: the following block causes intermittent hangs when using startActivity
1282 // temporarily comment out until root cause is fixed (bug 2630683)
1283// if (mWaitingActivities != null) {
1284// synchronized (mSync) {
1285// final int N = mWaitingActivities.size();
1286// for (int i=0; i<N; i++) {
1287// final ActivityWaiter aw = mWaitingActivities.get(i);
1288// final Intent intent = aw.intent;
1289// if (intent.filterEquals(activity.getIntent())) {
1290// aw.activity = activity;
1291// mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1292// }
1293// }
1294// }
1295// }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001296
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001297 activity.performDestroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001298 }
1299
1300 /**
1301 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1302 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001303 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001304 * @param activity The activity being restored.
1305 * @param savedInstanceState The previously saved state being restored.
1306 */
1307 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) {
1308 activity.performRestoreInstanceState(savedInstanceState);
1309 }
1310
1311 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001312 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1313 * method. The default implementation simply calls through to that method.
1314 *
1315 * @param activity The activity being restored.
1316 * @param savedInstanceState The previously saved state being restored.
1317 * @param persistentState The previously persisted state (or null)
1318 */
1319 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState,
1320 PersistableBundle persistentState) {
1321 activity.performRestoreInstanceState(savedInstanceState, persistentState);
1322 }
1323
1324 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001325 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1326 * The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001327 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001328 * @param activity The activity being created.
1329 * @param icicle The previously frozen state (or null) to pass through to
1330 * onPostCreate().
1331 */
1332 public void callActivityOnPostCreate(Activity activity, Bundle icicle) {
1333 activity.onPostCreate(icicle);
1334 }
1335
1336 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001337 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1338 * The default implementation simply calls through to that method.
1339 *
1340 * @param activity The activity being created.
1341 * @param icicle The previously frozen state (or null) to pass through to
1342 * onPostCreate().
1343 */
1344 public void callActivityOnPostCreate(Activity activity, Bundle icicle,
1345 PersistableBundle persistentState) {
1346 activity.onPostCreate(icicle, persistentState);
1347 }
1348
1349 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001350 * Perform calling of an activity's {@link Activity#onNewIntent}
1351 * method. The default implementation simply calls through to that method.
1352 *
1353 * @param activity The activity receiving a new Intent.
1354 * @param intent The new intent being received.
1355 */
1356 public void callActivityOnNewIntent(Activity activity, Intent intent) {
Winson Chung298f95b2017-08-10 15:57:18 -07001357 activity.performNewIntent(intent);
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001358 }
1359
1360 /**
1361 * @hide
1362 */
1363 public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001364 final String oldReferrer = activity.mReferrer;
1365 try {
Dianne Hackborn80b1c562014-12-09 20:22:08 -08001366 if (intent != null) {
1367 activity.mReferrer = intent.mReferrer;
1368 }
1369 callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001370 } finally {
1371 activity.mReferrer = oldReferrer;
1372 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001373 }
1374
1375 /**
1376 * Perform calling of an activity's {@link Activity#onStart}
1377 * method. The default implementation simply calls through to that method.
1378 *
1379 * @param activity The activity being started.
1380 */
1381 public void callActivityOnStart(Activity activity) {
1382 activity.onStart();
1383 }
1384
1385 /**
1386 * Perform calling of an activity's {@link Activity#onRestart}
1387 * method. The default implementation simply calls through to that method.
1388 *
1389 * @param activity The activity being restarted.
1390 */
1391 public void callActivityOnRestart(Activity activity) {
1392 activity.onRestart();
1393 }
1394
1395 /**
1396 * Perform calling of an activity's {@link Activity#onResume} method. The
1397 * default implementation simply calls through to that method.
1398 *
1399 * @param activity The activity being resumed.
1400 */
1401 public void callActivityOnResume(Activity activity) {
Jeff Hamilton52d32032011-01-08 15:31:26 -06001402 activity.mResumed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001403 activity.onResume();
1404
1405 if (mActivityMonitors != null) {
1406 synchronized (mSync) {
1407 final int N = mActivityMonitors.size();
1408 for (int i=0; i<N; i++) {
1409 final ActivityMonitor am = mActivityMonitors.get(i);
1410 am.match(activity, activity, activity.getIntent());
1411 }
1412 }
1413 }
1414 }
1415
1416 /**
1417 * Perform calling of an activity's {@link Activity#onStop}
1418 * method. The default implementation simply calls through to that method.
1419 *
1420 * @param activity The activity being stopped.
1421 */
1422 public void callActivityOnStop(Activity activity) {
1423 activity.onStop();
1424 }
1425
1426 /**
Newton Allenc5027442013-08-13 11:22:32 -07001427 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1428 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001429 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001430 * @param activity The activity being saved.
1431 * @param outState The bundle to pass to the call.
1432 */
1433 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) {
1434 activity.performSaveInstanceState(outState);
1435 }
1436
1437 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001438 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1439 * method. The default implementation simply calls through to that method.
1440 * @param activity The activity being saved.
1441 * @param outState The bundle to pass to the call.
1442 * @param outPersistentState The persistent bundle to pass to the call.
1443 */
1444 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState,
1445 PersistableBundle outPersistentState) {
1446 activity.performSaveInstanceState(outState, outPersistentState);
1447 }
1448
1449 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001450 * Perform calling of an activity's {@link Activity#onPause} method. The
1451 * default implementation simply calls through to that method.
1452 *
1453 * @param activity The activity being paused.
1454 */
1455 public void callActivityOnPause(Activity activity) {
1456 activity.performPause();
1457 }
1458
1459 /**
1460 * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
1461 * The default implementation simply calls through to that method.
1462 *
1463 * @param activity The activity being notified that the user has navigated away
1464 */
1465 public void callActivityOnUserLeaving(Activity activity) {
1466 activity.performUserLeaving();
1467 }
1468
1469 /*
1470 * Starts allocation counting. This triggers a gc and resets the counts.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001471 *
1472 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001474 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001475 public void startAllocCounting() {
1476 // Before we start trigger a GC and reset the debug counts. Run the
1477 // finalizers and another GC before starting and stopping the alloc
1478 // counts. This will free up any objects that were just sitting around
1479 // waiting for their finalizers to be run.
1480 Runtime.getRuntime().gc();
1481 Runtime.getRuntime().runFinalization();
1482 Runtime.getRuntime().gc();
1483
1484 Debug.resetAllCounts();
1485
1486 // start the counts
1487 Debug.startAllocCounting();
1488 }
1489
1490 /*
1491 * Stops allocation counting.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001492 *
1493 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001495 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001496 public void stopAllocCounting() {
1497 Runtime.getRuntime().gc();
1498 Runtime.getRuntime().runFinalization();
1499 Runtime.getRuntime().gc();
1500 Debug.stopAllocCounting();
1501 }
1502
1503 /**
1504 * If Results already contains Key, it appends Value to the key's ArrayList
1505 * associated with the key. If the key doesn't already exist in results, it
1506 * adds the key/value pair to results.
1507 */
1508 private void addValue(String key, int value, Bundle results) {
1509 if (results.containsKey(key)) {
1510 List<Integer> list = results.getIntegerArrayList(key);
1511 if (list != null) {
1512 list.add(value);
1513 }
1514 } else {
1515 ArrayList<Integer> list = new ArrayList<Integer>();
1516 list.add(value);
1517 results.putIntegerArrayList(key, list);
1518 }
1519 }
1520
1521 /**
1522 * Returns a bundle with the current results from the allocation counting.
1523 */
1524 public Bundle getAllocCounts() {
1525 Bundle results = new Bundle();
1526 results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
1527 results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
1528 results.putLong("global_freed_count", Debug.getGlobalFreedCount());
1529 results.putLong("global_freed_size", Debug.getGlobalFreedSize());
1530 results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
1531 return results;
1532 }
1533
1534 /**
1535 * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
1536 * reported are the number of send and the number of received transactions.
1537 */
1538 public Bundle getBinderCounts() {
1539 Bundle results = new Bundle();
1540 results.putLong("sent_transactions", Debug.getBinderSentTransactions());
1541 results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
1542 return results;
1543 }
1544
1545 /**
1546 * Description of a Activity execution result to return to the original
1547 * activity.
1548 */
1549 public static final class ActivityResult {
1550 /**
1551 * Create a new activity result. See {@link Activity#setResult} for
1552 * more information.
1553 *
1554 * @param resultCode The result code to propagate back to the
1555 * originating activity, often RESULT_CANCELED or RESULT_OK
1556 * @param resultData The data to propagate back to the originating
1557 * activity.
1558 */
1559 public ActivityResult(int resultCode, Intent resultData) {
1560 mResultCode = resultCode;
1561 mResultData = resultData;
1562 }
1563
1564 /**
1565 * Retrieve the result code contained in this result.
1566 */
1567 public int getResultCode() {
1568 return mResultCode;
1569 }
1570
1571 /**
1572 * Retrieve the data contained in this result.
1573 */
1574 public Intent getResultData() {
1575 return mResultData;
1576 }
1577
1578 private final int mResultCode;
1579 private final Intent mResultData;
1580 }
1581
1582 /**
1583 * Execute a startActivity call made by the application. The default
1584 * implementation takes care of updating any active {@link ActivityMonitor}
1585 * objects and dispatches this call to the system activity manager; you can
1586 * override this to watch for the application to start an activity, and
1587 * modify what happens when it does.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001588 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001589 * <p>This method returns an {@link ActivityResult} object, which you can
1590 * use when intercepting application calls to avoid performing the start
1591 * activity action but still return the result the application is
1592 * expecting. To do this, override this method to catch the call to start
1593 * activity so that it returns a new ActivityResult containing the results
1594 * you would like the application to see, and don't call up to the super
1595 * class. Note that an application is only expecting a result if
1596 * <var>requestCode</var> is &gt;= 0.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001597 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 * <p>This method throws {@link android.content.ActivityNotFoundException}
1599 * if there was no Activity found to run the given Intent.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001600 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 * @param who The Context from which the activity is being started.
1602 * @param contextThread The main thread of the Context from which the activity
1603 * is being started.
1604 * @param token Internal token identifying to the system who is starting
1605 * the activity; may be null.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001606 * @param target Which activity is performing the start (and thus receiving
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607 * any result); may be null if this call is not being made
1608 * from an activity.
1609 * @param intent The actual Intent to start.
1610 * @param requestCode Identifier for this request's result; less than zero
1611 * if the caller is not expecting a result.
Dianne Hackborna4972e92012-03-14 10:38:05 -07001612 * @param options Addition options.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001613 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001614 * @return To force the return of a particular result, return an
1615 * ActivityResult object containing the desired data; otherwise
1616 * return null. The default implementation always returns null.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001617 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618 * @throws android.content.ActivityNotFoundException
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001619 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001620 * @see Activity#startActivity(Intent)
1621 * @see Activity#startActivityForResult(Intent, int)
1622 * @see Activity#startActivityFromChild
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001623 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001624 * {@hide}
1625 */
1626 public ActivityResult execStartActivity(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001627 Context who, IBinder contextThread, IBinder token, Activity target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001628 Intent intent, int requestCode, Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 IApplicationThread whoThread = (IApplicationThread) contextThread;
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001630 Uri referrer = target != null ? target.onProvideReferrer() : null;
1631 if (referrer != null) {
1632 intent.putExtra(Intent.EXTRA_REFERRER, referrer);
1633 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001634 if (mActivityMonitors != null) {
1635 synchronized (mSync) {
1636 final int N = mActivityMonitors.size();
1637 for (int i=0; i<N; i++) {
1638 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001639 ActivityResult result = null;
1640 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001641 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001642 }
1643 if (result != null) {
1644 am.mHits++;
1645 return result;
1646 } else if (am.match(who, null, intent)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 am.mHits++;
1648 if (am.isBlocking()) {
1649 return requestCode >= 0 ? am.getResult() : null;
1650 }
1651 break;
1652 }
1653 }
1654 }
1655 }
1656 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001657 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001658 intent.prepareToLeaveProcess(who);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001659 int result = ActivityManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001660 .startActivity(whoThread, who.getBasePackageName(), intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001661 intent.resolveTypeIfNeeded(who.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07001662 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001663 requestCode, 0, null, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 checkStartActivityResult(result, intent);
1665 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001666 throw new RuntimeException("Failure from system", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 }
1668 return null;
1669 }
1670
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001671 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001672 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001673 * but accepts an array of activities to be started. Note that active
1674 * {@link ActivityMonitor} objects only match against the first activity in
1675 * the array.
1676 *
1677 * {@hide}
1678 */
1679 public void execStartActivities(Context who, IBinder contextThread,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001680 IBinder token, Activity target, Intent[] intents, Bundle options) {
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001681 execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
1682 UserHandle.myUserId());
1683 }
1684
1685 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001686 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001687 * but accepts an array of activities to be started. Note that active
1688 * {@link ActivityMonitor} objects only match against the first activity in
1689 * the array.
1690 *
1691 * {@hide}
1692 */
1693 public void execStartActivitiesAsUser(Context who, IBinder contextThread,
1694 IBinder token, Activity target, Intent[] intents, Bundle options,
1695 int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001696 IApplicationThread whoThread = (IApplicationThread) contextThread;
1697 if (mActivityMonitors != null) {
1698 synchronized (mSync) {
1699 final int N = mActivityMonitors.size();
1700 for (int i=0; i<N; i++) {
1701 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001702 ActivityResult result = null;
1703 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001704 result = am.onStartActivity(intents[0]);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001705 }
1706 if (result != null) {
1707 am.mHits++;
1708 return;
1709 } else if (am.match(who, null, intents[0])) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001710 am.mHits++;
1711 if (am.isBlocking()) {
1712 return;
1713 }
1714 break;
1715 }
1716 }
1717 }
1718 }
1719 try {
1720 String[] resolvedTypes = new String[intents.length];
1721 for (int i=0; i<intents.length; i++) {
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001722 intents[i].migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001723 intents[i].prepareToLeaveProcess(who);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001724 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
1725 }
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001726 int result = ActivityManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001727 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
1728 token, options, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001729 checkStartActivityResult(result, intents[0]);
1730 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001731 throw new RuntimeException("Failure from system", e);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001732 }
1733 }
1734
1735 /**
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001736 * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001737 * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)},
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001738 * but for calls from a {#link Fragment}.
1739 *
1740 * @param who The Context from which the activity is being started.
1741 * @param contextThread The main thread of the Context from which the activity
1742 * is being started.
1743 * @param token Internal token identifying to the system who is starting
1744 * the activity; may be null.
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001745 * @param target Which element is performing the start (and thus receiving
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001746 * any result).
1747 * @param intent The actual Intent to start.
1748 * @param requestCode Identifier for this request's result; less than zero
1749 * if the caller is not expecting a result.
1750 *
1751 * @return To force the return of a particular result, return an
1752 * ActivityResult object containing the desired data; otherwise
1753 * return null. The default implementation always returns null.
1754 *
1755 * @throws android.content.ActivityNotFoundException
1756 *
1757 * @see Activity#startActivity(Intent)
1758 * @see Activity#startActivityForResult(Intent, int)
1759 * @see Activity#startActivityFromChild
1760 *
1761 * {@hide}
1762 */
1763 public ActivityResult execStartActivity(
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001764 Context who, IBinder contextThread, IBinder token, String target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001765 Intent intent, int requestCode, Bundle options) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001766 IApplicationThread whoThread = (IApplicationThread) contextThread;
1767 if (mActivityMonitors != null) {
1768 synchronized (mSync) {
1769 final int N = mActivityMonitors.size();
1770 for (int i=0; i<N; i++) {
1771 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001772 ActivityResult result = null;
1773 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001774 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001775 }
1776 if (result != null) {
1777 am.mHits++;
1778 return result;
1779 } else if (am.match(who, null, intent)) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001780 am.mHits++;
1781 if (am.isBlocking()) {
1782 return requestCode >= 0 ? am.getResult() : null;
1783 }
1784 break;
1785 }
1786 }
1787 }
1788 }
1789 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001790 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001791 intent.prepareToLeaveProcess(who);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001792 int result = ActivityManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001793 .startActivity(whoThread, who.getBasePackageName(), intent,
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001794 intent.resolveTypeIfNeeded(who.getContentResolver()),
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001795 token, target, requestCode, 0, null, options);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001796 checkStartActivityResult(result, intent);
1797 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001798 throw new RuntimeException("Failure from system", e);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001799 }
1800 return null;
1801 }
1802
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001803 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001804 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
1805 * but for starting as a particular user.
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001806 *
1807 * @param who The Context from which the activity is being started.
1808 * @param contextThread The main thread of the Context from which the activity
1809 * is being started.
1810 * @param token Internal token identifying to the system who is starting
1811 * the activity; may be null.
1812 * @param target Which fragment is performing the start (and thus receiving
1813 * any result).
1814 * @param intent The actual Intent to start.
1815 * @param requestCode Identifier for this request's result; less than zero
1816 * if the caller is not expecting a result.
1817 *
1818 * @return To force the return of a particular result, return an
1819 * ActivityResult object containing the desired data; otherwise
1820 * return null. The default implementation always returns null.
1821 *
1822 * @throws android.content.ActivityNotFoundException
1823 *
1824 * @see Activity#startActivity(Intent)
1825 * @see Activity#startActivityForResult(Intent, int)
1826 * @see Activity#startActivityFromChild
1827 *
1828 * {@hide}
1829 */
1830 public ActivityResult execStartActivity(
Tony Mak96d26fe2017-04-11 20:05:39 +01001831 Context who, IBinder contextThread, IBinder token, String resultWho,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001832 Intent intent, int requestCode, Bundle options, UserHandle user) {
1833 IApplicationThread whoThread = (IApplicationThread) contextThread;
1834 if (mActivityMonitors != null) {
1835 synchronized (mSync) {
1836 final int N = mActivityMonitors.size();
1837 for (int i=0; i<N; i++) {
1838 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001839 ActivityResult result = null;
1840 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001841 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001842 }
1843 if (result != null) {
1844 am.mHits++;
1845 return result;
1846 } else if (am.match(who, null, intent)) {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001847 am.mHits++;
1848 if (am.isBlocking()) {
1849 return requestCode >= 0 ? am.getResult() : null;
1850 }
1851 break;
1852 }
1853 }
1854 }
1855 }
1856 try {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001857 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001858 intent.prepareToLeaveProcess(who);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001859 int result = ActivityManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001860 .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001861 intent.resolveTypeIfNeeded(who.getContentResolver()),
Tony Mak96d26fe2017-04-11 20:05:39 +01001862 token, resultWho,
Jeff Hao1b012d32014-08-20 10:35:34 -07001863 requestCode, 0, null, options, user.getIdentifier());
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001864 checkStartActivityResult(result, intent);
1865 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001866 throw new RuntimeException("Failure from system", e);
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001867 }
1868 return null;
1869 }
1870
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001871 /**
1872 * Special version!
1873 * @hide
1874 */
1875 public ActivityResult execStartActivityAsCaller(
1876 Context who, IBinder contextThread, IBinder token, Activity target,
Geoffrey Pitsch88f3d4d2017-11-22 13:31:11 -05001877 Intent intent, int requestCode, Bundle options, IBinder permissionToken,
1878 boolean ignoreTargetSecurity, int userId) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001879 IApplicationThread whoThread = (IApplicationThread) contextThread;
1880 if (mActivityMonitors != null) {
1881 synchronized (mSync) {
1882 final int N = mActivityMonitors.size();
1883 for (int i=0; i<N; i++) {
1884 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001885 ActivityResult result = null;
1886 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001887 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001888 }
1889 if (result != null) {
1890 am.mHits++;
1891 return result;
1892 } else if (am.match(who, null, intent)) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001893 am.mHits++;
1894 if (am.isBlocking()) {
1895 return requestCode >= 0 ? am.getResult() : null;
1896 }
1897 break;
1898 }
1899 }
1900 }
1901 }
1902 try {
1903 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001904 intent.prepareToLeaveProcess(who);
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001905 int result = ActivityManager.getService()
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001906 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
1907 intent.resolveTypeIfNeeded(who.getContentResolver()),
1908 token, target != null ? target.mEmbeddedID : null,
Geoffrey Pitsch88f3d4d2017-11-22 13:31:11 -05001909 requestCode, 0, null, options, permissionToken,
1910 ignoreTargetSecurity, userId);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001911 checkStartActivityResult(result, intent);
1912 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001913 throw new RuntimeException("Failure from system", e);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001914 }
1915 return null;
1916 }
1917
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001918 /**
1919 * Special version!
1920 * @hide
1921 */
1922 public void execStartActivityFromAppTask(
1923 Context who, IBinder contextThread, IAppTask appTask,
1924 Intent intent, Bundle options) {
1925 IApplicationThread whoThread = (IApplicationThread) contextThread;
1926 if (mActivityMonitors != null) {
1927 synchronized (mSync) {
1928 final int N = mActivityMonitors.size();
1929 for (int i=0; i<N; i++) {
1930 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001931 ActivityResult result = null;
1932 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001933 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001934 }
1935 if (result != null) {
1936 am.mHits++;
1937 return;
1938 } else if (am.match(who, null, intent)) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001939 am.mHits++;
1940 if (am.isBlocking()) {
1941 return;
1942 }
1943 break;
1944 }
1945 }
1946 }
1947 }
1948 try {
1949 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001950 intent.prepareToLeaveProcess(who);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001951 int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
1952 intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options);
1953 checkStartActivityResult(result, intent);
1954 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001955 throw new RuntimeException("Failure from system", e);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001956 }
1957 return;
1958 }
1959
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001960 /*package*/ final void init(ActivityThread thread,
1961 Context instrContext, Context appContext, ComponentName component,
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001962 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001963 mThread = thread;
1964 mMessageQueue = mThread.getLooper().myQueue();
1965 mInstrContext = instrContext;
1966 mAppContext = appContext;
1967 mComponent = component;
1968 mWatcher = watcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08001969 mUiAutomationConnection = uiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001970 }
1971
Jason Monka80bfb52017-11-16 17:15:37 -05001972 /**
1973 * Only sets the ActivityThread up, keeps everything else null because app is not being
1974 * instrumented.
1975 */
1976 final void basicInit(ActivityThread thread) {
1977 mThread = thread;
1978 }
1979
Dianne Hackborn91097de2014-04-04 18:02:06 -07001980 /** @hide */
1981 public static void checkStartActivityResult(int res, Object intent) {
Bryce Lee7f936862017-05-09 15:33:18 -07001982 if (!ActivityManager.isStartResultFatalError(res)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001983 return;
1984 }
Amith Yamasani42449782016-04-19 11:45:51 -07001985
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001986 switch (res) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07001987 case ActivityManager.START_INTENT_NOT_RESOLVED:
1988 case ActivityManager.START_CLASS_NOT_FOUND:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001989 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001990 throw new ActivityNotFoundException(
1991 "Unable to find explicit activity class "
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07001992 + ((Intent)intent).getComponent().toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001993 + "; have you declared this activity in your AndroidManifest.xml?");
1994 throw new ActivityNotFoundException(
1995 "No Activity found to handle " + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07001996 case ActivityManager.START_PERMISSION_DENIED:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001997 throw new SecurityException("Not allowed to start activity "
1998 + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07001999 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002000 throw new AndroidRuntimeException(
2001 "FORWARD_RESULT_FLAG used while also requesting a result");
Dianne Hackborna4972e92012-03-14 10:38:05 -07002002 case ActivityManager.START_NOT_ACTIVITY:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002003 throw new IllegalArgumentException(
2004 "PendingIntent is not an activity");
Dianne Hackborn91097de2014-04-04 18:02:06 -07002005 case ActivityManager.START_NOT_VOICE_COMPATIBLE:
2006 throw new SecurityException(
2007 "Starting under voice control not allowed for: " + intent);
Amith Yamasani42449782016-04-19 11:45:51 -07002008 case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
2009 throw new IllegalStateException(
2010 "Session calling startVoiceActivity does not match active session");
2011 case ActivityManager.START_VOICE_HIDDEN_SESSION:
2012 throw new IllegalStateException(
2013 "Cannot start voice activity on a hidden session");
Winson Chungfc3ec4c2017-06-01 15:35:48 -07002014 case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
2015 throw new IllegalStateException(
2016 "Session calling startAssistantActivity does not match active session");
2017 case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
2018 throw new IllegalStateException(
2019 "Cannot start assistant activity on a hidden session");
Amith Yamasani42449782016-04-19 11:45:51 -07002020 case ActivityManager.START_CANCELED:
2021 throw new AndroidRuntimeException("Activity could not be started for "
2022 + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002023 default:
2024 throw new AndroidRuntimeException("Unknown error code "
2025 + res + " when starting " + intent);
2026 }
2027 }
Chong Zhang45c25ce2015-08-10 22:18:26 -07002028
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002029 private final void validateNotAppThread() {
Kristian Monsen0a303282013-01-18 14:50:07 -08002030 if (Looper.myLooper() == Looper.getMainLooper()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002031 throw new RuntimeException(
2032 "This method can not be called from the main application thread");
2033 }
2034 }
2035
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002036 /**
Phil Weaverd8e88832016-03-28 17:26:25 -07002037 * Gets the {@link UiAutomation} instance with no flags set.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002038 * <p>
2039 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
2040 * work across application boundaries while the APIs exposed by the instrumentation
2041 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
2042 * not allow you to inject the event in an app different from the instrumentation
2043 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
2044 * will work regardless of the current application.
2045 * </p>
2046 * <p>
2047 * A typical test case should be using either the {@link UiAutomation} or
2048 * {@link Instrumentation} APIs. Using both APIs at the same time is not
2049 * a mistake by itself but a client has to be aware of the APIs limitations.
2050 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07002051 * <p>
2052 * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different
2053 * flags, the flags on that instance will be changed, and then it will be returned.
2054 * </p>
2055 * @return The UI automation instance.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002056 *
2057 * @see UiAutomation
2058 */
2059 public UiAutomation getUiAutomation() {
Phil Weaverd8e88832016-03-28 17:26:25 -07002060 return getUiAutomation(0);
Phil Weaver1dd87222016-01-26 17:15:15 -08002061 }
2062
2063 /**
2064 * Gets the {@link UiAutomation} instance with flags set.
2065 * <p>
Phil Weaver1dd87222016-01-26 17:15:15 -08002066 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
2067 * work across application boundaries while the APIs exposed by the instrumentation
2068 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
2069 * not allow you to inject the event in an app different from the instrumentation
2070 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
2071 * will work regardless of the current application.
2072 * </p>
2073 * <p>
2074 * A typical test case should be using either the {@link UiAutomation} or
2075 * {@link Instrumentation} APIs. Using both APIs at the same time is not
2076 * a mistake by itself but a client has to be aware of the APIs limitations.
2077 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07002078 * <p>
2079 * If a {@link UiAutomation} exists with different flags, the flags on that instance will be
2080 * changed, and then it will be returned.
2081 * </p>
Phil Weaver1dd87222016-01-26 17:15:15 -08002082 *
2083 * @param flags The flags to be passed to the UiAutomation, for example
2084 * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
2085 *
2086 * @return The UI automation instance.
2087 *
2088 * @see UiAutomation
2089 */
Phil Weaver35841682016-03-09 09:52:51 -08002090 public UiAutomation getUiAutomation(@UiAutomationFlags int flags) {
Phil Weaverd8e88832016-03-28 17:26:25 -07002091 boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed());
2092
Phil Weaver1dd87222016-01-26 17:15:15 -08002093 if (mUiAutomationConnection != null) {
Phil Weaverd8e88832016-03-28 17:26:25 -07002094 if (!mustCreateNewAutomation && (mUiAutomation.getFlags() == flags)) {
2095 return mUiAutomation;
2096 }
2097 if (mustCreateNewAutomation) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002098 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
2099 mUiAutomationConnection);
Phil Weaver1dd87222016-01-26 17:15:15 -08002100 } else {
Phil Weaverd8e88832016-03-28 17:26:25 -07002101 mUiAutomation.disconnect();
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002102 }
Phil Weaverd8e88832016-03-28 17:26:25 -07002103 mUiAutomation.connect(flags);
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002104 return mUiAutomation;
2105 }
2106 return null;
2107 }
2108
Jason Monk5be50f72017-03-10 10:57:34 -05002109 /**
2110 * Takes control of the execution of messages on the specified looper until
2111 * {@link TestLooperManager#release} is called.
2112 */
2113 public TestLooperManager acquireLooperManager(Looper looper) {
2114 checkInstrumenting("acquireLooperManager");
2115 return new TestLooperManager(looper);
2116 }
2117
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002118 private final class InstrumentationThread extends Thread {
2119 public InstrumentationThread(String name) {
2120 super(name);
2121 }
2122 public void run() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002123 try {
2124 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
2125 } catch (RuntimeException e) {
Phil Weaver1dd87222016-01-26 17:15:15 -08002126 Log.w(TAG, "Exception setting priority of instrumentation thread "
2127 + Process.myTid(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002128 }
2129 if (mAutomaticPerformanceSnapshots) {
2130 startPerformanceSnapshot();
2131 }
2132 onStart();
2133 }
2134 }
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002135
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002136 private static final class EmptyRunnable implements Runnable {
2137 public void run() {
2138 }
2139 }
2140
2141 private static final class SyncRunnable implements Runnable {
2142 private final Runnable mTarget;
2143 private boolean mComplete;
2144
2145 public SyncRunnable(Runnable target) {
2146 mTarget = target;
2147 }
2148
2149 public void run() {
2150 mTarget.run();
2151 synchronized (this) {
2152 mComplete = true;
2153 notifyAll();
2154 }
2155 }
2156
2157 public void waitForComplete() {
2158 synchronized (this) {
2159 while (!mComplete) {
2160 try {
2161 wait();
2162 } catch (InterruptedException e) {
2163 }
2164 }
2165 }
2166 }
2167 }
2168
2169 private static final class ActivityWaiter {
2170 public final Intent intent;
2171 public Activity activity;
2172
2173 public ActivityWaiter(Intent _intent) {
2174 intent = _intent;
2175 }
2176 }
2177
2178 private final class ActivityGoing implements MessageQueue.IdleHandler {
2179 private final ActivityWaiter mWaiter;
2180
2181 public ActivityGoing(ActivityWaiter waiter) {
2182 mWaiter = waiter;
2183 }
2184
2185 public final boolean queueIdle() {
2186 synchronized (mSync) {
2187 mWaitingActivities.remove(mWaiter);
2188 mSync.notifyAll();
2189 }
2190 return false;
2191 }
2192 }
2193
2194 private static final class Idler implements MessageQueue.IdleHandler {
2195 private final Runnable mCallback;
2196 private boolean mIdle;
2197
2198 public Idler(Runnable callback) {
2199 mCallback = callback;
2200 mIdle = false;
2201 }
2202
2203 public final boolean queueIdle() {
2204 if (mCallback != null) {
2205 mCallback.run();
2206 }
2207 synchronized (this) {
2208 mIdle = true;
2209 notifyAll();
2210 }
2211 return false;
2212 }
2213
2214 public void waitForIdle() {
2215 synchronized (this) {
2216 while (!mIdle) {
2217 try {
2218 wait();
2219 } catch (InterruptedException e) {
2220 }
2221 }
2222 }
2223 }
2224 }
2225}