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.content.pm.ServiceInfo; 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 59 public void setUp() throws Exception { 60 reset(mMockServiceInterface); 61 } 62 63 @MediumTest 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())).andReturn( 74 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); 75 expect(mockServiceInterface.getInstalledAccessibilityServiceList()).andReturn( 76 expectedServices); 77 replay(mockServiceInterface); 78 79 // invoke the method under test 80 AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface); 81 List<AccessibilityServiceInfo> receivedServices = 82 manager.getInstalledAccessibilityServiceList(); 83 84 // check expected result (list equals() compares it contents as well) 85 assertEquals("All expected services must be returned", receivedServices, expectedServices); 86 87 // verify the mock service was properly called 88 verify(mockServiceInterface); 89 } 90 91 @MediumTest 92 public void testInterrupt() throws Exception { 93 // configure the mock service behavior 94 IAccessibilityManager mockServiceInterface = mMockServiceInterface; 95 expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn( 96 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); 97 mockServiceInterface.interrupt(); 98 replay(mockServiceInterface); 99 100 // invoke the method under test 101 AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface); 102 manager.interrupt(); 103 104 // verify the mock service was properly called 105 verify(mockServiceInterface); 106 } 107 108 @LargeTest 109 public void testIsEnabled() throws Exception { 110 // configure the mock service behavior 111 IAccessibilityManager mockServiceInterface = mMockServiceInterface; 112 expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn( 113 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); 114 replay(mockServiceInterface); 115 116 // invoke the method under test 117 AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface); 118 boolean isEnabledServiceEnabled = manager.isEnabled(); 119 120 // check expected result 121 assertTrue("Must be enabled since the mock service is enabled", isEnabledServiceEnabled); 122 123 // disable accessibility 124 manager.getClient().setState(0); 125 126 // wait for the asynchronous IBinder call to complete 127 Thread.sleep(TIMEOUT_BINDER_CALL); 128 129 // invoke the method under test 130 boolean isEnabledServcieDisabled = manager.isEnabled(); 131 132 // check expected result 133 assertFalse("Must be disabled since the mock service is disabled", 134 isEnabledServcieDisabled); 135 136 // verify the mock service was properly called 137 verify(mockServiceInterface); 138 } 139 140 @MediumTest 141 public void testSendAccessibilityEvent_AccessibilityEnabled() throws Exception { 142 // create an event to be dispatched 143 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 144 145 // configure the mock service behavior 146 IAccessibilityManager mockServiceInterface = mMockServiceInterface; 147 expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn( 148 AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED); 149 expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent))) 150 .andReturn(true); 151 expect(mockServiceInterface.sendAccessibilityEvent(eqAccessibilityEvent(sentEvent))) 152 .andReturn(false); 153 replay(mockServiceInterface); 154 155 // invoke the method under test (manager and service in different processes) 156 AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface); 157 manager.sendAccessibilityEvent(sentEvent); 158 159 // check expected result 160 AccessibilityEvent nextEventDifferentProcesses = AccessibilityEvent.obtain(); 161 assertSame("The manager and the service are in different processes, so the event must be " + 162 "recycled", sentEvent, nextEventDifferentProcesses); 163 164 // invoke the method under test (manager and service in the same process) 165 manager.sendAccessibilityEvent(sentEvent); 166 167 // check expected result 168 AccessibilityEvent nextEventSameProcess = AccessibilityEvent.obtain(); 169 assertNotSame("The manager and the service are in the same process, so the event must not" + 170 "be recycled", sentEvent, nextEventSameProcess); 171 172 // verify the mock service was properly called 173 verify(mockServiceInterface); 174 } 175 176 @MediumTest 177 public void testSendAccessibilityEvent_AccessibilityDisabled() throws Exception { 178 // create an event to be dispatched 179 AccessibilityEvent sentEvent = AccessibilityEvent.obtain(); 180 181 // configure the mock service behavior 182 IAccessibilityManager mockServiceInterface = mMockServiceInterface; 183 expect(mockServiceInterface.addClient(anyIAccessibilityManagerClient())).andReturn(0); 184 replay(mockServiceInterface); 185 186 // invoke the method under test (accessibility disabled) 187 AccessibilityManager manager = new AccessibilityManager(mContext, mockServiceInterface); 188 try { 189 manager.sendAccessibilityEvent(sentEvent); 190 fail("No accessibility events are sent if accessibility is disabled"); 191 } catch (IllegalStateException ise) { 192 // check expected result 193 assertEquals("Accessibility off. Did you forget to check that?", ise.getMessage()); 194 } 195 196 // verify the mock service was properly called 197 verify(mockServiceInterface); 198 } 199 200 /** 201 * Determines if an {@link AccessibilityEvent} passed as a method argument 202 * matches expectations. 203 * 204 * @param matched The event to check. 205 * @return True if expectations are matched. 206 */ 207 private static AccessibilityEvent eqAccessibilityEvent(AccessibilityEvent matched) { 208 reportMatcher(new AccessibilityEventMather(matched)); 209 return null; 210 } 211 212 /** 213 * Determines if an {@link IAccessibilityManagerClient} passed as a method argument 214 * matches expectations which in this case are that any instance is accepted. 215 * 216 * @return <code>null</code>. 217 */ 218 private static IAccessibilityManagerClient anyIAccessibilityManagerClient() { 219 reportMatcher(new AnyIAccessibilityManagerClientMather()); 220 return null; 221 } 222 223 /** 224 * Matcher for {@link AccessibilityEvent}s. 225 */ 226 private static class AccessibilityEventMather implements IArgumentMatcher { 227 private AccessibilityEvent mExpectedEvent; 228 229 public AccessibilityEventMather(AccessibilityEvent expectedEvent) { 230 mExpectedEvent = expectedEvent; 231 } 232 233 public boolean matches(Object matched) { 234 if (!(matched instanceof AccessibilityEvent)) { 235 return false; 236 } 237 AccessibilityEvent receivedEvent = (AccessibilityEvent) matched; 238 return mExpectedEvent.getEventType() == receivedEvent.getEventType(); 239 } 240 241 public void appendTo(StringBuffer buffer) { 242 buffer.append("sendAccessibilityEvent()"); 243 buffer.append(" with event type \""); 244 buffer.append(mExpectedEvent.getEventType()); 245 buffer.append("\""); 246 } 247 } 248 249 /** 250 * Matcher for {@link IAccessibilityManagerClient}s. 251 */ 252 private static class AnyIAccessibilityManagerClientMather implements IArgumentMatcher { 253 public boolean matches(Object matched) { 254 if (!(matched instanceof IAccessibilityManagerClient)) { 255 return false; 256 } 257 return true; 258 } 259 260 public void appendTo(StringBuffer buffer) { 261 buffer.append("addClient() with any IAccessibilityManagerClient"); 262 } 263 } 264 } 265