1 package com.android.uiautomator.core; 2 3 import android.accessibilityservice.AccessibilityServiceInfo; 4 import android.app.ActivityManager; 5 import android.app.ActivityManagerNative; 6 import android.app.IActivityController; 7 import android.app.IActivityManager; 8 import android.app.UiAutomation; 9 import android.app.UiAutomationConnection; 10 import android.content.Intent; 11 import android.os.HandlerThread; 12 import android.os.RemoteException; 13 14 /** 15 * @hide 16 */ 17 public class UiAutomationShellWrapper { 18 19 private static final String HANDLER_THREAD_NAME = "UiAutomatorHandlerThread"; 20 21 private final HandlerThread mHandlerThread = new HandlerThread(HANDLER_THREAD_NAME); 22 23 private UiAutomation mUiAutomation; 24 25 public void connect() { 26 if (mHandlerThread.isAlive()) { 27 throw new IllegalStateException("Already connected!"); 28 } 29 mHandlerThread.start(); 30 mUiAutomation = new UiAutomation(mHandlerThread.getLooper(), 31 new UiAutomationConnection()); 32 mUiAutomation.connect(); 33 } 34 35 /** 36 * Enable or disable monkey test mode. 37 * 38 * Setting test as "monkey" indicates to some applications that a test framework is 39 * running as a "monkey" type. Such applications may choose not to perform actions that 40 * do submits so to avoid allowing monkey tests from doing harm or performing annoying 41 * actions such as dialing 911 or posting messages to public forums, etc. 42 * 43 * @param isSet True to set as monkey test. False to set as regular functional test (default). 44 * @see {@link ActivityManager#isUserAMonkey()} 45 */ 46 public void setRunAsMonkey(boolean isSet) { 47 IActivityManager am = ActivityManagerNative.getDefault(); 48 if (am == null) { 49 throw new RuntimeException("Can't manage monkey status; is the system running?"); 50 } 51 try { 52 if (isSet) { 53 am.setActivityController(new DummyActivityController()); 54 } else { 55 am.setActivityController(null); 56 } 57 } catch (RemoteException e) { 58 throw new RuntimeException(e); 59 } 60 } 61 62 public void disconnect() { 63 if (!mHandlerThread.isAlive()) { 64 throw new IllegalStateException("Already disconnected!"); 65 } 66 mUiAutomation.disconnect(); 67 mHandlerThread.quit(); 68 } 69 70 public UiAutomation getUiAutomation() { 71 return mUiAutomation; 72 } 73 74 public void setCompressedLayoutHierarchy(boolean compressed) { 75 AccessibilityServiceInfo info = mUiAutomation.getServiceInfo(); 76 if (compressed) 77 info.flags &= ~AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 78 else 79 info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS; 80 mUiAutomation.setServiceInfo(info); 81 } 82 83 /** 84 * Dummy, no interference, activity controller. 85 */ 86 private class DummyActivityController extends IActivityController.Stub { 87 @Override 88 public boolean activityStarting(Intent intent, String pkg) throws RemoteException { 89 /* do nothing and let activity proceed normally */ 90 return true; 91 } 92 93 @Override 94 public boolean activityResuming(String pkg) throws RemoteException { 95 /* do nothing and let activity proceed normally */ 96 return true; 97 } 98 99 @Override 100 public boolean appCrashed(String processName, int pid, String shortMsg, String longMsg, 101 long timeMillis, String stackTrace) throws RemoteException { 102 /* do nothing and let activity proceed normally */ 103 return true; 104 } 105 106 @Override 107 public int appEarlyNotResponding(String processName, int pid, String annotation) 108 throws RemoteException { 109 /* do nothing and let activity proceed normally */ 110 return 0; 111 } 112 113 @Override 114 public int appNotResponding(String processName, int pid, String processStats) 115 throws RemoteException { 116 /* do nothing and let activity proceed normally */ 117 return 0; 118 } 119 120 @Override 121 public int systemNotResponding(String message) 122 throws RemoteException { 123 /* do nothing and let system proceed normally */ 124 return 0; 125 } 126 } 127 } 128