Merge "Speedup the accessibility window querying APIs and clean up."

This commit is contained in:
Svetoslav Ganov
2012-02-01 13:45:24 -08:00
committed by Android (Google) Code Review
15 changed files with 1119 additions and 341 deletions

View File

@ -14,12 +14,12 @@
package android.accessibilityservice;
import com.android.frameworks.coretests.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import com.android.frameworks.coretests.R;
/**
* Activity for testing the accessibility APIs for "interrogation" of
* the screen content. These APIs allow exploring the screen and

View File

@ -14,26 +14,21 @@
package android.accessibilityservice;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_SELECTION;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_FOCUS;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_SELECT;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_SELECTION;
import android.content.Context;
import android.graphics.Rect;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityInteractionClient;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.IAccessibilityManager;
import com.android.frameworks.coretests.R;
import com.android.internal.util.Predicate;
import java.util.ArrayList;
import java.util.LinkedList;
@ -48,21 +43,15 @@ import java.util.Queue;
*/
public class InterrogationActivityTest
extends ActivityInstrumentationTestCase2<InterrogationActivity> {
private static final boolean DEBUG = true;
private static final boolean DEBUG = false;
private static String LOG_TAG = "InterrogationActivityTest";
// Timeout before give up wait for the system to process an accessibility setting change.
private static final int TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING = 2000;
// Timeout for the accessibility state of an Activity to be fully initialized.
private static final int TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS = 100;
private static final int TIMEOUT_PROPAGATE_ACCESSIBILITY_EVENT_MILLIS = 5000;
// Handle to a connection to the AccessibilityManagerService
private static int sConnectionId = View.NO_ID;
// The last received accessibility event
private volatile AccessibilityEvent mLastAccessibilityEvent;
private UiTestAutomationBridge mUiTestAutomationBridge;
public InterrogationActivityTest() {
super(InterrogationActivity.class);
@ -70,16 +59,39 @@ public class InterrogationActivityTest
@Override
public void setUp() throws Exception {
ensureConnection();
bringUpActivityWithInitalizedAccessbility();
super.setUp();
mUiTestAutomationBridge = new UiTestAutomationBridge();
mUiTestAutomationBridge.connect();
mUiTestAutomationBridge.executeCommandAndWaitForAccessibilityEvent(new Runnable() {
// wait for the first accessibility event
@Override
public void run() {
// bring up the activity
getActivity();
}
},
new Predicate<AccessibilityEvent>() {
@Override
public boolean apply(AccessibilityEvent event) {
return (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
&& event.getPackageName().equals(getActivity().getPackageName()));
}
},
TIMEOUT_PROPAGATE_ACCESSIBILITY_EVENT_MILLIS);
}
@Override
public void tearDown() throws Exception {
mUiTestAutomationBridge.disconnect();
super.tearDown();
}
@LargeTest
public void testFindAccessibilityNodeInfoByViewId() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
AccessibilityNodeInfo button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertNotNull(button);
assertEquals(0, button.getChildCount());
@ -125,8 +137,8 @@ public class InterrogationActivityTest
final long startTimeMillis = SystemClock.uptimeMillis();
try {
// find a view by text
List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfosByTextInActiveWindow(sConnectionId, "butto");
List<AccessibilityNodeInfo> buttons = mUiTestAutomationBridge
.findAccessibilityNodeInfosByTextInActiveWindow("butto");
assertEquals(9, buttons.size());
} finally {
if (DEBUG) {
@ -141,12 +153,9 @@ public class InterrogationActivityTest
public void testFindAccessibilityNodeInfoByViewTextContentDescription() throws Exception {
final long startTimeMillis = SystemClock.uptimeMillis();
try {
bringUpActivityWithInitalizedAccessbility();
// find a view by text
List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfosByTextInActiveWindow(sConnectionId,
"contentDescription");
List<AccessibilityNodeInfo> buttons = mUiTestAutomationBridge
.findAccessibilityNodeInfosByTextInActiveWindow("contentDescription");
assertEquals(1, buttons.size());
} finally {
if (DEBUG) {
@ -177,8 +186,8 @@ public class InterrogationActivityTest
classNameAndTextList.add("android.widget.ButtonButton8");
classNameAndTextList.add("android.widget.ButtonButton9");
AccessibilityNodeInfo root = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.root);
AccessibilityNodeInfo root = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.root);
assertNotNull("We must find the existing root.", root);
Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
@ -216,16 +225,16 @@ public class InterrogationActivityTest
final long startTimeMillis = SystemClock.uptimeMillis();
try {
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
AccessibilityNodeInfo button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isFocused());
// focus the view
assertTrue(button.performAction(ACTION_FOCUS));
// find the view again and make sure it is focused
button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertTrue(button.isFocused());
} finally {
if (DEBUG) {
@ -240,24 +249,24 @@ public class InterrogationActivityTest
final long startTimeMillis = SystemClock.uptimeMillis();
try {
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
AccessibilityNodeInfo button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isFocused());
// focus the view
assertTrue(button.performAction(ACTION_FOCUS));
// find the view again and make sure it is focused
button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertTrue(button.isFocused());
// unfocus the view
assertTrue(button.performAction(ACTION_CLEAR_FOCUS));
// find the view again and make sure it is not focused
button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isFocused());
} finally {
if (DEBUG) {
@ -273,16 +282,16 @@ public class InterrogationActivityTest
final long startTimeMillis = SystemClock.uptimeMillis();
try {
// find a view and make sure it is not selected
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
AccessibilityNodeInfo button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isSelected());
// select the view
assertTrue(button.performAction(ACTION_SELECT));
// find the view again and make sure it is selected
button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertTrue(button.isSelected());
} finally {
if (DEBUG) {
@ -297,24 +306,24 @@ public class InterrogationActivityTest
final long startTimeMillis = SystemClock.uptimeMillis();
try {
// find a view and make sure it is not selected
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
AccessibilityNodeInfo button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isSelected());
// select the view
assertTrue(button.performAction(ACTION_SELECT));
// find the view again and make sure it is selected
button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertTrue(button.isSelected());
// unselect the view
assertTrue(button.performAction(ACTION_CLEAR_SELECTION));
// find the view again and make sure it is not selected
button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isSelected());
} finally {
if (DEBUG) {
@ -330,23 +339,33 @@ public class InterrogationActivityTest
final long startTimeMillis = SystemClock.uptimeMillis();
try {
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
assertFalse(button.isSelected());
final AccessibilityNodeInfo button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertFalse(button.isFocused());
// focus the view
assertTrue(button.performAction(ACTION_FOCUS));
synchronized (this) {
try {
wait(TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS);
} catch (InterruptedException ie) {
/* ignore */
AccessibilityEvent event = mUiTestAutomationBridge
.executeCommandAndWaitForAccessibilityEvent(new Runnable() {
@Override
public void run() {
// focus the view
assertTrue(button.performAction(ACTION_FOCUS));
}
}
},
new Predicate<AccessibilityEvent>() {
@Override
public boolean apply(AccessibilityEvent event) {
return (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED
&& event.getPackageName().equals(getActivity().getPackageName())
&& event.getText().get(0).equals(button.getText()));
}
},
TIMEOUT_PROPAGATE_ACCESSIBILITY_EVENT_MILLIS);
// check the last event
assertNotNull(event);
// check that last event source
AccessibilityNodeInfo source = mLastAccessibilityEvent.getSource();
AccessibilityNodeInfo source = event.getSource();
assertNotNull(source);
// bounds
@ -389,8 +408,9 @@ public class InterrogationActivityTest
final long startTimeMillis = SystemClock.uptimeMillis();
try {
// find a view and make sure it is not focused
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
.findAccessibilityNodeInfoByViewIdInActiveWindow(sConnectionId, R.id.button5);
AccessibilityNodeInfo button = mUiTestAutomationBridge
.findAccessibilityNodeInfoByViewIdInActiveWindow(R.id.button5);
assertNotNull(button);
AccessibilityNodeInfo parent = button.getParent();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
@ -410,71 +430,4 @@ public class InterrogationActivityTest
}
}
}
private void bringUpActivityWithInitalizedAccessbility() {
mLastAccessibilityEvent = null;
// bring up the activity
getActivity();
final long startTimeMillis = SystemClock.uptimeMillis();
while (true) {
if (mLastAccessibilityEvent != null) {
final int eventType = mLastAccessibilityEvent.getEventType();
if (eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
return;
}
}
final long remainingTimeMillis = TIMEOUT_ACCESSIBLITY_STATE_INITIALIZED_MILLIS
- (SystemClock.uptimeMillis() - startTimeMillis);
if (remainingTimeMillis <= 0) {
return;
}
synchronized (this) {
try {
wait(remainingTimeMillis);
} catch (InterruptedException e) {
/* ignore */
}
}
}
}
private void ensureConnection() throws Exception {
if (sConnectionId == View.NO_ID) {
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 (this) {
notifyAll();
}
}
public void onInterrupt() {}
public void onAccessibilityEvent(AccessibilityEvent event) {
mLastAccessibilityEvent = AccessibilityEvent.obtain(event);
synchronized (this) {
notifyAll();
}
}
};
AccessibilityManager accessibilityManager =
AccessibilityManager.getInstance(getInstrumentation().getContext());
synchronized (this) {
IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
manager.registerEventListener(listener);
wait(TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING);
}
}
}
}