1 /* 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 17 package android.app; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.compat.annotation.UnsupportedAppUsage; 23 import android.content.ActivityNotFoundException; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.content.pm.ActivityInfo; 29 import android.content.res.Configuration; 30 import android.hardware.input.InputManager; 31 import android.hardware.input.InputManagerGlobal; 32 import android.net.Uri; 33 import android.os.Build; 34 import android.os.Bundle; 35 import android.os.Debug; 36 import android.os.IBinder; 37 import android.os.Looper; 38 import android.os.MessageQueue; 39 import android.os.PerformanceCollector; 40 import android.os.PersistableBundle; 41 import android.os.Process; 42 import android.os.RemoteException; 43 import android.os.ServiceManager; 44 import android.os.SystemClock; 45 import android.os.TestLooperManager; 46 import android.os.UserHandle; 47 import android.os.UserManager; 48 import android.util.AndroidRuntimeException; 49 import android.util.Log; 50 import android.view.Display; 51 import android.view.IWindowManager; 52 import android.view.InputDevice; 53 import android.view.KeyCharacterMap; 54 import android.view.KeyEvent; 55 import android.view.MotionEvent; 56 import android.view.SurfaceControl; 57 import android.view.ViewConfiguration; 58 import android.view.Window; 59 import android.view.WindowManagerGlobal; 60 61 import com.android.internal.content.ReferrerIntent; 62 63 import java.io.File; 64 import java.lang.annotation.Retention; 65 import java.lang.annotation.RetentionPolicy; 66 import java.util.ArrayList; 67 import java.util.List; 68 import java.util.concurrent.TimeoutException; 69 70 /** 71 * Base class for implementing application instrumentation code. When running 72 * with instrumentation turned on, this class will be instantiated for you 73 * before any of the application code, allowing you to monitor all of the 74 * interaction the system has with the application. An Instrumentation 75 * implementation is described to the system through an AndroidManifest.xml's 76 * <instrumentation> tag. 77 */ 78 public class Instrumentation { 79 80 /** 81 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key 82 * identifies the class that is writing the report. This can be used to provide more structured 83 * logging or reporting capabilities in the IInstrumentationWatcher. 84 */ 85 public static final String REPORT_KEY_IDENTIFIER = "id"; 86 /** 87 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key 88 * identifies a string which can simply be printed to the output stream. Using these streams 89 * provides a "pretty printer" version of the status & final packets. Any bundles including 90 * this key should also include the complete set of raw key/value pairs, so that the 91 * instrumentation can also be launched, and results collected, by an automated system. 92 */ 93 public static final String REPORT_KEY_STREAMRESULT = "stream"; 94 95 private static final String TAG = "Instrumentation"; 96 97 private static final long CONNECT_TIMEOUT_MILLIS = 60_000; 98 99 private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 100 101 /** 102 * @hide 103 */ 104 @Retention(RetentionPolicy.SOURCE) 105 @IntDef({0, UiAutomation.FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES, 106 UiAutomation.FLAG_DONT_USE_ACCESSIBILITY}) 107 public @interface UiAutomationFlags {}; 108 109 110 private final Object mSync = new Object(); 111 private ActivityThread mThread = null; 112 private MessageQueue mMessageQueue = null; 113 private Context mInstrContext; 114 private Context mAppContext; 115 private ComponentName mComponent; 116 private Thread mRunner; 117 private List<ActivityWaiter> mWaitingActivities; 118 private List<ActivityMonitor> mActivityMonitors; 119 private IInstrumentationWatcher mWatcher; 120 private IUiAutomationConnection mUiAutomationConnection; 121 private boolean mAutomaticPerformanceSnapshots = false; 122 private PerformanceCollector mPerformanceCollector; 123 private Bundle mPerfMetrics = new Bundle(); 124 private UiAutomation mUiAutomation; 125 private final Object mAnimationCompleteLock = new Object(); 126 Instrumentation()127 public Instrumentation() { 128 } 129 130 /** 131 * Called for methods that shouldn't be called by standard apps and 132 * should only be used in instrumentation environments. This is not 133 * security feature as these classes will still be accessible through 134 * reflection, but it will serve as noticeable discouragement from 135 * doing such a thing. 136 */ checkInstrumenting(String method)137 private void checkInstrumenting(String method) { 138 // Check if we have an instrumentation context, as init should only get called by 139 // the system in startup processes that are being instrumented. 140 if (mInstrContext == null) { 141 throw new RuntimeException(method + 142 " cannot be called outside of instrumented processes"); 143 } 144 } 145 146 /** 147 * Returns if it is being called in an instrumentation environment. 148 * 149 * @hide 150 */ isInstrumenting()151 public boolean isInstrumenting() { 152 // Check if we have an instrumentation context, as init should only get called by 153 // the system in startup processes that are being instrumented. 154 if (mInstrContext == null) { 155 return false; 156 } 157 return true; 158 } 159 160 /** 161 * Called when the instrumentation is starting, before any application code 162 * has been loaded. Usually this will be implemented to simply call 163 * {@link #start} to begin the instrumentation thread, which will then 164 * continue execution in {@link #onStart}. 165 * 166 * <p>If you do not need your own thread -- that is you are writing your 167 * instrumentation to be completely asynchronous (returning to the event 168 * loop so that the application can run), you can simply begin your 169 * instrumentation here, for example call {@link Context#startActivity} to 170 * begin the appropriate first activity of the application. 171 * 172 * @param arguments Any additional arguments that were supplied when the 173 * instrumentation was started. 174 */ onCreate(Bundle arguments)175 public void onCreate(Bundle arguments) { 176 } 177 178 /** 179 * Create and start a new thread in which to run instrumentation. This new 180 * thread will call to {@link #onStart} where you can implement the 181 * instrumentation. 182 */ start()183 public void start() { 184 if (mRunner != null) { 185 throw new RuntimeException("Instrumentation already started"); 186 } 187 mRunner = new InstrumentationThread("Instr: " + getClass().getName()); 188 mRunner.start(); 189 } 190 191 /** 192 * Method where the instrumentation thread enters execution. This allows 193 * you to run your instrumentation code in a separate thread than the 194 * application, so that it can perform blocking operation such as 195 * {@link #sendKeySync} or {@link #startActivitySync}. 196 * 197 * <p>You will typically want to call finish() when this function is done, 198 * to end your instrumentation. 199 */ onStart()200 public void onStart() { 201 } 202 203 /** 204 * This is called whenever the system captures an unhandled exception that 205 * was thrown by the application. The default implementation simply 206 * returns false, allowing normal system handling of the exception to take 207 * place. 208 * 209 * @param obj The client object that generated the exception. May be an 210 * Application, Activity, BroadcastReceiver, Service, or null. 211 * @param e The exception that was thrown. 212 * 213 * @return To allow normal system exception process to occur, return false. 214 * If true is returned, the system will proceed as if the exception 215 * didn't happen. 216 */ onException(Object obj, Throwable e)217 public boolean onException(Object obj, Throwable e) { 218 return false; 219 } 220 221 /** 222 * Provide a status report about the application. 223 * 224 * @param resultCode Current success/failure of instrumentation. 225 * @param results Any results to send back to the code that started the instrumentation. 226 */ sendStatus(int resultCode, Bundle results)227 public void sendStatus(int resultCode, Bundle results) { 228 if (mWatcher != null) { 229 try { 230 mWatcher.instrumentationStatus(mComponent, resultCode, results); 231 } 232 catch (RemoteException e) { 233 mWatcher = null; 234 } 235 } 236 } 237 238 /** 239 * Report some results in the middle of instrumentation execution. Later results (including 240 * those provided by {@link #finish}) will be combined with {@link Bundle#putAll}. 241 */ addResults(Bundle results)242 public void addResults(Bundle results) { 243 IActivityManager am = ActivityManager.getService(); 244 try { 245 am.addInstrumentationResults(mThread.getApplicationThread(), results); 246 } catch (RemoteException ex) { 247 throw ex.rethrowFromSystemServer(); 248 } 249 } 250 251 /** 252 * Terminate instrumentation of the application. This will cause the 253 * application process to exit, removing this instrumentation from the next 254 * time the application is started. If multiple processes are currently running 255 * for this instrumentation, all of those processes will be killed. 256 * 257 * @param resultCode Overall success/failure of instrumentation. 258 * @param results Any results to send back to the code that started the 259 * instrumentation. 260 */ finish(int resultCode, Bundle results)261 public void finish(int resultCode, Bundle results) { 262 if (mAutomaticPerformanceSnapshots) { 263 endPerformanceSnapshot(); 264 } 265 if (mPerfMetrics != null) { 266 if (results == null) { 267 results = new Bundle(); 268 } 269 results.putAll(mPerfMetrics); 270 } 271 if ((mUiAutomation != null) && !mUiAutomation.isDestroyed()) { 272 mUiAutomation.disconnect(); 273 mUiAutomation = null; 274 } 275 mThread.finishInstrumentation(resultCode, results); 276 } 277 setAutomaticPerformanceSnapshots()278 public void setAutomaticPerformanceSnapshots() { 279 mAutomaticPerformanceSnapshots = true; 280 mPerformanceCollector = new PerformanceCollector(); 281 } 282 startPerformanceSnapshot()283 public void startPerformanceSnapshot() { 284 if (!isProfiling()) { 285 mPerformanceCollector.beginSnapshot(null); 286 } 287 } 288 endPerformanceSnapshot()289 public void endPerformanceSnapshot() { 290 if (!isProfiling()) { 291 mPerfMetrics = mPerformanceCollector.endSnapshot(); 292 } 293 } 294 295 /** 296 * Called when the instrumented application is stopping, after all of the 297 * normal application cleanup has occurred. 298 */ onDestroy()299 public void onDestroy() { 300 } 301 302 /** 303 * Return the Context of this instrumentation's package. Note that this is 304 * often different than the Context of the application being 305 * instrumentated, since the instrumentation code often lives is a 306 * different package than that of the application it is running against. 307 * See {@link #getTargetContext} to retrieve a Context for the target 308 * application. 309 * 310 * @return The instrumentation's package context. 311 * 312 * @see #getTargetContext 313 */ getContext()314 public Context getContext() { 315 return mInstrContext; 316 } 317 318 /** 319 * Returns complete component name of this instrumentation. 320 * 321 * @return Returns the complete component name for this instrumentation. 322 */ getComponentName()323 public ComponentName getComponentName() { 324 return mComponent; 325 } 326 327 /** 328 * Return a Context for the target application being instrumented. Note 329 * that this is often different than the Context of the instrumentation 330 * code, since the instrumentation code often lives is a different package 331 * than that of the application it is running against. See 332 * {@link #getContext} to retrieve a Context for the instrumentation code. 333 * 334 * @return A Context in the target application. 335 * 336 * @see #getContext 337 */ getTargetContext()338 public Context getTargetContext() { 339 return mAppContext; 340 } 341 342 /** 343 * Return the name of the process this instrumentation is running in. Note this should 344 * only be used for testing and debugging. If you are thinking about using this to, 345 * for example, conditionalize what is initialized in an Application class, it is strongly 346 * recommended to instead use lazy initialization (such as a getter for the state that 347 * only creates it when requested). This can greatly reduce the work your process does 348 * when created for secondary things, such as to receive a broadcast. 349 */ getProcessName()350 public String getProcessName() { 351 return mThread.getProcessName(); 352 } 353 354 /** 355 * Check whether this instrumentation was started with profiling enabled. 356 * 357 * @return Returns true if profiling was enabled when starting, else false. 358 */ isProfiling()359 public boolean isProfiling() { 360 return mThread.isProfiling(); 361 } 362 363 /** 364 * This method will start profiling if isProfiling() returns true. You should 365 * only call this method if you set the handleProfiling attribute in the 366 * manifest file for this Instrumentation to true. 367 */ startProfiling()368 public void startProfiling() { 369 if (mThread.isProfiling()) { 370 File file = new File(mThread.getProfileFilePath()); 371 file.getParentFile().mkdirs(); 372 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 373 } 374 } 375 376 /** 377 * Stops profiling if isProfiling() returns true. 378 */ stopProfiling()379 public void stopProfiling() { 380 if (mThread.isProfiling()) { 381 Debug.stopMethodTracing(); 382 } 383 } 384 385 /** 386 * Force the global system in or out of touch mode. This can be used if your 387 * instrumentation relies on the UI being in one more or the other when it starts. 388 * 389 * <p><b>Note:</b> Starting from Android {@link Build.VERSION_CODES#TIRAMISU}, this method 390 * will only take effect if the instrumentation was sourced from a process with 391 * {@code MODIFY_TOUCH_MODE_STATE} internal permission granted (shell already have it). 392 * 393 * @param inTouch Set to true to be in touch mode, false to be in focus mode. 394 */ setInTouchMode(boolean inTouch)395 public void setInTouchMode(boolean inTouch) { 396 try { 397 IWindowManager.Stub.asInterface( 398 ServiceManager.getService("window")).setInTouchModeOnAllDisplays(inTouch); 399 } catch (RemoteException e) { 400 // Shouldn't happen! 401 } 402 } 403 404 /** 405 * Resets the {@link #setInTouchMode touch mode} to the device default. 406 */ resetInTouchMode()407 public void resetInTouchMode() { 408 final boolean defaultInTouchMode = getContext().getResources().getBoolean( 409 com.android.internal.R.bool.config_defaultInTouchMode); 410 setInTouchMode(defaultInTouchMode); 411 } 412 413 /** 414 * Schedule a callback for when the application's main thread goes idle 415 * (has no more events to process). 416 * 417 * @param recipient Called the next time the thread's message queue is 418 * idle. 419 */ waitForIdle(Runnable recipient)420 public void waitForIdle(Runnable recipient) { 421 mMessageQueue.addIdleHandler(new Idler(recipient)); 422 mThread.getHandler().post(new EmptyRunnable()); 423 } 424 425 /** 426 * Synchronously wait for the application to be idle. Can not be called 427 * from the main application thread -- use {@link #start} to execute 428 * instrumentation in its own thread. 429 */ waitForIdleSync()430 public void waitForIdleSync() { 431 validateNotAppThread(); 432 Idler idler = new Idler(null); 433 mMessageQueue.addIdleHandler(idler); 434 mThread.getHandler().post(new EmptyRunnable()); 435 idler.waitForIdle(); 436 } 437 waitForEnterAnimationComplete(Activity activity)438 private void waitForEnterAnimationComplete(Activity activity) { 439 synchronized (mAnimationCompleteLock) { 440 long timeout = 5000; 441 try { 442 // We need to check that this specified Activity completed the animation, not just 443 // any Activity. If it was another Activity, then decrease the timeout by how long 444 // it's already waited and wait for the thread to wakeup again. 445 while (timeout > 0 && !activity.mEnterAnimationComplete) { 446 long startTime = System.currentTimeMillis(); 447 mAnimationCompleteLock.wait(timeout); 448 long totalTime = System.currentTimeMillis() - startTime; 449 timeout -= totalTime; 450 } 451 } catch (InterruptedException e) { 452 } 453 } 454 } 455 456 /** @hide */ onEnterAnimationComplete()457 public void onEnterAnimationComplete() { 458 synchronized (mAnimationCompleteLock) { 459 mAnimationCompleteLock.notifyAll(); 460 } 461 } 462 463 /** 464 * Execute a call on the application's main thread, blocking until it is 465 * complete. Useful for doing things that are not thread-safe, such as 466 * looking at or modifying the view hierarchy. 467 * 468 * @param runner The code to run on the main thread. 469 */ runOnMainSync(Runnable runner)470 public void runOnMainSync(Runnable runner) { 471 validateNotAppThread(); 472 SyncRunnable sr = new SyncRunnable(runner); 473 mThread.getHandler().post(sr); 474 sr.waitForComplete(); 475 } 476 477 /** 478 * Start a new activity and wait for it to begin running before returning. 479 * In addition to being synchronous, this method as some semantic 480 * differences from the standard {@link Context#startActivity} call: the 481 * activity component is resolved before talking with the activity manager 482 * (its class name is specified in the Intent that this method ultimately 483 * starts), and it does not allow you to start activities that run in a 484 * different process. In addition, if the given Intent resolves to 485 * multiple activities, instead of displaying a dialog for the user to 486 * select an activity, an exception will be thrown. 487 * 488 * <p>The function returns as soon as the activity goes idle following the 489 * call to its {@link Activity#onCreate}. Generally this means it has gone 490 * through the full initialization including {@link Activity#onResume} and 491 * drawn and displayed its initial window. 492 * 493 * @param intent Description of the activity to start. 494 * 495 * @see Context#startActivity 496 * @see #startActivitySync(Intent, Bundle) 497 */ startActivitySync(Intent intent)498 public Activity startActivitySync(Intent intent) { 499 return startActivitySync(intent, null /* options */); 500 } 501 502 /** 503 * Start a new activity and wait for it to begin running before returning. 504 * In addition to being synchronous, this method as some semantic 505 * differences from the standard {@link Context#startActivity} call: the 506 * activity component is resolved before talking with the activity manager 507 * (its class name is specified in the Intent that this method ultimately 508 * starts), and it does not allow you to start activities that run in a 509 * different process. In addition, if the given Intent resolves to 510 * multiple activities, instead of displaying a dialog for the user to 511 * select an activity, an exception will be thrown. 512 * 513 * <p>The function returns as soon as the activity goes idle following the 514 * call to its {@link Activity#onCreate}. Generally this means it has gone 515 * through the full initialization including {@link Activity#onResume} and 516 * drawn and displayed its initial window. 517 * 518 * @param intent Description of the activity to start. 519 * @param options Additional options for how the Activity should be started. 520 * May be null if there are no options. See {@link android.app.ActivityOptions} 521 * for how to build the Bundle supplied here; there are no supported definitions 522 * for building it manually. 523 * 524 * @see Context#startActivity(Intent, Bundle) 525 */ 526 @NonNull startActivitySync(@onNull Intent intent, @Nullable Bundle options)527 public Activity startActivitySync(@NonNull Intent intent, @Nullable Bundle options) { 528 validateNotAppThread(); 529 530 final Activity activity; 531 synchronized (mSync) { 532 intent = new Intent(intent); 533 534 ActivityInfo ai = intent.resolveActivityInfo( 535 getTargetContext().getPackageManager(), 0); 536 if (ai == null) { 537 throw new RuntimeException("Unable to resolve activity for: " + intent); 538 } 539 String myProc = mThread.getProcessName(); 540 if (!ai.processName.equals(myProc)) { 541 // todo: if this intent is ambiguous, look here to see if 542 // there is a single match that is in our package. 543 throw new RuntimeException("Intent in process " 544 + myProc + " resolved to different process " 545 + ai.processName + ": " + intent); 546 } 547 548 intent.setComponent(new ComponentName( 549 ai.applicationInfo.packageName, ai.name)); 550 final ActivityWaiter aw = new ActivityWaiter(intent); 551 552 if (mWaitingActivities == null) { 553 mWaitingActivities = new ArrayList(); 554 } 555 mWaitingActivities.add(aw); 556 557 getTargetContext().startActivity(intent, options); 558 559 do { 560 try { 561 mSync.wait(); 562 } catch (InterruptedException e) { 563 } 564 } while (mWaitingActivities.contains(aw)); 565 activity = aw.activity; 566 } 567 568 // Do not call this method within mSync, lest it could block the main thread. 569 waitForEnterAnimationComplete(activity); 570 571 // Apply an empty transaction to ensure SF has a chance to update before 572 // the Activity is ready (b/138263890). 573 try (SurfaceControl.Transaction t = new SurfaceControl.Transaction()) { 574 t.apply(true); 575 } 576 return activity; 577 } 578 579 /** 580 * Information about a particular kind of Intent that is being monitored. 581 * An instance of this class is added to the 582 * current instrumentation through {@link #addMonitor}; after being added, 583 * when a new activity is being started the monitor will be checked and, if 584 * matching, its hit count updated and (optionally) the call stopped and a 585 * canned result returned. 586 * 587 * <p>An ActivityMonitor can also be used to look for the creation of an 588 * activity, through the {@link #waitForActivity} method. This will return 589 * after a matching activity has been created with that activity object. 590 */ 591 public static class ActivityMonitor { 592 private final IntentFilter mWhich; 593 private final String mClass; 594 private final ActivityResult mResult; 595 private final boolean mBlock; 596 private final boolean mIgnoreMatchingSpecificIntents; 597 598 599 // This is protected by 'Instrumentation.this.mSync'. 600 /*package*/ int mHits = 0; 601 602 // This is protected by 'this'. 603 /*package*/ Activity mLastActivity = null; 604 605 /** 606 * Create a new ActivityMonitor that looks for a particular kind of 607 * intent to be started. 608 * 609 * @param which The set of intents this monitor is responsible for. 610 * @param result A canned result to return if the monitor is hit; can 611 * be null. 612 * @param block Controls whether the monitor should block the activity 613 * start (returning its canned result) or let the call 614 * proceed. 615 * 616 * @see Instrumentation#addMonitor 617 */ ActivityMonitor( IntentFilter which, ActivityResult result, boolean block)618 public ActivityMonitor( 619 IntentFilter which, ActivityResult result, boolean block) { 620 mWhich = which; 621 mClass = null; 622 mResult = result; 623 mBlock = block; 624 mIgnoreMatchingSpecificIntents = false; 625 } 626 627 /** 628 * Create a new ActivityMonitor that looks for a specific activity 629 * class to be started. 630 * 631 * @param cls The activity class this monitor is responsible for. 632 * @param result A canned result to return if the monitor is hit; can 633 * be null. 634 * @param block Controls whether the monitor should block the activity 635 * start (returning its canned result) or let the call 636 * proceed. 637 * 638 * @see Instrumentation#addMonitor 639 */ ActivityMonitor( String cls, ActivityResult result, boolean block)640 public ActivityMonitor( 641 String cls, ActivityResult result, boolean block) { 642 mWhich = null; 643 mClass = cls; 644 mResult = result; 645 mBlock = block; 646 mIgnoreMatchingSpecificIntents = false; 647 } 648 649 /** 650 * Create a new ActivityMonitor that can be used for intercepting any activity to be 651 * started. 652 * 653 * <p> When an activity is started, {@link #onStartActivity(Intent)} will be called on 654 * instances created using this constructor to see if it is a hit. 655 * 656 * @see #onStartActivity(Intent) 657 */ ActivityMonitor()658 public ActivityMonitor() { 659 mWhich = null; 660 mClass = null; 661 mResult = null; 662 mBlock = false; 663 mIgnoreMatchingSpecificIntents = true; 664 } 665 666 /** 667 * @return true if this monitor is used for intercepting any started activity by calling 668 * into {@link #onStartActivity(Intent)}, false if this monitor is only used 669 * for specific intents corresponding to the intent filter or activity class 670 * passed in the constructor. 671 */ ignoreMatchingSpecificIntents()672 final boolean ignoreMatchingSpecificIntents() { 673 return mIgnoreMatchingSpecificIntents; 674 } 675 676 /** 677 * Retrieve the filter associated with this ActivityMonitor. 678 */ getFilter()679 public final IntentFilter getFilter() { 680 return mWhich; 681 } 682 683 /** 684 * Retrieve the result associated with this ActivityMonitor, or null if 685 * none. 686 */ getResult()687 public final ActivityResult getResult() { 688 return mResult; 689 } 690 691 /** 692 * Check whether this monitor blocks activity starts (not allowing the 693 * actual activity to run) or allows them to execute normally. 694 */ isBlocking()695 public final boolean isBlocking() { 696 return mBlock; 697 } 698 699 /** 700 * Retrieve the number of times the monitor has been hit so far. 701 */ getHits()702 public final int getHits() { 703 return mHits; 704 } 705 706 /** 707 * Retrieve the most recent activity class that was seen by this 708 * monitor. 709 */ getLastActivity()710 public final Activity getLastActivity() { 711 return mLastActivity; 712 } 713 714 /** 715 * Block until an Activity is created that matches this monitor, 716 * returning the resulting activity. 717 * 718 * @return Activity 719 */ waitForActivity()720 public final Activity waitForActivity() { 721 synchronized (this) { 722 while (mLastActivity == null) { 723 try { 724 wait(); 725 } catch (InterruptedException e) { 726 } 727 } 728 Activity res = mLastActivity; 729 mLastActivity = null; 730 return res; 731 } 732 } 733 734 /** 735 * Block until an Activity is created that matches this monitor, 736 * returning the resulting activity or till the timeOut period expires. 737 * If the timeOut expires before the activity is started, return null. 738 * 739 * @param timeOut Time to wait in milliseconds before the activity is created. 740 * 741 * @return Activity 742 */ waitForActivityWithTimeout(long timeOut)743 public final Activity waitForActivityWithTimeout(long timeOut) { 744 synchronized (this) { 745 if (mLastActivity == null) { 746 try { 747 wait(timeOut); 748 } catch (InterruptedException e) { 749 } 750 } 751 if (mLastActivity == null) { 752 return null; 753 } else { 754 Activity res = mLastActivity; 755 mLastActivity = null; 756 return res; 757 } 758 } 759 } 760 761 /** 762 * This overload is used for notifying the {@link android.window.TaskFragmentOrganizer} 763 * implementation internally about started activities. 764 * 765 * @see #onStartActivity(Intent) 766 * @hide 767 */ onStartActivity(@onNull Context who, @NonNull Intent intent, @NonNull Bundle options)768 public ActivityResult onStartActivity(@NonNull Context who, @NonNull Intent intent, 769 @NonNull Bundle options) { 770 return onStartActivity(intent); 771 } 772 773 /** 774 * Used for intercepting any started activity. 775 * 776 * <p> A non-null return value here will be considered a hit for this monitor. 777 * By default this will return {@code null} and subclasses can override this to return 778 * a non-null value if the intent needs to be intercepted. 779 * 780 * <p> Whenever a new activity is started, this method will be called on instances created 781 * using {@link #ActivityMonitor()} to check if there is a match. In case 782 * of a match, the activity start will be blocked and the returned result will be used. 783 * 784 * @param intent The intent used for starting the activity. 785 * @return The {@link ActivityResult} that needs to be used in case of a match. 786 */ onStartActivity(Intent intent)787 public ActivityResult onStartActivity(Intent intent) { 788 return null; 789 } 790 791 /** 792 * This is called after starting an Activity and provides the result code that defined in 793 * {@link ActivityManager}, like {@link ActivityManager#START_SUCCESS}. 794 * 795 * @param result the result code that returns after starting an Activity. 796 * @param bOptions the bundle generated from {@link ActivityOptions} that originally 797 * being used to start the Activity. 798 * @hide 799 */ onStartActivityResult(int result, @NonNull Bundle bOptions)800 public void onStartActivityResult(int result, @NonNull Bundle bOptions) {} 801 match(Context who, Activity activity, Intent intent)802 final boolean match(Context who, 803 Activity activity, 804 Intent intent) { 805 if (mIgnoreMatchingSpecificIntents) { 806 return false; 807 } 808 synchronized (this) { 809 if (mWhich != null 810 && mWhich.match(who.getContentResolver(), intent, 811 true, "Instrumentation") < 0) { 812 return false; 813 } 814 if (mClass != null) { 815 String cls = null; 816 if (activity != null) { 817 cls = activity.getClass().getName(); 818 } else if (intent.getComponent() != null) { 819 cls = intent.getComponent().getClassName(); 820 } 821 if (cls == null || !mClass.equals(cls)) { 822 return false; 823 } 824 } 825 if (activity != null) { 826 mLastActivity = activity; 827 notifyAll(); 828 } 829 return true; 830 } 831 } 832 } 833 834 /** 835 * Add a new {@link ActivityMonitor} that will be checked whenever an 836 * activity is started. The monitor is added 837 * after any existing ones; the monitor will be hit only if none of the 838 * existing monitors can themselves handle the Intent. 839 * 840 * @param monitor The new ActivityMonitor to see. 841 * 842 * @see #addMonitor(IntentFilter, ActivityResult, boolean) 843 * @see #checkMonitorHit 844 */ addMonitor(ActivityMonitor monitor)845 public void addMonitor(ActivityMonitor monitor) { 846 synchronized (mSync) { 847 if (mActivityMonitors == null) { 848 mActivityMonitors = new ArrayList(); 849 } 850 mActivityMonitors.add(monitor); 851 } 852 } 853 854 /** 855 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that 856 * creates an intent filter matching {@link ActivityMonitor} for you and 857 * returns it. 858 * 859 * @param filter The set of intents this monitor is responsible for. 860 * @param result A canned result to return if the monitor is hit; can 861 * be null. 862 * @param block Controls whether the monitor should block the activity 863 * start (returning its canned result) or let the call 864 * proceed. 865 * 866 * @return The newly created and added activity monitor. 867 * 868 * @see #addMonitor(ActivityMonitor) 869 * @see #checkMonitorHit 870 */ addMonitor( IntentFilter filter, ActivityResult result, boolean block)871 public ActivityMonitor addMonitor( 872 IntentFilter filter, ActivityResult result, boolean block) { 873 ActivityMonitor am = new ActivityMonitor(filter, result, block); 874 addMonitor(am); 875 return am; 876 } 877 878 /** 879 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that 880 * creates a class matching {@link ActivityMonitor} for you and returns it. 881 * 882 * @param cls The activity class this monitor is responsible for. 883 * @param result A canned result to return if the monitor is hit; can 884 * be null. 885 * @param block Controls whether the monitor should block the activity 886 * start (returning its canned result) or let the call 887 * proceed. 888 * 889 * @return The newly created and added activity monitor. 890 * 891 * @see #addMonitor(ActivityMonitor) 892 * @see #checkMonitorHit 893 */ addMonitor( String cls, ActivityResult result, boolean block)894 public ActivityMonitor addMonitor( 895 String cls, ActivityResult result, boolean block) { 896 ActivityMonitor am = new ActivityMonitor(cls, result, block); 897 addMonitor(am); 898 return am; 899 } 900 901 /** 902 * Test whether an existing {@link ActivityMonitor} has been hit. If the 903 * monitor has been hit at least <var>minHits</var> times, then it will be 904 * removed from the activity monitor list and true returned. Otherwise it 905 * is left as-is and false is returned. 906 * 907 * @param monitor The ActivityMonitor to check. 908 * @param minHits The minimum number of hits required. 909 * 910 * @return True if the hit count has been reached, else false. 911 * 912 * @see #addMonitor 913 */ checkMonitorHit(ActivityMonitor monitor, int minHits)914 public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) { 915 waitForIdleSync(); 916 synchronized (mSync) { 917 if (monitor.getHits() < minHits) { 918 return false; 919 } 920 mActivityMonitors.remove(monitor); 921 } 922 return true; 923 } 924 925 /** 926 * Wait for an existing {@link ActivityMonitor} to be hit. Once the 927 * monitor has been hit, it is removed from the activity monitor list and 928 * the first created Activity object that matched it is returned. 929 * 930 * @param monitor The ActivityMonitor to wait for. 931 * 932 * @return The Activity object that matched the monitor. 933 */ waitForMonitor(ActivityMonitor monitor)934 public Activity waitForMonitor(ActivityMonitor monitor) { 935 Activity activity = monitor.waitForActivity(); 936 synchronized (mSync) { 937 mActivityMonitors.remove(monitor); 938 } 939 return activity; 940 } 941 942 /** 943 * Wait for an existing {@link ActivityMonitor} to be hit till the timeout 944 * expires. Once the monitor has been hit, it is removed from the activity 945 * monitor list and the first created Activity object that matched it is 946 * returned. If the timeout expires, a null object is returned. 947 * 948 * @param monitor The ActivityMonitor to wait for. 949 * @param timeOut The timeout value in milliseconds. 950 * 951 * @return The Activity object that matched the monitor. 952 */ waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut)953 public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) { 954 Activity activity = monitor.waitForActivityWithTimeout(timeOut); 955 synchronized (mSync) { 956 mActivityMonitors.remove(monitor); 957 } 958 return activity; 959 } 960 961 /** 962 * Remove an {@link ActivityMonitor} that was previously added with 963 * {@link #addMonitor}. 964 * 965 * @param monitor The monitor to remove. 966 * 967 * @see #addMonitor 968 */ removeMonitor(ActivityMonitor monitor)969 public void removeMonitor(ActivityMonitor monitor) { 970 synchronized (mSync) { 971 mActivityMonitors.remove(monitor); 972 } 973 } 974 975 /** 976 * Execute a particular menu item. 977 * 978 * @param targetActivity The activity in question. 979 * @param id The identifier associated with the menu item. 980 * @param flag Additional flags, if any. 981 * @return Whether the invocation was successful (for example, it could be 982 * false if item is disabled). 983 */ invokeMenuActionSync(Activity targetActivity, int id, int flag)984 public boolean invokeMenuActionSync(Activity targetActivity, 985 int id, int flag) { 986 class MenuRunnable implements Runnable { 987 private final Activity activity; 988 private final int identifier; 989 private final int flags; 990 boolean returnValue; 991 992 public MenuRunnable(Activity _activity, int _identifier, 993 int _flags) { 994 activity = _activity; 995 identifier = _identifier; 996 flags = _flags; 997 } 998 999 public void run() { 1000 Window win = activity.getWindow(); 1001 1002 returnValue = win.performPanelIdentifierAction( 1003 Window.FEATURE_OPTIONS_PANEL, 1004 identifier, 1005 flags); 1006 } 1007 1008 } 1009 MenuRunnable mr = new MenuRunnable(targetActivity, id, flag); 1010 runOnMainSync(mr); 1011 return mr.returnValue; 1012 } 1013 1014 /** 1015 * Show the context menu for the currently focused view and executes a 1016 * particular context menu item. 1017 * 1018 * @param targetActivity The activity in question. 1019 * @param id The identifier associated with the context menu item. 1020 * @param flag Additional flags, if any. 1021 * @return Whether the invocation was successful (for example, it could be 1022 * false if item is disabled). 1023 */ invokeContextMenuAction(Activity targetActivity, int id, int flag)1024 public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) { 1025 validateNotAppThread(); 1026 1027 // Bring up context menu for current focus. 1028 // It'd be nice to do this through code, but currently ListView depends on 1029 // long press to set metadata for its selected child 1030 1031 final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER); 1032 sendKeySync(downEvent); 1033 1034 // Need to wait for long press 1035 waitForIdleSync(); 1036 try { 1037 Thread.sleep(ViewConfiguration.getLongPressTimeout()); 1038 } catch (InterruptedException e) { 1039 Log.e(TAG, "Could not sleep for long press timeout", e); 1040 return false; 1041 } 1042 1043 final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER); 1044 sendKeySync(upEvent); 1045 1046 // Wait for context menu to appear 1047 waitForIdleSync(); 1048 1049 class ContextMenuRunnable implements Runnable { 1050 private final Activity activity; 1051 private final int identifier; 1052 private final int flags; 1053 boolean returnValue; 1054 1055 public ContextMenuRunnable(Activity _activity, int _identifier, 1056 int _flags) { 1057 activity = _activity; 1058 identifier = _identifier; 1059 flags = _flags; 1060 } 1061 1062 public void run() { 1063 Window win = activity.getWindow(); 1064 returnValue = win.performContextMenuIdentifierAction( 1065 identifier, 1066 flags); 1067 } 1068 1069 } 1070 1071 ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag); 1072 runOnMainSync(cmr); 1073 return cmr.returnValue; 1074 } 1075 1076 /** 1077 * Sends the key events that result in the given text being typed into the currently focused 1078 * window, and waits for it to be processed. 1079 * 1080 * @param text The text to be sent. 1081 * @see #sendKeySync(KeyEvent) 1082 */ sendStringSync(String text)1083 public void sendStringSync(String text) { 1084 if (text == null) { 1085 return; 1086 } 1087 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); 1088 1089 KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray()); 1090 1091 if (events != null) { 1092 for (int i = 0; i < events.length; i++) { 1093 // We have to change the time of an event before injecting it because 1094 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same 1095 // time stamp and the system rejects too old events. Hence, it is 1096 // possible for an event to become stale before it is injected if it 1097 // takes too long to inject the preceding ones. 1098 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0)); 1099 } 1100 } 1101 } 1102 1103 /** 1104 * Sends a key event to the currently focused window, and waits for it to be processed. 1105 * <p> 1106 * This method blocks until the recipient has finished handling the event. Note that the 1107 * recipient may <em>not</em> have completely finished reacting from the event when this method 1108 * returns. For example, it may still be in the process of updating its display or UI contents 1109 * upon reacting to the injected event. 1110 * 1111 * @param event The event to send to the current focus. 1112 */ sendKeySync(KeyEvent event)1113 public void sendKeySync(KeyEvent event) { 1114 validateNotAppThread(); 1115 1116 long downTime = event.getDownTime(); 1117 long eventTime = event.getEventTime(); 1118 int source = event.getSource(); 1119 if (source == InputDevice.SOURCE_UNKNOWN) { 1120 source = InputDevice.SOURCE_KEYBOARD; 1121 } 1122 if (eventTime == 0) { 1123 eventTime = SystemClock.uptimeMillis(); 1124 } 1125 if (downTime == 0) { 1126 downTime = eventTime; 1127 } 1128 KeyEvent newEvent = new KeyEvent(event); 1129 newEvent.setTime(downTime, eventTime); 1130 newEvent.setSource(source); 1131 newEvent.setFlags(event.getFlags() | KeyEvent.FLAG_FROM_SYSTEM); 1132 setDisplayIfNeeded(newEvent); 1133 1134 InputManagerGlobal.getInstance().injectInputEvent(newEvent, 1135 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); 1136 } 1137 setDisplayIfNeeded(KeyEvent event)1138 private void setDisplayIfNeeded(KeyEvent event) { 1139 if (!UserManager.isVisibleBackgroundUsersEnabled()) { 1140 return; 1141 } 1142 // In devices that support visible background users visible, the display id must be set to 1143 // reflect the display the user was started visible on, otherwise the event would be sent to 1144 // the main display (which would most likely fail the test). 1145 int eventDisplayId = event.getDisplayId(); 1146 if (eventDisplayId != Display.INVALID_DISPLAY) { 1147 if (VERBOSE) { 1148 Log.v(TAG, "setDisplayIfNeeded(" + event + "): not changing display id as it's " 1149 + "explicitly set to " + eventDisplayId); 1150 } 1151 return; 1152 } 1153 1154 UserManager userManager = mInstrContext.getSystemService(UserManager.class); 1155 int userDisplayId = userManager.getMainDisplayIdAssignedToUser(); 1156 if (VERBOSE) { 1157 Log.v(TAG, "setDisplayIfNeeded(" + event + "): eventDisplayId=" + eventDisplayId 1158 + ", user=" + mInstrContext.getUser() + ", userDisplayId=" + userDisplayId); 1159 } 1160 if (userDisplayId == Display.INVALID_DISPLAY) { 1161 Log.e(TAG, "setDisplayIfNeeded(" + event + "): UserManager returned INVALID_DISPLAY as " 1162 + "display assigned to user " + mInstrContext.getUser()); 1163 return; 1164 1165 } 1166 1167 event.setDisplayId(userDisplayId); 1168 } 1169 1170 /** 1171 * Sends up and down key events with the given key code to the currently focused window, and 1172 * waits for it to be processed. 1173 * 1174 * @param keyCode The key code for the events to send. 1175 * @see #sendKeySync(KeyEvent) 1176 */ sendKeyDownUpSync(int keyCode)1177 public void sendKeyDownUpSync(int keyCode) { 1178 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); 1179 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode)); 1180 } 1181 1182 /** 1183 * Sends up and down key events with the given key code to the currently focused window, and 1184 * waits for it to be processed. 1185 * <p> 1186 * Equivalent to {@link #sendKeyDownUpSync(int)}. 1187 * 1188 * @param keyCode The key code of the character to send. 1189 * @see #sendKeySync(KeyEvent) 1190 */ sendCharacterSync(int keyCode)1191 public void sendCharacterSync(int keyCode) { 1192 sendKeyDownUpSync(keyCode); 1193 } 1194 1195 /** 1196 * Dispatches a pointer event into a window owned by the instrumented application, and waits for 1197 * it to be processed. 1198 * <p> 1199 * If the motion event being injected is targeted at a window that is not owned by the 1200 * instrumented application, the input injection will fail. See {@link #getUiAutomation()} for 1201 * injecting events into all windows. 1202 * <p> 1203 * This method blocks until the recipient has finished handling the event. Note that the 1204 * recipient may <em>not</em> have completely finished reacting from the event when this method 1205 * returns. For example, it may still be in the process of updating its display or UI contents 1206 * upon reacting to the injected event. 1207 * 1208 * @param event A motion event describing the pointer action. (As noted in 1209 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use 1210 * {@link SystemClock#uptimeMillis()} as the timebase. 1211 */ sendPointerSync(MotionEvent event)1212 public void sendPointerSync(MotionEvent event) { 1213 validateNotAppThread(); 1214 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) { 1215 event.setSource(InputDevice.SOURCE_TOUCHSCREEN); 1216 } 1217 1218 syncInputTransactionsAndInjectEventIntoSelf(event); 1219 } 1220 syncInputTransactionsAndInjectEventIntoSelf(MotionEvent event)1221 private void syncInputTransactionsAndInjectEventIntoSelf(MotionEvent event) { 1222 final boolean syncBefore = event.getAction() == MotionEvent.ACTION_DOWN 1223 || event.isFromSource(InputDevice.SOURCE_MOUSE); 1224 final boolean syncAfter = event.getAction() == MotionEvent.ACTION_UP; 1225 1226 try { 1227 if (syncBefore) { 1228 WindowManagerGlobal.getWindowManagerService() 1229 .syncInputTransactions(true /*waitForAnimations*/); 1230 } 1231 1232 // Direct the injected event into windows owned by the instrumentation target. 1233 InputManagerGlobal.getInstance().injectInputEvent( 1234 event, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH, Process.myUid()); 1235 1236 if (syncAfter) { 1237 WindowManagerGlobal.getWindowManagerService() 1238 .syncInputTransactions(true /*waitForAnimations*/); 1239 } 1240 } catch (RemoteException e) { 1241 e.rethrowFromSystemServer(); 1242 } 1243 } 1244 1245 /** 1246 * Dispatches a trackball event into the currently focused window, and waits for it to be 1247 * processed. 1248 * <p> 1249 * This method blocks until the recipient has finished handling the event. Note that the 1250 * recipient may <em>not</em> have completely finished reacting from the event when this method 1251 * returns. For example, it may still be in the process of updating its display or UI contents 1252 * upon reacting to the injected event. 1253 * 1254 * @param event A motion event describing the trackball action. (As noted in 1255 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use 1256 * {@link SystemClock#uptimeMillis()} as the timebase. 1257 */ sendTrackballEventSync(MotionEvent event)1258 public void sendTrackballEventSync(MotionEvent event) { 1259 validateNotAppThread(); 1260 if (!event.isFromSource(InputDevice.SOURCE_CLASS_TRACKBALL)) { 1261 event.setSource(InputDevice.SOURCE_TRACKBALL); 1262 } 1263 InputManagerGlobal.getInstance().injectInputEvent(event, 1264 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); 1265 } 1266 1267 /** 1268 * Perform instantiation of the process's {@link Application} object. The 1269 * default implementation provides the normal system behavior. 1270 * 1271 * @param cl The ClassLoader with which to instantiate the object. 1272 * @param className The name of the class implementing the Application 1273 * object. 1274 * @param context The context to initialize the application with 1275 * 1276 * @return The newly instantiated Application object. 1277 */ newApplication(ClassLoader cl, String className, Context context)1278 public Application newApplication(ClassLoader cl, String className, Context context) 1279 throws InstantiationException, IllegalAccessException, 1280 ClassNotFoundException { 1281 Application app = getFactory(context.getPackageName()) 1282 .instantiateApplication(cl, className); 1283 app.attach(context); 1284 return app; 1285 } 1286 1287 /** 1288 * Perform instantiation of the process's {@link Application} object. The 1289 * default implementation provides the normal system behavior. 1290 * 1291 * @param clazz The class used to create an Application object from. 1292 * @param context The context to initialize the application with 1293 * 1294 * @return The newly instantiated Application object. 1295 */ newApplication(Class<?> clazz, Context context)1296 static public Application newApplication(Class<?> clazz, Context context) 1297 throws InstantiationException, IllegalAccessException, 1298 ClassNotFoundException { 1299 Application app = (Application)clazz.newInstance(); 1300 app.attach(context); 1301 return app; 1302 } 1303 1304 /** 1305 * Perform calling of the application's {@link Application#onCreate} 1306 * method. The default implementation simply calls through to that method. 1307 * 1308 * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}. 1309 * Often instrumentation tests start their test thread in onCreate(); you 1310 * need to be careful of races between these. (Well between it and 1311 * everything else, but let's start here.) 1312 * 1313 * @param app The application being created. 1314 */ callApplicationOnCreate(Application app)1315 public void callApplicationOnCreate(Application app) { 1316 app.onCreate(); 1317 } 1318 1319 /** 1320 * Perform instantiation of an {@link Activity} object. This method is intended for use with 1321 * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable 1322 * locally but will be missing some of the linkages necessary for use within the system. 1323 * 1324 * @param clazz The Class of the desired Activity 1325 * @param context The base context for the activity to use 1326 * @param token The token for this activity to communicate with 1327 * @param application The application object (if any) 1328 * @param intent The intent that started this Activity 1329 * @param info ActivityInfo from the manifest 1330 * @param title The title, typically retrieved from the ActivityInfo record 1331 * @param parent The parent Activity (if any) 1332 * @param id The embedded Id (if any) 1333 * @param lastNonConfigurationInstance Arbitrary object that will be 1334 * available via {@link Activity#getLastNonConfigurationInstance() 1335 * Activity.getLastNonConfigurationInstance()}. 1336 * @return Returns the instantiated activity 1337 * @throws InstantiationException 1338 * @throws IllegalAccessException 1339 */ newActivity(Class<?> clazz, Context context, IBinder token, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, Object lastNonConfigurationInstance)1340 public Activity newActivity(Class<?> clazz, Context context, 1341 IBinder token, Application application, Intent intent, ActivityInfo info, 1342 CharSequence title, Activity parent, String id, 1343 Object lastNonConfigurationInstance) throws InstantiationException, 1344 IllegalAccessException { 1345 Activity activity = (Activity)clazz.newInstance(); 1346 ActivityThread aThread = null; 1347 // Activity.attach expects a non-null Application Object. 1348 if (application == null) { 1349 application = new Application(); 1350 } 1351 activity.attach(context, aThread, this, token, 0 /* ident */, application, intent, 1352 info, title, parent, id, 1353 (Activity.NonConfigurationInstances)lastNonConfigurationInstance, 1354 new Configuration(), null /* referrer */, null /* voiceInteractor */, 1355 null /* window */, null /* activityCallback */, null /*assistToken*/, 1356 null /*shareableActivityToken*/); 1357 return activity; 1358 } 1359 1360 /** 1361 * Perform instantiation of the process's {@link Activity} object. The 1362 * default implementation provides the normal system behavior. 1363 * 1364 * @param cl The ClassLoader with which to instantiate the object. 1365 * @param className The name of the class implementing the Activity 1366 * object. 1367 * @param intent The Intent object that specified the activity class being 1368 * instantiated. 1369 * 1370 * @return The newly instantiated Activity object. 1371 */ newActivity(ClassLoader cl, String className, Intent intent)1372 public Activity newActivity(ClassLoader cl, String className, 1373 Intent intent) 1374 throws InstantiationException, IllegalAccessException, 1375 ClassNotFoundException { 1376 String pkg = intent != null && intent.getComponent() != null 1377 ? intent.getComponent().getPackageName() : null; 1378 return getFactory(pkg).instantiateActivity(cl, className, intent); 1379 } 1380 getFactory(String pkg)1381 private AppComponentFactory getFactory(String pkg) { 1382 if (pkg == null) { 1383 Log.e(TAG, "No pkg specified, disabling AppComponentFactory"); 1384 return AppComponentFactory.DEFAULT; 1385 } 1386 if (mThread == null) { 1387 Log.e(TAG, "Uninitialized ActivityThread, likely app-created Instrumentation," 1388 + " disabling AppComponentFactory", new Throwable()); 1389 return AppComponentFactory.DEFAULT; 1390 } 1391 LoadedApk apk = mThread.peekPackageInfo(pkg, true); 1392 // This is in the case of starting up "android". 1393 if (apk == null) apk = mThread.getSystemContext().mPackageInfo; 1394 return apk.getAppFactory(); 1395 } 1396 1397 /** 1398 * This should be called before {@link #checkStartActivityResult(int, Object)}, because 1399 * exceptions might be thrown while checking the results. 1400 */ notifyStartActivityResult(int result, @Nullable Bundle options)1401 private void notifyStartActivityResult(int result, @Nullable Bundle options) { 1402 if (mActivityMonitors == null) { 1403 return; 1404 } 1405 synchronized (mSync) { 1406 final int size = mActivityMonitors.size(); 1407 for (int i = 0; i < size; i++) { 1408 final ActivityMonitor am = mActivityMonitors.get(i); 1409 if (am.ignoreMatchingSpecificIntents()) { 1410 if (options == null) { 1411 options = ActivityOptions.makeBasic().toBundle(); 1412 } 1413 am.onStartActivityResult(result, options); 1414 } 1415 } 1416 } 1417 } 1418 prePerformCreate(Activity activity)1419 private void prePerformCreate(Activity activity) { 1420 if (mWaitingActivities != null) { 1421 synchronized (mSync) { 1422 final int N = mWaitingActivities.size(); 1423 for (int i=0; i<N; i++) { 1424 final ActivityWaiter aw = mWaitingActivities.get(i); 1425 final Intent intent = aw.intent; 1426 if (intent.filterEquals(activity.getIntent())) { 1427 aw.activity = activity; 1428 mMessageQueue.addIdleHandler(new ActivityGoing(aw)); 1429 } 1430 } 1431 } 1432 } 1433 } 1434 postPerformCreate(Activity activity)1435 private void postPerformCreate(Activity activity) { 1436 if (mActivityMonitors != null) { 1437 synchronized (mSync) { 1438 final int N = mActivityMonitors.size(); 1439 for (int i=0; i<N; i++) { 1440 final ActivityMonitor am = mActivityMonitors.get(i); 1441 am.match(activity, activity, activity.getIntent()); 1442 } 1443 } 1444 } 1445 } 1446 1447 /** 1448 * Perform calling of an activity's {@link Activity#onCreate} 1449 * method. The default implementation simply calls through to that method. 1450 * 1451 * @param activity The activity being created. 1452 * @param icicle The previously frozen state (or null) to pass through to onCreate(). 1453 */ callActivityOnCreate(Activity activity, Bundle icicle)1454 public void callActivityOnCreate(Activity activity, Bundle icicle) { 1455 prePerformCreate(activity); 1456 activity.performCreate(icicle); 1457 postPerformCreate(activity); 1458 } 1459 1460 /** 1461 * Perform calling of an activity's {@link Activity#onCreate} 1462 * method. The default implementation simply calls through to that method. 1463 * @param activity The activity being created. 1464 * @param icicle The previously frozen state (or null) to pass through to 1465 * @param persistentState The previously persisted state (or null) 1466 */ callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState)1467 public void callActivityOnCreate(Activity activity, Bundle icicle, 1468 PersistableBundle persistentState) { 1469 prePerformCreate(activity); 1470 activity.performCreate(icicle, persistentState); 1471 postPerformCreate(activity); 1472 } 1473 callActivityOnDestroy(Activity activity)1474 public void callActivityOnDestroy(Activity activity) { 1475 // TODO: the following block causes intermittent hangs when using startActivity 1476 // temporarily comment out until root cause is fixed (bug 2630683) 1477 // if (mWaitingActivities != null) { 1478 // synchronized (mSync) { 1479 // final int N = mWaitingActivities.size(); 1480 // for (int i=0; i<N; i++) { 1481 // final ActivityWaiter aw = mWaitingActivities.get(i); 1482 // final Intent intent = aw.intent; 1483 // if (intent.filterEquals(activity.getIntent())) { 1484 // aw.activity = activity; 1485 // mMessageQueue.addIdleHandler(new ActivityGoing(aw)); 1486 // } 1487 // } 1488 // } 1489 // } 1490 1491 activity.performDestroy(); 1492 } 1493 1494 /** 1495 * Perform calling of an activity's {@link Activity#onRestoreInstanceState} 1496 * method. The default implementation simply calls through to that method. 1497 * 1498 * @param activity The activity being restored. 1499 * @param savedInstanceState The previously saved state being restored. 1500 */ callActivityOnRestoreInstanceState(@onNull Activity activity, @NonNull Bundle savedInstanceState)1501 public void callActivityOnRestoreInstanceState(@NonNull Activity activity, 1502 @NonNull Bundle savedInstanceState) { 1503 activity.performRestoreInstanceState(savedInstanceState); 1504 } 1505 1506 /** 1507 * Perform calling of an activity's {@link Activity#onRestoreInstanceState} 1508 * method. The default implementation simply calls through to that method. 1509 * 1510 * @param activity The activity being restored. 1511 * @param savedInstanceState The previously saved state being restored (or null). 1512 * @param persistentState The previously persisted state (or null) 1513 */ callActivityOnRestoreInstanceState(@onNull Activity activity, @Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState)1514 public void callActivityOnRestoreInstanceState(@NonNull Activity activity, 1515 @Nullable Bundle savedInstanceState, 1516 @Nullable PersistableBundle persistentState) { 1517 activity.performRestoreInstanceState(savedInstanceState, persistentState); 1518 } 1519 1520 /** 1521 * Perform calling of an activity's {@link Activity#onPostCreate} method. 1522 * The default implementation simply calls through to that method. 1523 * 1524 * @param activity The activity being created. 1525 * @param savedInstanceState The previously saved state (or null) to pass through to 1526 * onPostCreate(). 1527 */ callActivityOnPostCreate(@onNull Activity activity, @Nullable Bundle savedInstanceState)1528 public void callActivityOnPostCreate(@NonNull Activity activity, 1529 @Nullable Bundle savedInstanceState) { 1530 activity.onPostCreate(savedInstanceState); 1531 } 1532 1533 /** 1534 * Perform calling of an activity's {@link Activity#onPostCreate} method. 1535 * The default implementation simply calls through to that method. 1536 * 1537 * @param activity The activity being created. 1538 * @param savedInstanceState The previously frozen state (or null) to pass through to 1539 * onPostCreate(). 1540 * @param persistentState The previously persisted state (or null) 1541 */ callActivityOnPostCreate(@onNull Activity activity, @Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState)1542 public void callActivityOnPostCreate(@NonNull Activity activity, 1543 @Nullable Bundle savedInstanceState, 1544 @Nullable PersistableBundle persistentState) { 1545 activity.onPostCreate(savedInstanceState, persistentState); 1546 } 1547 1548 /** 1549 * Perform calling of an activity's {@link Activity#onNewIntent} 1550 * method. The default implementation simply calls through to that method. 1551 * 1552 * @param activity The activity receiving a new Intent. 1553 * @param intent The new intent being received. 1554 */ callActivityOnNewIntent(Activity activity, Intent intent)1555 public void callActivityOnNewIntent(Activity activity, Intent intent) { 1556 activity.performNewIntent(intent); 1557 } 1558 1559 /** 1560 * @hide 1561 */ 1562 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) callActivityOnNewIntent(Activity activity, ReferrerIntent intent)1563 public void callActivityOnNewIntent(Activity activity, ReferrerIntent intent) { 1564 final String oldReferrer = activity.mReferrer; 1565 try { 1566 if (intent != null) { 1567 activity.mReferrer = intent.mReferrer; 1568 } 1569 callActivityOnNewIntent(activity, intent != null ? new Intent(intent) : null); 1570 } finally { 1571 activity.mReferrer = oldReferrer; 1572 } 1573 } 1574 1575 /** 1576 * Perform calling of an activity's {@link Activity#onStart} 1577 * method. The default implementation simply calls through to that method. 1578 * 1579 * @param activity The activity being started. 1580 */ callActivityOnStart(Activity activity)1581 public void callActivityOnStart(Activity activity) { 1582 activity.onStart(); 1583 } 1584 1585 /** 1586 * Perform calling of an activity's {@link Activity#onRestart} 1587 * method. The default implementation simply calls through to that method. 1588 * 1589 * @param activity The activity being restarted. 1590 */ callActivityOnRestart(Activity activity)1591 public void callActivityOnRestart(Activity activity) { 1592 activity.onRestart(); 1593 } 1594 1595 /** 1596 * Perform calling of an activity's {@link Activity#onResume} method. The 1597 * default implementation simply calls through to that method. 1598 * 1599 * @param activity The activity being resumed. 1600 */ callActivityOnResume(Activity activity)1601 public void callActivityOnResume(Activity activity) { 1602 activity.mResumed = true; 1603 activity.onResume(); 1604 1605 if (mActivityMonitors != null) { 1606 synchronized (mSync) { 1607 final int N = mActivityMonitors.size(); 1608 for (int i=0; i<N; i++) { 1609 final ActivityMonitor am = mActivityMonitors.get(i); 1610 am.match(activity, activity, activity.getIntent()); 1611 } 1612 } 1613 } 1614 } 1615 1616 /** 1617 * Perform calling of an activity's {@link Activity#onStop} 1618 * method. The default implementation simply calls through to that method. 1619 * 1620 * @param activity The activity being stopped. 1621 */ callActivityOnStop(Activity activity)1622 public void callActivityOnStop(Activity activity) { 1623 activity.onStop(); 1624 } 1625 1626 /** 1627 * Perform calling of an activity's {@link Activity#onSaveInstanceState} 1628 * method. The default implementation simply calls through to that method. 1629 * 1630 * @param activity The activity being saved. 1631 * @param outState The bundle to pass to the call. 1632 */ callActivityOnSaveInstanceState(@onNull Activity activity, @NonNull Bundle outState)1633 public void callActivityOnSaveInstanceState(@NonNull Activity activity, 1634 @NonNull Bundle outState) { 1635 activity.performSaveInstanceState(outState); 1636 } 1637 1638 /** 1639 * Perform calling of an activity's {@link Activity#onSaveInstanceState} 1640 * method. The default implementation simply calls through to that method. 1641 * @param activity The activity being saved. 1642 * @param outState The bundle to pass to the call. 1643 * @param outPersistentState The persistent bundle to pass to the call. 1644 */ callActivityOnSaveInstanceState(@onNull Activity activity, @NonNull Bundle outState, @NonNull PersistableBundle outPersistentState)1645 public void callActivityOnSaveInstanceState(@NonNull Activity activity, 1646 @NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) { 1647 activity.performSaveInstanceState(outState, outPersistentState); 1648 } 1649 1650 /** 1651 * Perform calling of an activity's {@link Activity#onPause} method. The 1652 * default implementation simply calls through to that method. 1653 * 1654 * @param activity The activity being paused. 1655 */ callActivityOnPause(Activity activity)1656 public void callActivityOnPause(Activity activity) { 1657 activity.performPause(); 1658 } 1659 1660 /** 1661 * Perform calling of an activity's {@link Activity#onUserLeaveHint} method. 1662 * The default implementation simply calls through to that method. 1663 * 1664 * @param activity The activity being notified that the user has navigated away 1665 */ callActivityOnUserLeaving(Activity activity)1666 public void callActivityOnUserLeaving(Activity activity) { 1667 activity.performUserLeaving(); 1668 } 1669 1670 /** 1671 * Perform calling of an activity's {@link Activity#onPictureInPictureRequested} method. 1672 * The default implementation simply calls through to that method. 1673 * 1674 * @param activity The activity being notified that picture-in-picture is being requested. 1675 */ callActivityOnPictureInPictureRequested(@onNull Activity activity)1676 public void callActivityOnPictureInPictureRequested(@NonNull Activity activity) { 1677 activity.onPictureInPictureRequested(); 1678 } 1679 1680 /* 1681 * Starts allocation counting. This triggers a gc and resets the counts. 1682 * 1683 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1684 */ 1685 @Deprecated startAllocCounting()1686 public void startAllocCounting() { 1687 // Before we start trigger a GC and reset the debug counts. Run the 1688 // finalizers and another GC before starting and stopping the alloc 1689 // counts. This will free up any objects that were just sitting around 1690 // waiting for their finalizers to be run. 1691 Runtime.getRuntime().gc(); 1692 Runtime.getRuntime().runFinalization(); 1693 Runtime.getRuntime().gc(); 1694 1695 Debug.resetAllCounts(); 1696 1697 // start the counts 1698 Debug.startAllocCounting(); 1699 } 1700 1701 /* 1702 * Stops allocation counting. 1703 * 1704 * @deprecated Accurate counting is a burden on the runtime and may be removed. 1705 */ 1706 @Deprecated stopAllocCounting()1707 public void stopAllocCounting() { 1708 Runtime.getRuntime().gc(); 1709 Runtime.getRuntime().runFinalization(); 1710 Runtime.getRuntime().gc(); 1711 Debug.stopAllocCounting(); 1712 } 1713 1714 /** 1715 * If Results already contains Key, it appends Value to the key's ArrayList 1716 * associated with the key. If the key doesn't already exist in results, it 1717 * adds the key/value pair to results. 1718 */ addValue(String key, int value, Bundle results)1719 private void addValue(String key, int value, Bundle results) { 1720 if (results.containsKey(key)) { 1721 List<Integer> list = results.getIntegerArrayList(key); 1722 if (list != null) { 1723 list.add(value); 1724 } 1725 } else { 1726 ArrayList<Integer> list = new ArrayList<Integer>(); 1727 list.add(value); 1728 results.putIntegerArrayList(key, list); 1729 } 1730 } 1731 1732 /** 1733 * Returns a bundle with the current results from the allocation counting. 1734 */ getAllocCounts()1735 public Bundle getAllocCounts() { 1736 Bundle results = new Bundle(); 1737 results.putLong("global_alloc_count", Debug.getGlobalAllocCount()); 1738 results.putLong("global_alloc_size", Debug.getGlobalAllocSize()); 1739 results.putLong("global_freed_count", Debug.getGlobalFreedCount()); 1740 results.putLong("global_freed_size", Debug.getGlobalFreedSize()); 1741 results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount()); 1742 return results; 1743 } 1744 1745 /** 1746 * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are 1747 * reported are the number of send and the number of received transactions. 1748 */ getBinderCounts()1749 public Bundle getBinderCounts() { 1750 Bundle results = new Bundle(); 1751 results.putLong("sent_transactions", Debug.getBinderSentTransactions()); 1752 results.putLong("received_transactions", Debug.getBinderReceivedTransactions()); 1753 return results; 1754 } 1755 1756 /** 1757 * Description of a Activity execution result to return to the original 1758 * activity. 1759 */ 1760 public static final class ActivityResult { 1761 /** 1762 * Create a new activity result. See {@link Activity#setResult} for 1763 * more information. 1764 * 1765 * @param resultCode The result code to propagate back to the 1766 * originating activity, often RESULT_CANCELED or RESULT_OK 1767 * @param resultData The data to propagate back to the originating 1768 * activity. 1769 */ ActivityResult(int resultCode, Intent resultData)1770 public ActivityResult(int resultCode, Intent resultData) { 1771 mResultCode = resultCode; 1772 mResultData = resultData; 1773 } 1774 1775 /** 1776 * Retrieve the result code contained in this result. 1777 */ getResultCode()1778 public int getResultCode() { 1779 return mResultCode; 1780 } 1781 1782 /** 1783 * Retrieve the data contained in this result. 1784 */ getResultData()1785 public Intent getResultData() { 1786 return mResultData; 1787 } 1788 1789 private final int mResultCode; 1790 private final Intent mResultData; 1791 } 1792 1793 /** 1794 * Execute a startActivity call made by the application. The default 1795 * implementation takes care of updating any active {@link ActivityMonitor} 1796 * objects and dispatches this call to the system activity manager; you can 1797 * override this to watch for the application to start an activity, and 1798 * modify what happens when it does. 1799 * 1800 * <p>This method returns an {@link ActivityResult} object, which you can 1801 * use when intercepting application calls to avoid performing the start 1802 * activity action but still return the result the application is 1803 * expecting. To do this, override this method to catch the call to start 1804 * activity so that it returns a new ActivityResult containing the results 1805 * you would like the application to see, and don't call up to the super 1806 * class. Note that an application is only expecting a result if 1807 * <var>requestCode</var> is >= 0. 1808 * 1809 * <p>This method throws {@link android.content.ActivityNotFoundException} 1810 * if there was no Activity found to run the given Intent. 1811 * 1812 * @param who The Context from which the activity is being started. 1813 * @param contextThread The main thread of the Context from which the activity 1814 * is being started. 1815 * @param token Internal token identifying to the system who is starting 1816 * the activity; may be null. 1817 * @param target Which activity is performing the start (and thus receiving 1818 * any result); may be null if this call is not being made 1819 * from an activity. 1820 * @param intent The actual Intent to start. 1821 * @param requestCode Identifier for this request's result; less than zero 1822 * if the caller is not expecting a result. 1823 * @param options Addition options. 1824 * 1825 * @return To force the return of a particular result, return an 1826 * ActivityResult object containing the desired data; otherwise 1827 * return null. The default implementation always returns null. 1828 * 1829 * @throws android.content.ActivityNotFoundException 1830 * 1831 * @see Activity#startActivity(Intent) 1832 * @see Activity#startActivityForResult(Intent, int) 1833 * 1834 * {@hide} 1835 */ 1836 @UnsupportedAppUsage execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options)1837 public ActivityResult execStartActivity( 1838 Context who, IBinder contextThread, IBinder token, Activity target, 1839 Intent intent, int requestCode, Bundle options) { 1840 IApplicationThread whoThread = (IApplicationThread) contextThread; 1841 Uri referrer = target != null ? target.onProvideReferrer() : null; 1842 if (referrer != null) { 1843 intent.putExtra(Intent.EXTRA_REFERRER, referrer); 1844 } 1845 if (mActivityMonitors != null) { 1846 synchronized (mSync) { 1847 final int N = mActivityMonitors.size(); 1848 for (int i=0; i<N; i++) { 1849 final ActivityMonitor am = mActivityMonitors.get(i); 1850 ActivityResult result = null; 1851 if (am.ignoreMatchingSpecificIntents()) { 1852 if (options == null) { 1853 options = ActivityOptions.makeBasic().toBundle(); 1854 } 1855 result = am.onStartActivity(who, intent, options); 1856 } 1857 if (result != null) { 1858 am.mHits++; 1859 return result; 1860 } else if (am.match(who, null, intent)) { 1861 am.mHits++; 1862 if (am.isBlocking()) { 1863 return requestCode >= 0 ? am.getResult() : null; 1864 } 1865 break; 1866 } 1867 } 1868 } 1869 } 1870 try { 1871 intent.migrateExtraStreamToClipData(who); 1872 intent.prepareToLeaveProcess(who); 1873 int result = ActivityTaskManager.getService().startActivity(whoThread, 1874 who.getOpPackageName(), who.getAttributionTag(), intent, 1875 intent.resolveTypeIfNeeded(who.getContentResolver()), token, 1876 target != null ? target.mEmbeddedID : null, requestCode, 0, null, options); 1877 notifyStartActivityResult(result, options); 1878 checkStartActivityResult(result, intent); 1879 } catch (RemoteException e) { 1880 throw new RuntimeException("Failure from system", e); 1881 } 1882 return null; 1883 } 1884 1885 /** 1886 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)}, 1887 * but accepts an array of activities to be started. Note that active 1888 * {@link ActivityMonitor} objects only match against the first activity in 1889 * the array. 1890 * 1891 * {@hide} 1892 */ 1893 @UnsupportedAppUsage execStartActivities(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options)1894 public void execStartActivities(Context who, IBinder contextThread, 1895 IBinder token, Activity target, Intent[] intents, Bundle options) { 1896 execStartActivitiesAsUser(who, contextThread, token, target, intents, options, 1897 who.getUserId()); 1898 } 1899 1900 /** 1901 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)}, 1902 * but accepts an array of activities to be started. Note that active 1903 * {@link ActivityMonitor} objects only match against the first activity in 1904 * the array. 1905 * 1906 * @return The corresponding flag {@link ActivityManager#START_CANCELED}, 1907 * {@link ActivityManager#START_SUCCESS} etc. indicating whether the launch was 1908 * successful. 1909 * 1910 * {@hide} 1911 */ 1912 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) execStartActivitiesAsUser(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options, int userId)1913 public int execStartActivitiesAsUser(Context who, IBinder contextThread, 1914 IBinder token, Activity target, Intent[] intents, Bundle options, 1915 int userId) { 1916 IApplicationThread whoThread = (IApplicationThread) contextThread; 1917 if (mActivityMonitors != null) { 1918 synchronized (mSync) { 1919 final int N = mActivityMonitors.size(); 1920 for (int i=0; i<N; i++) { 1921 final ActivityMonitor am = mActivityMonitors.get(i); 1922 ActivityResult result = null; 1923 if (am.ignoreMatchingSpecificIntents()) { 1924 if (options == null) { 1925 options = ActivityOptions.makeBasic().toBundle(); 1926 } 1927 result = am.onStartActivity(who, intents[0], options); 1928 } 1929 if (result != null) { 1930 am.mHits++; 1931 return ActivityManager.START_CANCELED; 1932 } else if (am.match(who, null, intents[0])) { 1933 am.mHits++; 1934 if (am.isBlocking()) { 1935 return ActivityManager.START_CANCELED; 1936 } 1937 break; 1938 } 1939 } 1940 } 1941 } 1942 try { 1943 String[] resolvedTypes = new String[intents.length]; 1944 for (int i=0; i<intents.length; i++) { 1945 intents[i].migrateExtraStreamToClipData(who); 1946 intents[i].prepareToLeaveProcess(who); 1947 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver()); 1948 } 1949 int result = ActivityTaskManager.getService().startActivities(whoThread, 1950 who.getOpPackageName(), who.getAttributionTag(), intents, resolvedTypes, 1951 token, options, userId); 1952 notifyStartActivityResult(result, options); 1953 checkStartActivityResult(result, intents[0]); 1954 return result; 1955 } catch (RemoteException e) { 1956 throw new RuntimeException("Failure from system", e); 1957 } 1958 } 1959 1960 /** 1961 * Like {@link #execStartActivity(android.content.Context, android.os.IBinder, 1962 * android.os.IBinder, String, android.content.Intent, int, android.os.Bundle)}, 1963 * but for calls from a {@link Fragment}. 1964 * 1965 * @param who The Context from which the activity is being started. 1966 * @param contextThread The main thread of the Context from which the activity 1967 * is being started. 1968 * @param token Internal token identifying to the system who is starting 1969 * the activity; may be null. 1970 * @param target Which element is performing the start (and thus receiving 1971 * any result). 1972 * @param intent The actual Intent to start. 1973 * @param requestCode Identifier for this request's result; less than zero 1974 * if the caller is not expecting a result. 1975 * 1976 * @return To force the return of a particular result, return an 1977 * ActivityResult object containing the desired data; otherwise 1978 * return null. The default implementation always returns null. 1979 * 1980 * @throws android.content.ActivityNotFoundException 1981 * 1982 * @see Activity#startActivity(Intent) 1983 * @see Activity#startActivityForResult(Intent, int) 1984 * 1985 * {@hide} 1986 */ 1987 @UnsupportedAppUsage execStartActivity( Context who, IBinder contextThread, IBinder token, String target, Intent intent, int requestCode, Bundle options)1988 public ActivityResult execStartActivity( 1989 Context who, IBinder contextThread, IBinder token, String target, 1990 Intent intent, int requestCode, Bundle options) { 1991 IApplicationThread whoThread = (IApplicationThread) contextThread; 1992 if (mActivityMonitors != null) { 1993 synchronized (mSync) { 1994 final int N = mActivityMonitors.size(); 1995 for (int i=0; i<N; i++) { 1996 final ActivityMonitor am = mActivityMonitors.get(i); 1997 ActivityResult result = null; 1998 if (am.ignoreMatchingSpecificIntents()) { 1999 if (options == null) { 2000 options = ActivityOptions.makeBasic().toBundle(); 2001 } 2002 result = am.onStartActivity(who, intent, options); 2003 } 2004 if (result != null) { 2005 am.mHits++; 2006 return result; 2007 } else if (am.match(who, null, intent)) { 2008 am.mHits++; 2009 if (am.isBlocking()) { 2010 return requestCode >= 0 ? am.getResult() : null; 2011 } 2012 break; 2013 } 2014 } 2015 } 2016 } 2017 try { 2018 intent.migrateExtraStreamToClipData(who); 2019 intent.prepareToLeaveProcess(who); 2020 int result = ActivityTaskManager.getService().startActivity(whoThread, 2021 who.getOpPackageName(), who.getAttributionTag(), intent, 2022 intent.resolveTypeIfNeeded(who.getContentResolver()), token, target, 2023 requestCode, 0, null, options); 2024 notifyStartActivityResult(result, options); 2025 checkStartActivityResult(result, intent); 2026 } catch (RemoteException e) { 2027 throw new RuntimeException("Failure from system", e); 2028 } 2029 return null; 2030 } 2031 2032 /** 2033 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int, Bundle)}, 2034 * but for starting as a particular user. 2035 * 2036 * @param who The Context from which the activity is being started. 2037 * @param contextThread The main thread of the Context from which the activity 2038 * is being started. 2039 * @param token Internal token identifying to the system who is starting 2040 * the activity; may be null. 2041 * @param target Which fragment is performing the start (and thus receiving 2042 * any result). 2043 * @param intent The actual Intent to start. 2044 * @param requestCode Identifier for this request's result; less than zero 2045 * if the caller is not expecting a result. 2046 * 2047 * @return To force the return of a particular result, return an 2048 * ActivityResult object containing the desired data; otherwise 2049 * return null. The default implementation always returns null. 2050 * 2051 * @throws android.content.ActivityNotFoundException 2052 * 2053 * @see Activity#startActivity(Intent) 2054 * @see Activity#startActivityForResult(Intent, int) 2055 * 2056 * {@hide} 2057 */ 2058 @UnsupportedAppUsage execStartActivity( Context who, IBinder contextThread, IBinder token, String resultWho, Intent intent, int requestCode, Bundle options, UserHandle user)2059 public ActivityResult execStartActivity( 2060 Context who, IBinder contextThread, IBinder token, String resultWho, 2061 Intent intent, int requestCode, Bundle options, UserHandle user) { 2062 IApplicationThread whoThread = (IApplicationThread) contextThread; 2063 if (mActivityMonitors != null) { 2064 synchronized (mSync) { 2065 final int N = mActivityMonitors.size(); 2066 for (int i=0; i<N; i++) { 2067 final ActivityMonitor am = mActivityMonitors.get(i); 2068 ActivityResult result = null; 2069 if (am.ignoreMatchingSpecificIntents()) { 2070 if (options == null) { 2071 options = ActivityOptions.makeBasic().toBundle(); 2072 } 2073 result = am.onStartActivity(who, intent, options); 2074 } 2075 if (result != null) { 2076 am.mHits++; 2077 return result; 2078 } else if (am.match(who, null, intent)) { 2079 am.mHits++; 2080 if (am.isBlocking()) { 2081 return requestCode >= 0 ? am.getResult() : null; 2082 } 2083 break; 2084 } 2085 } 2086 } 2087 } 2088 try { 2089 intent.migrateExtraStreamToClipData(who); 2090 intent.prepareToLeaveProcess(who); 2091 int result = ActivityTaskManager.getService().startActivityAsUser(whoThread, 2092 who.getOpPackageName(), who.getAttributionTag(), intent, 2093 intent.resolveTypeIfNeeded(who.getContentResolver()), token, resultWho, 2094 requestCode, 0, null, options, user.getIdentifier()); 2095 notifyStartActivityResult(result, options); 2096 checkStartActivityResult(result, intent); 2097 } catch (RemoteException e) { 2098 throw new RuntimeException("Failure from system", e); 2099 } 2100 return null; 2101 } 2102 2103 /** 2104 * Special version! 2105 * @hide 2106 */ 2107 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) execStartActivityAsCaller( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity, int userId)2108 public ActivityResult execStartActivityAsCaller( 2109 Context who, IBinder contextThread, IBinder token, Activity target, 2110 Intent intent, int requestCode, Bundle options, 2111 boolean ignoreTargetSecurity, int userId) { 2112 IApplicationThread whoThread = (IApplicationThread) contextThread; 2113 if (mActivityMonitors != null) { 2114 synchronized (mSync) { 2115 final int N = mActivityMonitors.size(); 2116 for (int i=0; i<N; i++) { 2117 final ActivityMonitor am = mActivityMonitors.get(i); 2118 ActivityResult result = null; 2119 if (am.ignoreMatchingSpecificIntents()) { 2120 if (options == null) { 2121 options = ActivityOptions.makeBasic().toBundle(); 2122 } 2123 result = am.onStartActivity(who, intent, options); 2124 } 2125 if (result != null) { 2126 am.mHits++; 2127 return result; 2128 } else if (am.match(who, null, intent)) { 2129 am.mHits++; 2130 if (am.isBlocking()) { 2131 return requestCode >= 0 ? am.getResult() : null; 2132 } 2133 break; 2134 } 2135 } 2136 } 2137 } 2138 try { 2139 intent.migrateExtraStreamToClipData(who); 2140 intent.prepareToLeaveProcess(who); 2141 int result = ActivityTaskManager.getService() 2142 .startActivityAsCaller(whoThread, who.getOpPackageName(), intent, 2143 intent.resolveTypeIfNeeded(who.getContentResolver()), 2144 token, target != null ? target.mEmbeddedID : null, 2145 requestCode, 0, null, options, 2146 ignoreTargetSecurity, userId); 2147 notifyStartActivityResult(result, options); 2148 checkStartActivityResult(result, intent); 2149 } catch (RemoteException e) { 2150 throw new RuntimeException("Failure from system", e); 2151 } 2152 return null; 2153 } 2154 2155 /** 2156 * Special version! 2157 * @hide 2158 */ 2159 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) execStartActivityFromAppTask( Context who, IBinder contextThread, IAppTask appTask, Intent intent, Bundle options)2160 public void execStartActivityFromAppTask( 2161 Context who, IBinder contextThread, IAppTask appTask, 2162 Intent intent, Bundle options) { 2163 IApplicationThread whoThread = (IApplicationThread) contextThread; 2164 if (mActivityMonitors != null) { 2165 synchronized (mSync) { 2166 final int N = mActivityMonitors.size(); 2167 for (int i=0; i<N; i++) { 2168 final ActivityMonitor am = mActivityMonitors.get(i); 2169 ActivityResult result = null; 2170 if (am.ignoreMatchingSpecificIntents()) { 2171 if (options == null) { 2172 options = ActivityOptions.makeBasic().toBundle(); 2173 } 2174 result = am.onStartActivity(who, intent, options); 2175 } 2176 if (result != null) { 2177 am.mHits++; 2178 return; 2179 } else if (am.match(who, null, intent)) { 2180 am.mHits++; 2181 if (am.isBlocking()) { 2182 return; 2183 } 2184 break; 2185 } 2186 } 2187 } 2188 } 2189 try { 2190 intent.migrateExtraStreamToClipData(who); 2191 intent.prepareToLeaveProcess(who); 2192 int result = appTask.startActivity(whoThread.asBinder(), who.getOpPackageName(), 2193 who.getAttributionTag(), intent, 2194 intent.resolveTypeIfNeeded(who.getContentResolver()), options); 2195 notifyStartActivityResult(result, options); 2196 checkStartActivityResult(result, intent); 2197 } catch (RemoteException e) { 2198 throw new RuntimeException("Failure from system", e); 2199 } 2200 return; 2201 } 2202 init(ActivityThread thread, Context instrContext, Context appContext, ComponentName component, IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection)2203 /*package*/ final void init(ActivityThread thread, 2204 Context instrContext, Context appContext, ComponentName component, 2205 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) { 2206 mThread = thread; 2207 mMessageQueue = mThread.getLooper().myQueue(); 2208 mInstrContext = instrContext; 2209 mAppContext = appContext; 2210 mComponent = component; 2211 mWatcher = watcher; 2212 mUiAutomationConnection = uiAutomationConnection; 2213 } 2214 2215 /** 2216 * Only sets the ActivityThread up, keeps everything else null because app is not being 2217 * instrumented. 2218 */ basicInit(ActivityThread thread)2219 final void basicInit(ActivityThread thread) { 2220 mThread = thread; 2221 } 2222 2223 /** @hide */ 2224 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) checkStartActivityResult(int res, Object intent)2225 public static void checkStartActivityResult(int res, Object intent) { 2226 if (!ActivityManager.isStartResultFatalError(res)) { 2227 return; 2228 } 2229 2230 switch (res) { 2231 case ActivityManager.START_INTENT_NOT_RESOLVED: 2232 case ActivityManager.START_CLASS_NOT_FOUND: 2233 if (intent instanceof Intent && ((Intent)intent).getComponent() != null) 2234 throw new ActivityNotFoundException( 2235 "Unable to find explicit activity class " 2236 + ((Intent)intent).getComponent().toShortString() 2237 + "; have you declared this activity in your AndroidManifest.xml" 2238 + ", or does your intent not match its declared <intent-filter>?"); 2239 throw new ActivityNotFoundException( 2240 "No Activity found to handle " + intent); 2241 case ActivityManager.START_PERMISSION_DENIED: 2242 throw new SecurityException("Not allowed to start activity " 2243 + intent); 2244 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: 2245 throw new AndroidRuntimeException( 2246 "FORWARD_RESULT_FLAG used while also requesting a result"); 2247 case ActivityManager.START_NOT_ACTIVITY: 2248 throw new IllegalArgumentException( 2249 "PendingIntent is not an activity"); 2250 case ActivityManager.START_NOT_VOICE_COMPATIBLE: 2251 throw new SecurityException( 2252 "Starting under voice control not allowed for: " + intent); 2253 case ActivityManager.START_VOICE_NOT_ACTIVE_SESSION: 2254 throw new IllegalStateException( 2255 "Session calling startVoiceActivity does not match active session"); 2256 case ActivityManager.START_VOICE_HIDDEN_SESSION: 2257 throw new IllegalStateException( 2258 "Cannot start voice activity on a hidden session"); 2259 case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION: 2260 throw new IllegalStateException( 2261 "Session calling startAssistantActivity does not match active session"); 2262 case ActivityManager.START_ASSISTANT_HIDDEN_SESSION: 2263 throw new IllegalStateException( 2264 "Cannot start assistant activity on a hidden session"); 2265 case ActivityManager.START_CANCELED: 2266 throw new AndroidRuntimeException("Activity could not be started for " 2267 + intent); 2268 default: 2269 throw new AndroidRuntimeException("Unknown error code " 2270 + res + " when starting " + intent); 2271 } 2272 } 2273 validateNotAppThread()2274 private final void validateNotAppThread() { 2275 if (Looper.myLooper() == Looper.getMainLooper()) { 2276 throw new RuntimeException( 2277 "This method can not be called from the main application thread"); 2278 } 2279 } 2280 2281 /** 2282 * Gets the {@link UiAutomation} instance with no flags set. 2283 * <p> 2284 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation} 2285 * work across application boundaries while the APIs exposed by the instrumentation 2286 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will 2287 * not allow you to inject the event in an app different from the instrumentation 2288 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)} 2289 * will work regardless of the current application. 2290 * </p> 2291 * <p> 2292 * A typical test case should be using either the {@link UiAutomation} or 2293 * {@link Instrumentation} APIs. Using both APIs at the same time is not 2294 * a mistake by itself but a client has to be aware of the APIs limitations. 2295 * </p> 2296 * <p> 2297 * Equivalent to {@code getUiAutomation(0)}. If a {@link UiAutomation} exists with different 2298 * flags, the flags on that instance will be changed, and then it will be returned. 2299 * </p> 2300 * <p> 2301 * Compatibility mode: This method is infallible for apps targeted for 2302 * {@link Build.VERSION_CODES#R} and earlier versions; for apps targeted for later versions, it 2303 * will return null if {@link UiAutomation} fails to connect. The caller can check the return 2304 * value and retry on error. 2305 * </p> 2306 * 2307 * @return The UI automation instance. 2308 * 2309 * @see UiAutomation 2310 */ getUiAutomation()2311 public UiAutomation getUiAutomation() { 2312 return getUiAutomation(0); 2313 } 2314 2315 /** 2316 * Gets the {@link UiAutomation} instance with flags set. 2317 * <p> 2318 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation} 2319 * work across application boundaries while the APIs exposed by the instrumentation 2320 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will 2321 * not allow you to inject the event in an app different from the instrumentation 2322 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)} 2323 * will work regardless of the current application. 2324 * </p> 2325 * <p> 2326 * A typical test case should be using either the {@link UiAutomation} or 2327 * {@link Instrumentation} APIs. Using both APIs at the same time is not 2328 * a mistake by itself but a client has to be aware of the APIs limitations. 2329 * </p> 2330 * <p> 2331 * If a {@link UiAutomation} exists with different flags, the flags on that instance will be 2332 * changed, and then it will be returned. 2333 * </p> 2334 * <p> 2335 * Compatibility mode: This method is infallible for apps targeted for 2336 * {@link Build.VERSION_CODES#R} and earlier versions; for apps targeted for later versions, it 2337 * will return null if {@link UiAutomation} fails to connect. The caller can check the return 2338 * value and retry on error. 2339 * </p> 2340 * 2341 * @param flags The flags to be passed to the UiAutomation, for example 2342 * {@link UiAutomation#FLAG_DONT_SUPPRESS_ACCESSIBILITY_SERVICES}, 2343 * {@link UiAutomation#FLAG_DONT_USE_ACCESSIBILITY}. 2344 * 2345 * @return The UI automation instance. 2346 * 2347 * @see UiAutomation 2348 */ getUiAutomation(@iAutomationFlags int flags)2349 public UiAutomation getUiAutomation(@UiAutomationFlags int flags) { 2350 boolean mustCreateNewAutomation = (mUiAutomation == null) || (mUiAutomation.isDestroyed()); 2351 2352 if (mUiAutomationConnection != null) { 2353 if (!mustCreateNewAutomation && (mUiAutomation.getFlags() == flags)) { 2354 return mUiAutomation; 2355 } 2356 if (mustCreateNewAutomation) { 2357 mUiAutomation = new UiAutomation(getTargetContext(), mUiAutomationConnection); 2358 } else { 2359 mUiAutomation.disconnect(); 2360 } 2361 if (getTargetContext().getApplicationInfo().targetSdkVersion <= Build.VERSION_CODES.R) { 2362 mUiAutomation.connect(flags); 2363 return mUiAutomation; 2364 } 2365 final long startUptime = SystemClock.uptimeMillis(); 2366 try { 2367 mUiAutomation.connectWithTimeout(flags, CONNECT_TIMEOUT_MILLIS); 2368 return mUiAutomation; 2369 } catch (TimeoutException e) { 2370 final long waited = SystemClock.uptimeMillis() - startUptime; 2371 Log.e(TAG, "Unable to connect to UiAutomation. Waited for " + waited + " ms", e); 2372 mUiAutomation.destroy(); 2373 mUiAutomation = null; 2374 } 2375 } 2376 return null; 2377 } 2378 2379 /** 2380 * Takes control of the execution of messages on the specified looper until 2381 * {@link TestLooperManager#release} is called. 2382 */ acquireLooperManager(Looper looper)2383 public TestLooperManager acquireLooperManager(Looper looper) { 2384 checkInstrumenting("acquireLooperManager"); 2385 return new TestLooperManager(looper); 2386 } 2387 2388 private final class InstrumentationThread extends Thread { InstrumentationThread(String name)2389 public InstrumentationThread(String name) { 2390 super(name); 2391 } run()2392 public void run() { 2393 try { 2394 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 2395 } catch (RuntimeException e) { 2396 Log.w(TAG, "Exception setting priority of instrumentation thread " 2397 + Process.myTid(), e); 2398 } 2399 if (mAutomaticPerformanceSnapshots) { 2400 startPerformanceSnapshot(); 2401 } 2402 onStart(); 2403 } 2404 } 2405 2406 private static final class EmptyRunnable implements Runnable { run()2407 public void run() { 2408 } 2409 } 2410 2411 private static final class SyncRunnable implements Runnable { 2412 private final Runnable mTarget; 2413 private boolean mComplete; 2414 SyncRunnable(Runnable target)2415 public SyncRunnable(Runnable target) { 2416 mTarget = target; 2417 } 2418 run()2419 public void run() { 2420 mTarget.run(); 2421 synchronized (this) { 2422 mComplete = true; 2423 notifyAll(); 2424 } 2425 } 2426 waitForComplete()2427 public void waitForComplete() { 2428 synchronized (this) { 2429 while (!mComplete) { 2430 try { 2431 wait(); 2432 } catch (InterruptedException e) { 2433 } 2434 } 2435 } 2436 } 2437 } 2438 2439 private static final class ActivityWaiter { 2440 public final Intent intent; 2441 public Activity activity; 2442 ActivityWaiter(Intent _intent)2443 public ActivityWaiter(Intent _intent) { 2444 intent = _intent; 2445 } 2446 } 2447 2448 private final class ActivityGoing implements MessageQueue.IdleHandler { 2449 private final ActivityWaiter mWaiter; 2450 ActivityGoing(ActivityWaiter waiter)2451 public ActivityGoing(ActivityWaiter waiter) { 2452 mWaiter = waiter; 2453 } 2454 queueIdle()2455 public final boolean queueIdle() { 2456 synchronized (mSync) { 2457 mWaitingActivities.remove(mWaiter); 2458 mSync.notifyAll(); 2459 } 2460 return false; 2461 } 2462 } 2463 2464 private static final class Idler implements MessageQueue.IdleHandler { 2465 private final Runnable mCallback; 2466 private boolean mIdle; 2467 Idler(Runnable callback)2468 public Idler(Runnable callback) { 2469 mCallback = callback; 2470 mIdle = false; 2471 } 2472 queueIdle()2473 public final boolean queueIdle() { 2474 if (mCallback != null) { 2475 mCallback.run(); 2476 } 2477 synchronized (this) { 2478 mIdle = true; 2479 notifyAll(); 2480 } 2481 return false; 2482 } 2483 waitForIdle()2484 public void waitForIdle() { 2485 synchronized (this) { 2486 while (!mIdle) { 2487 try { 2488 wait(); 2489 } catch (InterruptedException e) { 2490 } 2491 } 2492 } 2493 } 2494 } 2495 } 2496