blob: 18932c6b078451c764c6ca0602fe764498dff660 [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;
Artur Satayevc895b1b2019-12-10 17:47:51 +000022import android.compat.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;
Prabir Pradhan03dde382019-07-26 14:21:21 -070053import android.view.SurfaceControl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.view.ViewConfiguration;
55import android.view.Window;
chaviw9f4bc552019-02-27 15:22:47 -080056import android.view.WindowManagerGlobal;
Winson Chung298f95b2017-08-10 15:57:18 -070057
Dianne Hackborn85d558c2014-11-04 10:31:54 -080058import com.android.internal.content.ReferrerIntent;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080059
60import java.io.File;
Phil Weaver35841682016-03-09 09:52:51 -080061import java.lang.annotation.Retention;
62import java.lang.annotation.RetentionPolicy;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import java.util.ArrayList;
64import java.util.List;
65
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066/**
67 * Base class for implementing application instrumentation code. When running
68 * with instrumentation turned on, this class will be instantiated for you
69 * before any of the application code, allowing you to monitor all of the
70 * interaction the system has with the application. An Instrumentation
71 * implementation is described to the system through an AndroidManifest.xml's
72 * <instrumentation> tag.
73 */
74public class Instrumentation {
Svetoslav Ganov80943d82013-01-02 10:25:37 -080075
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076 /**
77 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
78 * identifies the class that is writing the report. This can be used to provide more structured
79 * logging or reporting capabilities in the IInstrumentationWatcher.
80 */
81 public static final String REPORT_KEY_IDENTIFIER = "id";
82 /**
83 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key
84 * identifies a string which can simply be printed to the output stream. Using these streams
85 * provides a "pretty printer" version of the status & final packets. Any bundles including
86 * this key should also include the complete set of raw key/value pairs, so that the
87 * instrumentation can also be launched, and results collected, by an automated system.
88 */
89 public static final String REPORT_KEY_STREAMRESULT = "stream";
Svetoslav Ganov80943d82013-01-02 10:25:37 -080090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 private static final String TAG = "Instrumentation";
Phil Weaver35841682016-03-09 09:52:51 -080092
93 /**
94 * @hide
95 */
96 @Retention(RetentionPolicy.SOURCE)
97 @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES})
98 public @interface UiAutomationFlags {};
99
100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800101 private final Object mSync = new Object();
102 private ActivityThread mThread = null;
103 private MessageQueue mMessageQueue = null;
104 private Context mInstrContext;
105 private Context mAppContext;
106 private ComponentName mComponent;
107 private Thread mRunner;
108 private List<ActivityWaiter> mWaitingActivities;
109 private List<ActivityMonitor> mActivityMonitors;
110 private IInstrumentationWatcher mWatcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800111 private IUiAutomationConnection mUiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800112 private boolean mAutomaticPerformanceSnapshots = false;
Jack Wangff1df692009-08-26 17:19:13 -0700113 private PerformanceCollector mPerformanceCollector;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 private Bundle mPerfMetrics = new Bundle();
Svetoslav Ganov80943d82013-01-02 10:25:37 -0800115 private UiAutomation mUiAutomation;
chaviwfeb2e1e2018-12-19 17:24:11 -0800116 private final Object mAnimationCompleteLock = new Object();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800117
118 public Instrumentation() {
119 }
120
121 /**
Jason Monk5be50f72017-03-10 10:57:34 -0500122 * Called for methods that shouldn't be called by standard apps and
123 * should only be used in instrumentation environments. This is not
124 * security feature as these classes will still be accessible through
125 * reflection, but it will serve as noticeable discouragement from
126 * doing such a thing.
127 */
128 private void checkInstrumenting(String method) {
129 // Check if we have an instrumentation context, as init should only get called by
130 // the system in startup processes that are being instrumented.
131 if (mInstrContext == null) {
132 throw new RuntimeException(method +
133 " cannot be called outside of instrumented processes");
134 }
135 }
136
137 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800138 * Called when the instrumentation is starting, before any application code
139 * has been loaded. Usually this will be implemented to simply call
140 * {@link #start} to begin the instrumentation thread, which will then
141 * continue execution in {@link #onStart}.
142 *
143 * <p>If you do not need your own thread -- that is you are writing your
144 * instrumentation to be completely asynchronous (returning to the event
145 * loop so that the application can run), you can simply begin your
146 * instrumentation here, for example call {@link Context#startActivity} to
147 * begin the appropriate first activity of the application.
148 *
149 * @param arguments Any additional arguments that were supplied when the
150 * instrumentation was started.
151 */
152 public void onCreate(Bundle arguments) {
153 }
154
155 /**
156 * Create and start a new thread in which to run instrumentation. This new
157 * thread will call to {@link #onStart} where you can implement the
158 * instrumentation.
159 */
160 public void start() {
161 if (mRunner != null) {
162 throw new RuntimeException("Instrumentation already started");
163 }
164 mRunner = new InstrumentationThread("Instr: " + getClass().getName());
165 mRunner.start();
166 }
167
168 /**
169 * Method where the instrumentation thread enters execution. This allows
170 * you to run your instrumentation code in a separate thread than the
171 * application, so that it can perform blocking operation such as
172 * {@link #sendKeySync} or {@link #startActivitySync}.
173 *
174 * <p>You will typically want to call finish() when this function is done,
175 * to end your instrumentation.
176 */
177 public void onStart() {
178 }
179
180 /**
181 * This is called whenever the system captures an unhandled exception that
182 * was thrown by the application. The default implementation simply
183 * returns false, allowing normal system handling of the exception to take
184 * place.
185 *
186 * @param obj The client object that generated the exception. May be an
187 * Application, Activity, BroadcastReceiver, Service, or null.
188 * @param e The exception that was thrown.
189 *
190 * @return To allow normal system exception process to occur, return false.
191 * If true is returned, the system will proceed as if the exception
192 * didn't happen.
193 */
194 public boolean onException(Object obj, Throwable e) {
195 return false;
196 }
197
198 /**
199 * Provide a status report about the application.
200 *
201 * @param resultCode Current success/failure of instrumentation.
202 * @param results Any results to send back to the code that started the instrumentation.
203 */
204 public void sendStatus(int resultCode, Bundle results) {
205 if (mWatcher != null) {
206 try {
207 mWatcher.instrumentationStatus(mComponent, resultCode, results);
208 }
209 catch (RemoteException e) {
210 mWatcher = null;
211 }
212 }
213 }
Dianne Hackborn34041732017-01-31 15:27:13 -0800214
215 /**
216 * Report some results in the middle of instrumentation execution. Later results (including
217 * those provided by {@link #finish}) will be combined with {@link Bundle#putAll}.
218 */
219 public void addResults(Bundle results) {
220 IActivityManager am = ActivityManager.getService();
221 try {
222 am.addInstrumentationResults(mThread.getApplicationThread(), results);
223 } catch (RemoteException ex) {
224 throw ex.rethrowFromSystemServer();
225 }
226 }
227
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 /**
229 * Terminate instrumentation of the application. This will cause the
230 * application process to exit, removing this instrumentation from the next
Dianne Hackborn34041732017-01-31 15:27:13 -0800231 * time the application is started. If multiple processes are currently running
232 * for this instrumentation, all of those processes will be killed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 *
234 * @param resultCode Overall success/failure of instrumentation.
235 * @param results Any results to send back to the code that started the
236 * instrumentation.
237 */
238 public void finish(int resultCode, Bundle results) {
239 if (mAutomaticPerformanceSnapshots) {
240 endPerformanceSnapshot();
241 }
242 if (mPerfMetrics != null) {
Dianne Hackbornb65ea7b2014-06-20 12:18:55 -0700243 if (results == null) {
244 results = new Bundle();
245 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 results.putAll(mPerfMetrics);
247 }
Phil Weaverd8e88832016-03-28 17:26:25 -0700248 if ((mUiAutomation != null) && !mUiAutomation.isDestroyed()) {
Adam Momtaz8f6f1f42013-04-10 12:42:58 -0700249 mUiAutomation.disconnect();
250 mUiAutomation = null;
251 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 mThread.finishInstrumentation(resultCode, results);
253 }
254
255 public void setAutomaticPerformanceSnapshots() {
256 mAutomaticPerformanceSnapshots = true;
Jack Wangff1df692009-08-26 17:19:13 -0700257 mPerformanceCollector = new PerformanceCollector();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 }
259
260 public void startPerformanceSnapshot() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800261 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700262 mPerformanceCollector.beginSnapshot(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 }
264 }
265
266 public void endPerformanceSnapshot() {
267 if (!isProfiling()) {
Jack Wangff1df692009-08-26 17:19:13 -0700268 mPerfMetrics = mPerformanceCollector.endSnapshot();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800269 }
270 }
271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800272 /**
273 * Called when the instrumented application is stopping, after all of the
274 * normal application cleanup has occurred.
275 */
276 public void onDestroy() {
277 }
278
279 /**
280 * Return the Context of this instrumentation's package. Note that this is
281 * often different than the Context of the application being
282 * instrumentated, since the instrumentation code often lives is a
283 * different package than that of the application it is running against.
284 * See {@link #getTargetContext} to retrieve a Context for the target
285 * application.
286 *
287 * @return The instrumentation's package context.
288 *
289 * @see #getTargetContext
290 */
291 public Context getContext() {
292 return mInstrContext;
293 }
294
295 /**
296 * Returns complete component name of this instrumentation.
297 *
298 * @return Returns the complete component name for this instrumentation.
299 */
300 public ComponentName getComponentName() {
301 return mComponent;
302 }
303
304 /**
305 * Return a Context for the target application being instrumented. Note
306 * that this is often different than the Context of the instrumentation
307 * code, since the instrumentation code often lives is a different package
308 * than that of the application it is running against. See
309 * {@link #getContext} to retrieve a Context for the instrumentation code.
310 *
311 * @return A Context in the target application.
312 *
313 * @see #getContext
314 */
315 public Context getTargetContext() {
316 return mAppContext;
317 }
318
319 /**
Dianne Hackborn34041732017-01-31 15:27:13 -0800320 * Return the name of the process this instrumentation is running in. Note this should
321 * only be used for testing and debugging. If you are thinking about using this to,
322 * for example, conditionalize what is initialized in an Application class, it is strongly
323 * recommended to instead use lazy initialization (such as a getter for the state that
324 * only creates it when requested). This can greatly reduce the work your process does
325 * when created for secondary things, such as to receive a broadcast.
326 */
327 public String getProcessName() {
328 return mThread.getProcessName();
329 }
330
331 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800332 * Check whether this instrumentation was started with profiling enabled.
333 *
334 * @return Returns true if profiling was enabled when starting, else false.
335 */
336 public boolean isProfiling() {
337 return mThread.isProfiling();
338 }
339
340 /**
341 * This method will start profiling if isProfiling() returns true. You should
342 * only call this method if you set the handleProfiling attribute in the
343 * manifest file for this Instrumentation to true.
344 */
345 public void startProfiling() {
346 if (mThread.isProfiling()) {
347 File file = new File(mThread.getProfileFilePath());
348 file.getParentFile().mkdirs();
349 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
350 }
351 }
352
353 /**
354 * Stops profiling if isProfiling() returns true.
355 */
356 public void stopProfiling() {
357 if (mThread.isProfiling()) {
358 Debug.stopMethodTracing();
359 }
360 }
361
362 /**
363 * Force the global system in or out of touch mode. This can be used if
364 * your instrumentation relies on the UI being in one more or the other
365 * when it starts.
366 *
367 * @param inTouch Set to true to be in touch mode, false to be in
368 * focus mode.
369 */
370 public void setInTouchMode(boolean inTouch) {
371 try {
372 IWindowManager.Stub.asInterface(
373 ServiceManager.getService("window")).setInTouchMode(inTouch);
374 } catch (RemoteException e) {
375 // Shouldn't happen!
376 }
377 }
378
379 /**
380 * Schedule a callback for when the application's main thread goes idle
381 * (has no more events to process).
382 *
383 * @param recipient Called the next time the thread's message queue is
384 * idle.
385 */
386 public void waitForIdle(Runnable recipient) {
387 mMessageQueue.addIdleHandler(new Idler(recipient));
388 mThread.getHandler().post(new EmptyRunnable());
389 }
390
391 /**
392 * Synchronously wait for the application to be idle. Can not be called
393 * from the main application thread -- use {@link #start} to execute
394 * instrumentation in its own thread.
395 */
396 public void waitForIdleSync() {
397 validateNotAppThread();
398 Idler idler = new Idler(null);
399 mMessageQueue.addIdleHandler(idler);
400 mThread.getHandler().post(new EmptyRunnable());
401 idler.waitForIdle();
402 }
403
chaviwfeb2e1e2018-12-19 17:24:11 -0800404 private void waitForEnterAnimationComplete(Activity activity) {
405 synchronized (mAnimationCompleteLock) {
406 long timeout = 5000;
407 try {
408 // We need to check that this specified Activity completed the animation, not just
409 // any Activity. If it was another Activity, then decrease the timeout by how long
410 // it's already waited and wait for the thread to wakeup again.
411 while (timeout > 0 && !activity.mEnterAnimationComplete) {
412 long startTime = System.currentTimeMillis();
413 mAnimationCompleteLock.wait(timeout);
414 long totalTime = System.currentTimeMillis() - startTime;
415 timeout -= totalTime;
416 }
417 } catch (InterruptedException e) {
418 }
419 }
420 }
421
422 /** @hide */
423 public void onEnterAnimationComplete() {
424 synchronized (mAnimationCompleteLock) {
425 mAnimationCompleteLock.notifyAll();
426 }
427 }
428
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800429 /**
430 * Execute a call on the application's main thread, blocking until it is
431 * complete. Useful for doing things that are not thread-safe, such as
432 * looking at or modifying the view hierarchy.
433 *
434 * @param runner The code to run on the main thread.
435 */
436 public void runOnMainSync(Runnable runner) {
437 validateNotAppThread();
438 SyncRunnable sr = new SyncRunnable(runner);
439 mThread.getHandler().post(sr);
440 sr.waitForComplete();
441 }
442
443 /**
444 * Start a new activity and wait for it to begin running before returning.
445 * In addition to being synchronous, this method as some semantic
446 * differences from the standard {@link Context#startActivity} call: the
447 * activity component is resolved before talking with the activity manager
448 * (its class name is specified in the Intent that this method ultimately
449 * starts), and it does not allow you to start activities that run in a
450 * different process. In addition, if the given Intent resolves to
451 * multiple activities, instead of displaying a dialog for the user to
452 * select an activity, an exception will be thrown.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000453 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800454 * <p>The function returns as soon as the activity goes idle following the
455 * call to its {@link Activity#onCreate}. Generally this means it has gone
456 * through the full initialization including {@link Activity#onResume} and
457 * drawn and displayed its initial window.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000458 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 * @param intent Description of the activity to start.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000460 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800461 * @see Context#startActivity
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000462 * @see #startActivitySync(Intent, Bundle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 */
464 public Activity startActivitySync(Intent intent) {
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000465 return startActivitySync(intent, null /* options */);
466 }
467
468 /**
469 * Start a new activity and wait for it to begin running before returning.
470 * In addition to being synchronous, this method as some semantic
471 * differences from the standard {@link Context#startActivity} call: the
472 * activity component is resolved before talking with the activity manager
473 * (its class name is specified in the Intent that this method ultimately
474 * starts), and it does not allow you to start activities that run in a
475 * different process. In addition, if the given Intent resolves to
476 * multiple activities, instead of displaying a dialog for the user to
477 * select an activity, an exception will be thrown.
478 *
479 * <p>The function returns as soon as the activity goes idle following the
480 * call to its {@link Activity#onCreate}. Generally this means it has gone
481 * through the full initialization including {@link Activity#onResume} and
482 * drawn and displayed its initial window.
483 *
484 * @param intent Description of the activity to start.
485 * @param options Additional options for how the Activity should be started.
486 * May be null if there are no options. See {@link android.app.ActivityOptions}
487 * for how to build the Bundle supplied here; there are no supported definitions
488 * for building it manually.
489 *
490 * @see Context#startActivity(Intent, Bundle)
491 */
Wale Ogunwale2632c972018-01-22 06:54:48 -0800492 @NonNull
493 public Activity startActivitySync(@NonNull Intent intent, @Nullable Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800494 validateNotAppThread();
495
wilsonshih29fd42c2019-12-06 18:46:07 +0800496 final Activity activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 synchronized (mSync) {
498 intent = new Intent(intent);
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000499
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 ActivityInfo ai = intent.resolveActivityInfo(
501 getTargetContext().getPackageManager(), 0);
502 if (ai == null) {
503 throw new RuntimeException("Unable to resolve activity for: " + intent);
504 }
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700505 String myProc = mThread.getProcessName();
506 if (!ai.processName.equals(myProc)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 // todo: if this intent is ambiguous, look here to see if
508 // there is a single match that is in our package.
Dianne Hackbornd97c7ad2009-06-19 11:37:35 -0700509 throw new RuntimeException("Intent in process "
510 + myProc + " resolved to different process "
511 + ai.processName + ": " + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800512 }
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000513
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800514 intent.setComponent(new ComponentName(
515 ai.applicationInfo.packageName, ai.name));
516 final ActivityWaiter aw = new ActivityWaiter(intent);
517
518 if (mWaitingActivities == null) {
519 mWaitingActivities = new ArrayList();
520 }
521 mWaitingActivities.add(aw);
522
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000523 getTargetContext().startActivity(intent, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524
525 do {
526 try {
527 mSync.wait();
528 } catch (InterruptedException e) {
529 }
530 } while (mWaitingActivities.contains(aw));
wilsonshih29fd42c2019-12-06 18:46:07 +0800531 activity = aw.activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800532 }
wilsonshih29fd42c2019-12-06 18:46:07 +0800533
534 // Do not call this method within mSync, lest it could block the main thread.
535 waitForEnterAnimationComplete(activity);
536
537 // Apply an empty transaction to ensure SF has a chance to update before
538 // the Activity is ready (b/138263890).
539 try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) {
540 t.apply(true);
541 }
542 return activity;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800543 }
544
545 /**
546 * Information about a particular kind of Intent that is being monitored.
547 * An instance of this class is added to the
548 * current instrumentation through {@link #addMonitor}; after being added,
549 * when a new activity is being started the monitor will be checked and, if
550 * matching, its hit count updated and (optionally) the call stopped and a
551 * canned result returned.
552 *
553 * <p>An ActivityMonitor can also be used to look for the creation of an
554 * activity, through the {@link #waitForActivity} method. This will return
555 * after a matching activity has been created with that activity object.
556 */
557 public static class ActivityMonitor {
558 private final IntentFilter mWhich;
559 private final String mClass;
560 private final ActivityResult mResult;
561 private final boolean mBlock;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800562 private final boolean mIgnoreMatchingSpecificIntents;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563
564
565 // This is protected by 'Instrumentation.this.mSync'.
566 /*package*/ int mHits = 0;
567
568 // This is protected by 'this'.
569 /*package*/ Activity mLastActivity = null;
570
571 /**
572 * Create a new ActivityMonitor that looks for a particular kind of
573 * intent to be started.
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800574 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800575 * @param which The set of intents this monitor is responsible for.
576 * @param result A canned result to return if the monitor is hit; can
577 * be null.
578 * @param block Controls whether the monitor should block the activity
579 * start (returning its canned result) or let the call
580 * proceed.
581 *
582 * @see Instrumentation#addMonitor
583 */
584 public ActivityMonitor(
585 IntentFilter which, ActivityResult result, boolean block) {
586 mWhich = which;
587 mClass = null;
588 mResult = result;
589 mBlock = block;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800590 mIgnoreMatchingSpecificIntents = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800591 }
592
593 /**
594 * Create a new ActivityMonitor that looks for a specific activity
595 * class to be started.
596 *
597 * @param cls The activity class this monitor is responsible for.
598 * @param result A canned result to return if the monitor is hit; can
599 * be null.
600 * @param block Controls whether the monitor should block the activity
601 * start (returning its canned result) or let the call
602 * proceed.
603 *
604 * @see Instrumentation#addMonitor
605 */
606 public ActivityMonitor(
607 String cls, ActivityResult result, boolean block) {
608 mWhich = null;
609 mClass = cls;
610 mResult = result;
611 mBlock = block;
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800612 mIgnoreMatchingSpecificIntents = false;
613 }
614
615 /**
616 * Create a new ActivityMonitor that can be used for intercepting any activity to be
617 * started.
618 *
Sudheer Shanka34217512017-04-26 14:49:16 -0700619 * <p> When an activity is started, {@link #onStartActivity(Intent)} will be called on
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800620 * instances created using this constructor to see if it is a hit.
621 *
Sudheer Shanka34217512017-04-26 14:49:16 -0700622 * @see #onStartActivity(Intent)
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800623 */
624 public ActivityMonitor() {
625 mWhich = null;
626 mClass = null;
627 mResult = null;
628 mBlock = false;
629 mIgnoreMatchingSpecificIntents = true;
630 }
631
632 /**
633 * @return true if this monitor is used for intercepting any started activity by calling
Sudheer Shanka34217512017-04-26 14:49:16 -0700634 * into {@link #onStartActivity(Intent)}, false if this monitor is only used
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800635 * for specific intents corresponding to the intent filter or activity class
636 * passed in the constructor.
637 */
638 final boolean ignoreMatchingSpecificIntents() {
639 return mIgnoreMatchingSpecificIntents;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800640 }
641
642 /**
643 * Retrieve the filter associated with this ActivityMonitor.
644 */
645 public final IntentFilter getFilter() {
646 return mWhich;
647 }
648
649 /**
650 * Retrieve the result associated with this ActivityMonitor, or null if
651 * none.
652 */
653 public final ActivityResult getResult() {
654 return mResult;
655 }
656
657 /**
658 * Check whether this monitor blocks activity starts (not allowing the
659 * actual activity to run) or allows them to execute normally.
660 */
661 public final boolean isBlocking() {
662 return mBlock;
663 }
664
665 /**
666 * Retrieve the number of times the monitor has been hit so far.
667 */
668 public final int getHits() {
669 return mHits;
670 }
671
672 /**
673 * Retrieve the most recent activity class that was seen by this
674 * monitor.
675 */
676 public final Activity getLastActivity() {
677 return mLastActivity;
678 }
679
680 /**
681 * Block until an Activity is created that matches this monitor,
682 * returning the resulting activity.
683 *
684 * @return Activity
685 */
686 public final Activity waitForActivity() {
687 synchronized (this) {
688 while (mLastActivity == null) {
689 try {
690 wait();
691 } catch (InterruptedException e) {
692 }
693 }
694 Activity res = mLastActivity;
695 mLastActivity = null;
696 return res;
697 }
698 }
699
700 /**
701 * Block until an Activity is created that matches this monitor,
702 * returning the resulting activity or till the timeOut period expires.
703 * If the timeOut expires before the activity is started, return null.
704 *
Ben Gruver87904e82016-01-22 13:11:11 -0800705 * @param timeOut Time to wait in milliseconds before the activity is created.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800706 *
707 * @return Activity
708 */
709 public final Activity waitForActivityWithTimeout(long timeOut) {
710 synchronized (this) {
Costin Manolacheb0935342011-07-15 11:20:42 -0700711 if (mLastActivity == null) {
712 try {
713 wait(timeOut);
714 } catch (InterruptedException e) {
715 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800716 }
717 if (mLastActivity == null) {
718 return null;
719 } else {
720 Activity res = mLastActivity;
721 mLastActivity = null;
722 return res;
723 }
724 }
725 }
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800726
727 /**
728 * Used for intercepting any started activity.
729 *
730 * <p> A non-null return value here will be considered a hit for this monitor.
731 * By default this will return {@code null} and subclasses can override this to return
732 * a non-null value if the intent needs to be intercepted.
733 *
734 * <p> Whenever a new activity is started, this method will be called on instances created
735 * using {@link #Instrumentation.ActivityMonitor()} to check if there is a match. In case
736 * of a match, the activity start will be blocked and the returned result will be used.
737 *
738 * @param intent The intent used for starting the activity.
739 * @return The {@link ActivityResult} that needs to be used in case of a match.
740 */
Sudheer Shanka34217512017-04-26 14:49:16 -0700741 public ActivityResult onStartActivity(Intent intent) {
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800742 return null;
743 }
744
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800745 final boolean match(Context who,
746 Activity activity,
747 Intent intent) {
Sudheer Shankad1d12d12017-01-13 12:07:26 -0800748 if (mIgnoreMatchingSpecificIntents) {
749 return false;
750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800751 synchronized (this) {
752 if (mWhich != null
753 && mWhich.match(who.getContentResolver(), intent,
754 true, "Instrumentation") < 0) {
755 return false;
756 }
757 if (mClass != null) {
758 String cls = null;
759 if (activity != null) {
760 cls = activity.getClass().getName();
761 } else if (intent.getComponent() != null) {
762 cls = intent.getComponent().getClassName();
763 }
764 if (cls == null || !mClass.equals(cls)) {
765 return false;
766 }
767 }
768 if (activity != null) {
769 mLastActivity = activity;
770 notifyAll();
771 }
772 return true;
773 }
774 }
775 }
776
777 /**
778 * Add a new {@link ActivityMonitor} that will be checked whenever an
779 * activity is started. The monitor is added
780 * after any existing ones; the monitor will be hit only if none of the
781 * existing monitors can themselves handle the Intent.
782 *
783 * @param monitor The new ActivityMonitor to see.
784 *
785 * @see #addMonitor(IntentFilter, ActivityResult, boolean)
786 * @see #checkMonitorHit
787 */
788 public void addMonitor(ActivityMonitor monitor) {
789 synchronized (mSync) {
790 if (mActivityMonitors == null) {
791 mActivityMonitors = new ArrayList();
792 }
793 mActivityMonitors.add(monitor);
794 }
795 }
796
797 /**
798 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
799 * creates an intent filter matching {@link ActivityMonitor} for you and
800 * returns it.
801 *
802 * @param filter The set of intents this monitor is responsible for.
803 * @param result A canned result to return if the monitor is hit; can
804 * be null.
805 * @param block Controls whether the monitor should block the activity
806 * start (returning its canned result) or let the call
807 * proceed.
808 *
809 * @return The newly created and added activity monitor.
810 *
811 * @see #addMonitor(ActivityMonitor)
812 * @see #checkMonitorHit
813 */
814 public ActivityMonitor addMonitor(
815 IntentFilter filter, ActivityResult result, boolean block) {
816 ActivityMonitor am = new ActivityMonitor(filter, result, block);
817 addMonitor(am);
818 return am;
819 }
820
821 /**
822 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that
823 * creates a class matching {@link ActivityMonitor} for you and returns it.
824 *
825 * @param cls The activity class this monitor is responsible for.
826 * @param result A canned result to return if the monitor is hit; can
827 * be null.
828 * @param block Controls whether the monitor should block the activity
829 * start (returning its canned result) or let the call
830 * proceed.
831 *
832 * @return The newly created and added activity monitor.
833 *
834 * @see #addMonitor(ActivityMonitor)
835 * @see #checkMonitorHit
836 */
837 public ActivityMonitor addMonitor(
838 String cls, ActivityResult result, boolean block) {
839 ActivityMonitor am = new ActivityMonitor(cls, result, block);
840 addMonitor(am);
841 return am;
842 }
843
844 /**
845 * Test whether an existing {@link ActivityMonitor} has been hit. If the
846 * monitor has been hit at least <var>minHits</var> times, then it will be
847 * removed from the activity monitor list and true returned. Otherwise it
848 * is left as-is and false is returned.
849 *
850 * @param monitor The ActivityMonitor to check.
851 * @param minHits The minimum number of hits required.
852 *
853 * @return True if the hit count has been reached, else false.
854 *
855 * @see #addMonitor
856 */
857 public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) {
858 waitForIdleSync();
859 synchronized (mSync) {
860 if (monitor.getHits() < minHits) {
861 return false;
862 }
863 mActivityMonitors.remove(monitor);
864 }
865 return true;
866 }
867
868 /**
869 * Wait for an existing {@link ActivityMonitor} to be hit. Once the
870 * monitor has been hit, it is removed from the activity monitor list and
871 * the first created Activity object that matched it is returned.
872 *
873 * @param monitor The ActivityMonitor to wait for.
874 *
875 * @return The Activity object that matched the monitor.
876 */
877 public Activity waitForMonitor(ActivityMonitor monitor) {
878 Activity activity = monitor.waitForActivity();
879 synchronized (mSync) {
880 mActivityMonitors.remove(monitor);
881 }
882 return activity;
883 }
884
885 /**
886 * Wait for an existing {@link ActivityMonitor} to be hit till the timeout
887 * expires. Once the monitor has been hit, it is removed from the activity
888 * monitor list and the first created Activity object that matched it is
889 * returned. If the timeout expires, a null object is returned.
890 *
891 * @param monitor The ActivityMonitor to wait for.
Nimrod Gileadic895a4b2017-03-31 13:21:47 +0100892 * @param timeOut The timeout value in milliseconds.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800893 *
894 * @return The Activity object that matched the monitor.
895 */
896 public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) {
897 Activity activity = monitor.waitForActivityWithTimeout(timeOut);
898 synchronized (mSync) {
899 mActivityMonitors.remove(monitor);
900 }
901 return activity;
902 }
903
904 /**
905 * Remove an {@link ActivityMonitor} that was previously added with
906 * {@link #addMonitor}.
907 *
908 * @param monitor The monitor to remove.
909 *
910 * @see #addMonitor
911 */
912 public void removeMonitor(ActivityMonitor monitor) {
913 synchronized (mSync) {
914 mActivityMonitors.remove(monitor);
915 }
916 }
917
918 /**
919 * Execute a particular menu item.
920 *
921 * @param targetActivity The activity in question.
922 * @param id The identifier associated with the menu item.
923 * @param flag Additional flags, if any.
924 * @return Whether the invocation was successful (for example, it could be
925 * false if item is disabled).
926 */
927 public boolean invokeMenuActionSync(Activity targetActivity,
928 int id, int flag) {
929 class MenuRunnable implements Runnable {
930 private final Activity activity;
931 private final int identifier;
932 private final int flags;
933 boolean returnValue;
934
935 public MenuRunnable(Activity _activity, int _identifier,
936 int _flags) {
937 activity = _activity;
938 identifier = _identifier;
939 flags = _flags;
940 }
941
942 public void run() {
943 Window win = activity.getWindow();
944
945 returnValue = win.performPanelIdentifierAction(
946 Window.FEATURE_OPTIONS_PANEL,
947 identifier,
948 flags);
949 }
950
951 }
952 MenuRunnable mr = new MenuRunnable(targetActivity, id, flag);
953 runOnMainSync(mr);
954 return mr.returnValue;
955 }
956
957 /**
958 * Show the context menu for the currently focused view and executes a
959 * particular context menu item.
960 *
961 * @param targetActivity The activity in question.
962 * @param id The identifier associated with the context menu item.
963 * @param flag Additional flags, if any.
964 * @return Whether the invocation was successful (for example, it could be
965 * false if item is disabled).
966 */
967 public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) {
968 validateNotAppThread();
969
970 // Bring up context menu for current focus.
971 // It'd be nice to do this through code, but currently ListView depends on
972 // long press to set metadata for its selected child
973
974 final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER);
975 sendKeySync(downEvent);
976
977 // Need to wait for long press
978 waitForIdleSync();
979 try {
980 Thread.sleep(ViewConfiguration.getLongPressTimeout());
981 } catch (InterruptedException e) {
982 Log.e(TAG, "Could not sleep for long press timeout", e);
983 return false;
984 }
985
986 final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER);
987 sendKeySync(upEvent);
988
989 // Wait for context menu to appear
990 waitForIdleSync();
991
992 class ContextMenuRunnable implements Runnable {
993 private final Activity activity;
994 private final int identifier;
995 private final int flags;
996 boolean returnValue;
997
998 public ContextMenuRunnable(Activity _activity, int _identifier,
999 int _flags) {
1000 activity = _activity;
1001 identifier = _identifier;
1002 flags = _flags;
1003 }
1004
1005 public void run() {
1006 Window win = activity.getWindow();
1007 returnValue = win.performContextMenuIdentifierAction(
1008 identifier,
1009 flags);
1010 }
1011
1012 }
1013
1014 ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag);
1015 runOnMainSync(cmr);
1016 return cmr.returnValue;
1017 }
1018
1019 /**
1020 * Sends the key events corresponding to the text to the app being
1021 * instrumented.
1022 *
1023 * @param text The text to be sent.
1024 */
1025 public void sendStringSync(String text) {
1026 if (text == null) {
1027 return;
1028 }
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001029 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD);
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray());
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001032
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001033 if (events != null) {
1034 for (int i = 0; i < events.length; i++) {
Svetoslav Ganovf434e372011-11-11 16:50:21 -08001035 // We have to change the time of an event before injecting it because
1036 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same
1037 // time stamp and the system rejects too old events. Hence, it is
1038 // possible for an event to become stale before it is injected if it
1039 // takes too long to inject the preceding ones.
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001040 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001042 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001043 }
Svetoslav Ganovc350f162011-11-10 17:54:24 -08001044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 /**
1046 * Send a key event to the currently focused window/view and wait for it to
1047 * be processed. Finished at some point after the recipient has returned
1048 * from its event processing, though it may <em>not</em> have completely
1049 * finished reacting from the event -- for example, if it needs to update
1050 * its display as a result, it may still be in the process of doing that.
Tiger Huangfc218452018-09-27 00:38:50 +08001051 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001052 * @param event The event to send to the current focus.
1053 */
1054 public void sendKeySync(KeyEvent event) {
1055 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001056
1057 long downTime = event.getDownTime();
1058 long eventTime = event.getEventTime();
Jeff Brownac143512012-04-05 18:57:33 -07001059 int source = event.getSource();
Jeff Brownac143512012-04-05 18:57:33 -07001060 if (source == InputDevice.SOURCE_UNKNOWN) {
1061 source = InputDevice.SOURCE_KEYBOARD;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001062 }
Jeff Brownac143512012-04-05 18:57:33 -07001063 if (eventTime == 0) {
1064 eventTime = SystemClock.uptimeMillis();
1065 }
1066 if (downTime == 0) {
1067 downTime = eventTime;
1068 }
Tiger Huangfc218452018-09-27 00:38:50 +08001069 KeyEvent newEvent = new KeyEvent(event);
1070 newEvent.setTime(downTime, eventTime);
1071 newEvent.setSource(source);
1072 newEvent.setFlags(event.getFlags() | KeyEvent.FLAG_FROM_SYSTEM);
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001073 InputManager.getInstance().injectInputEvent(newEvent,
Jeff Brownac143512012-04-05 18:57:33 -07001074 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075 }
Tiger Huangfc218452018-09-27 00:38:50 +08001076
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001077 /**
1078 * Sends an up and down key event sync to the currently focused window.
1079 *
1080 * @param key The integer keycode for the event.
1081 */
1082 public void sendKeyDownUpSync(int key) {
1083 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key));
1084 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key));
1085 }
1086
1087 /**
1088 * Higher-level method for sending both the down and up key events for a
1089 * particular character key code. Equivalent to creating both KeyEvent
1090 * objects by hand and calling {@link #sendKeySync}. The event appears
1091 * as if it came from keyboard 0, the built in one.
1092 *
1093 * @param keyCode The key code of the character to send.
1094 */
1095 public void sendCharacterSync(int keyCode) {
1096 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode));
1097 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode));
1098 }
1099
1100 /**
1101 * Dispatch a pointer event. Finished at some point after the recipient has
1102 * returned from its event processing, though it may <em>not</em> have
1103 * completely finished reacting from the event -- for example, if it needs
1104 * to update its display as a result, it may still be in the process of
1105 * doing that.
1106 *
1107 * @param event A motion event describing the pointer action. (As noted in
1108 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
1109 * {@link SystemClock#uptimeMillis()} as the timebase.
1110 */
1111 public void sendPointerSync(MotionEvent event) {
1112 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001113 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) {
1114 event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 }
chaviw9f4bc552019-02-27 15:22:47 -08001116 try {
1117 WindowManagerGlobal.getWindowManagerService().injectInputAfterTransactionsApplied(event,
1118 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
1119 } catch (RemoteException e) {
1120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 }
1122
1123 /**
1124 * Dispatch a trackball event. Finished at some point after the recipient has
1125 * returned from its event processing, though it may <em>not</em> have
1126 * completely finished reacting from the event -- for example, if it needs
1127 * to update its display as a result, it may still be in the process of
1128 * doing that.
1129 *
1130 * @param event A motion event describing the trackball action. (As noted in
1131 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use
1132 * {@link SystemClock#uptimeMillis()} as the timebase.
1133 */
1134 public void sendTrackballEventSync(MotionEvent event) {
1135 validateNotAppThread();
Jeff Brownac143512012-04-05 18:57:33 -07001136 if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) {
1137 event.setSource(InputDevice.SOURCE_TRACKBALL);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 }
Jeff Brown9f25b7f2012-04-10 14:30:49 -07001139 InputManager.getInstance().injectInputEvent(event,
1140 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 }
1142
1143 /**
1144 * Perform instantiation of the process's {@link Application} object. The
1145 * default implementation provides the normal system behavior.
1146 *
1147 * @param cl The ClassLoader with which to instantiate the object.
1148 * @param className The name of the class implementing the Application
1149 * object.
1150 * @param context The context to initialize the application with
1151 *
1152 * @return The newly instantiated Application object.
1153 */
1154 public Application newApplication(ClassLoader cl, String className, Context context)
1155 throws InstantiationException, IllegalAccessException,
1156 ClassNotFoundException {
Jason Monka80bfb52017-11-16 17:15:37 -05001157 Application app = getFactory(context.getPackageName())
1158 .instantiateApplication(cl, className);
1159 app.attach(context);
1160 return app;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 }
1162
1163 /**
1164 * Perform instantiation of the process's {@link Application} object. The
1165 * default implementation provides the normal system behavior.
1166 *
1167 * @param clazz The class used to create an Application object from.
1168 * @param context The context to initialize the application with
1169 *
1170 * @return The newly instantiated Application object.
1171 */
1172 static public Application newApplication(Class<?> clazz, Context context)
1173 throws InstantiationException, IllegalAccessException,
1174 ClassNotFoundException {
1175 Application app = (Application)clazz.newInstance();
1176 app.attach(context);
1177 return app;
1178 }
1179
1180 /**
1181 * Perform calling of the application's {@link Application#onCreate}
1182 * method. The default implementation simply calls through to that method.
Dianne Hackborn6ae8d182012-05-23 13:12:42 -07001183 *
1184 * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}.
1185 * Often instrumentation tests start their test thread in onCreate(); you
1186 * need to be careful of races between these. (Well between it and
1187 * everything else, but let's start here.)
1188 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 * @param app The application being created.
1190 */
1191 public void callApplicationOnCreate(Application app) {
1192 app.onCreate();
1193 }
1194
1195 /**
1196 * Perform instantiation of an {@link Activity} object. This method is intended for use with
1197 * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable
Felipe Leme545569d2016-01-11 16:27:58 -08001198 * 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 -08001199 *
1200 * @param clazz The Class of the desired Activity
1201 * @param context The base context for the activity to use
1202 * @param token The token for this activity to communicate with
1203 * @param application The application object (if any)
1204 * @param intent The intent that started this Activity
1205 * @param info ActivityInfo from the manifest
1206 * @param title The title, typically retrieved from the ActivityInfo record
1207 * @param parent The parent Activity (if any)
1208 * @param id The embedded Id (if any)
1209 * @param lastNonConfigurationInstance Arbitrary object that will be
1210 * available via {@link Activity#getLastNonConfigurationInstance()
1211 * Activity.getLastNonConfigurationInstance()}.
1212 * @return Returns the instantiated activity
1213 * @throws InstantiationException
1214 * @throws IllegalAccessException
1215 */
1216 public Activity newActivity(Class<?> clazz, Context context,
1217 IBinder token, Application application, Intent intent, ActivityInfo info,
1218 CharSequence title, Activity parent, String id,
Sunny Goyald40c3452019-03-20 12:46:55 -07001219 Object lastNonConfigurationInstance) throws InstantiationException,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001220 IllegalAccessException {
1221 Activity activity = (Activity)clazz.newInstance();
1222 ActivityThread aThread = null;
Sudheer Shanka37820712018-04-11 15:47:35 -07001223 // Activity.attach expects a non-null Application Object.
1224 if (application == null) {
1225 application = new Application();
1226 }
Andrii Kulian51c1b672017-04-07 18:39:32 -07001227 activity.attach(context, aThread, this, token, 0 /* ident */, application, intent,
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07001228 info, title, parent, id,
1229 (Activity.NonConfigurationInstances)lastNonConfigurationInstance,
Andrii Kulian51c1b672017-04-07 18:39:32 -07001230 new Configuration(), null /* referrer */, null /* voiceInteractor */,
Sunny Goyald40c3452019-03-20 12:46:55 -07001231 null /* window */, null /* activityConfigCallback */, null /*assistToken*/);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001232 return activity;
1233 }
1234
1235 /**
1236 * Perform instantiation of the process's {@link Activity} object. The
1237 * default implementation provides the normal system behavior.
1238 *
1239 * @param cl The ClassLoader with which to instantiate the object.
1240 * @param className The name of the class implementing the Activity
1241 * object.
1242 * @param intent The Intent object that specified the activity class being
1243 * instantiated.
1244 *
1245 * @return The newly instantiated Activity object.
1246 */
1247 public Activity newActivity(ClassLoader cl, String className,
1248 Intent intent)
1249 throws InstantiationException, IllegalAccessException,
1250 ClassNotFoundException {
Jason Monke96443e2018-04-18 15:43:50 -04001251 String pkg = intent != null && intent.getComponent() != null
1252 ? intent.getComponent().getPackageName() : null;
Jason Monka80bfb52017-11-16 17:15:37 -05001253 return getFactory(pkg).instantiateActivity(cl, className, intent);
1254 }
1255
1256 private AppComponentFactory getFactory(String pkg) {
Jason Monke96443e2018-04-18 15:43:50 -04001257 if (pkg == null) {
1258 Log.e(TAG, "No pkg specified, disabling AppComponentFactory");
1259 return AppComponentFactory.DEFAULT;
1260 }
Jason Monk24d12a32017-12-21 10:39:17 -05001261 if (mThread == null) {
1262 Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation,"
1263 + " disabling AppComponentFactory", new Throwable());
1264 return AppComponentFactory.DEFAULT;
1265 }
Todd Kennedy233a0b12018-01-29 20:30:24 +00001266 LoadedApk apk = mThread.peekPackageInfo(pkg, true);
Jason Monka80bfb52017-11-16 17:15:37 -05001267 // This is in the case of starting up "android".
Todd Kennedy233a0b12018-01-29 20:30:24 +00001268 if (apk == null) apk = mThread.getSystemContext().mPackageInfo;
1269 return apk.getAppFactory();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 }
1271
Craig Mautnera0026042014-04-23 11:45:37 -07001272 private void prePerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001273 if (mWaitingActivities != null) {
1274 synchronized (mSync) {
1275 final int N = mWaitingActivities.size();
1276 for (int i=0; i<N; i++) {
1277 final ActivityWaiter aw = mWaitingActivities.get(i);
1278 final Intent intent = aw.intent;
1279 if (intent.filterEquals(activity.getIntent())) {
1280 aw.activity = activity;
1281 mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1282 }
1283 }
1284 }
1285 }
Craig Mautnera0026042014-04-23 11:45:37 -07001286 }
1287
1288 private void postPerformCreate(Activity activity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001289 if (mActivityMonitors != null) {
1290 synchronized (mSync) {
1291 final int N = mActivityMonitors.size();
1292 for (int i=0; i<N; i++) {
1293 final ActivityMonitor am = mActivityMonitors.get(i);
1294 am.match(activity, activity, activity.getIntent());
1295 }
1296 }
1297 }
1298 }
Craig Mautnera0026042014-04-23 11:45:37 -07001299
1300 /**
1301 * Perform calling of an activity's {@link Activity#onCreate}
1302 * method. The default implementation simply calls through to that method.
1303 *
1304 * @param activity The activity being created.
1305 * @param icicle The previously frozen state (or null) to pass through to onCreate().
1306 */
1307 public void callActivityOnCreate(Activity activity, Bundle icicle) {
1308 prePerformCreate(activity);
1309 activity.performCreate(icicle);
1310 postPerformCreate(activity);
1311 }
1312
1313 /**
1314 * Perform calling of an activity's {@link Activity#onCreate}
1315 * method. The default implementation simply calls through to that method.
1316 * @param activity The activity being created.
1317 * @param icicle The previously frozen state (or null) to pass through to
1318 * @param persistentState The previously persisted state (or null)
1319 */
1320 public void callActivityOnCreate(Activity activity, Bundle icicle,
1321 PersistableBundle persistentState) {
1322 prePerformCreate(activity);
1323 activity.performCreate(icicle, persistentState);
1324 postPerformCreate(activity);
1325 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001326
1327 public void callActivityOnDestroy(Activity activity) {
Brett Chabot18f9ce02010-05-12 12:41:50 -07001328 // TODO: the following block causes intermittent hangs when using startActivity
1329 // temporarily comment out until root cause is fixed (bug 2630683)
1330// if (mWaitingActivities != null) {
1331// synchronized (mSync) {
1332// final int N = mWaitingActivities.size();
1333// for (int i=0; i<N; i++) {
1334// final ActivityWaiter aw = mWaitingActivities.get(i);
1335// final Intent intent = aw.intent;
1336// if (intent.filterEquals(activity.getIntent())) {
1337// aw.activity = activity;
1338// mMessageQueue.addIdleHandler(new ActivityGoing(aw));
1339// }
1340// }
1341// }
1342// }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001343
Dianne Hackborn2dedce62010-04-15 14:45:25 -07001344 activity.performDestroy();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001345 }
1346
1347 /**
1348 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1349 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001350 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001351 * @param activity The activity being restored.
1352 * @param savedInstanceState The previously saved state being restored.
1353 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001354 public void callActivityOnRestoreInstanceState(@NonNull Activity activity,
1355 @NonNull Bundle savedInstanceState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001356 activity.performRestoreInstanceState(savedInstanceState);
1357 }
1358
1359 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001360 * Perform calling of an activity's {@link Activity#onRestoreInstanceState}
1361 * method. The default implementation simply calls through to that method.
1362 *
1363 * @param activity The activity being restored.
Jake Wharton63f4d892018-07-10 12:27:59 -04001364 * @param savedInstanceState The previously saved state being restored (or null).
Craig Mautnera0026042014-04-23 11:45:37 -07001365 * @param persistentState The previously persisted state (or null)
1366 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001367 public void callActivityOnRestoreInstanceState(@NonNull Activity activity,
1368 @Nullable Bundle savedInstanceState,
1369 @Nullable PersistableBundle persistentState) {
Craig Mautnera0026042014-04-23 11:45:37 -07001370 activity.performRestoreInstanceState(savedInstanceState, persistentState);
1371 }
1372
1373 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001374 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1375 * The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001376 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001377 * @param activity The activity being created.
Jake Wharton63f4d892018-07-10 12:27:59 -04001378 * @param savedInstanceState The previously saved state (or null) to pass through to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001379 * onPostCreate().
1380 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001381 public void callActivityOnPostCreate(@NonNull Activity activity,
1382 @Nullable Bundle savedInstanceState) {
1383 activity.onPostCreate(savedInstanceState);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001384 }
1385
1386 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001387 * Perform calling of an activity's {@link Activity#onPostCreate} method.
1388 * The default implementation simply calls through to that method.
1389 *
1390 * @param activity The activity being created.
Jake Wharton63f4d892018-07-10 12:27:59 -04001391 * @param savedInstanceState The previously frozen state (or null) to pass through to
Craig Mautnera0026042014-04-23 11:45:37 -07001392 * onPostCreate().
Jake Wharton63f4d892018-07-10 12:27:59 -04001393 * @param persistentState The previously persisted state (or null)
Craig Mautnera0026042014-04-23 11:45:37 -07001394 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001395 public void callActivityOnPostCreate(@NonNull Activity activity,
1396 @Nullable Bundle savedInstanceState,
1397 @Nullable PersistableBundle persistentState) {
1398 activity.onPostCreate(savedInstanceState, persistentState);
Craig Mautnera0026042014-04-23 11:45:37 -07001399 }
1400
1401 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001402 * Perform calling of an activity's {@link Activity#onNewIntent}
1403 * method. The default implementation simply calls through to that method.
1404 *
1405 * @param activity The activity receiving a new Intent.
1406 * @param intent The new intent being received.
1407 */
1408 public void callActivityOnNewIntent(Activity activity, Intent intent) {
Winson Chung298f95b2017-08-10 15:57:18 -07001409 activity.performNewIntent(intent);
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001410 }
1411
1412 /**
1413 * @hide
1414 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001415 @UnsupportedAppUsage
Dianne Hackborna01a0fa2014-12-02 10:33:14 -08001416 public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) {
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001417 final String oldReferrer = activity.mReferrer;
1418 try {
Dianne Hackborn80b1c562014-12-09 20:22:08 -08001419 if (intent != null) {
1420 activity.mReferrer = intent.mReferrer;
1421 }
1422 callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null);
Dianne Hackborn85d558c2014-11-04 10:31:54 -08001423 } finally {
1424 activity.mReferrer = oldReferrer;
1425 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001426 }
1427
1428 /**
1429 * Perform calling of an activity's {@link Activity#onStart}
1430 * method. The default implementation simply calls through to that method.
1431 *
1432 * @param activity The activity being started.
1433 */
1434 public void callActivityOnStart(Activity activity) {
1435 activity.onStart();
1436 }
1437
1438 /**
1439 * Perform calling of an activity's {@link Activity#onRestart}
1440 * method. The default implementation simply calls through to that method.
1441 *
1442 * @param activity The activity being restarted.
1443 */
1444 public void callActivityOnRestart(Activity activity) {
1445 activity.onRestart();
1446 }
1447
1448 /**
1449 * Perform calling of an activity's {@link Activity#onResume} method. The
1450 * default implementation simply calls through to that method.
1451 *
1452 * @param activity The activity being resumed.
1453 */
1454 public void callActivityOnResume(Activity activity) {
Jeff Hamilton52d32032011-01-08 15:31:26 -06001455 activity.mResumed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001456 activity.onResume();
1457
1458 if (mActivityMonitors != null) {
1459 synchronized (mSync) {
1460 final int N = mActivityMonitors.size();
1461 for (int i=0; i<N; i++) {
1462 final ActivityMonitor am = mActivityMonitors.get(i);
1463 am.match(activity, activity, activity.getIntent());
1464 }
1465 }
1466 }
1467 }
1468
1469 /**
1470 * Perform calling of an activity's {@link Activity#onStop}
1471 * method. The default implementation simply calls through to that method.
1472 *
1473 * @param activity The activity being stopped.
1474 */
1475 public void callActivityOnStop(Activity activity) {
1476 activity.onStop();
1477 }
1478
1479 /**
Newton Allenc5027442013-08-13 11:22:32 -07001480 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1481 * method. The default implementation simply calls through to that method.
Craig Mautnera0026042014-04-23 11:45:37 -07001482 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001483 * @param activity The activity being saved.
1484 * @param outState The bundle to pass to the call.
1485 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001486 public void callActivityOnSaveInstanceState(@NonNull Activity activity,
1487 @NonNull Bundle outState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001488 activity.performSaveInstanceState(outState);
1489 }
1490
1491 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001492 * Perform calling of an activity's {@link Activity#onSaveInstanceState}
1493 * method. The default implementation simply calls through to that method.
1494 * @param activity The activity being saved.
1495 * @param outState The bundle to pass to the call.
1496 * @param outPersistentState The persistent bundle to pass to the call.
1497 */
Jake Wharton63f4d892018-07-10 12:27:59 -04001498 public void callActivityOnSaveInstanceState(@NonNull Activity activity,
1499 @NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
Craig Mautnera0026042014-04-23 11:45:37 -07001500 activity.performSaveInstanceState(outState, outPersistentState);
1501 }
1502
1503 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001504 * Perform calling of an activity's {@link Activity#onPause} method. The
1505 * default implementation simply calls through to that method.
1506 *
1507 * @param activity The activity being paused.
1508 */
1509 public void callActivityOnPause(Activity activity) {
1510 activity.performPause();
1511 }
1512
1513 /**
1514 * Perform calling of an activity's {@link Activity#onUserLeaveHint} method.
1515 * The default implementation simply calls through to that method.
1516 *
1517 * @param activity The activity being notified that the user has navigated away
1518 */
1519 public void callActivityOnUserLeaving(Activity activity) {
1520 activity.performUserLeaving();
1521 }
jorgegil@google.com06bc3232019-10-31 14:51:22 -07001522
1523 /**
1524 * Perform calling of an activity's {@link Activity#onPictureInPictureRequested} method.
1525 * The default implementation simply calls through to that method.
1526 *
1527 * @param activity The activity being notified that picture-in-picture is being requested.
1528 */
1529 public void callActivityOnPictureInPictureRequested(@NonNull Activity activity) {
1530 activity.onPictureInPictureRequested();
1531 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001532
1533 /*
1534 * Starts allocation counting. This triggers a gc and resets the counts.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001535 *
1536 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001537 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001538 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001539 public void startAllocCounting() {
1540 // Before we start trigger a GC and reset the debug counts. Run the
1541 // finalizers and another GC before starting and stopping the alloc
1542 // counts. This will free up any objects that were just sitting around
1543 // waiting for their finalizers to be run.
1544 Runtime.getRuntime().gc();
1545 Runtime.getRuntime().runFinalization();
1546 Runtime.getRuntime().gc();
1547
1548 Debug.resetAllCounts();
1549
1550 // start the counts
1551 Debug.startAllocCounting();
1552 }
1553
1554 /*
1555 * Stops allocation counting.
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001556 *
1557 * @deprecated Accurate counting is a burden on the runtime and may be removed.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001558 */
Hiroshi Yamauchi172da262015-03-04 12:29:19 -08001559 @Deprecated
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001560 public void stopAllocCounting() {
1561 Runtime.getRuntime().gc();
1562 Runtime.getRuntime().runFinalization();
1563 Runtime.getRuntime().gc();
1564 Debug.stopAllocCounting();
1565 }
1566
1567 /**
1568 * If Results already contains Key, it appends Value to the key's ArrayList
1569 * associated with the key. If the key doesn't already exist in results, it
1570 * adds the key/value pair to results.
1571 */
1572 private void addValue(String key, int value, Bundle results) {
1573 if (results.containsKey(key)) {
1574 List<Integer> list = results.getIntegerArrayList(key);
1575 if (list != null) {
1576 list.add(value);
1577 }
1578 } else {
1579 ArrayList<Integer> list = new ArrayList<Integer>();
1580 list.add(value);
1581 results.putIntegerArrayList(key, list);
1582 }
1583 }
1584
1585 /**
1586 * Returns a bundle with the current results from the allocation counting.
1587 */
1588 public Bundle getAllocCounts() {
1589 Bundle results = new Bundle();
1590 results.putLong("global_alloc_count", Debug.getGlobalAllocCount());
1591 results.putLong("global_alloc_size", Debug.getGlobalAllocSize());
1592 results.putLong("global_freed_count", Debug.getGlobalFreedCount());
1593 results.putLong("global_freed_size", Debug.getGlobalFreedSize());
1594 results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount());
1595 return results;
1596 }
1597
1598 /**
1599 * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are
1600 * reported are the number of send and the number of received transactions.
1601 */
1602 public Bundle getBinderCounts() {
1603 Bundle results = new Bundle();
1604 results.putLong("sent_transactions", Debug.getBinderSentTransactions());
1605 results.putLong("received_transactions", Debug.getBinderReceivedTransactions());
1606 return results;
1607 }
1608
1609 /**
1610 * Description of a Activity execution result to return to the original
1611 * activity.
1612 */
1613 public static final class ActivityResult {
1614 /**
1615 * Create a new activity result. See {@link Activity#setResult} for
1616 * more information.
1617 *
1618 * @param resultCode The result code to propagate back to the
1619 * originating activity, often RESULT_CANCELED or RESULT_OK
1620 * @param resultData The data to propagate back to the originating
1621 * activity.
1622 */
1623 public ActivityResult(int resultCode, Intent resultData) {
1624 mResultCode = resultCode;
1625 mResultData = resultData;
1626 }
1627
1628 /**
1629 * Retrieve the result code contained in this result.
1630 */
1631 public int getResultCode() {
1632 return mResultCode;
1633 }
1634
1635 /**
1636 * Retrieve the data contained in this result.
1637 */
1638 public Intent getResultData() {
1639 return mResultData;
1640 }
1641
1642 private final int mResultCode;
1643 private final Intent mResultData;
1644 }
1645
1646 /**
1647 * Execute a startActivity call made by the application. The default
1648 * implementation takes care of updating any active {@link ActivityMonitor}
1649 * objects and dispatches this call to the system activity manager; you can
1650 * override this to watch for the application to start an activity, and
1651 * modify what happens when it does.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001652 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001653 * <p>This method returns an {@link ActivityResult} object, which you can
1654 * use when intercepting application calls to avoid performing the start
1655 * activity action but still return the result the application is
1656 * expecting. To do this, override this method to catch the call to start
1657 * activity so that it returns a new ActivityResult containing the results
1658 * you would like the application to see, and don't call up to the super
1659 * class. Note that an application is only expecting a result if
1660 * <var>requestCode</var> is &gt;= 0.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001661 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001662 * <p>This method throws {@link android.content.ActivityNotFoundException}
1663 * if there was no Activity found to run the given Intent.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001664 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001665 * @param who The Context from which the activity is being started.
1666 * @param contextThread The main thread of the Context from which the activity
1667 * is being started.
1668 * @param token Internal token identifying to the system who is starting
1669 * the activity; may be null.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001670 * @param target Which activity is performing the start (and thus receiving
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001671 * any result); may be null if this call is not being made
1672 * from an activity.
1673 * @param intent The actual Intent to start.
1674 * @param requestCode Identifier for this request's result; less than zero
1675 * if the caller is not expecting a result.
Dianne Hackborna4972e92012-03-14 10:38:05 -07001676 * @param options Addition options.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001677 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001678 * @return To force the return of a particular result, return an
1679 * ActivityResult object containing the desired data; otherwise
1680 * return null. The default implementation always returns null.
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001681 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001682 * @throws android.content.ActivityNotFoundException
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001683 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001684 * @see Activity#startActivity(Intent)
1685 * @see Activity#startActivityForResult(Intent, int)
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001686 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001687 * {@hide}
1688 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001689 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001690 public ActivityResult execStartActivity(
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001691 Context who, IBinder contextThread, IBinder token, Activity target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001692 Intent intent, int requestCode, Bundle options) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001693 IApplicationThread whoThread = (IApplicationThread) contextThread;
Dianne Hackborna3acdb32015-06-08 17:07:40 -07001694 Uri referrer = target != null ? target.onProvideReferrer() : null;
1695 if (referrer != null) {
1696 intent.putExtra(Intent.EXTRA_REFERRER, referrer);
1697 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001698 if (mActivityMonitors != null) {
1699 synchronized (mSync) {
1700 final int N = mActivityMonitors.size();
1701 for (int i=0; i<N; i++) {
1702 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001703 ActivityResult result = null;
1704 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001705 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001706 }
1707 if (result != null) {
1708 am.mHits++;
1709 return result;
1710 } else if (am.match(who, null, intent)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001711 am.mHits++;
1712 if (am.isBlocking()) {
1713 return requestCode >= 0 ? am.getResult() : null;
1714 }
1715 break;
1716 }
1717 }
1718 }
1719 }
1720 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001721 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001722 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001723 int result = ActivityTaskManager.getService()
Philip P. Moltmann9c5226f2020-01-10 08:53:43 -08001724 .startActivity(whoThread, who.getBasePackageName(), who.getFeatureId(), intent,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001725 intent.resolveTypeIfNeeded(who.getContentResolver()),
Dianne Hackborna4972e92012-03-14 10:38:05 -07001726 token, target != null ? target.mEmbeddedID : null,
Jeff Hao1b012d32014-08-20 10:35:34 -07001727 requestCode, 0, null, options);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001728 checkStartActivityResult(result, intent);
1729 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001730 throw new RuntimeException("Failure from system", e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001731 }
1732 return null;
1733 }
1734
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001735 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001736 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001737 * but accepts an array of activities to be started. Note that active
1738 * {@link ActivityMonitor} objects only match against the first activity in
1739 * the array.
1740 *
1741 * {@hide}
1742 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001743 @UnsupportedAppUsage
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001744 public void execStartActivities(Context who, IBinder contextThread,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001745 IBinder token, Activity target, Intent[] intents, Bundle options) {
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001746 execStartActivitiesAsUser(who, contextThread, token, target, intents, options,
Jeff Sharkeyad357d12018-02-02 13:25:31 -07001747 who.getUserId());
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001748 }
1749
1750 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001751 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001752 * but accepts an array of activities to be started. Note that active
1753 * {@link ActivityMonitor} objects only match against the first activity in
1754 * the array.
1755 *
Selim Cinek7fa385a2018-01-24 08:35:28 -08001756 * @return The corresponding flag {@link ActivityManager#START_CANCELED},
1757 * {@link ActivityManager#START_SUCCESS} etc. indicating whether the launch was
1758 * successful.
1759 *
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001760 * {@hide}
1761 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001762 @UnsupportedAppUsage
Selim Cinek7fa385a2018-01-24 08:35:28 -08001763 public int execStartActivitiesAsUser(Context who, IBinder contextThread,
Amith Yamasaniea7e9152012-09-24 16:11:18 -07001764 IBinder token, Activity target, Intent[] intents, Bundle options,
1765 int userId) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001766 IApplicationThread whoThread = (IApplicationThread) contextThread;
1767 if (mActivityMonitors != null) {
1768 synchronized (mSync) {
1769 final int N = mActivityMonitors.size();
1770 for (int i=0; i<N; i++) {
1771 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001772 ActivityResult result = null;
1773 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001774 result = am.onStartActivity(intents[0]);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001775 }
1776 if (result != null) {
1777 am.mHits++;
Selim Cinek7fa385a2018-01-24 08:35:28 -08001778 return ActivityManager.START_CANCELED;
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001779 } else if (am.match(who, null, intents[0])) {
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001780 am.mHits++;
1781 if (am.isBlocking()) {
Selim Cinek7fa385a2018-01-24 08:35:28 -08001782 return ActivityManager.START_CANCELED;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001783 }
1784 break;
1785 }
1786 }
1787 }
1788 }
1789 try {
1790 String[] resolvedTypes = new String[intents.length];
1791 for (int i=0; i<intents.length; i++) {
Jeff Sharkeya14acd22013-04-02 18:27:45 -07001792 intents[i].migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001793 intents[i].prepareToLeaveProcess(who);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001794 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver());
1795 }
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001796 int result = ActivityTaskManager.getService()
Philip P. Moltmann9c5226f2020-01-10 08:53:43 -08001797 .startActivities(whoThread, who.getBasePackageName(), who.getFeatureId(), intents,
1798 resolvedTypes, token, options, userId);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001799 checkStartActivityResult(result, intents[0]);
Selim Cinek7fa385a2018-01-24 08:35:28 -08001800 return result;
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001801 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001802 throw new RuntimeException("Failure from system", e);
Dianne Hackborn621e17d2010-11-22 15:59:56 -08001803 }
1804 }
1805
1806 /**
Dianne Hackbornf265ea92013-01-31 15:00:51 -08001807 * Like {@link #execStartActivity(android.content.Context, android.os.IBinder,
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001808 * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)},
Andrew Solovay5c05ded2018-10-02 14:14:42 -07001809 * but for calls from a {@link Fragment}.
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001810 *
1811 * @param who The Context from which the activity is being started.
1812 * @param contextThread The main thread of the Context from which the activity
1813 * is being started.
1814 * @param token Internal token identifying to the system who is starting
1815 * the activity; may be null.
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001816 * @param target Which element is performing the start (and thus receiving
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001817 * any result).
1818 * @param intent The actual Intent to start.
1819 * @param requestCode Identifier for this request's result; less than zero
1820 * if the caller is not expecting a result.
1821 *
1822 * @return To force the return of a particular result, return an
1823 * ActivityResult object containing the desired data; otherwise
1824 * return null. The default implementation always returns null.
1825 *
1826 * @throws android.content.ActivityNotFoundException
1827 *
1828 * @see Activity#startActivity(Intent)
1829 * @see Activity#startActivityForResult(Intent, int)
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001830 *
1831 * {@hide}
1832 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001833 @UnsupportedAppUsage
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001834 public ActivityResult execStartActivity(
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001835 Context who, IBinder contextThread, IBinder token, String target,
Dianne Hackborna4972e92012-03-14 10:38:05 -07001836 Intent intent, int requestCode, Bundle options) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001837 IApplicationThread whoThread = (IApplicationThread) contextThread;
1838 if (mActivityMonitors != null) {
1839 synchronized (mSync) {
1840 final int N = mActivityMonitors.size();
1841 for (int i=0; i<N; i++) {
1842 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001843 ActivityResult result = null;
1844 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001845 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001846 }
1847 if (result != null) {
1848 am.mHits++;
1849 return result;
1850 } else if (am.match(who, null, intent)) {
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001851 am.mHits++;
1852 if (am.isBlocking()) {
1853 return requestCode >= 0 ? am.getResult() : null;
1854 }
1855 break;
1856 }
1857 }
1858 }
1859 }
1860 try {
Jeff Sharkey678d04f2012-03-23 15:41:58 -07001861 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001862 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001863 int result = ActivityTaskManager.getService()
Philip P. Moltmann9c5226f2020-01-10 08:53:43 -08001864 .startActivity(whoThread, who.getBasePackageName(), who.getFeatureId(), intent,
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001865 intent.resolveTypeIfNeeded(who.getContentResolver()),
Clara Bayarrid5bf3ed2015-03-27 17:32:45 +00001866 token, target, requestCode, 0, null, options);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001867 checkStartActivityResult(result, intent);
1868 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001869 throw new RuntimeException("Failure from system", e);
Dianne Hackborn6e8304e2010-05-14 00:42:53 -07001870 }
1871 return null;
1872 }
1873
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001874 /**
Craig Mautnera0026042014-04-23 11:45:37 -07001875 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)},
1876 * but for starting as a particular user.
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001877 *
1878 * @param who The Context from which the activity is being started.
1879 * @param contextThread The main thread of the Context from which the activity
1880 * is being started.
1881 * @param token Internal token identifying to the system who is starting
1882 * the activity; may be null.
1883 * @param target Which fragment is performing the start (and thus receiving
1884 * any result).
1885 * @param intent The actual Intent to start.
1886 * @param requestCode Identifier for this request's result; less than zero
1887 * if the caller is not expecting a result.
1888 *
1889 * @return To force the return of a particular result, return an
1890 * ActivityResult object containing the desired data; otherwise
1891 * return null. The default implementation always returns null.
1892 *
1893 * @throws android.content.ActivityNotFoundException
1894 *
1895 * @see Activity#startActivity(Intent)
1896 * @see Activity#startActivityForResult(Intent, int)
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001897 *
1898 * {@hide}
1899 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001900 @UnsupportedAppUsage
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001901 public ActivityResult execStartActivity(
Tony Mak96d26fe2017-04-11 20:05:39 +01001902 Context who, IBinder contextThread, IBinder token, String resultWho,
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001903 Intent intent, int requestCode, Bundle options, UserHandle user) {
1904 IApplicationThread whoThread = (IApplicationThread) contextThread;
1905 if (mActivityMonitors != null) {
1906 synchronized (mSync) {
1907 final int N = mActivityMonitors.size();
1908 for (int i=0; i<N; i++) {
1909 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001910 ActivityResult result = null;
1911 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001912 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001913 }
1914 if (result != null) {
1915 am.mHits++;
1916 return result;
1917 } else if (am.match(who, null, intent)) {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001918 am.mHits++;
1919 if (am.isBlocking()) {
1920 return requestCode >= 0 ? am.getResult() : null;
1921 }
1922 break;
1923 }
1924 }
1925 }
1926 }
1927 try {
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001928 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001929 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001930 int result = ActivityTaskManager.getService()
Philip P. Moltmann9c5226f2020-01-10 08:53:43 -08001931 .startActivityAsUser(whoThread, who.getBasePackageName(), who.getFeatureId(),
1932 intent, intent.resolveTypeIfNeeded(who.getContentResolver()),
Tony Mak96d26fe2017-04-11 20:05:39 +01001933 token, resultWho,
Jeff Hao1b012d32014-08-20 10:35:34 -07001934 requestCode, 0, null, options, user.getIdentifier());
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001935 checkStartActivityResult(result, intent);
1936 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001937 throw new RuntimeException("Failure from system", e);
Dianne Hackbornf1c26e22012-08-23 13:54:58 -07001938 }
1939 return null;
1940 }
1941
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001942 /**
1943 * Special version!
1944 * @hide
1945 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001946 @UnsupportedAppUsage
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001947 public ActivityResult execStartActivityAsCaller(
1948 Context who, IBinder contextThread, IBinder token, Activity target,
Alison Cichowlas3e340502018-08-07 17:15:01 -04001949 Intent intent, int requestCode, Bundle options, IBinder permissionToken,
1950 boolean ignoreTargetSecurity, int userId) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001951 IApplicationThread whoThread = (IApplicationThread) contextThread;
1952 if (mActivityMonitors != null) {
1953 synchronized (mSync) {
1954 final int N = mActivityMonitors.size();
1955 for (int i=0; i<N; i++) {
1956 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001957 ActivityResult result = null;
1958 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07001959 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08001960 }
1961 if (result != null) {
1962 am.mHits++;
1963 return result;
1964 } else if (am.match(who, null, intent)) {
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001965 am.mHits++;
1966 if (am.isBlocking()) {
1967 return requestCode >= 0 ? am.getResult() : null;
1968 }
1969 break;
1970 }
1971 }
1972 }
1973 }
1974 try {
1975 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07001976 intent.prepareToLeaveProcess(who);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001977 int result = ActivityTaskManager.getService()
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001978 .startActivityAsCaller(whoThread, who.getBasePackageName(), intent,
1979 intent.resolveTypeIfNeeded(who.getContentResolver()),
1980 token, target != null ? target.mEmbeddedID : null,
Alison Cichowlas3e340502018-08-07 17:15:01 -04001981 requestCode, 0, null, options, permissionToken,
1982 ignoreTargetSecurity, userId);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001983 checkStartActivityResult(result, intent);
1984 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07001985 throw new RuntimeException("Failure from system", e);
Dianne Hackborn028ceeb2014-08-17 17:45:48 -07001986 }
1987 return null;
1988 }
1989
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001990 /**
1991 * Special version!
1992 * @hide
1993 */
Mathew Inwood61e8ae62018-08-14 14:17:44 +01001994 @UnsupportedAppUsage
Dianne Hackborn89ad4562014-08-24 16:45:38 -07001995 public void execStartActivityFromAppTask(
1996 Context who, IBinder contextThread, IAppTask appTask,
1997 Intent intent, Bundle options) {
1998 IApplicationThread whoThread = (IApplicationThread) contextThread;
1999 if (mActivityMonitors != null) {
2000 synchronized (mSync) {
2001 final int N = mActivityMonitors.size();
2002 for (int i=0; i<N; i++) {
2003 final ActivityMonitor am = mActivityMonitors.get(i);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08002004 ActivityResult result = null;
2005 if (am.ignoreMatchingSpecificIntents()) {
Sudheer Shanka34217512017-04-26 14:49:16 -07002006 result = am.onStartActivity(intent);
Sudheer Shankad1d12d12017-01-13 12:07:26 -08002007 }
2008 if (result != null) {
2009 am.mHits++;
2010 return;
2011 } else if (am.match(who, null, intent)) {
Dianne Hackborn89ad4562014-08-24 16:45:38 -07002012 am.mHits++;
2013 if (am.isBlocking()) {
2014 return;
2015 }
2016 break;
2017 }
2018 }
2019 }
2020 }
2021 try {
2022 intent.migrateExtraStreamToClipData();
Jeff Sharkey344744b2016-01-28 19:03:30 -07002023 intent.prepareToLeaveProcess(who);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07002024 int result = appTask.startActivity(whoThread.asBinder(), who.getBasePackageName(),
Philip P. Moltmann9c5226f2020-01-10 08:53:43 -08002025 who.getFeatureId(), intent,
2026 intent.resolveTypeIfNeeded(who.getContentResolver()), options);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07002027 checkStartActivityResult(result, intent);
2028 } catch (RemoteException e) {
Dianne Hackborne5c42622015-05-19 16:04:04 -07002029 throw new RuntimeException("Failure from system", e);
Dianne Hackborn89ad4562014-08-24 16:45:38 -07002030 }
2031 return;
2032 }
2033
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002034 /*package*/ final void init(ActivityThread thread,
2035 Context instrContext, Context appContext, ComponentName component,
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002036 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002037 mThread = thread;
2038 mMessageQueue = mThread.getLooper().myQueue();
2039 mInstrContext = instrContext;
2040 mAppContext = appContext;
2041 mComponent = component;
2042 mWatcher = watcher;
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002043 mUiAutomationConnection = uiAutomationConnection;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002044 }
2045
Jason Monka80bfb52017-11-16 17:15:37 -05002046 /**
2047 * Only sets the ActivityThread up, keeps everything else null because app is not being
2048 * instrumented.
2049 */
2050 final void basicInit(ActivityThread thread) {
2051 mThread = thread;
2052 }
2053
Dianne Hackborn91097de2014-04-04 18:02:06 -07002054 /** @hide */
Mathew Inwood31755f92018-12-20 13:53:36 +00002055 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Dianne Hackborn91097de2014-04-04 18:02:06 -07002056 public static void checkStartActivityResult(int res, Object intent) {
Bryce Lee7f936862017-05-09 15:33:18 -07002057 if (!ActivityManager.isStartResultFatalError(res)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002058 return;
2059 }
Amith Yamasani42449782016-04-19 11:45:51 -07002060
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002061 switch (res) {
Dianne Hackborna4972e92012-03-14 10:38:05 -07002062 case ActivityManager.START_INTENT_NOT_RESOLVED:
2063 case ActivityManager.START_CLASS_NOT_FOUND:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002064 if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002065 throw new ActivityNotFoundException(
2066 "Unable to find explicit activity class "
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002067 + ((Intent)intent).getComponent().toShortString()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002068 + "; have you declared this activity in your AndroidManifest.xml?");
2069 throw new ActivityNotFoundException(
2070 "No Activity found to handle " + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002071 case ActivityManager.START_PERMISSION_DENIED:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002072 throw new SecurityException("Not allowed to start activity "
2073 + intent);
Dianne Hackborna4972e92012-03-14 10:38:05 -07002074 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002075 throw new AndroidRuntimeException(
2076 "FORWARD_RESULT_FLAG used while also requesting a result");
Dianne Hackborna4972e92012-03-14 10:38:05 -07002077 case ActivityManager.START_NOT_ACTIVITY:
Dianne Hackbornbcbcaa72009-09-10 10:54:46 -07002078 throw new IllegalArgumentException(
2079 "PendingIntent is not an activity");
Dianne Hackborn91097de2014-04-04 18:02:06 -07002080 case ActivityManager.START_NOT_VOICE_COMPATIBLE:
2081 throw new SecurityException(
2082 "Starting under voice control not allowed for: " + intent);
Amith Yamasani42449782016-04-19 11:45:51 -07002083 case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION:
2084 throw new IllegalStateException(
2085 "Session calling startVoiceActivity does not match active session");
2086 case ActivityManager.START_VOICE_HIDDEN_SESSION:
2087 throw new IllegalStateException(
2088 "Cannot start voice activity on a hidden session");
Winson Chungfc3ec4c2017-06-01 15:35:48 -07002089 case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
2090 throw new IllegalStateException(
2091 "Session calling startAssistantActivity does not match active session");
2092 case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
2093 throw new IllegalStateException(
2094 "Cannot start assistant activity on a hidden session");
Amith Yamasani42449782016-04-19 11:45:51 -07002095 case ActivityManager.START_CANCELED:
2096 throw new AndroidRuntimeException("Activity could not be started for "
2097 + intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002098 default:
2099 throw new AndroidRuntimeException("Unknown error code "
2100 + res + " when starting " + intent);
2101 }
2102 }
Chong Zhang45c25ce2015-08-10 22:18:26 -07002103
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002104 private final void validateNotAppThread() {
Kristian Monsen0a303282013-01-18 14:50:07 -08002105 if (Looper.myLooper() == Looper.getMainLooper()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002106 throw new RuntimeException(
2107 "This method can not be called from the main application thread");
2108 }
2109 }
2110
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002111 /**
Phil Weaverd8e88832016-03-28 17:26:25 -07002112 * Gets the {@link UiAutomation} instance with no flags set.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002113 * <p>
2114 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
2115 * work across application boundaries while the APIs exposed by the instrumentation
2116 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
2117 * not allow you to inject the event in an app different from the instrumentation
2118 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
2119 * will work regardless of the current application.
2120 * </p>
2121 * <p>
2122 * A typical test case should be using either the {@link UiAutomation} or
2123 * {@link Instrumentation} APIs. Using both APIs at the same time is not
2124 * a mistake by itself but a client has to be aware of the APIs limitations.
2125 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07002126 * <p>
2127 * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different
2128 * flags, the flags on that instance will be changed, and then it will be returned.
2129 * </p>
2130 * @return The UI automation instance.
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002131 *
2132 * @see UiAutomation
2133 */
2134 public UiAutomation getUiAutomation() {
Phil Weaverd8e88832016-03-28 17:26:25 -07002135 return getUiAutomation(0);
Phil Weaver1dd87222016-01-26 17:15:15 -08002136 }
2137
2138 /**
2139 * Gets the {@link UiAutomation} instance with flags set.
2140 * <p>
Phil Weaver1dd87222016-01-26 17:15:15 -08002141 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation}
2142 * work across application boundaries while the APIs exposed by the instrumentation
2143 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will
2144 * not allow you to inject the event in an app different from the instrumentation
2145 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)}
2146 * will work regardless of the current application.
2147 * </p>
2148 * <p>
2149 * A typical test case should be using either the {@link UiAutomation} or
2150 * {@link Instrumentation} APIs. Using both APIs at the same time is not
2151 * a mistake by itself but a client has to be aware of the APIs limitations.
2152 * </p>
Phil Weaverd8e88832016-03-28 17:26:25 -07002153 * <p>
2154 * If a {@link UiAutomation} exists with different flags, the flags on that instance will be
2155 * changed, and then it will be returned.
2156 * </p>
Phil Weaver1dd87222016-01-26 17:15:15 -08002157 *
2158 * @param flags The flags to be passed to the UiAutomation, for example
2159 * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}.
2160 *
2161 * @return The UI automation instance.
2162 *
2163 * @see UiAutomation
2164 */
Phil Weaver35841682016-03-09 09:52:51 -08002165 public UiAutomation getUiAutomation(@UiAutomationFlags int flags) {
Phil Weaverd8e88832016-03-28 17:26:25 -07002166 boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed());
2167
Phil Weaver1dd87222016-01-26 17:15:15 -08002168 if (mUiAutomationConnection != null) {
Phil Weaverd8e88832016-03-28 17:26:25 -07002169 if (!mustCreateNewAutomation && (mUiAutomation.getFlags() == flags)) {
2170 return mUiAutomation;
2171 }
2172 if (mustCreateNewAutomation) {
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002173 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(),
2174 mUiAutomationConnection);
Phil Weaver1dd87222016-01-26 17:15:15 -08002175 } else {
Phil Weaverd8e88832016-03-28 17:26:25 -07002176 mUiAutomation.disconnect();
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002177 }
Phil Weaverd8e88832016-03-28 17:26:25 -07002178 mUiAutomation.connect(flags);
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002179 return mUiAutomation;
2180 }
2181 return null;
2182 }
2183
Jason Monk5be50f72017-03-10 10:57:34 -05002184 /**
2185 * Takes control of the execution of messages on the specified looper until
2186 * {@link TestLooperManager#release} is called.
2187 */
2188 public TestLooperManager acquireLooperManager(Looper looper) {
2189 checkInstrumenting("acquireLooperManager");
2190 return new TestLooperManager(looper);
2191 }
2192
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002193 private final class InstrumentationThread extends Thread {
2194 public InstrumentationThread(String name) {
2195 super(name);
2196 }
2197 public void run() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002198 try {
2199 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
2200 } catch (RuntimeException e) {
Phil Weaver1dd87222016-01-26 17:15:15 -08002201 Log.w(TAG, "Exception setting priority of instrumentation thread "
2202 + Process.myTid(), e);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002203 }
2204 if (mAutomaticPerformanceSnapshots) {
2205 startPerformanceSnapshot();
2206 }
2207 onStart();
2208 }
2209 }
Svetoslav Ganov80943d82013-01-02 10:25:37 -08002210
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002211 private static final class EmptyRunnable implements Runnable {
2212 public void run() {
2213 }
2214 }
2215
2216 private static final class SyncRunnable implements Runnable {
2217 private final Runnable mTarget;
2218 private boolean mComplete;
2219
2220 public SyncRunnable(Runnable target) {
2221 mTarget = target;
2222 }
2223
2224 public void run() {
2225 mTarget.run();
2226 synchronized (this) {
2227 mComplete = true;
2228 notifyAll();
2229 }
2230 }
2231
2232 public void waitForComplete() {
2233 synchronized (this) {
2234 while (!mComplete) {
2235 try {
2236 wait();
2237 } catch (InterruptedException e) {
2238 }
2239 }
2240 }
2241 }
2242 }
2243
2244 private static final class ActivityWaiter {
2245 public final Intent intent;
2246 public Activity activity;
2247
2248 public ActivityWaiter(Intent _intent) {
2249 intent = _intent;
2250 }
2251 }
2252
2253 private final class ActivityGoing implements MessageQueue.IdleHandler {
2254 private final ActivityWaiter mWaiter;
2255
2256 public ActivityGoing(ActivityWaiter waiter) {
2257 mWaiter = waiter;
2258 }
2259
2260 public final boolean queueIdle() {
2261 synchronized (mSync) {
2262 mWaitingActivities.remove(mWaiter);
2263 mSync.notifyAll();
2264 }
2265 return false;
2266 }
2267 }
2268
2269 private static final class Idler implements MessageQueue.IdleHandler {
2270 private final Runnable mCallback;
2271 private boolean mIdle;
2272
2273 public Idler(Runnable callback) {
2274 mCallback = callback;
2275 mIdle = false;
2276 }
2277
2278 public final boolean queueIdle() {
2279 if (mCallback != null) {
2280 mCallback.run();
2281 }
2282 synchronized (this) {
2283 mIdle = true;
2284 notifyAll();
2285 }
2286 return false;
2287 }
2288
2289 public void waitForIdle() {
2290 synchronized (this) {
2291 while (!mIdle) {
2292 try {
2293 wait();
2294 } catch (InterruptedException e) {
2295 }
2296 }
2297 }
2298 }
2299 }
2300}