Merge "Accessibility test automation API not working."
This commit is contained in:
committed by
Android (Google) Code Review
commit
31743d8cbb
@@ -19,14 +19,10 @@ import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_SELE
|
||||
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
|
||||
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_SELECT;
|
||||
|
||||
import com.android.frameworks.coretests.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.provider.Settings;
|
||||
import android.test.ActivityInstrumentationTestCase2;
|
||||
import android.test.suitebuilder.annotation.LargeTest;
|
||||
import android.util.Log;
|
||||
@@ -36,8 +32,8 @@ import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.accessibility.IAccessibilityManager;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import com.android.frameworks.coretests.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -55,14 +51,9 @@ public class InterrogationActivityTest
|
||||
|
||||
private static String LOG_TAG = "InterrogationActivityTest";
|
||||
|
||||
// Timeout before give up wait for the system to process an accessibility setting change.
|
||||
// Timeout before give up wait for the system to process an accessibility setting change.
|
||||
private static final int TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING = 2000;
|
||||
|
||||
// Helpers to figure out the first and last test methods
|
||||
// This is a workaround for the lack of such support in JUnit3
|
||||
private static int sTestMethodCount;
|
||||
private static int sExecutedTestMethodCount;
|
||||
|
||||
// Handle to a connection to the AccessibilityManagerService
|
||||
private static IAccessibilityServiceConnection sConnection;
|
||||
|
||||
@@ -71,19 +62,20 @@ public class InterrogationActivityTest
|
||||
|
||||
public InterrogationActivityTest() {
|
||||
super(InterrogationActivity.class);
|
||||
sTestMethodCount = getTestMethodCount();
|
||||
}
|
||||
|
||||
@LargeTest
|
||||
public void testFindAccessibilityNodeInfoByViewId() throws Exception {
|
||||
beforeClassIfNeeded();
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
try {
|
||||
// hook into the system first
|
||||
IAccessibilityServiceConnection connection = getConnection();
|
||||
|
||||
// bring up the activity
|
||||
getActivity();
|
||||
|
||||
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertNotNull(button);
|
||||
assertEquals(0, button.getChildCount());
|
||||
|
||||
@@ -116,7 +108,6 @@ public class InterrogationActivityTest
|
||||
assertEquals(ACTION_FOCUS | ACTION_SELECT | ACTION_CLEAR_SELECTION,
|
||||
button.getActions());
|
||||
} finally {
|
||||
afterClassIfNeeded();
|
||||
if (DEBUG) {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
Log.i(LOG_TAG, "testFindAccessibilityNodeInfoByViewId: "
|
||||
@@ -127,18 +118,19 @@ public class InterrogationActivityTest
|
||||
|
||||
@LargeTest
|
||||
public void testFindAccessibilityNodeInfoByViewText() throws Exception {
|
||||
beforeClassIfNeeded();
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
try {
|
||||
// hook into the system first
|
||||
IAccessibilityServiceConnection connection = getConnection();
|
||||
|
||||
// bring up the activity
|
||||
getActivity();
|
||||
|
||||
// find a view by text
|
||||
List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfosByViewTextInActiveWindow(getConnection(), "butto");
|
||||
.findAccessibilityNodeInfosByViewTextInActiveWindow(connection, "butto");
|
||||
assertEquals(9, buttons.size());
|
||||
} finally {
|
||||
afterClassIfNeeded();
|
||||
if (DEBUG) {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
Log.i(LOG_TAG, "testFindAccessibilityNodeInfoByViewText: "
|
||||
@@ -149,19 +141,20 @@ public class InterrogationActivityTest
|
||||
|
||||
@LargeTest
|
||||
public void testFindAccessibilityNodeInfoByViewTextContentDescription() throws Exception {
|
||||
beforeClassIfNeeded();
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
try {
|
||||
// hook into the system first
|
||||
IAccessibilityServiceConnection connection = getConnection();
|
||||
|
||||
// bring up the activity
|
||||
getActivity();
|
||||
|
||||
// find a view by text
|
||||
List<AccessibilityNodeInfo> buttons = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfosByViewTextInActiveWindow(getConnection(),
|
||||
.findAccessibilityNodeInfosByViewTextInActiveWindow(connection,
|
||||
"contentDescription");
|
||||
assertEquals(1, buttons.size());
|
||||
} finally {
|
||||
afterClassIfNeeded();
|
||||
if (DEBUG) {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
Log.i(LOG_TAG, "testFindAccessibilityNodeInfoByViewTextContentDescription: "
|
||||
@@ -172,9 +165,11 @@ public class InterrogationActivityTest
|
||||
|
||||
@LargeTest
|
||||
public void testTraverseAllViews() throws Exception {
|
||||
beforeClassIfNeeded();
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
try {
|
||||
// hook into the system first
|
||||
IAccessibilityServiceConnection connection = getConnection();
|
||||
|
||||
// bring up the activity
|
||||
getActivity();
|
||||
|
||||
@@ -195,7 +190,7 @@ public class InterrogationActivityTest
|
||||
classNameAndTextList.add("android.widget.ButtonButton9");
|
||||
|
||||
AccessibilityNodeInfo root = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.root);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.root);
|
||||
assertNotNull("We must find the existing root.", root);
|
||||
|
||||
Queue<AccessibilityNodeInfo> fringe = new LinkedList<AccessibilityNodeInfo>();
|
||||
@@ -221,7 +216,6 @@ public class InterrogationActivityTest
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
afterClassIfNeeded();
|
||||
if (DEBUG) {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
Log.i(LOG_TAG, "testTraverseAllViews: " + elapsedTimeMillis + "ms");
|
||||
@@ -231,15 +225,17 @@ public class InterrogationActivityTest
|
||||
|
||||
@LargeTest
|
||||
public void testPerformAccessibilityActionFocus() throws Exception {
|
||||
beforeClassIfNeeded();
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
try {
|
||||
// hook into the system first
|
||||
IAccessibilityServiceConnection connection = getConnection();
|
||||
|
||||
// bring up the activity
|
||||
getActivity();
|
||||
|
||||
// find a view and make sure it is not focused
|
||||
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertFalse(button.isFocused());
|
||||
|
||||
// focus the view
|
||||
@@ -247,10 +243,9 @@ public class InterrogationActivityTest
|
||||
|
||||
// find the view again and make sure it is focused
|
||||
button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertTrue(button.isFocused());
|
||||
} finally {
|
||||
afterClassIfNeeded();
|
||||
if (DEBUG) {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
Log.i(LOG_TAG, "testPerformAccessibilityActionFocus: " + elapsedTimeMillis + "ms");
|
||||
@@ -260,15 +255,17 @@ public class InterrogationActivityTest
|
||||
|
||||
@LargeTest
|
||||
public void testPerformAccessibilityActionClearFocus() throws Exception {
|
||||
beforeClassIfNeeded();
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
try {
|
||||
// hook into the system first
|
||||
IAccessibilityServiceConnection connection = getConnection();
|
||||
|
||||
// bring up the activity
|
||||
getActivity();
|
||||
|
||||
// find a view and make sure it is not focused
|
||||
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertFalse(button.isFocused());
|
||||
|
||||
// focus the view
|
||||
@@ -276,7 +273,7 @@ public class InterrogationActivityTest
|
||||
|
||||
// find the view again and make sure it is focused
|
||||
button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertTrue(button.isFocused());
|
||||
|
||||
// unfocus the view
|
||||
@@ -284,10 +281,9 @@ public class InterrogationActivityTest
|
||||
|
||||
// find the view again and make sure it is not focused
|
||||
button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertFalse(button.isFocused());
|
||||
} finally {
|
||||
afterClassIfNeeded();
|
||||
if (DEBUG) {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
Log.i(LOG_TAG, "testPerformAccessibilityActionClearFocus: "
|
||||
@@ -298,15 +294,17 @@ public class InterrogationActivityTest
|
||||
|
||||
@LargeTest
|
||||
public void testPerformAccessibilityActionSelect() throws Exception {
|
||||
beforeClassIfNeeded();
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
try {
|
||||
// hook into the system first
|
||||
IAccessibilityServiceConnection connection = getConnection();
|
||||
|
||||
// bring up the activity
|
||||
getActivity();
|
||||
|
||||
// find a view and make sure it is not selected
|
||||
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertFalse(button.isSelected());
|
||||
|
||||
// select the view
|
||||
@@ -314,10 +312,9 @@ public class InterrogationActivityTest
|
||||
|
||||
// find the view again and make sure it is selected
|
||||
button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertTrue(button.isSelected());
|
||||
} finally {
|
||||
afterClassIfNeeded();
|
||||
if (DEBUG) {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
Log.i(LOG_TAG, "testPerformAccessibilityActionSelect: " + elapsedTimeMillis + "ms");
|
||||
@@ -327,15 +324,17 @@ public class InterrogationActivityTest
|
||||
|
||||
@LargeTest
|
||||
public void testPerformAccessibilityActionClearSelection() throws Exception {
|
||||
beforeClassIfNeeded();
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
try {
|
||||
// hook into the system first
|
||||
IAccessibilityServiceConnection connection = getConnection();
|
||||
|
||||
// bring up the activity
|
||||
getActivity();
|
||||
|
||||
// find a view and make sure it is not selected
|
||||
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertFalse(button.isSelected());
|
||||
|
||||
// select the view
|
||||
@@ -343,7 +342,7 @@ public class InterrogationActivityTest
|
||||
|
||||
// find the view again and make sure it is selected
|
||||
button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertTrue(button.isSelected());
|
||||
|
||||
// unselect the view
|
||||
@@ -351,10 +350,9 @@ public class InterrogationActivityTest
|
||||
|
||||
// find the view again and make sure it is not selected
|
||||
button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertFalse(button.isSelected());
|
||||
} finally {
|
||||
afterClassIfNeeded();
|
||||
if (DEBUG) {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
Log.i(LOG_TAG, "testPerformAccessibilityActionClearSelection: "
|
||||
@@ -365,15 +363,17 @@ public class InterrogationActivityTest
|
||||
|
||||
@LargeTest
|
||||
public void testAccessibilityEventGetSource() throws Exception {
|
||||
beforeClassIfNeeded();
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
try {
|
||||
// hook into the system first
|
||||
IAccessibilityServiceConnection connection = getConnection();
|
||||
|
||||
// bring up the activity
|
||||
getActivity();
|
||||
getActivity();
|
||||
|
||||
// find a view and make sure it is not focused
|
||||
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
assertFalse(button.isSelected());
|
||||
|
||||
// focus the view
|
||||
@@ -419,7 +419,6 @@ public class InterrogationActivityTest
|
||||
assertSame(button.isCheckable(), source.isCheckable());
|
||||
assertSame(button.isChecked(), source.isChecked());
|
||||
} finally {
|
||||
afterClassIfNeeded();
|
||||
if (DEBUG) {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
Log.i(LOG_TAG, "testAccessibilityEventGetSource: " + elapsedTimeMillis + "ms");
|
||||
@@ -429,15 +428,17 @@ public class InterrogationActivityTest
|
||||
|
||||
@LargeTest
|
||||
public void testObjectContract() throws Exception {
|
||||
beforeClassIfNeeded();
|
||||
final long startTimeMillis = SystemClock.uptimeMillis();
|
||||
try {
|
||||
// hook into the system first
|
||||
IAccessibilityServiceConnection connection = getConnection();
|
||||
|
||||
// bring up the activity
|
||||
getActivity();
|
||||
|
||||
// find a view and make sure it is not focused
|
||||
AccessibilityNodeInfo button = AccessibilityInteractionClient.getInstance()
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(getConnection(), R.id.button5);
|
||||
.findAccessibilityNodeInfoByViewIdInActiveWindow(connection, R.id.button5);
|
||||
AccessibilityNodeInfo parent = button.getParent();
|
||||
final int childCount = parent.getChildCount();
|
||||
for (int i = 0; i < childCount; i++) {
|
||||
@@ -451,7 +452,6 @@ public class InterrogationActivityTest
|
||||
}
|
||||
fail("Parent's children do not have the info whose parent is the parent.");
|
||||
} finally {
|
||||
afterClassIfNeeded();
|
||||
if (DEBUG) {
|
||||
final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
|
||||
Log.i(LOG_TAG, "testObjectContract: " + elapsedTimeMillis + "ms");
|
||||
@@ -464,90 +464,10 @@ public class InterrogationActivityTest
|
||||
/* intentionally do not scrub */
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets accessibility in a given state by writing the state to the
|
||||
* settings and waiting until the accessibility manager service picks
|
||||
* it up for max {@link #TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING}.
|
||||
*
|
||||
* @param state The accessibility state.
|
||||
* @throws Exception If any error occurs.
|
||||
*/
|
||||
private void ensureAccessibilityState(boolean state) throws Exception {
|
||||
Context context = getInstrumentation().getContext();
|
||||
// If the local manager ready => nothing to do.
|
||||
AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(context);
|
||||
if (accessibilityManager.isEnabled() == state) {
|
||||
return;
|
||||
}
|
||||
synchronized (this) {
|
||||
// Check if the system already knows about the desired state.
|
||||
final boolean currentState = Settings.Secure.getInt(context.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_ENABLED) == 1;
|
||||
if (currentState != state) {
|
||||
// Make sure we wake ourselves as the desired state is propagated.
|
||||
accessibilityManager.addAccessibilityStateChangeListener(
|
||||
new AccessibilityManager.AccessibilityStateChangeListener() {
|
||||
public void onAccessibilityStateChanged(boolean enabled) {
|
||||
synchronized (this) {
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
Settings.Secure.putInt(context.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_ENABLED, state ? 1 : 0);
|
||||
}
|
||||
// No while one attempt and that is it.
|
||||
try {
|
||||
wait(TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING);
|
||||
} catch (InterruptedException ie) {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
if (accessibilityManager.isEnabled() != state) {
|
||||
throw new IllegalStateException("Could not set accessibility state to: " + state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute some set up code before any test method.
|
||||
*
|
||||
* NOTE: I miss Junit4's @BeforeClass
|
||||
*
|
||||
* @throws Exception If an error occurs.
|
||||
*/
|
||||
private void beforeClassIfNeeded() throws Exception {
|
||||
sExecutedTestMethodCount++;
|
||||
if (sExecutedTestMethodCount == 1) {
|
||||
ensureAccessibilityState(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute some clean up code after all test methods.
|
||||
*
|
||||
* NOTE: I miss Junit4's @AfterClass
|
||||
*
|
||||
* @throws Exception If an error occurs.
|
||||
*/
|
||||
public void afterClassIfNeeded() throws Exception {
|
||||
if (sExecutedTestMethodCount == sTestMethodCount) {
|
||||
sExecutedTestMethodCount = 0;
|
||||
ensureAccessibilityState(false);
|
||||
}
|
||||
}
|
||||
|
||||
private static IAccessibilityServiceConnection getConnection() throws Exception {
|
||||
private IAccessibilityServiceConnection getConnection() throws Exception {
|
||||
if (sConnection == null) {
|
||||
IEventListener listener = new IEventListener.Stub() {
|
||||
public void setConnection(IAccessibilityServiceConnection connection)
|
||||
throws RemoteException {
|
||||
AccessibilityServiceInfo info = new AccessibilityServiceInfo();
|
||||
info.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
|
||||
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
|
||||
info.notificationTimeout = 0;
|
||||
info.flags = AccessibilityServiceInfo.DEFAULT;
|
||||
connection.setServiceInfo(info);
|
||||
}
|
||||
public void setConnection(IAccessibilityServiceConnection connection) {}
|
||||
|
||||
public void onInterrupt() {}
|
||||
|
||||
@@ -560,26 +480,33 @@ public class InterrogationActivityTest
|
||||
}
|
||||
}
|
||||
};
|
||||
IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
|
||||
sConnection = manager.registerEventListener(listener);
|
||||
|
||||
AccessibilityManager accessibilityManager =
|
||||
AccessibilityManager.getInstance(getInstrumentation().getContext());
|
||||
|
||||
synchronized (this) {
|
||||
if (!accessibilityManager.isEnabled()) {
|
||||
// Make sure we wake ourselves as the desired state is propagated.
|
||||
accessibilityManager.addAccessibilityStateChangeListener(
|
||||
new AccessibilityManager.AccessibilityStateChangeListener() {
|
||||
public void onAccessibilityStateChanged(boolean enabled) {
|
||||
synchronized (this) {
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
});
|
||||
IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
|
||||
sConnection = manager.registerEventListener(listener);
|
||||
|
||||
wait(TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING);
|
||||
} else {
|
||||
IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
|
||||
ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
|
||||
sConnection = manager.registerEventListener(listener);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sConnection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of test methods.
|
||||
*/
|
||||
private int getTestMethodCount() {
|
||||
int testMethodCount = 0;
|
||||
for (Method method : getClass().getMethods()) {
|
||||
final int modifiers = method.getModifiers();
|
||||
if (method.getName().startsWith("test")
|
||||
&& (modifiers & Modifier.PUBLIC) != 0
|
||||
&& (modifiers & Modifier.STATIC) == 0) {
|
||||
testMethodCount++;
|
||||
}
|
||||
}
|
||||
return testMethodCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,16 +298,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
super.onChange(selfChange);
|
||||
|
||||
synchronized (mLock) {
|
||||
mIsAccessibilityEnabled = Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
|
||||
if (mIsAccessibilityEnabled) {
|
||||
manageServicesLocked();
|
||||
} else {
|
||||
unbindAllServicesLocked();
|
||||
}
|
||||
updateInputFilterLocked();
|
||||
sendStateToClientsLocked();
|
||||
handleAccessibilityEnabledSettingChangedLocked();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -354,6 +345,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
client.asBinder().linkToDeath(new DeathRecipient() {
|
||||
public void binderDied() {
|
||||
synchronized (mLock) {
|
||||
addedClient.asBinder().unlinkToDeath(this, 0);
|
||||
mClients.remove(addedClient);
|
||||
}
|
||||
}
|
||||
@@ -445,10 +437,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
IAccessibilityInteractionConnection connection) throws RemoteException {
|
||||
synchronized (mLock) {
|
||||
final IWindow addedWindowToken = windowToken;
|
||||
final IAccessibilityInteractionConnection addedConnection = connection;
|
||||
final int windowId = sNextWindowId++;
|
||||
connection.asBinder().linkToDeath(new DeathRecipient() {
|
||||
addedConnection.asBinder().linkToDeath(new DeathRecipient() {
|
||||
public void binderDied() {
|
||||
synchronized (mLock) {
|
||||
addedConnection.asBinder().unlinkToDeath(this, 0);
|
||||
removeAccessibilityInteractionConnection(addedWindowToken);
|
||||
}
|
||||
}
|
||||
@@ -485,21 +479,23 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
ComponentName componentName = new ComponentName("foo.bar",
|
||||
"AutomationAccessibilityService");
|
||||
synchronized (mLock) {
|
||||
Service oldService = mComponentNameToServiceMap.get(componentName);
|
||||
if (oldService != null) {
|
||||
tryRemoveServiceLocked(oldService);
|
||||
// If an automation services is connected to the system all services are stopped
|
||||
// so the automation one is the only one running. Settings are not changed so when
|
||||
// the automation service goes away the state is restored from the settings.
|
||||
|
||||
// Disable all services.
|
||||
final int runningServiceCount = mServices.size();
|
||||
for (int i = 0; i < runningServiceCount; i++) {
|
||||
Service runningService = mServices.get(i);
|
||||
runningService.unbind();
|
||||
}
|
||||
// If necessary enable accessibility and announce that.
|
||||
if (!mIsAccessibilityEnabled) {
|
||||
mIsAccessibilityEnabled = true;
|
||||
sendStateToClientsLocked();
|
||||
}
|
||||
// Now this service is enabled.
|
||||
mEnabledServices.add(componentName);
|
||||
// Also make sure this service is the only one.
|
||||
Settings.Secure.putString(mContext.getContentResolver(),
|
||||
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
|
||||
componentName.flattenToString());
|
||||
// This API is intended for testing so enable accessibility to make
|
||||
// sure clients can start poking with the window content.
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_ENABLED, 1);
|
||||
}
|
||||
// Hook the automation service up.
|
||||
AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo();
|
||||
accessibilityServiceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
|
||||
accessibilityServiceInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
|
||||
@@ -717,11 +713,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
* Manages services by starting enabled ones and stopping disabled ones.
|
||||
*/
|
||||
private void manageServicesLocked() {
|
||||
unbindAutomationService();
|
||||
populateEnabledServicesLocked(mEnabledServices);
|
||||
final int enabledInstalledServicesCount = updateServicesStateLocked(mInstalledServices,
|
||||
mEnabledServices);
|
||||
// No enabled installed services => disable accessibility to avoid
|
||||
// sending accessibility events with no recipient across processes.
|
||||
// sending accessibility events with no recipient across processes.
|
||||
if (mIsAccessibilityEnabled && enabledInstalledServicesCount == 0) {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_ENABLED, 0);
|
||||
@@ -743,6 +740,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbinds the automation service if such is running.
|
||||
*/
|
||||
private void unbindAutomationService() {
|
||||
List<Service> runningServices = mServices;
|
||||
int runningServiceCount = mServices.size();
|
||||
for (int i = 0; i < runningServiceCount; i++) {
|
||||
Service service = runningServices.get(i);
|
||||
if (service.mIsAutomation) {
|
||||
service.unbind();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates a list with the {@link ComponentName}s of all enabled
|
||||
* {@link AccessibilityService}s.
|
||||
@@ -867,6 +879,22 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updated the state based on the accessibility enabled setting.
|
||||
*/
|
||||
private void handleAccessibilityEnabledSettingChangedLocked() {
|
||||
mIsAccessibilityEnabled = Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
|
||||
if (mIsAccessibilityEnabled) {
|
||||
manageServicesLocked();
|
||||
} else {
|
||||
unbindAllServicesLocked();
|
||||
}
|
||||
updateInputFilterLocked();
|
||||
sendStateToClientsLocked();
|
||||
}
|
||||
|
||||
/**
|
||||
* This class represents an accessibility service. It stores all per service
|
||||
* data required for the service management, provides API for starting/stopping the
|
||||
@@ -1171,7 +1199,13 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
|
||||
|
||||
public void binderDied() {
|
||||
synchronized (mLock) {
|
||||
mService.unlinkToDeath(this, 0);
|
||||
tryRemoveServiceLocked(this);
|
||||
// We no longer have an automation service, so restore
|
||||
// the state based on values in the settings database.
|
||||
if (mIsAutomation) {
|
||||
handleAccessibilityEnabledSettingChangedLocked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user