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