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