FileDocCategorySizeDatePackage
AccessibilityManagerServiceTest.javaAPI DocAndroid 5.1 API29759Thu Mar 12 22:22:42 GMT 2015com.android.server

AccessibilityManagerServiceTest

public class AccessibilityManagerServiceTest extends android.test.AndroidTestCase
This test exercises the {@link com.android.server.accessibility.AccessibilityManagerService} by mocking the {@link android.view.accessibility.AccessibilityManager} which talks to to the service. The service itself is interacting with the platform. Note: Testing the service in full isolation would require significant amount of work for mocking all system interactions. It would also require a lot of mocking code.

Fields Summary
private static final long
TIMEOUT_BINDER_CALL
Timeout required for pending Binder calls or event processing to complete.
private static final long
TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES
Timeout in which we are waiting for the system to start the mock accessibility services.
private static final long
TIMEOUT_TEST_NOTIFICATION_TIMEOUT
Timeout used for testing that a service is notified only upon a notification timeout.
private android.view.accessibility.IAccessibilityManager
mManagerService
The interface used to talk to the tested service.
Constructors Summary
public AccessibilityManagerServiceTest()
Creates a new instance.

        IBinder iBinder = ServiceManager.getService(Context.ACCESSIBILITY_SERVICE);
        mManagerService = IAccessibilityManager.Stub.asInterface(iBinder);
    
