From b45af76b3d822be068d0855a9820a77c67fed2b9 Mon Sep 17 00:00:00 2001 From: Hiroki Sato Date: Thu, 14 Jan 2021 14:12:31 +0900 Subject: Dispatch accessibility gesture if device supports touch This change fixes the issue where AccessibilityService was not able to dispatch a gesture if a device doesn't have a touchscreen hardware feature, resulting the behavior gap between CTS and framework. With this CL, AccessibilityService can dispatch a gesture if the device declares touchscreen or faketouch hardware features. Bug: 177021722 Test: AccessibilityManagerServiceTest AccessibilityServiceConnectionTest Test: CtsAccessibilityServiceTestCases on crosshatch and kindred Change-Id: I8a1e4884d1283705d409ed38e35047ec2dcd89f0 --- .../server/accessibility/AccessibilityServiceConnection.java | 3 +-- .../java/com/android/server/wm/WindowManagerInternal.java | 4 ++-- .../java/com/android/server/wm/WindowManagerService.java | 12 ++++++------ .../accessibility/AccessibilityServiceConnectionTest.java | 10 ++++------ 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java index 2626654aabf2..a9e8ea03eab8 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityServiceConnection.java @@ -372,12 +372,11 @@ class AccessibilityServiceConnection extends AbstractAccessibilityServiceConnect @Override public void dispatchGesture(int sequence, ParceledListSlice gestureSteps, int displayId) { - final boolean isTouchableDisplay = mWindowManagerService.isTouchableDisplay(displayId); synchronized (mLock) { if (mSecurityPolicy.canPerformGestures(this)) { MotionEventInjector motionEventInjector = mSystemSupport.getMotionEventInjectorForDisplayLocked(displayId); - if (motionEventInjector != null && isTouchableDisplay) { + if (mWindowManagerService.isTouchOrFaketouchDevice()) { motionEventInjector.injectEvents( gestureSteps.getList(), mServiceInterface, sequence, displayId); } else { diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index a3a9eb773abf..1f438183754f 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -543,9 +543,9 @@ public abstract class WindowManagerInternal { public abstract void removeNonHighRefreshRatePackage(@NonNull String packageName); /** - * Checks if this display is touchable. + * Checks if the device supports touch or faketouch. */ - public abstract boolean isTouchableDisplay(int displayId); + public abstract boolean isTouchOrFaketouchDevice(); /** * Returns the info associated with the input token used to determine if a key should be diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 6319c80dc9bd..844edd08df17 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -753,6 +753,7 @@ public class WindowManagerService extends IWindowManager.Stub final TaskSnapshotController mTaskSnapshotController; boolean mIsTouchDevice; + boolean mIsFakeTouchDevice; final H mH = new H(); @@ -5030,6 +5031,8 @@ public class WindowManagerService extends IWindowManager.Stub mRoot.forAllDisplays(DisplayContent::reconfigureDisplayLocked); mIsTouchDevice = mContext.getPackageManager().hasSystemFeature( PackageManager.FEATURE_TOUCHSCREEN); + mIsFakeTouchDevice = mContext.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_FAKETOUCH); } try { @@ -8018,13 +8021,10 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public boolean isTouchableDisplay(int displayId) { + public boolean isTouchOrFaketouchDevice() { synchronized (mGlobalLock) { - final DisplayContent displayContent = mRoot.getDisplayContent(displayId); - final Configuration configuration = - displayContent != null ? displayContent.getConfiguration() : null; - return configuration != null - && configuration.touchscreen == Configuration.TOUCHSCREEN_FINGER; + // All touchable devices are also faketouchable. + return mIsFakeTouchDevice; } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java index 27edfd4ef1d2..6963a1ab1538 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityServiceConnectionTest.java @@ -110,8 +110,6 @@ public class AccessibilityServiceConnectionTest { mMockResolveInfo.serviceInfo.applicationInfo = mock(ApplicationInfo.class); when(mMockIBinder.queryLocalInterface(any())).thenReturn(mMockServiceClient); - when(mMockWindowManagerInternal.isTouchableDisplay(Display.DEFAULT_DISPLAY)).thenReturn( - true); mConnection = new AccessibilityServiceConnection(mMockUserState, mMockContext, COMPONENT_NAME, mMockServiceInfo, SERVICE_ID, mHandler, new Object(), @@ -197,8 +195,9 @@ public class AccessibilityServiceConnectionTest { } @Test - public void sendGesture_touchableDisplay_injectEvents() + public void sendGesture_touchableDevice_injectEvents() throws RemoteException { + when(mMockWindowManagerInternal.isTouchOrFaketouchDevice()).thenReturn(true); setServiceBinding(COMPONENT_NAME); mConnection.bindLocked(); mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); @@ -213,10 +212,9 @@ public class AccessibilityServiceConnectionTest { } @Test - public void sendGesture_untouchableDisplay_performGestureResultFailed() + public void sendGesture_untouchableDevice_performGestureResultFailed() throws RemoteException { - when(mMockWindowManagerInternal.isTouchableDisplay(Display.DEFAULT_DISPLAY)).thenReturn( - false); + when(mMockWindowManagerInternal.isTouchOrFaketouchDevice()).thenReturn(false); setServiceBinding(COMPONENT_NAME); mConnection.bindLocked(); mConnection.onServiceConnected(COMPONENT_NAME, mMockIBinder); -- cgit v1.2.3-59-g8ed1b