Merge "Updating the monkey to use a dedicated UI test bridge."
This commit is contained in:
committed by
Android (Google) Code Review
commit
6848f33575
@@ -18,49 +18,33 @@ package com.android.commands.monkey;
|
|||||||
|
|
||||||
import static com.android.commands.monkey.MonkeySourceNetwork.EARG;
|
import static com.android.commands.monkey.MonkeySourceNetwork.EARG;
|
||||||
|
|
||||||
import android.accessibilityservice.IAccessibilityServiceConnection;
|
import android.accessibilityservice.UiTestAutomationBridge;
|
||||||
import android.accessibilityservice.IEventListener;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.pm.IPackageManager;
|
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.IPackageManager;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.ServiceManager;
|
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.SystemClock;
|
import android.os.ServiceManager;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.accessibility.AccessibilityInteractionClient;
|
|
||||||
import android.view.accessibility.AccessibilityNodeInfo;
|
|
||||||
import android.view.accessibility.IAccessibilityManager;
|
|
||||||
import android.view.accessibility.AccessibilityEvent;
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
|
import android.view.accessibility.AccessibilityNodeInfo;
|
||||||
import dalvik.system.DexClassLoader;
|
|
||||||
|
|
||||||
import com.android.commands.monkey.MonkeySourceNetwork.CommandQueue;
|
import com.android.commands.monkey.MonkeySourceNetwork.CommandQueue;
|
||||||
import com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommand;
|
import com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommand;
|
||||||
import com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommandReturn;
|
import com.android.commands.monkey.MonkeySourceNetwork.MonkeyCommandReturn;
|
||||||
|
|
||||||
|
import dalvik.system.DexClassLoader;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ArrayList;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class that enables Monkey to perform view introspection when issued Monkey Network
|
* Utility class that enables Monkey to perform view introspection when issued Monkey Network
|
||||||
* Script commands over the network.
|
* Script commands over the network.
|
||||||
*/
|
*/
|
||||||
public class MonkeySourceNetworkViews {
|
public class MonkeySourceNetworkViews {
|
||||||
private static final String TAG = "MonkeyViews";
|
protected static UiTestAutomationBridge sUiTestAutomationBridge;
|
||||||
|
|
||||||
private static final int TIMEOUT_REGISTER_EVENT_LISTENER = 2000;
|
|
||||||
|
|
||||||
private static final int NO_ID = -1;
|
|
||||||
|
|
||||||
private static volatile AtomicReference<AccessibilityEvent> sLastAccessibilityEvent
|
|
||||||
= new AtomicReference<AccessibilityEvent>();
|
|
||||||
protected static int sConnectionId;
|
|
||||||
private static IPackageManager sPm =
|
private static IPackageManager sPm =
|
||||||
IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
|
IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
|
||||||
private static Map<String, Class<?>> sClassMap = new HashMap<String, Class<?>>();
|
private static Map<String, Class<?>> sClassMap = new HashMap<String, Class<?>>();
|
||||||
@@ -100,77 +84,15 @@ public class MonkeySourceNetworkViews {
|
|||||||
COMMAND_MAP.put("getaccessibilityids", new GetAccessibilityIds());
|
COMMAND_MAP.put("getaccessibilityids", new GetAccessibilityIds());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int getConnection() throws RemoteException {
|
|
||||||
if (sConnectionId != NO_ID) {
|
|
||||||
return sConnectionId;
|
|
||||||
}
|
|
||||||
IEventListener listener = new IEventListener.Stub() {
|
|
||||||
public void setConnection(IAccessibilityServiceConnection connection,
|
|
||||||
int connectionId) {
|
|
||||||
sConnectionId = connectionId;
|
|
||||||
if (connection != null) {
|
|
||||||
AccessibilityInteractionClient.getInstance().addConnection(connectionId,
|
|
||||||
connection);
|
|
||||||
} else {
|
|
||||||
AccessibilityInteractionClient.getInstance().removeConnection(connectionId);
|
|
||||||
}
|
|
||||||
synchronized (MonkeySourceNetworkViews.class) {
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onInterrupt() {}
|
|
||||||
|
|
||||||
public void onAccessibilityEvent(AccessibilityEvent event) {
|
|
||||||
Log.d(TAG, "Accessibility Event");
|
|
||||||
sLastAccessibilityEvent.set(AccessibilityEvent.obtain(event));
|
|
||||||
synchronized (MonkeySourceNetworkViews.class) {
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
|
|
||||||
ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
|
|
||||||
|
|
||||||
final long beginTime = SystemClock.uptimeMillis();
|
|
||||||
synchronized (MonkeySourceNetworkViews.class) {
|
|
||||||
manager.registerEventListener(listener);
|
|
||||||
while (true) {
|
|
||||||
if (sConnectionId != NO_ID) {
|
|
||||||
return sConnectionId;
|
|
||||||
}
|
|
||||||
final long elapsedTime = (SystemClock.uptimeMillis() - beginTime);
|
|
||||||
final long remainingTime = TIMEOUT_REGISTER_EVENT_LISTENER - elapsedTime;
|
|
||||||
if (remainingTime <= 0) {
|
|
||||||
if (sConnectionId == NO_ID) {
|
|
||||||
throw new IllegalStateException("Cound not register IEventListener.");
|
|
||||||
}
|
|
||||||
return sConnectionId;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
MonkeySourceNetworkViews.class.wait(remainingTime);
|
|
||||||
} catch (InterruptedException ie) {
|
|
||||||
/* ignore */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the event listener for AccessibilityEvents.
|
* Registers the event listener for AccessibilityEvents.
|
||||||
* Also sets up a communication connection so we can query the
|
* Also sets up a communication connection so we can query the
|
||||||
* accessibility service.
|
* accessibility service.
|
||||||
*/
|
*/
|
||||||
public static void setup() {
|
public static void setup() {
|
||||||
try {
|
sUiTestAutomationBridge = new UiTestAutomationBridge();
|
||||||
sConnectionId = getConnection();
|
sUiTestAutomationBridge.connect();
|
||||||
} catch (RemoteException re) {
|
|
||||||
Log.e(TAG,"Remote Exception encountered when"
|
|
||||||
+ " attempting to connect to Accessibility Service");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the ID class for the given package.
|
* Get the ID class for the given package.
|
||||||
@@ -181,7 +103,7 @@ public class MonkeySourceNetworkViews {
|
|||||||
* @return The ID class for the given package
|
* @return The ID class for the given package
|
||||||
*/
|
*/
|
||||||
private static Class<?> getIdClass(String packageName, String sourceDir)
|
private static Class<?> getIdClass(String packageName, String sourceDir)
|
||||||
throws RemoteException, ClassNotFoundException {
|
throws ClassNotFoundException {
|
||||||
// This kind of reflection is expensive, so let's only do it
|
// This kind of reflection is expensive, so let's only do it
|
||||||
// if we need to
|
// if we need to
|
||||||
Class<?> klass = sClassMap.get(packageName);
|
Class<?> klass = sClassMap.get(packageName);
|
||||||
@@ -240,15 +162,15 @@ public class MonkeySourceNetworkViews {
|
|||||||
String windowString, String viewString) {
|
String windowString, String viewString) {
|
||||||
int windowId = Integer.parseInt(windowString);
|
int windowId = Integer.parseInt(windowString);
|
||||||
int viewId = Integer.parseInt(viewString);
|
int viewId = Integer.parseInt(viewString);
|
||||||
return AccessibilityInteractionClient.getInstance()
|
return sUiTestAutomationBridge.findAccessibilityNodeInfoByAccessibilityId(windowId,
|
||||||
.findAccessibilityNodeInfoByAccessibilityId(sConnectionId, windowId, viewId);
|
viewId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AccessibilityNodeInfo getNodeByViewId(String viewId, AccessibilityEvent event)
|
private static AccessibilityNodeInfo getNodeByViewId(String viewId, AccessibilityEvent event)
|
||||||
throws MonkeyViewException {
|
throws MonkeyViewException {
|
||||||
int id = getId(viewId, event);
|
int id = getId(viewId, event);
|
||||||
return AccessibilityInteractionClient.getInstance()
|
return sUiTestAutomationBridge.findAccessibilityNodeInfoByViewId(
|
||||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, id);
|
UiTestAutomationBridge.ACTIVE_WINDOW_ID, UiTestAutomationBridge.ROOT_NODE_ID, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -259,11 +181,10 @@ public class MonkeySourceNetworkViews {
|
|||||||
//listviews
|
//listviews
|
||||||
public MonkeyCommandReturn translateCommand(List<String> command,
|
public MonkeyCommandReturn translateCommand(List<String> command,
|
||||||
CommandQueue queue) {
|
CommandQueue queue) {
|
||||||
AccessibilityEvent lastEvent = sLastAccessibilityEvent.get();
|
AccessibilityEvent lastEvent = sUiTestAutomationBridge.getLastAccessibilityEvent();
|
||||||
if (lastEvent == null) {
|
if (lastEvent == null) {
|
||||||
return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
|
return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
|
||||||
}
|
}
|
||||||
lastEvent.setSealed(true);
|
|
||||||
AccessibilityNodeInfo node = lastEvent.getSource();
|
AccessibilityNodeInfo node = lastEvent.getSource();
|
||||||
/* Occasionally the API will generate an event with no source, which is essentially the
|
/* Occasionally the API will generate an event with no source, which is essentially the
|
||||||
* same as it generating no event at all */
|
* same as it generating no event at all */
|
||||||
@@ -300,14 +221,13 @@ public class MonkeySourceNetworkViews {
|
|||||||
public MonkeyCommandReturn translateCommand(List<String> command,
|
public MonkeyCommandReturn translateCommand(List<String> command,
|
||||||
CommandQueue queue) {
|
CommandQueue queue) {
|
||||||
if (command.size() > 2) {
|
if (command.size() > 2) {
|
||||||
if (sConnectionId < 0) {
|
if (!sUiTestAutomationBridge.isConnected()) {
|
||||||
return new MonkeyCommandReturn(false, NO_CONNECTION);
|
return new MonkeyCommandReturn(false, NO_CONNECTION);
|
||||||
}
|
}
|
||||||
AccessibilityEvent lastEvent = sLastAccessibilityEvent.get();
|
AccessibilityEvent lastEvent = sUiTestAutomationBridge.getLastAccessibilityEvent();
|
||||||
if (lastEvent == null) {
|
if (lastEvent == null) {
|
||||||
return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
|
return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
|
||||||
}
|
}
|
||||||
lastEvent.setSealed(true);
|
|
||||||
String idType = command.get(1);
|
String idType = command.get(1);
|
||||||
AccessibilityNodeInfo node;
|
AccessibilityNodeInfo node;
|
||||||
String viewQuery;
|
String viewQuery;
|
||||||
@@ -352,11 +272,10 @@ public class MonkeySourceNetworkViews {
|
|||||||
// getrootview
|
// getrootview
|
||||||
public MonkeyCommandReturn translateCommand(List<String> command,
|
public MonkeyCommandReturn translateCommand(List<String> command,
|
||||||
CommandQueue queue) {
|
CommandQueue queue) {
|
||||||
AccessibilityEvent lastEvent = sLastAccessibilityEvent.get();
|
AccessibilityEvent lastEvent = sUiTestAutomationBridge.getLastAccessibilityEvent();
|
||||||
if (lastEvent == null) {
|
if (lastEvent == null) {
|
||||||
return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
|
return new MonkeyCommandReturn(false, NO_ACCESSIBILITY_EVENT);
|
||||||
}
|
}
|
||||||
lastEvent.setSealed(true);
|
|
||||||
AccessibilityNodeInfo node = lastEvent.getSource();
|
AccessibilityNodeInfo node = lastEvent.getSource();
|
||||||
return (new GetAccessibilityIds()).query(node, new ArrayList<String>());
|
return (new GetAccessibilityIds()).query(node, new ArrayList<String>());
|
||||||
}
|
}
|
||||||
@@ -372,13 +291,14 @@ public class MonkeySourceNetworkViews {
|
|||||||
// getviewswithtext "some text here"
|
// getviewswithtext "some text here"
|
||||||
public MonkeyCommandReturn translateCommand(List<String> command,
|
public MonkeyCommandReturn translateCommand(List<String> command,
|
||||||
CommandQueue queue) {
|
CommandQueue queue) {
|
||||||
if (sConnectionId < 0) {
|
if (!sUiTestAutomationBridge.isConnected()) {
|
||||||
return new MonkeyCommandReturn(false, NO_CONNECTION);
|
return new MonkeyCommandReturn(false, NO_CONNECTION);
|
||||||
}
|
}
|
||||||
if (command.size() == 2) {
|
if (command.size() == 2) {
|
||||||
String text = command.get(1);
|
String text = command.get(1);
|
||||||
List<AccessibilityNodeInfo> nodes = AccessibilityInteractionClient.getInstance()
|
List<AccessibilityNodeInfo> nodes = sUiTestAutomationBridge
|
||||||
.findAccessibilityNodeInfosByTextInActiveWindow(sConnectionId, text);
|
.findAccessibilityNodeInfosByText(UiTestAutomationBridge.ACTIVE_WINDOW_ID,
|
||||||
|
UiTestAutomationBridge.ROOT_NODE_ID, text);
|
||||||
ViewIntrospectionCommand idGetter = new GetAccessibilityIds();
|
ViewIntrospectionCommand idGetter = new GetAccessibilityIds();
|
||||||
List<String> emptyArgs = new ArrayList<String>();
|
List<String> emptyArgs = new ArrayList<String>();
|
||||||
StringBuilder ids = new StringBuilder();
|
StringBuilder ids = new StringBuilder();
|
||||||
@@ -550,7 +470,6 @@ public class MonkeySourceNetworkViews {
|
|||||||
//queryview viewid button1 setfocused false
|
//queryview viewid button1 setfocused false
|
||||||
public MonkeyCommandReturn query(AccessibilityNodeInfo node,
|
public MonkeyCommandReturn query(AccessibilityNodeInfo node,
|
||||||
List<String> args) {
|
List<String> args) {
|
||||||
node.setSealed(true);
|
|
||||||
if (args.size() == 1) {
|
if (args.size() == 1) {
|
||||||
boolean actionPerformed;
|
boolean actionPerformed;
|
||||||
if (Boolean.valueOf(args.get(0))) {
|
if (Boolean.valueOf(args.get(0))) {
|
||||||
@@ -579,7 +498,7 @@ public class MonkeySourceNetworkViews {
|
|||||||
if (args.size() == 0) {
|
if (args.size() == 0) {
|
||||||
int viewId;
|
int viewId;
|
||||||
try {
|
try {
|
||||||
Class klass = node.getClass();
|
Class<?> klass = node.getClass();
|
||||||
Field field = klass.getDeclaredField("mAccessibilityViewId");
|
Field field = klass.getDeclaredField("mAccessibilityViewId");
|
||||||
field.setAccessible(true);
|
field.setAccessible(true);
|
||||||
viewId = ((Integer) field.get(node)).intValue();
|
viewId = ((Integer) field.get(node)).intValue();
|
||||||
|
|||||||
Reference in New Issue
Block a user