Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6eca6e6 authored by Svetoslav Ganov's avatar Svetoslav Ganov
Browse files

Accessibility test automation API not working.

1. Due to a previous change that disabled accessibility if not enabled
   and installed serivces are present the automation APIs stopped working
   since they use fake automation service that is not installed.

2. Added clean up of death recipients when binders die.

bug:5374662
bug:5239044

Change-Id: I1f3c8cd1d1c79753a4a64e2b8b2963025abb2939
parent e921572b
Loading
Loading
Loading
Loading
+77 −150
Original line number Diff line number Diff line
@@ -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;
@@ -58,11 +54,6 @@ public class InterrogationActivityTest
    // 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();  

            // 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
                    }
                }
            };

            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);
        }
        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++;
                    wait(TIMEOUT_PROPAGATE_ACCESSIBLITY_SETTING);
                } else {
                    IAccessibilityManager manager = IAccessibilityManager.Stub.asInterface(
                          ServiceManager.getService(Context.ACCESSIBILITY_SERVICE));
                    sConnection = manager.registerEventListener(listener);
                }
            }
        return testMethodCount;
        }
        return sConnection;
    }
}
+59 −25

File changed.

Preview size limit exceeded, changes collapsed.