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 com.android.server.accessibility; 18 19 import android.accessibilityservice.FingerprintGestureController; 20 import android.content.res.Resources; 21 import android.hardware.fingerprint.IFingerprintClientActiveCallback; 22 import android.hardware.fingerprint.IFingerprintService; 23 import android.os.Binder; 24 import android.os.Handler; 25 import android.os.Message; 26 import android.os.RemoteException; 27 import android.util.Slog; 28 import android.view.KeyEvent; 29 30 import java.util.ArrayList; 31 import java.util.List; 32 33 /** 34 * Encapsulate fingerprint gesture logic 35 */ 36 public class FingerprintGestureDispatcher extends IFingerprintClientActiveCallback.Stub 37 implements Handler.Callback{ 38 private static final int MSG_REGISTER = 1; 39 private static final int MSG_UNREGISTER = 2; 40 private static final String LOG_TAG = "FingerprintGestureDispatcher"; 41 42 private final List<FingerprintGestureClient> mCapturingClients = new ArrayList<>(0); 43 private final Object mLock; 44 private final IFingerprintService mFingerprintService; 45 private final Handler mHandler; 46 private final boolean mHardwareSupportsGestures; 47 48 // This field is ground truth for whether or not we are registered. Only write to it in handler. 49 private boolean mRegisteredReadOnlyExceptInHandler; 50 51 /** 52 * @param fingerprintService The system's fingerprint service 53 * @param lock A lock to use when managing internal state 54 */ FingerprintGestureDispatcher(IFingerprintService fingerprintService, Resources resources, Object lock)55 public FingerprintGestureDispatcher(IFingerprintService fingerprintService, 56 Resources resources, Object lock) { 57 mFingerprintService = fingerprintService; 58 mHardwareSupportsGestures = resources.getBoolean( 59 com.android.internal.R.bool.config_fingerprintSupportsGestures); 60 mLock = lock; 61 mHandler = new Handler(this); 62 } 63 64 /** 65 * @param fingerprintService The system's fingerprint service 66 * @param lock A lock to use when managing internal state 67 * @param handler A handler to use internally. Used for testing. 68 */ FingerprintGestureDispatcher(IFingerprintService fingerprintService, Resources resources, Object lock, Handler handler)69 public FingerprintGestureDispatcher(IFingerprintService fingerprintService, 70 Resources resources, Object lock, Handler handler) { 71 mFingerprintService = fingerprintService; 72 mHardwareSupportsGestures = resources.getBoolean( 73 com.android.internal.R.bool.config_fingerprintSupportsGestures); 74 mLock = lock; 75 mHandler = handler; 76 } 77 78 /** 79 * Update the list of clients that are interested in fingerprint gestures. 80 * 81 * @param clientList The list of potential clients. 82 */ updateClientList(List<? extends FingerprintGestureClient> clientList)83 public void updateClientList(List<? extends FingerprintGestureClient> clientList) { 84 if (!mHardwareSupportsGestures) return; 85 86 synchronized (mLock) { 87 mCapturingClients.clear(); 88 for (int i = 0; i < clientList.size(); i++) { 89 FingerprintGestureClient client = clientList.get(i); 90 if (client.isCapturingFingerprintGestures()) { 91 mCapturingClients.add(client); 92 } 93 } 94 if (mCapturingClients.isEmpty()) { 95 if (mRegisteredReadOnlyExceptInHandler) { 96 mHandler.obtainMessage(MSG_UNREGISTER).sendToTarget(); 97 } 98 } else { 99 if(!mRegisteredReadOnlyExceptInHandler) { 100 mHandler.obtainMessage(MSG_REGISTER).sendToTarget(); 101 } 102 } 103 } 104 } 105 106 @Override onClientActiveChanged(boolean nonGestureFingerprintClientActive)107 public void onClientActiveChanged(boolean nonGestureFingerprintClientActive) { 108 if (!mHardwareSupportsGestures) return; 109 110 synchronized (mLock) { 111 for (int i = 0; i < mCapturingClients.size(); i++) { 112 mCapturingClients.get(i).onFingerprintGestureDetectionActiveChanged( 113 !nonGestureFingerprintClientActive); 114 } 115 } 116 } 117 isFingerprintGestureDetectionAvailable()118 public boolean isFingerprintGestureDetectionAvailable() { 119 if (!mHardwareSupportsGestures) return false; 120 121 long identity = Binder.clearCallingIdentity(); 122 try { 123 return !mFingerprintService.isClientActive(); 124 } catch (RemoteException re) { 125 return false; 126 } finally { 127 Binder.restoreCallingIdentity(identity); 128 } 129 } 130 131 /** 132 * Called when the fingerprint sensor detects a gesture 133 * 134 * @param fingerprintKeyCode 135 * @return {@code true} if the gesture is consumed. {@code false} otherwise. 136 */ onFingerprintGesture(int fingerprintKeyCode)137 public boolean onFingerprintGesture(int fingerprintKeyCode) { 138 int idForFingerprintGestureManager; 139 140 final List<FingerprintGestureClient> clientList; 141 synchronized (mLock) { 142 if (mCapturingClients.isEmpty()) { 143 return false; 144 } 145 switch (fingerprintKeyCode) { 146 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_UP: 147 idForFingerprintGestureManager = 148 FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_UP; 149 break; 150 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_DOWN: 151 idForFingerprintGestureManager = 152 FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_DOWN; 153 break; 154 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_RIGHT: 155 idForFingerprintGestureManager = 156 FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_RIGHT; 157 break; 158 case KeyEvent.KEYCODE_SYSTEM_NAVIGATION_LEFT: 159 idForFingerprintGestureManager = 160 FingerprintGestureController.FINGERPRINT_GESTURE_SWIPE_LEFT; 161 break; 162 default: 163 return false; 164 } 165 clientList = new ArrayList<>(mCapturingClients); 166 } 167 for (int i = 0; i < clientList.size(); i++) { 168 clientList.get(i).onFingerprintGesture(idForFingerprintGestureManager); 169 } 170 return true; 171 } 172 173 @Override handleMessage(Message message)174 public boolean handleMessage(Message message) { 175 if (message.what == MSG_REGISTER) { 176 long identity = Binder.clearCallingIdentity(); 177 try { 178 mFingerprintService.addClientActiveCallback(this); 179 mRegisteredReadOnlyExceptInHandler = true; 180 } catch (RemoteException re) { 181 Slog.e(LOG_TAG, "Failed to register for fingerprint activity callbacks"); 182 } finally { 183 Binder.restoreCallingIdentity(identity); 184 } 185 return false; 186 } else if (message.what == MSG_UNREGISTER) { 187 long identity = Binder.clearCallingIdentity(); 188 try { 189 mFingerprintService.removeClientActiveCallback(this); 190 } catch (RemoteException re) { 191 Slog.e(LOG_TAG, "Failed to unregister for fingerprint activity callbacks"); 192 } finally { 193 Binder.restoreCallingIdentity(identity); 194 } 195 mRegisteredReadOnlyExceptInHandler = false; 196 } else { 197 Slog.e(LOG_TAG, "Unknown message: " + message.what); 198 return false; 199 } 200 return true; 201 } 202 203 // Interface for potential clients. 204 public interface FingerprintGestureClient { 205 /** 206 * @return {@code true} if the client is capturing fingerprint gestures 207 */ isCapturingFingerprintGestures()208 boolean isCapturingFingerprintGestures(); 209 210 /** 211 * Callback when gesture detection becomes active or inactive. 212 * 213 * @param active {@code true} when detection is active 214 */ onFingerprintGestureDetectionActiveChanged(boolean active)215 void onFingerprintGestureDetectionActiveChanged(boolean active); 216 217 /** 218 * Callback when gesture is detected 219 * 220 * @param gesture The identifier for the gesture. For example, 221 * {@link FingerprintGestureController#FINGERPRINT_GESTURE_SWIPE_LEFT} 222 */ onFingerprintGesture(int gesture)223 void onFingerprintGesture(int gesture); 224 } 225 } 226