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