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 android.view.accessibility; 18 19 import android.accessibilityservice.IAccessibilityServiceConnection; 20 import android.graphics.Region; 21 import android.os.Bundle; 22 import android.os.Process; 23 import android.os.RemoteException; 24 25 /** 26 * Minimal {@link IAccessibilityServiceConnection} implementation that interacts 27 * with the {@link android.view.AccessibilityInteractionController} of a 28 * {@link android.view.ViewRootImpl}. 29 * 30 * <p> 31 * Uses {@link android.view.ViewRootImpl}'s {@link IAccessibilityServiceConnection} that wraps 32 * {@link android.view.AccessibilityInteractionController} within the app process, so that no 33 * interprocess communication is performed. 34 * </p> 35 * 36 * <p> 37 * Only the following methods are supported: 38 * <li>{@link #findAccessibilityNodeInfoByAccessibilityId}</li> 39 * <li>{@link #findAccessibilityNodeInfosByText}</li> 40 * <li>{@link #findAccessibilityNodeInfosByViewId}</li> 41 * <li>{@link #findFocus}</li> 42 * <li>{@link #focusSearch}</li> 43 * <li>{@link #performAccessibilityAction}</li> 44 * </p> 45 * 46 * <p> 47 * Other methods are no-ops and return default values. 48 * </p> 49 */ 50 class DirectAccessibilityConnection extends IAccessibilityServiceConnection.Default { 51 private final IAccessibilityInteractionConnection mAccessibilityInteractionConnection; 52 private final AccessibilityManager mAccessibilityManager; 53 private final int mMyProcessId; 54 55 // Fetch all views, but do not use prefetching/cache since this "connection" does not 56 // receive cache invalidation events (as it is not linked to an AccessibilityService). 57 private static final int FETCH_FLAGS = 58 AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS 59 | AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS; 60 private static final Region INTERACTIVE_REGION = null; 61 DirectAccessibilityConnection( IAccessibilityInteractionConnection accessibilityInteractionConnection, AccessibilityManager accessibilityManager)62 DirectAccessibilityConnection( 63 IAccessibilityInteractionConnection accessibilityInteractionConnection, 64 AccessibilityManager accessibilityManager) { 65 mAccessibilityInteractionConnection = accessibilityInteractionConnection; 66 mAccessibilityManager = accessibilityManager; 67 mMyProcessId = Process.myPid(); 68 } 69 70 @Override findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, long threadId, Bundle arguments)71 public String[] findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId, 72 long accessibilityNodeId, int interactionId, 73 IAccessibilityInteractionConnectionCallback callback, int flags, long threadId, 74 Bundle arguments) throws RemoteException { 75 IAccessibilityManager.WindowTransformationSpec spec = 76 mAccessibilityManager.getWindowTransformationSpec(accessibilityWindowId); 77 mAccessibilityInteractionConnection.findAccessibilityNodeInfoByAccessibilityId( 78 accessibilityNodeId, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, 79 mMyProcessId, threadId, spec.magnificationSpec, spec.transformationMatrix, 80 arguments); 81 return new String[0]; 82 } 83 84 @Override findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId)85 public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId, 86 long accessibilityNodeId, String text, int interactionId, 87 IAccessibilityInteractionConnectionCallback callback, long threadId) 88 throws RemoteException { 89 IAccessibilityManager.WindowTransformationSpec spec = 90 mAccessibilityManager.getWindowTransformationSpec(accessibilityWindowId); 91 mAccessibilityInteractionConnection.findAccessibilityNodeInfosByText(accessibilityNodeId, 92 text, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, mMyProcessId, 93 threadId, spec.magnificationSpec, spec.transformationMatrix); 94 return new String[0]; 95 } 96 97 @Override findAccessibilityNodeInfosByViewId(int accessibilityWindowId, long accessibilityNodeId, String viewId, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId)98 public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId, 99 long accessibilityNodeId, String viewId, int interactionId, 100 IAccessibilityInteractionConnectionCallback callback, long threadId) 101 throws RemoteException { 102 IAccessibilityManager.WindowTransformationSpec spec = 103 mAccessibilityManager.getWindowTransformationSpec(accessibilityWindowId); 104 mAccessibilityInteractionConnection.findAccessibilityNodeInfosByViewId(accessibilityNodeId, 105 viewId, INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, mMyProcessId, 106 threadId, spec.magnificationSpec, spec.transformationMatrix); 107 return new String[0]; 108 } 109 110 @Override findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId)111 public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, 112 int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId) 113 throws RemoteException { 114 IAccessibilityManager.WindowTransformationSpec spec = 115 mAccessibilityManager.getWindowTransformationSpec(accessibilityWindowId); 116 mAccessibilityInteractionConnection.findFocus(accessibilityNodeId, focusType, 117 INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, mMyProcessId, threadId, 118 spec.magnificationSpec, spec.transformationMatrix); 119 return new String[0]; 120 } 121 122 @Override focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId)123 public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, 124 int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId) 125 throws RemoteException { 126 IAccessibilityManager.WindowTransformationSpec spec = 127 mAccessibilityManager.getWindowTransformationSpec(accessibilityWindowId); 128 mAccessibilityInteractionConnection.focusSearch(accessibilityNodeId, direction, 129 INTERACTIVE_REGION, interactionId, callback, FETCH_FLAGS, mMyProcessId, threadId, 130 spec.magnificationSpec, spec.transformationMatrix); 131 return new String[0]; 132 } 133 134 @Override performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long threadId)135 public boolean performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId, 136 int action, Bundle arguments, int interactionId, 137 IAccessibilityInteractionConnectionCallback callback, long threadId) 138 throws RemoteException { 139 mAccessibilityInteractionConnection.performAccessibilityAction(accessibilityNodeId, action, 140 arguments, interactionId, callback, FETCH_FLAGS, mMyProcessId, threadId); 141 return true; 142 } 143 } 144