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