blob: 370e569f2598e30e2c8e3f2f4c25a7a9e811113b [file] [log] [blame]
Jim Millercb2ce6f2016-04-13 20:28:18 -07001/**
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
Jim Miller40e46452016-12-16 18:38:53 -080019import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
Jim Millercb2ce6f2016-04-13 20:28:18 -070020import com.android.internal.logging.MetricsLogger;
Tamas Berghammer383db5eb2016-06-22 15:21:38 +010021import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Jim Millercb2ce6f2016-04-13 20:28:18 -070022
23import android.content.Context;
24import android.hardware.fingerprint.Fingerprint;
25import android.hardware.fingerprint.FingerprintManager;
Jim Millercb2ce6f2016-04-13 20:28:18 -070026import android.hardware.fingerprint.IFingerprintServiceReceiver;
27import android.os.IBinder;
28import android.os.RemoteException;
Jim Millercb2ce6f2016-04-13 20:28:18 -070029import 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
Kevin Chyndf9d33e2017-05-03 21:40:12 -070037 public abstract int handleFailedAttempt();
Jim Millercb2ce6f2016-04-13 20:28:18 -070038 public abstract void resetFailedAttempts();
Kevin Chyndf9d33e2017-05-03 21:40:12 -070039
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
Jim Millercb2ce6f2016-04-13 20:28:18 -070044 public AuthenticationClient(Context context, long halDeviceId, IBinder token,
Jim Miller837fa7e2016-08-08 20:16:22 -070045 IFingerprintServiceReceiver receiver, int targetUserId, int groupId, long opId,
Jim Millercb2ce6f2016-04-13 20:28:18 -070046 boolean restricted, String owner) {
Jim Miller837fa7e2016-08-08 20:16:22 -070047 super(context, halDeviceId, token, receiver, targetUserId, groupId, restricted, owner);
Jim Millercb2ce6f2016-04-13 20:28:18 -070048 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;
Jim Miller837fa7e2016-08-08 20:16:22 -070071 receiver.onAuthenticationSucceeded(getHalDeviceId(), fp, getTargetUserId());
Jim Millercb2ce6f2016-04-13 20:28:18 -070072 }
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 }
Jim Millerd1974862016-05-03 18:35:18 -070080 if (!authenticated) {
Jim Millercb2ce6f2016-04-13 20:28:18 -070081 if (receiver != null) {
Michael Wright6726fd52017-06-27 00:41:45 +010082 vibrateError();
Jim Millercb2ce6f2016-04-13 20:28:18 -070083 }
84 // allow system-defined limit of number of attempts before giving up
Kevin Chyndf9d33e2017-05-03 21:40:12 -070085 int lockoutMode = handleFailedAttempt();
86 if (lockoutMode != LOCKOUT_NONE) {
Jim Millerd1974862016-05-03 18:35:18 -070087 try {
Kevin Chyndf9d33e2017-05-03 21:40:12 -070088 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 */);
Jim Millerd1974862016-05-03 18:35:18 -070095 } catch (RemoteException e) {
96 Slog.w(TAG, "Failed to notify lockout:", e);
97 }
98 }
Kevin Chyndf9d33e2017-05-03 21:40:12 -070099 result |= lockoutMode != LOCKOUT_NONE; // in a lockout mode
Jim Millercb2ce6f2016-04-13 20:28:18 -0700100 } else {
101 if (receiver != null) {
Michael Wright6726fd52017-06-27 00:41:45 +0100102 vibrateSuccess();
Jim Millercb2ce6f2016-04-13 20:28:18 -0700103 }
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() {
Jim Miller40e46452016-12-16 18:38:53 -0800115 IBiometricsFingerprint daemon = getFingerprintDaemon();
Jim Millercb2ce6f2016-04-13 20:28:18 -0700116 if (daemon == null) {
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700117 Slog.w(TAG, "start authentication: no fingerprint HAL!");
Jim Millercb2ce6f2016-04-13 20:28:18 -0700118 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);
Jim Millerc57c8d92016-09-30 17:17:59 -0700124 MetricsLogger.histogram(getContext(), "fingeprintd_auth_start_error", result);
Jim Miller40e46452016-12-16 18:38:53 -0800125 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700126 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) {
Kevin Chyn625a0142017-04-10 14:53:59 -0700138 if (mAlreadyCancelled) {
139 Slog.w(TAG, "stopAuthentication: already cancelled!");
140 return 0;
141 }
Jim Miller40e46452016-12-16 18:38:53 -0800142 IBiometricsFingerprint daemon = getFingerprintDaemon();
Jim Millercb2ce6f2016-04-13 20:28:18 -0700143 if (daemon == null) {
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700144 Slog.w(TAG, "stopAuthentication: no fingerprint HAL!");
Jim Millercb2ce6f2016-04-13 20:28:18 -0700145 return ERROR_ESRCH;
146 }
147 try {
Jim Miller40e46452016-12-16 18:38:53 -0800148 final int result = daemon.cancel();
Jim Millercb2ce6f2016-04-13 20:28:18 -0700149 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 }
Kevin Chyn625a0142017-04-10 14:53:59 -0700158 mAlreadyCancelled = true;
Jim Millercb2ce6f2016-04-13 20:28:18 -0700159 return 0; // success
160 }
161
162 @Override
Jim Miller40e46452016-12-16 18:38:53 -0800163 public boolean onEnrollResult(int fingerId, int groupId, int remaining) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700164 if (DEBUG) Slog.w(TAG, "onEnrollResult() called for authenticate!");
165 return true; // Invalid for Authenticate
166 }
167
168 @Override
Jim Miller40e46452016-12-16 18:38:53 -0800169 public boolean onRemoved(int fingerId, int groupId, int remaining) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700170 if (DEBUG) Slog.w(TAG, "onRemoved() called for authenticate!");
171 return true; // Invalid for Authenticate
172 }
173
174 @Override
Jim Miller40e46452016-12-16 18:38:53 -0800175 public boolean onEnumerationResult(int fingerId, int groupId, int remaining) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700176 if (DEBUG) Slog.w(TAG, "onEnumerationResult() called for authenticate!");
177 return true; // Invalid for Authenticate
178 }
179}