blob: dda5569a26b3143c986e51508e9f2259829e28c4 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.app;
18
Phil Weaver35841682016-03-09 09:52:51 -080019import android.annotation.IntDef;
Wale Ogunwale2632c972018-01-22 06:54:48 -080020import android.annotation.NonNull;
Wale Ogunwale828ff7e2017-11-14 01:01:29 +000021import android.annotation.Nullable;
Mathew Inwood61e8ae62018-08-14 14:17:44 +010022import android.annotation.UnsupportedAppUsage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.ActivityNotFoundException;
24import android.content.ComponentName;
25import android.content.Context;
26import android.content.Intent;
27import android.content.IntentFilter;
28import android.content.pm.ActivityInfo;
29import android.content.res.Configuration;
Jeff Brownac143512012-04-05 18:57:33 -070030import android.hardware.input.InputManager;
Dianne Hackborna3acdb32015-06-08 17:07:40 -070031import android.net.Uri;
Mathew Inwood31755f92018-12-20 13:53:36 +000032import android.os.Build;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080033import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.os.Debug;
35import android.os.IBinder;
Kristian Monsen0a303282013-01-18 14:50:07 -080036import android.os.Looper;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037import android.os.MessageQueue;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080038import android.os.PerformanceCollector;
Craig Mautnera0026042014-04-23 11:45:37 -070039import android.os.PersistableBundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.os.Process;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080041import android.os.RemoteException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042import android.os.ServiceManager;
Svetoslav Ganovc350f162011-11-10 17:54:24 -080043import android.os.SystemClock;
Jason Monk5be50f72017-03-10 10:57:34 -050044import android.os.TestLooperManager;
Dianne Hackbornf1c26e22012-08-23 13:54:58 -070045import android.os.UserHandle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.util.AndroidRuntimeException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.util.Log;
48import android.view.IWindowManager;
Jeff Brownac143512012-04-05 18:57:33 -070049import android.view.InputDevice;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050import android.view.KeyCharacterMap;
51import android.view.KeyEvent;
52import android.view.MotionEvent;
53import android.view.ViewConfiguration;
54import android.view.Window;
Winson Chung298f95b2017-08-10 15:57:18 -070055
Dianne Hackborn85d558c2014-11-04 10:31:54 -080056import com.android.internal.content.ReferrerIntent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057
58import java.io.File;
Phil Weaver35841682016-03-09 09:52:51 -080059import java.lang.annotation.Retention;
60import java.lang.annotation.RetentionPolicy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080061import java.util.ArrayList;
62import java.util.List;
63
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080064/**
65 * Base class for implementing application instrumentation code. When running
66 * with instrumentation turned on, this class will be instantiated for you
67 * before any of the application code, allowing you to monitor all of the
68 * interaction the system has with the application. An Instrumentation
69 * implementation is described to the system through an AndroidManifest.xml's
70 * <instrumentation> tag.
71 */
72public class Instrumentation {
Svetoslav Ganov80943d82013-01-02 10:25:37 -080073
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080074 /**
75 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
76 * identifies the class that is writing the report. This can be used to provide more structured
77 * logging or reporting capabilities in the IInstrumentationWatcher.
78 */
79 public static final String REPORT_KEY_IDENTIFIER = "id";
80 /**
81 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
82 * identifies a string which can simply be printed to the output stream. Using these streams
83 * provides a "pretty printer" version of the status & final packets. Any bundles including
84 * this key should also include the complete set of raw key/value pairs, so that the
85 * instrumentation can also be launched, and results collected, by an automated system.
86 */
87 public static final String REPORT_KEY_STREAMRESULT = "stream";
Svetoslav Ganov80943d82013-01-02 10:25:37 -080088
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080089 private static final String TAG = "Instrumentation";
Phil Weaver35841682016-03-09 09:52:51 -080090
91 /**
92 * @hide
93 */
94 @Retention(RetentionPolicy.SOURCE)
95 @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES})
96 public @interface UiAutomationFlags {};
97
98
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080099 private final Object mSync = new Object();
100 private ActivityThread mThread = null;
101 private MessageQueue mMessageQueue = null;
102 private Context mInstrContext;
103 private Context mAppContext;
104 private ComponentName mComponent;
105 private Thread mRunner;
106 private List<ActivityWaiter> mWaitingActivities;
107 private List<ActivityMonitor> mActivityMonitors;
108 private IInstrumentationWatcher mWatcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800109 private IUiAutomationConnection mUiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 private boolean mAutomaticPerformanceSnapshots = false;
Jack Wangff1df692009-08-26 17:19:13 -0700111 private PerformanceCollector mPerformanceCollector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 private Bundle mPerfMetrics = new Bundle();
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800113 private UiAutomation mUiAutomation;
chaviwfeb2e1e2018-12-19 17:24:11 -0800114 private final Object mAnimationCompleteLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115
116 public Instrumentation() {
117 }
118
119 /**
Jason Monk5be50f72017-03-10 10:57:34 -0500120 * Called for methods that shouldn't be called by standard apps and
121 * should only be used in instrumentation environments. This is not
122 * security feature as these classes will still be accessible through
123 * reflection, but it will serve as noticeable discouragement from
124 * doing such a thing.
125 */
126 private void checkInstrumenting(String method) {
127 // Check if we have an instrumentation context, as init should only get called by
128 // the system in startup processes that are being instrumented.
129 if (mInstrContext == null) {
130 throw new RuntimeException(method +
131 " cannot be called outside of instrumented processes");
132 }
133 }
134
135 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800136 * Called when the instrumentation is starting, before any application code
137 * has been loaded. Usually this will be implemented to simply call
138 * {@link #start} to begin the instrumentation thread, which will then
139 * continue execution in {@link #onStart}.
140 *
141 * <p>If you do not need your own thread -- that is you are writing your
142 * instrumentation to be completely asynchronous (returning to the event
143 * loop so that the application can run), you can simply begin your
144 * instrumentation here, for example call {@link Context#startActivity} to
145 * begin the appropriate first activity of the application.
146 *
147 * @param arguments Any additional arguments that were supplied when the
148 * instrumentation was started.
149 */
150 public void onCreate(Bundle arguments) {
151 }
152
153 /**
154 * Create and start a new thread in which to run instrumentation. This new
155 * thread will call to {@link #onStart} where you can implement the
156 * instrumentation.
157 */
158 public void start() {
159 if (mRunner != null) {
160 throw new RuntimeException("Instrumentation already started");
161 }
162 mRunner = new InstrumentationThread("Instr: " + getClass().getName());
163 mRunner.start();
164 }
165
166 /**
167 * Method where the instrumentation thread enters execution. This allows
168 * you to run your instrumentation code in a separate thread than the
169 * application, so that it can perform blocking operation such as
170 * {@link #sendKeySync} or {@link #startActivitySync}.
171 *
172 * <p>You will typically want to call finish() when this function is done,
173 * to end your instrumentation.
174 */
175 public void onStart() {
176 }
177
178 /**
179 * This is called whenever the system captures an unhandled exception that
180 * was thrown by the application. The default implementation simply
181 * returns false, allowing normal system handling of the exception to take
182 * place.
183 *
184 * @param obj The client object that generated the exception. May be an
185 * Application, Activity, BroadcastReceiver, Service, or null.
186 * @param e The exception that was thrown.
187 *
188 * @return To allow normal system exception process to occur, return false.
189 * If true is returned, the system will proceed as if the exception
190 * didn't happen.
191 */
192 public boolean onException(Object obj, Throwable e) {
193 return false;
194 }
195
196 /**
197 * Provide a status report about the application.
198 *
199 * @param resultCode Current success/failure of instrumentation.
200 * @param results Any results to send back to the code that started the instrumentation.
201 */
202 public void sendStatus(int resultCode, Bundle results) {
203 if (mWatcher != null) {
204 try {
205 mWatcher.instrumentationStatus(mComponent, resultCode, results);
206 }
207 catch (RemoteException e) {
208 mWatcher = null;
209 }
210 }
211 }
Dianne Hackborn34041732017-01-31 15:27:13 -0800212
213 /**
214 * Report some results in the middle of instrumentation execution. Later results (including
215 * those provided by {@link #finish}) will be combined with {@link Bundle#putAll}.
216 */
217 public void addResults(Bundle results) {
218 IActivityManager am = ActivityManager.getService();
219 try {
220 am.addInstrumentationResults(mThread.getApplicationThread(), results);
221 } catch (RemoteException ex) {
222 throw ex.rethrowFromSystemServer();
223 }
224 }
225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 /**
227 * Terminate instrumentation of the application. This will cause the
228 * application process to exit, removing this instrumentation from the next
Dianne Hackborn34041732017-01-31 15:27:13 -0800229 * time the application is started. If multiple processes are currently running
230 * for this instrumentation, all of those processes will be killed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 *
232 * @param resultCode Overall success/failure of instrumentation.
233 * @param results Any results to send back to the code that started the
234 * instrumentation.
235 */
236 public void finish(int resultCode, Bundle results) {
237 if (mAutomaticPerformanceSnapshots) {
238 endPerformanceSnapshot();
239 }
240 if (mPerfMetrics != null) {
Dianne Hackbornb65ea7b2014-06-20 12:18:55 -0700241 if (results == null) {
242 results = new Bundle();
243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800244 results.putAll(mPerfMetrics);
245 }
Phil Weaverd8e88832016-03-28 17:26:25 -0700246 if ((mUiAutomation != null) && !mUiAutomation.isDestroyed()) {
Adam Momtaz8f6f1f42013-04-10 12:42:58 -0700247 mUiAutomation.disconnect();
248 mUiAutomation = null;
249 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 mThread.finishInstrumentation(resultCode, results);
251 }
252
253 public void setAutomaticPerformanceSnapshots() {
254 mAutomaticPerformanceSnapshots = true;
Jack Wangff1df692009-08-26 17:19:13 -0700255 mPerformanceCollector = new PerformanceCollector();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 }
257
258 public void startPerformanceSnapshot() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800259 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700260 mPerformanceCollector.beginSnapshot(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 }
262 }
263
264 public void endPerformanceSnapshot() {
265 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700266 mPerfMetrics = mPerformanceCollector.endSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800267 }
268 }
269
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 /**
271 * Called when the instrumented application is stopping, after all of the
272 * normal application cleanup has occurred.
273 */
274 public void onDestroy() {
275 }
276
277 /**
278 * Return the Context of this instrumentation's package. Note that this is
279 * often different than the Context of the application being
280 * instrumentated, since the instrumentation code often lives is a
281 * different package than that of the application it is running against.
282 * See {@link #getTargetContext} to retrieve a Context for the target
283 * application.
284 *
285 * @return The instrumentation's package context.
286 *
287 * @see #getTargetContext
288 */
289 public Context getContext() {
290 return mInstrContext;
291 }
292
293 /**
294 * Returns complete component name of this instrumentation.
295 *
296 * @return Returns the complete component name for this instrumentation.
297 */
298 public ComponentName getComponentName() {
299 return mComponent;
300 }
301
302 /**
303 * Return a Context for the target application being instrumented. Note
304 * that this is often different than the Context of the instrumentation
305 * code, since the instrumentation code often lives is a different package
306 * than that of the application it is running against. See
307 * {@link #getContext} to retrieve a Context for the instrumentation code.
308 *
309 * @return A Context in the target application.
310 *
311 * @see #getContext
312 */
313 public Context getTargetContext() {
314 return mAppContext;
315 }
316
317 /**
Dianne Hackborn34041732017-01-31 15:27:13 -0800318 * Return the name of the process this instrumentation is running in. Note this should
319 * only be used for testing and debugging. If you are thinking about using this to,
320 * for example, conditionalize what is initialized in an Application class, it is strongly
321 * recommended to instead use lazy initialization (such as a getter for the state that
322 * only creates it when requested). This can greatly reduce the work your process does
323 * when created for secondary things, such as to receive a broadcast.
324 */
325 public String getProcessName() {
326 return mThread.getProcessName();
327 }
328
329 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800330 * Check whether this instrumentation was started with profiling enabled.
331 *
332 * @return Returns true if profiling was enabled when starting, else false.
333 */
334 public boolean isProfiling() {
335 return mThread.isProfiling();
336 }
337
338 /**
339 * This method will start profiling if isProfiling() returns true. You should
340 * only call this method if you set the handleProfiling attribute in the
341 * manifest file for this Instrumentation to true.
342 */
343 public void startProfiling() {
344 if (mThread.isProfiling()) {
345 File file = new File(mThread.getProfileFilePath());
346 file.getParentFile().mkdirs();
347 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
348 }
349 }
350
351 /**
352 * Stops profiling if isProfiling() returns true.
353 */
354 public void stopProfiling() {
355 if (mThread.isProfiling()) {
356 Debug.stopMethodTracing();
357 }
358 }
359
360 /**
361 * Force the global system in or out of touch mode. This can be used if
362 * your instrumentation relies on the UI being in one more or the other
363 * when it starts.
364 *
365 * @param inTouch Set to true to be in touch mode, false to be in
366 * focus mode.
367 */
368 public void setInTouchMode(boolean inTouch) {
369 try {
370 IWindowManager.Stub.asInterface(
371 ServiceManager.getService("window")).setInTouchMode(inTouch);
372 } catch (RemoteException e) {
373 // Shouldn't happen!
374 }
375 }
376
377 /**
378 * Schedule a callback for when the application's main thread goes idle
379 * (has no more events to process).
380 *
381 * @param recipient Called the next time the thread's message queue is
382 * idle.
383 */
384 public void waitForIdle(Runnable recipient) {
385 mMessageQueue.addIdleHandler(new Idler(recipient));
386 mThread.getHandler().post(new EmptyRunnable());
387 }
388
389 /**
390 * Synchronously wait for the application to be idle. Can not be called
391 * from the main application thread -- use {@link #start} to execute
392 * instrumentation in its own thread.
393 */
394 public void waitForIdleSync() {
395 validateNotAppThread();
396 Idler idler = new Idler(null);
397 mMessageQueue.addIdleHandler(idler);
398 mThread.getHandler().post(new EmptyRunnable());
399 idler.waitForIdle();
400 }
401
chaviwfeb2e1e2018-12-19 17:24:11 -0800402 private void waitForEnterAnimationComplete(Activity activity) {
403 synchronized (mAnimationCompleteLock) {
404 long timeout = 5000;
405 try {
406 // We need to check that this specified Activity completed the animation, not just
407 // any Activity. If it was another Activity, then decrease the timeout by how long
408 // it's already waited and wait for the thread to wakeup again.
409 while (timeout > 0 && !activity.mEnterAnimationComplete) {
410 long startTime = System.currentTimeMillis();
411 mAnimationCompleteLock.wait(timeout);
412 long totalTime = System.currentTimeMillis() - startTime;
413 timeout -= totalTime;
414 }
415 } catch (InterruptedException e) {
416 }
417 }
418 }
419
420 /** @hide */
421 public void onEnterAnimationComplete() {
422 synchronized (mAnimationCompleteLock) {
423 mAnimationCompleteLock.notifyAll();
424 }
425 }
426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 /**
428 * Execute a call on the application's main thread, blocking until it is
429 * complete. Useful for doing things that are not thread-safe, such as
430 * looking at or modifying the view hierarchy.
431 *
432 * @param runner The code to run on the main thread.
433 */
434 public void runOnMainSync(Runnable runner) {
435 validateNotAppThread();
436 SyncRunnable sr = new SyncRunnable(runner);
437 mThread.getHandler().post(sr);
438 sr.waitForComplete();
439 }
440
441 /**
442 * Start a new activity and wait for it to begin running before returning.
443 * In addition to being synchronous, this method as some semantic
444 * differences from the standard {@link Context#startActivity} call: the
445 * activity component is resolved before talking with the activity manager
446 * (its class name is specified in the Intent that this method ultimately
447 * starts), and it does not allow you to start activities that run in a
448 * different process. In addition, if the given Intent resolves to
449 * multiple activities, instead of displaying a dialog for the user to
450 * select an activity, an exception will be thrown.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000451 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 * <p>The function returns as soon as the activity goes idle following the
453 * call to its {@link Activity#onCreate}. Generally this means it has gone
454 * through the full initialization including {@link Activity#onResume} and
455 * drawn and displayed its initial window.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000456 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800457 * @param intent Description of the activity to start.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000458 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 * @see Context#startActivity
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000460 * @see #startActivitySync(Intent, Bundle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 */
462 public Activity startActivitySync(Intent intent) {
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000463 return startActivitySync(intent, null /* options */);
464 }
465
466 /**
467 * Start a new activity and wait for it to begin running before returning.
468 * In addition to being synchronous, this method as some semantic
469 * differences from the standard {@link Context#startActivity} call: the
470 * activity component is resolved before talking with the activity manager
471 * (its class name is specified in the Intent that this method ultimately
472 * starts), and it does not allow you to start activities that run in a
473 * different process. In addition, if the given Intent resolves to
474 * multiple activities, instead of displaying a dialog for the user to
475 * select an activity, an exception will be thrown.
476 *
477 * <p>The function returns as soon as the activity goes idle following the
478 * call to its {@link Activity#onCreate}. Generally this means it has gone
479 * through the full initialization including {@link Activity#onResume} and
480 * drawn and displayed its initial window.
481 *
482 * @param intent Description of the activity to start.
483 * @param options Additional options for how the Activity should be started.
484 * May be null if there are no options. See {@link android.app.ActivityOptions}
485 * for how to build the Bundle supplied here; there are no supported definitions
486 * for building it manually.
487 *
488 * @see Context#startActivity(Intent, Bundle)
489 */
Wale Ogunwale2632c972018-01-22 06:54:48 -0800490 @NonNull
491 public Activity startActivitySync(@NonNull Intent intent, @Nullable Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800492 validateNotAppThread();
493
494 synchronized (mSync) {
495 intent = new Intent(intent);
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000496
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 ActivityInfo ai = intent.resolveActivityInfo(
498 getTargetContext().getPackageManager(), 0);
499 if (ai == null) {
500 throw new RuntimeException("Unable to resolve activity for: " + intent);
501 }
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700502 String myProc = mThread.getProcessName();
503 if (!ai.processName.equals(myProc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 // todo: if this intent is ambiguous, look here to see if
505 // there is a single match that is in our package.
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700506 throw new RuntimeException("Intent in process "
507 + myProc + " resolved to different process "
508 + ai.processName + ": " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800509 }
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000510
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 intent.setComponent(new ComponentName(
512 ai.applicationInfo.packageName, ai.name));
513 final ActivityWaiter aw = new ActivityWaiter(intent);
514
515 if (mWaitingActivities == null) {
516 mWaitingActivities = new ArrayList();
517 }
518 mWaitingActivities.add(aw);
519
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000520 getTargetContext().startActivity(intent, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800521
522 do {
523 try {
524 mSync.wait();
525 } catch (InterruptedException e) {
526 }
527 } while (mWaitingActivities.contains(aw));
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000528
chaviwfeb2e1e2018-12-19 17:24:11 -0800529 waitForEnterAnimationComplete(aw.activity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 return aw.activity;
531 }
532 }
533
534 /**
535 * Information about a particular kind of Intent that is being monitored.
536 * An instance of this class is added to the
537 * current instrumentation through {@link #addMonitor}; after being added,
538 * when a new activity is being started the monitor will be checked and, if
539 * matching, its hit count updated and (optionally) the call stopped and a
540 * canned result returned.
541 *
542 * <p>An ActivityMonitor can also be used to look for the creation of an
543 * activity, through the {@link #waitForActivity} method. This will return
544 * after a matching activity has been created with that activity object.
545 */
546 public static class ActivityMonitor {
547 private final IntentFilter mWhich;
548 private final String mClass;
549 private final ActivityResult mResult;
550 private final boolean mBlock;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800551 private final boolean mIgnoreMatchingSpecificIntents;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800552
553
554 // This is protected by 'Instrumentation.this.mSync'.
555 /*package*/ int mHits = 0;
556
557 // This is protected by 'this'.
558 /*package*/ Activity mLastActivity = null;
559
560 /**
561 * Create a new ActivityMonitor that looks for a particular kind of
562 * intent to be started.
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800563 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800564 * @param which The set of intents this monitor is responsible for.
565 * @param result A canned result to return if the monitor is hit; can
566 * be null.
567 * @param block Controls whether the monitor should block the activity
568 * start (returning its canned result) or let the call
569 * proceed.
570 *
571 * @see Instrumentation#addMonitor
572 */
573 public ActivityMonitor(
574 IntentFilter which, ActivityResult result, boolean block) {
575 mWhich = which;
576 mClass = null;
577 mResult = result;
578 mBlock = block;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800579 mIgnoreMatchingSpecificIntents = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800580 }
581
582 /**
583 * Create a new ActivityMonitor that looks for a specific activity
584 * class to be started.
585 *
586 * @param cls The activity class this monitor is responsible for.
587 * @param result A canned result to return if the monitor is hit; can
588 * be null.
589 * @param block Controls whether the monitor should block the activity
590 * start (returning its canned result) or let the call
591 * proceed.
592 *
593 * @see Instrumentation#addMonitor
594 */
595 public ActivityMonitor(
596 String cls, ActivityResult result, boolean block) {
597 mWhich = null;
598 mClass = cls;
599 mResult = result;
600 mBlock = block;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800601 mIgnoreMatchingSpecificIntents = false;
602 }
603
604 /**
605 * Create a new ActivityMonitor that can be used for intercepting any activity to be
606 * started.
607 *
Sudheer Shanka34217512017-04-26 14:49:16 -0700608 * <p> When an activity is started, {@link #onStartActivity(Intent)} will be called on
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800609 * instances created using this constructor to see if it is a hit.
610 *
Sudheer Shanka34217512017-04-26 14:49:16 -0700611 * @see #onStartActivity(Intent)
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800612 */
613 public ActivityMonitor() {
614 mWhich = null;
615 mClass = null;
616 mResult = null;
617 mBlock = false;
618 mIgnoreMatchingSpecificIntents = true;
619 }
620
621 /**
622 * @return true if this monitor is used for intercepting any started activity by calling
Sudheer Shanka34217512017-04-26 14:49:16 -0700623 * into {@link #onStartActivity(Intent)}, false if this monitor is only used
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800624 * for specific intents corresponding to the intent filter or activity class
625 * passed in the constructor.
626 */
627 final boolean ignoreMatchingSpecificIntents() {
628 return mIgnoreMatchingSpecificIntents;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 }
630
631 /**
632 * Retrieve the filter associated with this ActivityMonitor.
633 */
634 public final IntentFilter getFilter() {
635 return mWhich;
636 }
637
638 /**
639 * Retrieve the result associated with this ActivityMonitor, or null if
640 * none.
641 */
642 public final ActivityResult getResult() {
643 return mResult;
644 }
645
646 /**
647 * Check whether this monitor blocks activity starts (not allowing the
648 * actual activity to run) or allows them to execute normally.
649 */
650 public final boolean isBlocking() {
651 return mBlock;
652 }
653
654 /**
655 * Retrieve the number of times the monitor has been hit so far.
656 */
657 public final int getHits() {
658 return mHits;
659 }
660
661 /**
662 * Retrieve the most recent activity class that was seen by this
663 * monitor.
664 */
665 public final Activity getLastActivity() {
666 return mLastActivity;
667 }
668
669 /**
670 * Block until an Activity is created that matches this monitor,
671 * returning the resulting activity.
672 *
673 * @return Activity
674 */
675 public final Activity waitForActivity() {
676 synchronized (this) {
677 while (mLastActivity == null) {
678 try {
679 wait();
680 } catch (InterruptedException e) {
681 }
682 }
683 Activity res = mLastActivity;
684 mLastActivity = null;
685 return res;
686 }
687 }
688
689 /**
690 * Block until an Activity is created that matches this monitor,
691 * returning the resulting activity or till the timeOut period expires.
692 * If the timeOut expires before the activity is started, return null.
693 *
Ben Gruver87904e82016-01-22 13:11:11 -0800694 * @param timeOut Time to wait in milliseconds before the activity is created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800695 *
696 * @return Activity
697 */
698 public final Activity waitForActivityWithTimeout(long timeOut) {
699 synchronized (this) {
Costin Manolacheb0935342011-07-15 11:20:42 -0700700 if (mLastActivity == null) {
701 try {
702 wait(timeOut);
703 } catch (InterruptedException e) {
704 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800705 }
706 if (mLastActivity == null) {
707 return null;
708 } else {
709 Activity res = mLastActivity;
710 mLastActivity = null;
711 return res;
712 }
713 }
714 }
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800715
716 /**
717 * Used for intercepting any started activity.
718 *
719 * <p> A non-null return value here will be considered a hit for this monitor.
720 * By default this will return {@code null} and subclasses can override this to return
721 * a non-null value if the intent needs to be intercepted.
722 *
723 * <p> Whenever a new activity is started, this method will be called on instances created
724 * using {@link #Instrumentation.ActivityMonitor()} to check if there is a match. In case
725 * of a match, the activity start will be blocked and the returned result will be used.
726 *
727 * @param intent The intent used for starting the activity.
728 * @return The {@link ActivityResult} that needs to be used in case of a match.
729 */
Sudheer Shanka34217512017-04-26 14:49:16 -0700730 public ActivityResult onStartActivity(Intent intent) {
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800731 return null;
732 }
733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 final boolean match(Context who,
735 Activity activity,
736 Intent intent) {
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800737 if (mIgnoreMatchingSpecificIntents) {
738 return false;
739 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 synchronized (this) {
741 if (mWhich != null
742 && mWhich.match(who.getContentResolver(), intent,
743 true, "Instrumentation") < 0) {
744 return false;
745 }
746 if (mClass != null) {
747 String cls = null;
748 if (activity != null) {
749 cls = activity.getClass().getName();
750 } else if (intent.getComponent() != null) {
751 cls = intent.getComponent().getClassName();
752 }
753 if (cls == null || !mClass.equals(cls)) {
754 return false;
755 }
756 }
757 if (activity != null) {
758 mLastActivity = activity;
759 notifyAll();
760 }
761 return true;
762 }
763 }
764 }
765
766 /**
767 * Add a new {@link ActivityMonitor} that will be checked whenever an
768 * activity is started. The monitor is added
769 * after any existing ones; the monitor will be hit only if none of the
770 * existing monitors can themselves handle the Intent.
771 *
772 * @param monitor The new ActivityMonitor to see.
773 *
774 * @see #addMonitor(IntentFilter, ActivityResult, boolean)
775 * @see #checkMonitorHit
776 */
777 public void addMonitor(ActivityMonitor monitor) {
778 synchronized (mSync) {
779 if (mActivityMonitors == null) {
780 mActivityMonitors = new ArrayList();
781 }
782 mActivityMonitors.add(monitor);
783 }
784 }
785
786 /**
787 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
788 * creates an intent filter matching {@link ActivityMonitor} for you and
789 * returns it.
790 *
791 * @param filter The set of intents this monitor is responsible for.
792 * @param result A canned result to return if the monitor is hit; can
793 * be null.
794 * @param block Controls whether the monitor should block the activity
795 * start (returning its canned result) or let the call
796 * proceed.
797 *
798 * @return The newly created and added activity monitor.
799 *
800 * @see #addMonitor(ActivityMonitor)
801 * @see #checkMonitorHit
802 */
803 public ActivityMonitor addMonitor(
804 IntentFilter filter, ActivityResult result, boolean block) {
805 ActivityMonitor am = new ActivityMonitor(filter, result, block);
806 addMonitor(am);
807 return am;
808 }
809
810 /**
811 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
812 * creates a class matching {@link ActivityMonitor} for you and returns it.
813 *
814 * @param cls The activity class this monitor is responsible for.
815 * @param result A canned result to return if the monitor is hit; can
816 * be null.
817 * @param block Controls whether the monitor should block the activity
818 * start (returning its canned result) or let the call
819 * proceed.
820 *
821 * @return The newly created and added activity monitor.
822 *
823 * @see #addMonitor(ActivityMonitor)
824 * @see #checkMonitorHit
825 */
826 public ActivityMonitor addMonitor(
827 String cls, ActivityResult result, boolean block) {
828 ActivityMonitor am = new ActivityMonitor(cls, result, block);
829 addMonitor(am);
830 return am;
831 }
832
833 /**
834 * Test whether an existing {@link ActivityMonitor} has been hit. If the
835 * monitor has been hit at least <var>minHits</var> times, then it will be
836 * removed from the activity monitor list and true returned. Otherwise it
837 * is left as-is and false is returned.
838 *
839 * @param monitor The ActivityMonitor to check.
840 * @param minHits The minimum number of hits required.
841 *
842 * @return True if the hit count has been reached, else false.
843 *
844 * @see #addMonitor
845 */
846 public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
847 waitForIdleSync();
848 synchronized (mSync) {
849 if (monitor.getHits() < minHits) {
850 return false;
851 }
852 mActivityMonitors.remove(monitor);
853 }
854 return true;
855 }
856
857 /**
858 * Wait for an existing {@link ActivityMonitor} to be hit. Once the
859 * monitor has been hit, it is removed from the activity monitor list and
860 * the first created Activity object that matched it is returned.
861 *
862 * @param monitor The ActivityMonitor to wait for.
863 *
864 * @return The Activity object that matched the monitor.
865 */
866 public Activity waitForMonitor(ActivityMonitor monitor) {
867 Activity activity = monitor.waitForActivity();
868 synchronized (mSync) {
869 mActivityMonitors.remove(monitor);
870 }
871 return activity;
872 }
873
874 /**
875 * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
876 * expires. Once the monitor has been hit, it is removed from the activity
877 * monitor list and the first created Activity object that matched it is
878 * returned. If the timeout expires, a null object is returned.
879 *
880 * @param monitor The ActivityMonitor to wait for.
Nimrod Gileadic895a4b2017-03-31 13:21:47 +0100881 * @param timeOut The timeout value in milliseconds.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800882 *
883 * @return The Activity object that matched the monitor.
884 */
885 public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
886 Activity activity = monitor.waitForActivityWithTimeout(timeOut);
887 synchronized (mSync) {
888 mActivityMonitors.remove(monitor);
889 }
890 return activity;
891 }
892
893 /**
894 * Remove an {@link ActivityMonitor} that was previously added with
895 * {@link #addMonitor}.
896 *
897 * @param monitor The monitor to remove.
898 *
899 * @see #addMonitor
900 */
901 public void removeMonitor(ActivityMonitor monitor) {
902 synchronized (mSync) {
903 mActivityMonitors.remove(monitor);
904 }
905 }
906
907 /**
908 * Execute a particular menu item.
909 *
910 * @param targetActivity The activity in question.
911 * @param id The identifier associated with the menu item.
912 * @param flag Additional flags, if any.
913 * @return Whether the invocation was successful (for example, it could be
914 * false if item is disabled).
915 */
916 public boolean invokeMenuActionSync(Activity targetActivity,
917 int id, int flag) {
918 class MenuRunnable implements Runnable {
919 private final Activity activity;
920 private final int identifier;
921 private final int flags;
922 boolean returnValue;
923
924 public MenuRunnable(Activity _activity, int _identifier,
925 int _flags) {
926 activity = _activity;
927 identifier = _identifier;
928 flags = _flags;
929 }
930
931 public void run() {
932 Window win = activity.getWindow();
933
934 returnValue = win.performPanelIdentifierAction(
935 Window.FEATURE_OPTIONS_PANEL,
936 identifier,
937 flags);
938 }
939
940 }
941 MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
942 runOnMainSync(mr);
943 return mr.returnValue;
944 }
945
946 /**
947 * Show the context menu for the currently focused view and executes a
948 * particular context menu item.
949 *
950 * @param targetActivity The activity in question.
951 * @param id The identifier associated with the context menu item.
952 * @param flag Additional flags, if any.
953 * @return Whether the invocation was successful (for example, it could be
954 * false if item is disabled).
955 */
956 public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
957 validateNotAppThread();
958
959 // Bring up context menu for current focus.
960 // It'd be nice to do this through code, but currently ListView depends on
961 // long press to set metadata for its selected child
962
963 final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
964 sendKeySync(downEvent);
965
966 // Need to wait for long press
967 waitForIdleSync();
968 try {
969 Thread.sleep(ViewConfiguration.getLongPressTimeout());
970 } catch (InterruptedException e) {
971 Log.e(TAG, "Could not sleep for long press timeout", e);
972 return false;
973 }
974
975 final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
976 sendKeySync(upEvent);
977
978 // Wait for context menu to appear
979 waitForIdleSync();
980
981 class ContextMenuRunnable implements Runnable {
982 private final Activity activity;
983 private final int identifier;
984 private final int flags;
985 boolean returnValue;
986
987 public ContextMenuRunnable(Activity _activity, int _identifier,
988 int _flags) {
989 activity = _activity;
990 identifier = _identifier;
991 flags = _flags;
992 }
993
994 public void run() {
995 Window win = activity.getWindow();
996 returnValue = win.performContextMenuIdentifierAction(
997 identifier,
998 flags);
999 }
1000
1001 }
1002
1003 ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
1004 runOnMainSync(cmr);
1005 return cmr.returnValue;
1006 }
1007
1008 /**
1009 * Sends the key events corresponding to the text to the app being
1010 * instrumented.
1011 *
1012 * @param text The text to be sent.
1013 */
1014 public void sendStringSync(String text) {
1015 if (text == null) {
1016 return;
1017 }
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001018 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001019
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001021
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001022 if (events != null) {
1023 for (int i = 0; i < events.length; i++) {
Svetoslav Ganovf434e372011-11-11 16:50:21 -08001024 // We have to change the time of an event before injecting it because
1025 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
1026 // time stamp and the system rejects too old events. Hence, it is
1027 // possible for an event to become stale before it is injected if it
1028 // takes too long to inject the preceding ones.
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001029 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001031 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034 /**
1035 * Send a key event to the currently focused window/view and wait for it to
1036 * be processed. Finished at some point after the recipient has returned
1037 * from its event processing, though it may <em>not</em> have completely
1038 * finished reacting from the event -- for example, if it needs to update
1039 * its display as a result, it may still be in the process of doing that.
Tiger Huangfc218452018-09-27 00:38:50 +08001040 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 * @param event The event to send to the current focus.
1042 */
1043 public void sendKeySync(KeyEvent event) {
1044 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001045
1046 long downTime = event.getDownTime();
1047 long eventTime = event.getEventTime();
Jeff Brownac143512012-04-05 18:57:33 -07001048 int source = event.getSource();
Jeff Brownac143512012-04-05 18:57:33 -07001049 if (source == InputDevice.SOURCE_UNKNOWN) {
1050 source = InputDevice.SOURCE_KEYBOARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 }
Jeff Brownac143512012-04-05 18:57:33 -07001052 if (eventTime == 0) {
1053 eventTime = SystemClock.uptimeMillis();
1054 }
1055 if (downTime == 0) {
1056 downTime = eventTime;
1057 }
Tiger Huangfc218452018-09-27 00:38:50 +08001058 KeyEvent newEvent = new KeyEvent(event);
1059 newEvent.setTime(downTime, eventTime);
1060 newEvent.setSource(source);
1061 newEvent.setFlags(event.getFlags() | KeyEvent.FLAG_FROM_SYSTEM);
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001062 InputManager.getInstance().injectInputEvent(newEvent,
Jeff Brownac143512012-04-05 18:57:33 -07001063 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 }
Tiger Huangfc218452018-09-27 00:38:50 +08001065
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001066 /**
1067 * Sends an up and down key event sync to the currently focused window.
1068 *
1069 * @param key The integer keycode for the event.
1070 */
1071 public void sendKeyDownUpSync(int key) {
1072 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
1073 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
1074 }
1075
1076 /**
1077 * Higher-level method for sending both the down and up key events for a
1078 * particular character key code. Equivalent to creating both KeyEvent
1079 * objects by hand and calling {@link #sendKeySync}. The event appears
1080 * as if it came from keyboard 0, the built in one.
1081 *
1082 * @param keyCode The key code of the character to send.
1083 */
1084 public void sendCharacterSync(int keyCode) {
1085 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
1086 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
1087 }
1088
1089 /**
1090 * Dispatch a pointer event. Finished at some point after the recipient has
1091 * returned from its event processing, though it may <em>not</em> have
1092 * completely finished reacting from the event -- for example, if it needs
1093 * to update its display as a result, it may still be in the process of
1094 * doing that.
1095 *
1096 * @param event A motion event describing the pointer action. (As noted in
1097 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
1098 * {@link SystemClock#uptimeMillis()} as the timebase.
1099 */
1100 public void sendPointerSync(MotionEvent event) {
1101 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001102 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
1103 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001105 InputManager.getInstance().injectInputEvent(event,
1106 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 }
1108
1109 /**
1110 * Dispatch a trackball event. Finished at some point after the recipient has
1111 * returned from its event processing, though it may <em>not</em> have
1112 * completely finished reacting from the event -- for example, if it needs
1113 * to update its display as a result, it may still be in the process of
1114 * doing that.
1115 *
1116 * @param event A motion event describing the trackball action. (As noted in
1117 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
1118 * {@link SystemClock#uptimeMillis()} as the timebase.
1119 */
1120 public void sendTrackballEventSync(MotionEvent event) {
1121 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001122 if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
1123 event.setSource(InputDevice.SOURCE_TRACKBALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001125 InputManager.getInstance().injectInputEvent(event,
1126 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001127 }
1128
1129 /**
1130 * Perform instantiation of the process's {@link Application} object. The
1131 * default implementation provides the normal system behavior.
1132 *
1133 * @param cl The ClassLoader with which to instantiate the object.
1134 * @param className The name of the class implementing the Application
1135 * object.
1136 * @param context The context to initialize the application with
1137 *
1138 * @return The newly instantiated Application object.
1139 */
1140 public Application newApplication(ClassLoader cl, String className, Context context)
1141 throws InstantiationException, IllegalAccessException,
1142 ClassNotFoundException {
Jason Monka80bfb52017-11-16 17:15:37 -05001143 Application app = getFactory(context.getPackageName())
1144 .instantiateApplication(cl, className);
1145 app.attach(context);
1146 return app;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147 }
1148
1149 /**
1150 * Perform instantiation of the process's {@link Application} object. The
1151 * default implementation provides the normal system behavior.
1152 *
1153 * @param clazz The class used to create an Application object from.
1154 * @param context The context to initialize the application with
1155 *
1156 * @return The newly instantiated Application object.
1157 */
1158 static public Application newApplication(Class<?> clazz, Context context)
1159 throws InstantiationException, IllegalAccessException,
1160 ClassNotFoundException {
1161 Application app = (Application)clazz.newInstance();
1162 app.attach(context);
1163 return app;
1164 }
1165
1166 /**
1167 * Perform calling of the application's {@link Application#onCreate}
1168 * method. The default implementation simply calls through to that method.
Dianne Hackborn6ae8d182012-05-23 13:12:42 -07001169 *
1170 * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
1171 * Often instrumentation tests start their test thread in onCreate(); you
1172 * need to be careful of races between these. (Well between it and
1173 * everything else, but let's start here.)
1174 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 * @param app The application being created.
1176 */
1177 public void callApplicationOnCreate(Application app) {
1178 app.onCreate();
1179 }
1180
1181 /**
1182 * Perform instantiation of an {@link Activity} object. This method is intended for use with
1183 * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
Felipe Leme545569d2016-01-11 16:27:58 -08001184 * 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 -08001185 *
1186 * @param clazz The Class of the desired Activity
1187 * @param context The base context for the activity to use
1188 * @param token The token for this activity to communicate with
1189 * @param application The application object (if any)
1190 * @param intent The intent that started this Activity
1191 * @param info ActivityInfo from the manifest
1192 * @param title The title, typically retrieved from the ActivityInfo record
1193 * @param parent The parent Activity (if any)
1194 * @param id The embedded Id (if any)
1195 * @param lastNonConfigurationInstance Arbitrary object that will be
1196 * available via {@link Activity#getLastNonConfigurationInstance()
1197 * Activity.getLastNonConfigurationInstance()}.
1198 * @return Returns the instantiated activity
1199 * @throws InstantiationException
1200 * @throws IllegalAccessException
1201 */
1202 public Activity newActivity(Class<?> clazz, Context context,
1203 IBinder token, Application application, Intent intent, ActivityInfo info,
1204 CharSequence title, Activity parent, String id,
1205 Object lastNonConfigurationInstance) throws InstantiationException,
1206 IllegalAccessException {
1207 Activity activity = (Activity)clazz.newInstance();
1208 ActivityThread aThread = null;
Sudheer Shanka37820712018-04-11 15:47:35 -07001209 // Activity.attach expects a non-null Application Object.
1210 if (application == null) {
1211 application = new Application();
1212 }
Andrii Kulian51c1b672017-04-07 18:39:32 -07001213 activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001214 info, title, parent, id,
1215 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
Andrii Kulian51c1b672017-04-07 18:39:32 -07001216 new Configuration(), null /* referrer */, null /* voiceInteractor */,
1217 null /* window */, null /* activityConfigCallback */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001218 return activity;
1219 }
1220
1221 /**
1222 * Perform instantiation of the process's {@link Activity} object. The
1223 * default implementation provides the normal system behavior.
1224 *
1225 * @param cl The ClassLoader with which to instantiate the object.
1226 * @param className The name of the class implementing the Activity
1227 * object.
1228 * @param intent The Intent object that specified the activity class being
1229 * instantiated.
1230 *
1231 * @return The newly instantiated Activity object.
1232 */
1233 public Activity newActivity(ClassLoader cl, String className,
1234 Intent intent)
1235 throws InstantiationException, IllegalAccessException,
1236 ClassNotFoundException {
Jason Monke96443e2018-04-18 15:43:50 -04001237 String pkg = intent != null && intent.getComponent() != null
1238 ? intent.getComponent().getPackageName() : null;
Jason Monka80bfb52017-11-16 17:15:37 -05001239 return getFactory(pkg).instantiateActivity(cl, className, intent);
1240 }
1241
1242 private AppComponentFactory getFactory(String pkg) {
Jason Monke96443e2018-04-18 15:43:50 -04001243 if (pkg == null) {
1244 Log.e(TAG, "No pkg specified, disabling AppComponentFactory");
1245 return AppComponentFactory.DEFAULT;
1246 }
Jason Monk24d12a32017-12-21 10:39:17 -05001247 if (mThread == null) {
1248 Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
1249 + " disabling AppComponentFactory", new Throwable());
1250 return AppComponentFactory.DEFAULT;
1251 }
Todd Kennedy233a0b12018-01-29 20:30:24 +00001252 LoadedApk apk = mThread.peekPackageInfo(pkg, true);
Jason Monka80bfb52017-11-16 17:15:37 -05001253 // This is in the case of starting up "android".
Todd Kennedy233a0b12018-01-29 20:30:24 +00001254 if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
1255 return apk.getAppFactory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001256 }
1257
Craig Mautnera0026042014-04-23 11:45:37 -07001258 private void prePerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 if (mWaitingActivities != null) {
1260 synchronized (mSync) {
1261 final int N = mWaitingActivities.size();
1262 for (int i=0; i<N; i++) {
1263 final ActivityWaiter aw = mWaitingActivities.get(i);
1264 final Intent intent = aw.intent;
1265 if (intent.filterEquals(activity.getIntent())) {
1266 aw.activity = activity;
1267 mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1268 }
1269 }
1270 }
1271 }
Craig Mautnera0026042014-04-23 11:45:37 -07001272 }
1273
1274 private void postPerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001275 if (mActivityMonitors != null) {
1276 synchronized (mSync) {
1277 final int N = mActivityMonitors.size();
1278 for (int i=0; i<N; i++) {
1279 final ActivityMonitor am = mActivityMonitors.get(i);
1280 am.match(activity, activity, activity.getIntent());
1281 }
1282 }
1283 }
1284 }
Craig Mautnera0026042014-04-23 11:45:37 -07001285
1286 /**
1287 * Perform calling of an activity's {@link Activity#onCreate}
1288 * method. The default implementation simply calls through to that method.
1289 *
1290 * @param activity The activity being created.
1291 * @param icicle The previously frozen state (or null) to pass through to onCreate().
1292 */
1293 public void callActivityOnCreate(Activity activity, Bundle icicle) {
1294 prePerformCreate(activity);
1295 activity.performCreate(icicle);
1296 postPerformCreate(activity);
1297 }
1298
1299 /**
1300 * Perform calling of an activity's {@link Activity#onCreate}
1301 * method. The default implementation simply calls through to that method.
1302 * @param activity The activity being created.
1303 * @param icicle The previously frozen state (or null) to pass through to
1304 * @param persistentState The previously persisted state (or null)
1305 */
1306 public void callActivityOnCreate(Activity activity, Bundle icicle,
1307 PersistableBundle persistentState) {
1308 prePerformCreate(activity);
1309 activity.performCreate(icicle, persistentState);
1310 postPerformCreate(activity);
1311 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001312
1313 public void callActivityOnDestroy(Activity activity) {
Brett Chabot18f9ce02010-05-12 12:41:50 -07001314 // TODO: the following block causes intermittent hangs when using startActivity
1315 // temporarily comment out until root cause is fixed (bug 2630683)
1316// if (mWaitingActivities != null) {
1317// synchronized (mSync) {
1318// final int N = mWaitingActivities.size();
1319// for (int i=0; i<N; i++) {
1320// final ActivityWaiter aw = mWaitingActivities.get(i);
1321// final Intent intent = aw.intent;
1322// if (intent.filterEquals(activity.getIntent())) {
1323// aw.activity = activity;
1324// mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1325// }
1326// }
1327// }
1328// }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001330 activity.performDestroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001331 }
1332
1333 /**
1334 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1335 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001336 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001337 * @param activity The activity being restored.
1338 * @param savedInstanceState The previously saved state being restored.
1339 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001340 public void callActivityOnRestoreInstanceState(@NonNull Activity activity,
1341 @NonNull Bundle savedInstanceState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001342 activity.performRestoreInstanceState(savedInstanceState);
1343 }
1344
1345 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001346 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1347 * method. The default implementation simply calls through to that method.
1348 *
1349 * @param activity The activity being restored.
Jake Wharton63f4d892018-07-10 12:27:59 -04001350 * @param savedInstanceState The previously saved state being restored (or null).
Craig Mautnera0026042014-04-23 11:45:37 -07001351 * @param persistentState The previously persisted state (or null)
1352 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001353 public void callActivityOnRestoreInstanceState(@NonNull Activity activity,
1354 @Nullable Bundle savedInstanceState,
1355 @Nullable PersistableBundle persistentState) {
Craig Mautnera0026042014-04-23 11:45:37 -07001356 activity.performRestoreInstanceState(savedInstanceState, persistentState);
1357 }
1358
1359 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001360 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1361 * The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001362 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001363 * @param activity The activity being created.
Jake Wharton63f4d892018-07-10 12:27:59 -04001364 * @param savedInstanceState The previously saved state (or null) to pass through to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001365 * onPostCreate().
1366 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001367 public void callActivityOnPostCreate(@NonNull Activity activity,
1368 @Nullable Bundle savedInstanceState) {
1369 activity.onPostCreate(savedInstanceState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001370 }
1371
1372 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001373 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1374 * The default implementation simply calls through to that method.
1375 *
1376 * @param activity The activity being created.
Jake Wharton63f4d892018-07-10 12:27:59 -04001377 * @param savedInstanceState The previously frozen state (or null) to pass through to
Craig Mautnera0026042014-04-23 11:45:37 -07001378 * onPostCreate().
Jake Wharton63f4d892018-07-10 12:27:59 -04001379 * @param persistentState The previously persisted state (or null)
Craig Mautnera0026042014-04-23 11:45:37 -07001380 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001381 public void callActivityOnPostCreate(@NonNull Activity activity,
1382 @Nullable Bundle savedInstanceState,
1383 @Nullable PersistableBundle persistentState) {
1384 activity.onPostCreate(savedInstanceState, persistentState);
Craig Mautnera0026042014-04-23 11:45:37 -07001385 }
1386
1387 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001388 * Perform calling of an activity's {@link Activity#onNewIntent}
1389 * method. The default implementation simply calls through to that method.
1390 *
1391 * @param activity The activity receiving a new Intent.
1392 * @param intent The new intent being received.
1393 */
1394 public void callActivityOnNewIntent(Activity activity, Intent intent) {
Winson Chung298f95b2017-08-10 15:57:18 -07001395 activity.performNewIntent(intent);
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001396 }
1397
1398 /**
1399 * @hide
1400 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001401 @UnsupportedAppUsage
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001402 public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001403 final String oldReferrer = activity.mReferrer;
1404 try {
Dianne Hackborn80b1c562014-12-09 20:22:08 -08001405 if (intent != null) {
1406 activity.mReferrer = intent.mReferrer;
1407 }
1408 callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001409 } finally {
1410 activity.mReferrer = oldReferrer;
1411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001412 }
1413
1414 /**
1415 * Perform calling of an activity's {@link Activity#onStart}
1416 * method. The default implementation simply calls through to that method.
1417 *
1418 * @param activity The activity being started.
1419 */
1420 public void callActivityOnStart(Activity activity) {
1421 activity.onStart();
1422 }
1423
1424 /**
1425 * Perform calling of an activity's {@link Activity#onRestart}
1426 * method. The default implementation simply calls through to that method.
1427 *
1428 * @param activity The activity being restarted.
1429 */
1430 public void callActivityOnRestart(Activity activity) {
1431 activity.onRestart();
1432 }
1433
1434 /**
1435 * Perform calling of an activity's {@link Activity#onResume} method. The
1436 * default implementation simply calls through to that method.
1437 *
1438 * @param activity The activity being resumed.
1439 */
1440 public void callActivityOnResume(Activity activity) {
Jeff Hamilton52d32032011-01-08 15:31:26 -06001441 activity.mResumed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001442 activity.onResume();
1443
1444 if (mActivityMonitors != null) {
1445 synchronized (mSync) {
1446 final int N = mActivityMonitors.size();
1447 for (int i=0; i<N; i++) {
1448 final ActivityMonitor am = mActivityMonitors.get(i);
1449 am.match(activity, activity, activity.getIntent());
1450 }
1451 }
1452 }
1453 }
1454
1455 /**
1456 * Perform calling of an activity's {@link Activity#onStop}
1457 * method. The default implementation simply calls through to that method.
1458 *
1459 * @param activity The activity being stopped.
1460 */
1461 public void callActivityOnStop(Activity activity) {
1462 activity.onStop();
1463 }
1464
1465 /**
Newton Allenc5027442013-08-13 11:22:32 -07001466 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1467 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001468 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001469 * @param activity The activity being saved.
1470 * @param outState The bundle to pass to the call.
1471 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001472 public void callActivityOnSaveInstanceState(@NonNull Activity activity,
1473 @NonNull Bundle outState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001474 activity.performSaveInstanceState(outState);
1475 }
1476
1477 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001478 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1479 * method. The default implementation simply calls through to that method.
1480 * @param activity The activity being saved.
1481 * @param outState The bundle to pass to the call.
1482 * @param outPersistentState The persistent bundle to pass to the call.
1483 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001484 public void callActivityOnSaveInstanceState(@NonNull Activity activity,
1485 @NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
Craig Mautnera0026042014-04-23 11:45:37 -07001486 activity.performSaveInstanceState(outState, outPersistentState);
1487 }
1488
1489 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001490 * Perform calling of an activity's {@link Activity#onPause} method. The
1491 * default implementation simply calls through to that method.
1492 *
1493 * @param activity The activity being paused.
1494 */
1495 public void callActivityOnPause(Activity activity) {
1496 activity.performPause();
1497 }
1498
1499 /**
1500 * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
1501 * The default implementation simply calls through to that method.
1502 *
1503 * @param activity The activity being notified that the user has navigated away
1504 */
1505 public void callActivityOnUserLeaving(Activity activity) {
1506 activity.performUserLeaving();
1507 }
1508
1509 /*
1510 * Starts allocation counting. This triggers a gc and resets the counts.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001511 *
1512 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001513 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001514 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001515 public void startAllocCounting() {
1516 // Before we start trigger a GC and reset the debug counts. Run the
1517 // finalizers and another GC before starting and stopping the alloc
1518 // counts. This will free up any objects that were just sitting around
1519 // waiting for their finalizers to be run.
1520 Runtime.getRuntime().gc();
1521 Runtime.getRuntime().runFinalization();
1522 Runtime.getRuntime().gc();
1523
1524 Debug.resetAllCounts();
1525
1526 // start the counts
1527 Debug.startAllocCounting();
1528 }
1529
1530 /*
1531 * Stops allocation counting.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001532 *
1533 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001534 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001535 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001536 public void stopAllocCounting() {
1537 Runtime.getRuntime().gc();
1538 Runtime.getRuntime().runFinalization();
1539 Runtime.getRuntime().gc();
1540 Debug.stopAllocCounting();
1541 }
1542
1543 /**
1544 * If Results already contains Key, it appends Value to the key's ArrayList
1545 * associated with the key. If the key doesn't already exist in results, it
1546 * adds the key/value pair to results.
1547 */
1548 private void addValue(String key, int value, Bundle results) {
1549 if (results.containsKey(key)) {
1550 List<Integer> list = results.getIntegerArrayList(key);
1551 if (list != null) {
1552 list.add(value);
1553 }
1554 } else {
1555 ArrayList<Integer> list = new ArrayList<Integer>();
1556 list.add(value);
1557 results.putIntegerArrayList(key, list);
1558 }
1559 }
1560
1561 /**
1562 * Returns a bundle with the current results from the allocation counting.
1563 */
1564 public Bundle getAllocCounts() {
1565 Bundle results = new Bundle();
1566 results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
1567 results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
1568 results.putLong("global_freed_count", Debug.getGlobalFreedCount());
1569 results.putLong("global_freed_size", Debug.getGlobalFreedSize());
1570 results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
1571 return results;
1572 }
1573
1574 /**
1575 * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
1576 * reported are the number of send and the number of received transactions.
1577 */
1578 public Bundle getBinderCounts() {
1579 Bundle results = new Bundle();
1580 results.putLong("sent_transactions", Debug.getBinderSentTransactions());
1581 results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
1582 return results;
1583 }
1584
1585 /**
1586 * Description of a Activity execution result to return to the original
1587 * activity.
1588 */
1589 public static final class ActivityResult {
1590 /**
1591 * Create a new activity result. See {@link Activity#setResult} for
1592 * more information.
1593 *
1594 * @param resultCode The result code to propagate back to the
1595 * originating activity, often RESULT_CANCELED or RESULT_OK
1596 * @param resultData The data to propagate back to the originating
1597 * activity.
1598 */
1599 public ActivityResult(int resultCode, Intent resultData) {
1600 mResultCode = resultCode;
1601 mResultData = resultData;
1602 }
1603
1604 /**
1605 * Retrieve the result code contained in this result.
1606 */
1607 public int getResultCode() {
1608 return mResultCode;
1609 }
1610
1611 /**
1612 * Retrieve the data contained in this result.
1613 */
1614 public Intent getResultData() {
1615 return mResultData;
1616 }
1617
1618 private final int mResultCode;
1619 private final Intent mResultData;
1620 }
1621
1622 /**
1623 * Execute a startActivity call made by the application. The default
1624 * implementation takes care of updating any active {@link ActivityMonitor}
1625 * objects and dispatches this call to the system activity manager; you can
1626 * override this to watch for the application to start an activity, and
1627 * modify what happens when it does.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001628 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001629 * <p>This method returns an {@link ActivityResult} object, which you can
1630 * use when intercepting application calls to avoid performing the start
1631 * activity action but still return the result the application is
1632 * expecting. To do this, override this method to catch the call to start
1633 * activity so that it returns a new ActivityResult containing the results
1634 * you would like the application to see, and don't call up to the super
1635 * class. Note that an application is only expecting a result if
1636 * <var>requestCode</var> is &gt;= 0.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001637 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001638 * <p>This method throws {@link android.content.ActivityNotFoundException}
1639 * if there was no Activity found to run the given Intent.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001640 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001641 * @param who The Context from which the activity is being started.
1642 * @param contextThread The main thread of the Context from which the activity
1643 * is being started.
1644 * @param token Internal token identifying to the system who is starting
1645 * the activity; may be null.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001646 * @param target Which activity is performing the start (and thus receiving
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001647 * any result); may be null if this call is not being made
1648 * from an activity.
1649 * @param intent The actual Intent to start.
1650 * @param requestCode Identifier for this request's result; less than zero
1651 * if the caller is not expecting a result.
Dianne Hackborna4972e92012-03-14 10:38:05 -07001652 * @param options Addition options.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001653 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001654 * @return To force the return of a particular result, return an
1655 * ActivityResult object containing the desired data; otherwise
1656 * return null. The default implementation always returns null.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001657 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 * @throws android.content.ActivityNotFoundException
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001659 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001660 * @see Activity#startActivity(Intent)
1661 * @see Activity#startActivityForResult(Intent, int)
1662 * @see Activity#startActivityFromChild
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001663 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 * {@hide}
1665 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001666 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001667 public ActivityResult execStartActivity(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001668 Context who, IBinder contextThread, IBinder token, Activity target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001669 Intent intent, int requestCode, Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001670 IApplicationThread whoThread = (IApplicationThread) contextThread;
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001671 Uri referrer = target != null ? target.onProvideReferrer() : null;
1672 if (referrer != null) {
1673 intent.putExtra(Intent.EXTRA_REFERRER, referrer);
1674 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001675 if (mActivityMonitors != null) {
1676 synchronized (mSync) {
1677 final int N = mActivityMonitors.size();
1678 for (int i=0; i<N; i++) {
1679 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001680 ActivityResult result = null;
1681 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001682 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001683 }
1684 if (result != null) {
1685 am.mHits++;
1686 return result;
1687 } else if (am.match(who, null, intent)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001688 am.mHits++;
1689 if (am.isBlocking()) {
1690 return requestCode >= 0 ? am.getResult() : null;
1691 }
1692 break;
1693 }
1694 }
1695 }
1696 }
1697 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001698 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001699 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001700 int result = ActivityTaskManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001701 .startActivity(whoThread, who.getBasePackageName(), intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001702 intent.resolveTypeIfNeeded(who.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07001703 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001704 requestCode, 0, null, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001705 checkStartActivityResult(result, intent);
1706 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001707 throw new RuntimeException("Failure from system", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001708 }
1709 return null;
1710 }
1711
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001712 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001713 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001714 * but accepts an array of activities to be started. Note that active
1715 * {@link ActivityMonitor} objects only match against the first activity in
1716 * the array.
1717 *
1718 * {@hide}
1719 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001720 @UnsupportedAppUsage
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001721 public void execStartActivities(Context who, IBinder contextThread,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001722 IBinder token, Activity target, Intent[] intents, Bundle options) {
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001723 execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
Jeff Sharkeyad357d12018-02-02 13:25:31 -07001724 who.getUserId());
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001725 }
1726
1727 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001728 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001729 * but accepts an array of activities to be started. Note that active
1730 * {@link ActivityMonitor} objects only match against the first activity in
1731 * the array.
1732 *
Selim Cinek7fa385a2018-01-24 08:35:28 -08001733 * @return The corresponding flag {@link ActivityManager#START_CANCELED},
1734 * {@link ActivityManager#START_SUCCESS} etc. indicating whether the launch was
1735 * successful.
1736 *
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001737 * {@hide}
1738 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001739 @UnsupportedAppUsage
Selim Cinek7fa385a2018-01-24 08:35:28 -08001740 public int execStartActivitiesAsUser(Context who, IBinder contextThread,
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001741 IBinder token, Activity target, Intent[] intents, Bundle options,
1742 int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001743 IApplicationThread whoThread = (IApplicationThread) contextThread;
1744 if (mActivityMonitors != null) {
1745 synchronized (mSync) {
1746 final int N = mActivityMonitors.size();
1747 for (int i=0; i<N; i++) {
1748 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001749 ActivityResult result = null;
1750 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001751 result = am.onStartActivity(intents[0]);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001752 }
1753 if (result != null) {
1754 am.mHits++;
Selim Cinek7fa385a2018-01-24 08:35:28 -08001755 return ActivityManager.START_CANCELED;
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001756 } else if (am.match(who, null, intents[0])) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001757 am.mHits++;
1758 if (am.isBlocking()) {
Selim Cinek7fa385a2018-01-24 08:35:28 -08001759 return ActivityManager.START_CANCELED;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001760 }
1761 break;
1762 }
1763 }
1764 }
1765 }
1766 try {
1767 String[] resolvedTypes = new String[intents.length];
1768 for (int i=0; i<intents.length; i++) {
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001769 intents[i].migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001770 intents[i].prepareToLeaveProcess(who);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001771 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
1772 }
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001773 int result = ActivityTaskManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001774 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
1775 token, options, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001776 checkStartActivityResult(result, intents[0]);
Selim Cinek7fa385a2018-01-24 08:35:28 -08001777 return result;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001778 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001779 throw new RuntimeException("Failure from system", e);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001780 }
1781 }
1782
1783 /**
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001784 * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001785 * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)},
Andrew Solovay5c05ded2018-10-02 14:14:42 -07001786 * but for calls from a {@link Fragment}.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001787 *
1788 * @param who The Context from which the activity is being started.
1789 * @param contextThread The main thread of the Context from which the activity
1790 * is being started.
1791 * @param token Internal token identifying to the system who is starting
1792 * the activity; may be null.
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001793 * @param target Which element is performing the start (and thus receiving
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001794 * any result).
1795 * @param intent The actual Intent to start.
1796 * @param requestCode Identifier for this request's result; less than zero
1797 * if the caller is not expecting a result.
1798 *
1799 * @return To force the return of a particular result, return an
1800 * ActivityResult object containing the desired data; otherwise
1801 * return null. The default implementation always returns null.
1802 *
1803 * @throws android.content.ActivityNotFoundException
1804 *
1805 * @see Activity#startActivity(Intent)
1806 * @see Activity#startActivityForResult(Intent, int)
1807 * @see Activity#startActivityFromChild
1808 *
1809 * {@hide}
1810 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001811 @UnsupportedAppUsage
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001812 public ActivityResult execStartActivity(
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001813 Context who, IBinder contextThread, IBinder token, String target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001814 Intent intent, int requestCode, Bundle options) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001815 IApplicationThread whoThread = (IApplicationThread) contextThread;
1816 if (mActivityMonitors != null) {
1817 synchronized (mSync) {
1818 final int N = mActivityMonitors.size();
1819 for (int i=0; i<N; i++) {
1820 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001821 ActivityResult result = null;
1822 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001823 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001824 }
1825 if (result != null) {
1826 am.mHits++;
1827 return result;
1828 } else if (am.match(who, null, intent)) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001829 am.mHits++;
1830 if (am.isBlocking()) {
1831 return requestCode >= 0 ? am.getResult() : null;
1832 }
1833 break;
1834 }
1835 }
1836 }
1837 }
1838 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001839 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001840 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001841 int result = ActivityTaskManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001842 .startActivity(whoThread, who.getBasePackageName(), intent,
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001843 intent.resolveTypeIfNeeded(who.getContentResolver()),
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001844 token, target, requestCode, 0, null, options);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001845 checkStartActivityResult(result, intent);
1846 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001847 throw new RuntimeException("Failure from system", e);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001848 }
1849 return null;
1850 }
1851
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001852 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001853 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
1854 * but for starting as a particular user.
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001855 *
1856 * @param who The Context from which the activity is being started.
1857 * @param contextThread The main thread of the Context from which the activity
1858 * is being started.
1859 * @param token Internal token identifying to the system who is starting
1860 * the activity; may be null.
1861 * @param target Which fragment is performing the start (and thus receiving
1862 * any result).
1863 * @param intent The actual Intent to start.
1864 * @param requestCode Identifier for this request's result; less than zero
1865 * if the caller is not expecting a result.
1866 *
1867 * @return To force the return of a particular result, return an
1868 * ActivityResult object containing the desired data; otherwise
1869 * return null. The default implementation always returns null.
1870 *
1871 * @throws android.content.ActivityNotFoundException
1872 *
1873 * @see Activity#startActivity(Intent)
1874 * @see Activity#startActivityForResult(Intent, int)
1875 * @see Activity#startActivityFromChild
1876 *
1877 * {@hide}
1878 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001879 @UnsupportedAppUsage
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001880 public ActivityResult execStartActivity(
Tony Mak96d26fe2017-04-11 20:05:39 +01001881 Context who, IBinder contextThread, IBinder token, String resultWho,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001882 Intent intent, int requestCode, Bundle options, UserHandle user) {
1883 IApplicationThread whoThread = (IApplicationThread) contextThread;
1884 if (mActivityMonitors != null) {
1885 synchronized (mSync) {
1886 final int N = mActivityMonitors.size();
1887 for (int i=0; i<N; i++) {
1888 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001889 ActivityResult result = null;
1890 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001891 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001892 }
1893 if (result != null) {
1894 am.mHits++;
1895 return result;
1896 } else if (am.match(who, null, intent)) {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001897 am.mHits++;
1898 if (am.isBlocking()) {
1899 return requestCode >= 0 ? am.getResult() : null;
1900 }
1901 break;
1902 }
1903 }
1904 }
1905 }
1906 try {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001907 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001908 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001909 int result = ActivityTaskManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001910 .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001911 intent.resolveTypeIfNeeded(who.getContentResolver()),
Tony Mak96d26fe2017-04-11 20:05:39 +01001912 token, resultWho,
Jeff Hao1b012d32014-08-20 10:35:34 -07001913 requestCode, 0, null, options, user.getIdentifier());
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001914 checkStartActivityResult(result, intent);
1915 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001916 throw new RuntimeException("Failure from system", e);
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001917 }
1918 return null;
1919 }
1920
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001921 /**
1922 * Special version!
1923 * @hide
1924 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001925 @UnsupportedAppUsage
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001926 public ActivityResult execStartActivityAsCaller(
1927 Context who, IBinder contextThread, IBinder token, Activity target,
Alison Cichowlas3e340502018-08-07 17:15:01 -04001928 Intent intent, int requestCode, Bundle options, IBinder permissionToken,
1929 boolean ignoreTargetSecurity, int userId) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001930 IApplicationThread whoThread = (IApplicationThread) contextThread;
1931 if (mActivityMonitors != null) {
1932 synchronized (mSync) {
1933 final int N = mActivityMonitors.size();
1934 for (int i=0; i<N; i++) {
1935 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001936 ActivityResult result = null;
1937 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001938 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001939 }
1940 if (result != null) {
1941 am.mHits++;
1942 return result;
1943 } else if (am.match(who, null, intent)) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001944 am.mHits++;
1945 if (am.isBlocking()) {
1946 return requestCode >= 0 ? am.getResult() : null;
1947 }
1948 break;
1949 }
1950 }
1951 }
1952 }
1953 try {
1954 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001955 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001956 int result = ActivityTaskManager.getService()
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001957 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
1958 intent.resolveTypeIfNeeded(who.getContentResolver()),
1959 token, target != null ? target.mEmbeddedID : null,
Alison Cichowlas3e340502018-08-07 17:15:01 -04001960 requestCode, 0, null, options, permissionToken,
1961 ignoreTargetSecurity, userId);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001962 checkStartActivityResult(result, intent);
1963 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001964 throw new RuntimeException("Failure from system", e);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001965 }
1966 return null;
1967 }
1968
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001969 /**
1970 * Special version!
1971 * @hide
1972 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001973 @UnsupportedAppUsage
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001974 public void execStartActivityFromAppTask(
1975 Context who, IBinder contextThread, IAppTask appTask,
1976 Intent intent, Bundle options) {
1977 IApplicationThread whoThread = (IApplicationThread) contextThread;
1978 if (mActivityMonitors != null) {
1979 synchronized (mSync) {
1980 final int N = mActivityMonitors.size();
1981 for (int i=0; i<N; i++) {
1982 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001983 ActivityResult result = null;
1984 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001985 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001986 }
1987 if (result != null) {
1988 am.mHits++;
1989 return;
1990 } else if (am.match(who, null, intent)) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001991 am.mHits++;
1992 if (am.isBlocking()) {
1993 return;
1994 }
1995 break;
1996 }
1997 }
1998 }
1999 }
2000 try {
2001 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07002002 intent.prepareToLeaveProcess(who);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07002003 int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
2004 intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options);
2005 checkStartActivityResult(result, intent);
2006 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07002007 throw new RuntimeException("Failure from system", e);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07002008 }
2009 return;
2010 }
2011
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002012 /*package*/ final void init(ActivityThread thread,
2013 Context instrContext, Context appContext, ComponentName component,
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002014 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002015 mThread = thread;
2016 mMessageQueue = mThread.getLooper().myQueue();
2017 mInstrContext = instrContext;
2018 mAppContext = appContext;
2019 mComponent = component;
2020 mWatcher = watcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002021 mUiAutomationConnection = uiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002022 }
2023
Jason Monka80bfb52017-11-16 17:15:37 -05002024 /**
2025 * Only sets the ActivityThread up, keeps everything else null because app is not being
2026 * instrumented.
2027 */
2028 final void basicInit(ActivityThread thread) {
2029 mThread = thread;
2030 }
2031
Dianne Hackborn91097de2014-04-04 18:02:06 -07002032 /** @hide */
Mathew Inwood31755f92018-12-20 13:53:36 +00002033 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Dianne Hackborn91097de2014-04-04 18:02:06 -07002034 public static void checkStartActivityResult(int res, Object intent) {
Bryce Lee7f936862017-05-09 15:33:18 -07002035 if (!ActivityManager.isStartResultFatalError(res)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002036 return;
2037 }
Amith Yamasani42449782016-04-19 11:45:51 -07002038
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002039 switch (res) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07002040 case ActivityManager.START_INTENT_NOT_RESOLVED:
2041 case ActivityManager.START_CLASS_NOT_FOUND:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002042 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 throw new ActivityNotFoundException(
2044 "Unable to find explicit activity class "
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002045 + ((Intent)intent).getComponent().toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002046 + "; have you declared this activity in your AndroidManifest.xml?");
2047 throw new ActivityNotFoundException(
2048 "No Activity found to handle " + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002049 case ActivityManager.START_PERMISSION_DENIED:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 throw new SecurityException("Not allowed to start activity "
2051 + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002052 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002053 throw new AndroidRuntimeException(
2054 "FORWARD_RESULT_FLAG used while also requesting a result");
Dianne Hackborna4972e92012-03-14 10:38:05 -07002055 case ActivityManager.START_NOT_ACTIVITY:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002056 throw new IllegalArgumentException(
2057 "PendingIntent is not an activity");
Dianne Hackborn91097de2014-04-04 18:02:06 -07002058 case ActivityManager.START_NOT_VOICE_COMPATIBLE:
2059 throw new SecurityException(
2060 "Starting under voice control not allowed for: " + intent);
Amith Yamasani42449782016-04-19 11:45:51 -07002061 case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
2062 throw new IllegalStateException(
2063 "Session calling startVoiceActivity does not match active session");
2064 case ActivityManager.START_VOICE_HIDDEN_SESSION:
2065 throw new IllegalStateException(
2066 "Cannot start voice activity on a hidden session");
Winson Chungfc3ec4c2017-06-01 15:35:48 -07002067 case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
2068 throw new IllegalStateException(
2069 "Session calling startAssistantActivity does not match active session");
2070 case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
2071 throw new IllegalStateException(
2072 "Cannot start assistant activity on a hidden session");
Amith Yamasani42449782016-04-19 11:45:51 -07002073 case ActivityManager.START_CANCELED:
2074 throw new AndroidRuntimeException("Activity could not be started for "
2075 + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002076 default:
2077 throw new AndroidRuntimeException("Unknown error code "
2078 + res + " when starting " + intent);
2079 }
2080 }
Chong Zhang45c25ce2015-08-10 22:18:26 -07002081
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002082 private final void validateNotAppThread() {
Kristian Monsen0a303282013-01-18 14:50:07 -08002083 if (Looper.myLooper() == Looper.getMainLooper()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002084 throw new RuntimeException(
2085 "This method can not be called from the main application thread");
2086 }
2087 }
2088
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002089 /**
Phil Weaverd8e88832016-03-28 17:26:25 -07002090 * Gets the {@link UiAutomation} instance with no flags set.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002091 * <p>
2092 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
2093 * work across application boundaries while the APIs exposed by the instrumentation
2094 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
2095 * not allow you to inject the event in an app different from the instrumentation
2096 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
2097 * will work regardless of the current application.
2098 * </p>
2099 * <p>
2100 * A typical test case should be using either the {@link UiAutomation} or
2101 * {@link Instrumentation} APIs. Using both APIs at the same time is not
2102 * a mistake by itself but a client has to be aware of the APIs limitations.
2103 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07002104 * <p>
2105 * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different
2106 * flags, the flags on that instance will be changed, and then it will be returned.
2107 * </p>
2108 * @return The UI automation instance.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002109 *
2110 * @see UiAutomation
2111 */
2112 public UiAutomation getUiAutomation() {
Phil Weaverd8e88832016-03-28 17:26:25 -07002113 return getUiAutomation(0);
Phil Weaver1dd87222016-01-26 17:15:15 -08002114 }
2115
2116 /**
2117 * Gets the {@link UiAutomation} instance with flags set.
2118 * <p>
Phil Weaver1dd87222016-01-26 17:15:15 -08002119 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
2120 * work across application boundaries while the APIs exposed by the instrumentation
2121 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
2122 * not allow you to inject the event in an app different from the instrumentation
2123 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
2124 * will work regardless of the current application.
2125 * </p>
2126 * <p>
2127 * A typical test case should be using either the {@link UiAutomation} or
2128 * {@link Instrumentation} APIs. Using both APIs at the same time is not
2129 * a mistake by itself but a client has to be aware of the APIs limitations.
2130 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07002131 * <p>
2132 * If a {@link UiAutomation} exists with different flags, the flags on that instance will be
2133 * changed, and then it will be returned.
2134 * </p>
Phil Weaver1dd87222016-01-26 17:15:15 -08002135 *
2136 * @param flags The flags to be passed to the UiAutomation, for example
2137 * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
2138 *
2139 * @return The UI automation instance.
2140 *
2141 * @see UiAutomation
2142 */
Phil Weaver35841682016-03-09 09:52:51 -08002143 public UiAutomation getUiAutomation(@UiAutomationFlags int flags) {
Phil Weaverd8e88832016-03-28 17:26:25 -07002144 boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed());
2145
Phil Weaver1dd87222016-01-26 17:15:15 -08002146 if (mUiAutomationConnection != null) {
Phil Weaverd8e88832016-03-28 17:26:25 -07002147 if (!mustCreateNewAutomation && (mUiAutomation.getFlags() == flags)) {
2148 return mUiAutomation;
2149 }
2150 if (mustCreateNewAutomation) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002151 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
2152 mUiAutomationConnection);
Phil Weaver1dd87222016-01-26 17:15:15 -08002153 } else {
Phil Weaverd8e88832016-03-28 17:26:25 -07002154 mUiAutomation.disconnect();
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002155 }
Phil Weaverd8e88832016-03-28 17:26:25 -07002156 mUiAutomation.connect(flags);
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002157 return mUiAutomation;
2158 }
2159 return null;
2160 }
2161
Jason Monk5be50f72017-03-10 10:57:34 -05002162 /**
2163 * Takes control of the execution of messages on the specified looper until
2164 * {@link TestLooperManager#release} is called.
2165 */
2166 public TestLooperManager acquireLooperManager(Looper looper) {
2167 checkInstrumenting("acquireLooperManager");
2168 return new TestLooperManager(looper);
2169 }
2170
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002171 private final class InstrumentationThread extends Thread {
2172 public InstrumentationThread(String name) {
2173 super(name);
2174 }
2175 public void run() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002176 try {
2177 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
2178 } catch (RuntimeException e) {
Phil Weaver1dd87222016-01-26 17:15:15 -08002179 Log.w(TAG, "Exception setting priority of instrumentation thread "
2180 + Process.myTid(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002181 }
2182 if (mAutomaticPerformanceSnapshots) {
2183 startPerformanceSnapshot();
2184 }
2185 onStart();
2186 }
2187 }
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002188
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002189 private static final class EmptyRunnable implements Runnable {
2190 public void run() {
2191 }
2192 }
2193
2194 private static final class SyncRunnable implements Runnable {
2195 private final Runnable mTarget;
2196 private boolean mComplete;
2197
2198 public SyncRunnable(Runnable target) {
2199 mTarget = target;
2200 }
2201
2202 public void run() {
2203 mTarget.run();
2204 synchronized (this) {
2205 mComplete = true;
2206 notifyAll();
2207 }
2208 }
2209
2210 public void waitForComplete() {
2211 synchronized (this) {
2212 while (!mComplete) {
2213 try {
2214 wait();
2215 } catch (InterruptedException e) {
2216 }
2217 }
2218 }
2219 }
2220 }
2221
2222 private static final class ActivityWaiter {
2223 public final Intent intent;
2224 public Activity activity;
2225
2226 public ActivityWaiter(Intent _intent) {
2227 intent = _intent;
2228 }
2229 }
2230
2231 private final class ActivityGoing implements MessageQueue.IdleHandler {
2232 private final ActivityWaiter mWaiter;
2233
2234 public ActivityGoing(ActivityWaiter waiter) {
2235 mWaiter = waiter;
2236 }
2237
2238 public final boolean queueIdle() {
2239 synchronized (mSync) {
2240 mWaitingActivities.remove(mWaiter);
2241 mSync.notifyAll();
2242 }
2243 return false;
2244 }
2245 }
2246
2247 private static final class Idler implements MessageQueue.IdleHandler {
2248 private final Runnable mCallback;
2249 private boolean mIdle;
2250
2251 public Idler(Runnable callback) {
2252 mCallback = callback;
2253 mIdle = false;
2254 }
2255
2256 public final boolean queueIdle() {
2257 if (mCallback != null) {
2258 mCallback.run();
2259 }
2260 synchronized (this) {
2261 mIdle = true;
2262 notifyAll();
2263 }
2264 return false;
2265 }
2266
2267 public void waitForIdle() {
2268 synchronized (this) {
2269 while (!mIdle) {
2270 try {
2271 wait();
2272 } catch (InterruptedException e) {
2273 }
2274 }
2275 }
2276 }
2277 }
2278}