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