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 android.accessibilityservice.AccessibilityService.ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS;
20 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE;
21 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER;
22 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_STATUS;
23 import static android.accessibilityservice.AccessibilityService.KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP;
24 import static android.accessibilityservice.AccessibilityServiceInfo.DEFAULT;
25 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION;
26 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CLIENT;
27 import static android.accessibilityservice.AccessibilityTrace.FLAGS_ACCESSIBILITY_SERVICE_CONNECTION;
28 import static android.accessibilityservice.AccessibilityTrace.FLAGS_WINDOW_MANAGER_INTERNAL;
29 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
30 import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
31 import static android.view.accessibility.AccessibilityInteractionClient.CALL_STACK;
32 import static android.view.accessibility.AccessibilityInteractionClient.IGNORE_CALL_STACK;
33 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS;
34 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS;
35 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_CLICK;
36 import static android.view.accessibility.AccessibilityNodeInfo.ACTION_LONG_CLICK;
37 
38 import android.accessibilityservice.AccessibilityGestureEvent;
39 import android.accessibilityservice.AccessibilityService;
40 import android.accessibilityservice.AccessibilityServiceInfo;
41 import android.accessibilityservice.AccessibilityTrace;
42 import android.accessibilityservice.IAccessibilityServiceClient;
43 import android.accessibilityservice.IAccessibilityServiceConnection;
44 import android.accessibilityservice.MagnificationConfig;
45 import android.annotation.IntDef;
46 import android.annotation.NonNull;
47 import android.annotation.Nullable;
48 import android.app.PendingIntent;
49 import android.content.ComponentName;
50 import android.content.Context;
51 import android.content.Intent;
52 import android.content.ServiceConnection;
53 import android.content.pm.PackageManager;
54 import android.content.pm.ParceledListSlice;
55 import android.graphics.ParcelableColorSpace;
56 import android.graphics.Region;
57 import android.hardware.HardwareBuffer;
58 import android.hardware.display.DisplayManager;
59 import android.hardware.display.DisplayManagerInternal;
60 import android.os.Binder;
61 import android.os.Build;
62 import android.os.Bundle;
63 import android.os.Handler;
64 import android.os.IBinder;
65 import android.os.Looper;
66 import android.os.Message;
67 import android.os.PowerManager;
68 import android.os.RemoteCallback;
69 import android.os.RemoteException;
70 import android.os.ServiceManager;
71 import android.os.SystemClock;
72 import android.os.Trace;
73 import android.provider.Settings;
74 import android.util.Pair;
75 import android.util.Slog;
76 import android.util.SparseArray;
77 import android.view.Display;
78 import android.view.InputDevice;
79 import android.view.KeyEvent;
80 import android.view.MagnificationSpec;
81 import android.view.MotionEvent;
82 import android.view.SurfaceControl;
83 import android.view.View;
84 import android.view.accessibility.AccessibilityCache;
85 import android.view.accessibility.AccessibilityEvent;
86 import android.view.accessibility.AccessibilityNodeInfo;
87 import android.view.accessibility.AccessibilityWindowInfo;
88 import android.view.accessibility.IAccessibilityInteractionConnectionCallback;
89 import android.view.inputmethod.EditorInfo;
90 import android.window.ScreenCapture;
91 import android.window.ScreenCapture.ScreenshotHardwareBuffer;
92 
93 import com.android.internal.annotations.GuardedBy;
94 import com.android.internal.compat.IPlatformCompat;
95 import com.android.internal.inputmethod.IAccessibilityInputMethodSession;
96 import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback;
97 import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
98 import com.android.internal.os.SomeArgs;
99 import com.android.internal.util.DumpUtils;
100 import com.android.internal.util.function.pooled.PooledLambda;
101 import com.android.server.LocalServices;
102 import com.android.server.accessibility.AccessibilityWindowManager.RemoteAccessibilityConnection;
103 import com.android.server.accessibility.magnification.MagnificationProcessor;
104 import com.android.server.inputmethod.InputMethodManagerInternal;
105 import com.android.server.wm.WindowManagerInternal;
106 
107 import java.io.FileDescriptor;
108 import java.io.PrintWriter;
109 import java.lang.annotation.Retention;
110 import java.lang.annotation.RetentionPolicy;
111 import java.util.ArrayList;
112 import java.util.Arrays;
113 import java.util.Collections;
114 import java.util.HashSet;
115 import java.util.List;
116 import java.util.NoSuchElementException;
117 import java.util.Set;
118 
119 /**
120  * This class represents an accessibility client - either an AccessibilityService or a UiAutomation.
121  * It is responsible for behavior common to both types of clients.
122  */
123 abstract class AbstractAccessibilityServiceConnection extends IAccessibilityServiceConnection.Stub
124         implements ServiceConnection, IBinder.DeathRecipient, KeyEventDispatcher.KeyEventFilter,
125         FingerprintGestureDispatcher.FingerprintGestureClient {
126     private static final boolean DEBUG = false;
127     private static final String LOG_TAG = "AbstractAccessibilityServiceConnection";
128     private static final String TRACE_SVC_CONN = LOG_TAG + ".IAccessibilityServiceConnection";
129     private static final String TRACE_SVC_CLIENT = LOG_TAG + ".IAccessibilityServiceClient";
130     private static final String TRACE_WM = "WindowManagerInternal";
131     private static final int WAIT_WINDOWS_TIMEOUT_MILLIS = 5000;
132 
133     /** Display type for displays associated with the default user of the device. */
134     public static final int DISPLAY_TYPE_DEFAULT = 1 << 0;
135     /** Display type for displays associated with an AccessibilityDisplayProxy user. */
136     public static final int DISPLAY_TYPE_PROXY = 1 << 1;
137 
138     protected static final String TAKE_SCREENSHOT = "takeScreenshot";
139     protected final Context mContext;
140     protected final SystemSupport mSystemSupport;
141     protected final WindowManagerInternal mWindowManagerService;
142     private final SystemActionPerformer mSystemActionPerformer;
143     final AccessibilityWindowManager mA11yWindowManager;
144     private final DisplayManager mDisplayManager;
145     private final PowerManager mPowerManager;
146     private final IPlatformCompat mIPlatformCompat;
147 
148     private final Handler mMainHandler;
149 
150     // Handler for scheduling method invocations on the main thread.
151     public final InvocationHandler mInvocationHandler;
152 
153     final int mId;
154 
155     protected final AccessibilityServiceInfo mAccessibilityServiceInfo;
156 
157     // Lock must match the one used by AccessibilityManagerService
158     protected final Object mLock;
159 
160     protected final AccessibilitySecurityPolicy mSecurityPolicy;
161     protected final AccessibilityTrace mTrace;
162 
163     // The attribution tag set by the service that is bound to this instance
164     protected String mAttributionTag;
165 
166     protected int mDisplayTypes = DISPLAY_TYPE_DEFAULT;
167 
168     // The service that's bound to this instance. Whenever this value is non-null, this
169     // object is registered as a death recipient
170     IBinder mService;
171 
172     IAccessibilityServiceClient mServiceInterface;
173 
174     int mEventTypes;
175 
176     int mFeedbackType;
177 
178     Set<String> mPackageNames = new HashSet<>();
179 
180     boolean mIsDefault;
181 
182     boolean mRequestTouchExplorationMode;
183 
184     private boolean mServiceHandlesDoubleTap;
185 
186     private boolean mRequestMultiFingerGestures;
187 
188     private boolean mRequestTwoFingerPassthrough;
189 
190     private boolean mSendMotionEvents;
191 
192     private SparseArray<Boolean> mServiceDetectsGestures = new SparseArray<>(0);
193     boolean mRequestFilterKeyEvents;
194 
195     boolean mRetrieveInteractiveWindows;
196 
197     boolean mCaptureFingerprintGestures;
198 
199     boolean mRequestAccessibilityButton;
200 
201     boolean mReceivedAccessibilityButtonCallbackSinceBind;
202 
203     boolean mLastAccessibilityButtonCallbackState;
204 
205     boolean mRequestImeApis;
206 
207     int mFetchFlags;
208 
209     long mNotificationTimeout;
210 
211     final ComponentName mComponentName;
212 
213     int mGenericMotionEventSources;
214 
215     // the events pending events to be dispatched to this service
216     final SparseArray<AccessibilityEvent> mPendingEvents = new SparseArray<>();
217 
218     /** Whether this service relies on its {@link AccessibilityCache} being up to date */
219     boolean mUsesAccessibilityCache = false;
220 
221     // Handler only for dispatching accessibility events since we use event
222     // types as message types allowing us to remove messages per event type.
223     public Handler mEventDispatchHandler;
224 
225     final SparseArray<IBinder> mOverlayWindowTokens = new SparseArray();
226 
227     /** The timestamp of requesting to take screenshot in milliseconds */
228     private long mRequestTakeScreenshotTimestampMs;
229     /**
230      * The timestamps of requesting to take a window screenshot in milliseconds,
231      * mapping from accessibility window id -> timestamp.
232      */
233     private SparseArray<Long> mRequestTakeScreenshotOfWindowTimestampMs = new SparseArray<>();
234 
235     /** @hide */
236     @Retention(RetentionPolicy.SOURCE)
237     @IntDef(flag = true, prefix = { "DISPLAY_TYPE_" }, value = {
238             DISPLAY_TYPE_DEFAULT,
239             DISPLAY_TYPE_PROXY
240     })
241     public @interface DisplayTypes {}
242 
243     public interface SystemSupport {
244         /**
245          * @return The current dispatcher for key events
246          */
getKeyEventDispatcher()247         @NonNull KeyEventDispatcher getKeyEventDispatcher();
248 
249         /**
250          * @param displayId The display id.
251          * @return The current injector of motion events used on the display, if one exists.
252          */
getMotionEventInjectorForDisplayLocked(int displayId)253         @Nullable MotionEventInjector getMotionEventInjectorForDisplayLocked(int displayId);
254 
255         /**
256          * @return The current dispatcher for fingerprint gestures, if one exists
257          */
getFingerprintGestureDispatcher()258         @Nullable FingerprintGestureDispatcher getFingerprintGestureDispatcher();
259 
260         /**
261          * @return The magnification processor
262          */
263         @NonNull
getMagnificationProcessor()264         MagnificationProcessor getMagnificationProcessor();
265 
266         /**
267          * Called back to notify system that the client has changed
268          * @param serviceInfoChanged True if the service's AccessibilityServiceInfo changed.
269          */
onClientChangeLocked(boolean serviceInfoChanged)270         void onClientChangeLocked(boolean serviceInfoChanged);
271 
272         /**
273          * Called back to notify the system the proxy client for a device has changed.
274          *
275          * Changes include if the proxy is unregistered, if its service info list has changed, or if
276          * its focus appearance has changed.
277          */
onProxyChanged(int deviceId)278         void onProxyChanged(int deviceId);
279 
getCurrentUserIdLocked()280         int getCurrentUserIdLocked();
281 
getWindowTransformationMatrixAndMagnificationSpec( int windowId)282         Pair<float[], MagnificationSpec> getWindowTransformationMatrixAndMagnificationSpec(
283                 int windowId);
284 
isAccessibilityButtonShown()285         boolean isAccessibilityButtonShown();
286 
287         /**
288          * Persists the component names in the specified setting in a
289          * colon separated fashion.
290          *
291          * @param settingName The setting name.
292          * @param componentNames The component names.
293          * @param userId The user id to persist the setting for.
294          */
persistComponentNamesToSettingLocked(String settingName, Set<ComponentName> componentNames, int userId)295         void persistComponentNamesToSettingLocked(String settingName,
296                 Set<ComponentName> componentNames, int userId);
297 
298         /* This is exactly PendingIntent.getActivity, separated out for testability */
getPendingIntentActivity(Context context, int requestCode, Intent intent, int flags)299         PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent,
300                 int flags);
301 
setGestureDetectionPassthroughRegion(int displayId, Region region)302         void setGestureDetectionPassthroughRegion(int displayId, Region region);
303 
setTouchExplorationPassthroughRegion(int displayId, Region region)304         void setTouchExplorationPassthroughRegion(int displayId, Region region);
305 
setServiceDetectsGesturesEnabled(int displayId, boolean mode)306         void setServiceDetectsGesturesEnabled(int displayId, boolean mode);
307 
requestTouchExploration(int displayId)308         void requestTouchExploration(int displayId);
309 
requestDragging(int displayId, int pointerId)310         void requestDragging(int displayId, int pointerId);
311 
requestDelegating(int displayId)312         void requestDelegating(int displayId);
313 
onDoubleTap(int displayId)314         void onDoubleTap(int displayId);
315 
onDoubleTapAndHold(int displayId)316         void onDoubleTapAndHold(int displayId);
317 
requestImeLocked(AbstractAccessibilityServiceConnection connection)318         void requestImeLocked(AbstractAccessibilityServiceConnection connection);
319 
unbindImeLocked(AbstractAccessibilityServiceConnection connection)320         void unbindImeLocked(AbstractAccessibilityServiceConnection connection);
321 
attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc)322         void attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc);
323 
324     }
325 
AbstractAccessibilityServiceConnection(Context context, ComponentName componentName, AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler, Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport, AccessibilityTrace trace, WindowManagerInternal windowManagerInternal, SystemActionPerformer systemActionPerfomer, AccessibilityWindowManager a11yWindowManager)326     public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName,
327             AccessibilityServiceInfo accessibilityServiceInfo, int id, Handler mainHandler,
328             Object lock, AccessibilitySecurityPolicy securityPolicy, SystemSupport systemSupport,
329             AccessibilityTrace trace, WindowManagerInternal windowManagerInternal,
330             SystemActionPerformer systemActionPerfomer,
331             AccessibilityWindowManager a11yWindowManager) {
332         mContext = context;
333         mWindowManagerService = windowManagerInternal;
334         mId = id;
335         mComponentName = componentName;
336         mAccessibilityServiceInfo = accessibilityServiceInfo;
337         mLock = lock;
338         mSecurityPolicy = securityPolicy;
339         mSystemActionPerformer = systemActionPerfomer;
340         mSystemSupport = systemSupport;
341         mTrace = trace;
342         mMainHandler = mainHandler;
343         mInvocationHandler = new InvocationHandler(mainHandler.getLooper());
344         mA11yWindowManager = a11yWindowManager;
345         mDisplayManager = (DisplayManager) context.getSystemService(Context.DISPLAY_SERVICE);
346         mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
347         mIPlatformCompat = IPlatformCompat.Stub.asInterface(
348                 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
349         mEventDispatchHandler = new Handler(mainHandler.getLooper()) {
350             @Override
351             public void handleMessage(Message message) {
352                 final int eventType =  message.what;
353                 AccessibilityEvent event = (AccessibilityEvent) message.obj;
354                 boolean serviceWantsEvent = message.arg1 != 0;
355                 notifyAccessibilityEventInternal(eventType, event, serviceWantsEvent);
356             }
357         };
358         setDynamicallyConfigurableProperties(accessibilityServiceInfo);
359     }
360 
361     @Override
onKeyEvent(KeyEvent keyEvent, int sequenceNumber)362     public boolean onKeyEvent(KeyEvent keyEvent, int sequenceNumber) {
363         if (!mRequestFilterKeyEvents || (mServiceInterface == null)) {
364             return false;
365         }
366         if((mAccessibilityServiceInfo.getCapabilities()
367                 & AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FILTER_KEY_EVENTS) == 0) {
368             return false;
369         }
370         if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
371             return false;
372         }
373         try {
374             if (svcClientTracingEnabled()) {
375                 logTraceSvcClient("onKeyEvent", keyEvent + ", " + sequenceNumber);
376             }
377             mServiceInterface.onKeyEvent(keyEvent, sequenceNumber);
378         } catch (RemoteException e) {
379             return false;
380         }
381         return true;
382     }
383 
setDynamicallyConfigurableProperties(AccessibilityServiceInfo info)384     public void setDynamicallyConfigurableProperties(AccessibilityServiceInfo info) {
385         mEventTypes = info.eventTypes;
386         mFeedbackType = info.feedbackType;
387         String[] packageNames = info.packageNames;
388         mPackageNames.clear();
389         if (packageNames != null) {
390             mPackageNames.addAll(Arrays.asList(packageNames));
391         }
392         mNotificationTimeout = info.notificationTimeout;
393         mIsDefault = (info.flags & DEFAULT) != 0;
394         mGenericMotionEventSources = info.getMotionEventSources();
395 
396         if (supportsFlagForNotImportantViews(info)) {
397             if ((info.flags & AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS) != 0) {
398                 mFetchFlags |=
399                         AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS;
400             } else {
401                 mFetchFlags &=
402                         ~AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS;
403             }
404         }
405 
406         if ((info.flags & AccessibilityServiceInfo.FLAG_REPORT_VIEW_IDS) != 0) {
407             mFetchFlags |= AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS;
408         } else {
409             mFetchFlags &= ~AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_REPORT_VIEW_IDS;
410         }
411 
412         if (mAccessibilityServiceInfo.isAccessibilityTool()) {
413             mFetchFlags |= AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL;
414         } else {
415             mFetchFlags &= ~AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL;
416         }
417 
418         mRequestTouchExplorationMode = (info.flags
419                 & AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE) != 0;
420         mServiceHandlesDoubleTap = (info.flags
421                 & AccessibilityServiceInfo.FLAG_SERVICE_HANDLES_DOUBLE_TAP) != 0;
422         mRequestMultiFingerGestures = (info.flags
423                 & AccessibilityServiceInfo.FLAG_REQUEST_MULTI_FINGER_GESTURES) != 0;
424         mRequestTwoFingerPassthrough =
425                 (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_2_FINGER_PASSTHROUGH) != 0;
426         mSendMotionEvents =
427                 (info.flags & AccessibilityServiceInfo.FLAG_SEND_MOTION_EVENTS) != 0;
428         mRequestFilterKeyEvents =
429                 (info.flags & AccessibilityServiceInfo.FLAG_REQUEST_FILTER_KEY_EVENTS) != 0;
430         mRetrieveInteractiveWindows = (info.flags
431                 & AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS) != 0;
432         mCaptureFingerprintGestures = (info.flags
433                 & AccessibilityServiceInfo.FLAG_REQUEST_FINGERPRINT_GESTURES) != 0;
434         mRequestAccessibilityButton = (info.flags
435                 & AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON) != 0;
436         mRequestImeApis = (info.flags
437                 & AccessibilityServiceInfo.FLAG_INPUT_METHOD_EDITOR) != 0;
438     }
439 
supportsFlagForNotImportantViews(AccessibilityServiceInfo info)440     protected boolean supportsFlagForNotImportantViews(AccessibilityServiceInfo info) {
441         return info.getResolveInfo().serviceInfo.applicationInfo.targetSdkVersion
442                 >= Build.VERSION_CODES.JELLY_BEAN;
443     }
444 
canReceiveEventsLocked()445     public boolean canReceiveEventsLocked() {
446         return (mEventTypes != 0 && mService != null);
447     }
448 
449     @Override
setOnKeyEventResult(boolean handled, int sequence)450     public void setOnKeyEventResult(boolean handled, int sequence) {
451         if (svcConnTracingEnabled()) {
452             logTraceSvcConn("setOnKeyEventResult", "handled=" + handled + ";sequence=" + sequence);
453         }
454         mSystemSupport.getKeyEventDispatcher().setOnKeyEventResult(this, handled, sequence);
455     }
456 
457     @Override
getServiceInfo()458     public AccessibilityServiceInfo getServiceInfo() {
459         if (svcConnTracingEnabled()) {
460             logTraceSvcConn("getServiceInfo", "");
461         }
462         synchronized (mLock) {
463             return mAccessibilityServiceInfo;
464         }
465     }
466 
getCapabilities()467     public int getCapabilities() {
468         return mAccessibilityServiceInfo.getCapabilities();
469     }
470 
getRelevantEventTypes()471     int getRelevantEventTypes() {
472         return (mUsesAccessibilityCache ? AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK
473                 : AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) | mEventTypes;
474     }
475 
476     @Override
setServiceInfo(AccessibilityServiceInfo info)477     public void setServiceInfo(AccessibilityServiceInfo info) {
478         if (svcConnTracingEnabled()) {
479             logTraceSvcConn("setServiceInfo", "info=" + info);
480         }
481         final long identity = Binder.clearCallingIdentity();
482         try {
483             synchronized (mLock) {
484                 // If the XML manifest had data to configure the service its info
485                 // should be already set. In such a case update only the dynamically
486                 // configurable properties.
487                 boolean oldRequestIme = mRequestImeApis;
488                 AccessibilityServiceInfo oldInfo = mAccessibilityServiceInfo;
489                 if (oldInfo != null) {
490                     oldInfo.updateDynamicallyConfigurableProperties(mIPlatformCompat, info);
491                     setDynamicallyConfigurableProperties(oldInfo);
492                 } else {
493                     setDynamicallyConfigurableProperties(info);
494                 }
495                 mSystemSupport.onClientChangeLocked(true);
496                 if (!oldRequestIme && mRequestImeApis) {
497                     mSystemSupport.requestImeLocked(this);
498                 } else if (oldRequestIme && !mRequestImeApis) {
499                     mSystemSupport.unbindImeLocked(this);
500                 }
501             }
502         } finally {
503             Binder.restoreCallingIdentity(identity);
504         }
505     }
506 
507     @Override
setInstalledAndEnabledServices(List<AccessibilityServiceInfo> infos)508     public void setInstalledAndEnabledServices(List<AccessibilityServiceInfo> infos) {
509         return;
510     }
511 
512     @Override
getInstalledAndEnabledServices()513     public List<AccessibilityServiceInfo> getInstalledAndEnabledServices() {
514         return null;
515     }
516 
517     @Override
setAttributionTag(String attributionTag)518     public void setAttributionTag(String attributionTag) {
519         mAttributionTag = attributionTag;
520     }
521 
getAttributionTag()522     String getAttributionTag() {
523         return mAttributionTag;
524     }
525 
hasRightsToCurrentUserLocked()526     protected abstract boolean hasRightsToCurrentUserLocked();
527 
528     @Nullable
529     @Override
getWindows()530     public AccessibilityWindowInfo.WindowListSparseArray getWindows() {
531         if (svcConnTracingEnabled()) {
532             logTraceSvcConn("getWindows", "");
533         }
534         synchronized (mLock) {
535             if (!hasRightsToCurrentUserLocked()) {
536                 return null;
537             }
538             final boolean permissionGranted =
539                     mSecurityPolicy.canRetrieveWindowsLocked(this);
540             if (!permissionGranted) {
541                 return null;
542             }
543             if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
544                 return null;
545             }
546             final AccessibilityWindowInfo.WindowListSparseArray allWindows =
547                     new AccessibilityWindowInfo.WindowListSparseArray();
548             final ArrayList<Integer> displayList = mA11yWindowManager.getDisplayListLocked(
549                     mDisplayTypes);
550             final int displayListCounts = displayList.size();
551             if (displayListCounts > 0) {
552                 for (int i = 0; i < displayListCounts; i++) {
553                     final int displayId = displayList.get(i);
554                     ensureWindowsAvailableTimedLocked(displayId);
555 
556                     final List<AccessibilityWindowInfo> windowList = getWindowsByDisplayLocked(
557                             displayId);
558                     if (windowList != null) {
559                         allWindows.put(displayId, windowList);
560                     }
561                 }
562             }
563             return allWindows;
564         }
565     }
566 
setDisplayTypes(@isplayTypes int displayTypes)567     protected void setDisplayTypes(@DisplayTypes int displayTypes) {
568         mDisplayTypes = displayTypes;
569     }
570 
571     @Override
getWindow(int windowId)572     public AccessibilityWindowInfo getWindow(int windowId) {
573         if (svcConnTracingEnabled()) {
574             logTraceSvcConn("getWindow", "windowId=" + windowId);
575         }
576         synchronized (mLock) {
577             int displayId = Display.INVALID_DISPLAY;
578             if (windowId != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID) {
579                 displayId = mA11yWindowManager.getDisplayIdByUserIdAndWindowIdLocked(
580                         mSystemSupport.getCurrentUserIdLocked(), windowId);
581             }
582             ensureWindowsAvailableTimedLocked(displayId);
583 
584             if (!hasRightsToCurrentUserLocked()) {
585                 return null;
586             }
587             final boolean permissionGranted =
588                     mSecurityPolicy.canRetrieveWindowsLocked(this);
589             if (!permissionGranted) {
590                 return null;
591             }
592             if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
593                 return null;
594             }
595             AccessibilityWindowInfo window =
596                     mA11yWindowManager.findA11yWindowInfoByIdLocked(windowId);
597             if (window != null) {
598                 AccessibilityWindowInfo windowClone = AccessibilityWindowInfo.obtain(window);
599                 windowClone.setConnectionId(mId);
600                 return windowClone;
601             }
602             return null;
603         }
604     }
605 
606     @Override
findAccessibilityNodeInfosByViewId(int accessibilityWindowId, long accessibilityNodeId, String viewIdResName, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)607     public String[] findAccessibilityNodeInfosByViewId(int accessibilityWindowId,
608             long accessibilityNodeId, String viewIdResName, int interactionId,
609             IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
610             throws RemoteException {
611         if (svcConnTracingEnabled()) {
612             logTraceSvcConn("findAccessibilityNodeInfosByViewId",
613                     "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
614                     + accessibilityNodeId + ";viewIdResName=" + viewIdResName + ";interactionId="
615                     + interactionId + ";callback=" + callback + ";interrogatingTid="
616                     + interrogatingTid);
617         }
618         final int resolvedWindowId;
619         RemoteAccessibilityConnection connection;
620         Region partialInteractiveRegion = Region.obtain();
621         synchronized (mLock) {
622             mUsesAccessibilityCache = true;
623             if (!hasRightsToCurrentUserLocked()) {
624                 return null;
625             }
626             resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
627             final boolean permissionGranted =
628                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
629                             mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId);
630             if (!permissionGranted) {
631                 return null;
632             } else {
633                 connection = mA11yWindowManager.getConnectionLocked(
634                         mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId);
635                 if (connection == null) {
636                     return null;
637                 }
638             }
639             if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
640                     resolvedWindowId, partialInteractiveRegion)) {
641                 partialInteractiveRegion.recycle();
642                 partialInteractiveRegion = null;
643             }
644         }
645         final Pair<float[], MagnificationSpec> transformMatrixAndSpec =
646                 getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
647         final float[] transformMatrix = transformMatrixAndSpec.first;
648         final MagnificationSpec spec = transformMatrixAndSpec.second;
649         if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
650             return null;
651         }
652         final int interrogatingPid = Binder.getCallingPid();
653         callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
654                 interrogatingPid, interrogatingTid);
655         final long identityToken = Binder.clearCallingIdentity();
656         if (intConnTracingEnabled()) {
657             logTraceIntConn("findAccessibilityNodeInfosByViewId",
658                     accessibilityNodeId + ";" + viewIdResName + ";" + partialInteractiveRegion + ";"
659                     + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid
660                     + ";" + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix));
661         }
662         try {
663             connection.getRemote().findAccessibilityNodeInfosByViewId(accessibilityNodeId,
664                     viewIdResName, partialInteractiveRegion, interactionId, callback, mFetchFlags,
665                     interrogatingPid, interrogatingTid, spec, transformMatrix);
666             return mSecurityPolicy.computeValidReportedPackages(
667                     connection.getPackageName(), connection.getUid());
668         } catch (RemoteException re) {
669             if (DEBUG) {
670                 Slog.e(LOG_TAG, "Error findAccessibilityNodeInfoByViewId().");
671             }
672         } finally {
673             Binder.restoreCallingIdentity(identityToken);
674             // Recycle if passed to another process.
675             if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
676                 partialInteractiveRegion.recycle();
677             }
678         }
679         return null;
680     }
681 
682     @Override
findAccessibilityNodeInfosByText(int accessibilityWindowId, long accessibilityNodeId, String text, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)683     public String[] findAccessibilityNodeInfosByText(int accessibilityWindowId,
684             long accessibilityNodeId, String text, int interactionId,
685             IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
686             throws RemoteException {
687         if (svcConnTracingEnabled()) {
688             logTraceSvcConn("findAccessibilityNodeInfosByText",
689                     "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
690                     + accessibilityNodeId + ";text=" + text + ";interactionId=" + interactionId
691                     + ";callback=" + callback + ";interrogatingTid=" + interrogatingTid);
692         }
693         final int resolvedWindowId;
694         RemoteAccessibilityConnection connection;
695         Region partialInteractiveRegion = Region.obtain();
696         synchronized (mLock) {
697             mUsesAccessibilityCache = true;
698             if (!hasRightsToCurrentUserLocked()) {
699                 return null;
700             }
701             resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
702             final boolean permissionGranted =
703                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
704                             mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId);
705             if (!permissionGranted) {
706                 return null;
707             } else {
708                 connection = mA11yWindowManager.getConnectionLocked(
709                         mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId);
710                 if (connection == null) {
711                     return null;
712                 }
713             }
714             if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
715                     resolvedWindowId, partialInteractiveRegion)) {
716                 partialInteractiveRegion.recycle();
717                 partialInteractiveRegion = null;
718             }
719         }
720         final Pair<float[], MagnificationSpec> transformMatrixAndSpec =
721                 getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
722         final float[] transformMatrix = transformMatrixAndSpec.first;
723         final MagnificationSpec spec = transformMatrixAndSpec.second;
724         if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
725             return null;
726         }
727         final int interrogatingPid = Binder.getCallingPid();
728         callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
729                 interrogatingPid, interrogatingTid);
730         final long identityToken = Binder.clearCallingIdentity();
731         if (intConnTracingEnabled()) {
732             logTraceIntConn("findAccessibilityNodeInfosByText",
733                     accessibilityNodeId + ";" + text + ";" + partialInteractiveRegion + ";"
734                     + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid
735                     + ";" + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix));
736         }
737         try {
738             connection.getRemote().findAccessibilityNodeInfosByText(accessibilityNodeId,
739                     text, partialInteractiveRegion, interactionId, callback, mFetchFlags,
740                     interrogatingPid, interrogatingTid, spec, transformMatrix);
741             return mSecurityPolicy.computeValidReportedPackages(
742                     connection.getPackageName(), connection.getUid());
743         } catch (RemoteException re) {
744             if (DEBUG) {
745                 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfosByText()");
746             }
747         } finally {
748             Binder.restoreCallingIdentity(identityToken);
749             // Recycle if passed to another process.
750             if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
751                 partialInteractiveRegion.recycle();
752             }
753         }
754         return null;
755     }
756 
757     @Override
findAccessibilityNodeInfoByAccessibilityId( int accessibilityWindowId, long accessibilityNodeId, int interactionId, IAccessibilityInteractionConnectionCallback callback, int flags, long interrogatingTid, Bundle arguments)758     public String[] findAccessibilityNodeInfoByAccessibilityId(
759             int accessibilityWindowId, long accessibilityNodeId, int interactionId,
760             IAccessibilityInteractionConnectionCallback callback, int flags,
761             long interrogatingTid, Bundle arguments) throws RemoteException {
762         if (svcConnTracingEnabled()) {
763             logTraceSvcConn("findAccessibilityNodeInfoByAccessibilityId",
764                     "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
765                     + accessibilityNodeId + ";interactionId=" + interactionId + ";callback="
766                     + callback + ";flags=" + flags + ";interrogatingTid=" + interrogatingTid
767                     + ";arguments=" + arguments);
768         }
769         final int resolvedWindowId;
770         RemoteAccessibilityConnection connection;
771         Region partialInteractiveRegion = Region.obtain();
772         synchronized (mLock) {
773             mUsesAccessibilityCache = true;
774             if (!hasRightsToCurrentUserLocked()) {
775                 return null;
776             }
777             resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
778             final boolean permissionGranted =
779                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
780                             mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId);
781             if (!permissionGranted) {
782                 return null;
783             } else {
784                 connection = mA11yWindowManager.getConnectionLocked(
785                         mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId);
786                 if (connection == null) {
787                     return null;
788                 }
789             }
790             if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
791                     resolvedWindowId, partialInteractiveRegion)) {
792                 partialInteractiveRegion.recycle();
793                 partialInteractiveRegion = null;
794             }
795         }
796         final Pair<float[], MagnificationSpec> transformMatrixAndSpec =
797                 getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
798         final float[] transformMatrix = transformMatrixAndSpec.first;
799         final MagnificationSpec spec = transformMatrixAndSpec.second;
800         if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
801             return null;
802         }
803         final int interrogatingPid = Binder.getCallingPid();
804         callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
805                 interrogatingPid, interrogatingTid);
806         final long identityToken = Binder.clearCallingIdentity();
807         if (intConnTracingEnabled()) {
808             logTraceIntConn("findAccessibilityNodeInfoByAccessibilityId",
809                     accessibilityNodeId + ";" + partialInteractiveRegion + ";" + interactionId + ";"
810                     + callback + ";" + (mFetchFlags | flags) + ";" + interrogatingPid + ";"
811                             + interrogatingTid + ";" + spec + ";" + Arrays.toString(transformMatrix)
812                             + ";" + arguments);
813         }
814         try {
815             connection.getRemote().findAccessibilityNodeInfoByAccessibilityId(
816                     accessibilityNodeId, partialInteractiveRegion, interactionId, callback,
817                     mFetchFlags | flags, interrogatingPid, interrogatingTid, spec, transformMatrix,
818                     arguments);
819             return mSecurityPolicy.computeValidReportedPackages(
820                     connection.getPackageName(), connection.getUid());
821         } catch (RemoteException re) {
822             if (DEBUG) {
823                 Slog.e(LOG_TAG, "Error calling findAccessibilityNodeInfoByAccessibilityId()");
824             }
825         } finally {
826             Binder.restoreCallingIdentity(identityToken);
827             // Recycle if passed to another process.
828             if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
829                 partialInteractiveRegion.recycle();
830             }
831         }
832         return null;
833     }
834 
835     @Override
findFocus(int accessibilityWindowId, long accessibilityNodeId, int focusType, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)836     public String[] findFocus(int accessibilityWindowId, long accessibilityNodeId,
837             int focusType, int interactionId,
838             IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
839             throws RemoteException {
840         if (svcConnTracingEnabled()) {
841             logTraceSvcConn("findFocus",
842                     "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
843                     + accessibilityNodeId + ";focusType=" + focusType + ";interactionId="
844                     + interactionId + ";callback=" + callback + ";interrogatingTid="
845                     + interrogatingTid);
846         }
847         final int resolvedWindowId;
848         RemoteAccessibilityConnection connection;
849         Region partialInteractiveRegion = Region.obtain();
850         synchronized (mLock) {
851             if (!hasRightsToCurrentUserLocked()) {
852                 return null;
853             }
854             resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
855                     accessibilityWindowId, focusType);
856             final boolean permissionGranted =
857                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
858                             mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId);
859             if (!permissionGranted) {
860                 return null;
861             } else {
862                 connection = mA11yWindowManager.getConnectionLocked(
863                         mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId);
864                 if (connection == null) {
865                     return null;
866                 }
867             }
868             if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
869                     resolvedWindowId, partialInteractiveRegion)) {
870                 partialInteractiveRegion.recycle();
871                 partialInteractiveRegion = null;
872             }
873         }
874         final Pair<float[], MagnificationSpec> transformMatrixAndSpec =
875                 getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
876         final float[] transformMatrix = transformMatrixAndSpec.first;
877         final MagnificationSpec spec = transformMatrixAndSpec.second;
878         if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
879             return null;
880         }
881         final int interrogatingPid = Binder.getCallingPid();
882         callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
883                 interrogatingPid, interrogatingTid);
884         final long identityToken = Binder.clearCallingIdentity();
885         if (intConnTracingEnabled()) {
886             logTraceIntConn("findFocus",
887                     accessibilityNodeId + ";" + focusType + ";" + partialInteractiveRegion + ";"
888                     + interactionId + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid
889                             + ";" + interrogatingTid + ";" + spec + ";"
890                             + Arrays.toString(transformMatrix));
891         }
892         try {
893             connection.getRemote().findFocus(accessibilityNodeId, focusType,
894                     partialInteractiveRegion, interactionId, callback, mFetchFlags,
895                     interrogatingPid, interrogatingTid, spec, transformMatrix);
896             return mSecurityPolicy.computeValidReportedPackages(
897                     connection.getPackageName(), connection.getUid());
898         } catch (RemoteException re) {
899             if (DEBUG) {
900                 Slog.e(LOG_TAG, "Error calling findFocus()");
901             }
902         } finally {
903             Binder.restoreCallingIdentity(identityToken);
904             // Recycle if passed to another process.
905             if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
906                 partialInteractiveRegion.recycle();
907             }
908         }
909         return null;
910     }
911 
912     @Override
focusSearch(int accessibilityWindowId, long accessibilityNodeId, int direction, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)913     public String[] focusSearch(int accessibilityWindowId, long accessibilityNodeId,
914             int direction, int interactionId,
915             IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
916             throws RemoteException {
917         if (svcConnTracingEnabled()) {
918             logTraceSvcConn("focusSearch",
919                     "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
920                     + accessibilityNodeId + ";direction=" + direction + ";interactionId="
921                     + interactionId + ";callback=" + callback + ";interrogatingTid="
922                     + interrogatingTid);
923         }
924         final int resolvedWindowId;
925         RemoteAccessibilityConnection connection;
926         Region partialInteractiveRegion = Region.obtain();
927         synchronized (mLock) {
928             if (!hasRightsToCurrentUserLocked()) {
929                 return null;
930             }
931             resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
932             final boolean permissionGranted =
933                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
934                             mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId);
935             if (!permissionGranted) {
936                 return null;
937             } else {
938                 connection = mA11yWindowManager.getConnectionLocked(
939                         mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId);
940                 if (connection == null) {
941                     return null;
942                 }
943             }
944             if (!mA11yWindowManager.computePartialInteractiveRegionForWindowLocked(
945                     resolvedWindowId, partialInteractiveRegion)) {
946                 partialInteractiveRegion.recycle();
947                 partialInteractiveRegion = null;
948             }
949         }
950         final Pair<float[], MagnificationSpec> transformMatrixAndSpec =
951                 getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
952         final float[] transformMatrix = transformMatrixAndSpec.first;
953         final MagnificationSpec spec = transformMatrixAndSpec.second;
954         if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
955             return null;
956         }
957         final int interrogatingPid = Binder.getCallingPid();
958         callback = replaceCallbackIfNeeded(callback, resolvedWindowId, interactionId,
959                 interrogatingPid, interrogatingTid);
960         final long identityToken = Binder.clearCallingIdentity();
961         if (intConnTracingEnabled()) {
962             logTraceIntConn("focusSearch",
963                     accessibilityNodeId + ";" + direction + ";" + partialInteractiveRegion
964                     + ";" + interactionId + ";" + callback + ";" + mFetchFlags + ";"
965                             + interrogatingPid + ";" + interrogatingTid + ";" + spec + ";"
966                              + Arrays.toString(transformMatrix));
967         }
968         try {
969             connection.getRemote().focusSearch(accessibilityNodeId, direction,
970                     partialInteractiveRegion, interactionId, callback, mFetchFlags,
971                     interrogatingPid, interrogatingTid, spec, transformMatrix);
972             return mSecurityPolicy.computeValidReportedPackages(
973                     connection.getPackageName(), connection.getUid());
974         } catch (RemoteException re) {
975             if (DEBUG) {
976                 Slog.e(LOG_TAG, "Error calling accessibilityFocusSearch()");
977             }
978         } finally {
979             Binder.restoreCallingIdentity(identityToken);
980             // Recycle if passed to another process.
981             if (partialInteractiveRegion != null && Binder.isProxy(connection.getRemote())) {
982                 partialInteractiveRegion.recycle();
983             }
984         }
985         return null;
986     }
987 
988     @Override
sendGesture(int sequence, ParceledListSlice gestureSteps)989     public void sendGesture(int sequence, ParceledListSlice gestureSteps) {
990         if (svcConnTracingEnabled()) {
991             logTraceSvcConn(
992                     "sendGesture", "sequence=" + sequence + ";gestureSteps=" + gestureSteps);
993         }
994     }
995 
996     @Override
dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId)997     public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) {
998         if (svcConnTracingEnabled()) {
999             logTraceSvcConn("dispatchGesture", "sequence=" + sequence + ";gestureSteps="
1000                     + gestureSteps + ";displayId=" + displayId);
1001         }
1002     }
1003 
1004     @Override
performAccessibilityAction(int accessibilityWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)1005     public boolean performAccessibilityAction(int accessibilityWindowId,
1006             long accessibilityNodeId, int action, Bundle arguments, int interactionId,
1007             IAccessibilityInteractionConnectionCallback callback, long interrogatingTid)
1008             throws RemoteException {
1009         if (svcConnTracingEnabled()) {
1010             logTraceSvcConn("performAccessibilityAction",
1011                     "accessibilityWindowId=" + accessibilityWindowId + ";accessibilityNodeId="
1012                     + accessibilityNodeId + ";action=" + action + ";arguments=" + arguments
1013                     + ";interactionId=" + interactionId + ";callback=" + callback
1014                     + ";interrogatingTid=" + interrogatingTid);
1015         }
1016         final int resolvedWindowId;
1017         synchronized (mLock) {
1018             if (!hasRightsToCurrentUserLocked()) {
1019                 return false;
1020             }
1021             resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
1022             if (!mSecurityPolicy.canGetAccessibilityNodeInfoLocked(
1023                     mSystemSupport.getCurrentUserIdLocked(), this, resolvedWindowId)) {
1024                 return false;
1025             }
1026         }
1027         if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
1028             return false;
1029         }
1030         return performAccessibilityActionInternal(
1031                 mSystemSupport.getCurrentUserIdLocked(), resolvedWindowId, accessibilityNodeId,
1032                 action, arguments, interactionId, callback, mFetchFlags, interrogatingTid);
1033     }
1034 
1035     @Override
performGlobalAction(int action)1036     public boolean performGlobalAction(int action) {
1037         if (svcConnTracingEnabled()) {
1038             logTraceSvcConn("performGlobalAction", "action=" + action);
1039         }
1040         synchronized (mLock) {
1041             if (!hasRightsToCurrentUserLocked()) {
1042                 return false;
1043             }
1044         }
1045         return mSystemActionPerformer.performSystemAction(action);
1046     }
1047 
1048     @Override
getSystemActions()1049     public @NonNull List<AccessibilityNodeInfo.AccessibilityAction> getSystemActions() {
1050         if (svcConnTracingEnabled()) {
1051             logTraceSvcConn("getSystemActions", "");
1052         }
1053         synchronized (mLock) {
1054             if (!hasRightsToCurrentUserLocked()) {
1055                 return Collections.emptyList();
1056             }
1057         }
1058         return mSystemActionPerformer.getSystemActions();
1059     }
1060 
1061     @Override
isFingerprintGestureDetectionAvailable()1062     public boolean isFingerprintGestureDetectionAvailable() {
1063         if (svcConnTracingEnabled()) {
1064             logTraceSvcConn("isFingerprintGestureDetectionAvailable", "");
1065         }
1066         if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
1067             return false;
1068         }
1069         if (isCapturingFingerprintGestures()) {
1070             FingerprintGestureDispatcher dispatcher =
1071                     mSystemSupport.getFingerprintGestureDispatcher();
1072             return (dispatcher != null) && dispatcher.isFingerprintGestureDetectionAvailable();
1073         }
1074         return false;
1075     }
1076 
1077     @Nullable
1078     @Override
getMagnificationConfig(int displayId)1079     public MagnificationConfig getMagnificationConfig(int displayId) {
1080         if (svcConnTracingEnabled()) {
1081             logTraceSvcConn("getMagnificationConfig", "displayId=" + displayId);
1082         }
1083         synchronized (mLock) {
1084             if (!hasRightsToCurrentUserLocked()) {
1085                 return null;
1086             }
1087         }
1088         final long identity = Binder.clearCallingIdentity();
1089         try {
1090             return mSystemSupport.getMagnificationProcessor().getMagnificationConfig(displayId);
1091         } finally {
1092             Binder.restoreCallingIdentity(identity);
1093         }
1094     }
1095 
1096     @Override
getMagnificationScale(int displayId)1097     public float getMagnificationScale(int displayId) {
1098         if (svcConnTracingEnabled()) {
1099             logTraceSvcConn("getMagnificationScale", "displayId=" + displayId);
1100         }
1101         synchronized (mLock) {
1102             if (!hasRightsToCurrentUserLocked()) {
1103                 return 1.0f;
1104             }
1105         }
1106         final long identity = Binder.clearCallingIdentity();
1107         try {
1108             return mSystemSupport.getMagnificationProcessor().getScale(displayId);
1109         } finally {
1110             Binder.restoreCallingIdentity(identity);
1111         }
1112     }
1113 
1114     @Override
getMagnificationRegion(int displayId)1115     public Region getMagnificationRegion(int displayId) {
1116         if (svcConnTracingEnabled()) {
1117             logTraceSvcConn("getMagnificationRegion", "displayId=" + displayId);
1118         }
1119         synchronized (mLock) {
1120             final Region region = Region.obtain();
1121             if (!hasRightsToCurrentUserLocked()) {
1122                 return region;
1123             }
1124             MagnificationProcessor magnificationProcessor =
1125                     mSystemSupport.getMagnificationProcessor();
1126             final long identity = Binder.clearCallingIdentity();
1127             try {
1128                 magnificationProcessor.getFullscreenMagnificationRegion(displayId,
1129                         region, mSecurityPolicy.canControlMagnification(this));
1130                 return region;
1131             } finally {
1132                 Binder.restoreCallingIdentity(identity);
1133             }
1134         }
1135     }
1136 
1137 
1138     @Override
getCurrentMagnificationRegion(int displayId)1139     public Region getCurrentMagnificationRegion(int displayId) {
1140         if (svcConnTracingEnabled()) {
1141             logTraceSvcConn("getCurrentMagnificationRegion", "displayId=" + displayId);
1142         }
1143         synchronized (mLock) {
1144             final Region region = Region.obtain();
1145             if (!hasRightsToCurrentUserLocked()) {
1146                 return region;
1147             }
1148             MagnificationProcessor magnificationProcessor =
1149                     mSystemSupport.getMagnificationProcessor();
1150             final long identity = Binder.clearCallingIdentity();
1151             try {
1152                 magnificationProcessor.getCurrentMagnificationRegion(displayId,
1153                         region, mSecurityPolicy.canControlMagnification(this));
1154                 return region;
1155             } finally {
1156                 Binder.restoreCallingIdentity(identity);
1157             }
1158         }
1159     }
1160 
1161     @Override
getMagnificationCenterX(int displayId)1162     public float getMagnificationCenterX(int displayId) {
1163         if (svcConnTracingEnabled()) {
1164             logTraceSvcConn("getMagnificationCenterX", "displayId=" + displayId);
1165         }
1166         synchronized (mLock) {
1167             if (!hasRightsToCurrentUserLocked()) {
1168                 return 0.0f;
1169             }
1170             MagnificationProcessor magnificationProcessor =
1171                     mSystemSupport.getMagnificationProcessor();
1172             final long identity = Binder.clearCallingIdentity();
1173             try {
1174                 return magnificationProcessor.getCenterX(displayId,
1175                         mSecurityPolicy.canControlMagnification(this));
1176             } finally {
1177                 Binder.restoreCallingIdentity(identity);
1178             }
1179         }
1180     }
1181 
1182     @Override
getMagnificationCenterY(int displayId)1183     public float getMagnificationCenterY(int displayId) {
1184         if (svcConnTracingEnabled()) {
1185             logTraceSvcConn("getMagnificationCenterY", "displayId=" + displayId);
1186         }
1187         synchronized (mLock) {
1188             if (!hasRightsToCurrentUserLocked()) {
1189                 return 0.0f;
1190             }
1191             MagnificationProcessor magnificationProcessor =
1192                     mSystemSupport.getMagnificationProcessor();
1193             final long identity = Binder.clearCallingIdentity();
1194             try {
1195                 return magnificationProcessor.getCenterY(displayId,
1196                         mSecurityPolicy.canControlMagnification(this));
1197             } finally {
1198                 Binder.restoreCallingIdentity(identity);
1199             }
1200         }
1201     }
1202 
1203     @Override
resetMagnification(int displayId, boolean animate)1204     public boolean resetMagnification(int displayId, boolean animate) {
1205         if (svcConnTracingEnabled()) {
1206             logTraceSvcConn("resetMagnification", "displayId=" + displayId + ";animate=" + animate);
1207         }
1208         synchronized (mLock) {
1209             if (!hasRightsToCurrentUserLocked()) {
1210                 return false;
1211             }
1212             if (!mSecurityPolicy.canControlMagnification(this)) {
1213                 return false;
1214             }
1215         }
1216         final long identity = Binder.clearCallingIdentity();
1217         try {
1218             MagnificationProcessor magnificationProcessor =
1219                     mSystemSupport.getMagnificationProcessor();
1220             return (magnificationProcessor.resetFullscreenMagnification(displayId, animate)
1221                     || !magnificationProcessor.isMagnifying(displayId));
1222         } finally {
1223             Binder.restoreCallingIdentity(identity);
1224         }
1225     }
1226 
1227     @Override
resetCurrentMagnification(int displayId, boolean animate)1228     public boolean resetCurrentMagnification(int displayId, boolean animate) {
1229         if (svcConnTracingEnabled()) {
1230             logTraceSvcConn("resetCurrentMagnification",
1231                     "displayId=" + displayId + ";animate=" + animate);
1232         }
1233         synchronized (mLock) {
1234             if (!hasRightsToCurrentUserLocked()) {
1235                 return false;
1236             }
1237             if (!mSecurityPolicy.canControlMagnification(this)) {
1238                 return false;
1239             }
1240         }
1241         final long identity = Binder.clearCallingIdentity();
1242         try {
1243             MagnificationProcessor magnificationProcessor =
1244                     mSystemSupport.getMagnificationProcessor();
1245             return (magnificationProcessor.resetCurrentMagnification(displayId, animate)
1246                     || !magnificationProcessor.isMagnifying(displayId));
1247         } finally {
1248             Binder.restoreCallingIdentity(identity);
1249         }
1250     }
1251 
1252     @Override
setMagnificationConfig(int displayId, @NonNull MagnificationConfig config, boolean animate)1253     public boolean setMagnificationConfig(int displayId,
1254             @NonNull MagnificationConfig config, boolean animate) {
1255         if (svcConnTracingEnabled()) {
1256             logTraceSvcConn("setMagnificationSpec",
1257                     "displayId=" + displayId + ", config=" + config.toString());
1258         }
1259         synchronized (mLock) {
1260             if (!hasRightsToCurrentUserLocked()) {
1261                 return false;
1262             }
1263             if (!mSecurityPolicy.canControlMagnification(this)) {
1264                 return false;
1265             }
1266             final long identity = Binder.clearCallingIdentity();
1267             try {
1268                 MagnificationProcessor magnificationProcessor =
1269                         mSystemSupport.getMagnificationProcessor();
1270                 return magnificationProcessor.setMagnificationConfig(displayId, config, animate,
1271                         mId);
1272             } finally {
1273                 Binder.restoreCallingIdentity(identity);
1274             }
1275         }
1276     }
1277 
1278     @Override
setMagnificationCallbackEnabled(int displayId, boolean enabled)1279     public void setMagnificationCallbackEnabled(int displayId, boolean enabled) {
1280         if (svcConnTracingEnabled()) {
1281             logTraceSvcConn("setMagnificationCallbackEnabled",
1282                     "displayId=" + displayId + ";enabled=" + enabled);
1283         }
1284         mInvocationHandler.setMagnificationCallbackEnabled(displayId, enabled);
1285     }
1286 
isMagnificationCallbackEnabled(int displayId)1287     public boolean isMagnificationCallbackEnabled(int displayId) {
1288         return mInvocationHandler.isMagnificationCallbackEnabled(displayId);
1289     }
1290 
1291     @Override
setSoftKeyboardCallbackEnabled(boolean enabled)1292     public void setSoftKeyboardCallbackEnabled(boolean enabled) {
1293         if (svcConnTracingEnabled()) {
1294             logTraceSvcConn("setSoftKeyboardCallbackEnabled", "enabled=" + enabled);
1295         }
1296         mInvocationHandler.setSoftKeyboardCallbackEnabled(enabled);
1297     }
1298 
1299     @Override
takeScreenshotOfWindow(int accessibilityWindowId, int interactionId, ScreenCapture.ScreenCaptureListener listener, IAccessibilityInteractionConnectionCallback callback)1300     public void takeScreenshotOfWindow(int accessibilityWindowId, int interactionId,
1301             ScreenCapture.ScreenCaptureListener listener,
1302             IAccessibilityInteractionConnectionCallback callback) throws RemoteException {
1303         final long currentTimestamp = SystemClock.uptimeMillis();
1304         if ((currentTimestamp
1305                 - mRequestTakeScreenshotOfWindowTimestampMs.get(accessibilityWindowId, 0L))
1306                 <= ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS) {
1307             callback.sendTakeScreenshotOfWindowError(
1308                     AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT, interactionId);
1309             return;
1310         }
1311         mRequestTakeScreenshotOfWindowTimestampMs.put(accessibilityWindowId, currentTimestamp);
1312 
1313         synchronized (mLock) {
1314             if (!hasRightsToCurrentUserLocked()) {
1315                 callback.sendTakeScreenshotOfWindowError(
1316                         AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR, interactionId);
1317                 return;
1318             }
1319             if (!mSecurityPolicy.canTakeScreenshotLocked(this)) {
1320                 callback.sendTakeScreenshotOfWindowError(
1321                         AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS,
1322                         interactionId);
1323                 return;
1324             }
1325         }
1326         if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
1327             callback.sendTakeScreenshotOfWindowError(
1328                     AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS,
1329                     interactionId);
1330             return;
1331         }
1332 
1333         RemoteAccessibilityConnection connection = mA11yWindowManager.getConnectionLocked(
1334                 mSystemSupport.getCurrentUserIdLocked(),
1335                 resolveAccessibilityWindowIdLocked(accessibilityWindowId));
1336         if (connection == null) {
1337             callback.sendTakeScreenshotOfWindowError(
1338                     AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_WINDOW, interactionId);
1339             return;
1340         }
1341         connection.getRemote().takeScreenshotOfWindow(interactionId, listener, callback);
1342     }
1343 
1344     @Override
takeScreenshot(int displayId, RemoteCallback callback)1345     public void takeScreenshot(int displayId, RemoteCallback callback) {
1346         if (svcConnTracingEnabled()) {
1347             logTraceSvcConn("takeScreenshot", "displayId=" + displayId + ";callback=" + callback);
1348         }
1349         final long currentTimestamp = SystemClock.uptimeMillis();
1350         if (mRequestTakeScreenshotTimestampMs != 0
1351                 && (currentTimestamp - mRequestTakeScreenshotTimestampMs)
1352                 <= AccessibilityService.ACCESSIBILITY_TAKE_SCREENSHOT_REQUEST_INTERVAL_TIMES_MS) {
1353             sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERVAL_TIME_SHORT,
1354                     callback);
1355             return;
1356         }
1357         mRequestTakeScreenshotTimestampMs = currentTimestamp;
1358 
1359         synchronized (mLock) {
1360             if (!hasRightsToCurrentUserLocked()) {
1361                 sendScreenshotFailure(AccessibilityService.ERROR_TAKE_SCREENSHOT_INTERNAL_ERROR,
1362                         callback);
1363                 return;
1364             }
1365 
1366             if (!mSecurityPolicy.canTakeScreenshotLocked(this)) {
1367                 throw new SecurityException("Services don't have the capability of taking"
1368                         + " the screenshot.");
1369             }
1370         }
1371 
1372         if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
1373             sendScreenshotFailure(
1374                     AccessibilityService.ERROR_TAKE_SCREENSHOT_NO_ACCESSIBILITY_ACCESS,
1375                     callback);
1376             return;
1377         }
1378 
1379         // Private virtual displays are created by the ap and is not allowed to access by other
1380         // aps.  We assume the contents on this display should not be captured.
1381         final DisplayManager displayManager =
1382                 (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
1383         final Display display = displayManager.getDisplay(displayId);
1384         if ((display == null) || (display.getType() == Display.TYPE_VIRTUAL
1385                 && (display.getFlags() & Display.FLAG_PRIVATE) != 0)) {
1386             sendScreenshotFailure(
1387                     AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback);
1388             return;
1389         }
1390 
1391         final long identity = Binder.clearCallingIdentity();
1392         try {
1393             mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
1394                 final ScreenshotHardwareBuffer screenshotBuffer = LocalServices
1395                         .getService(DisplayManagerInternal.class).userScreenshot(displayId);
1396                 if (screenshotBuffer != null) {
1397                     sendScreenshotSuccess(screenshotBuffer, callback);
1398                 } else {
1399                     sendScreenshotFailure(
1400                             AccessibilityService.ERROR_TAKE_SCREENSHOT_INVALID_DISPLAY, callback);
1401                 }
1402             }, null).recycleOnUse());
1403         } finally {
1404             Binder.restoreCallingIdentity(identity);
1405         }
1406     }
1407 
sendScreenshotSuccess(ScreenshotHardwareBuffer screenshotBuffer, RemoteCallback callback)1408     private void sendScreenshotSuccess(ScreenshotHardwareBuffer screenshotBuffer,
1409             RemoteCallback callback) {
1410         final HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
1411         final ParcelableColorSpace colorSpace =
1412                 new ParcelableColorSpace(screenshotBuffer.getColorSpace());
1413 
1414         final Bundle payload = new Bundle();
1415         payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS,
1416                 AccessibilityService.TAKE_SCREENSHOT_SUCCESS);
1417         payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_HARDWAREBUFFER,
1418                 hardwareBuffer);
1419         payload.putParcelable(KEY_ACCESSIBILITY_SCREENSHOT_COLORSPACE, colorSpace);
1420         payload.putLong(KEY_ACCESSIBILITY_SCREENSHOT_TIMESTAMP,
1421                 SystemClock.uptimeMillis());
1422 
1423         // Send back the result.
1424         callback.sendResult(payload);
1425         hardwareBuffer.close();
1426     }
1427 
sendScreenshotFailure(@ccessibilityService.ScreenshotErrorCode int errorCode, RemoteCallback callback)1428     private void sendScreenshotFailure(@AccessibilityService.ScreenshotErrorCode int errorCode,
1429             RemoteCallback callback) {
1430         mMainHandler.post(PooledLambda.obtainRunnable((nonArg) -> {
1431             final Bundle payload = new Bundle();
1432             payload.putInt(KEY_ACCESSIBILITY_SCREENSHOT_STATUS, errorCode);
1433             // Send back the result.
1434             callback.sendResult(payload);
1435         }, null).recycleOnUse());
1436     }
1437 
1438     @Override
dump(FileDescriptor fd, final PrintWriter pw, String[] args)1439     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
1440         if (!DumpUtils.checkDumpPermission(mContext, LOG_TAG, pw)) return;
1441         synchronized (mLock) {
1442             pw.append("Service[label=" + mAccessibilityServiceInfo.getResolveInfo()
1443                     .loadLabel(mContext.getPackageManager()));
1444             pw.append(", feedbackType"
1445                     + AccessibilityServiceInfo.feedbackTypeToString(mFeedbackType));
1446             pw.append(", capabilities=" + mAccessibilityServiceInfo.getCapabilities());
1447             pw.append(", eventTypes="
1448                     + AccessibilityEvent.eventTypeToString(mEventTypes));
1449             pw.append(", notificationTimeout=" + mNotificationTimeout);
1450             pw.append(", requestA11yBtn=" + mRequestAccessibilityButton);
1451             pw.append("]");
1452         }
1453     }
1454 
onAdded()1455     public void onAdded() {
1456         final Display[] displays = mDisplayManager.getDisplays();
1457         for (int i = 0; i < displays.length; i++) {
1458             final int displayId = displays[i].getDisplayId();
1459             onDisplayAdded(displayId);
1460         }
1461     }
1462 
1463     /**
1464      * Called whenever a logical display has been added to the system. Add a window token for adding
1465      * an accessibility overlay.
1466      *
1467      * @param displayId The id of the logical display that was added.
1468      */
onDisplayAdded(int displayId)1469     public void onDisplayAdded(int displayId) {
1470         final long identity = Binder.clearCallingIdentity();
1471         try {
1472             final IBinder overlayWindowToken = new Binder();
1473             if (wmTracingEnabled()) {
1474                 logTraceWM("addWindowToken",
1475                         overlayWindowToken + ";TYPE_ACCESSIBILITY_OVERLAY;" + displayId + ";null");
1476             }
1477             mWindowManagerService.addWindowToken(overlayWindowToken, TYPE_ACCESSIBILITY_OVERLAY,
1478                     displayId, null /* options */);
1479             synchronized (mLock) {
1480                 mOverlayWindowTokens.put(displayId, overlayWindowToken);
1481             }
1482         } finally {
1483             Binder.restoreCallingIdentity(identity);
1484         }
1485     }
1486 
onRemoved()1487     public void onRemoved() {
1488         final Display[] displays = mDisplayManager.getDisplays();
1489         for (int i = 0; i < displays.length; i++) {
1490             final int displayId = displays[i].getDisplayId();
1491             onDisplayRemoved(displayId);
1492         }
1493     }
1494 
1495     /**
1496      * Called whenever a logical display has been removed from the system. Remove a window token for
1497      * removing an accessibility overlay.
1498      *
1499      * @param displayId The id of the logical display that was added.
1500      */
onDisplayRemoved(int displayId)1501     public void onDisplayRemoved(int displayId) {
1502         final long identity = Binder.clearCallingIdentity();
1503         if (wmTracingEnabled()) {
1504             logTraceWM(
1505                     "addWindowToken", mOverlayWindowTokens.get(displayId) + ";true;" + displayId);
1506         }
1507         try {
1508             mWindowManagerService.removeWindowToken(mOverlayWindowTokens.get(displayId), true,
1509                     displayId);
1510             synchronized (mLock) {
1511                 mOverlayWindowTokens.remove(displayId);
1512             }
1513         } finally {
1514             Binder.restoreCallingIdentity(identity);
1515         }
1516     }
1517 
1518     /**
1519      * Gets overlay window token by the display Id.
1520      *
1521      * @param displayId The id of the logical display that was added.
1522      * @return window token.
1523      */
1524     @Override
getOverlayWindowToken(int displayId)1525     public IBinder getOverlayWindowToken(int displayId) {
1526         if (svcConnTracingEnabled()) {
1527             logTraceSvcConn("getOverlayWindowToken", "displayId=" + displayId);
1528         }
1529         synchronized (mLock) {
1530             return mOverlayWindowTokens.get(displayId);
1531         }
1532     }
1533 
1534     /**
1535      * Gets windowId of given token.
1536      *
1537      * @param token The token
1538      * @return window id
1539      */
1540     @Override
getWindowIdForLeashToken(@onNull IBinder token)1541     public int getWindowIdForLeashToken(@NonNull IBinder token) {
1542         if (svcConnTracingEnabled()) {
1543             logTraceSvcConn("getWindowIdForLeashToken", "token=" + token);
1544         }
1545         synchronized (mLock) {
1546             return mA11yWindowManager.getWindowIdLocked(token);
1547         }
1548     }
1549 
resetLocked()1550     public void resetLocked() {
1551         mSystemSupport.getKeyEventDispatcher().flush(this);
1552         try {
1553             // Clear the proxy in the other process so this
1554             // IAccessibilityServiceConnection can be garbage collected.
1555             if (mServiceInterface != null) {
1556                 if (svcClientTracingEnabled()) {
1557                     logTraceSvcClient("init", "null, " + mId + ", null");
1558                 }
1559                 mServiceInterface.init(null, mId, null);
1560             }
1561         } catch (RemoteException re) {
1562                 /* ignore */
1563         }
1564         if (mService != null) {
1565             try {
1566                 mService.unlinkToDeath(this, 0);
1567             } catch (NoSuchElementException e) {
1568                 Slog.e(LOG_TAG, "Failed unregistering death link");
1569             }
1570             mService = null;
1571         }
1572 
1573         mServiceInterface = null;
1574         mReceivedAccessibilityButtonCallbackSinceBind = false;
1575     }
1576 
isConnectedLocked()1577     public boolean isConnectedLocked() {
1578         return (mService != null);
1579     }
1580 
notifyAccessibilityEvent(AccessibilityEvent event)1581     public void notifyAccessibilityEvent(AccessibilityEvent event) {
1582         synchronized (mLock) {
1583             final int eventType = event.getEventType();
1584 
1585             final boolean serviceWantsEvent = wantsEventLocked(event);
1586             final boolean requiredForCacheConsistency = mUsesAccessibilityCache
1587                     && ((AccessibilityCache.CACHE_CRITICAL_EVENTS_MASK & eventType) != 0);
1588             if (!serviceWantsEvent && !requiredForCacheConsistency) {
1589                 return;
1590             }
1591 
1592             if (!mSecurityPolicy.checkAccessibilityAccess(this)) {
1593                 return;
1594             }
1595             // Make a copy since during dispatch it is possible the event to
1596             // be modified to remove its source if the receiving service does
1597             // not have permission to access the window content.
1598             AccessibilityEvent newEvent = AccessibilityEvent.obtain(event);
1599             Message message;
1600             if ((mNotificationTimeout > 0)
1601                     && (eventType != AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED)) {
1602                 // Allow at most one pending event
1603                 final AccessibilityEvent oldEvent = mPendingEvents.get(eventType);
1604                 mPendingEvents.put(eventType, newEvent);
1605                 if (oldEvent != null) {
1606                     mEventDispatchHandler.removeMessages(eventType);
1607                     oldEvent.recycle();
1608                 }
1609                 message = mEventDispatchHandler.obtainMessage(eventType);
1610             } else {
1611                 // Send all messages, bypassing mPendingEvents
1612                 message = mEventDispatchHandler.obtainMessage(eventType, newEvent);
1613             }
1614             message.arg1 = serviceWantsEvent ? 1 : 0;
1615 
1616             mEventDispatchHandler.sendMessageDelayed(message, mNotificationTimeout);
1617         }
1618     }
1619 
1620     /**
1621      * Determines if given event can be dispatched to a service based on the package of the
1622      * event source. Specifically, a service is notified if it is interested in events from the
1623      * package.
1624      *
1625      * @param event The event.
1626      * @return True if the listener should be notified, false otherwise.
1627      */
wantsEventLocked(AccessibilityEvent event)1628     private boolean wantsEventLocked(AccessibilityEvent event) {
1629 
1630         if (!canReceiveEventsLocked()) {
1631             return false;
1632         }
1633 
1634         final boolean includeNotImportantViews = (mFetchFlags
1635                 & AccessibilityNodeInfo.FLAG_SERVICE_REQUESTS_INCLUDE_NOT_IMPORTANT_VIEWS) != 0;
1636         if ((event.getWindowId() != AccessibilityWindowInfo.UNDEFINED_WINDOW_ID)
1637                 && !event.isImportantForAccessibility()
1638                 && !includeNotImportantViews) {
1639             return false;
1640         }
1641 
1642         if (event.isAccessibilityDataSensitive()
1643                 && (mFetchFlags & AccessibilityNodeInfo.FLAG_SERVICE_IS_ACCESSIBILITY_TOOL) == 0) {
1644             return false;
1645         }
1646 
1647         int eventType = event.getEventType();
1648         if ((mEventTypes & eventType) != eventType) {
1649             return false;
1650         }
1651 
1652         Set<String> packageNames = mPackageNames;
1653         String packageName = (event.getPackageName() != null)
1654                 ? event.getPackageName().toString() : null;
1655 
1656         return (packageNames.isEmpty() || packageNames.contains(packageName));
1657     }
1658 
1659     /**
1660      * Notifies an accessibility service client for a scheduled event given the event type.
1661      *
1662      * @param eventType The type of the event to dispatch.
1663      */
notifyAccessibilityEventInternal( int eventType, AccessibilityEvent event, boolean serviceWantsEvent)1664     private void notifyAccessibilityEventInternal(
1665             int eventType,
1666             AccessibilityEvent event,
1667             boolean serviceWantsEvent) {
1668         IAccessibilityServiceClient listener;
1669 
1670         synchronized (mLock) {
1671             listener = mServiceInterface;
1672 
1673             // If the service died/was disabled while the message for dispatching
1674             // the accessibility event was propagating the listener may be null.
1675             if (listener == null) {
1676                 return;
1677             }
1678 
1679             // There are two ways we notify for events, throttled AND non-throttled. If we
1680             // are not throttling, then messages come with events, which we handle with
1681             // minimal fuss.
1682             if (event == null) {
1683                 // We are throttling events, so we'll send the event for this type in
1684                 // mPendingEvents as long as it it's null. It can only null due to a race
1685                 // condition:
1686                 //
1687                 //   1) A binder thread calls notifyAccessibilityServiceDelayedLocked
1688                 //      which posts a message for dispatching an event and stores the event
1689                 //      in mPendingEvents.
1690                 //   2) The message is pulled from the queue by the handler on the service
1691                 //      thread and this method is just about to acquire the lock.
1692                 //   3) Another binder thread acquires the lock in notifyAccessibilityEvent
1693                 //   4) notifyAccessibilityEvent recycles the event that this method was about
1694                 //      to process, replaces it with a new one, and posts a second message
1695                 //   5) This method grabs the new event, processes it, and removes it from
1696                 //      mPendingEvents
1697                 //   6) The second message dispatched in (4) arrives, but the event has been
1698                 //      remvoved in (5).
1699                 event = mPendingEvents.get(eventType);
1700                 if (event == null) {
1701                     return;
1702                 }
1703                 mPendingEvents.remove(eventType);
1704             }
1705             if (mSecurityPolicy.canRetrieveWindowContentLocked(this)) {
1706                 event.setConnectionId(mId);
1707             } else {
1708                 event.setSource((View) null);
1709             }
1710             event.setSealed(true);
1711         }
1712 
1713         try {
1714             if (svcClientTracingEnabled()) {
1715                 logTraceSvcClient("onAccessibilityEvent", event + ";" + serviceWantsEvent);
1716             }
1717             listener.onAccessibilityEvent(event, serviceWantsEvent);
1718             if (DEBUG) {
1719                 Slog.i(LOG_TAG, "Event " + event + " sent to " + listener);
1720             }
1721         } catch (RemoteException re) {
1722             Slog.e(LOG_TAG, "Error during sending " + event + " to " + listener, re);
1723         } finally {
1724             event.recycle();
1725         }
1726     }
1727 
notifyGesture(AccessibilityGestureEvent gestureEvent)1728     public void notifyGesture(AccessibilityGestureEvent gestureEvent) {
1729         mInvocationHandler.obtainMessage(InvocationHandler.MSG_ON_GESTURE,
1730                 gestureEvent).sendToTarget();
1731     }
1732 
notifySystemActionsChangedLocked()1733     public void notifySystemActionsChangedLocked() {
1734         mInvocationHandler.sendEmptyMessage(
1735                 InvocationHandler.MSG_ON_SYSTEM_ACTIONS_CHANGED);
1736     }
1737 
notifyClearAccessibilityNodeInfoCache()1738     public void notifyClearAccessibilityNodeInfoCache() {
1739         mInvocationHandler.sendEmptyMessage(
1740                 InvocationHandler.MSG_CLEAR_ACCESSIBILITY_CACHE);
1741     }
1742 
notifyMagnificationChangedLocked(int displayId, @NonNull Region region, @NonNull MagnificationConfig config)1743     public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
1744             @NonNull MagnificationConfig config) {
1745         mInvocationHandler
1746                 .notifyMagnificationChangedLocked(displayId, region, config);
1747     }
1748 
notifySoftKeyboardShowModeChangedLocked(int showState)1749     public void notifySoftKeyboardShowModeChangedLocked(int showState) {
1750         mInvocationHandler.notifySoftKeyboardShowModeChangedLocked(showState);
1751     }
1752 
notifyAccessibilityButtonClickedLocked(int displayId)1753     public void notifyAccessibilityButtonClickedLocked(int displayId) {
1754         mInvocationHandler.notifyAccessibilityButtonClickedLocked(displayId);
1755     }
1756 
notifyAccessibilityButtonAvailabilityChangedLocked(boolean available)1757     public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
1758         mInvocationHandler.notifyAccessibilityButtonAvailabilityChangedLocked(available);
1759     }
1760 
createImeSessionLocked()1761     public void createImeSessionLocked() {
1762         mInvocationHandler.createImeSessionLocked();
1763     }
1764 
setImeSessionEnabledLocked(IAccessibilityInputMethodSession session, boolean enabled)1765     public void setImeSessionEnabledLocked(IAccessibilityInputMethodSession session,
1766             boolean enabled) {
1767         mInvocationHandler.setImeSessionEnabledLocked(session, enabled);
1768     }
1769 
bindInputLocked()1770     public void bindInputLocked() {
1771         mInvocationHandler.bindInputLocked();
1772     }
1773 
unbindInputLocked()1774     public  void unbindInputLocked() {
1775         mInvocationHandler.unbindInputLocked();
1776     }
1777 
startInputLocked(IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting)1778     public void startInputLocked(IRemoteAccessibilityInputConnection connection,
1779             EditorInfo editorInfo, boolean restarting) {
1780         mInvocationHandler.startInputLocked(connection, editorInfo, restarting);
1781     }
1782 
1783     @Nullable
getWindowTransformationMatrixAndMagnificationSpec( int resolvedWindowId)1784     private Pair<float[], MagnificationSpec> getWindowTransformationMatrixAndMagnificationSpec(
1785             int resolvedWindowId) {
1786         return mSystemSupport.getWindowTransformationMatrixAndMagnificationSpec(resolvedWindowId);
1787     }
1788 
wantsGenericMotionEvent(MotionEvent event)1789     public boolean wantsGenericMotionEvent(MotionEvent event) {
1790         final int eventSourceWithoutClass = event.getSource() & ~InputDevice.SOURCE_CLASS_MASK;
1791         return (mGenericMotionEventSources & eventSourceWithoutClass) != 0;
1792     }
1793 
1794     /**
1795      * Called by the invocation handler to notify the service that the
1796      * state of magnification has changed.
1797      */
notifyMagnificationChangedInternal(int displayId, @NonNull Region region, @NonNull MagnificationConfig config)1798     private void notifyMagnificationChangedInternal(int displayId, @NonNull Region region,
1799             @NonNull MagnificationConfig config) {
1800         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1801         if (listener != null) {
1802             try {
1803                 if (svcClientTracingEnabled()) {
1804                     logTraceSvcClient("onMagnificationChanged", displayId + ", " + region + ", "
1805                             + config.toString());
1806                 }
1807                 listener.onMagnificationChanged(displayId, region, config);
1808             } catch (RemoteException re) {
1809                 Slog.e(LOG_TAG, "Error sending magnification changes to " + mService, re);
1810             }
1811         }
1812     }
1813 
1814     /**
1815      * Called by the invocation handler to notify the service that the state of the soft
1816      * keyboard show mode has changed.
1817      */
notifySoftKeyboardShowModeChangedInternal(int showState)1818     private void notifySoftKeyboardShowModeChangedInternal(int showState) {
1819         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1820         if (listener != null) {
1821             try {
1822                 if (svcClientTracingEnabled()) {
1823                     logTraceSvcClient("onSoftKeyboardShowModeChanged", String.valueOf(showState));
1824                 }
1825                 listener.onSoftKeyboardShowModeChanged(showState);
1826             } catch (RemoteException re) {
1827                 Slog.e(LOG_TAG, "Error sending soft keyboard show mode changes to " + mService,
1828                         re);
1829             }
1830         }
1831     }
1832 
notifyAccessibilityButtonClickedInternal(int displayId)1833     private void notifyAccessibilityButtonClickedInternal(int displayId) {
1834         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1835         if (listener != null) {
1836             try {
1837                 if (svcClientTracingEnabled()) {
1838                     logTraceSvcClient("onAccessibilityButtonClicked", String.valueOf(displayId));
1839                 }
1840                 listener.onAccessibilityButtonClicked(displayId);
1841             } catch (RemoteException re) {
1842                 Slog.e(LOG_TAG, "Error sending accessibility button click to " + mService, re);
1843             }
1844         }
1845     }
1846 
notifyAccessibilityButtonAvailabilityChangedInternal(boolean available)1847     private void notifyAccessibilityButtonAvailabilityChangedInternal(boolean available) {
1848         // Only notify the service if it's not been notified or the state has changed
1849         if (mReceivedAccessibilityButtonCallbackSinceBind
1850                 && (mLastAccessibilityButtonCallbackState == available)) {
1851             return;
1852         }
1853         mReceivedAccessibilityButtonCallbackSinceBind = true;
1854         mLastAccessibilityButtonCallbackState = available;
1855         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1856         if (listener != null) {
1857             try {
1858                 if (svcClientTracingEnabled()) {
1859                     logTraceSvcClient("onAccessibilityButtonAvailabilityChanged",
1860                             String.valueOf(available));
1861                 }
1862                 listener.onAccessibilityButtonAvailabilityChanged(available);
1863             } catch (RemoteException re) {
1864                 Slog.e(LOG_TAG,
1865                         "Error sending accessibility button availability change to " + mService,
1866                         re);
1867             }
1868         }
1869     }
1870 
notifyGestureInternal(AccessibilityGestureEvent gestureInfo)1871     private void notifyGestureInternal(AccessibilityGestureEvent gestureInfo) {
1872         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1873         if (listener != null) {
1874             try {
1875                 if (svcClientTracingEnabled()) {
1876                     logTraceSvcClient("onGesture", gestureInfo.toString());
1877                 }
1878                 listener.onGesture(gestureInfo);
1879             } catch (RemoteException re) {
1880                 Slog.e(LOG_TAG, "Error during sending gesture " + gestureInfo
1881                         + " to " + mService, re);
1882             }
1883         }
1884     }
1885 
notifySystemActionsChangedInternal()1886     private void notifySystemActionsChangedInternal() {
1887         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1888         if (listener != null) {
1889             try {
1890                 if (svcClientTracingEnabled()) {
1891                     logTraceSvcClient("onSystemActionsChanged", "");
1892                 }
1893                 listener.onSystemActionsChanged();
1894             } catch (RemoteException re) {
1895                 Slog.e(LOG_TAG, "Error sending system actions change to " + mService,
1896                         re);
1897             }
1898         }
1899     }
1900 
notifyClearAccessibilityCacheInternal()1901     private void notifyClearAccessibilityCacheInternal() {
1902         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1903         if (listener != null) {
1904             try {
1905                 if (svcClientTracingEnabled()) {
1906                     logTraceSvcClient("clearAccessibilityCache", "");
1907                 }
1908                 listener.clearAccessibilityCache();
1909             } catch (RemoteException re) {
1910                 Slog.e(LOG_TAG, "Error during requesting accessibility info cache"
1911                         + " to be cleared.", re);
1912             }
1913         }
1914     }
1915 
createImeSessionInternal()1916     private void createImeSessionInternal() {
1917         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1918         if (listener != null) {
1919             try {
1920                 if (svcClientTracingEnabled()) {
1921                     logTraceSvcClient("createImeSession", "");
1922                 }
1923                 AccessibilityCallback callback = new AccessibilityCallback();
1924                 listener.createImeSession(callback);
1925             } catch (RemoteException re) {
1926                 Slog.e(LOG_TAG,
1927                         "Error requesting IME session from " + mService, re);
1928             }
1929         }
1930     }
1931 
setImeSessionEnabledInternal(IAccessibilityInputMethodSession session, boolean enabled)1932     private void setImeSessionEnabledInternal(IAccessibilityInputMethodSession session,
1933             boolean enabled) {
1934         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1935         if (listener != null && session != null) {
1936             try {
1937                 if (svcClientTracingEnabled()) {
1938                     logTraceSvcClient("createImeSession", "");
1939                 }
1940                 listener.setImeSessionEnabled(session, enabled);
1941             } catch (RemoteException re) {
1942                 Slog.e(LOG_TAG,
1943                         "Error requesting IME session from " + mService, re);
1944             }
1945         }
1946     }
1947 
bindInputInternal()1948     private void bindInputInternal() {
1949         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1950         if (listener != null) {
1951             try {
1952                 if (svcClientTracingEnabled()) {
1953                     logTraceSvcClient("bindInput", "");
1954                 }
1955                 listener.bindInput();
1956             } catch (RemoteException re) {
1957                 Slog.e(LOG_TAG,
1958                         "Error binding input to " + mService, re);
1959             }
1960         }
1961     }
1962 
unbindInputInternal()1963     private void unbindInputInternal() {
1964         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1965         if (listener != null) {
1966             try {
1967                 if (svcClientTracingEnabled()) {
1968                     logTraceSvcClient("unbindInput", "");
1969                 }
1970                 listener.unbindInput();
1971             } catch (RemoteException re) {
1972                 Slog.e(LOG_TAG,
1973                         "Error unbinding input to " + mService, re);
1974             }
1975         }
1976     }
1977 
startInputInternal(IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting)1978     private void startInputInternal(IRemoteAccessibilityInputConnection connection,
1979             EditorInfo editorInfo, boolean restarting) {
1980         final IAccessibilityServiceClient listener = getServiceInterfaceSafely();
1981         if (listener != null) {
1982             try {
1983                 if (svcClientTracingEnabled()) {
1984                     logTraceSvcClient("startInput", "editorInfo=" + editorInfo
1985                             + " restarting=" + restarting);
1986                 }
1987                 listener.startInput(connection, editorInfo, restarting);
1988             } catch (RemoteException re) {
1989                 Slog.e(LOG_TAG,
1990                         "Error starting input to " + mService, re);
1991             }
1992         }
1993     }
1994 
getServiceInterfaceSafely()1995     protected IAccessibilityServiceClient getServiceInterfaceSafely() {
1996         synchronized (mLock) {
1997             return mServiceInterface;
1998         }
1999     }
2000 
resolveAccessibilityWindowIdLocked(int accessibilityWindowId)2001     private int resolveAccessibilityWindowIdLocked(int accessibilityWindowId) {
2002         if (accessibilityWindowId == AccessibilityWindowInfo.ACTIVE_WINDOW_ID) {
2003             final int focusedWindowId =
2004                     mA11yWindowManager.getActiveWindowId(mSystemSupport.getCurrentUserIdLocked());
2005             if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) {
2006                 return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
2007             }
2008             return focusedWindowId;
2009         }
2010         return accessibilityWindowId;
2011     }
2012 
resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType)2013     int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
2014         if (windowId == AccessibilityWindowInfo.ANY_WINDOW_ID) {
2015             final int focusedWindowId = mA11yWindowManager.getFocusedWindowId(focusType);
2016             // If the caller is a proxy and the found window doesn't belong to a proxy display
2017             // (or vice versa), then return null. This doesn't work if there are multiple active
2018             // proxys, but in the future this code shouldn't be needed if input focus are
2019             // properly split. (so we will deal with the issues if we see them).
2020             //TODO(254545943): Remove this when there is user and proxy separation of input focus
2021             if (!mA11yWindowManager.windowIdBelongsToDisplayType(focusedWindowId, mDisplayTypes)) {
2022                 return AccessibilityWindowInfo.UNDEFINED_WINDOW_ID;
2023             }
2024             return focusedWindowId;
2025         }
2026         return windowId;
2027     }
2028 
2029     /**
2030      * Request that the system make sure windows are available to interrogate.
2031      *
2032      * @param displayId The logical display id.
2033      */
ensureWindowsAvailableTimedLocked(int displayId)2034     private void ensureWindowsAvailableTimedLocked(int displayId) {
2035         if (displayId == Display.INVALID_DISPLAY) {
2036             return;
2037         }
2038 
2039         if (mA11yWindowManager.getWindowListLocked(displayId) != null) {
2040             return;
2041         }
2042         // If we have no registered callback, update the state we
2043         // we may have to register one but it didn't happen yet.
2044         if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
2045             // Invokes client change to make sure tracking window enabled.
2046             mSystemSupport.onClientChangeLocked(false);
2047         }
2048         // We have no windows but do not care about them, done.
2049         if (!mA11yWindowManager.isTrackingWindowsLocked(displayId)) {
2050             return;
2051         }
2052 
2053         // Wait for the windows with a timeout.
2054         final long startMillis = SystemClock.uptimeMillis();
2055         while (mA11yWindowManager.getWindowListLocked(displayId) == null) {
2056             final long elapsedMillis = SystemClock.uptimeMillis() - startMillis;
2057             final long remainMillis = WAIT_WINDOWS_TIMEOUT_MILLIS - elapsedMillis;
2058             if (remainMillis <= 0) {
2059                 return;
2060             }
2061             try {
2062                 mLock.wait(remainMillis);
2063             } catch (InterruptedException ie) {
2064                 /* ignore */
2065             }
2066         }
2067     }
2068 
2069     /**
2070      * Perform the specified accessibility action
2071      *
2072      * @param resolvedWindowId The window ID
2073      * [Other parameters match the method on IAccessibilityServiceConnection]
2074      *
2075      * @return Whether or not the action could be sent to the app process
2076      */
performAccessibilityActionInternal(int userId, int resolvedWindowId, long accessibilityNodeId, int action, Bundle arguments, int interactionId, IAccessibilityInteractionConnectionCallback callback, int fetchFlags, long interrogatingTid)2077     private boolean performAccessibilityActionInternal(int userId, int resolvedWindowId,
2078             long accessibilityNodeId, int action, Bundle arguments, int interactionId,
2079             IAccessibilityInteractionConnectionCallback callback, int fetchFlags,
2080             long interrogatingTid) {
2081         RemoteAccessibilityConnection connection;
2082         IBinder windowToken = null;
2083         synchronized (mLock) {
2084             connection = mA11yWindowManager.getConnectionLocked(userId, resolvedWindowId);
2085             if (connection == null)  {
2086                 return false;
2087             }
2088             final boolean isA11yFocusAction = (action == ACTION_ACCESSIBILITY_FOCUS)
2089                     || (action == ACTION_CLEAR_ACCESSIBILITY_FOCUS);
2090             if (!isA11yFocusAction) {
2091                 windowToken = mA11yWindowManager.getWindowTokenForUserAndWindowIdLocked(
2092                         userId, resolvedWindowId);
2093             }
2094             final AccessibilityWindowInfo a11yWindowInfo =
2095                     mA11yWindowManager.findA11yWindowInfoByIdLocked(resolvedWindowId);
2096             if (a11yWindowInfo != null && a11yWindowInfo.isInPictureInPictureMode()
2097                     && mA11yWindowManager.getPictureInPictureActionReplacingConnection() != null
2098                     && !isA11yFocusAction) {
2099                 connection = mA11yWindowManager.getPictureInPictureActionReplacingConnection();
2100             }
2101         }
2102         final int interrogatingPid = Binder.getCallingPid();
2103         final long identityToken = Binder.clearCallingIdentity();
2104         try {
2105             // Regardless of whether or not the action succeeds, it was generated by an
2106             // accessibility service that is driven by user actions, so note user activity.
2107             mPowerManager.userActivity(SystemClock.uptimeMillis(),
2108                     PowerManager.USER_ACTIVITY_EVENT_ACCESSIBILITY, 0);
2109 
2110             if (action == ACTION_CLICK || action == ACTION_LONG_CLICK) {
2111                 mA11yWindowManager.notifyOutsideTouch(userId, resolvedWindowId);
2112             }
2113             if (windowToken != null) {
2114                 mWindowManagerService.requestWindowFocus(windowToken);
2115             }
2116             if (intConnTracingEnabled()) {
2117                 logTraceIntConn("performAccessibilityAction",
2118                         accessibilityNodeId + ";" + action + ";" + arguments + ";" + interactionId
2119                         + ";" + callback + ";" + mFetchFlags + ";" + interrogatingPid + ";"
2120                         + interrogatingTid);
2121             }
2122             connection.getRemote().performAccessibilityAction(accessibilityNodeId, action,
2123                     arguments, interactionId, callback, fetchFlags, interrogatingPid,
2124                     interrogatingTid);
2125         } catch (RemoteException re) {
2126             if (DEBUG) {
2127                 Slog.e(LOG_TAG, "Error calling performAccessibilityAction: " + re);
2128             }
2129             return false;
2130         } finally {
2131             Binder.restoreCallingIdentity(identityToken);
2132         }
2133         return true;
2134     }
2135 
2136     /**
2137      * Replace the interaction callback if needed, for example if the window is in picture-
2138      * in-picture mode and needs its nodes replaced.
2139      *
2140      * @param originalCallback The callback we were planning to use
2141      * @param resolvedWindowId The ID of the window we're calling
2142      * @param interactionId The id for the original callback
2143      * @param interrogatingPid Process ID of requester
2144      * @param interrogatingTid Thread ID of requester
2145      *
2146      * @return The callback to use, which may be the original one.
2147      */
replaceCallbackIfNeeded( IAccessibilityInteractionConnectionCallback originalCallback, int resolvedWindowId, int interactionId, int interrogatingPid, long interrogatingTid)2148     private IAccessibilityInteractionConnectionCallback replaceCallbackIfNeeded(
2149             IAccessibilityInteractionConnectionCallback originalCallback, int resolvedWindowId,
2150             int interactionId, int interrogatingPid, long interrogatingTid) {
2151         final RemoteAccessibilityConnection pipActionReplacingConnection =
2152                 mA11yWindowManager.getPictureInPictureActionReplacingConnection();
2153         synchronized (mLock) {
2154             final AccessibilityWindowInfo windowInfo =
2155                     mA11yWindowManager.findA11yWindowInfoByIdLocked(resolvedWindowId);
2156             if ((windowInfo == null) || !windowInfo.isInPictureInPictureMode()
2157                 || (pipActionReplacingConnection == null)) {
2158                 return originalCallback;
2159             }
2160         }
2161         return new ActionReplacingCallback(originalCallback,
2162                 pipActionReplacingConnection.getRemote(), interactionId,
2163                 interrogatingPid, interrogatingTid);
2164     }
2165 
getWindowsByDisplayLocked(int displayId)2166     private List<AccessibilityWindowInfo> getWindowsByDisplayLocked(int displayId) {
2167         final List<AccessibilityWindowInfo> internalWindowList =
2168                 mA11yWindowManager.getWindowListLocked(displayId);
2169         if (internalWindowList == null) {
2170             return null;
2171         }
2172         final List<AccessibilityWindowInfo> returnedWindowList = new ArrayList<>();
2173         final int windowCount = internalWindowList.size();
2174         for (int i = 0; i < windowCount; i++) {
2175             AccessibilityWindowInfo window = internalWindowList.get(i);
2176             AccessibilityWindowInfo windowClone =
2177                     AccessibilityWindowInfo.obtain(window);
2178             windowClone.setConnectionId(mId);
2179             returnedWindowList.add(windowClone);
2180         }
2181         return returnedWindowList;
2182     }
2183 
getComponentName()2184     public ComponentName getComponentName() {
2185         return mComponentName;
2186     }
2187 
2188     private final class InvocationHandler extends Handler {
2189         public static final int MSG_ON_GESTURE = 1;
2190         public static final int MSG_CLEAR_ACCESSIBILITY_CACHE = 2;
2191 
2192         private static final int MSG_ON_MAGNIFICATION_CHANGED = 5;
2193         private static final int MSG_ON_SOFT_KEYBOARD_STATE_CHANGED = 6;
2194         private static final int MSG_ON_ACCESSIBILITY_BUTTON_CLICKED = 7;
2195         private static final int MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED = 8;
2196         private static final int MSG_ON_SYSTEM_ACTIONS_CHANGED = 9;
2197         private static final int MSG_CREATE_IME_SESSION = 10;
2198         private static final int MSG_SET_IME_SESSION_ENABLED = 11;
2199         private static final int MSG_BIND_INPUT = 12;
2200         private static final int MSG_UNBIND_INPUT = 13;
2201         private static final int MSG_START_INPUT = 14;
2202 
2203         /** List of magnification callback states, mapping from displayId -> Boolean */
2204         @GuardedBy("mlock")
2205         private final SparseArray<Boolean> mMagnificationCallbackState = new SparseArray<>(0);
2206         private boolean mIsSoftKeyboardCallbackEnabled = false;
2207 
InvocationHandler(Looper looper)2208         public InvocationHandler(Looper looper) {
2209             super(looper, null, true);
2210         }
2211 
2212         @Override
handleMessage(Message message)2213         public void handleMessage(Message message) {
2214             final int type = message.what;
2215             switch (type) {
2216                 case MSG_ON_GESTURE: {
2217                     notifyGestureInternal((AccessibilityGestureEvent) message.obj);
2218                 } break;
2219 
2220                 case MSG_CLEAR_ACCESSIBILITY_CACHE: {
2221                     notifyClearAccessibilityCacheInternal();
2222                 } break;
2223 
2224                 case MSG_ON_MAGNIFICATION_CHANGED: {
2225                     final SomeArgs args = (SomeArgs) message.obj;
2226                     final Region region = (Region) args.arg1;
2227                     final MagnificationConfig config = (MagnificationConfig) args.arg2;
2228                     final int displayId = args.argi1;
2229                     notifyMagnificationChangedInternal(displayId, region, config);
2230                     args.recycle();
2231                 } break;
2232 
2233                 case MSG_ON_SOFT_KEYBOARD_STATE_CHANGED: {
2234                     final int showState = (int) message.arg1;
2235                     notifySoftKeyboardShowModeChangedInternal(showState);
2236                 } break;
2237 
2238                 case MSG_ON_ACCESSIBILITY_BUTTON_CLICKED: {
2239                     final int displayId = (int) message.arg1;
2240                     notifyAccessibilityButtonClickedInternal(displayId);
2241                 } break;
2242 
2243                 case MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED: {
2244                     final boolean available = (message.arg1 != 0);
2245                     notifyAccessibilityButtonAvailabilityChangedInternal(available);
2246                 } break;
2247                 case MSG_ON_SYSTEM_ACTIONS_CHANGED: {
2248                     notifySystemActionsChangedInternal();
2249                     break;
2250                 }
2251                 case MSG_CREATE_IME_SESSION:
2252                     createImeSessionInternal();
2253                     break;
2254                 case MSG_SET_IME_SESSION_ENABLED:
2255                     final boolean enabled = (message.arg1 != 0);
2256                     final IAccessibilityInputMethodSession session =
2257                             (IAccessibilityInputMethodSession) message.obj;
2258                     setImeSessionEnabledInternal(session, enabled);
2259                     break;
2260                 case MSG_BIND_INPUT:
2261                     bindInputInternal();
2262                     break;
2263                 case MSG_UNBIND_INPUT:
2264                     unbindInputInternal();
2265                     break;
2266                 case MSG_START_INPUT:
2267                     final boolean restarting = (message.arg1 != 0);
2268                     final SomeArgs args = (SomeArgs) message.obj;
2269                     final IRemoteAccessibilityInputConnection connection =
2270                             (IRemoteAccessibilityInputConnection) args.arg1;
2271                     final EditorInfo editorInfo = (EditorInfo) args.arg2;
2272                     startInputInternal(connection, editorInfo, restarting);
2273                     args.recycle();
2274                     break;
2275                 default: {
2276                     throw new IllegalArgumentException("Unknown message: " + type);
2277                 }
2278             }
2279         }
2280 
notifyMagnificationChangedLocked(int displayId, @NonNull Region region, @NonNull MagnificationConfig config)2281         public void notifyMagnificationChangedLocked(int displayId, @NonNull Region region,
2282                 @NonNull MagnificationConfig config) {
2283             synchronized (mLock) {
2284                 if (mMagnificationCallbackState.get(displayId) == null) {
2285                     return;
2286                 }
2287             }
2288 
2289             final SomeArgs args = SomeArgs.obtain();
2290             args.arg1 = region;
2291             args.arg2 = config;
2292             args.argi1 = displayId;
2293 
2294             final Message msg = obtainMessage(MSG_ON_MAGNIFICATION_CHANGED, args);
2295             msg.sendToTarget();
2296         }
2297 
setMagnificationCallbackEnabled(int displayId, boolean enabled)2298         public void setMagnificationCallbackEnabled(int displayId, boolean enabled) {
2299             synchronized (mLock) {
2300                 if (enabled) {
2301                     mMagnificationCallbackState.put(displayId, true);
2302                 } else {
2303                     mMagnificationCallbackState.remove(displayId);
2304                 }
2305             }
2306         }
2307 
isMagnificationCallbackEnabled(int displayId)2308         public boolean isMagnificationCallbackEnabled(int displayId) {
2309             synchronized (mLock) {
2310                 return mMagnificationCallbackState.get(displayId) != null;
2311             }
2312         }
2313 
notifySoftKeyboardShowModeChangedLocked(int showState)2314         public void notifySoftKeyboardShowModeChangedLocked(int showState) {
2315             if (!mIsSoftKeyboardCallbackEnabled) {
2316                 return;
2317             }
2318 
2319             final Message msg = obtainMessage(MSG_ON_SOFT_KEYBOARD_STATE_CHANGED, showState, 0);
2320             msg.sendToTarget();
2321         }
2322 
setSoftKeyboardCallbackEnabled(boolean enabled)2323         public void setSoftKeyboardCallbackEnabled(boolean enabled) {
2324             mIsSoftKeyboardCallbackEnabled = enabled;
2325         }
2326 
notifyAccessibilityButtonClickedLocked(int displayId)2327         public void notifyAccessibilityButtonClickedLocked(int displayId) {
2328             final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_CLICKED, displayId, 0);
2329             msg.sendToTarget();
2330         }
2331 
notifyAccessibilityButtonAvailabilityChangedLocked(boolean available)2332         public void notifyAccessibilityButtonAvailabilityChangedLocked(boolean available) {
2333             final Message msg = obtainMessage(MSG_ON_ACCESSIBILITY_BUTTON_AVAILABILITY_CHANGED,
2334                     (available ? 1 : 0), 0);
2335             msg.sendToTarget();
2336         }
2337 
createImeSessionLocked()2338         public void createImeSessionLocked() {
2339             final Message msg = obtainMessage(MSG_CREATE_IME_SESSION);
2340             msg.sendToTarget();
2341         }
2342 
setImeSessionEnabledLocked(IAccessibilityInputMethodSession session, boolean enabled)2343         public void setImeSessionEnabledLocked(IAccessibilityInputMethodSession session,
2344                 boolean enabled) {
2345             final Message msg = obtainMessage(MSG_SET_IME_SESSION_ENABLED, (enabled ? 1 : 0),
2346                     0, session);
2347             msg.sendToTarget();
2348         }
2349 
bindInputLocked()2350         public void bindInputLocked() {
2351             final Message msg = obtainMessage(MSG_BIND_INPUT);
2352             msg.sendToTarget();
2353         }
2354 
unbindInputLocked()2355         public void unbindInputLocked() {
2356             final Message msg = obtainMessage(MSG_UNBIND_INPUT);
2357             msg.sendToTarget();
2358         }
2359 
startInputLocked( IRemoteAccessibilityInputConnection connection, EditorInfo editorInfo, boolean restarting)2360         public void startInputLocked(
2361                 IRemoteAccessibilityInputConnection connection,
2362                 EditorInfo editorInfo, boolean restarting) {
2363             final SomeArgs args = SomeArgs.obtain();
2364             args.arg1 = connection;
2365             args.arg2 = editorInfo;
2366             final Message msg = obtainMessage(MSG_START_INPUT, restarting ? 1 : 0, 0, args);
2367             msg.sendToTarget();
2368         }
2369     }
2370 
isServiceHandlesDoubleTapEnabled()2371     public boolean isServiceHandlesDoubleTapEnabled() {
2372         return mServiceHandlesDoubleTap;
2373     }
2374 
isMultiFingerGesturesEnabled()2375     public boolean isMultiFingerGesturesEnabled() {
2376         return mRequestMultiFingerGestures;
2377     }
2378 
isTwoFingerPassthroughEnabled()2379     public boolean isTwoFingerPassthroughEnabled() {
2380         return mRequestTwoFingerPassthrough;
2381     }
2382 
isSendMotionEventsEnabled()2383     public boolean isSendMotionEventsEnabled() {
2384         return mSendMotionEvents;
2385     }
2386 
2387     @Override
setGestureDetectionPassthroughRegion(int displayId, Region region)2388     public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
2389         if (svcConnTracingEnabled()) {
2390             logTraceSvcConn("setGestureDetectionPassthroughRegion",
2391                     "displayId=" + displayId + ";region=" + region);
2392         }
2393         mSystemSupport.setGestureDetectionPassthroughRegion(displayId, region);
2394     }
2395 
2396     @Override
setTouchExplorationPassthroughRegion(int displayId, Region region)2397     public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
2398         if (svcConnTracingEnabled()) {
2399             logTraceSvcConn("setTouchExplorationPassthroughRegion",
2400                     "displayId=" + displayId + ";region=" + region);
2401         }
2402         mSystemSupport.setTouchExplorationPassthroughRegion(displayId, region);
2403     }
2404 
2405     @Override
setFocusAppearance(int strokeWidth, int color)2406     public void setFocusAppearance(int strokeWidth, int color) {
2407         if (svcConnTracingEnabled()) {
2408             logTraceSvcConn("setFocusAppearance", "strokeWidth=" + strokeWidth + ";color=" + color);
2409         }
2410     }
2411 
2412     @Override
setCacheEnabled(boolean enabled)2413     public void setCacheEnabled(boolean enabled) {
2414         if (svcConnTracingEnabled()) {
2415             logTraceSvcConn("setCacheEnabled", "enabled=" + enabled);
2416         }
2417         final long identity = Binder.clearCallingIdentity();
2418         try {
2419             synchronized (mLock) {
2420                 mUsesAccessibilityCache = enabled;
2421                 mSystemSupport.onClientChangeLocked(true);
2422             }
2423         } finally {
2424             Binder.restoreCallingIdentity(identity);
2425         }
2426     }
2427 
2428     @Override
logTrace(long timestamp, String where, long loggingTypes, String callingParams, int processId, long threadId, int callingUid, Bundle callingStack)2429     public void logTrace(long timestamp, String where, long loggingTypes, String callingParams,
2430             int processId, long threadId, int callingUid, Bundle callingStack) {
2431         if (mTrace.isA11yTracingEnabledForTypes(loggingTypes)) {
2432             ArrayList<StackTraceElement> list =
2433                     (ArrayList<StackTraceElement>) callingStack.getSerializable(CALL_STACK, java.util.ArrayList.class);
2434             HashSet<String> ignoreList =
2435                     (HashSet<String>) callingStack.getSerializable(IGNORE_CALL_STACK, java.util.HashSet.class);
2436             mTrace.logTrace(timestamp, where, loggingTypes, callingParams, processId, threadId,
2437                     callingUid, list.toArray(new StackTraceElement[list.size()]), ignoreList);
2438         }
2439     }
2440 
svcClientTracingEnabled()2441     protected boolean svcClientTracingEnabled() {
2442         return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CLIENT);
2443     }
2444 
logTraceSvcClient(String methodName, String params)2445     protected void logTraceSvcClient(String methodName, String params) {
2446         mTrace.logTrace(TRACE_SVC_CLIENT + "." + methodName,
2447                     FLAGS_ACCESSIBILITY_SERVICE_CLIENT, params);
2448     }
2449 
svcConnTracingEnabled()2450     protected boolean svcConnTracingEnabled() {
2451         return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_SERVICE_CONNECTION);
2452     }
2453 
logTraceSvcConn(String methodName, String params)2454     protected void logTraceSvcConn(String methodName, String params) {
2455         mTrace.logTrace(TRACE_SVC_CONN + "." + methodName,
2456                 FLAGS_ACCESSIBILITY_SERVICE_CONNECTION, params);
2457     }
2458 
intConnTracingEnabled()2459     protected boolean intConnTracingEnabled() {
2460         return mTrace.isA11yTracingEnabledForTypes(FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION);
2461     }
2462 
logTraceIntConn(String methodName, String params)2463     protected void logTraceIntConn(String methodName, String params) {
2464         mTrace.logTrace(LOG_TAG + "." + methodName,
2465                 FLAGS_ACCESSIBILITY_INTERACTION_CONNECTION, params);
2466     }
2467 
wmTracingEnabled()2468     protected boolean wmTracingEnabled() {
2469         return mTrace.isA11yTracingEnabledForTypes(FLAGS_WINDOW_MANAGER_INTERNAL);
2470     }
2471 
logTraceWM(String methodName, String params)2472     protected void logTraceWM(String methodName, String params) {
2473         mTrace.logTrace(TRACE_WM + "." + methodName, FLAGS_WINDOW_MANAGER_INTERNAL, params);
2474     }
2475 
setServiceDetectsGesturesEnabled(int displayId, boolean mode)2476     public void setServiceDetectsGesturesEnabled(int displayId, boolean mode) {
2477         mServiceDetectsGestures.put(displayId, mode);
2478         mSystemSupport.setServiceDetectsGesturesEnabled(displayId, mode);
2479     }
2480 
isServiceDetectsGesturesEnabled(int displayId)2481     public boolean isServiceDetectsGesturesEnabled(int displayId) {
2482         if (mServiceDetectsGestures.contains(displayId)) {
2483             return mServiceDetectsGestures.get(displayId);
2484         }
2485         return false;
2486     }
2487 
requestTouchExploration(int displayId)2488     public void requestTouchExploration(int displayId) {
2489         mSystemSupport.requestTouchExploration(displayId);
2490     }
2491 
requestDragging(int displayId, int pointerId)2492     public void requestDragging(int displayId, int pointerId) {
2493         mSystemSupport.requestDragging(displayId, pointerId);
2494     }
2495 
requestDelegating(int displayId)2496     public void requestDelegating(int displayId) {
2497         mSystemSupport.requestDelegating(displayId);
2498     }
2499 
onDoubleTap(int displayId)2500     public void onDoubleTap(int displayId) {
2501         mSystemSupport.onDoubleTap(displayId);
2502     }
2503 
onDoubleTapAndHold(int displayId)2504     public void onDoubleTapAndHold(int displayId) {
2505         mSystemSupport.onDoubleTapAndHold(displayId);
2506     }
2507 
2508     /**
2509      * Sets the scaling factor for animations.
2510      */
setAnimationScale(float scale)2511     public void setAnimationScale(float scale) {
2512         final long identity = Binder.clearCallingIdentity();
2513         try {
2514             Settings.Global.putFloat(
2515                     mContext.getContentResolver(), Settings.Global.WINDOW_ANIMATION_SCALE, scale);
2516             Settings.Global.putFloat(
2517                     mContext.getContentResolver(),
2518                     Settings.Global.TRANSITION_ANIMATION_SCALE,
2519                     scale);
2520             Settings.Global.putFloat(
2521                     mContext.getContentResolver(), Settings.Global.ANIMATOR_DURATION_SCALE, scale);
2522         } finally {
2523             Binder.restoreCallingIdentity(identity);
2524         }
2525     }
2526 
2527     private static final class AccessibilityCallback
2528             extends IAccessibilityInputMethodSessionCallback.Stub {
2529         @Override
sessionCreated(IAccessibilityInputMethodSession session, int id)2530         public void sessionCreated(IAccessibilityInputMethodSession session, int id) {
2531             Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AACS.sessionCreated");
2532             final long ident = Binder.clearCallingIdentity();
2533             try {
2534                 InputMethodManagerInternal.get().onSessionForAccessibilityCreated(id, session);
2535             } finally {
2536                 Binder.restoreCallingIdentity(ident);
2537             }
2538             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2539         }
2540     }
2541 
2542     @Override
attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc)2543     public void attachAccessibilityOverlayToDisplay(int displayId, SurfaceControl sc) {
2544         mSystemSupport.attachAccessibilityOverlayToDisplay(displayId, sc);
2545     }
2546 
2547     @Override
attachAccessibilityOverlayToWindow(int accessibilityWindowId, SurfaceControl sc)2548     public void attachAccessibilityOverlayToWindow(int accessibilityWindowId, SurfaceControl sc)
2549             throws RemoteException {
2550         SurfaceControl.Transaction t = new SurfaceControl.Transaction();
2551         t.setTrustedOverlay(sc, true).apply();
2552         t.close();
2553         synchronized (mLock) {
2554             RemoteAccessibilityConnection connection =
2555                     mA11yWindowManager.getConnectionLocked(
2556                             mSystemSupport.getCurrentUserIdLocked(),
2557                             resolveAccessibilityWindowIdLocked(accessibilityWindowId));
2558             if (connection == null) {
2559                 Slog.e(LOG_TAG, "unable to get remote accessibility connection.");
2560                 return;
2561             }
2562             connection.getRemote().attachAccessibilityOverlayToWindow(sc);
2563         }
2564     }
2565 }