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