1 /* 2 * Copyright (C) 2022 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.ProxyManager.PROXY_COMPONENT_CLASS_NAME; 20 import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_PACKAGE_NAME; 21 22 import android.accessibilityservice.AccessibilityServiceInfo; 23 import android.accessibilityservice.AccessibilityTrace; 24 import android.accessibilityservice.IAccessibilityServiceClient; 25 import android.accessibilityservice.MagnificationConfig; 26 import android.annotation.NonNull; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.pm.ApplicationInfo; 30 import android.content.pm.ParceledListSlice; 31 import android.content.pm.ResolveInfo; 32 import android.content.pm.ServiceInfo; 33 import android.graphics.Region; 34 import android.os.Binder; 35 import android.os.Handler; 36 import android.os.IBinder; 37 import android.os.RemoteCallback; 38 import android.os.RemoteException; 39 import android.view.KeyEvent; 40 import android.view.accessibility.AccessibilityDisplayProxy; 41 import android.view.accessibility.AccessibilityEvent; 42 import android.view.accessibility.AccessibilityNodeInfo; 43 import android.view.accessibility.AccessibilityWindowInfo; 44 45 import androidx.annotation.Nullable; 46 47 import com.android.internal.R; 48 import com.android.internal.util.DumpUtils; 49 import com.android.server.wm.WindowManagerInternal; 50 51 import java.io.FileDescriptor; 52 import java.io.PrintWriter; 53 import java.util.Arrays; 54 import java.util.Collections; 55 import java.util.HashSet; 56 import java.util.List; 57 import java.util.Set; 58 59 /** 60 * Represents the system connection to an {@link AccessibilityDisplayProxy}. 61 * 62 * <p>Most methods are no-ops since this connection does not need to capture input or listen to 63 * hardware-related changes. 64 * 65 * TODO(241429275): Initialize this when a proxy is registered. 66 */ 67 public class ProxyAccessibilityServiceConnection extends AccessibilityServiceConnection { 68 private static final String LOG_TAG = "ProxyAccessibilityServiceConnection"; 69 70 private int mDeviceId; 71 private int mDisplayId; 72 private List<AccessibilityServiceInfo> mInstalledAndEnabledServices; 73 74 /** The stroke width of the focus rectangle in pixels */ 75 private int mFocusStrokeWidth; 76 /** The color of the focus rectangle */ 77 private int mFocusColor; 78 79 private int mInteractiveTimeout; 80 private int mNonInteractiveTimeout; 81 ProxyAccessibilityServiceConnection( Context context, ComponentName componentName, AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport, AccessibilityTrace trace, WindowManagerInternal windowManagerInternal, AccessibilityWindowManager awm, int displayId, int deviceId)82 ProxyAccessibilityServiceConnection( 83 Context context, 84 ComponentName componentName, 85 AccessibilityServiceInfo accessibilityServiceInfo, int id, 86 Handler mainHandler, Object lock, 87 AccessibilitySecurityPolicy securityPolicy, 88 SystemSupport systemSupport, AccessibilityTrace trace, 89 WindowManagerInternal windowManagerInternal, 90 AccessibilityWindowManager awm, int displayId, int deviceId) { 91 super(/* userState= */null, context, componentName, accessibilityServiceInfo, id, 92 mainHandler, lock, securityPolicy, systemSupport, trace, windowManagerInternal, 93 /* systemActionPerformer= */ null, awm, /* activityTaskManagerService= */ null); 94 mDisplayId = displayId; 95 setDisplayTypes(DISPLAY_TYPE_PROXY); 96 mFocusStrokeWidth = mContext.getResources().getDimensionPixelSize( 97 R.dimen.accessibility_focus_highlight_stroke_width); 98 mFocusColor = mContext.getResources().getColor( 99 R.color.accessibility_focus_highlight_color); 100 mDeviceId = deviceId; 101 } 102 getDisplayId()103 int getDisplayId() { 104 return mDisplayId; 105 } getDeviceId()106 int getDeviceId() { 107 return mDeviceId; 108 } 109 110 /** 111 * Called when the proxy is registered. 112 */ initializeServiceInterface(IAccessibilityServiceClient serviceInterface)113 void initializeServiceInterface(IAccessibilityServiceClient serviceInterface) 114 throws RemoteException { 115 mServiceInterface = serviceInterface; 116 mService = serviceInterface.asBinder(); 117 mServiceInterface.init(this, mId, this.mOverlayWindowTokens.get(mDisplayId)); 118 } 119 120 /** 121 * Keeps mAccessibilityServiceInfo in sync with the proxy's list of AccessibilityServiceInfos. 122 * 123 * <p>This also sets the properties that are assumed to be populated by installed packages. 124 * 125 * @param infos the list of enabled and installed services. 126 */ 127 @Override setInstalledAndEnabledServices(List<AccessibilityServiceInfo> infos)128 public void setInstalledAndEnabledServices(List<AccessibilityServiceInfo> infos) { 129 final long identity = Binder.clearCallingIdentity(); 130 try { 131 synchronized (mLock) { 132 mInstalledAndEnabledServices = infos; 133 final AccessibilityServiceInfo proxyInfo = mAccessibilityServiceInfo; 134 // Reset values. mAccessibilityServiceInfo is not completely reset since it is final 135 proxyInfo.flags = 0; 136 proxyInfo.eventTypes = 0; 137 proxyInfo.notificationTimeout = 0; 138 final Set<String> packageNames = new HashSet<>(); 139 boolean hasNullPackagesNames = false; 140 boolean isAccessibilityTool = false; 141 int interactiveUiTimeout = 0; 142 int nonInteractiveUiTimeout = 0; 143 144 // Go through and set properties that are relevant to the proxy. This bypasses 145 // A11yServiceInfo.updateDynamicallyConfigurableProperties since the proxy has 146 // higher security privileges as a SystemAPI and has to set values at runtime. 147 for (AccessibilityServiceInfo info : infos) { 148 isAccessibilityTool = isAccessibilityTool | info.isAccessibilityTool(); 149 if (info.packageNames == null || info.packageNames.length == 0) { 150 hasNullPackagesNames = true; 151 } else if (!hasNullPackagesNames) { 152 packageNames.addAll(Arrays.asList(info.packageNames)); 153 } 154 interactiveUiTimeout = Math.max(interactiveUiTimeout, 155 info.getInteractiveUiTimeoutMillis()); 156 nonInteractiveUiTimeout = Math.max(nonInteractiveUiTimeout, 157 info.getNonInteractiveUiTimeoutMillis()); 158 proxyInfo.notificationTimeout = Math.max(proxyInfo.notificationTimeout, 159 info.notificationTimeout); 160 proxyInfo.eventTypes |= info.eventTypes; 161 proxyInfo.feedbackType |= info.feedbackType; 162 proxyInfo.flags |= info.flags; 163 // For each info, populate default properties like ResolveInfo. 164 setDefaultPropertiesIfNullLocked(info); 165 } 166 167 proxyInfo.setAccessibilityTool(isAccessibilityTool); 168 proxyInfo.setInteractiveUiTimeoutMillis(interactiveUiTimeout); 169 proxyInfo.setNonInteractiveUiTimeoutMillis(nonInteractiveUiTimeout); 170 mInteractiveTimeout = interactiveUiTimeout; 171 mNonInteractiveTimeout = nonInteractiveUiTimeout; 172 173 // If any one service info doesn't set package names, i.e. if it's interested in all 174 // apps, the proxy shouldn't filter by package name even if some infos specify this. 175 if (hasNullPackagesNames) { 176 proxyInfo.packageNames = null; 177 } else { 178 proxyInfo.packageNames = packageNames.toArray(new String[0]); 179 } 180 181 // Update connection with mAccessibilityServiceInfo values. 182 setDynamicallyConfigurableProperties(proxyInfo); 183 // Notify manager service. 184 mSystemSupport.onProxyChanged(mDeviceId); 185 } 186 } finally { 187 Binder.restoreCallingIdentity(identity); 188 } 189 } 190 setDefaultPropertiesIfNullLocked(AccessibilityServiceInfo info)191 private void setDefaultPropertiesIfNullLocked(AccessibilityServiceInfo info) { 192 final String componentClassDisplayName = PROXY_COMPONENT_CLASS_NAME + mDisplayId; 193 // Populate the properties that can't be null, since this may cause crashes in apps that 194 // assume these are populated by an installed package. 195 if (info.getResolveInfo() == null) { 196 final ResolveInfo resolveInfo = new ResolveInfo(); 197 final ServiceInfo serviceInfo = new ServiceInfo(); 198 final ApplicationInfo applicationInfo = new ApplicationInfo(); 199 200 serviceInfo.packageName = PROXY_COMPONENT_PACKAGE_NAME; 201 serviceInfo.name = componentClassDisplayName; 202 203 applicationInfo.processName = PROXY_COMPONENT_PACKAGE_NAME; 204 applicationInfo.className = componentClassDisplayName; 205 206 resolveInfo.serviceInfo = serviceInfo; 207 serviceInfo.applicationInfo = applicationInfo; 208 info.setResolveInfo(resolveInfo); 209 } 210 211 if (info.getComponentName() == null) { 212 info.setComponentName(new ComponentName(PROXY_COMPONENT_PACKAGE_NAME, 213 componentClassDisplayName)); 214 } 215 } 216 217 @Override getInstalledAndEnabledServices()218 public List<AccessibilityServiceInfo> getInstalledAndEnabledServices() { 219 synchronized (mLock) { 220 return mInstalledAndEnabledServices; 221 } 222 } 223 224 @Override getWindows()225 public AccessibilityWindowInfo.WindowListSparseArray getWindows() { 226 final AccessibilityWindowInfo.WindowListSparseArray allWindows = super.getWindows(); 227 AccessibilityWindowInfo.WindowListSparseArray displayWindows = new 228 AccessibilityWindowInfo.WindowListSparseArray(); 229 // Filter here so A11yInteractionClient will not cache all the windows belonging to other 230 // proxy connections. 231 displayWindows.put(mDisplayId, allWindows.get(mDisplayId, Collections.emptyList())); 232 return displayWindows; 233 } 234 235 @Override setFocusAppearance(int strokeWidth, int color)236 public void setFocusAppearance(int strokeWidth, int color) { 237 synchronized (mLock) { 238 if (!hasRightsToCurrentUserLocked()) { 239 return; 240 } 241 242 if (!mSecurityPolicy.checkAccessibilityAccess(this)) { 243 return; 244 } 245 246 if (getFocusStrokeWidthLocked() == strokeWidth && getFocusColorLocked() == color) { 247 return; 248 } 249 250 mFocusStrokeWidth = strokeWidth; 251 mFocusColor = color; 252 mSystemSupport.onProxyChanged(mDeviceId); 253 } 254 } 255 256 /** 257 * Gets the stroke width of the focus rectangle. 258 * @return The stroke width. 259 */ getFocusStrokeWidthLocked()260 public int getFocusStrokeWidthLocked() { 261 return mFocusStrokeWidth; 262 } 263 264 /** 265 * Gets the color of the focus rectangle. 266 * @return The color. 267 */ getFocusColorLocked()268 public int getFocusColorLocked() { 269 return mFocusColor; 270 } 271 272 @Override resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType)273 int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) { 274 if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) { 275 final int focusedWindowId = mA11yWindowManager.getFocusedWindowId(focusType, 276 mDisplayId); 277 // If the caller is a proxy and the found window doesn't belong to a proxy display 278 // (or vice versa), then return null. This doesn't work if there are multiple active 279 // proxys, but in the future this code shouldn't be needed if input focus 280 // properly split. (so we will deal with the issues if we see them). 281 //TODO(254545943): Remove this when there is user and proxy separation of input 282 if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) { 283 return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID; 284 } 285 return focusedWindowId; 286 } 287 return windowId; 288 } 289 290 @Override binderDied()291 public void binderDied() { 292 } 293 294 @Override supportsFlagForNotImportantViews(AccessibilityServiceInfo info)295 protected boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) { 296 // Don't need to check for earlier APIs. 297 return true; 298 } 299 300 @Override hasRightsToCurrentUserLocked()301 protected boolean hasRightsToCurrentUserLocked() { 302 // TODO(250929565): Proxy access is not currently determined by user. Adjust in refactoring. 303 return true; 304 } 305 306 /** @throws UnsupportedOperationException since a proxy does not need key events */ 307 @Override onKeyEvent(KeyEvent keyEvent, int sequenceNumber)308 public boolean onKeyEvent(KeyEvent keyEvent, int sequenceNumber) 309 throws UnsupportedOperationException { 310 throw new UnsupportedOperationException("onKeyEvent is not supported"); 311 } 312 313 /** @throws UnsupportedOperationException since a proxy does not need fingerprint hardware */ 314 @Override isCapturingFingerprintGestures()315 public boolean isCapturingFingerprintGestures() throws UnsupportedOperationException { 316 throw new UnsupportedOperationException("isCapturingFingerprintGestures is not supported"); 317 } 318 319 /** @throws UnsupportedOperationException since a proxy does not need fingerprint hardware */ 320 @Override onFingerprintGestureDetectionActiveChanged(boolean active)321 public void onFingerprintGestureDetectionActiveChanged(boolean active) 322 throws UnsupportedOperationException { 323 throw new UnsupportedOperationException("onFingerprintGestureDetectionActiveChanged is not" 324 + " supported"); 325 } 326 327 /** @throws UnsupportedOperationException since a proxy does not need fingerprint hardware */ 328 @Override onFingerprintGesture(int gesture)329 public void onFingerprintGesture(int gesture) throws UnsupportedOperationException { 330 throw new UnsupportedOperationException("onFingerprintGesture is not supported"); 331 } 332 333 /** @throws UnsupportedOperationException since a proxy does not need fingerprint hardware */ 334 @Override isFingerprintGestureDetectionAvailable()335 public boolean isFingerprintGestureDetectionAvailable() throws UnsupportedOperationException { 336 throw new UnsupportedOperationException("isFingerprintGestureDetectionAvailable is not" 337 + " supported"); 338 } 339 340 /** @throws UnsupportedOperationException since a proxy is not a Service */ 341 @Override onServiceConnected(ComponentName name, IBinder service)342 public void onServiceConnected(ComponentName name, IBinder service) 343 throws UnsupportedOperationException { 344 throw new UnsupportedOperationException("onServiceConnected is not supported"); 345 346 } 347 348 /** @throws UnsupportedOperationException since a proxy is not a Service */ 349 @Override onServiceDisconnected(ComponentName name)350 public void onServiceDisconnected(ComponentName name) 351 throws UnsupportedOperationException { 352 throw new UnsupportedOperationException("onServiceDisconnected is not supported"); 353 } 354 355 /** @throws UnsupportedOperationException since a proxy should use 356 * setInstalledAndEnabledServices*/ 357 @Override setServiceInfo(AccessibilityServiceInfo info)358 public void setServiceInfo(AccessibilityServiceInfo info) 359 throws UnsupportedOperationException { 360 // TODO(241429275): Ensure getServiceInfo is called appropriately for a proxy or is a no-op. 361 throw new UnsupportedOperationException("setServiceInfo is not supported"); 362 } 363 364 /** @throws UnsupportedOperationException since a proxy should use A11yManager#unregister */ 365 @Override disableSelf()366 public void disableSelf() throws UnsupportedOperationException { 367 // A proxy uses A11yManager#unregister to turn itself off. 368 throw new UnsupportedOperationException("disableSelf is not supported"); 369 } 370 371 /** @throws UnsupportedOperationException since a proxy does not have global system access */ 372 @Override performGlobalAction(int action)373 public boolean performGlobalAction(int action) throws UnsupportedOperationException { 374 throw new UnsupportedOperationException("performGlobalAction is not supported"); 375 } 376 377 /** @throws UnsupportedOperationException since a proxy does not need key events */ 378 @Override setOnKeyEventResult(boolean handled, int sequence)379 public void setOnKeyEventResult(boolean handled, int sequence) 380 throws UnsupportedOperationException { 381 throw new UnsupportedOperationException("setOnKeyEventResult is not supported"); 382 } 383 384 /** @throws UnsupportedOperationException since a proxy does not have global system access */ 385 @Override getSystemActions()386 public @NonNull List<AccessibilityNodeInfo.AccessibilityAction> getSystemActions() 387 throws UnsupportedOperationException { 388 throw new UnsupportedOperationException("getSystemActions is not supported"); 389 } 390 391 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 392 @Nullable 393 @Override getMagnificationConfig(int displayId)394 public MagnificationConfig getMagnificationConfig(int displayId) 395 throws UnsupportedOperationException { 396 throw new UnsupportedOperationException("getMagnificationConfig is not supported"); 397 } 398 399 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 400 @Override getMagnificationScale(int displayId)401 public float getMagnificationScale(int displayId) throws UnsupportedOperationException { 402 throw new UnsupportedOperationException("getMagnificationScale is not supported"); 403 } 404 405 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 406 @Override getMagnificationCenterX(int displayId)407 public float getMagnificationCenterX(int displayId) throws UnsupportedOperationException { 408 throw new UnsupportedOperationException("getMagnificationCenterX is not supported"); 409 } 410 411 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 412 @Override getMagnificationCenterY(int displayId)413 public float getMagnificationCenterY(int displayId) throws UnsupportedOperationException { 414 throw new UnsupportedOperationException("getMagnificationCenterY is not supported"); 415 } 416 417 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 418 @Override getMagnificationRegion(int displayId)419 public Region getMagnificationRegion(int displayId) throws UnsupportedOperationException { 420 throw new UnsupportedOperationException("getMagnificationRegion is not supported"); 421 } 422 423 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 424 @Override getCurrentMagnificationRegion(int displayId)425 public Region getCurrentMagnificationRegion(int displayId) 426 throws UnsupportedOperationException { 427 throw new UnsupportedOperationException("getCurrentMagnificationRegion is not supported"); 428 } 429 430 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 431 @Override resetMagnification(int displayId, boolean animate)432 public boolean resetMagnification(int displayId, boolean animate) 433 throws UnsupportedOperationException { 434 throw new UnsupportedOperationException("resetMagnification is not supported"); 435 } 436 437 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 438 @Override resetCurrentMagnification(int displayId, boolean animate)439 public boolean resetCurrentMagnification(int displayId, boolean animate) 440 throws UnsupportedOperationException { 441 throw new UnsupportedOperationException("resetCurrentMagnification is not supported"); 442 } 443 444 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 445 @Override setMagnificationConfig(int displayId, @androidx.annotation.NonNull MagnificationConfig config, boolean animate)446 public boolean setMagnificationConfig(int displayId, 447 @androidx.annotation.NonNull MagnificationConfig config, boolean animate) 448 throws UnsupportedOperationException { 449 throw new UnsupportedOperationException("setMagnificationConfig is not supported"); 450 } 451 452 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 453 @Override setMagnificationCallbackEnabled(int displayId, boolean enabled)454 public void setMagnificationCallbackEnabled(int displayId, boolean enabled) 455 throws UnsupportedOperationException { 456 throw new UnsupportedOperationException("setMagnificationCallbackEnabled is not supported"); 457 } 458 459 /** @throws UnsupportedOperationException since a proxy does not need magnification */ 460 @Override isMagnificationCallbackEnabled(int displayId)461 public boolean isMagnificationCallbackEnabled(int displayId) { 462 throw new UnsupportedOperationException("isMagnificationCallbackEnabled is not supported"); 463 } 464 465 /** @throws UnsupportedOperationException since a proxy does not need IME access*/ 466 @Override setSoftKeyboardShowMode(int showMode)467 public boolean setSoftKeyboardShowMode(int showMode) throws UnsupportedOperationException { 468 throw new UnsupportedOperationException("setSoftKeyboardShowMode is not supported"); 469 } 470 471 /** @throws UnsupportedOperationException since a proxy does not need IME access */ 472 @Override getSoftKeyboardShowMode()473 public int getSoftKeyboardShowMode() throws UnsupportedOperationException { 474 throw new UnsupportedOperationException("getSoftKeyboardShowMode is not supported"); 475 } 476 477 /** @throws UnsupportedOperationException since a proxy does not need IME access */ 478 @Override setSoftKeyboardCallbackEnabled(boolean enabled)479 public void setSoftKeyboardCallbackEnabled(boolean enabled) 480 throws UnsupportedOperationException { 481 throw new UnsupportedOperationException("setSoftKeyboardCallbackEnabled is not supported"); 482 } 483 484 /** @throws UnsupportedOperationException since a proxy does not need IME access */ 485 @Override switchToInputMethod(String imeId)486 public boolean switchToInputMethod(String imeId) throws UnsupportedOperationException { 487 throw new UnsupportedOperationException("switchToInputMethod is not supported"); 488 } 489 490 /** @throws UnsupportedOperationException since a proxy does not need IME access */ 491 @Override setInputMethodEnabled(String imeId, boolean enabled)492 public int setInputMethodEnabled(String imeId, boolean enabled) 493 throws UnsupportedOperationException { 494 throw new UnsupportedOperationException("setInputMethodEnabled is not supported"); 495 } 496 497 /** @throws UnsupportedOperationException since a proxy does not need access to the shortcut */ 498 @Override isAccessibilityButtonAvailable()499 public boolean isAccessibilityButtonAvailable() throws UnsupportedOperationException { 500 throw new UnsupportedOperationException("isAccessibilityButtonAvailable is not supported"); 501 } 502 503 /** @throws UnsupportedOperationException since a proxy does not need gestures/input access */ 504 @Override sendGesture(int sequence, ParceledListSlice gestureSteps)505 public void sendGesture(int sequence, ParceledListSlice gestureSteps) 506 throws UnsupportedOperationException { 507 throw new UnsupportedOperationException("sendGesture is not supported"); 508 } 509 510 /** @throws UnsupportedOperationException since a proxy does not need gestures/input access */ 511 @Override dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId)512 public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) 513 throws UnsupportedOperationException { 514 throw new UnsupportedOperationException("dispatchGesture is not supported"); 515 } 516 517 /** @throws UnsupportedOperationException since a proxy does not need access to screenshots */ 518 @Override takeScreenshot(int displayId, RemoteCallback callback)519 public void takeScreenshot(int displayId, RemoteCallback callback) 520 throws UnsupportedOperationException { 521 throw new UnsupportedOperationException("takeScreenshot is not supported"); 522 } 523 524 /** @throws UnsupportedOperationException since a proxy does not need gestures/input access */ 525 @Override setGestureDetectionPassthroughRegion(int displayId, Region region)526 public void setGestureDetectionPassthroughRegion(int displayId, Region region) 527 throws UnsupportedOperationException { 528 throw new UnsupportedOperationException("setGestureDetectionPassthroughRegion is not" 529 + " supported"); 530 } 531 532 /** @throws UnsupportedOperationException since a proxy does not need gestures/input access */ 533 @Override setTouchExplorationPassthroughRegion(int displayId, Region region)534 public void setTouchExplorationPassthroughRegion(int displayId, Region region) 535 throws UnsupportedOperationException { 536 throw new UnsupportedOperationException("setTouchExplorationPassthroughRegion is not" 537 + " supported"); 538 } 539 540 /** @throws UnsupportedOperationException since a proxy does not need gestures/input access */ 541 @Override setServiceDetectsGesturesEnabled(int displayId, boolean mode)542 public void setServiceDetectsGesturesEnabled(int displayId, boolean mode) 543 throws UnsupportedOperationException { 544 throw new UnsupportedOperationException("setServiceDetectsGesturesEnabled is not" 545 + " supported"); 546 } 547 548 /** @throws UnsupportedOperationException since a proxy does not need touch input access */ 549 @Override requestTouchExploration(int displayId)550 public void requestTouchExploration(int displayId) throws UnsupportedOperationException { 551 throw new UnsupportedOperationException("requestTouchExploration is not supported"); 552 } 553 554 /** @throws UnsupportedOperationException since a proxy does not need touch input access */ 555 @Override requestDragging(int displayId, int pointerId)556 public void requestDragging(int displayId, int pointerId) throws UnsupportedOperationException { 557 throw new UnsupportedOperationException("requestDragging is not supported"); 558 } 559 560 /** @throws UnsupportedOperationException since a proxy does not need touch input access */ 561 @Override requestDelegating(int displayId)562 public void requestDelegating(int displayId) throws UnsupportedOperationException { 563 throw new UnsupportedOperationException("requestDelegating is not supported"); 564 } 565 566 /** @throws UnsupportedOperationException since a proxy does not need touch input access */ 567 @Override onDoubleTap(int displayId)568 public void onDoubleTap(int displayId) throws UnsupportedOperationException { 569 throw new UnsupportedOperationException("onDoubleTap is not supported"); 570 } 571 572 /** @throws UnsupportedOperationException since a proxy does not need touch input access */ 573 @Override onDoubleTapAndHold(int displayId)574 public void onDoubleTapAndHold(int displayId) throws UnsupportedOperationException { 575 throw new UnsupportedOperationException("onDoubleTapAndHold is not supported"); 576 } 577 578 /** @throws UnsupportedOperationException since a proxy does not need touch input access */ 579 @Override setAnimationScale(float scale)580 public void setAnimationScale(float scale) throws UnsupportedOperationException { 581 throw new UnsupportedOperationException("setAnimationScale is not supported"); 582 } 583 getInteractiveTimeout()584 public int getInteractiveTimeout() { 585 return mInteractiveTimeout; 586 } 587 getNonInteractiveTimeout()588 public int getNonInteractiveTimeout() { 589 return mNonInteractiveTimeout; 590 } 591 592 /** 593 * Returns true if a timeout was updated. 594 */ updateTimeouts(int nonInteractiveUiTimeout, int interactiveUiTimeout)595 public boolean updateTimeouts(int nonInteractiveUiTimeout, int interactiveUiTimeout) { 596 final int newInteractiveUiTimeout = interactiveUiTimeout != 0 597 ? interactiveUiTimeout 598 : mAccessibilityServiceInfo.getInteractiveUiTimeoutMillis(); 599 final int newNonInteractiveUiTimeout = nonInteractiveUiTimeout != 0 600 ? nonInteractiveUiTimeout 601 : mAccessibilityServiceInfo.getNonInteractiveUiTimeoutMillis(); 602 boolean updated = false; 603 604 if (mInteractiveTimeout != newInteractiveUiTimeout) { 605 mInteractiveTimeout = newInteractiveUiTimeout; 606 updated = true; 607 } 608 if (mNonInteractiveTimeout != newNonInteractiveUiTimeout) { 609 mNonInteractiveTimeout = newNonInteractiveUiTimeout; 610 updated = true; 611 } 612 return updated; 613 } 614 615 @Override dump(FileDescriptor fd, final PrintWriter pw, String[] args)616 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 617 if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return; 618 synchronized (mLock) { 619 pw.append("Proxy[displayId=" + mDisplayId); 620 pw.append(", deviceId=" + mDeviceId); 621 pw.append(", feedbackType" 622 + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType)); 623 pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities()); 624 pw.append(", eventTypes=" 625 + AccessibilityEvent.eventTypeToString(mEventTypes)); 626 pw.append(", notificationTimeout=" + mNotificationTimeout); 627 pw.append(", nonInteractiveUiTimeout=").append(String.valueOf(mNonInteractiveTimeout)); 628 pw.append(", interactiveUiTimeout=").append(String.valueOf(mInteractiveTimeout)); 629 pw.append(", focusStrokeWidth=").append(String.valueOf(mFocusStrokeWidth)); 630 pw.append(", focusColor=").append(String.valueOf(mFocusColor)); 631 pw.append(", installedAndEnabledServiceCount=").append(String.valueOf( 632 mInstalledAndEnabledServices.size())); 633 pw.append(", installedAndEnabledServices=").append( 634 mInstalledAndEnabledServices.toString()); 635 pw.append("]"); 636 } 637 } 638 } 639