1 /* 2 ** Copyright 2017, 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.accessibility; 18 19 import static junit.framework.Assert.assertFalse; 20 import static junit.framework.Assert.assertTrue; 21 22 import static org.mockito.ArgumentMatchers.any; 23 import static org.mockito.ArgumentMatchers.anyInt; 24 import static org.mockito.ArgumentMatchers.eq; 25 import static org.mockito.Mockito.mock; 26 import static org.mockito.Mockito.never; 27 import static org.mockito.Mockito.times; 28 import static org.mockito.Mockito.verify; 29 import static org.mockito.Mockito.when; 30 31 import android.accessibilityservice.AccessibilityServiceInfo; 32 import android.accessibilityservice.AccessibilityTrace; 33 import android.accessibilityservice.GestureDescription; 34 import android.accessibilityservice.IAccessibilityServiceClient; 35 import android.content.ComponentName; 36 import android.content.Context; 37 import android.content.Intent; 38 import android.content.pm.ApplicationInfo; 39 import android.content.pm.ParceledListSlice; 40 import android.content.pm.ResolveInfo; 41 import android.content.pm.ServiceInfo; 42 import android.os.IBinder; 43 import android.os.RemoteException; 44 import android.os.UserHandle; 45 import android.testing.DexmakerShareClassLoaderRule; 46 import android.view.Display; 47 48 import com.android.server.accessibility.magnification.MagnificationProcessor; 49 import com.android.server.accessibility.test.MessageCapturingHandler; 50 import com.android.server.wm.ActivityTaskManagerInternal; 51 import com.android.server.wm.WindowManagerInternal; 52 53 import org.junit.After; 54 import org.junit.Before; 55 import org.junit.Rule; 56 import org.junit.Test; 57 import org.mockito.Mock; 58 import org.mockito.MockitoAnnotations; 59 60 import java.util.Arrays; 61 import java.util.Collections; 62 import java.util.HashSet; 63 import java.util.List; 64 65 66 /** 67 * Tests for AccessibilityServiceConnection 68 */ 69 public class AccessibilityServiceConnectionTest { 70 static final ComponentName COMPONENT_NAME = new ComponentName( 71 "com.android.server.accessibility", "AccessibilityServiceConnectionTest"); 72 static final int SERVICE_ID = 42; 73 74 // Mock package-private AccessibilityUserState class 75 @Rule 76 public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = 77 new DexmakerShareClassLoaderRule(); 78 79 AccessibilityServiceConnection mConnection; 80 81 @Mock AccessibilityUserState mMockUserState; 82 @Mock Context mMockContext; 83 @Mock AccessibilityServiceInfo mMockServiceInfo; 84 @Mock ResolveInfo mMockResolveInfo; 85 @Mock AccessibilitySecurityPolicy mMockSecurityPolicy; 86 @Mock AccessibilityWindowManager mMockA11yWindowManager; 87 @Mock ActivityTaskManagerInternal mMockActivityTaskManagerInternal; 88 @Mock AbstractAccessibilityServiceConnection.SystemSupport mMockSystemSupport; 89 @Mock AccessibilityTrace mMockA11yTrace; 90 @Mock WindowManagerInternal mMockWindowManagerInternal; 91 @Mock SystemActionPerformer mMockSystemActionPerformer; 92 @Mock KeyEventDispatcher mMockKeyEventDispatcher; 93 @Mock 94 MagnificationProcessor mMockMagnificationProcessor; 95 @Mock IBinder mMockIBinder; 96 @Mock IAccessibilityServiceClient mMockServiceClient; 97 @Mock MotionEventInjector mMockMotionEventInjector; 98 99 MessageCapturingHandler mHandler = new MessageCapturingHandler(null); 100 101 @Before setup()102 public void setup() { 103 MockitoAnnotations.initMocks(this); 104 when(mMockSystemSupport.getKeyEventDispatcher()).thenReturn(mMockKeyEventDispatcher); 105 when(mMockSystemSupport.getMagnificationProcessor()) 106 .thenReturn(mMockMagnificationProcessor); 107 when(mMockSystemSupport.getMotionEventInjectorForDisplayLocked( 108 Display.DEFAULT_DISPLAY)).thenReturn(mMockMotionEventInjector); 109 110 when(mMockServiceInfo.getResolveInfo()).thenReturn(mMockResolveInfo); 111 mMockResolveInfo.serviceInfo = mock(ServiceInfo.class); 112 mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class); 113 114 when(mMockIBinder.queryLocalInterface(any())).thenReturn(mMockServiceClient); 115 when(mMockA11yTrace.isA11yTracingEnabled()).thenReturn(false); 116 117 mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext, 118 COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, mHandler, new Object(), 119 mMockSecurityPolicy, mMockSystemSupport, mMockA11yTrace, 120 mMockWindowManagerInternal, mMockSystemActionPerformer, 121 mMockA11yWindowManager, mMockActivityTaskManagerInternal); 122 when(mMockSecurityPolicy.canPerformGestures(mConnection)).thenReturn(true); 123 } 124 125 @After tearDown()126 public void tearDown() { 127 mHandler.removeAllMessages(); 128 } 129 130 131 @Test bind_requestsContextToBindService()132 public void bind_requestsContextToBindService() { 133 mConnection.bindLocked(); 134 verify(mMockContext).bindServiceAsUser(any(Intent.class), eq(mConnection), 135 eq(Context.BIND_AUTO_CREATE 136 | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE 137 | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS 138 | Context.BIND_INCLUDE_CAPABILITIES), 139 any(UserHandle.class)); 140 } 141 142 @Test unbind_requestsContextToUnbindService()143 public void unbind_requestsContextToUnbindService() { 144 mConnection.unbindLocked(); 145 verify(mMockContext).unbindService(mConnection); 146 } 147 148 @Test bindConnectUnbind_linksAndUnlinksToServiceDeath()149 public void bindConnectUnbind_linksAndUnlinksToServiceDeath() throws RemoteException { 150 setServiceBinding(COMPONENT_NAME); 151 mConnection.bindLocked(); 152 mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); 153 verify(mMockIBinder).linkToDeath(eq(mConnection), anyInt()); 154 mConnection.unbindLocked(); 155 verify(mMockIBinder).unlinkToDeath(eq(mConnection), anyInt()); 156 } 157 158 @Test connectedServiceCrashedAndRestarted_crashReportedInServiceInfo()159 public void connectedServiceCrashedAndRestarted_crashReportedInServiceInfo() { 160 setServiceBinding(COMPONENT_NAME); 161 mConnection.bindLocked(); 162 mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); 163 assertFalse(mConnection.getServiceInfo().crashed); 164 mConnection.binderDied(); 165 assertTrue(mConnection.getServiceInfo().crashed); 166 mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); 167 mHandler.sendAllMessages(); 168 assertFalse(mConnection.getServiceInfo().crashed); 169 } 170 setServiceBinding(ComponentName componentName)171 private void setServiceBinding(ComponentName componentName) { 172 when(mMockUserState.getBindingServicesLocked()) 173 .thenReturn(new HashSet<>(Arrays.asList(componentName))); 174 } 175 176 @Test binderDied_keysGetFlushed()177 public void binderDied_keysGetFlushed() { 178 setServiceBinding(COMPONENT_NAME); 179 mConnection.bindLocked(); 180 mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); 181 mConnection.binderDied(); 182 assertTrue(mConnection.getServiceInfo().crashed); 183 verify(mMockKeyEventDispatcher).flush(mConnection); 184 } 185 186 @Test connectedService_notInEnabledServiceList_doNotInitClient()187 public void connectedService_notInEnabledServiceList_doNotInitClient() 188 throws RemoteException { 189 when(mMockUserState.getEnabledServicesLocked()) 190 .thenReturn(Collections.emptySet()); 191 setServiceBinding(COMPONENT_NAME); 192 193 mConnection.bindLocked(); 194 mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); 195 mHandler.sendAllMessages(); 196 verify(mMockSystemSupport, times(2)).onClientChangeLocked(false); 197 verify(mMockServiceClient, times(0)).init(any(), anyInt(), any()); 198 } 199 200 @Test sendGesture_touchableDevice_injectEvents()201 public void sendGesture_touchableDevice_injectEvents() 202 throws RemoteException { 203 when(mMockWindowManagerInternal.isTouchOrFaketouchDevice()).thenReturn(true); 204 setServiceBinding(COMPONENT_NAME); 205 mConnection.bindLocked(); 206 mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); 207 208 ParceledListSlice parceledListSlice = mock(ParceledListSlice.class); 209 List<GestureDescription.GestureStep> gestureSteps = mock(List.class); 210 when(parceledListSlice.getList()).thenReturn(gestureSteps); 211 mConnection.dispatchGesture(0, parceledListSlice, Display.DEFAULT_DISPLAY); 212 213 verify(mMockMotionEventInjector).injectEvents(gestureSteps, mMockServiceClient, 0, 214 Display.DEFAULT_DISPLAY); 215 } 216 217 @Test sendGesture_untouchableDevice_performGestureResultFailed()218 public void sendGesture_untouchableDevice_performGestureResultFailed() 219 throws RemoteException { 220 when(mMockWindowManagerInternal.isTouchOrFaketouchDevice()).thenReturn(false); 221 setServiceBinding(COMPONENT_NAME); 222 mConnection.bindLocked(); 223 mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); 224 225 ParceledListSlice parceledListSlice = mock(ParceledListSlice.class); 226 List<GestureDescription.GestureStep> gestureSteps = mock(List.class); 227 when(parceledListSlice.getList()).thenReturn(gestureSteps); 228 mConnection.dispatchGesture(0, parceledListSlice, Display.DEFAULT_DISPLAY); 229 230 verify(mMockMotionEventInjector, never()).injectEvents(gestureSteps, mMockServiceClient, 0, 231 Display.DEFAULT_DISPLAY); 232 verify(mMockServiceClient).onPerformGestureResult(0, false); 233 } 234 235 @Test sendGesture_invalidDisplay_performGestureResultFailed()236 public void sendGesture_invalidDisplay_performGestureResultFailed() 237 throws RemoteException { 238 setServiceBinding(COMPONENT_NAME); 239 mConnection.bindLocked(); 240 mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); 241 242 ParceledListSlice parceledListSlice = mock(ParceledListSlice.class); 243 List<GestureDescription.GestureStep> gestureSteps = mock(List.class); 244 when(parceledListSlice.getList()).thenReturn(gestureSteps); 245 mConnection.dispatchGesture(0, parceledListSlice, Display.INVALID_DISPLAY); 246 247 verify(mMockServiceClient).onPerformGestureResult(0, false); 248 } 249 250 @Test unbind_resetAllMagnification()251 public void unbind_resetAllMagnification() { 252 mConnection.unbindLocked(); 253 verify(mMockMagnificationProcessor).resetAllIfNeeded(anyInt()); 254 } 255 256 @Test binderDied_resetAllMagnification()257 public void binderDied_resetAllMagnification() { 258 setServiceBinding(COMPONENT_NAME); 259 mConnection.bindLocked(); 260 mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); 261 262 mConnection.binderDied(); 263 264 verify(mMockMagnificationProcessor).resetAllIfNeeded(anyInt()); 265 } 266 267 } 268