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 Instrumentation()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 */ onCreate(Bundle arguments)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 */ start()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 */ onStart()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 */ onException(Object obj, Throwable e)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 */ sendStatus(int resultCode, Bundle results)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 */ finish(int resultCode, Bundle results)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 setAutomaticPerformanceSnapshots()205 public void setAutomaticPerformanceSnapshots() { 206 mAutomaticPerformanceSnapshots = true; 207 mPerformanceCollector = new PerformanceCollector(); 208 } 209 startPerformanceSnapshot()210 public void startPerformanceSnapshot() { 211 if (!isProfiling()) { 212 mPerformanceCollector.beginSnapshot(null); 213 } 214 } 215 endPerformanceSnapshot()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 */ onDestroy()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 */ getContext()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 */ getComponentName()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 */ getTargetContext()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 */ isProfiling()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 */ startProfiling()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 */ stopProfiling()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 */ setInTouchMode(boolean inTouch)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 */ waitForIdle(Runnable recipient)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 */ waitForIdleSync()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 */ runOnMainSync(Runnable runner)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 */ startActivitySync(Intent intent)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 */ ActivityMonitor( IntentFilter which, ActivityResult result, boolean block)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 */ ActivityMonitor( String cls, ActivityResult result, boolean block)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 */ getFilter()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 */ getResult()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 */ isBlocking()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 */ getHits()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 */ getLastActivity()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 */ waitForActivity()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 */ waitForActivityWithTimeout(long timeOut)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 match(Context who, Activity activity, Intent intent)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 */ addMonitor(ActivityMonitor monitor)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 */ addMonitor( IntentFilter filter, ActivityResult result, boolean block)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 */ addMonitor( String cls, ActivityResult result, boolean block)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 */ checkMonitorHit(ActivityMonitor monitor, int minHits)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 */ waitForMonitor(ActivityMonitor monitor)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 */ waitForMonitorWithTimeout(ActivityMonitor monitor, long timeOut)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 */ removeMonitor(ActivityMonitor monitor)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 */ invokeMenuActionSync(Activity targetActivity, int id, int flag)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 */ invokeContextMenuAction(Activity targetActivity, int id, int flag)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 */ sendStringSync(String text)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 */ sendKeySync(KeyEvent event)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 */ sendKeyDownUpSync(int key)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 */ sendCharacterSync(int keyCode)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 */ sendPointerSync(MotionEvent event)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 */ sendTrackballEventSync(MotionEvent event)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 */ newApplication(ClassLoader cl, String className, Context context)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 */ newApplication(Class<?> clazz, Context context)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 */ callApplicationOnCreate(Application app)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 */ newActivity(Class<?> clazz, Context context, IBinder token, Application application, Intent intent, ActivityInfo info, CharSequence title, Activity parent, String id, Object lastNonConfigurationInstance)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 */ newActivity(ClassLoader cl, String className, Intent intent)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 prePerformCreate(Activity activity)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 postPerformCreate(Activity activity)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 */ callActivityOnCreate(Activity activity, Bundle icicle)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 */ callActivityOnCreate(Activity activity, Bundle icicle, PersistableBundle persistentState)1118 public void callActivityOnCreate(Activity activity, Bundle icicle, 1119 PersistableBundle persistentState) { 1120 prePerformCreate(activity); 1121 activity.performCreate(icicle, persistentState); 1122 postPerformCreate(activity); 1123 } 1124 callActivityOnDestroy(Activity activity)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 */ callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState)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 */ callActivityOnRestoreInstanceState(Activity activity, Bundle savedInstanceState, PersistableBundle persistentState)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 */ callActivityOnPostCreate(Activity activity, Bundle icicle)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 */ callActivityOnPostCreate(Activity activity, Bundle icicle, PersistableBundle persistentState)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 */ callActivityOnNewIntent(Activity activity, Intent intent)1211 public void callActivityOnNewIntent(Activity activity, Intent intent) { 1212 activity.onNewIntent(intent); 1213 } 1214 1215 /** 1216 * @hide 1217 */ callActivityOnNewIntent(Activity activity, ReferrerIntent intent)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 */ callActivityOnStart(Activity activity)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 */ callActivityOnRestart(Activity activity)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 */ callActivityOnResume(Activity activity)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 */ callActivityOnStop(Activity activity)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 */ callActivityOnSaveInstanceState(Activity activity, Bundle outState)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 */ callActivityOnSaveInstanceState(Activity activity, Bundle outState, PersistableBundle outPersistentState)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 */ callActivityOnPause(Activity activity)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 */ callActivityOnUserLeaving(Activity activity)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 startAllocCounting()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 stopAllocCounting()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 */ addValue(String key, int value, Bundle results)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 */ getAllocCounts()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 */ getBinderCounts()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 */ ActivityResult(int resultCode, Intent resultData)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 */ getResultCode()1422 public int getResultCode() { 1423 return mResultCode; 1424 } 1425 1426 /** 1427 * Retrieve the data contained in this result. 1428 */ getResultData()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 */ execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options)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 */ execStartActivities(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options)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 */ execStartActivitiesAsUser(Context who, IBinder contextThread, IBinder token, Activity target, Intent[] intents, Bundle options, int userId)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 */ execStartActivity( Context who, IBinder contextThread, IBinder token, String target, Intent intent, int requestCode, Bundle options)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 */ execStartActivity( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options, UserHandle user)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 */ execStartActivityAsCaller( Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options, boolean ignoreTargetSecurity, int userId)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 */ execStartActivityFromAppTask( Context who, IBinder contextThread, IAppTask appTask, Intent intent, Bundle options)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 init(ActivityThread thread, Context instrContext, Context appContext, ComponentName component, IInstrumentationWatcher watcher, IUiAutomationConnection uiAutomationConnection)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 */ checkStartActivityResult(int res, Object intent)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 validateNotAppThread()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 */ getUiAutomation()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 { InstrumentationThread(String name)1866 public InstrumentationThread(String name) { 1867 super(name); 1868 } run()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 { run()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 SyncRunnable(Runnable target)1892 public SyncRunnable(Runnable target) { 1893 mTarget = target; 1894 } 1895 run()1896 public void run() { 1897 mTarget.run(); 1898 synchronized (this) { 1899 mComplete = true; 1900 notifyAll(); 1901 } 1902 } 1903 waitForComplete()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 ActivityWaiter(Intent _intent)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 ActivityGoing(ActivityWaiter waiter)1928 public ActivityGoing(ActivityWaiter waiter) { 1929 mWaiter = waiter; 1930 } 1931 queueIdle()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 Idler(Runnable callback)1945 public Idler(Runnable callback) { 1946 mCallback = callback; 1947 mIdle = false; 1948 } 1949 queueIdle()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 waitForIdle()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