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