1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import static org.easymock.EasyMock.createStrictMock; 20 import static org.easymock.EasyMock.expect; 21 import static org.easymock.EasyMock.replay; 22 import static org.easymock.EasyMock.reportMatcher; 23 import static org.easymock.EasyMock.reset; 24 import static org.easymock.EasyMock.verify; 25 26 import org.easymock.IArgumentMatcher; 27 28 import android.accessibilityservice.AccessibilityServiceInfo; 29 import android.os.UserHandle; 30 import android.test.AndroidTestCase; 31 import android.test.suitebuilder.annotation.LargeTest; 32 import android.test.suitebuilder.annotation.MediumTest; 33 import android.view.accessibility.AccessibilityEvent; 34 import android.view.accessibility.AccessibilityManager; 35 import android.view.accessibility.IAccessibilityManager; 36 import android.view.accessibility.IAccessibilityManagerClient; 37 38 import java.util.ArrayList; 39 import java.util.List; 40 41 /** 42 * Tests for the AccessibilityManager which mocking the backing service. 43 */ 44 public class AccessibilityManagerTest extends AndroidTestCase { 45 46 /** 47 * Timeout required for pending Binder calls or event processing to 48 * complete. 49 */ 50 public static final long TIMEOUT_BINDER_CALL = 50; 51 52 /** 53 * The reusable mock {@link IAccessibilityManager}. 54 */ 55 private final IAccessibilityManager mMockServiceInterface = 56 createStrictMock(IAccessibilityManager.class); 57 58 @Override setUp()59 public void setUp() throws Exception { 60 reset(mMockServiceInterface); 61 } 62 63 @MediumTest testGetAccessibilityServiceList()64 public void testGetAccessibilityServiceList() throws Exception { 65 // create a list of installed accessibility services the mock service returns 66 List<AccessibilityServiceInfo> expectedServices = new ArrayList<AccessibilityServiceInfo>(); 67 AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo(); 68 accessibilityServiceInfo.packageNames = new String[] { "foo.bar" }; 69 expectedServices.add(accessibilityServiceInfo); 70 71 // configure the mock service behavior 72 IAccessibilityManager mockServiceInterface = mMockServiceInterface; 73 expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(), 74 UserHandle.USER_OWNER)).andReturn( 75 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); 76 expect(mockServiceInterface.getInstalledAccessibilityServiceList(UserHandle.USER_OWNER)) 77 .andReturn(expectedServices); 78 replay(mockServiceInterface); 79 80 // invoke the method under test 81 AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface, 82 UserHandle.USER_OWNER); 83 List<AccessibilityServiceInfo> receivedServices = 84 manager.getInstalledAccessibilityServiceList(); 85 86 // check expected result (list equals() compares it contents as well) 87 assertEquals("All expected services must be returned", receivedServices, expectedServices); 88 89 // verify the mock service was properly called 90 verify(mockServiceInterface); 91 } 92 93 @MediumTest testInterrupt()94 public void testInterrupt() throws Exception { 95 // configure the mock service behavior 96 IAccessibilityManager mockServiceInterface = mMockServiceInterface; 97 expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(), 98 UserHandle.USER_OWNER)).andReturn( 99 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); 100 mockServiceInterface.interrupt(UserHandle.USER_OWNER); 101 replay(mockServiceInterface); 102 103 // invoke the method under test 104 AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface, 105 UserHandle.USER_OWNER); 106 manager.interrupt(); 107 108 // verify the mock service was properly called 109 verify(mockServiceInterface); 110 } 111 112 @LargeTest testIsEnabled()113 public void testIsEnabled() throws Exception { 114 // configure the mock service behavior 115 IAccessibilityManager mockServiceInterface = mMockServiceInterface; 116 expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(), 117 UserHandle.USER_OWNER)).andReturn( 118 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); 119 replay(mockServiceInterface); 120 121 // invoke the method under test 122 AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface, 123 UserHandle.USER_OWNER); 124 boolean isEnabledServiceEnabled = manager.isEnabled(); 125 126 // check expected result 127 assertTrue("Must be enabled since the mock service is enabled", isEnabledServiceEnabled); 128 129 // disable accessibility 130 manager.getClient().setState(0); 131 132 // wait for the asynchronous IBinder call to complete 133 Thread.sleep(TIMEOUT_BINDER_CALL); 134 135 // invoke the method under test 136 boolean isEnabledServcieDisabled = manager.isEnabled(); 137 138 // check expected result 139 assertFalse("Must be disabled since the mock service is disabled", 140 isEnabledServcieDisabled); 141 142 // verify the mock service was properly called 143 verify(mockServiceInterface); 144 } 145 146 @MediumTest testSendAccessibilityEvent_AccessibilityEnabled()147 public void testSendAccessibilityEvent_AccessibilityEnabled() throws Exception { 148 // create an event to be dispatched 149 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 150 151 // configure the mock service behavior 152 IAccessibilityManager mockServiceInterface = mMockServiceInterface; 153 expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(), 154 UserHandle.USER_OWNER)).andReturn( 155 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); 156 expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent), 157 UserHandle.USER_OWNER)).andReturn(true); 158 expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent), 159 UserHandle.USER_OWNER)).andReturn(false); 160 replay(mockServiceInterface); 161 162 // invoke the method under test (manager and service in different processes) 163 AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface, 164 UserHandle.USER_OWNER); 165 manager.sendAccessibilityEvent(sentEvent); 166 167 // check expected result 168 AccessibilityEvent nextEventDifferentProcesses = AccessibilityEvent.obtain(); 169 assertSame("The manager and the service are in different processes, so the event must be " + 170 "recycled", sentEvent, nextEventDifferentProcesses); 171 172 // invoke the method under test (manager and service in the same process) 173 manager.sendAccessibilityEvent(sentEvent); 174 175 // check expected result 176 AccessibilityEvent nextEventSameProcess = AccessibilityEvent.obtain(); 177 assertNotSame("The manager and the service are in the same process, so the event must not" + 178 "be recycled", sentEvent, nextEventSameProcess); 179 180 // verify the mock service was properly called 181 verify(mockServiceInterface); 182 } 183 184 @MediumTest testSendAccessibilityEvent_AccessibilityDisabled()185 public void testSendAccessibilityEvent_AccessibilityDisabled() throws Exception { 186 // create an event to be dispatched 187 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 188 189 // configure the mock service behavior 190 IAccessibilityManager mockServiceInterface = mMockServiceInterface; 191 expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient(), 192 UserHandle.USER_OWNER)).andReturn(0); 193 replay(mockServiceInterface); 194 195 // invoke the method under test (accessibility disabled) 196 AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface, 197 UserHandle.USER_OWNER); 198 try { 199 manager.sendAccessibilityEvent(sentEvent); 200 fail("No accessibility events are sent if accessibility is disabled"); 201 } catch (IllegalStateException ise) { 202 // check expected result 203 assertEquals("Accessibility off. Did you forget to check that?", ise.getMessage()); 204 } 205 206 // verify the mock service was properly called 207 verify(mockServiceInterface); 208 } 209 210 /** 211 * Determines if an {@link AccessibilityEvent} passed as a method argument 212 * matches expectations. 213 * 214 * @param matched The event to check. 215 * @return True if expectations are matched. 216 */ eqAccessibilityEvent(AccessibilityEvent matched)217 private static AccessibilityEvent eqAccessibilityEvent(AccessibilityEvent matched) { 218 reportMatcher(new AccessibilityEventMather(matched)); 219 return null; 220 } 221 222 /** 223 * Determines if an {@link IAccessibilityManagerClient} passed as a method argument 224 * matches expectations which in this case are that any instance is accepted. 225 * 226 * @return <code>null</code>. 227 */ anyIAccessibilityManagerClient()228 private static IAccessibilityManagerClient anyIAccessibilityManagerClient() { 229 reportMatcher(new AnyIAccessibilityManagerClientMather()); 230 return null; 231 } 232 233 /** 234 * Matcher for {@link AccessibilityEvent}s. 235 */ 236 private static class AccessibilityEventMather implements IArgumentMatcher { 237 private AccessibilityEvent mExpectedEvent; 238 AccessibilityEventMather(AccessibilityEvent expectedEvent)239 public AccessibilityEventMather(AccessibilityEvent expectedEvent) { 240 mExpectedEvent = expectedEvent; 241 } 242 matches(Object matched)243 public boolean matches(Object matched) { 244 if (!(matched instanceof AccessibilityEvent)) { 245 return false; 246 } 247 AccessibilityEvent receivedEvent = (AccessibilityEvent) matched; 248 return mExpectedEvent.getEventType() == receivedEvent.getEventType(); 249 } 250 appendTo(StringBuffer buffer)251 public void appendTo(StringBuffer buffer) { 252 buffer.append("sendAccessibilityEvent()"); 253 buffer.append(" with event type \""); 254 buffer.append(mExpectedEvent.getEventType()); 255 buffer.append("\""); 256 } 257 } 258 259 /** 260 * Matcher for {@link IAccessibilityManagerClient}s. 261 */ 262 private static class AnyIAccessibilityManagerClientMather implements IArgumentMatcher { matches(Object matched)263 public boolean matches(Object matched) { 264 if (!(matched instanceof IAccessibilityManagerClient)) { 265 return false; 266 } 267 return true; 268 } 269 appendTo(StringBuffer buffer)270 public void appendTo(StringBuffer buffer) { 271 buffer.append("addClient() with any IAccessibilityManagerClient"); 272 } 273 } 274 } 275