Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2018 The Android Open Source Project |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 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 |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 14 | * limitations under the License |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 15 | */ |
| 16 | |
Kevin Chyn | 836f2cf | 2018-08-27 11:06:39 -0700 | [diff] [blame] | 17 | package com.android.server.biometrics; |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 18 | |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 19 | import android.content.Context; |
Kevin Chyn | a56dff7 | 2018-06-19 18:41:12 -0700 | [diff] [blame] | 20 | import android.hardware.biometrics.BiometricAuthenticator; |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 21 | import android.hardware.biometrics.BiometricConstants; |
Kevin Chyn | 7782d14 | 2019-01-18 12:51:33 -0800 | [diff] [blame] | 22 | import android.hardware.biometrics.BiometricsProtoEnums; |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 23 | import android.os.IBinder; |
| 24 | import android.os.RemoteException; |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 25 | import android.security.KeyStore; |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 26 | import android.util.Slog; |
| 27 | |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 28 | import java.util.ArrayList; |
| 29 | |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 30 | /** |
| 31 | * A class to keep track of the authentication state for a given client. |
| 32 | */ |
| 33 | public abstract class AuthenticationClient extends ClientMonitor { |
| 34 | private long mOpId; |
| 35 | |
Kevin Chyn | df9d33e | 2017-05-03 21:40:12 -0700 | [diff] [blame] | 36 | public abstract int handleFailedAttempt(); |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 37 | public void resetFailedAttempts() {} |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 38 | |
Kevin Chyn | df9d33e | 2017-05-03 21:40:12 -0700 | [diff] [blame] | 39 | public static final int LOCKOUT_NONE = 0; |
| 40 | public static final int LOCKOUT_TIMED = 1; |
| 41 | public static final int LOCKOUT_PERMANENT = 2; |
| 42 | |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 43 | private final boolean mRequireConfirmation; |
Kevin Chyn | aae4a15 | 2018-01-18 11:48:09 -0800 | [diff] [blame] | 44 | |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 45 | // We need to track this state since it's possible for applications to request for |
| 46 | // authentication while the device is already locked out. In that case, the client is created |
| 47 | // but not started yet. The user shouldn't receive the error haptics in this case. |
| 48 | private boolean mStarted; |
Kevin Chyn | 9bc1d49 | 2019-06-21 15:31:50 -0700 | [diff] [blame] | 49 | private long mStartTimeMs; |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 50 | |
Kevin Chyn | d4f43c2 | 2018-03-12 17:33:13 -0700 | [diff] [blame] | 51 | /** |
| 52 | * This method is called when authentication starts. |
| 53 | */ |
| 54 | public abstract void onStart(); |
| 55 | |
| 56 | /** |
Kevin Chyn | 5a2ff5d | 2018-08-29 19:07:30 -0700 | [diff] [blame] | 57 | * This method is called when a biometric is authenticated or authentication is stopped |
Kevin Chyn | d4f43c2 | 2018-03-12 17:33:13 -0700 | [diff] [blame] | 58 | * (cancelled by the user, or an error such as lockout has occurred). |
| 59 | */ |
| 60 | public abstract void onStop(); |
| 61 | |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 62 | /** |
| 63 | * @return true if the framework should handle lockout. |
| 64 | */ |
| 65 | public abstract boolean shouldFrameworkHandleLockout(); |
| 66 | |
Kevin Chyn | 0ce7085 | 2019-05-10 10:29:18 -0700 | [diff] [blame] | 67 | public abstract boolean wasUserDetected(); |
| 68 | |
Kevin Chyn | 4cc49f7 | 2019-04-24 13:53:35 -0700 | [diff] [blame] | 69 | public AuthenticationClient(Context context, Constants constants, |
Kevin Chyn | 355c6bf | 2018-09-20 22:14:19 -0700 | [diff] [blame] | 70 | BiometricServiceBase.DaemonWrapper daemon, long halDeviceId, IBinder token, |
| 71 | BiometricServiceBase.ServiceListener listener, int targetUserId, int groupId, long opId, |
Kevin Chyn | 87f257a | 2018-11-27 16:26:07 -0800 | [diff] [blame] | 72 | boolean restricted, String owner, int cookie, boolean requireConfirmation) { |
Kevin Chyn | 4cc49f7 | 2019-04-24 13:53:35 -0700 | [diff] [blame] | 73 | super(context, constants, daemon, halDeviceId, token, listener, targetUserId, groupId, |
Kevin Chyn | 87f257a | 2018-11-27 16:26:07 -0800 | [diff] [blame] | 74 | restricted, owner, cookie); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 75 | mOpId = opId; |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 76 | mRequireConfirmation = requireConfirmation; |
Kevin Chyn | aae4a15 | 2018-01-18 11:48:09 -0800 | [diff] [blame] | 77 | } |
| 78 | |
Kevin Chyn | 9bc1d49 | 2019-06-21 15:31:50 -0700 | [diff] [blame] | 79 | protected long getStartTimeMs() { |
| 80 | return mStartTimeMs; |
| 81 | } |
| 82 | |
Kevin Chyn | aae4a15 | 2018-01-18 11:48:09 -0800 | [diff] [blame] | 83 | @Override |
| 84 | public void binderDied() { |
| 85 | super.binderDied(); |
| 86 | // When the binder dies, we should stop the client. This probably belongs in |
| 87 | // ClientMonitor's binderDied(), but testing all the cases would be tricky. |
| 88 | // AuthenticationClient is the most user-visible case. |
| 89 | stop(false /* initiatedByClient */); |
| 90 | } |
| 91 | |
Kevin Chyn | 7782d14 | 2019-01-18 12:51:33 -0800 | [diff] [blame] | 92 | @Override |
| 93 | protected int statsAction() { |
| 94 | return BiometricsProtoEnums.ACTION_AUTHENTICATE; |
| 95 | } |
| 96 | |
Kevin Chyn | 3a018719 | 2018-10-08 15:40:05 -0700 | [diff] [blame] | 97 | public boolean isBiometricPrompt() { |
Kevin Chyn | 87f257a | 2018-11-27 16:26:07 -0800 | [diff] [blame] | 98 | return getCookie() != 0; |
Kevin Chyn | 3a018719 | 2018-10-08 15:40:05 -0700 | [diff] [blame] | 99 | } |
| 100 | |
Kevin Chyn | 87f257a | 2018-11-27 16:26:07 -0800 | [diff] [blame] | 101 | public boolean getRequireConfirmation() { |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 102 | return mRequireConfirmation; |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 103 | } |
| 104 | |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 105 | @Override |
Kevin Chyn | 7782d14 | 2019-01-18 12:51:33 -0800 | [diff] [blame] | 106 | protected boolean isCryptoOperation() { |
| 107 | return mOpId != 0; |
| 108 | } |
| 109 | |
| 110 | @Override |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 111 | public boolean onError(long deviceId, int error, int vendorCode) { |
| 112 | if (!shouldFrameworkHandleLockout()) { |
| 113 | switch (error) { |
Kevin Chyn | e674e85 | 2019-04-24 12:39:40 -0700 | [diff] [blame] | 114 | case BiometricConstants.BIOMETRIC_ERROR_TIMEOUT: |
Kevin Chyn | 0ce7085 | 2019-05-10 10:29:18 -0700 | [diff] [blame] | 115 | if (!wasUserDetected() && !isBiometricPrompt()) { |
| 116 | // No vibration if user was not detected on keyguard |
| 117 | break; |
| 118 | } |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 119 | case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT: |
| 120 | case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT: |
| 121 | if (mStarted) { |
| 122 | vibrateError(); |
| 123 | } |
| 124 | break; |
| 125 | default: |
| 126 | break; |
| 127 | } |
| 128 | } |
| 129 | return super.onError(deviceId, error, vendorCode); |
| 130 | } |
| 131 | |
| 132 | @Override |
Kevin Chyn | b528d69 | 2018-07-20 11:53:14 -0700 | [diff] [blame] | 133 | public boolean onAuthenticated(BiometricAuthenticator.Identifier identifier, |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 134 | boolean authenticated, ArrayList<Byte> token) { |
Kevin Chyn | 4858da4 | 2019-04-11 13:02:56 -0700 | [diff] [blame] | 135 | super.logOnAuthenticated(getContext(), authenticated, mRequireConfirmation, |
| 136 | getTargetUserId(), isBiometricPrompt()); |
Kevin Chyn | 7782d14 | 2019-01-18 12:51:33 -0800 | [diff] [blame] | 137 | |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 138 | final BiometricServiceBase.ServiceListener listener = getListener(); |
Kevin Chyn | 6cf54e8 | 2018-09-18 19:13:27 -0700 | [diff] [blame] | 139 | |
Kevin Chyn | 4cc49f7 | 2019-04-24 13:53:35 -0700 | [diff] [blame] | 140 | mMetricsLogger.action(mConstants.actionBiometricAuth(), authenticated); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 141 | boolean result = false; |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 142 | |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 143 | try { |
Kevin Chyn | d4ee8af | 2019-04-09 12:10:11 -0700 | [diff] [blame] | 144 | if (DEBUG) Slog.v(getLogTag(), "onAuthenticated(" + authenticated + ")" |
| 145 | + ", ID:" + identifier.getBiometricId() |
| 146 | + ", Owner: " + getOwnerString() |
| 147 | + ", isBP: " + isBiometricPrompt() |
| 148 | + ", listener: " + listener |
Kevin Chyn | 8d2694a | 2019-04-11 18:30:40 -0700 | [diff] [blame] | 149 | + ", requireConfirmation: " + mRequireConfirmation |
| 150 | + ", user: " + getTargetUserId()); |
Kevin Chyn | d4ee8af | 2019-04-09 12:10:11 -0700 | [diff] [blame] | 151 | |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 152 | if (authenticated) { |
| 153 | mAlreadyDone = true; |
Kevin Chyn | d4ee8af | 2019-04-09 12:10:11 -0700 | [diff] [blame] | 154 | |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 155 | if (listener != null) { |
| 156 | vibrateSuccess(); |
Kevin Chyn | aae4a15 | 2018-01-18 11:48:09 -0800 | [diff] [blame] | 157 | } |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 158 | result = true; |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 159 | if (shouldFrameworkHandleLockout()) { |
| 160 | resetFailedAttempts(); |
| 161 | } |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 162 | onStop(); |
Kevin Chyn | aae4a15 | 2018-01-18 11:48:09 -0800 | [diff] [blame] | 163 | |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 164 | final byte[] byteToken = new byte[token.size()]; |
| 165 | for (int i = 0; i < token.size(); i++) { |
| 166 | byteToken[i] = token.get(i); |
| 167 | } |
| 168 | if (isBiometricPrompt() && listener != null) { |
| 169 | // BiometricService will add the token to keystore |
| 170 | listener.onAuthenticationSucceededInternal(mRequireConfirmation, byteToken); |
| 171 | } else if (!isBiometricPrompt() && listener != null) { |
| 172 | KeyStore.getInstance().addAuthToken(byteToken); |
| 173 | try { |
| 174 | // Explicitly have if/else here to make it super obvious in case the code is |
| 175 | // touched in the future. |
| 176 | if (!getIsRestricted()) { |
| 177 | listener.onAuthenticationSucceeded( |
| 178 | getHalDeviceId(), identifier, getTargetUserId()); |
| 179 | } else { |
| 180 | listener.onAuthenticationSucceeded( |
| 181 | getHalDeviceId(), null, getTargetUserId()); |
| 182 | } |
| 183 | } catch (RemoteException e) { |
| 184 | Slog.e(getLogTag(), "Remote exception", e); |
| 185 | } |
| 186 | } else { |
| 187 | // Client not listening |
| 188 | Slog.w(getLogTag(), "Client not listening"); |
| 189 | result = true; |
| 190 | } |
| 191 | } else { |
| 192 | if (listener != null) { |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 193 | vibrateError(); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 194 | } |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 195 | |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 196 | // Allow system-defined limit of number of attempts before giving up |
| 197 | final int lockoutMode = handleFailedAttempt(); |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 198 | if (lockoutMode != LOCKOUT_NONE && shouldFrameworkHandleLockout()) { |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 199 | Slog.w(getLogTag(), "Forcing lockout (driver code should do this!), mode(" |
| 200 | + lockoutMode + ")"); |
| 201 | stop(false); |
| 202 | final int errorCode = lockoutMode == LOCKOUT_TIMED |
| 203 | ? BiometricConstants.BIOMETRIC_ERROR_LOCKOUT |
| 204 | : BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; |
Kevin Chyn | 7782d14 | 2019-01-18 12:51:33 -0800 | [diff] [blame] | 205 | onError(getHalDeviceId(), errorCode, 0 /* vendorCode */); |
Kevin Chyn | 23289ef | 2018-11-28 16:32:36 -0800 | [diff] [blame] | 206 | } else { |
| 207 | // Don't send onAuthenticationFailed if we're in lockout, it causes a |
| 208 | // janky UI on Keyguard/BiometricPrompt since "authentication failed" |
| 209 | // will show briefly and be replaced by "device locked out" message. |
| 210 | if (listener != null) { |
| 211 | if (isBiometricPrompt()) { |
| 212 | listener.onAuthenticationFailedInternal(getCookie(), |
| 213 | getRequireConfirmation()); |
| 214 | } else { |
| 215 | listener.onAuthenticationFailed(getHalDeviceId()); |
| 216 | } |
| 217 | } |
Jim Miller | d197486 | 2016-05-03 18:35:18 -0700 | [diff] [blame] | 218 | } |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 219 | result = lockoutMode != LOCKOUT_NONE; // in a lockout mode |
Jim Miller | d197486 | 2016-05-03 18:35:18 -0700 | [diff] [blame] | 220 | } |
Kevin Chyn | e92cdae | 2018-11-21 16:35:04 -0800 | [diff] [blame] | 221 | } catch (RemoteException e) { |
| 222 | Slog.e(getLogTag(), "Remote exception", e); |
| 223 | result = true; |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 224 | } |
| 225 | return result; |
| 226 | } |
| 227 | |
| 228 | /** |
| 229 | * Start authentication |
| 230 | */ |
| 231 | @Override |
| 232 | public int start() { |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 233 | mStarted = true; |
Kevin Chyn | d4f43c2 | 2018-03-12 17:33:13 -0700 | [diff] [blame] | 234 | onStart(); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 235 | try { |
Kevin Chyn | 9bc1d49 | 2019-06-21 15:31:50 -0700 | [diff] [blame] | 236 | mStartTimeMs = System.currentTimeMillis(); |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 237 | final int result = getDaemonWrapper().authenticate(mOpId, getGroupId()); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 238 | if (result != 0) { |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 239 | Slog.w(getLogTag(), "startAuthentication failed, result=" + result); |
Kevin Chyn | 4cc49f7 | 2019-04-24 13:53:35 -0700 | [diff] [blame] | 240 | mMetricsLogger.histogram(mConstants.tagAuthStartError(), result); |
Kevin Chyn | a56dff7 | 2018-06-19 18:41:12 -0700 | [diff] [blame] | 241 | onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, |
| 242 | 0 /* vendorCode */); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 243 | return result; |
| 244 | } |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 245 | if (DEBUG) Slog.w(getLogTag(), "client " + getOwnerString() + " is authenticating..."); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 246 | } catch (RemoteException e) { |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 247 | Slog.e(getLogTag(), "startAuthentication failed", e); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 248 | return ERROR_ESRCH; |
| 249 | } |
| 250 | return 0; // success |
| 251 | } |
| 252 | |
| 253 | @Override |
| 254 | public int stop(boolean initiatedByClient) { |
Kevin Chyn | 625a014 | 2017-04-10 14:53:59 -0700 | [diff] [blame] | 255 | if (mAlreadyCancelled) { |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 256 | Slog.w(getLogTag(), "stopAuthentication: already cancelled!"); |
Kevin Chyn | 625a014 | 2017-04-10 14:53:59 -0700 | [diff] [blame] | 257 | return 0; |
| 258 | } |
Kevin Chyn | aae4a15 | 2018-01-18 11:48:09 -0800 | [diff] [blame] | 259 | |
Kevin Chyn | a38653c | 2019-02-11 17:46:21 -0800 | [diff] [blame] | 260 | mStarted = false; |
| 261 | |
Kevin Chyn | d4f43c2 | 2018-03-12 17:33:13 -0700 | [diff] [blame] | 262 | onStop(); |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 263 | |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 264 | try { |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 265 | final int result = getDaemonWrapper().cancel(); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 266 | if (result != 0) { |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 267 | Slog.w(getLogTag(), "stopAuthentication failed, result=" + result); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 268 | return result; |
| 269 | } |
Kevin Chyn | 5a2ff5d | 2018-08-29 19:07:30 -0700 | [diff] [blame] | 270 | if (DEBUG) Slog.w(getLogTag(), "client " + getOwnerString() + |
| 271 | " is no longer authenticating"); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 272 | } catch (RemoteException e) { |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 273 | Slog.e(getLogTag(), "stopAuthentication failed", e); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 274 | return ERROR_ESRCH; |
| 275 | } |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 276 | |
Kevin Chyn | 625a014 | 2017-04-10 14:53:59 -0700 | [diff] [blame] | 277 | mAlreadyCancelled = true; |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 278 | return 0; // success |
| 279 | } |
| 280 | |
| 281 | @Override |
Kevin Chyn | a56dff7 | 2018-06-19 18:41:12 -0700 | [diff] [blame] | 282 | public boolean onEnrollResult(BiometricAuthenticator.Identifier identifier, |
| 283 | int remaining) { |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 284 | if (DEBUG) Slog.w(getLogTag(), "onEnrollResult() called for authenticate!"); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 285 | return true; // Invalid for Authenticate |
| 286 | } |
| 287 | |
| 288 | @Override |
Kevin Chyn | a56dff7 | 2018-06-19 18:41:12 -0700 | [diff] [blame] | 289 | public boolean onRemoved(BiometricAuthenticator.Identifier identifier, int remaining) { |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 290 | if (DEBUG) Slog.w(getLogTag(), "onRemoved() called for authenticate!"); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 291 | return true; // Invalid for Authenticate |
| 292 | } |
| 293 | |
| 294 | @Override |
Kevin Chyn | a56dff7 | 2018-06-19 18:41:12 -0700 | [diff] [blame] | 295 | public boolean onEnumerationResult(BiometricAuthenticator.Identifier identifier, |
| 296 | int remaining) { |
Kevin Chyn | 037c4d5 | 2018-06-11 19:17:32 -0700 | [diff] [blame] | 297 | if (DEBUG) Slog.w(getLogTag(), "onEnumerationResult() called for authenticate!"); |
Jim Miller | cb2ce6f | 2016-04-13 20:28:18 -0700 | [diff] [blame] | 298 | return true; // Invalid for Authenticate |
| 299 | } |
| 300 | } |