/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server; import static org.easymock.EasyMock.createStrictMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.reportMatcher; import static org.easymock.EasyMock.reset; import static org.easymock.EasyMock.verify; import org.easymock.IArgumentMatcher; import android.accessibilityservice.AccessibilityServiceInfo; import android.os.UserHandle; import android.test.AndroidTestCase; import android.test.suitebuilder.annotation.LargeTest; import android.test.suitebuilder.annotation.MediumTest; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManager; import android.view.accessibility.IAccessibilityManagerClient; import java.util.ArrayList; import java.util.List; /** * Tests for the AccessibilityManager which mocking the backing service. */ public class AccessibilityManagerTest extends AndroidTestCase { /** * Timeout required for pending Binder calls or event processing to * complete. */ public static final long TIMEOUT_BINDER_CALL = 50; /** * The reusable mock {@link IAccessibilityManager}. */ private final IAccessibilityManager mMockServiceInterface = createStrictMock(IAccessibilityManager.class); @Override public void setUp() throws Exception { reset(mMockServiceInterface); } @MediumTest public void testGetAccessibilityServiceList() throws Exception { // create a list of installed accessibility services the mock service returns List expectedServices = new ArrayList(); AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo(); accessibilityServiceInfo.packageNames = new String[] { "foo.bar" }; expectedServices.add(accessibilityServiceInfo); // configure the mock service behavior IAccessibilityManager mockServiceInterface = mMockServiceInterface; expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(), UserHandle.USER_OWNER)).andReturn( AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); expect(mockServiceInterface.getInstalledAccessibilityServiceList(UserHandle.USER_OWNER)) .andReturn(expectedServices); replay(mockServiceInterface); // invoke the method under test AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface, UserHandle.USER_OWNER); List receivedServices = manager.getInstalledAccessibilityServiceList(); // check expected result (list equals() compares it contents as well) assertEquals("All expected services must be returned", receivedServices, expectedServices); // verify the mock service was properly called verify(mockServiceInterface); } @MediumTest public void testInterrupt() throws Exception { // configure the mock service behavior IAccessibilityManager mockServiceInterface = mMockServiceInterface; expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(), UserHandle.USER_OWNER)).andReturn( AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); mockServiceInterface.interrupt(UserHandle.USER_OWNER); replay(mockServiceInterface); // invoke the method under test AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface, UserHandle.USER_OWNER); manager.interrupt(); // verify the mock service was properly called verify(mockServiceInterface); } @LargeTest public void testIsEnabled() throws Exception { // configure the mock service behavior IAccessibilityManager mockServiceInterface = mMockServiceInterface; expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(), UserHandle.USER_OWNER)).andReturn( AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); replay(mockServiceInterface); // invoke the method under test AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface, UserHandle.USER_OWNER); boolean isEnabledServiceEnabled = manager.isEnabled(); // check expected result assertTrue("Must be enabled since the mock service is enabled", isEnabledServiceEnabled); // disable accessibility manager.getClient().setState(0); // wait for the asynchronous IBinder call to complete Thread.sleep(TIMEOUT_BINDER_CALL); // invoke the method under test boolean isEnabledServcieDisabled = manager.isEnabled(); // check expected result assertFalse("Must be disabled since the mock service is disabled", isEnabledServcieDisabled); // verify the mock service was properly called verify(mockServiceInterface); } @MediumTest public void testSendAccessibilityEvent_AccessibilityEnabled() throws Exception { // create an event to be dispatched AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); // configure the mock service behavior IAccessibilityManager mockServiceInterface = mMockServiceInterface; expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(), UserHandle.USER_OWNER)).andReturn( AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent), UserHandle.USER_OWNER)).andReturn(true); expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent), UserHandle.USER_OWNER)).andReturn(false); replay(mockServiceInterface); // invoke the method under test (manager and service in different processes) AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface, UserHandle.USER_OWNER); manager.sendAccessibilityEvent(sentEvent); // check expected result AccessibilityEvent nextEventDifferentProcesses = AccessibilityEvent.obtain(); assertSame("The manager and the service are in different processes, so the event must be " + "recycled", sentEvent, nextEventDifferentProcesses); // invoke the method under test (manager and service in the same process) manager.sendAccessibilityEvent(sentEvent); // check expected result AccessibilityEvent nextEventSameProcess = AccessibilityEvent.obtain(); assertNotSame("The manager and the service are in the same process, so the event must not" + "be recycled", sentEvent, nextEventSameProcess); // verify the mock service was properly called verify(mockServiceInterface); } @MediumTest public void testSendAccessibilityEvent_AccessibilityDisabled() throws Exception { // create an event to be dispatched AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); // configure the mock service behavior IAccessibilityManager mockServiceInterface = mMockServiceInterface; expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(), UserHandle.USER_OWNER)).andReturn(0); replay(mockServiceInterface); // invoke the method under test (accessibility disabled) AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface, UserHandle.USER_OWNER); try { manager.sendAccessibilityEvent(sentEvent); fail("No accessibility events are sent if accessibility is disabled"); } catch (IllegalStateException ise) { // check expected result assertEquals("Accessibility off. Did you forget to check that?", ise.getMessage()); } // verify the mock service was properly called verify(mockServiceInterface); } /** * Determines if an {@link AccessibilityEvent} passed as a method argument * matches expectations. * * @param matched The event to check. * @return True if expectations are matched. */ private static AccessibilityEvent eqAccessibilityEvent(AccessibilityEvent matched) { reportMatcher(new AccessibilityEventMather(matched)); return null; } /** * Determines if an {@link IAccessibilityManagerClient} passed as a method argument * matches expectations which in this case are that any instance is accepted. * * @return null. */ private static IAccessibilityManagerClient anyIAccessibilityManagerClient() { reportMatcher(new AnyIAccessibilityManagerClientMather()); return null; } /** * Matcher for {@link AccessibilityEvent}s. */ private static class AccessibilityEventMather implements IArgumentMatcher { private AccessibilityEvent mExpectedEvent; public AccessibilityEventMather(AccessibilityEvent expectedEvent) { mExpectedEvent = expectedEvent; } public boolean matches(Object matched) { if (!(matched instanceof AccessibilityEvent)) { return false; } AccessibilityEvent receivedEvent = (AccessibilityEvent) matched; return mExpectedEvent.getEventType() == receivedEvent.getEventType(); } public void appendTo(StringBuffer buffer) { buffer.append("sendAccessibilityEvent()"); buffer.append(" with event type \""); buffer.append(mExpectedEvent.getEventType()); buffer.append("\""); } } /** * Matcher for {@link IAccessibilityManagerClient}s. */ private static class AnyIAccessibilityManagerClientMather implements IArgumentMatcher { public boolean matches(Object matched) { if (!(matched instanceof IAccessibilityManagerClient)) { return false; } return true; } public void appendTo(StringBuffer buffer) { buffer.append("addClient() with any IAccessibilityManagerClient"); } } }