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