1/** 2 * Copyright (C) 2016 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 17package com.android.server.fingerprint; 18 19import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; 20import com.android.internal.logging.MetricsLogger; 21import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 22 23import android.content.Context; 24import android.hardware.fingerprint.Fingerprint; 25import android.hardware.fingerprint.FingerprintManager; 26import android.hardware.fingerprint.IFingerprintServiceReceiver; 27import android.os.IBinder; 28import android.os.RemoteException; 29import android.util.Slog; 30 31/** 32 * A class to keep track of the authentication state for a given client. 33 */ 34public abstract class AuthenticationClient extends ClientMonitor { 35 private long mOpId; 36 37 public abstract int handleFailedAttempt(); 38 public abstract void resetFailedAttempts(); 39 40 public static final int LOCKOUT_NONE = 0; 41 public static final int LOCKOUT_TIMED = 1; 42 public static final int LOCKOUT_PERMANENT = 2; 43 44 public AuthenticationClient(Context context, long halDeviceId, IBinder token, 45 IFingerprintServiceReceiver receiver, int targetUserId, int groupId, long opId, 46 boolean restricted, String owner) { 47 super(context, halDeviceId, token, receiver, targetUserId, groupId, restricted, owner); 48 mOpId = opId; 49 } 50 51 @Override 52 public boolean onAuthenticated(int fingerId, int groupId) { 53 boolean result = false; 54 boolean authenticated = fingerId != 0; 55 56 IFingerprintServiceReceiver receiver = getReceiver(); 57 if (receiver != null) { 58 try { 59 MetricsLogger.action(getContext(), MetricsEvent.ACTION_FINGERPRINT_AUTH, 60 authenticated); 61 if (!authenticated) { 62 receiver.onAuthenticationFailed(getHalDeviceId()); 63 } else { 64 if (DEBUG) { 65 Slog.v(TAG, "onAuthenticated(owner=" + getOwnerString() 66 + ", id=" + fingerId + ", gp=" + groupId + ")"); 67 } 68 Fingerprint fp = !getIsRestricted() 69 ? new Fingerprint("" /* TODO */, groupId, fingerId, getHalDeviceId()) 70 : null; 71 receiver.onAuthenticationSucceeded(getHalDeviceId(), fp, getTargetUserId()); 72 } 73 } catch (RemoteException e) { 74 Slog.w(TAG, "Failed to notify Authenticated:", e); 75 result = true; // client failed 76 } 77 } else { 78 result = true; // client not listening 79 } 80 if (!authenticated) { 81 if (receiver != null) { 82 vibrateError(); 83 } 84 // allow system-defined limit of number of attempts before giving up 85 int lockoutMode = handleFailedAttempt(); 86 if (lockoutMode != LOCKOUT_NONE) { 87 try { 88 Slog.w(TAG, "Forcing lockout (fp driver code should do this!), mode(" + 89 lockoutMode + ")"); 90 stop(false); 91 int errorCode = lockoutMode == LOCKOUT_TIMED ? 92 FingerprintManager.FINGERPRINT_ERROR_LOCKOUT : 93 FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT; 94 receiver.onError(getHalDeviceId(), errorCode, 0 /* vendorCode */); 95 } catch (RemoteException e) { 96 Slog.w(TAG, "Failed to notify lockout:", e); 97 } 98 } 99 result |= lockoutMode != LOCKOUT_NONE; // in a lockout mode 100 } else { 101 if (receiver != null) { 102 vibrateSuccess(); 103 } 104 result |= true; // we have a valid fingerprint, done 105 resetFailedAttempts(); 106 } 107 return result; 108 } 109 110 /** 111 * Start authentication 112 */ 113 @Override 114 public int start() { 115 IBiometricsFingerprint daemon = getFingerprintDaemon(); 116 if (daemon == null) { 117 Slog.w(TAG, "start authentication: no fingerprint HAL!"); 118 return ERROR_ESRCH; 119 } 120 try { 121 final int result = daemon.authenticate(mOpId, getGroupId()); 122 if (result != 0) { 123 Slog.w(TAG, "startAuthentication failed, result=" + result); 124 MetricsLogger.histogram(getContext(), "fingeprintd_auth_start_error", result); 125 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */); 126 return result; 127 } 128 if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is authenticating..."); 129 } catch (RemoteException e) { 130 Slog.e(TAG, "startAuthentication failed", e); 131 return ERROR_ESRCH; 132 } 133 return 0; // success 134 } 135 136 @Override 137 public int stop(boolean initiatedByClient) { 138 if (mAlreadyCancelled) { 139 Slog.w(TAG, "stopAuthentication: already cancelled!"); 140 return 0; 141 } 142 IBiometricsFingerprint daemon = getFingerprintDaemon(); 143 if (daemon == null) { 144 Slog.w(TAG, "stopAuthentication: no fingerprint HAL!"); 145 return ERROR_ESRCH; 146 } 147 try { 148 final int result = daemon.cancel(); 149 if (result != 0) { 150 Slog.w(TAG, "stopAuthentication failed, result=" + result); 151 return result; 152 } 153 if (DEBUG) Slog.w(TAG, "client " + getOwnerString() + " is no longer authenticating"); 154 } catch (RemoteException e) { 155 Slog.e(TAG, "stopAuthentication failed", e); 156 return ERROR_ESRCH; 157 } 158 mAlreadyCancelled = true; 159 return 0; // success 160 } 161 162 @Override 163 public boolean onEnrollResult(int fingerId, int groupId, int remaining) { 164 if (DEBUG) Slog.w(TAG, "onEnrollResult() called for authenticate!"); 165 return true; // Invalid for Authenticate 166 } 167 168 @Override 169 public boolean onRemoved(int fingerId, int groupId, int remaining) { 170 if (DEBUG) Slog.w(TAG, "onRemoved() called for authenticate!"); 171 return true; // Invalid for Authenticate 172 } 173 174 @Override 175 public boolean onEnumerationResult(int fingerId, int groupId, int remaining) { 176 if (DEBUG) Slog.w(TAG, "onEnumerationResult() called for authenticate!"); 177 return true; // Invalid for Authenticate 178 } 179} 180