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