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.content.ActivityNotFoundException; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.content.pm.ActivityInfo; 25 import android.content.res.Configuration; 26 import android.hardware.input.InputManager; 27 import android.os.Bundle; 28 import android.os.Debug; 29 import android.os.IBinder; 30 import android.os.Looper; 31 import android.os.MessageQueue; 32 import android.os.PerformanceCollector; 33 import android.os.Process; 34 import android.os.RemoteException; 35 import android.os.ServiceManager; 36 import android.os.SystemClock; 37 import android.os.UserHandle; 38 import android.util.AndroidRuntimeException; 39 import android.util.Log; 40 import android.view.IWindowManager; 41 import android.view.InputDevice; 42 import android.view.KeyCharacterMap; 43 import android.view.KeyEvent; 44 import android.view.MotionEvent; 45 import android.view.ViewConfiguration; 46 import android.view.Window; 47 48 import java.io.File; 49 import java.util.ArrayList; 50 import java.util.List; 51 52 /** 53 * Base class for implementing application instrumentation code. When running 54 * with instrumentation turned on, this class will be instantiated for you 55 * before any of the application code, allowing you to monitor all of the 56 * interaction the system has with the application. An Instrumentation 57 * implementation is described to the system through an AndroidManifest.xml's 58 * <instrumentation> tag. 59 */ 60 public class Instrumentation { 61 62 /** 63 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key 64 * identifies the class that is writing the report. This can be used to provide more structured 65 * logging or reporting capabilities in the IInstrumentationWatcher. 66 */ 67 public static final String REPORT_KEY_IDENTIFIER = "id"; 68 /** 69 * If included in the status or final bundle sent to an IInstrumentationWatcher, this key 70 * identifies a string which can simply be printed to the output stream. Using these streams 71 * provides a "pretty printer" version of the status & final packets. Any bundles including 72 * this key should also include the complete set of raw key/value pairs, so that the 73 * instrumentation can also be launched, and results collected, by an automated system. 74 */ 75 public static final String REPORT_KEY_STREAMRESULT = "stream"; 76 77 private static final String TAG = "Instrumentation"; 78 79 private final Object mSync = new Object(); 80 private ActivityThread mThread = null; 81 private MessageQueue mMessageQueue = null; 82 private Context mInstrContext; 83 private Context mAppContext; 84 private ComponentName mComponent; 85 private Thread mRunner; 86 private List<ActivityWaiter> mWaitingActivities; 87 private List<ActivityMonitor> mActivityMonitors; 88 private IInstrumentationWatcher mWatcher; 89 private IUiAutomationConnection mUiAutomationConnection; 90 private boolean mAutomaticPerformanceSnapshots = false; 91 private PerformanceCollector mPerformanceCollector; 92 private Bundle mPerfMetrics = new Bundle(); 93 private UiAutomation mUiAutomation; 94 95 public Instrumentation() { 96 } 97 98 /** 99 * Called when the instrumentation is starting, before any application code 100 * has been loaded. Usually this will be implemented to simply call 101 * {@link #start} to begin the instrumentation thread, which will then 102 * continue execution in {@link #onStart}. 103 * 104 * <p>If you do not need your own thread -- that is you are writing your 105 * instrumentation to be completely asynchronous (returning to the event 106 * loop so that the application can run), you can simply begin your 107 * instrumentation here, for example call {@link Context#startActivity} to 108 * begin the appropriate first activity of the application. 109 * 110 * @param arguments Any additional arguments that were supplied when the 111 * instrumentation was started. 112 */ 113 public void onCreate(Bundle arguments) { 114 } 115 116 /** 117 * Create and start a new thread in which to run instrumentation. This new 118 * thread will call to {@link #onStart} where you can implement the 119 * instrumentation. 120 */ 121 public void start() { 122 if (mRunner != null) { 123 throw new RuntimeException("Instrumentation already started"); 124 } 125 mRunner = new InstrumentationThread("Instr: " + getClass().getName()); 126 mRunner.start(); 127 } 128 129 /** 130 * Method where the instrumentation thread enters execution. This allows 131 * you to run your instrumentation code in a separate thread than the 132 * application, so that it can perform blocking operation such as 133 * {@link #sendKeySync} or {@link #startActivitySync}. 134 * 135 * <p>You will typically want to call finish() when this function is done, 136 * to end your instrumentation. 137 */ 138 public void onStart() { 139 } 140 141 /** 142 * This is called whenever the system captures an unhandled exception that 143 * was thrown by the application. The default implementation simply 144 * returns false, allowing normal system handling of the exception to take 145 * place. 146 * 147 * @param obj The client object that generated the exception. May be an 148 * Application, Activity, BroadcastReceiver, Service, or null. 149 * @param e The exception that was thrown. 150 * 151 * @return To allow normal system exception process to occur, return false. 152 * If true is returned, the system will proceed as if the exception 153 * didn't happen. 154 */ 155 public boolean onException(Object obj, Throwable e) { 156 return false; 157 } 158 159 /** 160 * Provide a status report about the application. 161 * 162 * @param resultCode Current success/failure of instrumentation. 163 * @param results Any results to send back to the code that started the instrumentation. 164 */ 165 public void sendStatus(int resultCode, Bundle results) { 166 if (mWatcher != null) { 167 try { 168 mWatcher.instrumentationStatus(mComponent, resultCode, results); 169 } 170 catch (RemoteException e) { 171 mWatcher = null; 172 } 173 } 174 } 175 176 /** 177 * Terminate instrumentation of the application. This will cause the 178 * application process to exit, removing this instrumentation from the next 179 * time the application is started. 180 * 181 * @param resultCode Overall success/failure of instrumentation. 182 * @param results Any results to send back to the code that started the 183 * instrumentation. 184 */ 185 public void finish(int resultCode, Bundle results) { 186 if (mAutomaticPerformanceSnapshots) { 187 endPerformanceSnapshot(); 188 } 189 if (mPerfMetrics != null) { 190 results.putAll(mPerfMetrics); 191 } 192 if (mUiAutomation != null) { 193 mUiAutomation.disconnect(); 194 mUiAutomation = null; 195 } 196 mThread.finishInstrumentation(resultCode, results); 197 } 198 199 public void setAutomaticPerformanceSnapshots() { 200 mAutomaticPerformanceSnapshots = true; 201 mPerformanceCollector = new PerformanceCollector(); 202 } 203 204 public void startPerformanceSnapshot() { 205 if (!isProfiling()) { 206 mPerformanceCollector.beginSnapshot(null); 207 } 208 } 209 210 public void endPerformanceSnapshot() { 211 if (!isProfiling()) { 212 mPerfMetrics = mPerformanceCollector.endSnapshot(); 213 } 214 } 215 216 /** 217 * Called when the instrumented application is stopping, after all of the 218 * normal application cleanup has occurred. 219 */ 220 public void onDestroy() { 221 } 222 223 /** 224 * Return the Context of this instrumentation's package. Note that this is 225 * often different than the Context of the application being 226 * instrumentated, since the instrumentation code often lives is a 227 * different package than that of the application it is running against. 228 * See {@link #getTargetContext} to retrieve a Context for the target 229 * application. 230 * 231 * @return The instrumentation's package context. 232 * 233 * @see #getTargetContext 234 */ 235 public Context getContext() { 236 return mInstrContext; 237 } 238 239 /** 240 * Returns complete component name of this instrumentation. 241 * 242 * @return Returns the complete component name for this instrumentation. 243 */ 244 public ComponentName getComponentName() { 245 return mComponent; 246 } 247 248 /** 249 * Return a Context for the target application being instrumented. Note 250 * that this is often different than the Context of the instrumentation 251 * code, since the instrumentation code often lives is a different package 252 * than that of the application it is running against. See 253 * {@link #getContext} to retrieve a Context for the instrumentation code. 254 * 255 * @return A Context in the target application. 256 * 257 * @see #getContext 258 */ 259 public Context getTargetContext() { 260 return mAppContext; 261 } 262 263 /** 264 * Check whether this instrumentation was started with profiling enabled. 265 * 266 * @return Returns true if profiling was enabled when starting, else false. 267 */ 268 public boolean isProfiling() { 269 return mThread.isProfiling(); 270 } 271 272 /** 273 * This method will start profiling if isProfiling() returns true. You should 274 * only call this method if you set the handleProfiling attribute in the 275 * manifest file for this Instrumentation to true. 276 */ 277 public void startProfiling() { 278 if (mThread.isProfiling()) { 279 File file = new File(mThread.getProfileFilePath()); 280 file.getParentFile().mkdirs(); 281 Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024); 282 } 283 } 284 285 /** 286 * Stops profiling if isProfiling() returns true. 287 */ 288 public void stopProfiling() { 289 if (mThread.isProfiling()) { 290 Debug.stopMethodTracing(); 291 } 292 } 293 294 /** 295 * Force the global system in or out of touch mode. This can be used if 296 * your instrumentation relies on the UI being in one more or the other 297 * when it starts. 298 * 299 * @param inTouch Set to true to be in touch mode, false to be in 300 * focus mode. 301 */ 302 public void setInTouchMode(boolean inTouch) { 303 try { 304 IWindowManager.Stub.asInterface( 305 ServiceManager.getService("window")).setInTouchMode(inTouch); 306 } catch (RemoteException e) { 307 // Shouldn't happen! 308 } 309 } 310 311 /** 312 * Schedule a callback for when the application's main thread goes idle 313 * (has no more events to process). 314 * 315 * @param recipient Called the next time the thread's message queue is 316 * idle. 317 */ 318 public void waitForIdle(Runnable recipient) { 319 mMessageQueue.addIdleHandler(new Idler(recipient)); 320 mThread.getHandler().post(new EmptyRunnable()); 321 } 322 323 /** 324 * Synchronously wait for the application to be idle. Can not be called 325 * from the main application thread -- use {@link #start} to execute 326 * instrumentation in its own thread. 327 */ 328 public void waitForIdleSync() { 329 validateNotAppThread(); 330 Idler idler = new Idler(null); 331 mMessageQueue.addIdleHandler(idler); 332 mThread.getHandler().post(new EmptyRunnable()); 333 idler.waitForIdle(); 334 } 335 336 /** 337 * Execute a call on the application's main thread, blocking until it is 338 * complete. Useful for doing things that are not thread-safe, such as 339 * looking at or modifying the view hierarchy. 340 * 341 * @param runner The code to run on the main thread. 342 */ 343 public void runOnMainSync(Runnable runner) { 344 validateNotAppThread(); 345 SyncRunnable sr = new SyncRunnable(runner); 346 mThread.getHandler().post(sr); 347 sr.waitForComplete(); 348 } 349 350 /** 351 * Start a new activity and wait for it to begin running before returning. 352 * In addition to being synchronous, this method as some semantic 353 * differences from the standard {@link Context#startActivity} call: the 354 * activity component is resolved before talking with the activity manager 355 * (its class name is specified in the Intent that this method ultimately 356 * starts), and it does not allow you to start activities that run in a 357 * different process. In addition, if the given Intent resolves to 358 * multiple activities, instead of displaying a dialog for the user to 359 * select an activity, an exception will be thrown. 360 * 361 * <p>The function returns as soon as the activity goes idle following the 362 * call to its {@link Activity#onCreate}. Generally this means it has gone 363 * through the full initialization including {@link Activity#onResume} and 364 * drawn and displayed its initial window. 365 * 366 * @param intent Description of the activity to start. 367 * 368 * @see Context#startActivity 369 */ 370 public Activity startActivitySync(Intent intent) { 371 validateNotAppThread(); 372 373 synchronized (mSync) { 374 intent = new Intent(intent); 375 376 ActivityInfo ai = intent.resolveActivityInfo( 377 getTargetContext().getPackageManager(), 0); 378 if (ai == null) { 379 throw new RuntimeException("Unable to resolve activity for: " + intent); 380 } 381 String myProc = mThread.getProcessName(); 382 if (!ai.processName.equals(myProc)) { 383 // todo: if this intent is ambiguous, look here to see if 384 // there is a single match that is in our package. 385 throw new RuntimeException("Intent in process " 386 + myProc + " resolved to different process " 387 + ai.processName + ": " + intent); 388 } 389 390 intent.setComponent(new ComponentName( 391 ai.applicationInfo.packageName, ai.name)); 392 final ActivityWaiter aw = new ActivityWaiter(intent); 393 394 if (mWaitingActivities == null) { 395 mWaitingActivities = new ArrayList(); 396 } 397 mWaitingActivities.add(aw); 398 399 getTargetContext().startActivity(intent); 400 401 do { 402 try { 403 mSync.wait(); 404 } catch (InterruptedException e) { 405 } 406 } while (mWaitingActivities.contains(aw)); 407 408 return aw.activity; 409 } 410 } 411 412 /** 413 * Information about a particular kind of Intent that is being monitored. 414 * An instance of this class is added to the 415 * current instrumentation through {@link #addMonitor}; after being added, 416 * when a new activity is being started the monitor will be checked and, if 417 * matching, its hit count updated and (optionally) the call stopped and a 418 * canned result returned. 419 * 420 * <p>An ActivityMonitor can also be used to look for the creation of an 421 * activity, through the {@link #waitForActivity} method. This will return 422 * after a matching activity has been created with that activity object. 423 */ 424 public static class ActivityMonitor { 425 private final IntentFilter mWhich; 426 private final String mClass; 427 private final ActivityResult mResult; 428 private final boolean mBlock; 429 430 431 // This is protected by 'Instrumentation.this.mSync'. 432 /*package*/ int mHits = 0; 433 434 // This is protected by 'this'. 435 /*package*/ Activity mLastActivity = null; 436 437 /** 438 * Create a new ActivityMonitor that looks for a particular kind of 439 * intent to be started. 440 * 441 * @param which The set of intents this monitor is responsible for. 442 * @param result A canned result to return if the monitor is hit; can 443 * be null. 444 * @param block Controls whether the monitor should block the activity 445 * start (returning its canned result) or let the call 446 * proceed. 447 * 448 * @see Instrumentation#addMonitor 449 */ 450 public ActivityMonitor( 451 IntentFilter which, ActivityResult result, boolean block) { 452 mWhich = which; 453 mClass = null; 454 mResult = result; 455 mBlock = block; 456 } 457 458 /** 459 * Create a new ActivityMonitor that looks for a specific activity 460 * class to be started. 461 * 462 * @param cls The activity class this monitor is responsible for. 463 * @param result A canned result to return if the monitor is hit; can 464 * be null. 465 * @param block Controls whether the monitor should block the activity 466 * start (returning its canned result) or let the call 467 * proceed. 468 * 469 * @see Instrumentation#addMonitor 470 */ 471 public ActivityMonitor( 472 String cls, ActivityResult result, boolean block) { 473 mWhich = null; 474 mClass = cls; 475 mResult = result; 476 mBlock = block; 477 } 478 479 /** 480 * Retrieve the filter associated with this ActivityMonitor. 481 */ 482 public final IntentFilter getFilter() { 483 return mWhich; 484 } 485 486 /** 487 * Retrieve the result associated with this ActivityMonitor, or null if 488 * none. 489 */ 490 public final ActivityResult getResult() { 491 return mResult; 492 } 493 494 /** 495 * Check whether this monitor blocks activity starts (not allowing the 496 * actual activity to run) or allows them to execute normally. 497 */ 498 public final boolean isBlocking() { 499 return mBlock; 500 } 501 502 /** 503 * Retrieve the number of times the monitor has been hit so far. 504 */ 505 public final int getHits() { 506 return mHits; 507 } 508 509 /** 510 * Retrieve the most recent activity class that was seen by this 511 * monitor. 512 */ 513 public final Activity getLastActivity() { 514 return mLastActivity; 515 } 516 517 /** 518 * Block until an Activity is created that matches this monitor, 519 * returning the resulting activity. 520 * 521 * @return Activity 522 */ 523 public final Activity waitForActivity() { 524 synchronized (this) { 525 while (mLastActivity == null) { 526 try { 527 wait(); 528 } catch (InterruptedException e) { 529 } 530 } 531 Activity res = mLastActivity; 532 mLastActivity = null; 533 return res; 534 } 535 } 536 537 /** 538 * Block until an Activity is created that matches this monitor, 539 * returning the resulting activity or till the timeOut period expires. 540 * If the timeOut expires before the activity is started, return null. 541 * 542 * @param timeOut Time to wait before the activity is created. 543 * 544 * @return Activity 545 */ 546 public final Activity waitForActivityWithTimeout(long timeOut) { 547 synchronized (this) { 548 if (mLastActivity == null) { 549 try { 550 wait(timeOut); 551 } catch (InterruptedException e) { 552 } 553 } 554 if (mLastActivity == null) { 555 return null; 556 } else { 557 Activity res = mLastActivity; 558 mLastActivity = null; 559 return res; 560 } 561 } 562 } 563 564 final boolean match(Context who, 565 Activity activity, 566 Intent intent) { 567 synchronized (this) { 568 if (mWhich != null 569 && mWhich.match(who.getContentResolver(), intent, 570 true, "Instrumentation") < 0) { 571 return false; 572 } 573 if (mClass != null) { 574 String cls = null; 575 if (activity != null) { 576 cls = activity.getClass().getName(); 577 } else if (intent.getComponent() != null) { 578 cls = intent.getComponent().getClassName(); 579 } 580 if (cls == null || !mClass.equals(cls)) { 581 return false; 582 } 583 } 584 if (activity != null) { 585 mLastActivity = activity; 586 notifyAll(); 587 } 588 return true; 589 } 590 } 591 } 592 593 /** 594 * Add a new {@link ActivityMonitor} that will be checked whenever an 595 * activity is started. The monitor is added 596 * after any existing ones; the monitor will be hit only if none of the 597 * existing monitors can themselves handle the Intent. 598 * 599 * @param monitor The new ActivityMonitor to see. 600 * 601 * @see #addMonitor(IntentFilter, ActivityResult, boolean) 602 * @see #checkMonitorHit 603 */ 604 public void addMonitor(ActivityMonitor monitor) { 605 synchronized (mSync) { 606 if (mActivityMonitors == null) { 607 mActivityMonitors = new ArrayList(); 608 } 609 mActivityMonitors.add(monitor); 610 } 611 } 612 613 /** 614 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that 615 * creates an intent filter matching {@link ActivityMonitor} for you and 616 * returns it. 617 * 618 * @param filter The set of intents this monitor is responsible for. 619 * @param result A canned result to return if the monitor is hit; can 620 * be null. 621 * @param block Controls whether the monitor should block the activity 622 * start (returning its canned result) or let the call 623 * proceed. 624 * 625 * @return The newly created and added activity monitor. 626 * 627 * @see #addMonitor(ActivityMonitor) 628 * @see #checkMonitorHit 629 */ 630 public ActivityMonitor addMonitor( 631 IntentFilter filter, ActivityResult result, boolean block) { 632 ActivityMonitor am = new ActivityMonitor(filter, result, block); 633 addMonitor(am); 634 return am; 635 } 636 637 /** 638 * A convenience wrapper for {@link #addMonitor(ActivityMonitor)} that 639 * creates a class matching {@link ActivityMonitor} for you and returns it. 640 * 641 * @param cls The activity class this monitor is responsible for. 642 * @param result A canned result to return if the monitor is hit; can 643 * be null. 644 * @param block Controls whether the monitor should block the activity 645 * start (returning its canned result) or let the call 646 * proceed. 647 * 648 * @return The newly created and added activity monitor. 649 * 650 * @see #addMonitor(ActivityMonitor) 651 * @see #checkMonitorHit 652 */ 653 public ActivityMonitor addMonitor( 654 String cls, ActivityResult result, boolean block) { 655 ActivityMonitor am = new ActivityMonitor(cls, result, block); 656 addMonitor(am); 657 return am; 658 } 659 660 /** 661 * Test whether an existing {@link ActivityMonitor} has been hit. If the 662 * monitor has been hit at least <var>minHits</var> times, then it will be 663 * removed from the activity monitor list and true returned. Otherwise it 664 * is left as-is and false is returned. 665 * 666 * @param monitor The ActivityMonitor to check. 667 * @param minHits The minimum number of hits required. 668 * 669 * @return True if the hit count has been reached, else false. 670 * 671 * @see #addMonitor 672 */ 673 public boolean checkMonitorHit(ActivityMonitor monitor, int minHits) { 674 waitForIdleSync(); 675 synchronized (mSync) { 676 if (monitor.getHits() < minHits) { 677 return false; 678 } 679 mActivityMonitors.remove(monitor); 680 } 681 return true; 682 } 683 684 /** 685 * Wait for an existing {@link ActivityMonitor} to be hit. Once the 686 * monitor has been hit, it is removed from the activity monitor list and 687 * the first created Activity object that matched it is returned. 688 * 689 * @param monitor The ActivityMonitor to wait for. 690 * 691 * @return The Activity object that matched the monitor. 692 */ 693 public Activity waitForMonitor(ActivityMonitor monitor) { 694 Activity activity = monitor.waitForActivity(); 695 synchronized (mSync) { 696 mActivityMonitors.remove(monitor); 697 } 698 return activity; 699 } 700 701 /** 702 * Wait for an existing {@link ActivityMonitor} to be hit till the timeout 703 * expires. Once the monitor has been hit, it is removed from the activity 704 * monitor list and the first created Activity object that matched it is 705 * returned. If the timeout expires, a null object is returned. 706 * 707 * @param monitor The ActivityMonitor to wait for. 708 * @param timeOut The timeout value in secs. 709 * 710 * @return The Activity object that matched the monitor. 711 */ 712 public Activity waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut) { 713 Activity activity = monitor.waitForActivityWithTimeout(timeOut); 714 synchronized (mSync) { 715 mActivityMonitors.remove(monitor); 716 } 717 return activity; 718 } 719 720 /** 721 * Remove an {@link ActivityMonitor} that was previously added with 722 * {@link #addMonitor}. 723 * 724 * @param monitor The monitor to remove. 725 * 726 * @see #addMonitor 727 */ 728 public void removeMonitor(ActivityMonitor monitor) { 729 synchronized (mSync) { 730 mActivityMonitors.remove(monitor); 731 } 732 } 733 734 /** 735 * Execute a particular menu item. 736 * 737 * @param targetActivity The activity in question. 738 * @param id The identifier associated with the menu item. 739 * @param flag Additional flags, if any. 740 * @return Whether the invocation was successful (for example, it could be 741 * false if item is disabled). 742 */ 743 public boolean invokeMenuActionSync(Activity targetActivity, 744 int id, int flag) { 745 class MenuRunnable implements Runnable { 746 private final Activity activity; 747 private final int identifier; 748 private final int flags; 749 boolean returnValue; 750 751 public MenuRunnable(Activity _activity, int _identifier, 752 int _flags) { 753 activity = _activity; 754 identifier = _identifier; 755 flags = _flags; 756 } 757 758 public void run() { 759 Window win = activity.getWindow(); 760 761 returnValue = win.performPanelIdentifierAction( 762 Window.FEATURE_OPTIONS_PANEL, 763 identifier, 764 flags); 765 } 766 767 } 768 MenuRunnable mr = new MenuRunnable(targetActivity, id, flag); 769 runOnMainSync(mr); 770 return mr.returnValue; 771 } 772 773 /** 774 * Show the context menu for the currently focused view and executes a 775 * particular context menu item. 776 * 777 * @param targetActivity The activity in question. 778 * @param id The identifier associated with the context menu item. 779 * @param flag Additional flags, if any. 780 * @return Whether the invocation was successful (for example, it could be 781 * false if item is disabled). 782 */ 783 public boolean invokeContextMenuAction(Activity targetActivity, int id, int flag) { 784 validateNotAppThread(); 785 786 // Bring up context menu for current focus. 787 // It'd be nice to do this through code, but currently ListView depends on 788 // long press to set metadata for its selected child 789 790 final KeyEvent downEvent = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER); 791 sendKeySync(downEvent); 792 793 // Need to wait for long press 794 waitForIdleSync(); 795 try { 796 Thread.sleep(ViewConfiguration.getLongPressTimeout()); 797 } catch (InterruptedException e) { 798 Log.e(TAG, "Could not sleep for long press timeout", e); 799 return false; 800 } 801 802 final KeyEvent upEvent = new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER); 803 sendKeySync(upEvent); 804 805 // Wait for context menu to appear 806 waitForIdleSync(); 807 808 class ContextMenuRunnable implements Runnable { 809 private final Activity activity; 810 private final int identifier; 811 private final int flags; 812 boolean returnValue; 813 814 public ContextMenuRunnable(Activity _activity, int _identifier, 815 int _flags) { 816 activity = _activity; 817 identifier = _identifier; 818 flags = _flags; 819 } 820 821 public void run() { 822 Window win = activity.getWindow(); 823 returnValue = win.performContextMenuIdentifierAction( 824 identifier, 825 flags); 826 } 827 828 } 829 830 ContextMenuRunnable cmr = new ContextMenuRunnable(targetActivity, id, flag); 831 runOnMainSync(cmr); 832 return cmr.returnValue; 833 } 834 835 /** 836 * Sends the key events corresponding to the text to the app being 837 * instrumented. 838 * 839 * @param text The text to be sent. 840 */ 841 public void sendStringSync(String text) { 842 if (text == null) { 843 return; 844 } 845 KeyCharacterMap keyCharacterMap = KeyCharacterMap.load(KeyCharacterMap.VIRTUAL_KEYBOARD); 846 847 KeyEvent[] events = keyCharacterMap.getEvents(text.toCharArray()); 848 849 if (events != null) { 850 for (int i = 0; i < events.length; i++) { 851 // We have to change the time of an event before injecting it because 852 // all KeyEvents returned by KeyCharacterMap.getEvents() have the same 853 // time stamp and the system rejects too old events. Hence, it is 854 // possible for an event to become stale before it is injected if it 855 // takes too long to inject the preceding ones. 856 sendKeySync(KeyEvent.changeTimeRepeat(events[i], SystemClock.uptimeMillis(), 0)); 857 } 858 } 859 } 860 861 /** 862 * Send a key event to the currently focused window/view and wait for it to 863 * be processed. Finished at some point after the recipient has returned 864 * from its event processing, though it may <em>not</em> have completely 865 * finished reacting from the event -- for example, if it needs to update 866 * its display as a result, it may still be in the process of doing that. 867 * 868 * @param event The event to send to the current focus. 869 */ 870 public void sendKeySync(KeyEvent event) { 871 validateNotAppThread(); 872 873 long downTime = event.getDownTime(); 874 long eventTime = event.getEventTime(); 875 int action = event.getAction(); 876 int code = event.getKeyCode(); 877 int repeatCount = event.getRepeatCount(); 878 int metaState = event.getMetaState(); 879 int deviceId = event.getDeviceId(); 880 int scancode = event.getScanCode(); 881 int source = event.getSource(); 882 int flags = event.getFlags(); 883 if (source == InputDevice.SOURCE_UNKNOWN) { 884 source = InputDevice.SOURCE_KEYBOARD; 885 } 886 if (eventTime == 0) { 887 eventTime = SystemClock.uptimeMillis(); 888 } 889 if (downTime == 0) { 890 downTime = eventTime; 891 } 892 KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState, 893 deviceId, scancode, flags | KeyEvent.FLAG_FROM_SYSTEM, source); 894 InputManager.getInstance().injectInputEvent(newEvent, 895 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); 896 } 897 898 /** 899 * Sends an up and down key event sync to the currently focused window. 900 * 901 * @param key The integer keycode for the event. 902 */ 903 public void sendKeyDownUpSync(int key) { 904 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, key)); 905 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, key)); 906 } 907 908 /** 909 * Higher-level method for sending both the down and up key events for a 910 * particular character key code. Equivalent to creating both KeyEvent 911 * objects by hand and calling {@link #sendKeySync}. The event appears 912 * as if it came from keyboard 0, the built in one. 913 * 914 * @param keyCode The key code of the character to send. 915 */ 916 public void sendCharacterSync(int keyCode) { 917 sendKeySync(new KeyEvent(KeyEvent.ACTION_DOWN, keyCode)); 918 sendKeySync(new KeyEvent(KeyEvent.ACTION_UP, keyCode)); 919 } 920 921 /** 922 * Dispatch a pointer event. Finished at some point after the recipient has 923 * returned from its event processing, though it may <em>not</em> have 924 * completely finished reacting from the event -- for example, if it needs 925 * to update its display as a result, it may still be in the process of 926 * doing that. 927 * 928 * @param event A motion event describing the pointer action. (As noted in 929 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use 930 * {@link SystemClock#uptimeMillis()} as the timebase. 931 */ 932 public void sendPointerSync(MotionEvent event) { 933 validateNotAppThread(); 934 if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) == 0) { 935 event.setSource(InputDevice.SOURCE_TOUCHSCREEN); 936 } 937 InputManager.getInstance().injectInputEvent(event, 938 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); 939 } 940 941 /** 942 * Dispatch a trackball event. Finished at some point after the recipient has 943 * returned from its event processing, though it may <em>not</em> have 944 * completely finished reacting from the event -- for example, if it needs 945 * to update its display as a result, it may still be in the process of 946 * doing that. 947 * 948 * @param event A motion event describing the trackball action. (As noted in 949 * {@link MotionEvent#obtain(long, long, int, float, float, int)}, be sure to use 950 * {@link SystemClock#uptimeMillis()} as the timebase. 951 */ 952 public void sendTrackballEventSync(MotionEvent event) { 953 validateNotAppThread(); 954 if ((event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == 0) { 955 event.setSource(InputDevice.SOURCE_TRACKBALL); 956 } 957 InputManager.getInstance().injectInputEvent(event, 958 InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH); 959 } 960 961 /** 962 * Perform instantiation of the process's {@link Application} object. The 963 * default implementation provides the normal system behavior. 964 * 965 * @param cl The ClassLoader with which to instantiate the object. 966 * @param className The name of the class implementing the Application 967 * object. 968 * @param context The context to initialize the application with 969 * 970 * @return The newly instantiated Application object. 971 */ 972 public Application newApplication(ClassLoader cl, String className, Context context) 973 throws InstantiationException, IllegalAccessException, 974 ClassNotFoundException { 975 return newApplication(cl.loadClass(className), context); 976 } 977 978 /** 979 * Perform instantiation of the process's {@link Application} object. The 980 * default implementation provides the normal system behavior. 981 * 982 * @param clazz The class used to create an Application object from. 983 * @param context The context to initialize the application with 984 * 985 * @return The newly instantiated Application object. 986 */ 987 static public Application newApplication(Class<?> clazz, Context context) 988 throws InstantiationException, IllegalAccessException, 989 ClassNotFoundException { 990 Application app = (Application)clazz.newInstance(); 991 app.attach(context); 992 return app; 993 } 994 995 /** 996 * Perform calling of the application's {@link Application#onCreate} 997 * method. The default implementation simply calls through to that method. 998 * 999 * <p>Note: This method will be called immediately after {@link #onCreate(Bundle)}. 1000 * Often instrumentation tests start their test thread in onCreate(); you 1001 * need to be careful of races between these. (Well between it and 1002 * everything else, but let's start here.) 1003 * 1004 * @param app The application being created. 1005 */ 1006 public void callApplicationOnCreate(Application app) { 1007 app.onCreate(); 1008 } 1009 1010 /** 1011 * Perform instantiation of an {@link Activity} object. This method is intended for use with 1012 * unit tests, such as android.test.ActivityUnitTestCase. The activity will be useable 1013 * locally but will be missing some of the linkages necessary for use within the sytem. 1014 * 1015 * @param clazz The Class of the desired Activity 1016 * @param context The base context for the activity to use 1017 * @param token The token for this activity to communicate with 1018 * @param application The application object (if any) 1019 * @param intent The intent that started this Activity 1020 * @param info ActivityInfo from the manifest 1021 * @param title The title, typically retrieved from the ActivityInfo record 1022 * @param parent The parent Activity (if any) 1023 * @param id The embedded Id (if any) 1024 * @param lastNonConfigurationInstance Arbitrary object that will be 1025 * available via {@link Activity#getLastNonConfigurationInstance() 1026 * Activity.getLastNonConfigurationInstance()}. 1027 * @return Returns the instantiated activity 1028 * @throws InstantiationException 1029 * @throws IllegalAccessException 1030 */ 1031 public Activity newActivity(Class<?> clazz, Context context, 1032 IBinder token, Application application, Intent intent, ActivityInfo info, 1033 CharSequence title, Activity parent, String id, 1034 Object lastNonConfigurationInstance) throws InstantiationException, 1035 IllegalAccessException { 1036 Activity activity = (Activity)clazz.newInstance(); 1037 ActivityThread aThread = null; 1038 activity.attach(context, aThread, this, token, application, intent, 1039 info, title, parent, id, 1040 (Activity.NonConfigurationInstances)lastNonConfigurationInstance, 1041 new Configuration()); 1042 return activity; 1043 } 1044 1045 /** 1046 * Perform instantiation of the process's {@link Activity} object. The 1047 * default implementation provides the normal system behavior. 1048 * 1049 * @param cl The ClassLoader with which to instantiate the object. 1050 * @param className The name of the class implementing the Activity 1051 * object. 1052 * @param intent The Intent object that specified the activity class being 1053 * instantiated. 1054 * 1055 * @return The newly instantiated Activity object. 1056 */ 1057 public Activity newActivity(ClassLoader cl, String className, 1058 Intent intent) 1059 throws InstantiationException, IllegalAccessException, 1060 ClassNotFoundException { 1061 return (Activity)cl.loadClass(className).newInstance(); 1062 } 1063 1064 /** 1065 * Perform calling of an activity's {@link Activity#onCreate} 1066 * method. The default implementation simply calls through to that method. 1067 * 1068 * @param activity The activity being created. 1069 * @param icicle The previously frozen state (or null) to pass through to 1070 * onCreate(). 1071 */ 1072 public void callActivityOnCreate(Activity activity, Bundle icicle) { 1073 if (mWaitingActivities != null) { 1074 synchronized (mSync) { 1075 final int N = mWaitingActivities.size(); 1076 for (int i=0; i<N; i++) { 1077 final ActivityWaiter aw = mWaitingActivities.get(i); 1078 final Intent intent = aw.intent; 1079 if (intent.filterEquals(activity.getIntent())) { 1080 aw.activity = activity; 1081 mMessageQueue.addIdleHandler(new ActivityGoing(aw)); 1082 } 1083 } 1084 } 1085 } 1086 1087 activity.performCreate(icicle); 1088 1089 if (mActivityMonitors != null) { 1090 synchronized (mSync) { 1091 final int N = mActivityMonitors.size(); 1092 for (int i=0; i<N; i++) { 1093 final ActivityMonitor am = mActivityMonitors.get(i); 1094 am.match(activity, activity, activity.getIntent()); 1095 } 1096 } 1097 } 1098 } 1099 1100 public void callActivityOnDestroy(Activity activity) { 1101 // TODO: the following block causes intermittent hangs when using startActivity 1102 // temporarily comment out until root cause is fixed (bug 2630683) 1103 // if (mWaitingActivities != null) { 1104 // synchronized (mSync) { 1105 // final int N = mWaitingActivities.size(); 1106 // for (int i=0; i<N; i++) { 1107 // final ActivityWaiter aw = mWaitingActivities.get(i); 1108 // final Intent intent = aw.intent; 1109 // if (intent.filterEquals(activity.getIntent())) { 1110 // aw.activity = activity; 1111 // mMessageQueue.addIdleHandler(new ActivityGoing(aw)); 1112 // } 1113 // } 1114 // } 1115 // } 1116 1117 activity.performDestroy(); 1118 1119 if (mActivityMonitors != null) { 1120 synchronized (mSync) { 1121 final int N = mActivityMonitors.size(); 1122 for (int i=0; i<N; i++) { 1123 final ActivityMonitor am = mActivityMonitors.get(i); 1124 am.match(activity, activity, activity.getIntent()); 1125 } 1126 } 1127 } 1128 } 1129 1130 /** 1131 * Perform calling of an activity's {@link Activity#onRestoreInstanceState} 1132 * method. The default implementation simply calls through to that method. 1133 * 1134 * @param activity The activity being restored. 1135 * @param savedInstanceState The previously saved state being restored. 1136 */ 1137 public void callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState) { 1138 activity.performRestoreInstanceState(savedInstanceState); 1139 } 1140 1141 /** 1142 * Perform calling of an activity's {@link Activity#onPostCreate} method. 1143 * The default implementation simply calls through to that method. 1144 * 1145 * @param activity The activity being created. 1146 * @param icicle The previously frozen state (or null) to pass through to 1147 * onPostCreate(). 1148 */ 1149 public void callActivityOnPostCreate(Activity activity, Bundle icicle) { 1150 activity.onPostCreate(icicle); 1151 } 1152 1153 /** 1154 * Perform calling of an activity's {@link Activity#onNewIntent} 1155 * method. The default implementation simply calls through to that method. 1156 * 1157 * @param activity The activity receiving a new Intent. 1158 * @param intent The new intent being received. 1159 */ 1160 public void callActivityOnNewIntent(Activity activity, Intent intent) { 1161 activity.onNewIntent(intent); 1162 } 1163 1164 /** 1165 * Perform calling of an activity's {@link Activity#onStart} 1166 * method. The default implementation simply calls through to that method. 1167 * 1168 * @param activity The activity being started. 1169 */ 1170 public void callActivityOnStart(Activity activity) { 1171 activity.onStart(); 1172 } 1173 1174 /** 1175 * Perform calling of an activity's {@link Activity#onRestart} 1176 * method. The default implementation simply calls through to that method. 1177 * 1178 * @param activity The activity being restarted. 1179 */ 1180 public void callActivityOnRestart(Activity activity) { 1181 activity.onRestart(); 1182 } 1183 1184 /** 1185 * Perform calling of an activity's {@link Activity#onResume} method. The 1186 * default implementation simply calls through to that method. 1187 * 1188 * @param activity The activity being resumed. 1189 */ 1190 public void callActivityOnResume(Activity activity) { 1191 activity.mResumed = true; 1192 activity.onResume(); 1193 1194 if (mActivityMonitors != null) { 1195 synchronized (mSync) { 1196 final int N = mActivityMonitors.size(); 1197 for (int i=0; i<N; i++) { 1198 final ActivityMonitor am = mActivityMonitors.get(i); 1199 am.match(activity, activity, activity.getIntent()); 1200 } 1201 } 1202 } 1203 } 1204 1205 /** 1206 * Perform calling of an activity's {@link Activity#onStop} 1207 * method. The default implementation simply calls through to that method. 1208 * 1209 * @param activity The activity being stopped. 1210 */ 1211 public void callActivityOnStop(Activity activity) { 1212 activity.onStop(); 1213 } 1214 1215 /** 1216 * Perform calling of an activity's {@link Activity#onPause} method. The 1217 * default implementation simply calls through to that method. 1218 * 1219 * @param activity The activity being saved. 1220 * @param outState The bundle to pass to the call. 1221 */ 1222 public void callActivityOnSaveInstanceState(Activity activity, Bundle outState) { 1223 activity.performSaveInstanceState(outState); 1224 } 1225 1226 /** 1227 * Perform calling of an activity's {@link Activity#onPause} method. The 1228 * default implementation simply calls through to that method. 1229 * 1230 * @param activity The activity being paused. 1231 */ 1232 public void callActivityOnPause(Activity activity) { 1233 activity.performPause(); 1234 } 1235 1236 /** 1237 * Perform calling of an activity's {@link Activity#onUserLeaveHint} method. 1238 * The default implementation simply calls through to that method. 1239 * 1240 * @param activity The activity being notified that the user has navigated away 1241 */ 1242 public void callActivityOnUserLeaving(Activity activity) { 1243 activity.performUserLeaving(); 1244 } 1245 1246 /* 1247 * Starts allocation counting. This triggers a gc and resets the counts. 1248 */ 1249 public void startAllocCounting() { 1250 // Before we start trigger a GC and reset the debug counts. Run the 1251 // finalizers and another GC before starting and stopping the alloc 1252 // counts. This will free up any objects that were just sitting around 1253 // waiting for their finalizers to be run. 1254 Runtime.getRuntime().gc(); 1255 Runtime.getRuntime().runFinalization(); 1256 Runtime.getRuntime().gc(); 1257 1258 Debug.resetAllCounts(); 1259 1260 // start the counts 1261 Debug.startAllocCounting(); 1262 } 1263 1264 /* 1265 * Stops allocation counting. 1266 */ 1267 public void stopAllocCounting() { 1268 Runtime.getRuntime().gc(); 1269 Runtime.getRuntime().runFinalization(); 1270 Runtime.getRuntime().gc(); 1271 Debug.stopAllocCounting(); 1272 } 1273 1274 /** 1275 * If Results already contains Key, it appends Value to the key's ArrayList 1276 * associated with the key. If the key doesn't already exist in results, it 1277 * adds the key/value pair to results. 1278 */ 1279 private void addValue(String key, int value, Bundle results) { 1280 if (results.containsKey(key)) { 1281 List<Integer> list = results.getIntegerArrayList(key); 1282 if (list != null) { 1283 list.add(value); 1284 } 1285 } else { 1286 ArrayList<Integer> list = new ArrayList<Integer>(); 1287 list.add(value); 1288 results.putIntegerArrayList(key, list); 1289 } 1290 } 1291 1292 /** 1293 * Returns a bundle with the current results from the allocation counting. 1294 */ 1295 public Bundle getAllocCounts() { 1296 Bundle results = new Bundle(); 1297 results.putLong("global_alloc_count", Debug.getGlobalAllocCount()); 1298 results.putLong("global_alloc_size", Debug.getGlobalAllocSize()); 1299 results.putLong("global_freed_count", Debug.getGlobalFreedCount()); 1300 results.putLong("global_freed_size", Debug.getGlobalFreedSize()); 1301 results.putLong("gc_invocation_count", Debug.getGlobalGcInvocationCount()); 1302 return results; 1303 } 1304 1305 /** 1306 * Returns a bundle with the counts for various binder counts for this process. Currently the only two that are 1307 * reported are the number of send and the number of received transactions. 1308 */ 1309 public Bundle getBinderCounts() { 1310 Bundle results = new Bundle(); 1311 results.putLong("sent_transactions", Debug.getBinderSentTransactions()); 1312 results.putLong("received_transactions", Debug.getBinderReceivedTransactions()); 1313 return results; 1314 } 1315 1316 /** 1317 * Description of a Activity execution result to return to the original 1318 * activity. 1319 */ 1320 public static final class ActivityResult { 1321 /** 1322 * Create a new activity result. See {@link Activity#setResult} for 1323 * more information. 1324 * 1325 * @param resultCode The result code to propagate back to the 1326 * originating activity, often RESULT_CANCELED or RESULT_OK 1327 * @param resultData The data to propagate back to the originating 1328 * activity. 1329 */ 1330 public ActivityResult(int resultCode, Intent resultData) { 1331 mResultCode = resultCode; 1332 mResultData = resultData; 1333 } 1334 1335 /** 1336 * Retrieve the result code contained in this result. 1337 */ 1338 public int getResultCode() { 1339 return mResultCode; 1340 } 1341 1342 /** 1343 * Retrieve the data contained in this result. 1344 */ 1345 public Intent getResultData() { 1346 return mResultData; 1347 } 1348 1349 private final int mResultCode; 1350 private final Intent mResultData; 1351 } 1352 1353 /** 1354 * Execute a startActivity call made by the application. The default 1355 * implementation takes care of updating any active {@link ActivityMonitor} 1356 * objects and dispatches this call to the system activity manager; you can 1357 * override this to watch for the application to start an activity, and 1358 * modify what happens when it does. 1359 * 1360 * <p>This method returns an {@link ActivityResult} object, which you can 1361 * use when intercepting application calls to avoid performing the start 1362 * activity action but still return the result the application is 1363 * expecting. To do this, override this method to catch the call to start 1364 * activity so that it returns a new ActivityResult containing the results 1365 * you would like the application to see, and don't call up to the super 1366 * class. Note that an application is only expecting a result if 1367 * <var>requestCode</var> is >= 0. 1368 * 1369 * <p>This method throws {@link android.content.ActivityNotFoundException} 1370 * if there was no Activity found to run the given Intent. 1371 * 1372 * @param who The Context from which the activity is being started. 1373 * @param contextThread The main thread of the Context from which the activity 1374 * is being started. 1375 * @param token Internal token identifying to the system who is starting 1376 * the activity; may be null. 1377 * @param target Which activity is performing the start (and thus receiving 1378 * any result); may be null if this call is not being made 1379 * from an activity. 1380 * @param intent The actual Intent to start. 1381 * @param requestCode Identifier for this request's result; less than zero 1382 * if the caller is not expecting a result. 1383 * @param options Addition options. 1384 * 1385 * @return To force the return of a particular result, return an 1386 * ActivityResult object containing the desired data; otherwise 1387 * return null. The default implementation always returns null. 1388 * 1389 * @throws android.content.ActivityNotFoundException 1390 * 1391 * @see Activity#startActivity(Intent) 1392 * @see Activity#startActivityForResult(Intent, int) 1393 * @see Activity#startActivityFromChild 1394 * 1395 * {@hide} 1396 */ 1397 public ActivityResult execStartActivity( 1398 Context who, IBinder contextThread, IBinder token, Activity target, 1399 Intent intent, int requestCode, Bundle options) { 1400 IApplicationThread whoThread = (IApplicationThread) contextThread; 1401 if (mActivityMonitors != null) { 1402 synchronized (mSync) { 1403 final int N = mActivityMonitors.size(); 1404 for (int i=0; i<N; i++) { 1405 final ActivityMonitor am = mActivityMonitors.get(i); 1406 if (am.match(who, null, intent)) { 1407 am.mHits++; 1408 if (am.isBlocking()) { 1409 return requestCode >= 0 ? am.getResult() : null; 1410 } 1411 break; 1412 } 1413 } 1414 } 1415 } 1416 try { 1417 intent.migrateExtraStreamToClipData(); 1418 intent.prepareToLeaveProcess(); 1419 int result = ActivityManagerNative.getDefault() 1420 .startActivity(whoThread, who.getBasePackageName(), intent, 1421 intent.resolveTypeIfNeeded(who.getContentResolver()), 1422 token, target != null ? target.mEmbeddedID : null, 1423 requestCode, 0, null, null, options); 1424 checkStartActivityResult(result, intent); 1425 } catch (RemoteException e) { 1426 } 1427 return null; 1428 } 1429 1430 /** 1431 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)}, 1432 * but accepts an array of activities to be started. Note that active 1433 * {@link ActivityMonitor} objects only match against the first activity in 1434 * the array. 1435 * 1436 * {@hide} 1437 */ 1438 public void execStartActivities(Context who, IBinder contextThread, 1439 IBinder token, Activity target, Intent[] intents, Bundle options) { 1440 execStartActivitiesAsUser(who, contextThread, token, target, intents, options, 1441 UserHandle.myUserId()); 1442 } 1443 1444 /** 1445 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)}, 1446 * but accepts an array of activities to be started. Note that active 1447 * {@link ActivityMonitor} objects only match against the first activity in 1448 * the array. 1449 * 1450 * {@hide} 1451 */ 1452 public void execStartActivitiesAsUser(Context who, IBinder contextThread, 1453 IBinder token, Activity target, Intent[] intents, Bundle options, 1454 int userId) { 1455 IApplicationThread whoThread = (IApplicationThread) contextThread; 1456 if (mActivityMonitors != null) { 1457 synchronized (mSync) { 1458 final int N = mActivityMonitors.size(); 1459 for (int i=0; i<N; i++) { 1460 final ActivityMonitor am = mActivityMonitors.get(i); 1461 if (am.match(who, null, intents[0])) { 1462 am.mHits++; 1463 if (am.isBlocking()) { 1464 return; 1465 } 1466 break; 1467 } 1468 } 1469 } 1470 } 1471 try { 1472 String[] resolvedTypes = new String[intents.length]; 1473 for (int i=0; i<intents.length; i++) { 1474 intents[i].migrateExtraStreamToClipData(); 1475 intents[i].prepareToLeaveProcess(); 1476 resolvedTypes[i] = intents[i].resolveTypeIfNeeded(who.getContentResolver()); 1477 } 1478 int result = ActivityManagerNative.getDefault() 1479 .startActivities(whoThread, who.getBasePackageName(), intents, resolvedTypes, 1480 token, options, userId); 1481 checkStartActivityResult(result, intents[0]); 1482 } catch (RemoteException e) { 1483 } 1484 } 1485 1486 /** 1487 * Like {@link #execStartActivity(android.content.Context, android.os.IBinder, 1488 * android.os.IBinder, Fragment, android.content.Intent, int, android.os.Bundle)}, 1489 * but for calls from a {#link Fragment}. 1490 * 1491 * @param who The Context from which the activity is being started. 1492 * @param contextThread The main thread of the Context from which the activity 1493 * is being started. 1494 * @param token Internal token identifying to the system who is starting 1495 * the activity; may be null. 1496 * @param target Which fragment is performing the start (and thus receiving 1497 * any result). 1498 * @param intent The actual Intent to start. 1499 * @param requestCode Identifier for this request's result; less than zero 1500 * if the caller is not expecting a result. 1501 * 1502 * @return To force the return of a particular result, return an 1503 * ActivityResult object containing the desired data; otherwise 1504 * return null. The default implementation always returns null. 1505 * 1506 * @throws android.content.ActivityNotFoundException 1507 * 1508 * @see Activity#startActivity(Intent) 1509 * @see Activity#startActivityForResult(Intent, int) 1510 * @see Activity#startActivityFromChild 1511 * 1512 * {@hide} 1513 */ 1514 public ActivityResult execStartActivity( 1515 Context who, IBinder contextThread, IBinder token, Fragment target, 1516 Intent intent, int requestCode, Bundle options) { 1517 IApplicationThread whoThread = (IApplicationThread) contextThread; 1518 if (mActivityMonitors != null) { 1519 synchronized (mSync) { 1520 final int N = mActivityMonitors.size(); 1521 for (int i=0; i<N; i++) { 1522 final ActivityMonitor am = mActivityMonitors.get(i); 1523 if (am.match(who, null, intent)) { 1524 am.mHits++; 1525 if (am.isBlocking()) { 1526 return requestCode >= 0 ? am.getResult() : null; 1527 } 1528 break; 1529 } 1530 } 1531 } 1532 } 1533 try { 1534 intent.migrateExtraStreamToClipData(); 1535 intent.prepareToLeaveProcess(); 1536 int result = ActivityManagerNative.getDefault() 1537 .startActivity(whoThread, who.getBasePackageName(), intent, 1538 intent.resolveTypeIfNeeded(who.getContentResolver()), 1539 token, target != null ? target.mWho : null, 1540 requestCode, 0, null, null, options); 1541 checkStartActivityResult(result, intent); 1542 } catch (RemoteException e) { 1543 } 1544 return null; 1545 } 1546 1547 /** 1548 * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)}, 1549 * but for starting as a particular user. 1550 * 1551 * @param who The Context from which the activity is being started. 1552 * @param contextThread The main thread of the Context from which the activity 1553 * is being started. 1554 * @param token Internal token identifying to the system who is starting 1555 * the activity; may be null. 1556 * @param target Which fragment is performing the start (and thus receiving 1557 * any result). 1558 * @param intent The actual Intent to start. 1559 * @param requestCode Identifier for this request's result; less than zero 1560 * if the caller is not expecting a result. 1561 * 1562 * @return To force the return of a particular result, return an 1563 * ActivityResult object containing the desired data; otherwise 1564 * return null. The default implementation always returns null. 1565 * 1566 * @throws android.content.ActivityNotFoundException 1567 * 1568 * @see Activity#startActivity(Intent) 1569 * @see Activity#startActivityForResult(Intent, int) 1570 * @see Activity#startActivityFromChild 1571 * 1572 * {@hide} 1573 */ 1574 public ActivityResult execStartActivity( 1575 Context who, IBinder contextThread, IBinder token, Activity target, 1576 Intent intent, int requestCode, Bundle options, UserHandle user) { 1577 IApplicationThread whoThread = (IApplicationThread) contextThread; 1578 if (mActivityMonitors != null) { 1579 synchronized (mSync) { 1580 final int N = mActivityMonitors.size(); 1581 for (int i=0; i<N; i++) { 1582 final ActivityMonitor am = mActivityMonitors.get(i); 1583 if (am.match(who, null, intent)) { 1584 am.mHits++; 1585 if (am.isBlocking()) { 1586 return requestCode >= 0 ? am.getResult() : null; 1587 } 1588 break; 1589 } 1590 } 1591 } 1592 } 1593 try { 1594 intent.migrateExtraStreamToClipData(); 1595 intent.prepareToLeaveProcess(); 1596 int result = ActivityManagerNative.getDefault() 1597 .startActivityAsUser(whoThread, who.getBasePackageName(), intent, 1598 intent.resolveTypeIfNeeded(who.getContentResolver()), 1599 token, target != null ? target.mEmbeddedID : null, 1600 requestCode, 0, null, null, options, user.getIdentifier()); 1601 checkStartActivityResult(result, intent); 1602 } catch (RemoteException e) { 1603 } 1604 return null; 1605 } 1606 1607 /*package*/ final void init(ActivityThread thread, 1608 Context instrContext, Context appContext, ComponentName component, 1609 IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection) { 1610 mThread = thread; 1611 mMessageQueue = mThread.getLooper().myQueue(); 1612 mInstrContext = instrContext; 1613 mAppContext = appContext; 1614 mComponent = component; 1615 mWatcher = watcher; 1616 mUiAutomationConnection = uiAutomationConnection; 1617 } 1618 1619 /*package*/ static void checkStartActivityResult(int res, Object intent) { 1620 if (res >= ActivityManager.START_SUCCESS) { 1621 return; 1622 } 1623 1624 switch (res) { 1625 case ActivityManager.START_INTENT_NOT_RESOLVED: 1626 case ActivityManager.START_CLASS_NOT_FOUND: 1627 if (intent instanceof Intent && ((Intent)intent).getComponent() != null) 1628 throw new ActivityNotFoundException( 1629 "Unable to find explicit activity class " 1630 + ((Intent)intent).getComponent().toShortString() 1631 + "; have you declared this activity in your AndroidManifest.xml?"); 1632 throw new ActivityNotFoundException( 1633 "No Activity found to handle " + intent); 1634 case ActivityManager.START_PERMISSION_DENIED: 1635 throw new SecurityException("Not allowed to start activity " 1636 + intent); 1637 case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT: 1638 throw new AndroidRuntimeException( 1639 "FORWARD_RESULT_FLAG used while also requesting a result"); 1640 case ActivityManager.START_NOT_ACTIVITY: 1641 throw new IllegalArgumentException( 1642 "PendingIntent is not an activity"); 1643 default: 1644 throw new AndroidRuntimeException("Unknown error code " 1645 + res + " when starting " + intent); 1646 } 1647 } 1648 1649 private final void validateNotAppThread() { 1650 if (Looper.myLooper() == Looper.getMainLooper()) { 1651 throw new RuntimeException( 1652 "This method can not be called from the main application thread"); 1653 } 1654 } 1655 1656 /** 1657 * Gets the {@link UiAutomation} instance. 1658 * <p> 1659 * <strong>Note:</strong> The APIs exposed via the returned {@link UiAutomation} 1660 * work across application boundaries while the APIs exposed by the instrumentation 1661 * do not. For example, {@link Instrumentation#sendPointerSync(MotionEvent)} will 1662 * not allow you to inject the event in an app different from the instrumentation 1663 * target, while {@link UiAutomation#injectInputEvent(android.view.InputEvent, boolean)} 1664 * will work regardless of the current application. 1665 * </p> 1666 * <p> 1667 * A typical test case should be using either the {@link UiAutomation} or 1668 * {@link Instrumentation} APIs. Using both APIs at the same time is not 1669 * a mistake by itself but a client has to be aware of the APIs limitations. 1670 * </p> 1671 * @return The UI automation instance. 1672 * 1673 * @see UiAutomation 1674 */ 1675 public UiAutomation getUiAutomation() { 1676 if (mUiAutomationConnection != null) { 1677 if (mUiAutomation == null) { 1678 mUiAutomation = new UiAutomation(getTargetContext().getMainLooper(), 1679 mUiAutomationConnection); 1680 mUiAutomation.connect(); 1681 } 1682 return mUiAutomation; 1683 } 1684 return null; 1685 } 1686 1687 private final class InstrumentationThread extends Thread { 1688 public InstrumentationThread(String name) { 1689 super(name); 1690 } 1691 public void run() { 1692 try { 1693 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 1694 } catch (RuntimeException e) { 1695 Log.w(TAG, "Exception setting priority of instrumentation thread " 1696 + Process.myTid(), e); 1697 } 1698 if (mAutomaticPerformanceSnapshots) { 1699 startPerformanceSnapshot(); 1700 } 1701 onStart(); 1702 } 1703 } 1704 1705 private static final class EmptyRunnable implements Runnable { 1706 public void run() { 1707 } 1708 } 1709 1710 private static final class SyncRunnable implements Runnable { 1711 private final Runnable mTarget; 1712 private boolean mComplete; 1713 1714 public SyncRunnable(Runnable target) { 1715 mTarget = target; 1716 } 1717 1718 public void run() { 1719 mTarget.run(); 1720 synchronized (this) { 1721 mComplete = true; 1722 notifyAll(); 1723 } 1724 } 1725 1726 public void waitForComplete() { 1727 synchronized (this) { 1728 while (!mComplete) { 1729 try { 1730 wait(); 1731 } catch (InterruptedException e) { 1732 } 1733 } 1734 } 1735 } 1736 } 1737 1738 private static final class ActivityWaiter { 1739 public final Intent intent; 1740 public Activity activity; 1741 1742 public ActivityWaiter(Intent _intent) { 1743 intent = _intent; 1744 } 1745 } 1746 1747 private final class ActivityGoing implements MessageQueue.IdleHandler { 1748 private final ActivityWaiter mWaiter; 1749 1750 public ActivityGoing(ActivityWaiter waiter) { 1751 mWaiter = waiter; 1752 } 1753 1754 public final boolean queueIdle() { 1755 synchronized (mSync) { 1756 mWaitingActivities.remove(mWaiter); 1757 mSync.notifyAll(); 1758 } 1759 return false; 1760 } 1761 } 1762 1763 private static final class Idler implements MessageQueue.IdleHandler { 1764 private final Runnable mCallback; 1765 private boolean mIdle; 1766 1767 public Idler(Runnable callback) { 1768 mCallback = callback; 1769 mIdle = false; 1770 } 1771 1772 public final boolean queueIdle() { 1773 if (mCallback != null) { 1774 mCallback.run(); 1775 } 1776 synchronized (this) { 1777 mIdle = true; 1778 notifyAll(); 1779 } 1780 return false; 1781 } 1782 1783 public void waitForIdle() { 1784 synchronized (this) { 1785 while (!mIdle) { 1786 try { 1787 wait(); 1788 } catch (InterruptedException e) { 1789 } 1790 } 1791 } 1792 } 1793 } 1794 } 1795