Home | History | Annotate | Download | only in accessibilityservice
      1 /*
      2  * Copyright (C) 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 android.accessibilityservice;
     18 
     19 import android.annotation.NonNull;
     20 import android.annotation.Nullable;
     21 import android.os.Handler;
     22 import android.os.RemoteException;
     23 import android.util.ArrayMap;
     24 import android.util.Log;
     25 import com.android.internal.annotations.VisibleForTesting;
     26 
     27 /**
     28  * An {@link AccessibilityService} can capture gestures performed on a device's fingerprint
     29  * sensor, as long as the device has a sensor capable of detecting gestures.
     30  * <p>
     31  * This capability must be declared by the service as
     32  * {@link AccessibilityServiceInfo#CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES}. It also requires
     33  * the permission {@link android.Manifest.permission#USE_FINGERPRINT}.
     34  * <p>
     35  * Because capturing fingerprint gestures may have side effects, services with the capability only
     36  * capture gestures when {@link AccessibilityServiceInfo#FLAG_CAPTURE_FINGERPRINT_GESTURES} is set.
     37  * <p>
     38  * <strong>Note: </strong>The fingerprint sensor is used for authentication in critical use cases,
     39  * so services must carefully design their user's experience when performing gestures on the sensor.
     40  * When the sensor is in use by an app, for example, when authenticating or enrolling a user,
     41  * the sensor will not detect gestures. Services need to ensure that users understand when the
     42  * sensor is in-use for authentication to prevent users from authenticating unintentionally when
     43  * trying to interact with the service. They can use
     44  * {@link FingerprintGestureCallback#onGestureDetectionAvailabilityChanged(boolean)} to learn when
     45  * gesture detection becomes unavailable.
     46  * <p>
     47  * Multiple accessibility services may listen for fingerprint gestures simultaneously, so services
     48  * should provide a way for the user to disable the use of this feature so multiple services don't
     49  * conflict with each other.
     50  * <p>
     51  * {@see android.hardware.fingerprint.FingerprintManager#isHardwareDetected}
     52  */
     53 public final class FingerprintGestureController {
     54     /** Identifier for a swipe right on the fingerprint sensor */
     55     public static final int FINGERPRINT_GESTURE_SWIPE_RIGHT = 0x00000001;
     56 
     57     /** Identifier for a swipe left on the fingerprint sensor */
     58     public static final int FINGERPRINT_GESTURE_SWIPE_LEFT = 0x00000002;
     59 
     60     /** Identifier for a swipe up on the fingerprint sensor */
     61     public static final int FINGERPRINT_GESTURE_SWIPE_UP = 0x00000004;
     62 
     63     /** Identifier for a swipe down on the fingerprint sensor */
     64     public static final int FINGERPRINT_GESTURE_SWIPE_DOWN = 0x00000008;
     65 
     66     private static final String LOG_TAG = "FingerprintGestureController";
     67     private final Object mLock = new Object();
     68     private final IAccessibilityServiceConnection mAccessibilityServiceConnection;
     69 
     70     private final ArrayMap<FingerprintGestureCallback, Handler> mCallbackHandlerMap =
     71             new ArrayMap<>(1);
     72 
     73     /**
     74      * @param connection The connection to use for system interactions
     75      * @hide
     76      */
     77     @VisibleForTesting
     78     public FingerprintGestureController(IAccessibilityServiceConnection connection) {
     79         mAccessibilityServiceConnection = connection;
     80     }
     81 
     82     /**
     83      * Gets if the fingerprint sensor's gesture detection is available.
     84      *
     85      * @return {@code true} if the sensor's gesture detection is available. {@code false} if it is
     86      * not currently detecting gestures (for example, if it is enrolling a finger).
     87      */
     88     public boolean isGestureDetectionAvailable() {
     89         try {
     90             return mAccessibilityServiceConnection.isFingerprintGestureDetectionAvailable();
     91         } catch (RemoteException re) {
     92             Log.w(LOG_TAG, "Failed to check if fingerprint gestures are active", re);
     93             re.rethrowFromSystemServer();
     94             return false;
     95         }
     96     }
     97 
     98     /**
     99      * Register a callback to be informed of fingerprint sensor gesture events.
    100      *
    101      * @param callback The listener to be added.
    102      * @param handler The handler to use for the callback. If {@code null}, callbacks will happen
    103      * on the service's main thread.
    104      */
    105     public void registerFingerprintGestureCallback(
    106             @NonNull FingerprintGestureCallback callback, @Nullable Handler handler) {
    107         synchronized (mLock) {
    108             mCallbackHandlerMap.put(callback, handler);
    109         }
    110     }
    111 
    112     /**
    113      * Unregister a listener added with {@link #registerFingerprintGestureCallback}.
    114      *
    115      * @param callback The callback to remove. Removing a callback that was never added has no
    116      * effect.
    117      */
    118     public void unregisterFingerprintGestureCallback(FingerprintGestureCallback callback) {
    119         synchronized (mLock) {
    120             mCallbackHandlerMap.remove(callback);
    121         }
    122     }
    123 
    124     /**
    125      * Called when gesture detection becomes active or inactive
    126      * @hide
    127      */
    128     public void onGestureDetectionActiveChanged(boolean active) {
    129         final ArrayMap<FingerprintGestureCallback, Handler> handlerMap;
    130         synchronized (mLock) {
    131             handlerMap = new ArrayMap<>(mCallbackHandlerMap);
    132         }
    133         int numListeners = handlerMap.size();
    134         for (int i = 0; i < numListeners; i++) {
    135             FingerprintGestureCallback callback = handlerMap.keyAt(i);
    136             Handler handler = handlerMap.valueAt(i);
    137             if (handler != null) {
    138                 handler.post(() -> callback.onGestureDetectionAvailabilityChanged(active));
    139             } else {
    140                 callback.onGestureDetectionAvailabilityChanged(active);
    141             }
    142         }
    143     }
    144 
    145     /**
    146      * Called when gesture is detected.
    147      * @hide
    148      */
    149     public void onGesture(int gesture) {
    150         final ArrayMap<FingerprintGestureCallback, Handler> handlerMap;
    151         synchronized (mLock) {
    152             handlerMap = new ArrayMap<>(mCallbackHandlerMap);
    153         }
    154         int numListeners = handlerMap.size();
    155         for (int i = 0; i < numListeners; i++) {
    156             FingerprintGestureCallback callback = handlerMap.keyAt(i);
    157             Handler handler = handlerMap.valueAt(i);
    158             if (handler != null) {
    159                 handler.post(() -> callback.onGestureDetected(gesture));
    160             } else {
    161                 callback.onGestureDetected(gesture);
    162             }
    163         }
    164     }
    165 
    166     /**
    167      * Class that is called back when fingerprint gestures are being used for accessibility.
    168      */
    169     public abstract static class FingerprintGestureCallback {
    170         /**
    171          * Called when the fingerprint sensor's gesture detection becomes available or unavailable.
    172          *
    173          * @param available Whether or not the sensor's gesture detection is now available.
    174          */
    175         public void onGestureDetectionAvailabilityChanged(boolean available) {}
    176 
    177         /**
    178          * Called when the fingerprint sensor detects gestures.
    179          *
    180          * @param gesture The id of the gesture that was detected. For example,
    181          * {@link #FINGERPRINT_GESTURE_SWIPE_RIGHT}.
    182          */
    183         public void onGestureDetected(int gesture) {}
    184     }
    185 }
    186