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