blob: 4f94209466804e105a63209ea53eb08068fcbebf [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;
chaviw9f4bc552019-02-27 15:22:47 -080055import android.view.WindowManagerGlobal;
Winson Chung298f95b2017-08-10 15:57:18 -070056
Dianne Hackborn85d558c2014-11-04 10:31:54 -080057import com.android.internal.content.ReferrerIntent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058
59import java.io.File;
Phil Weaver35841682016-03-09 09:52:51 -080060import java.lang.annotation.Retention;
61import java.lang.annotation.RetentionPolicy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import java.util.ArrayList;
63import java.util.List;
64
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065/**
66 * Base class for implementing application instrumentation code. When running
67 * with instrumentation turned on, this class will be instantiated for you
68 * before any of the application code, allowing you to monitor all of the
69 * interaction the system has with the application. An Instrumentation
70 * implementation is described to the system through an AndroidManifest.xml's
71 * <instrumentation> tag.
72 */
73public class Instrumentation {
Svetoslav Ganov80943d82013-01-02 10:25:37 -080074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 /**
76 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
77 * identifies the class that is writing the report. This can be used to provide more structured
78 * logging or reporting capabilities in the IInstrumentationWatcher.
79 */
80 public static final String REPORT_KEY_IDENTIFIER = "id";
81 /**
82 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
83 * identifies a string which can simply be printed to the output stream. Using these streams
84 * provides a "pretty printer" version of the status & final packets. Any bundles including
85 * this key should also include the complete set of raw key/value pairs, so that the
86 * instrumentation can also be launched, and results collected, by an automated system.
87 */
88 public static final String REPORT_KEY_STREAMRESULT = "stream";
Svetoslav Ganov80943d82013-01-02 10:25:37 -080089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090 private static final String TAG = "Instrumentation";
Phil Weaver35841682016-03-09 09:52:51 -080091
92 /**
93 * @hide
94 */
95 @Retention(RetentionPolicy.SOURCE)
96 @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES})
97 public @interface UiAutomationFlags {};
98
99
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800100 private final Object mSync = new Object();
101 private ActivityThread mThread = null;
102 private MessageQueue mMessageQueue = null;
103 private Context mInstrContext;
104 private Context mAppContext;
105 private ComponentName mComponent;
106 private Thread mRunner;
107 private List<ActivityWaiter> mWaitingActivities;
108 private List<ActivityMonitor> mActivityMonitors;
109 private IInstrumentationWatcher mWatcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800110 private IUiAutomationConnection mUiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 private boolean mAutomaticPerformanceSnapshots = false;
Jack Wangff1df692009-08-26 17:19:13 -0700112 private PerformanceCollector mPerformanceCollector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 private Bundle mPerfMetrics = new Bundle();
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800114 private UiAutomation mUiAutomation;
chaviwfeb2e1e2018-12-19 17:24:11 -0800115 private final Object mAnimationCompleteLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116
117 public Instrumentation() {
118 }
119
120 /**
Jason Monk5be50f72017-03-10 10:57:34 -0500121 * Called for methods that shouldn't be called by standard apps and
122 * should only be used in instrumentation environments. This is not
123 * security feature as these classes will still be accessible through
124 * reflection, but it will serve as noticeable discouragement from
125 * doing such a thing.
126 */
127 private void checkInstrumenting(String method) {
128 // Check if we have an instrumentation context, as init should only get called by
129 // the system in startup processes that are being instrumented.
130 if (mInstrContext == null) {
131 throw new RuntimeException(method +
132 " cannot be called outside of instrumented processes");
133 }
134 }
135
136 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800137 * Called when the instrumentation is starting, before any application code
138 * has been loaded. Usually this will be implemented to simply call
139 * {@link #start} to begin the instrumentation thread, which will then
140 * continue execution in {@link #onStart}.
141 *
142 * <p>If you do not need your own thread -- that is you are writing your
143 * instrumentation to be completely asynchronous (returning to the event
144 * loop so that the application can run), you can simply begin your
145 * instrumentation here, for example call {@link Context#startActivity} to
146 * begin the appropriate first activity of the application.
147 *
148 * @param arguments Any additional arguments that were supplied when the
149 * instrumentation was started.
150 */
151 public void onCreate(Bundle arguments) {
152 }
153
154 /**
155 * Create and start a new thread in which to run instrumentation. This new
156 * thread will call to {@link #onStart} where you can implement the
157 * instrumentation.
158 */
159 public void start() {
160 if (mRunner != null) {
161 throw new RuntimeException("Instrumentation already started");
162 }
163 mRunner = new InstrumentationThread("Instr: " + getClass().getName());
164 mRunner.start();
165 }
166
167 /**
168 * Method where the instrumentation thread enters execution. This allows
169 * you to run your instrumentation code in a separate thread than the
170 * application, so that it can perform blocking operation such as
171 * {@link #sendKeySync} or {@link #startActivitySync}.
172 *
173 * <p>You will typically want to call finish() when this function is done,
174 * to end your instrumentation.
175 */
176 public void onStart() {
177 }
178
179 /**
180 * This is called whenever the system captures an unhandled exception that
181 * was thrown by the application. The default implementation simply
182 * returns false, allowing normal system handling of the exception to take
183 * place.
184 *
185 * @param obj The client object that generated the exception. May be an
186 * Application, Activity, BroadcastReceiver, Service, or null.
187 * @param e The exception that was thrown.
188 *
189 * @return To allow normal system exception process to occur, return false.
190 * If true is returned, the system will proceed as if the exception
191 * didn't happen.
192 */
193 public boolean onException(Object obj, Throwable e) {
194 return false;
195 }
196
197 /**
198 * Provide a status report about the application.
199 *
200 * @param resultCode Current success/failure of instrumentation.
201 * @param results Any results to send back to the code that started the instrumentation.
202 */
203 public void sendStatus(int resultCode, Bundle results) {
204 if (mWatcher != null) {
205 try {
206 mWatcher.instrumentationStatus(mComponent, resultCode, results);
207 }
208 catch (RemoteException e) {
209 mWatcher = null;
210 }
211 }
212 }
Dianne Hackborn34041732017-01-31 15:27:13 -0800213
214 /**
215 * Report some results in the middle of instrumentation execution. Later results (including
216 * those provided by {@link #finish}) will be combined with {@link Bundle#putAll}.
217 */
218 public void addResults(Bundle results) {
219 IActivityManager am = ActivityManager.getService();
220 try {
221 am.addInstrumentationResults(mThread.getApplicationThread(), results);
222 } catch (RemoteException ex) {
223 throw ex.rethrowFromSystemServer();
224 }
225 }
226
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 /**
228 * Terminate instrumentation of the application. This will cause the
229 * application process to exit, removing this instrumentation from the next
Dianne Hackborn34041732017-01-31 15:27:13 -0800230 * time the application is started. If multiple processes are currently running
231 * for this instrumentation, all of those processes will be killed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 *
233 * @param resultCode Overall success/failure of instrumentation.
234 * @param results Any results to send back to the code that started the
235 * instrumentation.
236 */
237 public void finish(int resultCode, Bundle results) {
238 if (mAutomaticPerformanceSnapshots) {
239 endPerformanceSnapshot();
240 }
241 if (mPerfMetrics != null) {
Dianne Hackbornb65ea7b2014-06-20 12:18:55 -0700242 if (results == null) {
243 results = new Bundle();
244 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 results.putAll(mPerfMetrics);
246 }
Phil Weaverd8e88832016-03-28 17:26:25 -0700247 if ((mUiAutomation != null) && !mUiAutomation.isDestroyed()) {
Adam Momtaz8f6f1f42013-04-10 12:42:58 -0700248 mUiAutomation.disconnect();
249 mUiAutomation = null;
250 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800251 mThread.finishInstrumentation(resultCode, results);
252 }
253
254 public void setAutomaticPerformanceSnapshots() {
255 mAutomaticPerformanceSnapshots = true;
Jack Wangff1df692009-08-26 17:19:13 -0700256 mPerformanceCollector = new PerformanceCollector();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 }
258
259 public void startPerformanceSnapshot() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800260 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700261 mPerformanceCollector.beginSnapshot(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 }
263 }
264
265 public void endPerformanceSnapshot() {
266 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700267 mPerfMetrics = mPerformanceCollector.endSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800268 }
269 }
270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 /**
272 * Called when the instrumented application is stopping, after all of the
273 * normal application cleanup has occurred.
274 */
275 public void onDestroy() {
276 }
277
278 /**
279 * Return the Context of this instrumentation's package. Note that this is
280 * often different than the Context of the application being
281 * instrumentated, since the instrumentation code often lives is a
282 * different package than that of the application it is running against.
283 * See {@link #getTargetContext} to retrieve a Context for the target
284 * application.
285 *
286 * @return The instrumentation's package context.
287 *
288 * @see #getTargetContext
289 */
290 public Context getContext() {
291 return mInstrContext;
292 }
293
294 /**
295 * Returns complete component name of this instrumentation.
296 *
297 * @return Returns the complete component name for this instrumentation.
298 */
299 public ComponentName getComponentName() {
300 return mComponent;
301 }
302
303 /**
304 * Return a Context for the target application being instrumented. Note
305 * that this is often different than the Context of the instrumentation
306 * code, since the instrumentation code often lives is a different package
307 * than that of the application it is running against. See
308 * {@link #getContext} to retrieve a Context for the instrumentation code.
309 *
310 * @return A Context in the target application.
311 *
312 * @see #getContext
313 */
314 public Context getTargetContext() {
315 return mAppContext;
316 }
317
318 /**
Dianne Hackborn34041732017-01-31 15:27:13 -0800319 * Return the name of the process this instrumentation is running in. Note this should
320 * only be used for testing and debugging. If you are thinking about using this to,
321 * for example, conditionalize what is initialized in an Application class, it is strongly
322 * recommended to instead use lazy initialization (such as a getter for the state that
323 * only creates it when requested). This can greatly reduce the work your process does
324 * when created for secondary things, such as to receive a broadcast.
325 */
326 public String getProcessName() {
327 return mThread.getProcessName();
328 }
329
330 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800331 * Check whether this instrumentation was started with profiling enabled.
332 *
333 * @return Returns true if profiling was enabled when starting, else false.
334 */
335 public boolean isProfiling() {
336 return mThread.isProfiling();
337 }
338
339 /**
340 * This method will start profiling if isProfiling() returns true. You should
341 * only call this method if you set the handleProfiling attribute in the
342 * manifest file for this Instrumentation to true.
343 */
344 public void startProfiling() {
345 if (mThread.isProfiling()) {
346 File file = new File(mThread.getProfileFilePath());
347 file.getParentFile().mkdirs();
348 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
349 }
350 }
351
352 /**
353 * Stops profiling if isProfiling() returns true.
354 */
355 public void stopProfiling() {
356 if (mThread.isProfiling()) {
357 Debug.stopMethodTracing();
358 }
359 }
360
361 /**
362 * Force the global system in or out of touch mode. This can be used if
363 * your instrumentation relies on the UI being in one more or the other
364 * when it starts.
365 *
366 * @param inTouch Set to true to be in touch mode, false to be in
367 * focus mode.
368 */
369 public void setInTouchMode(boolean inTouch) {
370 try {
371 IWindowManager.Stub.asInterface(
372 ServiceManager.getService("window")).setInTouchMode(inTouch);
373 } catch (RemoteException e) {
374 // Shouldn't happen!
375 }
376 }
377
378 /**
379 * Schedule a callback for when the application's main thread goes idle
380 * (has no more events to process).
381 *
382 * @param recipient Called the next time the thread's message queue is
383 * idle.
384 */
385 public void waitForIdle(Runnable recipient) {
386 mMessageQueue.addIdleHandler(new Idler(recipient));
387 mThread.getHandler().post(new EmptyRunnable());
388 }
389
390 /**
391 * Synchronously wait for the application to be idle. Can not be called
392 * from the main application thread -- use {@link #start} to execute
393 * instrumentation in its own thread.
394 */
395 public void waitForIdleSync() {
396 validateNotAppThread();
397 Idler idler = new Idler(null);
398 mMessageQueue.addIdleHandler(idler);
399 mThread.getHandler().post(new EmptyRunnable());
400 idler.waitForIdle();
401 }
402
chaviwfeb2e1e2018-12-19 17:24:11 -0800403 private void waitForEnterAnimationComplete(Activity activity) {
404 synchronized (mAnimationCompleteLock) {
405 long timeout = 5000;
406 try {
407 // We need to check that this specified Activity completed the animation, not just
408 // any Activity. If it was another Activity, then decrease the timeout by how long
409 // it's already waited and wait for the thread to wakeup again.
410 while (timeout > 0 && !activity.mEnterAnimationComplete) {
411 long startTime = System.currentTimeMillis();
412 mAnimationCompleteLock.wait(timeout);
413 long totalTime = System.currentTimeMillis() - startTime;
414 timeout -= totalTime;
415 }
416 } catch (InterruptedException e) {
417 }
418 }
419 }
420
421 /** @hide */
422 public void onEnterAnimationComplete() {
423 synchronized (mAnimationCompleteLock) {
424 mAnimationCompleteLock.notifyAll();
425 }
426 }
427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 /**
429 * Execute a call on the application's main thread, blocking until it is
430 * complete. Useful for doing things that are not thread-safe, such as
431 * looking at or modifying the view hierarchy.
432 *
433 * @param runner The code to run on the main thread.
434 */
435 public void runOnMainSync(Runnable runner) {
436 validateNotAppThread();
437 SyncRunnable sr = new SyncRunnable(runner);
438 mThread.getHandler().post(sr);
439 sr.waitForComplete();
440 }
441
442 /**
443 * Start a new activity and wait for it to begin running before returning.
444 * In addition to being synchronous, this method as some semantic
445 * differences from the standard {@link Context#startActivity} call: the
446 * activity component is resolved before talking with the activity manager
447 * (its class name is specified in the Intent that this method ultimately
448 * starts), and it does not allow you to start activities that run in a
449 * different process. In addition, if the given Intent resolves to
450 * multiple activities, instead of displaying a dialog for the user to
451 * select an activity, an exception will be thrown.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000452 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 * <p>The function returns as soon as the activity goes idle following the
454 * call to its {@link Activity#onCreate}. Generally this means it has gone
455 * through the full initialization including {@link Activity#onResume} and
456 * drawn and displayed its initial window.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000457 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800458 * @param intent Description of the activity to start.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000459 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 * @see Context#startActivity
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000461 * @see #startActivitySync(Intent, Bundle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 */
463 public Activity startActivitySync(Intent intent) {
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000464 return startActivitySync(intent, null /* options */);
465 }
466
467 /**
468 * Start a new activity and wait for it to begin running before returning.
469 * In addition to being synchronous, this method as some semantic
470 * differences from the standard {@link Context#startActivity} call: the
471 * activity component is resolved before talking with the activity manager
472 * (its class name is specified in the Intent that this method ultimately
473 * starts), and it does not allow you to start activities that run in a
474 * different process. In addition, if the given Intent resolves to
475 * multiple activities, instead of displaying a dialog for the user to
476 * select an activity, an exception will be thrown.
477 *
478 * <p>The function returns as soon as the activity goes idle following the
479 * call to its {@link Activity#onCreate}. Generally this means it has gone
480 * through the full initialization including {@link Activity#onResume} and
481 * drawn and displayed its initial window.
482 *
483 * @param intent Description of the activity to start.
484 * @param options Additional options for how the Activity should be started.
485 * May be null if there are no options. See {@link android.app.ActivityOptions}
486 * for how to build the Bundle supplied here; there are no supported definitions
487 * for building it manually.
488 *
489 * @see Context#startActivity(Intent, Bundle)
490 */
Wale Ogunwale2632c972018-01-22 06:54:48 -0800491 @NonNull
492 public Activity startActivitySync(@NonNull Intent intent, @Nullable Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493 validateNotAppThread();
494
495 synchronized (mSync) {
496 intent = new Intent(intent);
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800498 ActivityInfo ai = intent.resolveActivityInfo(
499 getTargetContext().getPackageManager(), 0);
500 if (ai == null) {
501 throw new RuntimeException("Unable to resolve activity for: " + intent);
502 }
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700503 String myProc = mThread.getProcessName();
504 if (!ai.processName.equals(myProc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800505 // todo: if this intent is ambiguous, look here to see if
506 // there is a single match that is in our package.
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700507 throw new RuntimeException("Intent in process "
508 + myProc + " resolved to different process "
509 + ai.processName + ": " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 }
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000511
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 intent.setComponent(new ComponentName(
513 ai.applicationInfo.packageName, ai.name));
514 final ActivityWaiter aw = new ActivityWaiter(intent);
515
516 if (mWaitingActivities == null) {
517 mWaitingActivities = new ArrayList();
518 }
519 mWaitingActivities.add(aw);
520
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000521 getTargetContext().startActivity(intent, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522
523 do {
524 try {
525 mSync.wait();
526 } catch (InterruptedException e) {
527 }
528 } while (mWaitingActivities.contains(aw));
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000529
chaviwfeb2e1e2018-12-19 17:24:11 -0800530 waitForEnterAnimationComplete(aw.activity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 return aw.activity;
532 }
533 }
534
535 /**
536 * Information about a particular kind of Intent that is being monitored.
537 * An instance of this class is added to the
538 * current instrumentation through {@link #addMonitor}; after being added,
539 * when a new activity is being started the monitor will be checked and, if
540 * matching, its hit count updated and (optionally) the call stopped and a
541 * canned result returned.
542 *
543 * <p>An ActivityMonitor can also be used to look for the creation of an
544 * activity, through the {@link #waitForActivity} method. This will return
545 * after a matching activity has been created with that activity object.
546 */
547 public static class ActivityMonitor {
548 private final IntentFilter mWhich;
549 private final String mClass;
550 private final ActivityResult mResult;
551 private final boolean mBlock;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800552 private final boolean mIgnoreMatchingSpecificIntents;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800553
554
555 // This is protected by 'Instrumentation.this.mSync'.
556 /*package*/ int mHits = 0;
557
558 // This is protected by 'this'.
559 /*package*/ Activity mLastActivity = null;
560
561 /**
562 * Create a new ActivityMonitor that looks for a particular kind of
563 * intent to be started.
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800564 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800565 * @param which The set of intents this monitor is responsible for.
566 * @param result A canned result to return if the monitor is hit; can
567 * be null.
568 * @param block Controls whether the monitor should block the activity
569 * start (returning its canned result) or let the call
570 * proceed.
571 *
572 * @see Instrumentation#addMonitor
573 */
574 public ActivityMonitor(
575 IntentFilter which, ActivityResult result, boolean block) {
576 mWhich = which;
577 mClass = null;
578 mResult = result;
579 mBlock = block;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800580 mIgnoreMatchingSpecificIntents = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800581 }
582
583 /**
584 * Create a new ActivityMonitor that looks for a specific activity
585 * class to be started.
586 *
587 * @param cls The activity class this monitor is responsible for.
588 * @param result A canned result to return if the monitor is hit; can
589 * be null.
590 * @param block Controls whether the monitor should block the activity
591 * start (returning its canned result) or let the call
592 * proceed.
593 *
594 * @see Instrumentation#addMonitor
595 */
596 public ActivityMonitor(
597 String cls, ActivityResult result, boolean block) {
598 mWhich = null;
599 mClass = cls;
600 mResult = result;
601 mBlock = block;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800602 mIgnoreMatchingSpecificIntents = false;
603 }
604
605 /**
606 * Create a new ActivityMonitor that can be used for intercepting any activity to be
607 * started.
608 *
Sudheer Shanka34217512017-04-26 14:49:16 -0700609 * <p> When an activity is started, {@link #onStartActivity(Intent)} will be called on
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800610 * instances created using this constructor to see if it is a hit.
611 *
Sudheer Shanka34217512017-04-26 14:49:16 -0700612 * @see #onStartActivity(Intent)
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800613 */
614 public ActivityMonitor() {
615 mWhich = null;
616 mClass = null;
617 mResult = null;
618 mBlock = false;
619 mIgnoreMatchingSpecificIntents = true;
620 }
621
622 /**
623 * @return true if this monitor is used for intercepting any started activity by calling
Sudheer Shanka34217512017-04-26 14:49:16 -0700624 * into {@link #onStartActivity(Intent)}, false if this monitor is only used
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800625 * for specific intents corresponding to the intent filter or activity class
626 * passed in the constructor.
627 */
628 final boolean ignoreMatchingSpecificIntents() {
629 return mIgnoreMatchingSpecificIntents;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 }
631
632 /**
633 * Retrieve the filter associated with this ActivityMonitor.
634 */
635 public final IntentFilter getFilter() {
636 return mWhich;
637 }
638
639 /**
640 * Retrieve the result associated with this ActivityMonitor, or null if
641 * none.
642 */
643 public final ActivityResult getResult() {
644 return mResult;
645 }
646
647 /**
648 * Check whether this monitor blocks activity starts (not allowing the
649 * actual activity to run) or allows them to execute normally.
650 */
651 public final boolean isBlocking() {
652 return mBlock;
653 }
654
655 /**
656 * Retrieve the number of times the monitor has been hit so far.
657 */
658 public final int getHits() {
659 return mHits;
660 }
661
662 /**
663 * Retrieve the most recent activity class that was seen by this
664 * monitor.
665 */
666 public final Activity getLastActivity() {
667 return mLastActivity;
668 }
669
670 /**
671 * Block until an Activity is created that matches this monitor,
672 * returning the resulting activity.
673 *
674 * @return Activity
675 */
676 public final Activity waitForActivity() {
677 synchronized (this) {
678 while (mLastActivity == null) {
679 try {
680 wait();
681 } catch (InterruptedException e) {
682 }
683 }
684 Activity res = mLastActivity;
685 mLastActivity = null;
686 return res;
687 }
688 }
689
690 /**
691 * Block until an Activity is created that matches this monitor,
692 * returning the resulting activity or till the timeOut period expires.
693 * If the timeOut expires before the activity is started, return null.
694 *
Ben Gruver87904e82016-01-22 13:11:11 -0800695 * @param timeOut Time to wait in milliseconds before the activity is created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800696 *
697 * @return Activity
698 */
699 public final Activity waitForActivityWithTimeout(long timeOut) {
700 synchronized (this) {
Costin Manolacheb0935342011-07-15 11:20:42 -0700701 if (mLastActivity == null) {
702 try {
703 wait(timeOut);
704 } catch (InterruptedException e) {
705 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 }
707 if (mLastActivity == null) {
708 return null;
709 } else {
710 Activity res = mLastActivity;
711 mLastActivity = null;
712 return res;
713 }
714 }
715 }
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800716
717 /**
718 * Used for intercepting any started activity.
719 *
720 * <p> A non-null return value here will be considered a hit for this monitor.
721 * By default this will return {@code null} and subclasses can override this to return
722 * a non-null value if the intent needs to be intercepted.
723 *
724 * <p> Whenever a new activity is started, this method will be called on instances created
725 * using {@link #Instrumentation.ActivityMonitor()} to check if there is a match. In case
726 * of a match, the activity start will be blocked and the returned result will be used.
727 *
728 * @param intent The intent used for starting the activity.
729 * @return The {@link ActivityResult} that needs to be used in case of a match.
730 */
Sudheer Shanka34217512017-04-26 14:49:16 -0700731 public ActivityResult onStartActivity(Intent intent) {
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800732 return null;
733 }
734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800735 final boolean match(Context who,
736 Activity activity,
737 Intent intent) {
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800738 if (mIgnoreMatchingSpecificIntents) {
739 return false;
740 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800741 synchronized (this) {
742 if (mWhich != null
743 && mWhich.match(who.getContentResolver(), intent,
744 true, "Instrumentation") < 0) {
745 return false;
746 }
747 if (mClass != null) {
748 String cls = null;
749 if (activity != null) {
750 cls = activity.getClass().getName();
751 } else if (intent.getComponent() != null) {
752 cls = intent.getComponent().getClassName();
753 }
754 if (cls == null || !mClass.equals(cls)) {
755 return false;
756 }
757 }
758 if (activity != null) {
759 mLastActivity = activity;
760 notifyAll();
761 }
762 return true;
763 }
764 }
765 }
766
767 /**
768 * Add a new {@link ActivityMonitor} that will be checked whenever an
769 * activity is started. The monitor is added
770 * after any existing ones; the monitor will be hit only if none of the
771 * existing monitors can themselves handle the Intent.
772 *
773 * @param monitor The new ActivityMonitor to see.
774 *
775 * @see #addMonitor(IntentFilter, ActivityResult, boolean)
776 * @see #checkMonitorHit
777 */
778 public void addMonitor(ActivityMonitor monitor) {
779 synchronized (mSync) {
780 if (mActivityMonitors == null) {
781 mActivityMonitors = new ArrayList();
782 }
783 mActivityMonitors.add(monitor);
784 }
785 }
786
787 /**
788 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
789 * creates an intent filter matching {@link ActivityMonitor} for you and
790 * returns it.
791 *
792 * @param filter The set of intents this monitor is responsible for.
793 * @param result A canned result to return if the monitor is hit; can
794 * be null.
795 * @param block Controls whether the monitor should block the activity
796 * start (returning its canned result) or let the call
797 * proceed.
798 *
799 * @return The newly created and added activity monitor.
800 *
801 * @see #addMonitor(ActivityMonitor)
802 * @see #checkMonitorHit
803 */
804 public ActivityMonitor addMonitor(
805 IntentFilter filter, ActivityResult result, boolean block) {
806 ActivityMonitor am = new ActivityMonitor(filter, result, block);
807 addMonitor(am);
808 return am;
809 }
810
811 /**
812 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
813 * creates a class matching {@link ActivityMonitor} for you and returns it.
814 *
815 * @param cls The activity class this monitor is responsible for.
816 * @param result A canned result to return if the monitor is hit; can
817 * be null.
818 * @param block Controls whether the monitor should block the activity
819 * start (returning its canned result) or let the call
820 * proceed.
821 *
822 * @return The newly created and added activity monitor.
823 *
824 * @see #addMonitor(ActivityMonitor)
825 * @see #checkMonitorHit
826 */
827 public ActivityMonitor addMonitor(
828 String cls, ActivityResult result, boolean block) {
829 ActivityMonitor am = new ActivityMonitor(cls, result, block);
830 addMonitor(am);
831 return am;
832 }
833
834 /**
835 * Test whether an existing {@link ActivityMonitor} has been hit. If the
836 * monitor has been hit at least <var>minHits</var> times, then it will be
837 * removed from the activity monitor list and true returned. Otherwise it
838 * is left as-is and false is returned.
839 *
840 * @param monitor The ActivityMonitor to check.
841 * @param minHits The minimum number of hits required.
842 *
843 * @return True if the hit count has been reached, else false.
844 *
845 * @see #addMonitor
846 */
847 public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
848 waitForIdleSync();
849 synchronized (mSync) {
850 if (monitor.getHits() < minHits) {
851 return false;
852 }
853 mActivityMonitors.remove(monitor);
854 }
855 return true;
856 }
857
858 /**
859 * Wait for an existing {@link ActivityMonitor} to be hit. Once the
860 * monitor has been hit, it is removed from the activity monitor list and
861 * the first created Activity object that matched it is returned.
862 *
863 * @param monitor The ActivityMonitor to wait for.
864 *
865 * @return The Activity object that matched the monitor.
866 */
867 public Activity waitForMonitor(ActivityMonitor monitor) {
868 Activity activity = monitor.waitForActivity();
869 synchronized (mSync) {
870 mActivityMonitors.remove(monitor);
871 }
872 return activity;
873 }
874
875 /**
876 * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
877 * expires. Once the monitor has been hit, it is removed from the activity
878 * monitor list and the first created Activity object that matched it is
879 * returned. If the timeout expires, a null object is returned.
880 *
881 * @param monitor The ActivityMonitor to wait for.
Nimrod Gileadic895a4b2017-03-31 13:21:47 +0100882 * @param timeOut The timeout value in milliseconds.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800883 *
884 * @return The Activity object that matched the monitor.
885 */
886 public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
887 Activity activity = monitor.waitForActivityWithTimeout(timeOut);
888 synchronized (mSync) {
889 mActivityMonitors.remove(monitor);
890 }
891 return activity;
892 }
893
894 /**
895 * Remove an {@link ActivityMonitor} that was previously added with
896 * {@link #addMonitor}.
897 *
898 * @param monitor The monitor to remove.
899 *
900 * @see #addMonitor
901 */
902 public void removeMonitor(ActivityMonitor monitor) {
903 synchronized (mSync) {
904 mActivityMonitors.remove(monitor);
905 }
906 }
907
908 /**
909 * Execute a particular menu item.
910 *
911 * @param targetActivity The activity in question.
912 * @param id The identifier associated with the menu item.
913 * @param flag Additional flags, if any.
914 * @return Whether the invocation was successful (for example, it could be
915 * false if item is disabled).
916 */
917 public boolean invokeMenuActionSync(Activity targetActivity,
918 int id, int flag) {
919 class MenuRunnable implements Runnable {
920 private final Activity activity;
921 private final int identifier;
922 private final int flags;
923 boolean returnValue;
924
925 public MenuRunnable(Activity _activity, int _identifier,
926 int _flags) {
927 activity = _activity;
928 identifier = _identifier;
929 flags = _flags;
930 }
931
932 public void run() {
933 Window win = activity.getWindow();
934
935 returnValue = win.performPanelIdentifierAction(
936 Window.FEATURE_OPTIONS_PANEL,
937 identifier,
938 flags);
939 }
940
941 }
942 MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
943 runOnMainSync(mr);
944 return mr.returnValue;
945 }
946
947 /**
948 * Show the context menu for the currently focused view and executes a
949 * particular context menu item.
950 *
951 * @param targetActivity The activity in question.
952 * @param id The identifier associated with the context menu item.
953 * @param flag Additional flags, if any.
954 * @return Whether the invocation was successful (for example, it could be
955 * false if item is disabled).
956 */
957 public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
958 validateNotAppThread();
959
960 // Bring up context menu for current focus.
961 // It'd be nice to do this through code, but currently ListView depends on
962 // long press to set metadata for its selected child
963
964 final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
965 sendKeySync(downEvent);
966
967 // Need to wait for long press
968 waitForIdleSync();
969 try {
970 Thread.sleep(ViewConfiguration.getLongPressTimeout());
971 } catch (InterruptedException e) {
972 Log.e(TAG, "Could not sleep for long press timeout", e);
973 return false;
974 }
975
976 final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
977 sendKeySync(upEvent);
978
979 // Wait for context menu to appear
980 waitForIdleSync();
981
982 class ContextMenuRunnable implements Runnable {
983 private final Activity activity;
984 private final int identifier;
985 private final int flags;
986 boolean returnValue;
987
988 public ContextMenuRunnable(Activity _activity, int _identifier,
989 int _flags) {
990 activity = _activity;
991 identifier = _identifier;
992 flags = _flags;
993 }
994
995 public void run() {
996 Window win = activity.getWindow();
997 returnValue = win.performContextMenuIdentifierAction(
998 identifier,
999 flags);
1000 }
1001
1002 }
1003
1004 ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
1005 runOnMainSync(cmr);
1006 return cmr.returnValue;
1007 }
1008
1009 /**
1010 * Sends the key events corresponding to the text to the app being
1011 * instrumented.
1012 *
1013 * @param text The text to be sent.
1014 */
1015 public void sendStringSync(String text) {
1016 if (text == null) {
1017 return;
1018 }
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001019 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001020
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001021 KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 if (events != null) {
1024 for (int i = 0; i < events.length; i++) {
Svetoslav Ganovf434e372011-11-11 16:50:21 -08001025 // We have to change the time of an event before injecting it because
1026 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
1027 // time stamp and the system rejects too old events. Hence, it is
1028 // possible for an event to become stale before it is injected if it
1029 // takes too long to inject the preceding ones.
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001030 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001034
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 /**
1036 * Send a key event to the currently focused window/view and wait for it to
1037 * be processed. Finished at some point after the recipient has returned
1038 * from its event processing, though it may <em>not</em> have completely
1039 * finished reacting from the event -- for example, if it needs to update
1040 * its display as a result, it may still be in the process of doing that.
Tiger Huangfc218452018-09-27 00:38:50 +08001041 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 * @param event The event to send to the current focus.
1043 */
1044 public void sendKeySync(KeyEvent event) {
1045 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001046
1047 long downTime = event.getDownTime();
1048 long eventTime = event.getEventTime();
Jeff Brownac143512012-04-05 18:57:33 -07001049 int source = event.getSource();
Jeff Brownac143512012-04-05 18:57:33 -07001050 if (source == InputDevice.SOURCE_UNKNOWN) {
1051 source = InputDevice.SOURCE_KEYBOARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 }
Jeff Brownac143512012-04-05 18:57:33 -07001053 if (eventTime == 0) {
1054 eventTime = SystemClock.uptimeMillis();
1055 }
1056 if (downTime == 0) {
1057 downTime = eventTime;
1058 }
Tiger Huangfc218452018-09-27 00:38:50 +08001059 KeyEvent newEvent = new KeyEvent(event);
1060 newEvent.setTime(downTime, eventTime);
1061 newEvent.setSource(source);
1062 newEvent.setFlags(event.getFlags() | KeyEvent.FLAG_FROM_SYSTEM);
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001063 InputManager.getInstance().injectInputEvent(newEvent,
Jeff Brownac143512012-04-05 18:57:33 -07001064 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001065 }
Tiger Huangfc218452018-09-27 00:38:50 +08001066
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001067 /**
1068 * Sends an up and down key event sync to the currently focused window.
1069 *
1070 * @param key The integer keycode for the event.
1071 */
1072 public void sendKeyDownUpSync(int key) {
1073 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
1074 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
1075 }
1076
1077 /**
1078 * Higher-level method for sending both the down and up key events for a
1079 * particular character key code. Equivalent to creating both KeyEvent
1080 * objects by hand and calling {@link #sendKeySync}. The event appears
1081 * as if it came from keyboard 0, the built in one.
1082 *
1083 * @param keyCode The key code of the character to send.
1084 */
1085 public void sendCharacterSync(int keyCode) {
1086 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
1087 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
1088 }
1089
1090 /**
1091 * Dispatch a pointer event. Finished at some point after the recipient has
1092 * returned from its event processing, though it may <em>not</em> have
1093 * completely finished reacting from the event -- for example, if it needs
1094 * to update its display as a result, it may still be in the process of
1095 * doing that.
1096 *
1097 * @param event A motion event describing the pointer action. (As noted in
1098 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
1099 * {@link SystemClock#uptimeMillis()} as the timebase.
1100 */
1101 public void sendPointerSync(MotionEvent event) {
1102 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001103 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
1104 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 }
chaviw9f4bc552019-02-27 15:22:47 -08001106 try {
1107 WindowManagerGlobal.getWindowManagerService().injectInputAfterTransactionsApplied(event,
1108 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
1109 } catch (RemoteException e) {
1110 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 }
1112
1113 /**
1114 * Dispatch a trackball event. Finished at some point after the recipient has
1115 * returned from its event processing, though it may <em>not</em> have
1116 * completely finished reacting from the event -- for example, if it needs
1117 * to update its display as a result, it may still be in the process of
1118 * doing that.
1119 *
1120 * @param event A motion event describing the trackball action. (As noted in
1121 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
1122 * {@link SystemClock#uptimeMillis()} as the timebase.
1123 */
1124 public void sendTrackballEventSync(MotionEvent event) {
1125 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001126 if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
1127 event.setSource(InputDevice.SOURCE_TRACKBALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001128 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001129 InputManager.getInstance().injectInputEvent(event,
1130 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001131 }
1132
1133 /**
1134 * Perform instantiation of the process's {@link Application} object. The
1135 * default implementation provides the normal system behavior.
1136 *
1137 * @param cl The ClassLoader with which to instantiate the object.
1138 * @param className The name of the class implementing the Application
1139 * object.
1140 * @param context The context to initialize the application with
1141 *
1142 * @return The newly instantiated Application object.
1143 */
1144 public Application newApplication(ClassLoader cl, String className, Context context)
1145 throws InstantiationException, IllegalAccessException,
1146 ClassNotFoundException {
Jason Monka80bfb52017-11-16 17:15:37 -05001147 Application app = getFactory(context.getPackageName())
1148 .instantiateApplication(cl, className);
1149 app.attach(context);
1150 return app;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 }
1152
1153 /**
1154 * Perform instantiation of the process's {@link Application} object. The
1155 * default implementation provides the normal system behavior.
1156 *
1157 * @param clazz The class used to create an Application object from.
1158 * @param context The context to initialize the application with
1159 *
1160 * @return The newly instantiated Application object.
1161 */
1162 static public Application newApplication(Class<?> clazz, Context context)
1163 throws InstantiationException, IllegalAccessException,
1164 ClassNotFoundException {
1165 Application app = (Application)clazz.newInstance();
1166 app.attach(context);
1167 return app;
1168 }
1169
1170 /**
1171 * Perform calling of the application's {@link Application#onCreate}
1172 * method. The default implementation simply calls through to that method.
Dianne Hackborn6ae8d182012-05-23 13:12:42 -07001173 *
1174 * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
1175 * Often instrumentation tests start their test thread in onCreate(); you
1176 * need to be careful of races between these. (Well between it and
1177 * everything else, but let's start here.)
1178 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 * @param app The application being created.
1180 */
1181 public void callApplicationOnCreate(Application app) {
1182 app.onCreate();
1183 }
1184
1185 /**
1186 * Perform instantiation of an {@link Activity} object. This method is intended for use with
1187 * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
Felipe Leme545569d2016-01-11 16:27:58 -08001188 * 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 -08001189 *
1190 * @param clazz The Class of the desired Activity
1191 * @param context The base context for the activity to use
1192 * @param token The token for this activity to communicate with
1193 * @param application The application object (if any)
1194 * @param intent The intent that started this Activity
1195 * @param info ActivityInfo from the manifest
1196 * @param title The title, typically retrieved from the ActivityInfo record
1197 * @param parent The parent Activity (if any)
1198 * @param id The embedded Id (if any)
1199 * @param lastNonConfigurationInstance Arbitrary object that will be
1200 * available via {@link Activity#getLastNonConfigurationInstance()
1201 * Activity.getLastNonConfigurationInstance()}.
1202 * @return Returns the instantiated activity
1203 * @throws InstantiationException
1204 * @throws IllegalAccessException
1205 */
1206 public Activity newActivity(Class<?> clazz, Context context,
1207 IBinder token, Application application, Intent intent, ActivityInfo info,
1208 CharSequence title, Activity parent, String id,
1209 Object lastNonConfigurationInstance) throws InstantiationException,
1210 IllegalAccessException {
1211 Activity activity = (Activity)clazz.newInstance();
1212 ActivityThread aThread = null;
Sudheer Shanka37820712018-04-11 15:47:35 -07001213 // Activity.attach expects a non-null Application Object.
1214 if (application == null) {
1215 application = new Application();
1216 }
Andrii Kulian51c1b672017-04-07 18:39:32 -07001217 activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001218 info, title, parent, id,
1219 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
Andrii Kulian51c1b672017-04-07 18:39:32 -07001220 new Configuration(), null /* referrer */, null /* voiceInteractor */,
1221 null /* window */, null /* activityConfigCallback */);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 return activity;
1223 }
1224
1225 /**
1226 * Perform instantiation of the process's {@link Activity} object. The
1227 * default implementation provides the normal system behavior.
1228 *
1229 * @param cl The ClassLoader with which to instantiate the object.
1230 * @param className The name of the class implementing the Activity
1231 * object.
1232 * @param intent The Intent object that specified the activity class being
1233 * instantiated.
1234 *
1235 * @return The newly instantiated Activity object.
1236 */
1237 public Activity newActivity(ClassLoader cl, String className,
1238 Intent intent)
1239 throws InstantiationException, IllegalAccessException,
1240 ClassNotFoundException {
Jason Monke96443e2018-04-18 15:43:50 -04001241 String pkg = intent != null && intent.getComponent() != null
1242 ? intent.getComponent().getPackageName() : null;
Jason Monka80bfb52017-11-16 17:15:37 -05001243 return getFactory(pkg).instantiateActivity(cl, className, intent);
1244 }
1245
1246 private AppComponentFactory getFactory(String pkg) {
Jason Monke96443e2018-04-18 15:43:50 -04001247 if (pkg == null) {
1248 Log.e(TAG, "No pkg specified, disabling AppComponentFactory");
1249 return AppComponentFactory.DEFAULT;
1250 }
Jason Monk24d12a32017-12-21 10:39:17 -05001251 if (mThread == null) {
1252 Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
1253 + " disabling AppComponentFactory", new Throwable());
1254 return AppComponentFactory.DEFAULT;
1255 }
Todd Kennedy233a0b12018-01-29 20:30:24 +00001256 LoadedApk apk = mThread.peekPackageInfo(pkg, true);
Jason Monka80bfb52017-11-16 17:15:37 -05001257 // This is in the case of starting up "android".
Todd Kennedy233a0b12018-01-29 20:30:24 +00001258 if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
1259 return apk.getAppFactory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 }
1261
Craig Mautnera0026042014-04-23 11:45:37 -07001262 private void prePerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001263 if (mWaitingActivities != null) {
1264 synchronized (mSync) {
1265 final int N = mWaitingActivities.size();
1266 for (int i=0; i<N; i++) {
1267 final ActivityWaiter aw = mWaitingActivities.get(i);
1268 final Intent intent = aw.intent;
1269 if (intent.filterEquals(activity.getIntent())) {
1270 aw.activity = activity;
1271 mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1272 }
1273 }
1274 }
1275 }
Craig Mautnera0026042014-04-23 11:45:37 -07001276 }
1277
1278 private void postPerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001279 if (mActivityMonitors != null) {
1280 synchronized (mSync) {
1281 final int N = mActivityMonitors.size();
1282 for (int i=0; i<N; i++) {
1283 final ActivityMonitor am = mActivityMonitors.get(i);
1284 am.match(activity, activity, activity.getIntent());
1285 }
1286 }
1287 }
1288 }
Craig Mautnera0026042014-04-23 11:45:37 -07001289
1290 /**
1291 * Perform calling of an activity's {@link Activity#onCreate}
1292 * method. The default implementation simply calls through to that method.
1293 *
1294 * @param activity The activity being created.
1295 * @param icicle The previously frozen state (or null) to pass through to onCreate().
1296 */
1297 public void callActivityOnCreate(Activity activity, Bundle icicle) {
1298 prePerformCreate(activity);
1299 activity.performCreate(icicle);
1300 postPerformCreate(activity);
1301 }
1302
1303 /**
1304 * Perform calling of an activity's {@link Activity#onCreate}
1305 * method. The default implementation simply calls through to that method.
1306 * @param activity The activity being created.
1307 * @param icicle The previously frozen state (or null) to pass through to
1308 * @param persistentState The previously persisted state (or null)
1309 */
1310 public void callActivityOnCreate(Activity activity, Bundle icicle,
1311 PersistableBundle persistentState) {
1312 prePerformCreate(activity);
1313 activity.performCreate(icicle, persistentState);
1314 postPerformCreate(activity);
1315 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001316
1317 public void callActivityOnDestroy(Activity activity) {
Brett Chabot18f9ce02010-05-12 12:41:50 -07001318 // TODO: the following block causes intermittent hangs when using startActivity
1319 // temporarily comment out until root cause is fixed (bug 2630683)
1320// if (mWaitingActivities != null) {
1321// synchronized (mSync) {
1322// final int N = mWaitingActivities.size();
1323// for (int i=0; i<N; i++) {
1324// final ActivityWaiter aw = mWaitingActivities.get(i);
1325// final Intent intent = aw.intent;
1326// if (intent.filterEquals(activity.getIntent())) {
1327// aw.activity = activity;
1328// mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1329// }
1330// }
1331// }
1332// }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001333
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001334 activity.performDestroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001335 }
1336
1337 /**
1338 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1339 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001340 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341 * @param activity The activity being restored.
1342 * @param savedInstanceState The previously saved state being restored.
1343 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001344 public void callActivityOnRestoreInstanceState(@NonNull Activity activity,
1345 @NonNull Bundle savedInstanceState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001346 activity.performRestoreInstanceState(savedInstanceState);
1347 }
1348
1349 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001350 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1351 * method. The default implementation simply calls through to that method.
1352 *
1353 * @param activity The activity being restored.
Jake Wharton63f4d892018-07-10 12:27:59 -04001354 * @param savedInstanceState The previously saved state being restored (or null).
Craig Mautnera0026042014-04-23 11:45:37 -07001355 * @param persistentState The previously persisted state (or null)
1356 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001357 public void callActivityOnRestoreInstanceState(@NonNull Activity activity,
1358 @Nullable Bundle savedInstanceState,
1359 @Nullable PersistableBundle persistentState) {
Craig Mautnera0026042014-04-23 11:45:37 -07001360 activity.performRestoreInstanceState(savedInstanceState, persistentState);
1361 }
1362
1363 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001364 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1365 * The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001366 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001367 * @param activity The activity being created.
Jake Wharton63f4d892018-07-10 12:27:59 -04001368 * @param savedInstanceState The previously saved state (or null) to pass through to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 * onPostCreate().
1370 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001371 public void callActivityOnPostCreate(@NonNull Activity activity,
1372 @Nullable Bundle savedInstanceState) {
1373 activity.onPostCreate(savedInstanceState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 }
1375
1376 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001377 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1378 * The default implementation simply calls through to that method.
1379 *
1380 * @param activity The activity being created.
Jake Wharton63f4d892018-07-10 12:27:59 -04001381 * @param savedInstanceState The previously frozen state (or null) to pass through to
Craig Mautnera0026042014-04-23 11:45:37 -07001382 * onPostCreate().
Jake Wharton63f4d892018-07-10 12:27:59 -04001383 * @param persistentState The previously persisted state (or null)
Craig Mautnera0026042014-04-23 11:45:37 -07001384 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001385 public void callActivityOnPostCreate(@NonNull Activity activity,
1386 @Nullable Bundle savedInstanceState,
1387 @Nullable PersistableBundle persistentState) {
1388 activity.onPostCreate(savedInstanceState, persistentState);
Craig Mautnera0026042014-04-23 11:45:37 -07001389 }
1390
1391 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001392 * Perform calling of an activity's {@link Activity#onNewIntent}
1393 * method. The default implementation simply calls through to that method.
1394 *
1395 * @param activity The activity receiving a new Intent.
1396 * @param intent The new intent being received.
1397 */
1398 public void callActivityOnNewIntent(Activity activity, Intent intent) {
Winson Chung298f95b2017-08-10 15:57:18 -07001399 activity.performNewIntent(intent);
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001400 }
1401
1402 /**
1403 * @hide
1404 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001405 @UnsupportedAppUsage
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001406 public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001407 final String oldReferrer = activity.mReferrer;
1408 try {
Dianne Hackborn80b1c562014-12-09 20:22:08 -08001409 if (intent != null) {
1410 activity.mReferrer = intent.mReferrer;
1411 }
1412 callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001413 } finally {
1414 activity.mReferrer = oldReferrer;
1415 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001416 }
1417
1418 /**
1419 * Perform calling of an activity's {@link Activity#onStart}
1420 * method. The default implementation simply calls through to that method.
1421 *
1422 * @param activity The activity being started.
1423 */
1424 public void callActivityOnStart(Activity activity) {
1425 activity.onStart();
1426 }
1427
1428 /**
1429 * Perform calling of an activity's {@link Activity#onRestart}
1430 * method. The default implementation simply calls through to that method.
1431 *
1432 * @param activity The activity being restarted.
1433 */
1434 public void callActivityOnRestart(Activity activity) {
1435 activity.onRestart();
1436 }
1437
1438 /**
1439 * Perform calling of an activity's {@link Activity#onResume} method. The
1440 * default implementation simply calls through to that method.
1441 *
1442 * @param activity The activity being resumed.
1443 */
1444 public void callActivityOnResume(Activity activity) {
Jeff Hamilton52d32032011-01-08 15:31:26 -06001445 activity.mResumed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001446 activity.onResume();
1447
1448 if (mActivityMonitors != null) {
1449 synchronized (mSync) {
1450 final int N = mActivityMonitors.size();
1451 for (int i=0; i<N; i++) {
1452 final ActivityMonitor am = mActivityMonitors.get(i);
1453 am.match(activity, activity, activity.getIntent());
1454 }
1455 }
1456 }
1457 }
1458
1459 /**
1460 * Perform calling of an activity's {@link Activity#onStop}
1461 * method. The default implementation simply calls through to that method.
1462 *
1463 * @param activity The activity being stopped.
1464 */
1465 public void callActivityOnStop(Activity activity) {
1466 activity.onStop();
1467 }
1468
1469 /**
Newton Allenc5027442013-08-13 11:22:32 -07001470 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1471 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001472 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001473 * @param activity The activity being saved.
1474 * @param outState The bundle to pass to the call.
1475 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001476 public void callActivityOnSaveInstanceState(@NonNull Activity activity,
1477 @NonNull Bundle outState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 activity.performSaveInstanceState(outState);
1479 }
1480
1481 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001482 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1483 * method. The default implementation simply calls through to that method.
1484 * @param activity The activity being saved.
1485 * @param outState The bundle to pass to the call.
1486 * @param outPersistentState The persistent bundle to pass to the call.
1487 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001488 public void callActivityOnSaveInstanceState(@NonNull Activity activity,
1489 @NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
Craig Mautnera0026042014-04-23 11:45:37 -07001490 activity.performSaveInstanceState(outState, outPersistentState);
1491 }
1492
1493 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 * Perform calling of an activity's {@link Activity#onPause} method. The
1495 * default implementation simply calls through to that method.
1496 *
1497 * @param activity The activity being paused.
1498 */
1499 public void callActivityOnPause(Activity activity) {
1500 activity.performPause();
1501 }
1502
1503 /**
1504 * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
1505 * The default implementation simply calls through to that method.
1506 *
1507 * @param activity The activity being notified that the user has navigated away
1508 */
1509 public void callActivityOnUserLeaving(Activity activity) {
1510 activity.performUserLeaving();
1511 }
1512
1513 /*
1514 * Starts allocation counting. This triggers a gc and resets the counts.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001515 *
1516 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001517 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001518 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001519 public void startAllocCounting() {
1520 // Before we start trigger a GC and reset the debug counts. Run the
1521 // finalizers and another GC before starting and stopping the alloc
1522 // counts. This will free up any objects that were just sitting around
1523 // waiting for their finalizers to be run.
1524 Runtime.getRuntime().gc();
1525 Runtime.getRuntime().runFinalization();
1526 Runtime.getRuntime().gc();
1527
1528 Debug.resetAllCounts();
1529
1530 // start the counts
1531 Debug.startAllocCounting();
1532 }
1533
1534 /*
1535 * Stops allocation counting.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001536 *
1537 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001538 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001539 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001540 public void stopAllocCounting() {
1541 Runtime.getRuntime().gc();
1542 Runtime.getRuntime().runFinalization();
1543 Runtime.getRuntime().gc();
1544 Debug.stopAllocCounting();
1545 }
1546
1547 /**
1548 * If Results already contains Key, it appends Value to the key's ArrayList
1549 * associated with the key. If the key doesn't already exist in results, it
1550 * adds the key/value pair to results.
1551 */
1552 private void addValue(String key, int value, Bundle results) {
1553 if (results.containsKey(key)) {
1554 List<Integer> list = results.getIntegerArrayList(key);
1555 if (list != null) {
1556 list.add(value);
1557 }
1558 } else {
1559 ArrayList<Integer> list = new ArrayList<Integer>();
1560 list.add(value);
1561 results.putIntegerArrayList(key, list);
1562 }
1563 }
1564
1565 /**
1566 * Returns a bundle with the current results from the allocation counting.
1567 */
1568 public Bundle getAllocCounts() {
1569 Bundle results = new Bundle();
1570 results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
1571 results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
1572 results.putLong("global_freed_count", Debug.getGlobalFreedCount());
1573 results.putLong("global_freed_size", Debug.getGlobalFreedSize());
1574 results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
1575 return results;
1576 }
1577
1578 /**
1579 * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
1580 * reported are the number of send and the number of received transactions.
1581 */
1582 public Bundle getBinderCounts() {
1583 Bundle results = new Bundle();
1584 results.putLong("sent_transactions", Debug.getBinderSentTransactions());
1585 results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
1586 return results;
1587 }
1588
1589 /**
1590 * Description of a Activity execution result to return to the original
1591 * activity.
1592 */
1593 public static final class ActivityResult {
1594 /**
1595 * Create a new activity result. See {@link Activity#setResult} for
1596 * more information.
1597 *
1598 * @param resultCode The result code to propagate back to the
1599 * originating activity, often RESULT_CANCELED or RESULT_OK
1600 * @param resultData The data to propagate back to the originating
1601 * activity.
1602 */
1603 public ActivityResult(int resultCode, Intent resultData) {
1604 mResultCode = resultCode;
1605 mResultData = resultData;
1606 }
1607
1608 /**
1609 * Retrieve the result code contained in this result.
1610 */
1611 public int getResultCode() {
1612 return mResultCode;
1613 }
1614
1615 /**
1616 * Retrieve the data contained in this result.
1617 */
1618 public Intent getResultData() {
1619 return mResultData;
1620 }
1621
1622 private final int mResultCode;
1623 private final Intent mResultData;
1624 }
1625
1626 /**
1627 * Execute a startActivity call made by the application. The default
1628 * implementation takes care of updating any active {@link ActivityMonitor}
1629 * objects and dispatches this call to the system activity manager; you can
1630 * override this to watch for the application to start an activity, and
1631 * modify what happens when it does.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001632 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001633 * <p>This method returns an {@link ActivityResult} object, which you can
1634 * use when intercepting application calls to avoid performing the start
1635 * activity action but still return the result the application is
1636 * expecting. To do this, override this method to catch the call to start
1637 * activity so that it returns a new ActivityResult containing the results
1638 * you would like the application to see, and don't call up to the super
1639 * class. Note that an application is only expecting a result if
1640 * <var>requestCode</var> is &gt;= 0.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001641 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001642 * <p>This method throws {@link android.content.ActivityNotFoundException}
1643 * if there was no Activity found to run the given Intent.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001644 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001645 * @param who The Context from which the activity is being started.
1646 * @param contextThread The main thread of the Context from which the activity
1647 * is being started.
1648 * @param token Internal token identifying to the system who is starting
1649 * the activity; may be null.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001650 * @param target Which activity is performing the start (and thus receiving
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001651 * any result); may be null if this call is not being made
1652 * from an activity.
1653 * @param intent The actual Intent to start.
1654 * @param requestCode Identifier for this request's result; less than zero
1655 * if the caller is not expecting a result.
Dianne Hackborna4972e92012-03-14 10:38:05 -07001656 * @param options Addition options.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001657 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001658 * @return To force the return of a particular result, return an
1659 * ActivityResult object containing the desired data; otherwise
1660 * return null. The default implementation always returns null.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001661 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 * @throws android.content.ActivityNotFoundException
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001663 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001664 * @see Activity#startActivity(Intent)
1665 * @see Activity#startActivityForResult(Intent, int)
1666 * @see Activity#startActivityFromChild
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001667 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001668 * {@hide}
1669 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001670 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 public ActivityResult execStartActivity(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001672 Context who, IBinder contextThread, IBinder token, Activity target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001673 Intent intent, int requestCode, Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001674 IApplicationThread whoThread = (IApplicationThread) contextThread;
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001675 Uri referrer = target != null ? target.onProvideReferrer() : null;
1676 if (referrer != null) {
1677 intent.putExtra(Intent.EXTRA_REFERRER, referrer);
1678 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001679 if (mActivityMonitors != null) {
1680 synchronized (mSync) {
1681 final int N = mActivityMonitors.size();
1682 for (int i=0; i<N; i++) {
1683 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001684 ActivityResult result = null;
1685 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001686 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001687 }
1688 if (result != null) {
1689 am.mHits++;
1690 return result;
1691 } else if (am.match(who, null, intent)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001692 am.mHits++;
1693 if (am.isBlocking()) {
1694 return requestCode >= 0 ? am.getResult() : null;
1695 }
1696 break;
1697 }
1698 }
1699 }
1700 }
1701 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001702 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001703 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001704 int result = ActivityTaskManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001705 .startActivity(whoThread, who.getBasePackageName(), intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001706 intent.resolveTypeIfNeeded(who.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07001707 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001708 requestCode, 0, null, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001709 checkStartActivityResult(result, intent);
1710 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001711 throw new RuntimeException("Failure from system", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001712 }
1713 return null;
1714 }
1715
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001716 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001717 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001718 * but accepts an array of activities to be started. Note that active
1719 * {@link ActivityMonitor} objects only match against the first activity in
1720 * the array.
1721 *
1722 * {@hide}
1723 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001724 @UnsupportedAppUsage
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001725 public void execStartActivities(Context who, IBinder contextThread,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001726 IBinder token, Activity target, Intent[] intents, Bundle options) {
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001727 execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
Jeff Sharkeyad357d12018-02-02 13:25:31 -07001728 who.getUserId());
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001729 }
1730
1731 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001732 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001733 * but accepts an array of activities to be started. Note that active
1734 * {@link ActivityMonitor} objects only match against the first activity in
1735 * the array.
1736 *
Selim Cinek7fa385a2018-01-24 08:35:28 -08001737 * @return The corresponding flag {@link ActivityManager#START_CANCELED},
1738 * {@link ActivityManager#START_SUCCESS} etc. indicating whether the launch was
1739 * successful.
1740 *
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001741 * {@hide}
1742 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001743 @UnsupportedAppUsage
Selim Cinek7fa385a2018-01-24 08:35:28 -08001744 public int execStartActivitiesAsUser(Context who, IBinder contextThread,
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001745 IBinder token, Activity target, Intent[] intents, Bundle options,
1746 int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001747 IApplicationThread whoThread = (IApplicationThread) contextThread;
1748 if (mActivityMonitors != null) {
1749 synchronized (mSync) {
1750 final int N = mActivityMonitors.size();
1751 for (int i=0; i<N; i++) {
1752 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001753 ActivityResult result = null;
1754 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001755 result = am.onStartActivity(intents[0]);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001756 }
1757 if (result != null) {
1758 am.mHits++;
Selim Cinek7fa385a2018-01-24 08:35:28 -08001759 return ActivityManager.START_CANCELED;
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001760 } else if (am.match(who, null, intents[0])) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001761 am.mHits++;
1762 if (am.isBlocking()) {
Selim Cinek7fa385a2018-01-24 08:35:28 -08001763 return ActivityManager.START_CANCELED;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001764 }
1765 break;
1766 }
1767 }
1768 }
1769 }
1770 try {
1771 String[] resolvedTypes = new String[intents.length];
1772 for (int i=0; i<intents.length; i++) {
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001773 intents[i].migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001774 intents[i].prepareToLeaveProcess(who);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001775 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
1776 }
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001777 int result = ActivityTaskManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001778 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes,
1779 token, options, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001780 checkStartActivityResult(result, intents[0]);
Selim Cinek7fa385a2018-01-24 08:35:28 -08001781 return result;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001782 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001783 throw new RuntimeException("Failure from system", e);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001784 }
1785 }
1786
1787 /**
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001788 * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001789 * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)},
Andrew Solovay5c05ded2018-10-02 14:14:42 -07001790 * but for calls from a {@link Fragment}.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001791 *
1792 * @param who The Context from which the activity is being started.
1793 * @param contextThread The main thread of the Context from which the activity
1794 * is being started.
1795 * @param token Internal token identifying to the system who is starting
1796 * the activity; may be null.
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001797 * @param target Which element is performing the start (and thus receiving
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001798 * any result).
1799 * @param intent The actual Intent to start.
1800 * @param requestCode Identifier for this request's result; less than zero
1801 * if the caller is not expecting a result.
1802 *
1803 * @return To force the return of a particular result, return an
1804 * ActivityResult object containing the desired data; otherwise
1805 * return null. The default implementation always returns null.
1806 *
1807 * @throws android.content.ActivityNotFoundException
1808 *
1809 * @see Activity#startActivity(Intent)
1810 * @see Activity#startActivityForResult(Intent, int)
1811 * @see Activity#startActivityFromChild
1812 *
1813 * {@hide}
1814 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001815 @UnsupportedAppUsage
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001816 public ActivityResult execStartActivity(
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001817 Context who, IBinder contextThread, IBinder token, String target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001818 Intent intent, int requestCode, Bundle options) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001819 IApplicationThread whoThread = (IApplicationThread) contextThread;
1820 if (mActivityMonitors != null) {
1821 synchronized (mSync) {
1822 final int N = mActivityMonitors.size();
1823 for (int i=0; i<N; i++) {
1824 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001825 ActivityResult result = null;
1826 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001827 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001828 }
1829 if (result != null) {
1830 am.mHits++;
1831 return result;
1832 } else if (am.match(who, null, intent)) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001833 am.mHits++;
1834 if (am.isBlocking()) {
1835 return requestCode >= 0 ? am.getResult() : null;
1836 }
1837 break;
1838 }
1839 }
1840 }
1841 }
1842 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001843 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001844 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001845 int result = ActivityTaskManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001846 .startActivity(whoThread, who.getBasePackageName(), intent,
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001847 intent.resolveTypeIfNeeded(who.getContentResolver()),
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001848 token, target, requestCode, 0, null, options);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001849 checkStartActivityResult(result, intent);
1850 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001851 throw new RuntimeException("Failure from system", e);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001852 }
1853 return null;
1854 }
1855
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001856 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001857 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
1858 * but for starting as a particular user.
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001859 *
1860 * @param who The Context from which the activity is being started.
1861 * @param contextThread The main thread of the Context from which the activity
1862 * is being started.
1863 * @param token Internal token identifying to the system who is starting
1864 * the activity; may be null.
1865 * @param target Which fragment is performing the start (and thus receiving
1866 * any result).
1867 * @param intent The actual Intent to start.
1868 * @param requestCode Identifier for this request's result; less than zero
1869 * if the caller is not expecting a result.
1870 *
1871 * @return To force the return of a particular result, return an
1872 * ActivityResult object containing the desired data; otherwise
1873 * return null. The default implementation always returns null.
1874 *
1875 * @throws android.content.ActivityNotFoundException
1876 *
1877 * @see Activity#startActivity(Intent)
1878 * @see Activity#startActivityForResult(Intent, int)
1879 * @see Activity#startActivityFromChild
1880 *
1881 * {@hide}
1882 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001883 @UnsupportedAppUsage
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001884 public ActivityResult execStartActivity(
Tony Mak96d26fe2017-04-11 20:05:39 +01001885 Context who, IBinder contextThread, IBinder token, String resultWho,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001886 Intent intent, int requestCode, Bundle options, UserHandle user) {
1887 IApplicationThread whoThread = (IApplicationThread) contextThread;
1888 if (mActivityMonitors != null) {
1889 synchronized (mSync) {
1890 final int N = mActivityMonitors.size();
1891 for (int i=0; i<N; i++) {
1892 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001893 ActivityResult result = null;
1894 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001895 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001896 }
1897 if (result != null) {
1898 am.mHits++;
1899 return result;
1900 } else if (am.match(who, null, intent)) {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001901 am.mHits++;
1902 if (am.isBlocking()) {
1903 return requestCode >= 0 ? am.getResult() : null;
1904 }
1905 break;
1906 }
1907 }
1908 }
1909 }
1910 try {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001911 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001912 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001913 int result = ActivityTaskManager.getService()
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001914 .startActivityAsUser(whoThread, who.getBasePackageName(), intent,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001915 intent.resolveTypeIfNeeded(who.getContentResolver()),
Tony Mak96d26fe2017-04-11 20:05:39 +01001916 token, resultWho,
Jeff Hao1b012d32014-08-20 10:35:34 -07001917 requestCode, 0, null, options, user.getIdentifier());
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001918 checkStartActivityResult(result, intent);
1919 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001920 throw new RuntimeException("Failure from system", e);
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001921 }
1922 return null;
1923 }
1924
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001925 /**
1926 * Special version!
1927 * @hide
1928 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001929 @UnsupportedAppUsage
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001930 public ActivityResult execStartActivityAsCaller(
1931 Context who, IBinder contextThread, IBinder token, Activity target,
Alison Cichowlas3e340502018-08-07 17:15:01 -04001932 Intent intent, int requestCode, Bundle options, IBinder permissionToken,
1933 boolean ignoreTargetSecurity, int userId) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001934 IApplicationThread whoThread = (IApplicationThread) contextThread;
1935 if (mActivityMonitors != null) {
1936 synchronized (mSync) {
1937 final int N = mActivityMonitors.size();
1938 for (int i=0; i<N; i++) {
1939 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001940 ActivityResult result = null;
1941 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001942 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001943 }
1944 if (result != null) {
1945 am.mHits++;
1946 return result;
1947 } else if (am.match(who, null, intent)) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001948 am.mHits++;
1949 if (am.isBlocking()) {
1950 return requestCode >= 0 ? am.getResult() : null;
1951 }
1952 break;
1953 }
1954 }
1955 }
1956 }
1957 try {
1958 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001959 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001960 int result = ActivityTaskManager.getService()
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001961 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
1962 intent.resolveTypeIfNeeded(who.getContentResolver()),
1963 token, target != null ? target.mEmbeddedID : null,
Alison Cichowlas3e340502018-08-07 17:15:01 -04001964 requestCode, 0, null, options, permissionToken,
1965 ignoreTargetSecurity, userId);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001966 checkStartActivityResult(result, intent);
1967 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001968 throw new RuntimeException("Failure from system", e);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001969 }
1970 return null;
1971 }
1972
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001973 /**
1974 * Special version!
1975 * @hide
1976 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001977 @UnsupportedAppUsage
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001978 public void execStartActivityFromAppTask(
1979 Context who, IBinder contextThread, IAppTask appTask,
1980 Intent intent, Bundle options) {
1981 IApplicationThread whoThread = (IApplicationThread) contextThread;
1982 if (mActivityMonitors != null) {
1983 synchronized (mSync) {
1984 final int N = mActivityMonitors.size();
1985 for (int i=0; i<N; i++) {
1986 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001987 ActivityResult result = null;
1988 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001989 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001990 }
1991 if (result != null) {
1992 am.mHits++;
1993 return;
1994 } else if (am.match(who, null, intent)) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001995 am.mHits++;
1996 if (am.isBlocking()) {
1997 return;
1998 }
1999 break;
2000 }
2001 }
2002 }
2003 }
2004 try {
2005 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07002006 intent.prepareToLeaveProcess(who);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07002007 int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
2008 intent, intent.resolveTypeIfNeeded(who.getContentResolver()), options);
2009 checkStartActivityResult(result, intent);
2010 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07002011 throw new RuntimeException("Failure from system", e);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07002012 }
2013 return;
2014 }
2015
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002016 /*package*/ final void init(ActivityThread thread,
2017 Context instrContext, Context appContext, ComponentName component,
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002018 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002019 mThread = thread;
2020 mMessageQueue = mThread.getLooper().myQueue();
2021 mInstrContext = instrContext;
2022 mAppContext = appContext;
2023 mComponent = component;
2024 mWatcher = watcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002025 mUiAutomationConnection = uiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002026 }
2027
Jason Monka80bfb52017-11-16 17:15:37 -05002028 /**
2029 * Only sets the ActivityThread up, keeps everything else null because app is not being
2030 * instrumented.
2031 */
2032 final void basicInit(ActivityThread thread) {
2033 mThread = thread;
2034 }
2035
Dianne Hackborn91097de2014-04-04 18:02:06 -07002036 /** @hide */
Mathew Inwood31755f92018-12-20 13:53:36 +00002037 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Dianne Hackborn91097de2014-04-04 18:02:06 -07002038 public static void checkStartActivityResult(int res, Object intent) {
Bryce Lee7f936862017-05-09 15:33:18 -07002039 if (!ActivityManager.isStartResultFatalError(res)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002040 return;
2041 }
Amith Yamasani42449782016-04-19 11:45:51 -07002042
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002043 switch (res) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07002044 case ActivityManager.START_INTENT_NOT_RESOLVED:
2045 case ActivityManager.START_CLASS_NOT_FOUND:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002046 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002047 throw new ActivityNotFoundException(
2048 "Unable to find explicit activity class "
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002049 + ((Intent)intent).getComponent().toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002050 + "; have you declared this activity in your AndroidManifest.xml?");
2051 throw new ActivityNotFoundException(
2052 "No Activity found to handle " + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002053 case ActivityManager.START_PERMISSION_DENIED:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002054 throw new SecurityException("Not allowed to start activity "
2055 + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002056 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002057 throw new AndroidRuntimeException(
2058 "FORWARD_RESULT_FLAG used while also requesting a result");
Dianne Hackborna4972e92012-03-14 10:38:05 -07002059 case ActivityManager.START_NOT_ACTIVITY:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002060 throw new IllegalArgumentException(
2061 "PendingIntent is not an activity");
Dianne Hackborn91097de2014-04-04 18:02:06 -07002062 case ActivityManager.START_NOT_VOICE_COMPATIBLE:
2063 throw new SecurityException(
2064 "Starting under voice control not allowed for: " + intent);
Amith Yamasani42449782016-04-19 11:45:51 -07002065 case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
2066 throw new IllegalStateException(
2067 "Session calling startVoiceActivity does not match active session");
2068 case ActivityManager.START_VOICE_HIDDEN_SESSION:
2069 throw new IllegalStateException(
2070 "Cannot start voice activity on a hidden session");
Winson Chungfc3ec4c2017-06-01 15:35:48 -07002071 case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
2072 throw new IllegalStateException(
2073 "Session calling startAssistantActivity does not match active session");
2074 case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
2075 throw new IllegalStateException(
2076 "Cannot start assistant activity on a hidden session");
Amith Yamasani42449782016-04-19 11:45:51 -07002077 case ActivityManager.START_CANCELED:
2078 throw new AndroidRuntimeException("Activity could not be started for "
2079 + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002080 default:
2081 throw new AndroidRuntimeException("Unknown error code "
2082 + res + " when starting " + intent);
2083 }
2084 }
Chong Zhang45c25ce2015-08-10 22:18:26 -07002085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002086 private final void validateNotAppThread() {
Kristian Monsen0a303282013-01-18 14:50:07 -08002087 if (Looper.myLooper() == Looper.getMainLooper()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002088 throw new RuntimeException(
2089 "This method can not be called from the main application thread");
2090 }
2091 }
2092
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002093 /**
Phil Weaverd8e88832016-03-28 17:26:25 -07002094 * Gets the {@link UiAutomation} instance with no flags set.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002095 * <p>
2096 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
2097 * work across application boundaries while the APIs exposed by the instrumentation
2098 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
2099 * not allow you to inject the event in an app different from the instrumentation
2100 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
2101 * will work regardless of the current application.
2102 * </p>
2103 * <p>
2104 * A typical test case should be using either the {@link UiAutomation} or
2105 * {@link Instrumentation} APIs. Using both APIs at the same time is not
2106 * a mistake by itself but a client has to be aware of the APIs limitations.
2107 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07002108 * <p>
2109 * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different
2110 * flags, the flags on that instance will be changed, and then it will be returned.
2111 * </p>
2112 * @return The UI automation instance.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002113 *
2114 * @see UiAutomation
2115 */
2116 public UiAutomation getUiAutomation() {
Phil Weaverd8e88832016-03-28 17:26:25 -07002117 return getUiAutomation(0);
Phil Weaver1dd87222016-01-26 17:15:15 -08002118 }
2119
2120 /**
2121 * Gets the {@link UiAutomation} instance with flags set.
2122 * <p>
Phil Weaver1dd87222016-01-26 17:15:15 -08002123 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
2124 * work across application boundaries while the APIs exposed by the instrumentation
2125 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
2126 * not allow you to inject the event in an app different from the instrumentation
2127 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
2128 * will work regardless of the current application.
2129 * </p>
2130 * <p>
2131 * A typical test case should be using either the {@link UiAutomation} or
2132 * {@link Instrumentation} APIs. Using both APIs at the same time is not
2133 * a mistake by itself but a client has to be aware of the APIs limitations.
2134 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07002135 * <p>
2136 * If a {@link UiAutomation} exists with different flags, the flags on that instance will be
2137 * changed, and then it will be returned.
2138 * </p>
Phil Weaver1dd87222016-01-26 17:15:15 -08002139 *
2140 * @param flags The flags to be passed to the UiAutomation, for example
2141 * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
2142 *
2143 * @return The UI automation instance.
2144 *
2145 * @see UiAutomation
2146 */
Phil Weaver35841682016-03-09 09:52:51 -08002147 public UiAutomation getUiAutomation(@UiAutomationFlags int flags) {
Phil Weaverd8e88832016-03-28 17:26:25 -07002148 boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed());
2149
Phil Weaver1dd87222016-01-26 17:15:15 -08002150 if (mUiAutomationConnection != null) {
Phil Weaverd8e88832016-03-28 17:26:25 -07002151 if (!mustCreateNewAutomation && (mUiAutomation.getFlags() == flags)) {
2152 return mUiAutomation;
2153 }
2154 if (mustCreateNewAutomation) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002155 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
2156 mUiAutomationConnection);
Phil Weaver1dd87222016-01-26 17:15:15 -08002157 } else {
Phil Weaverd8e88832016-03-28 17:26:25 -07002158 mUiAutomation.disconnect();
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002159 }
Phil Weaverd8e88832016-03-28 17:26:25 -07002160 mUiAutomation.connect(flags);
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002161 return mUiAutomation;
2162 }
2163 return null;
2164 }
2165
Jason Monk5be50f72017-03-10 10:57:34 -05002166 /**
2167 * Takes control of the execution of messages on the specified looper until
2168 * {@link TestLooperManager#release} is called.
2169 */
2170 public TestLooperManager acquireLooperManager(Looper looper) {
2171 checkInstrumenting("acquireLooperManager");
2172 return new TestLooperManager(looper);
2173 }
2174
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002175 private final class InstrumentationThread extends Thread {
2176 public InstrumentationThread(String name) {
2177 super(name);
2178 }
2179 public void run() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002180 try {
2181 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
2182 } catch (RuntimeException e) {
Phil Weaver1dd87222016-01-26 17:15:15 -08002183 Log.w(TAG, "Exception setting priority of instrumentation thread "
2184 + Process.myTid(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002185 }
2186 if (mAutomaticPerformanceSnapshots) {
2187 startPerformanceSnapshot();
2188 }
2189 onStart();
2190 }
2191 }
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002193 private static final class EmptyRunnable implements Runnable {
2194 public void run() {
2195 }
2196 }
2197
2198 private static final class SyncRunnable implements Runnable {
2199 private final Runnable mTarget;
2200 private boolean mComplete;
2201
2202 public SyncRunnable(Runnable target) {
2203 mTarget = target;
2204 }
2205
2206 public void run() {
2207 mTarget.run();
2208 synchronized (this) {
2209 mComplete = true;
2210 notifyAll();
2211 }
2212 }
2213
2214 public void waitForComplete() {
2215 synchronized (this) {
2216 while (!mComplete) {
2217 try {
2218 wait();
2219 } catch (InterruptedException e) {
2220 }
2221 }
2222 }
2223 }
2224 }
2225
2226 private static final class ActivityWaiter {
2227 public final Intent intent;
2228 public Activity activity;
2229
2230 public ActivityWaiter(Intent _intent) {
2231 intent = _intent;
2232 }
2233 }
2234
2235 private final class ActivityGoing implements MessageQueue.IdleHandler {
2236 private final ActivityWaiter mWaiter;
2237
2238 public ActivityGoing(ActivityWaiter waiter) {
2239 mWaiter = waiter;
2240 }
2241
2242 public final boolean queueIdle() {
2243 synchronized (mSync) {
2244 mWaitingActivities.remove(mWaiter);
2245 mSync.notifyAll();
2246 }
2247 return false;
2248 }
2249 }
2250
2251 private static final class Idler implements MessageQueue.IdleHandler {
2252 private final Runnable mCallback;
2253 private boolean mIdle;
2254
2255 public Idler(Runnable callback) {
2256 mCallback = callback;
2257 mIdle = false;
2258 }
2259
2260 public final boolean queueIdle() {
2261 if (mCallback != null) {
2262 mCallback.run();
2263 }
2264 synchronized (this) {
2265 mIdle = true;
2266 notifyAll();
2267 }
2268 return false;
2269 }
2270
2271 public void waitForIdle() {
2272 synchronized (this) {
2273 while (!mIdle) {
2274 try {
2275 wait();
2276 } catch (InterruptedException e) {
2277 }
2278 }
2279 }
2280 }
2281 }
2282}