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