Methods Summary
private voidassertMockServiceVerifiedWithinTimeout(MockAccessibilityService service)
Asserts the the mock accessibility service has been successfully verified (which is it has received the expected method calls with expected arguments) within the {@link #TIMEOUT_BINDER_CALL}. The verified state is checked by polling upon small intervals.

param
service The service to verify.
throws
Exception If the verification has failed with exception after the {@link #TIMEOUT_BINDER_CALL}.

        Exception lastVerifyException = null;
        long beginTime = SystemClock.uptimeMillis();
        long pollTmeout = TIMEOUT_BINDER_CALL / 5;

        // poll until the timeout has elapsed
        while (SystemClock.uptimeMillis() - beginTime < TIMEOUT_BINDER_CALL) {
            // sleep first since immediate call will always fail
            try {
                Thread.sleep(pollTmeout);
            } catch (InterruptedException ie) {
                /* ignore */
            }
            // poll for verification and if this fails save the exception and
            // keep polling
            try {
                service.verify();
                // reset so it does not accept more events
                service.reset();
                return;
            } catch (Exception e) {
                lastVerifyException = e;
            }
        }

        // reset, we have already failed
        service.reset();

        // always not null
        throw lastVerifyException;
    
private voidensureAccessibilityEnabled(android.content.Context context, boolean enabled)
Ensures accessibility is in a given state by writing the state to the settings and waiting until the accessibility manager service pick it up.

param
context A context handle to access the settings.
param
enabled The accessibility state to write to the settings.
throws
Exception If any error occurs.

        boolean isEnabled = (Settings.Secure.getInt(context.getContentResolver(),
                Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1 ? true : false);

        if (isEnabled == enabled) {
            return;
        }

        Settings.Secure.putInt(context.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED,
                enabled ? 1 : 0);

        // wait the accessibility manager service to pick the change up
        Thread.sleep(TIMEOUT_BINDER_CALL);
    
private voidensureOnlyMockServicesEnabled(android.content.Context context, boolean firstMockServiceEnabled, boolean secondMockServiceEnabled)
Ensures the only {@link MockAccessibilityService}s with given component names are enabled by writing to the system settings and waiting until the accessibility manager service picks that up or the {@link #TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES} is exceeded.

param
context A context handle to access the settings.
param
firstMockServiceEnabled If the first mock accessibility service is enabled.
param
secondMockServiceEnabled If the second mock accessibility service is enabled.
throws
IllegalStateException If some of the requested for enabling mock services is not properly started.
throws
Exception Exception If any error occurs.

        String enabledServices = Settings.Secure.getString(context.getContentResolver(),
                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);

        StringBuilder servicesToEnable = new StringBuilder();
        if (firstMockServiceEnabled) {
            servicesToEnable.append(MyFirstMockAccessibilityService.sComponentName).append(":");
        }
        if (secondMockServiceEnabled) {
            servicesToEnable.append(MySecondMockAccessibilityService.sComponentName).append(":");
        }

        if (servicesToEnable.equals(enabledServices)) {
            return;
        }

        Settings.Secure.putString(context.getContentResolver(),
                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, servicesToEnable.toString());

        // we have enabled the services of interest and need to wait until they
        // are instantiated and started (if needed) and the system binds to them
        boolean firstMockServiceOK = false;
        boolean secondMockServiceOK = false;
        long start = SystemClock.uptimeMillis();
        long pollingInterval = TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES / 6;

        while (SystemClock.uptimeMillis() - start < TIMEOUT_START_MOCK_ACCESSIBILITY_SERVICES)  {
            firstMockServiceOK = !firstMockServiceEnabled
                    || (MyFirstMockAccessibilityService.sInstance != null
                    && MyFirstMockAccessibilityService.sInstance.isSystemBoundAsClient());

            secondMockServiceOK = !secondMockServiceEnabled
                    || (MySecondMockAccessibilityService.sInstance != null
                    && MySecondMockAccessibilityService.sInstance.isSystemBoundAsClient());

            if (firstMockServiceOK && secondMockServiceOK) {
                return;
            }

            Thread.sleep(pollingInterval);
        }

        StringBuilder message = new StringBuilder();
        message.append("Mock accessibility services not started or system not bound as a client: ");
        if (!firstMockServiceOK) {
            message.append(MyFirstMockAccessibilityService.sComponentName);
            message.append(" ");
        }
        if (!secondMockServiceOK) {
            message.append(MySecondMockAccessibilityService.sComponentName);
        }
        throw new IllegalStateException(message.toString());
    
private voidfullyPopulateDefaultAccessibilityEvent(android.view.accessibility.AccessibilityEvent sentEvent)
Fully populates the {@link AccessibilityEvent} to marshal.

param
sentEvent The event to populate.

        sentEvent.setAddedCount(1);
        sentEvent.setBeforeText("BeforeText");
        sentEvent.setChecked(true);
        sentEvent.setClassName("foo.bar.baz.Class");
        sentEvent.setContentDescription("ContentDescription");
        sentEvent.setCurrentItemIndex(1);
        sentEvent.setEnabled(true);
        sentEvent.setEventType(AccessibilityEvent.TYPE_VIEW_CLICKED);
        sentEvent.setEventTime(1000);
        sentEvent.setFromIndex(1);
        sentEvent.setFullScreen(true);
        sentEvent.setItemCount(1);
        sentEvent.setPackageName("foo.bar.baz");
        sentEvent.setParcelableData(Message.obtain(null, 1, null));
        sentEvent.setPassword(true);
        sentEvent.setRemovedCount(1);
    
public voidsetContext(android.content.Context context)


    
        
        super.setContext(context);
        if (MyFirstMockAccessibilityService.sComponentName == null) {
            MyFirstMockAccessibilityService.sComponentName = new ComponentName(
                    context.getPackageName(), MyFirstMockAccessibilityService.class.getName())
                    .flattenToShortString();
        }
        if (MySecondMockAccessibilityService.sComponentName == null) {
            MySecondMockAccessibilityService.sComponentName = new ComponentName(
                    context.getPackageName(), MySecondMockAccessibilityService.class.getName())
                    .flattenToShortString();
        }
    
public voidtestAddClient_AccessibilityDisabledThenEnabled()

        // make sure accessibility is disabled
        ensureAccessibilityEnabled(mContext, false);

        // create a client mock instance
        MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();

        // invoke the method under test
        final int stateFlagsDisabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
        boolean enabledAccessibilityDisabled =
            (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;

        // check expected result
        assertFalse("The client must be disabled since accessibility is disabled.",
                enabledAccessibilityDisabled);

        // enable accessibility
        ensureAccessibilityEnabled(mContext, true);

        // invoke the method under test
        final int stateFlagsEnabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
        boolean enabledAccessibilityEnabled =
            (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;


        // check expected result
        assertTrue("The client must be enabled since accessibility is enabled.",
                enabledAccessibilityEnabled);
    
public voidtestAddClient_AccessibilityEnabledThenDisabled()

        // enable accessibility before registering the client
        ensureAccessibilityEnabled(mContext, true);

        // create a client mock instance
        MyMockAccessibilityManagerClient mockClient = new MyMockAccessibilityManagerClient();

        // invoke the method under test
        final int stateFlagsEnabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
        boolean enabledAccessibilityEnabled =
            (stateFlagsEnabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;

        // check expected result
        assertTrue("The client must be enabled since accessibility is enabled.",
                enabledAccessibilityEnabled);

        // disable accessibility
        ensureAccessibilityEnabled(mContext, false);

        // invoke the method under test
        final int stateFlagsDisabled = mManagerService.addClient(mockClient, UserHandle.USER_OWNER);
        boolean enabledAccessibilityDisabled =
            (stateFlagsDisabled & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0;

        // check expected result
        assertFalse("The client must be disabled since accessibility is disabled.",
                enabledAccessibilityDisabled);
    
public voidtestGetAccessibilityServicesList()

        boolean firstMockServiceInstalled = false;
        boolean secondMockServiceInstalled = false;

        String packageName = getContext().getPackageName();
        String firstMockServiceClassName = MyFirstMockAccessibilityService.class.getName();
        String secondMockServiceClassName = MySecondMockAccessibilityService.class.getName();

        // look for the two mock services
        for (AccessibilityServiceInfo info : mManagerService.getInstalledAccessibilityServiceList(
                UserHandle.USER_OWNER)) {
            ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo;
            if (packageName.equals(serviceInfo.packageName)) {
                if (firstMockServiceClassName.equals(serviceInfo.name)) {
                    firstMockServiceInstalled = true;
                } else if (secondMockServiceClassName.equals(serviceInfo.name)) {
                    secondMockServiceInstalled = true;
                }
            }
        }

        // check expected result
        assertTrue("First mock service must be installed", firstMockServiceInstalled);
        assertTrue("Second mock service must be installed", secondMockServiceInstalled);
    
public voidtestInterrupt()

        // set the accessibility setting value
        ensureAccessibilityEnabled(mContext, true);

        // enable the mock accessibility services
        ensureOnlyMockServicesEnabled(mContext, true, true);

        // configure the first mock service
        MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance;
        firstService.setServiceInfo(MockAccessibilityService.createDefaultInfo());

        // configure the second mock service
        MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance;
        secondService.setServiceInfo(MockAccessibilityService.createDefaultInfo());

        // wait for the binder calls to #setService to complete
        Thread.sleep(TIMEOUT_BINDER_CALL);

        // set expectations for the first mock service
        firstService.expectInterrupt();
        firstService.replay();

        // set expectations for the second mock service
        secondService.expectInterrupt();
        secondService.replay();

        // call the method under test
        mManagerService.interrupt(UserHandle.USER_OWNER);

        // verify if all expected methods have been called
        assertMockServiceVerifiedWithinTimeout(firstService);
        assertMockServiceVerifiedWithinTimeout(secondService);
    
public voidtestSendAccessibilityEvent_OneService_MatchingPackageAndEventType()

        // set the accessibility setting value
        ensureAccessibilityEnabled(mContext, true);

        // enable the mock accessibility service
        ensureOnlyMockServicesEnabled(mContext, true, false);

        // configure the mock service
        MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance;
        service.setServiceInfo(MockAccessibilityService.createDefaultInfo());

        // wait for the binder call to #setService to complete
        Thread.sleep(TIMEOUT_BINDER_CALL);

        // create and populate an event to be sent
        AccessibilityEvent sentEvent = AccessibilityEvent.obtain();
        fullyPopulateDefaultAccessibilityEvent(sentEvent);

        // set expectations
        service.expectEvent(sentEvent);
        service.replay();

        // send the event
        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);

        // verify if all expected methods have been called
        assertMockServiceVerifiedWithinTimeout(service);
    
public voidtestSendAccessibilityEvent_OneService_NotMatchingEventType()

        // set the accessibility setting value
        ensureAccessibilityEnabled(mContext, true);

        // enable the mock accessibility service
        ensureOnlyMockServicesEnabled(mContext, true, false);

        // configure the mock service
        MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance;
        service.setServiceInfo(MockAccessibilityService.createDefaultInfo());

        // wait for the binder call to #setService to complete
        Thread.sleep(TIMEOUT_BINDER_CALL);

        // create and populate an event to be sent
        AccessibilityEvent sentEvent = AccessibilityEvent.obtain();
        fullyPopulateDefaultAccessibilityEvent(sentEvent);
        sentEvent.setEventType(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);

        // set expectations
        service.replay();

        // send the event
        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);

        // verify if all expected methods have been called
        assertMockServiceVerifiedWithinTimeout(service);
    
public voidtestSendAccessibilityEvent_OneService_NotMatchingPackage()

        // set the accessibility setting value
        ensureAccessibilityEnabled(mContext, true);

        // enable the mock accessibility service
        ensureOnlyMockServicesEnabled(mContext, true, false);

        // configure the mock service
        MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance;
        service.setServiceInfo(MockAccessibilityService.createDefaultInfo());

        // wait for the binder call to #setService to complete
        Thread.sleep(TIMEOUT_BINDER_CALL);

        // create and populate an event to be sent
        AccessibilityEvent sentEvent = AccessibilityEvent.obtain();
        fullyPopulateDefaultAccessibilityEvent(sentEvent);
        sentEvent.setPackageName("no.service.registered.for.this.package");

        // set expectations
        service.replay();

        // send the event
        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);

        // verify if all expected methods have been called
        assertMockServiceVerifiedWithinTimeout(service);
    
public voidtestSendAccessibilityEvent_OneService_NotifivationAfterTimeout()

        // set the accessibility setting value
        ensureAccessibilityEnabled(mContext, true);

        // enable the mock accessibility service
        ensureOnlyMockServicesEnabled(mContext, true, false);

        // configure the mock service
        MockAccessibilityService service = MyFirstMockAccessibilityService.sInstance;
        AccessibilityServiceInfo info = MockAccessibilityService.createDefaultInfo();
        info.notificationTimeout = TIMEOUT_TEST_NOTIFICATION_TIMEOUT;
        service.setServiceInfo(info);

        // wait for the binder call to #setService to complete
        Thread.sleep(TIMEOUT_BINDER_CALL);

        // create and populate the first event to be sent
        AccessibilityEvent firstEvent = AccessibilityEvent.obtain();
        fullyPopulateDefaultAccessibilityEvent(firstEvent);

        // create and populate the second event to be sent
        AccessibilityEvent secondEvent = AccessibilityEvent.obtain();
        fullyPopulateDefaultAccessibilityEvent(secondEvent);

        // set expectations
        service.expectEvent(secondEvent);
        service.replay();

        // send the events
        mManagerService.sendAccessibilityEvent(firstEvent, UserHandle.USER_OWNER);
        mManagerService.sendAccessibilityEvent(secondEvent, UserHandle.USER_OWNER);

        // wait for #sendAccessibilityEvent to reach the backing service
        Thread.sleep(TIMEOUT_BINDER_CALL);

        try {
            service.verify();
            fail("No events must be dispatched before the expiration of the notification timeout.");
        } catch (IllegalStateException ise) {
            /* expected */
        }

        // wait for the configured notification timeout to expire
        Thread.sleep(TIMEOUT_TEST_NOTIFICATION_TIMEOUT);

        // verify if all expected methods have been called
        assertMockServiceVerifiedWithinTimeout(service);
    
public voidtestSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType()

        // set the accessibility setting value
        ensureAccessibilityEnabled(mContext, true);

        // enable the mock accessibility services
        ensureOnlyMockServicesEnabled(mContext, true, true);

        // configure the first mock service
        MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance;
        firstService.setServiceInfo(MockAccessibilityService.createDefaultInfo());

        // configure the second mock service
        MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance;
        secondService.setServiceInfo(MockAccessibilityService.createDefaultInfo());

        // wait for the binder calls to #setService to complete
        Thread.sleep(TIMEOUT_BINDER_CALL);

        // create and populate an event to be sent
        AccessibilityEvent sentEvent = AccessibilityEvent.obtain();
        fullyPopulateDefaultAccessibilityEvent(sentEvent);

        // set expectations for the first mock service
        firstService.expectEvent(sentEvent);
        firstService.replay();

        // set expectations for the second mock service
        secondService.replay();

        // send the event
        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);

        // verify if all expected methods have been called
        assertMockServiceVerifiedWithinTimeout(firstService);
        assertMockServiceVerifiedWithinTimeout(secondService);
    
public voidtestSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_DiffFeedback()

        // set the accessibility setting value
        ensureAccessibilityEnabled(mContext, true);

        // enable the mock accessibility services
        ensureOnlyMockServicesEnabled(mContext, true, true);

        // configure the first mock service
        MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance;
        AccessibilityServiceInfo firstInfo = MockAccessibilityService.createDefaultInfo();
        firstInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_AUDIBLE;
        firstService.setServiceInfo(firstInfo);

        // configure the second mock service
        MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance;
        AccessibilityServiceInfo secondInfo = MockAccessibilityService.createDefaultInfo();
        secondInfo.feedbackType = AccessibilityServiceInfo.FEEDBACK_HAPTIC;
        secondService.setServiceInfo(secondInfo);

        // wait for the binder calls to #setService to complete
        Thread.sleep(TIMEOUT_BINDER_CALL);

        // create and populate an event to be sent
        AccessibilityEvent sentEvent = AccessibilityEvent.obtain();
        fullyPopulateDefaultAccessibilityEvent(sentEvent);

        // set expectations for the first mock service
        firstService.expectEvent(sentEvent);
        firstService.replay();

        // set expectations for the second mock service
        secondService.expectEvent(sentEvent);
        secondService.replay();

        // send the event
        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);

        // verify if all expected methods have been called
        assertMockServiceVerifiedWithinTimeout(firstService);
        assertMockServiceVerifiedWithinTimeout(secondService);
    
public voidtestSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_OneDefault()

        // set the accessibility setting value
        ensureAccessibilityEnabled(mContext, true);

        // enable the mock accessibility services
        ensureOnlyMockServicesEnabled(mContext, true, true);

        // configure the first mock service
        MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance;
        AccessibilityServiceInfo firstInfo = MyFirstMockAccessibilityService.createDefaultInfo();
        firstInfo.flags = AccessibilityServiceInfo.DEFAULT;
        firstService.setServiceInfo(firstInfo);

        // configure the second mock service
        MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance;
        secondService.setServiceInfo(MySecondMockAccessibilityService.createDefaultInfo());

        // wait for the binder calls to #setService to complete
        Thread.sleep(TIMEOUT_BINDER_CALL);

        // create and populate an event to be sent
        AccessibilityEvent sentEvent = AccessibilityEvent.obtain();
        fullyPopulateDefaultAccessibilityEvent(sentEvent);

        // set expectations for the first mock service
        firstService.replay();

        // set expectations for the second mock service
        secondService.expectEvent(sentEvent);
        secondService.replay();

        // send the event
        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);

        // verify if all expected methods have been called
        assertMockServiceVerifiedWithinTimeout(firstService);
        assertMockServiceVerifiedWithinTimeout(secondService);
    
public voidtestSendAccessibilityEvent_TwoServices_MatchingPackageAndEventType_TwoDefault()

        // set the accessibility setting value
        ensureAccessibilityEnabled(mContext, true);

        // enable the mock accessibility services
        ensureOnlyMockServicesEnabled(mContext, true, true);

        // configure the first mock service
        MockAccessibilityService firstService = MyFirstMockAccessibilityService.sInstance;
        AccessibilityServiceInfo firstInfo = MyFirstMockAccessibilityService.createDefaultInfo();
        firstInfo.flags = AccessibilityServiceInfo.DEFAULT;
        firstService.setServiceInfo(firstInfo);

        // configure the second mock service
        MockAccessibilityService secondService = MySecondMockAccessibilityService.sInstance;
        AccessibilityServiceInfo secondInfo = MyFirstMockAccessibilityService.createDefaultInfo();
        secondInfo.flags = AccessibilityServiceInfo.DEFAULT;
        secondService.setServiceInfo(firstInfo);

        // wait for the binder calls to #setService to complete
        Thread.sleep(TIMEOUT_BINDER_CALL);

        // create and populate an event to be sent
        AccessibilityEvent sentEvent = AccessibilityEvent.obtain();
        fullyPopulateDefaultAccessibilityEvent(sentEvent);

        // set expectations for the first mock service
        firstService.expectEvent(sentEvent);
        firstService.replay();

        // set expectations for the second mock service
        secondService.replay();

        // send the event
        mManagerService.sendAccessibilityEvent(sentEvent, UserHandle.USER_OWNER);

        // verify if all expected methods have been called
        assertMockServiceVerifiedWithinTimeout(firstService);
        assertMockServiceVerifiedWithinTimeout(secondService);