1 /* 2 * Copyright (C) 2023 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 com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.INTERACTIVE_UI_TIMEOUT_100MS; 20 import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.INTERACTIVE_UI_TIMEOUT_200MS; 21 import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.NON_INTERACTIVE_UI_TIMEOUT_100MS; 22 import static com.android.server.accessibility.ProxyAccessibilityServiceConnectionTest.NON_INTERACTIVE_UI_TIMEOUT_200MS; 23 import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_CLASS_NAME; 24 import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_PACKAGE_NAME; 25 26 import static org.junit.Assert.fail; 27 28 import android.accessibilityservice.AccessibilityGestureEvent; 29 import android.accessibilityservice.AccessibilityServiceInfo; 30 import android.accessibilityservice.AccessibilityTrace; 31 import android.accessibilityservice.IAccessibilityServiceClient; 32 import android.accessibilityservice.IAccessibilityServiceConnection; 33 import android.accessibilityservice.MagnificationConfig; 34 import android.companion.virtual.IVirtualDeviceManager; 35 import android.companion.virtual.VirtualDeviceManager; 36 import android.content.ComponentName; 37 import android.content.Context; 38 import android.content.res.Resources; 39 import android.graphics.Region; 40 import android.os.IBinder; 41 import android.os.RemoteCallbackList; 42 import android.os.RemoteException; 43 import android.util.ArraySet; 44 import android.view.KeyEvent; 45 import android.view.MotionEvent; 46 import android.view.accessibility.AccessibilityEvent; 47 import android.view.accessibility.AccessibilityManager; 48 import android.view.accessibility.IAccessibilityManagerClient; 49 import android.view.inputmethod.EditorInfo; 50 51 import com.android.internal.R; 52 import com.android.internal.inputmethod.IAccessibilityInputMethodSession; 53 import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback; 54 import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection; 55 import com.android.internal.util.IntPair; 56 import com.android.server.LocalServices; 57 import com.android.server.accessibility.test.MessageCapturingHandler; 58 import com.android.server.companion.virtual.VirtualDeviceManagerInternal; 59 import com.android.server.wm.WindowManagerInternal; 60 61 import static com.google.common.truth.Truth.assertThat; 62 63 import androidx.test.InstrumentationRegistry; 64 65 import static org.mockito.ArgumentMatchers.any; 66 import static org.mockito.ArgumentMatchers.anyInt; 67 import static org.mockito.Mockito.never; 68 import static org.mockito.Mockito.verify; 69 import static org.mockito.Mockito.when; 70 71 import org.junit.After; 72 import org.junit.Before; 73 import org.junit.Test; 74 import org.mockito.Mock; 75 import org.mockito.MockitoAnnotations; 76 77 import java.util.ArrayList; 78 import java.util.List; 79 import java.util.Set; 80 81 /** 82 * Tests for ProxyManager. 83 */ 84 public class ProxyManagerTest { 85 private static final int DISPLAY_ID = 1000; 86 private static final int DISPLAY_2_ID = 1001; 87 private static final int DEVICE_ID = 10; 88 private static final int STREAMED_CALLING_UID = 9876; 89 90 @Mock private Context mMockContext; 91 @Mock private AccessibilitySecurityPolicy mMockSecurityPolicy; 92 @Mock private AccessibilityWindowManager mMockA11yWindowManager; 93 @Mock private ProxyManager.SystemSupport mMockProxySystemSupport; 94 @Mock private AbstractAccessibilityServiceConnection.SystemSupport mMockConnectionSystemSupport; 95 @Mock private AccessibilityTrace mMockA11yTrace; 96 @Mock private WindowManagerInternal mMockWindowManagerInternal; 97 @Mock private IAccessibilityServiceClient mMockAccessibilityServiceClient; 98 @Mock private IBinder mMockServiceAsBinder; 99 @Mock private VirtualDeviceManagerInternal mMockVirtualDeviceManagerInternal; 100 @Mock private IVirtualDeviceManager mMockIVirtualDeviceManager; 101 102 private int mFocusStrokeWidthDefaultValue; 103 private int mFocusColorDefaultValue; 104 105 private MessageCapturingHandler mMessageCapturingHandler = new MessageCapturingHandler(null); 106 private ProxyManager mProxyManager; 107 108 @Before setup()109 public void setup() throws RemoteException { 110 MockitoAnnotations.initMocks(this); 111 final Resources resources = InstrumentationRegistry.getContext().getResources(); 112 113 mFocusStrokeWidthDefaultValue = 114 resources.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width); 115 mFocusColorDefaultValue = resources.getColor(R.color.accessibility_focus_highlight_color); 116 when(mMockContext.getResources()).thenReturn(resources); 117 118 when(mMockVirtualDeviceManagerInternal.getDeviceIdsForUid(anyInt())).thenReturn( 119 new ArraySet(Set.of(DEVICE_ID))); 120 LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class); 121 LocalServices.addService(VirtualDeviceManagerInternal.class, 122 mMockVirtualDeviceManagerInternal); 123 124 when(mMockIVirtualDeviceManager.getDeviceIdForDisplayId(anyInt())).thenReturn(DEVICE_ID); 125 final VirtualDeviceManager virtualDeviceManager = 126 new VirtualDeviceManager(mMockIVirtualDeviceManager, mMockContext); 127 when(mMockContext.getSystemServiceName(VirtualDeviceManager.class)).thenReturn( 128 Context.VIRTUAL_DEVICE_SERVICE); 129 when(mMockContext.getSystemService(VirtualDeviceManager.class)) 130 .thenReturn(virtualDeviceManager); 131 132 when(mMockA11yTrace.isA11yTracingEnabled()).thenReturn(false); 133 134 final RemoteCallbackList<IAccessibilityManagerClient> userClients = 135 new RemoteCallbackList<>(); 136 final RemoteCallbackList<IAccessibilityManagerClient> globalClients = 137 new RemoteCallbackList<>(); 138 when(mMockProxySystemSupport.getCurrentUserClientsLocked()).thenReturn(userClients); 139 when(mMockProxySystemSupport.getGlobalClientsLocked()).thenReturn(globalClients); 140 141 when(mMockAccessibilityServiceClient.asBinder()).thenReturn(mMockServiceAsBinder); 142 143 mProxyManager = new ProxyManager(new Object(), mMockA11yWindowManager, mMockContext, 144 mMessageCapturingHandler, new UiAutomationManager(new Object()), 145 mMockProxySystemSupport); 146 } 147 148 @After tearDown()149 public void tearDown() { 150 mMessageCapturingHandler.removeAllMessages(); 151 } 152 153 /** 154 * Tests that the proxy’s backing AccessibilityServiceClient is initialized when registering a 155 * proxy. 156 */ 157 @Test registerProxy_always_connectsServiceClient()158 public void registerProxy_always_connectsServiceClient() throws RemoteException { 159 registerProxy(DISPLAY_ID); 160 verify(mMockAccessibilityServiceClient).init(any(), anyInt(), any()); 161 } 162 163 /** Tests that unregistering a proxy removes its display from tracking. */ 164 @Test unregisterProxy_always_stopsTrackingDisplay()165 public void unregisterProxy_always_stopsTrackingDisplay() { 166 registerProxy(DISPLAY_ID); 167 168 mProxyManager.unregisterProxy(DISPLAY_ID); 169 170 verify(mMockA11yWindowManager).stopTrackingDisplayProxy(DISPLAY_ID); 171 assertThat(mProxyManager.isProxyedDisplay(DISPLAY_ID)).isFalse(); 172 } 173 /** 174 * Tests that unregistering a proxied display of a virtual device, where that virtual device 175 * owned only that one proxied display, removes the device from tracking. 176 */ 177 @Test unregisterProxy_deviceAssociatedWithSingleDisplay_stopsTrackingDevice()178 public void unregisterProxy_deviceAssociatedWithSingleDisplay_stopsTrackingDevice() { 179 registerProxy(DISPLAY_ID); 180 181 mProxyManager.unregisterProxy(DISPLAY_ID); 182 183 assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isFalse(); 184 verify(mMockProxySystemSupport).removeDeviceIdLocked(DEVICE_ID); 185 } 186 187 /** 188 * Tests that unregistering a proxied display of a virtual device, where that virtual device 189 * owns more than one proxied display, does not remove the device from tracking. 190 */ 191 @Test unregisterProxy_deviceAssociatedWithMultipleDisplays_tracksRemainingProxy()192 public void unregisterProxy_deviceAssociatedWithMultipleDisplays_tracksRemainingProxy() { 193 registerProxy(DISPLAY_ID); 194 registerProxy(DISPLAY_2_ID); 195 196 mProxyManager.unregisterProxy(DISPLAY_ID); 197 198 assertThat(mProxyManager.isProxyedDeviceId(DEVICE_ID)).isTrue(); 199 verify(mMockProxySystemSupport, never()).removeDeviceIdLocked(DEVICE_ID); 200 } 201 202 /** 203 * Tests that changing a proxy, e.g. registering/unregistering a proxy or updating its service 204 * info, notifies the apps being streamed and AccessibilityManagerService. 205 */ 206 @Test testOnProxyChanged_always_propagatesChange()207 public void testOnProxyChanged_always_propagatesChange() { 208 registerProxy(DISPLAY_ID); 209 mMessageCapturingHandler.sendAllMessages(); 210 211 mProxyManager.onProxyChanged(DEVICE_ID); 212 213 // Messages to notify IAccessibilityManagerClients should be posted. 214 assertThat(mMessageCapturingHandler.hasMessages()).isTrue(); 215 216 verify(mMockProxySystemSupport).updateWindowsForAccessibilityCallbackLocked(); 217 verify(mMockProxySystemSupport).notifyClearAccessibilityCacheLocked(); 218 } 219 220 /** 221 * Tests that getting the first device id for an app uid, such as when an app queries for 222 * device-specific state, returns the right device id. 223 */ 224 @Test testGetFirstDeviceForUid_streamedAppQueriesState_getsHostDeviceId()225 public void testGetFirstDeviceForUid_streamedAppQueriesState_getsHostDeviceId() { 226 registerProxy(DISPLAY_ID); 227 assertThat(mProxyManager.getFirstDeviceIdForUidLocked(STREAMED_CALLING_UID)) 228 .isEqualTo(DEVICE_ID); 229 } 230 231 /** 232 * Tests that the app client state retrieved for a device reflects that touch exploration is 233 * enabled since a proxy info has requested touch exploration. 234 */ 235 @Test testGetClientState_proxyWantsTouchExploration_returnsTouchExplorationEnabled()236 public void testGetClientState_proxyWantsTouchExploration_returnsTouchExplorationEnabled() { 237 registerProxy(DISPLAY_ID); 238 239 final AccessibilityServiceInfo secondDisplayInfo = new AccessibilityServiceInfo(); 240 secondDisplayInfo.flags |= AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE; 241 AccessibilityServiceClientImpl client = new AccessibilityServiceClientImpl( 242 secondDisplayInfo); 243 registerProxy(DISPLAY_2_ID, client); 244 245 final int deviceClientState = mProxyManager.getStateLocked(DEVICE_ID); 246 assertThat((deviceClientState 247 & AccessibilityManager.STATE_FLAG_TOUCH_EXPLORATION_ENABLED) != 0).isTrue(); 248 } 249 250 /** 251 * Tests that the highest interactive and non-interactive timeout is returned if there are 252 * multiple proxied displays belonging to a device. 253 */ 254 @Test testGetRecommendedTimeout_multipleProxies_returnsHighestTimeout()255 public void testGetRecommendedTimeout_multipleProxies_returnsHighestTimeout() { 256 final AccessibilityServiceInfo firstDisplayInfo = new AccessibilityServiceInfo(); 257 firstDisplayInfo.setInteractiveUiTimeoutMillis(INTERACTIVE_UI_TIMEOUT_100MS); 258 firstDisplayInfo.setNonInteractiveUiTimeoutMillis(NON_INTERACTIVE_UI_TIMEOUT_200MS); 259 260 final AccessibilityServiceInfo secondDisplayInfo = new AccessibilityServiceInfo(); 261 secondDisplayInfo.setInteractiveUiTimeoutMillis(INTERACTIVE_UI_TIMEOUT_200MS); 262 secondDisplayInfo.setNonInteractiveUiTimeoutMillis(NON_INTERACTIVE_UI_TIMEOUT_100MS); 263 264 registerProxy(DISPLAY_ID, new AccessibilityServiceClientImpl(firstDisplayInfo)); 265 registerProxy(DISPLAY_2_ID, new AccessibilityServiceClientImpl(secondDisplayInfo)); 266 267 final long timeout = mProxyManager.getRecommendedTimeoutMillisLocked(DEVICE_ID); 268 final int interactiveTimeout = IntPair.first(timeout); 269 final int nonInteractiveTimeout = IntPair.second(timeout); 270 271 assertThat(interactiveTimeout).isEqualTo(INTERACTIVE_UI_TIMEOUT_200MS); 272 assertThat(nonInteractiveTimeout).isEqualTo(NON_INTERACTIVE_UI_TIMEOUT_200MS); 273 } 274 /** 275 * Tests that getting the installed and enabled services returns the info of the registered 276 * proxy. (The component name reflects the display id.) 277 */ 278 @Test testGetInstalledAndEnabledServices_defaultInfo_returnsInfoForDisplayId()279 public void testGetInstalledAndEnabledServices_defaultInfo_returnsInfoForDisplayId() { 280 final AccessibilityServiceInfo info = new AccessibilityServiceInfo(); 281 registerProxy(DISPLAY_ID, new AccessibilityServiceClientImpl(info)); 282 final List<AccessibilityServiceInfo> installedAndEnabledServices = 283 mProxyManager.getInstalledAndEnabledServiceInfosLocked( 284 AccessibilityServiceInfo.FEEDBACK_ALL_MASK, DEVICE_ID); 285 assertThat(installedAndEnabledServices.size()).isEqualTo(1); 286 AccessibilityServiceInfo proxyInfo = installedAndEnabledServices.get(0); 287 288 assertThat(proxyInfo.getComponentName()).isEqualTo(new ComponentName( 289 PROXY_COMPONENT_PACKAGE_NAME, PROXY_COMPONENT_CLASS_NAME + DISPLAY_ID)); 290 } 291 292 /** 293 * Tests that the app client state retrieved for a device reflects that accessibility is 294 * enabled. 295 */ 296 @Test testGetClientState_always_returnsAccessibilityEnabled()297 public void testGetClientState_always_returnsAccessibilityEnabled() { 298 registerProxy(DISPLAY_ID); 299 300 final int deviceClientState = mProxyManager.getStateLocked(DEVICE_ID); 301 assertThat((deviceClientState 302 & AccessibilityManager.STATE_FLAG_ACCESSIBILITY_ENABLED) != 0).isTrue(); 303 } 304 305 /** 306 * Tests that the manager can retrieve interactive windows if a proxy sets 307 * AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS. 308 */ 309 @Test testCanRetrieveInteractiveWindows_atLeastOneProxyWantsWindows_returnsTrue()310 public void testCanRetrieveInteractiveWindows_atLeastOneProxyWantsWindows_returnsTrue() { 311 registerProxy(DISPLAY_ID); 312 313 final AccessibilityServiceInfo secondDisplayInfo = new AccessibilityServiceInfo(); 314 secondDisplayInfo.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS; 315 registerProxy(DISPLAY_2_ID, new AccessibilityServiceClientImpl(secondDisplayInfo)); 316 317 assertThat(mProxyManager.canRetrieveInteractiveWindowsLocked()).isTrue(); 318 } 319 320 /** 321 * Tests that getting service interfaces to interrupt when AccessibilityManager#interrupt 322 * returns the registered proxy interface. 323 */ 324 @Test testGetServiceInterfacesForInterrupt_defaultProxy_returnsProxyInterface()325 public void testGetServiceInterfacesForInterrupt_defaultProxy_returnsProxyInterface() { 326 registerProxy(DISPLAY_ID); 327 final List<IAccessibilityServiceClient> interfacesToInterrupt = new ArrayList<>(); 328 mProxyManager.addServiceInterfacesLocked(interfacesToInterrupt, DEVICE_ID); 329 330 assertThat(interfacesToInterrupt.size()).isEqualTo(1); 331 assertThat(interfacesToInterrupt.get(0).asBinder()).isEqualTo(mMockServiceAsBinder); 332 } 333 334 /** Tests that the default timeout (0) is returned when the proxy is registered. */ 335 @Test getRecommendedTimeout_defaultProxyInfo_getsDefaultTimeout()336 public void getRecommendedTimeout_defaultProxyInfo_getsDefaultTimeout() { 337 registerProxy(DISPLAY_ID); 338 final long timeout = mProxyManager.getRecommendedTimeoutMillisLocked(DEVICE_ID); 339 final int interactiveTimeout = IntPair.first(timeout); 340 final int nonInteractiveTimeout = IntPair.second(timeout); 341 342 assertThat(interactiveTimeout).isEqualTo(0); 343 assertThat(nonInteractiveTimeout).isEqualTo(0); 344 } 345 346 /** Tests that the manager returns the updated timeout when the proxy’s timeout is updated. */ 347 @Test getRecommendedTimeout_updateTimeout_getsUpdatedTimeout()348 public void getRecommendedTimeout_updateTimeout_getsUpdatedTimeout() { 349 registerProxy(DISPLAY_ID); 350 351 mProxyManager.updateTimeoutsIfNeeded(NON_INTERACTIVE_UI_TIMEOUT_100MS, 352 INTERACTIVE_UI_TIMEOUT_200MS); 353 354 final long updatedTimeout = mProxyManager.getRecommendedTimeoutMillisLocked(DEVICE_ID); 355 final int updatedInteractiveTimeout = IntPair.first(updatedTimeout); 356 final int updatedNonInteractiveTimeout = IntPair.second(updatedTimeout); 357 358 assertThat(updatedInteractiveTimeout).isEqualTo(INTERACTIVE_UI_TIMEOUT_200MS); 359 assertThat(updatedNonInteractiveTimeout).isEqualTo(NON_INTERACTIVE_UI_TIMEOUT_100MS); 360 } 361 362 /** Tests that the system’s default focus color is returned. */ 363 @Test testGetFocusColor_defaultProxy_getsDefaultSystemColor()364 public void testGetFocusColor_defaultProxy_getsDefaultSystemColor() { 365 registerProxy(DISPLAY_ID); 366 final int focusColor = mProxyManager.getFocusColorLocked(DEVICE_ID); 367 assertThat(focusColor).isEqualTo(mFocusColorDefaultValue); 368 } 369 370 /** Tests that the system’s default focus stroke width is returned. */ 371 @Test testGetFocusStrokeWidth_defaultProxy_getsDefaultSystemWidth()372 public void testGetFocusStrokeWidth_defaultProxy_getsDefaultSystemWidth() { 373 registerProxy(DISPLAY_ID); 374 final int focusStrokeWidth = mProxyManager.getFocusStrokeWidthLocked(DEVICE_ID); 375 assertThat(focusStrokeWidth).isEqualTo(mFocusStrokeWidthDefaultValue); 376 } 377 registerProxy(int displayId)378 private void registerProxy(int displayId) { 379 try { 380 mProxyManager.registerProxy(mMockAccessibilityServiceClient, displayId, anyInt(), 381 mMockSecurityPolicy, mMockConnectionSystemSupport, 382 mMockA11yTrace, mMockWindowManagerInternal); 383 } catch (RemoteException e) { 384 fail("Failed to register proxy " + e); 385 } 386 } 387 registerProxy(int displayId, AccessibilityServiceClientImpl serviceClient)388 private void registerProxy(int displayId, AccessibilityServiceClientImpl serviceClient) { 389 try { 390 mProxyManager.registerProxy(serviceClient, displayId, anyInt(), 391 mMockSecurityPolicy, mMockConnectionSystemSupport, 392 mMockA11yTrace, mMockWindowManagerInternal); 393 } catch (RemoteException e) { 394 fail("Failed to register proxy " + e); 395 } 396 } 397 398 /** 399 * IAccessibilityServiceClient implementation. 400 * A proxy connection does not populate non-default AccessibilityServiceInfo values until the 401 * proxy is connected in A11yDisplayProxy#onServiceConnected. For tests that check for 402 * non-default values, populate immediately in this testing class, since a real Service is not 403 * being used and connected. 404 */ 405 static class AccessibilityServiceClientImpl extends IAccessibilityServiceClient.Stub { 406 List<AccessibilityServiceInfo> mInstalledAndEnabledServices; 407 AccessibilityServiceClientImpl(AccessibilityServiceInfo installedAndEnabledService)408 AccessibilityServiceClientImpl(AccessibilityServiceInfo 409 installedAndEnabledService) { 410 mInstalledAndEnabledServices = List.of(installedAndEnabledService); 411 } 412 413 @Override init(IAccessibilityServiceConnection connection, int connectionId, IBinder windowToken)414 public void init(IAccessibilityServiceConnection connection, int connectionId, 415 IBinder windowToken) throws RemoteException { 416 connection.setInstalledAndEnabledServices(mInstalledAndEnabledServices); 417 } 418 419 @Override onAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent)420 public void onAccessibilityEvent(AccessibilityEvent event, boolean serviceWantsEvent) 421 throws RemoteException { 422 423 } 424 425 @Override onInterrupt()426 public void onInterrupt() throws RemoteException { 427 428 } 429 430 @Override onGesture(AccessibilityGestureEvent gestureEvent)431 public void onGesture(AccessibilityGestureEvent gestureEvent) throws RemoteException { 432 433 } 434 435 @Override clearAccessibilityCache()436 public void clearAccessibilityCache() throws RemoteException { 437 438 } 439 440 @Override onKeyEvent(KeyEvent event, int sequence)441 public void onKeyEvent(KeyEvent event, int sequence) throws RemoteException { 442 443 } 444 445 @Override onMagnificationChanged(int displayId, Region region, MagnificationConfig config)446 public void onMagnificationChanged(int displayId, Region region, MagnificationConfig config) 447 throws RemoteException { 448 449 } 450 451 @Override onMotionEvent(MotionEvent event)452 public void onMotionEvent(MotionEvent event) throws RemoteException { 453 454 } 455 456 @Override onTouchStateChanged(int displayId, int state)457 public void onTouchStateChanged(int displayId, int state) throws RemoteException { 458 459 } 460 461 @Override onSoftKeyboardShowModeChanged(int showMode)462 public void onSoftKeyboardShowModeChanged(int showMode) throws RemoteException { 463 464 } 465 466 @Override onPerformGestureResult(int sequence, boolean completedSuccessfully)467 public void onPerformGestureResult(int sequence, boolean completedSuccessfully) 468 throws RemoteException { 469 470 } 471 472 @Override onFingerprintCapturingGesturesChanged(boolean capturing)473 public void onFingerprintCapturingGesturesChanged(boolean capturing) 474 throws RemoteException { 475 476 } 477 478 @Override onFingerprintGesture(int gesture)479 public void onFingerprintGesture(int gesture) throws RemoteException { 480 481 } 482 483 @Override onAccessibilityButtonClicked(int displayId)484 public void onAccessibilityButtonClicked(int displayId) throws RemoteException { 485 486 } 487 488 @Override onAccessibilityButtonAvailabilityChanged(boolean available)489 public void onAccessibilityButtonAvailabilityChanged(boolean available) 490 throws RemoteException { 491 492 } 493 494 @Override onSystemActionsChanged()495 public void onSystemActionsChanged() throws RemoteException { 496 497 } 498 499 @Override createImeSession(IAccessibilityInputMethodSessionCallback callback)500 public void createImeSession(IAccessibilityInputMethodSessionCallback callback) 501 throws RemoteException { 502 503 } 504 505 @Override setImeSessionEnabled(IAccessibilityInputMethodSession session, boolean enabled)506 public void setImeSessionEnabled(IAccessibilityInputMethodSession session, boolean enabled) 507 throws RemoteException { 508 509 } 510 511 @Override bindInput()512 public void bindInput() throws RemoteException { 513 514 } 515 516 @Override unbindInput()517 public void unbindInput() throws RemoteException { 518 519 } 520 521 @Override startInput(IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting)522 public void startInput(IRemoteAccessibilityInputConnection connection, 523 EditorInfo editorInfo, boolean restarting) throws RemoteException { 524 525 } 526 } 527 } 528