From 466b71e1a287bd20560f1bf10db15e5fa7f2c8d1 Mon Sep 17 00:00:00 2001 From: Phil Weaver Date: Fri, 20 Apr 2018 14:51:39 -0700 Subject: [PATCH] Add config value for fingerprint gesture support Also correcting docs for using the fingerprint gesture flag. Bug: 76419487 Test: Verified with a test a11y service that gestures are not available. Adding a unit test to verify this case. Change-Id: I90233613777013e8b117a2d94f767be292c80019 --- .../AccessibilityServiceInfo.java | 11 ++++++- core/res/res/values/config.xml | 3 ++ core/res/res/values/symbols.xml | 1 + .../AccessibilityManagerService.java | 2 +- .../FingerprintGestureDispatcher.java | 19 +++++++++-- .../FingerprintGestureDispatcherTest.java | 33 +++++++++++++++++-- 6 files changed, 61 insertions(+), 8 deletions(-) diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java index 452225cd7da0f..ed684d7a59018 100644 --- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java +++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java @@ -302,7 +302,16 @@ public class AccessibilityServiceInfo implements Parcelable { /** * This flag requests that all fingerprint gestures be sent to the accessibility service. - * It is handled in {@link FingerprintGestureController} + *

+ * Services that want to set this flag have to declare the capability + * to retrieve window content in their meta-data by setting the attribute + * {@link android.R.attr#canRequestFingerprintGestures} to + * true, otherwise this flag will be ignored. For how to declare the meta-data + * of a service refer to {@value AccessibilityService#SERVICE_META_DATA}. + *

+ * + * @see android.R.styleable#AccessibilityService_canRequestFingerprintGestures + * @see AccessibilityService#getFingerprintGestureController() */ public static final int FLAG_REQUEST_FINGERPRINT_GESTURES = 0x00000200; diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index fc030ca3d316c..8c6ef7608a554 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2850,6 +2850,9 @@ 5 + + false + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 0de2cb0d13ae2..ea32a1723e026 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2404,6 +2404,7 @@ + diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index 08aa0632206c2..7798cf7af3cb9 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -2232,7 +2232,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } if (service != null) { mFingerprintGestureDispatcher = new FingerprintGestureDispatcher( - service, mLock); + service, mContext.getResources(), mLock); break; } } diff --git a/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java b/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java index fe787b36472db..96418aac7ffad 100644 --- a/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java +++ b/services/accessibility/java/com/android/server/accessibility/FingerprintGestureDispatcher.java @@ -17,6 +17,7 @@ package com.android.server.accessibility; import android.accessibilityservice.FingerprintGestureController; +import android.content.res.Resources; import android.hardware.fingerprint.IFingerprintClientActiveCallback; import android.hardware.fingerprint.IFingerprintService; import android.os.Binder; @@ -42,6 +43,7 @@ public class FingerprintGestureDispatcher extends IFingerprintClientActiveCallba private final Object mLock; private final IFingerprintService mFingerprintService; private final Handler mHandler; + private final boolean mHardwareSupportsGestures; // This field is ground truth for whether or not we are registered. Only write to it in handler. private boolean mRegisteredReadOnlyExceptInHandler; @@ -50,8 +52,11 @@ public class FingerprintGestureDispatcher extends IFingerprintClientActiveCallba * @param fingerprintService The system's fingerprint service * @param lock A lock to use when managing internal state */ - public FingerprintGestureDispatcher(IFingerprintService fingerprintService, Object lock) { + public FingerprintGestureDispatcher(IFingerprintService fingerprintService, + Resources resources, Object lock) { mFingerprintService = fingerprintService; + mHardwareSupportsGestures = resources.getBoolean( + com.android.internal.R.bool.config_fingerprintSupportsGestures); mLock = lock; mHandler = new Handler(this); } @@ -61,9 +66,11 @@ public class FingerprintGestureDispatcher extends IFingerprintClientActiveCallba * @param lock A lock to use when managing internal state * @param handler A handler to use internally. Used for testing. */ - public FingerprintGestureDispatcher(IFingerprintService fingerprintService, Object lock, - Handler handler) { + public FingerprintGestureDispatcher(IFingerprintService fingerprintService, + Resources resources, Object lock, Handler handler) { mFingerprintService = fingerprintService; + mHardwareSupportsGestures = resources.getBoolean( + com.android.internal.R.bool.config_fingerprintSupportsGestures); mLock = lock; mHandler = handler; } @@ -74,6 +81,8 @@ public class FingerprintGestureDispatcher extends IFingerprintClientActiveCallba * @param clientList The list of potential clients. */ public void updateClientList(List clientList) { + if (!mHardwareSupportsGestures) return; + synchronized (mLock) { mCapturingClients.clear(); for (int i = 0; i < clientList.size(); i++) { @@ -96,6 +105,8 @@ public class FingerprintGestureDispatcher extends IFingerprintClientActiveCallba @Override public void onClientActiveChanged(boolean nonGestureFingerprintClientActive) { + if (!mHardwareSupportsGestures) return; + synchronized (mLock) { for (int i = 0; i < mCapturingClients.size(); i++) { mCapturingClients.get(i).onFingerprintGestureDetectionActiveChanged( @@ -105,6 +116,8 @@ public class FingerprintGestureDispatcher extends IFingerprintClientActiveCallba } public boolean isFingerprintGestureDetectionAvailable() { + if (!mHardwareSupportsGestures) return false; + long identity = Binder.clearCallingIdentity(); try { return !mFingerprintService.isClientActive(); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java index 98bf53c9d55fa..6ce7bbe6117ed 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/FingerprintGestureDispatcherTest.java @@ -17,14 +17,17 @@ package com.android.server.accessibility; import android.accessibilityservice.FingerprintGestureController; +import android.content.res.Resources; import android.hardware.fingerprint.IFingerprintService; import android.os.Handler; +import android.os.Looper; import android.os.Message; import android.view.KeyEvent; import com.android.server.accessibility.FingerprintGestureDispatcher.FingerprintGestureClient; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -49,16 +52,27 @@ public class FingerprintGestureDispatcherTest { private @Mock IFingerprintService mMockFingerprintService; private @Mock FingerprintGestureClient mNonGestureCapturingClient; private @Mock FingerprintGestureClient mGestureCapturingClient; - private @Mock FingerprintGestureDispatcher mFingerprintGestureDispatcher; + private @Mock Resources mMockResources; + private MessageCapturingHandler mMessageCapturingHandler; + private FingerprintGestureDispatcher mFingerprintGestureDispatcher; + + @BeforeClass + public static void oneTimeInitialization() { + if (Looper.myLooper() == null) { + Looper.prepare(); + } + } @Before public void setup() { MockitoAnnotations.initMocks(this); + // For most tests, we support fingerprint gestures + when(mMockResources.getBoolean(anyInt())).thenReturn(true); mMessageCapturingHandler = new MessageCapturingHandler( msg -> mFingerprintGestureDispatcher.handleMessage(msg)); mFingerprintGestureDispatcher = new FingerprintGestureDispatcher(mMockFingerprintService, - new Object(), mMessageCapturingHandler); + mMockResources, new Object(), mMessageCapturingHandler); when(mNonGestureCapturingClient.isCapturingFingerprintGestures()).thenReturn(false); when(mGestureCapturingClient.isCapturingFingerprintGestures()).thenReturn(true); } @@ -149,10 +163,23 @@ public class FingerprintGestureDispatcherTest { } @Test - public void testIsGestureDetectionActive_dependsOnFingerprintService() throws Exception { + public void testIsGestureDetectionAvailable_dependsOnFingerprintService() throws Exception { when(mMockFingerprintService.isClientActive()).thenReturn(true); assertFalse(mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable()); when(mMockFingerprintService.isClientActive()).thenReturn(false); assertTrue(mFingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable()); } + + @Test + public void ifGestureDectionNotSupported_neverSaysAvailable() throws Exception { + when(mMockResources.getBoolean(anyInt())).thenReturn(false); + // Need to create a new dispatcher, since it picks up the resource value in its + // constructor. This is fine since hardware config values don't change dynamically. + FingerprintGestureDispatcher fingerprintGestureDispatcher = + new FingerprintGestureDispatcher(mMockFingerprintService, mMockResources, + new Object(), mMessageCapturingHandler); + + when(mMockFingerprintService.isClientActive()).thenReturn(false); + assertFalse(fingerprintGestureDispatcher.isFingerprintGestureDetectionAvailable()); + } }