blob: 271ec79074e8401e68111f068ca02e174c653a70 [file] [log] [blame]
Jim Miller08fa40c2014-04-29 18:18:47 -07001/**
2 * Copyright (C) 2014 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
Jim Millerebbf2052015-03-31 17:24:34 -070017package android.hardware.fingerprint;
Jim Miller08fa40c2014-04-29 18:18:47 -070018
Jim Millerce7eb6d2015-04-03 19:29:13 -070019import android.annotation.NonNull;
20import android.annotation.Nullable;
Jim Millerf501b582015-06-03 16:36:31 -070021import android.annotation.RequiresPermission;
Jim Miller08fa40c2014-04-29 18:18:47 -070022import android.app.ActivityManagerNative;
Jim Miller08fa40c2014-04-29 18:18:47 -070023import android.content.Context;
Jim Millera75961472014-06-06 15:00:49 -070024import android.os.Binder;
Jim Miller9f0753f2015-03-23 23:59:22 -070025import android.os.CancellationSignal;
Jim Millerce7eb6d2015-04-03 19:29:13 -070026import android.os.CancellationSignal.OnCancelListener;
Jim Miller08fa40c2014-04-29 18:18:47 -070027import android.os.Handler;
28import android.os.IBinder;
Jim Millerf501b582015-06-03 16:36:31 -070029import android.os.Looper;
Jorim Jaggi5e354222015-09-04 14:17:58 -070030import android.os.PowerManager;
Jim Miller08fa40c2014-04-29 18:18:47 -070031import android.os.RemoteException;
32import android.os.UserHandle;
Alex Klyubindcdaf872015-05-13 15:57:09 -070033import android.security.keystore.AndroidKeyStoreProvider;
Jim Miller08fa40c2014-04-29 18:18:47 -070034import android.util.Log;
Jim Millera75961472014-06-06 15:00:49 -070035import android.util.Slog;
Jim Miller08fa40c2014-04-29 18:18:47 -070036
Jim Miller9f0753f2015-03-23 23:59:22 -070037import java.security.Signature;
Jim Millerba67aee2015-02-20 16:21:26 -080038import java.util.List;
39
Jim Miller9f0753f2015-03-23 23:59:22 -070040import javax.crypto.Cipher;
Jim Millerb62dc822015-04-28 20:05:53 -070041import javax.crypto.Mac;
Jim Miller9f0753f2015-03-23 23:59:22 -070042
Clara Bayarri33fd3cf2016-02-19 16:54:49 +000043import static android.Manifest.permission.INTERACT_ACROSS_USERS;
Jim Millerf501b582015-06-03 16:36:31 -070044import static android.Manifest.permission.USE_FINGERPRINT;
45import static android.Manifest.permission.MANAGE_FINGERPRINT;
46
Jim Miller08fa40c2014-04-29 18:18:47 -070047/**
48 * A class that coordinates access to the fingerprint hardware.
Jim Millerce7eb6d2015-04-03 19:29:13 -070049 * <p>
50 * Use {@link android.content.Context#getSystemService(java.lang.String)}
51 * with argument {@link android.content.Context#FINGERPRINT_SERVICE} to get
52 * an instance of this class.
Jim Miller08fa40c2014-04-29 18:18:47 -070053 */
54
55public class FingerprintManager {
56 private static final String TAG = "FingerprintManager";
Jim Millerd08c2ac2014-05-14 16:30:38 -070057 private static final boolean DEBUG = true;
Jim Miller08fa40c2014-04-29 18:18:47 -070058 private static final int MSG_ENROLL_RESULT = 100;
Jim Millera75961472014-06-06 15:00:49 -070059 private static final int MSG_ACQUIRED = 101;
Jim Millerf501b582015-06-03 16:36:31 -070060 private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
61 private static final int MSG_AUTHENTICATION_FAILED = 103;
62 private static final int MSG_ERROR = 104;
63 private static final int MSG_REMOVED = 105;
Jim Miller08fa40c2014-04-29 18:18:47 -070064
Jim Millerce7eb6d2015-04-03 19:29:13 -070065 //
66 // Error messages from fingerprint hardware during initilization, enrollment, authentication or
67 // removal. Must agree with the list in fingerprint.h
68 //
Jim Miller08fa40c2014-04-29 18:18:47 -070069
Jim Millerce7eb6d2015-04-03 19:29:13 -070070 /**
71 * The hardware is unavailable. Try again later.
72 */
Jim Miller08fa40c2014-04-29 18:18:47 -070073 public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
Jim Millerce7eb6d2015-04-03 19:29:13 -070074
75 /**
76 * Error state returned when the sensor was unable to process the current image.
77 */
Jim Millera75961472014-06-06 15:00:49 -070078 public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2;
Jim Millerce7eb6d2015-04-03 19:29:13 -070079
80 /**
81 * Error state returned when the current request has been running too long. This is intended to
82 * prevent programs from waiting for the fingerprint sensor indefinitely. The timeout is
83 * platform and sensor-specific, but is generally on the order of 30 seconds.
84 */
Jim Miller08fa40c2014-04-29 18:18:47 -070085 public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
Jim Millerce7eb6d2015-04-03 19:29:13 -070086
87 /**
88 * Error state returned for operations like enrollment; the operation cannot be completed
89 * because there's not enough storage remaining to complete the operation.
90 */
Jim Miller08fa40c2014-04-29 18:18:47 -070091 public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
Jim Millerce7eb6d2015-04-03 19:29:13 -070092
93 /**
94 * The operation was canceled because the fingerprint sensor is unavailable. For example,
95 * this may happen when the user is switched, the device is locked or another pending operation
96 * prevents or disables it.
97 */
Jim Miller9f0753f2015-03-23 23:59:22 -070098 public static final int FINGERPRINT_ERROR_CANCELED = 5;
Jim Millerce7eb6d2015-04-03 19:29:13 -070099
100 /**
101 * The {@link FingerprintManager#remove(Fingerprint, RemovalCallback)} call failed. Typically
102 * this will happen when the provided fingerprint id was incorrect.
103 *
104 * @hide
105 */
106 public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6;
107
Jim Millerfe6439f2015-04-11 18:07:57 -0700108 /**
109 * The operation was canceled because the API is locked out due to too many attempts.
110 */
111 public static final int FINGERPRINT_ERROR_LOCKOUT = 7;
112
Jim Millerce7eb6d2015-04-03 19:29:13 -0700113 /**
114 * Hardware vendors may extend this list if there are conditions that do not fall under one of
115 * the above categories. Vendors are responsible for providing error strings for these errors.
Jim Millerf501b582015-06-03 16:36:31 -0700116 * @hide
Jim Millerce7eb6d2015-04-03 19:29:13 -0700117 */
Jim Miller9f0753f2015-03-23 23:59:22 -0700118 public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000;
Jim Miller08fa40c2014-04-29 18:18:47 -0700119
Jim Millerce7eb6d2015-04-03 19:29:13 -0700120 //
121 // Image acquisition messages. Must agree with those in fingerprint.h
122 //
123
124 /**
125 * The image acquired was good.
126 */
Jim Millera75961472014-06-06 15:00:49 -0700127 public static final int FINGERPRINT_ACQUIRED_GOOD = 0;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700128
129 /**
130 * Only a partial fingerprint image was detected. During enrollment, the user should be
131 * informed on what needs to happen to resolve this problem, e.g. "press firmly on sensor."
132 */
Jim Millera75961472014-06-06 15:00:49 -0700133 public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700134
135 /**
136 * The fingerprint image was too noisy to process due to a detected condition (i.e. dry skin) or
137 * a possibly dirty sensor (See {@link #FINGERPRINT_ACQUIRED_IMAGER_DIRTY}).
138 */
Jim Millera75961472014-06-06 15:00:49 -0700139 public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700140
141 /**
142 * The fingerprint image was too noisy due to suspected or detected dirt on the sensor.
143 * For example, it's reasonable return this after multiple
144 * {@link #FINGERPRINT_ACQUIRED_INSUFFICIENT} or actual detection of dirt on the sensor
145 * (stuck pixels, swaths, etc.). The user is expected to take action to clean the sensor
146 * when this is returned.
147 */
Jim Miller9f0753f2015-03-23 23:59:22 -0700148 public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700149
150 /**
151 * The fingerprint image was unreadable due to lack of motion. This is most appropriate for
152 * linear array sensors that require a swipe motion.
153 */
Jim Miller9f0753f2015-03-23 23:59:22 -0700154 public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700155
156 /**
157 * The fingerprint image was incomplete due to quick motion. While mostly appropriate for
158 * linear array sensors, this could also happen if the finger was moved during acquisition.
159 * The user should be asked to move the finger slower (linear) or leave the finger on the sensor
160 * longer.
161 */
Jim Miller9f0753f2015-03-23 23:59:22 -0700162 public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700163
164 /**
165 * Hardware vendors may extend this list if there are conditions that do not fall under one of
166 * the above categories. Vendors are responsible for providing error strings for these errors.
Jim Millerf501b582015-06-03 16:36:31 -0700167 * @hide
Jim Millerce7eb6d2015-04-03 19:29:13 -0700168 */
Jim Miller9f0753f2015-03-23 23:59:22 -0700169 public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
Jim Millera75961472014-06-06 15:00:49 -0700170
Jim Miller08fa40c2014-04-29 18:18:47 -0700171 private IFingerprintService mService;
Jim Millerd08c2ac2014-05-14 16:30:38 -0700172 private Context mContext;
Jim Millera75961472014-06-06 15:00:49 -0700173 private IBinder mToken = new Binder();
Jim Miller9f0753f2015-03-23 23:59:22 -0700174 private AuthenticationCallback mAuthenticationCallback;
175 private EnrollmentCallback mEnrollmentCallback;
176 private RemovalCallback mRemovalCallback;
177 private CryptoObject mCryptoObject;
178 private Fingerprint mRemovalFingerprint;
Jim Millerf501b582015-06-03 16:36:31 -0700179 private Handler mHandler;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700180
181 private class OnEnrollCancelListener implements OnCancelListener {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700182 @Override
183 public void onCancel() {
Jim Millerfe6439f2015-04-11 18:07:57 -0700184 cancelEnrollment();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700185 }
186 }
187
188 private class OnAuthenticationCancelListener implements OnCancelListener {
189 private CryptoObject mCrypto;
190
191 public OnAuthenticationCancelListener(CryptoObject crypto) {
192 mCrypto = crypto;
193 }
194
195 @Override
196 public void onCancel() {
197 cancelAuthentication(mCrypto);
198 }
199 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700200
201 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700202 * A wrapper class for the crypto objects supported by FingerprintManager. Currently the
Jim Millerb62dc822015-04-28 20:05:53 -0700203 * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
Jim Miller9f0753f2015-03-23 23:59:22 -0700204 */
Jim Millerf501b582015-06-03 16:36:31 -0700205 public static final class CryptoObject {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700206
Jim Millerb62dc822015-04-28 20:05:53 -0700207 public CryptoObject(@NonNull Signature signature) {
Jim Millerf501b582015-06-03 16:36:31 -0700208 mCrypto = signature;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700209 }
210
Jim Millerb62dc822015-04-28 20:05:53 -0700211 public CryptoObject(@NonNull Cipher cipher) {
Jim Millerf501b582015-06-03 16:36:31 -0700212 mCrypto = cipher;
Jim Millerb62dc822015-04-28 20:05:53 -0700213 }
214
215 public CryptoObject(@NonNull Mac mac) {
Jim Millerf501b582015-06-03 16:36:31 -0700216 mCrypto = mac;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700217 }
218
219 /**
220 * Get {@link Signature} object.
221 * @return {@link Signature} object or null if this doesn't contain one.
222 */
Jim Millerf501b582015-06-03 16:36:31 -0700223 public Signature getSignature() {
224 return mCrypto instanceof Signature ? (Signature) mCrypto : null;
225 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700226
227 /**
228 * Get {@link Cipher} object.
229 * @return {@link Cipher} object or null if this doesn't contain one.
230 */
Jim Millerf501b582015-06-03 16:36:31 -0700231 public Cipher getCipher() {
232 return mCrypto instanceof Cipher ? (Cipher) mCrypto : null;
233 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700234
235 /**
Jim Millerb62dc822015-04-28 20:05:53 -0700236 * Get {@link Mac} object.
237 * @return {@link Mac} object or null if this doesn't contain one.
238 */
Jim Millerf501b582015-06-03 16:36:31 -0700239 public Mac getMac() {
240 return mCrypto instanceof Mac ? (Mac) mCrypto : null;
241 }
Jim Millerb62dc822015-04-28 20:05:53 -0700242
243 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700244 * @hide
245 * @return the opId associated with this object or 0 if none
246 */
247 public long getOpId() {
Jim Millerf501b582015-06-03 16:36:31 -0700248 return mCrypto != null ?
249 AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700250 }
251
Jim Millerf501b582015-06-03 16:36:31 -0700252 private final Object mCrypto;
Jim Miller9f0753f2015-03-23 23:59:22 -0700253 };
254
255 /**
256 * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
Jim Millerf501b582015-06-03 16:36:31 -0700257 * CancellationSignal, int, AuthenticationCallback, Handler)}.
Jim Miller9f0753f2015-03-23 23:59:22 -0700258 */
Jim Miller748bc362015-07-08 19:02:28 -0700259 public static class AuthenticationResult {
Jim Miller9f0753f2015-03-23 23:59:22 -0700260 private Fingerprint mFingerprint;
261 private CryptoObject mCryptoObject;
262
Jim Millerf501b582015-06-03 16:36:31 -0700263 /**
264 * Authentication result
265 *
266 * @param crypto the crypto object
267 * @param fingerprint the recognized fingerprint data, if allowed.
268 * @hide
269 */
Jim Miller9f0753f2015-03-23 23:59:22 -0700270 public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) {
271 mCryptoObject = crypto;
272 mFingerprint = fingerprint;
273 }
274
275 /**
276 * Obtain the crypto object associated with this transaction
277 * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
Jim Millerf501b582015-06-03 16:36:31 -0700278 * CancellationSignal, int, AuthenticationCallback, Handler)}.
Jim Miller9f0753f2015-03-23 23:59:22 -0700279 */
280 public CryptoObject getCryptoObject() { return mCryptoObject; }
281
282 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700283 * Obtain the Fingerprint associated with this operation. Applications are strongly
284 * discouraged from associating specific fingers with specific applications or operations.
285 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700286 * @hide
287 */
288 public Fingerprint getFingerprint() { return mFingerprint; }
289 };
290
291 /**
292 * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
Jim Millerf501b582015-06-03 16:36:31 -0700293 * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link
Jim Millerce7eb6d2015-04-03 19:29:13 -0700294 * FingerprintManager#authenticate(CryptoObject, CancellationSignal,
Jim Millerf501b582015-06-03 16:36:31 -0700295 * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
Jim Millerce7eb6d2015-04-03 19:29:13 -0700296 * fingerprint events.
Jim Miller9f0753f2015-03-23 23:59:22 -0700297 */
298 public static abstract class AuthenticationCallback {
299 /**
300 * Called when an unrecoverable error has been encountered and the operation is complete.
301 * No further callbacks will be made on this object.
Jim Millerf501b582015-06-03 16:36:31 -0700302 * @param errorCode An integer identifying the error message
Jim Millerce7eb6d2015-04-03 19:29:13 -0700303 * @param errString A human-readable error string that can be shown in UI
Jim Miller9f0753f2015-03-23 23:59:22 -0700304 */
Jim Millerf501b582015-06-03 16:36:31 -0700305 public void onAuthenticationError(int errorCode, CharSequence errString) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700306
307 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700308 * Called when a recoverable error has been encountered during authentication. The help
Jim Miller9f0753f2015-03-23 23:59:22 -0700309 * string is provided to give the user guidance for what went wrong, such as
310 * "Sensor dirty, please clean it."
Jim Millerf501b582015-06-03 16:36:31 -0700311 * @param helpCode An integer identifying the error message
Jim Millerce7eb6d2015-04-03 19:29:13 -0700312 * @param helpString A human-readable string that can be shown in UI
Jim Miller9f0753f2015-03-23 23:59:22 -0700313 */
Jim Millerf501b582015-06-03 16:36:31 -0700314 public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700315
316 /**
317 * Called when a fingerprint is recognized.
Jim Millerce7eb6d2015-04-03 19:29:13 -0700318 * @param result An object containing authentication-related data
Jim Miller9f0753f2015-03-23 23:59:22 -0700319 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700320 public void onAuthenticationSucceeded(AuthenticationResult result) { }
321
322 /**
323 * Called when a fingerprint is valid but not recognized.
324 */
325 public void onAuthenticationFailed() { }
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700326
327 /**
328 * Called when a fingerprint image has been acquired, but wasn't processed yet.
329 *
330 * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants
331 * @hide
332 */
333 public void onAuthenticationAcquired(int acquireInfo) {}
Jim Miller9f0753f2015-03-23 23:59:22 -0700334 };
335
336 /**
337 * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback,
338 * CancellationSignal, int). Users of {@link #FingerprintManager()}
339 * must provide an implementation of this to {@link FingerprintManager#enroll(long,
Jim Millerf501b582015-06-03 16:36:31 -0700340 * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events.
Jim Millerce7eb6d2015-04-03 19:29:13 -0700341 *
342 * @hide
Jim Miller9f0753f2015-03-23 23:59:22 -0700343 */
344 public static abstract class EnrollmentCallback {
345 /**
346 * Called when an unrecoverable error has been encountered and the operation is complete.
347 * No further callbacks will be made on this object.
Jim Millerce7eb6d2015-04-03 19:29:13 -0700348 * @param errMsgId An integer identifying the error message
349 * @param errString A human-readable error string that can be shown in UI
Jim Miller9f0753f2015-03-23 23:59:22 -0700350 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700351 public void onEnrollmentError(int errMsgId, CharSequence errString) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700352
353 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700354 * Called when a recoverable error has been encountered during enrollment. The help
Jim Miller9f0753f2015-03-23 23:59:22 -0700355 * string is provided to give the user guidance for what went wrong, such as
356 * "Sensor dirty, please clean it" or what they need to do next, such as
357 * "Touch sensor again."
Jim Millerce7eb6d2015-04-03 19:29:13 -0700358 * @param helpMsgId An integer identifying the error message
359 * @param helpString A human-readable string that can be shown in UI
Jim Miller9f0753f2015-03-23 23:59:22 -0700360 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700361 public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700362
363 /**
364 * Called as each enrollment step progresses. Enrollment is considered complete when
Jim Millerce7eb6d2015-04-03 19:29:13 -0700365 * remaining reaches 0. This function will not be called if enrollment fails. See
Jim Miller9f0753f2015-03-23 23:59:22 -0700366 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
Jim Millerce7eb6d2015-04-03 19:29:13 -0700367 * @param remaining The number of remaining steps
Jim Miller9f0753f2015-03-23 23:59:22 -0700368 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700369 public void onEnrollmentProgress(int remaining) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700370 };
371
372 /**
373 * Callback structure provided to {@link FingerprintManager#remove(int). Users of
374 * {@link #FingerprintManager()} may optionally provide an implementation of this to
375 * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to
376 * fingerprint template removal events.
Jim Millerce7eb6d2015-04-03 19:29:13 -0700377 *
378 * @hide
Jim Miller9f0753f2015-03-23 23:59:22 -0700379 */
380 public static abstract class RemovalCallback {
381 /**
382 * Called when the given fingerprint can't be removed.
Jim Millerce7eb6d2015-04-03 19:29:13 -0700383 * @param fp The fingerprint that the call attempted to remove
384 * @param errMsgId An associated error message id
385 * @param errString An error message indicating why the fingerprint id can't be removed
Jim Miller9f0753f2015-03-23 23:59:22 -0700386 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700387 public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700388
389 /**
390 * Called when a given fingerprint is successfully removed.
391 * @param fingerprint the fingerprint template that was removed.
392 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700393 public void onRemovalSucceeded(Fingerprint fingerprint) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700394 };
395
396 /**
Jorim Jaggi3a464782015-08-28 16:59:13 -0700397 * @hide
398 */
399 public static abstract class LockoutResetCallback {
400
401 /**
402 * Called when lockout period expired and clients are allowed to listen for fingerprint
403 * again.
404 */
405 public void onLockoutReset() { }
406 };
407
408 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700409 * Request authentication of a crypto object. This call warms up the fingerprint hardware
410 * and starts scanning for a fingerprint. It terminates when
Jim Miller9f0753f2015-03-23 23:59:22 -0700411 * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
Jim Miller5f69ca32015-08-19 22:03:43 -0700412 * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
Jim Miller9f0753f2015-03-23 23:59:22 -0700413 * which point the object is no longer valid. The operation can be canceled by using the
414 * provided cancel object.
415 *
416 * @param crypto object associated with the call or null if none required.
Jim Miller9f0753f2015-03-23 23:59:22 -0700417 * @param cancel an object that can be used to cancel authentication
Jim Millerce7eb6d2015-04-03 19:29:13 -0700418 * @param flags optional flags; should be 0
Jim Millerf501b582015-06-03 16:36:31 -0700419 * @param callback an object to receive authentication events
420 * @param handler an optional handler to handle callback events
Jim Millere4c58e42015-06-09 13:48:57 -0700421 *
422 * @throws IllegalArgumentException if the crypto operation is not supported or is not backed
423 * by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
424 * facility</a>.
425 * @throws IllegalStateException if the crypto primitive is not initialized.
Jim Miller9f0753f2015-03-23 23:59:22 -0700426 */
Jim Millerf501b582015-06-03 16:36:31 -0700427 @RequiresPermission(USE_FINGERPRINT)
Jim Millerce7eb6d2015-04-03 19:29:13 -0700428 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
Jim Millerf501b582015-06-03 16:36:31 -0700429 int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
430 authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId());
Jorim Jaggiccdfa932015-04-13 16:29:48 -0700431 }
432
433 /**
Jim Millerf501b582015-06-03 16:36:31 -0700434 * Use the provided handler thread for events.
435 * @param handler
436 */
437 private void useHandler(Handler handler) {
438 if (handler != null) {
439 mHandler = new MyHandler(handler.getLooper());
440 } else if (mHandler.getLooper() != mContext.getMainLooper()){
441 mHandler = new MyHandler(mContext.getMainLooper());
442 }
443 }
444
445 /**
446 * Per-user version
Jorim Jaggiccdfa932015-04-13 16:29:48 -0700447 * @hide
448 */
Jim Millerf501b582015-06-03 16:36:31 -0700449 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggiccdfa932015-04-13 16:29:48 -0700450 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
Jim Millerf501b582015-06-03 16:36:31 -0700451 int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700452 if (callback == null) {
453 throw new IllegalArgumentException("Must supply an authentication callback");
454 }
455
Jim Millerce7eb6d2015-04-03 19:29:13 -0700456 if (cancel != null) {
457 if (cancel.isCanceled()) {
458 Log.w(TAG, "authentication already canceled");
459 return;
460 } else {
461 cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
462 }
463 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700464
465 if (mService != null) try {
Jim Millerf501b582015-06-03 16:36:31 -0700466 useHandler(handler);
Jim Miller9f0753f2015-03-23 23:59:22 -0700467 mAuthenticationCallback = callback;
468 mCryptoObject = crypto;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700469 long sessionId = crypto != null ? crypto.getOpId() : 0;
Svetoslav4af76a52015-04-29 15:29:46 -0700470 mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
471 mContext.getOpPackageName());
Jim Miller9f0753f2015-03-23 23:59:22 -0700472 } catch (RemoteException e) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700473 Log.w(TAG, "Remote exception while authenticating: ", e);
474 if (callback != null) {
475 // Though this may not be a hardware issue, it will cause apps to give up or try
476 // again later.
477 callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
478 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
479 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700480 }
481 }
482
483 /**
484 * Request fingerprint enrollment. This call warms up the fingerprint hardware
485 * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
486 * {@link EnrollmentCallback} object. It terminates when
487 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or
488 * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at
489 * which point the object is no longer valid. The operation can be canceled by using the
490 * provided cancel object.
Jim Millerfe6439f2015-04-11 18:07:57 -0700491 * @param token a unique token provided by a recent creation or verification of device
492 * credentials (e.g. pin, pattern or password).
Jim Miller9f0753f2015-03-23 23:59:22 -0700493 * @param cancel an object that can be used to cancel enrollment
494 * @param flags optional flags
Clara Bayarria5c1a772016-01-26 16:36:14 +0000495 * @param userId the user to whom this fingerprint will belong to
Jim Millerf501b582015-06-03 16:36:31 -0700496 * @param callback an object to receive enrollment events
Jim Millerce7eb6d2015-04-03 19:29:13 -0700497 * @hide
Jim Miller9f0753f2015-03-23 23:59:22 -0700498 */
Jim Millerf501b582015-06-03 16:36:31 -0700499 @RequiresPermission(MANAGE_FINGERPRINT)
500 public void enroll(byte [] token, CancellationSignal cancel, int flags,
Clara Bayarria5c1a772016-01-26 16:36:14 +0000501 int userId, EnrollmentCallback callback) {
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000502 if (userId == UserHandle.USER_CURRENT) {
503 userId = getCurrentUserId();
504 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700505 if (callback == null) {
506 throw new IllegalArgumentException("Must supply an enrollment callback");
507 }
508
Jim Millerce7eb6d2015-04-03 19:29:13 -0700509 if (cancel != null) {
510 if (cancel.isCanceled()) {
511 Log.w(TAG, "enrollment already canceled");
512 return;
513 } else {
Jim Millerfe6439f2015-04-11 18:07:57 -0700514 cancel.setOnCancelListener(new OnEnrollCancelListener());
Jim Millerce7eb6d2015-04-03 19:29:13 -0700515 }
516 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700517
518 if (mService != null) try {
519 mEnrollmentCallback = callback;
Jim Millercb2ce6f2016-04-13 20:28:18 -0700520 mService.enroll(mToken, token, userId, mServiceReceiver, flags,
521 mContext.getOpPackageName());
Jim Miller9f0753f2015-03-23 23:59:22 -0700522 } catch (RemoteException e) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700523 Log.w(TAG, "Remote exception in enroll: ", e);
524 if (callback != null) {
525 // Though this may not be a hardware issue, it will cause apps to give up or try
526 // again later.
527 callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
528 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
529 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700530 }
531 }
532
533 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700534 * Requests a pre-enrollment auth token to tie enrollment to the confirmation of
535 * existing device credentials (e.g. pin/pattern/password).
536 * @hide
537 */
Jim Millerf501b582015-06-03 16:36:31 -0700538 @RequiresPermission(MANAGE_FINGERPRINT)
Jim Millerce7eb6d2015-04-03 19:29:13 -0700539 public long preEnroll() {
540 long result = 0;
541 if (mService != null) try {
542 result = mService.preEnroll(mToken);
543 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700544 throw e.rethrowFromSystemServer();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700545 }
546 return result;
547 }
548
549 /**
Sasha Levitskiye0943cf2015-07-08 13:22:20 -0700550 * Finishes enrollment and cancels the current auth token.
551 * @hide
552 */
553 @RequiresPermission(MANAGE_FINGERPRINT)
554 public int postEnroll() {
555 int result = 0;
556 if (mService != null) try {
557 result = mService.postEnroll(mToken);
558 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700559 throw e.rethrowFromSystemServer();
Sasha Levitskiye0943cf2015-07-08 13:22:20 -0700560 }
561 return result;
562 }
563
564 /**
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000565 * Sets the active user. This is meant to be used to select the current profile for enrollment
566 * to allow separate enrolled fingers for a work profile
567 * @param userId
568 * @hide
569 */
570 @RequiresPermission(MANAGE_FINGERPRINT)
571 public void setActiveUser(int userId) {
572 if (mService != null) try {
573 mService.setActiveUser(userId);
574 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700575 throw e.rethrowFromSystemServer();
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000576 }
577 }
578
579 /**
Jim Miller9f0753f2015-03-23 23:59:22 -0700580 * Remove given fingerprint template from fingerprint hardware and/or protected storage.
581 * @param fp the fingerprint item to remove
Clara Bayarria5c1a772016-01-26 16:36:14 +0000582 * @param userId the user who this fingerprint belongs to
Jim Miller9f0753f2015-03-23 23:59:22 -0700583 * @param callback an optional callback to verify that fingerprint templates have been
Jim Millerce7eb6d2015-04-03 19:29:13 -0700584 * successfully removed. May be null of no callback is required.
585 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700586 * @hide
587 */
Jim Millerf501b582015-06-03 16:36:31 -0700588 @RequiresPermission(MANAGE_FINGERPRINT)
Clara Bayarria5c1a772016-01-26 16:36:14 +0000589 public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700590 if (mService != null) try {
591 mRemovalCallback = callback;
592 mRemovalFingerprint = fp;
Clara Bayarria5c1a772016-01-26 16:36:14 +0000593 mService.remove(mToken, fp.getFingerId(), userId, mServiceReceiver);
Jim Miller9f0753f2015-03-23 23:59:22 -0700594 } catch (RemoteException e) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700595 Log.w(TAG, "Remote exception in remove: ", e);
596 if (callback != null) {
597 callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE,
598 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
599 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700600 }
601 }
602
603 /**
604 * Renames the given fingerprint template
605 * @param fpId the fingerprint id
Clara Bayarria5c1a772016-01-26 16:36:14 +0000606 * @param userId the user who this fingerprint belongs to
Jim Miller9f0753f2015-03-23 23:59:22 -0700607 * @param newName the new name
Jim Millerce7eb6d2015-04-03 19:29:13 -0700608 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700609 * @hide
610 */
Jim Millerf501b582015-06-03 16:36:31 -0700611 @RequiresPermission(MANAGE_FINGERPRINT)
Clara Bayarria5c1a772016-01-26 16:36:14 +0000612 public void rename(int fpId, int userId, String newName) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700613 // Renames the given fpId
614 if (mService != null) {
615 try {
Clara Bayarria5c1a772016-01-26 16:36:14 +0000616 mService.rename(fpId, userId, newName);
Jim Miller9f0753f2015-03-23 23:59:22 -0700617 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700618 throw e.rethrowFromSystemServer();
Jim Miller9f0753f2015-03-23 23:59:22 -0700619 }
620 } else {
621 Log.w(TAG, "rename(): Service not connected!");
622 }
623 }
624
625 /**
626 * Obtain the list of enrolled fingerprints templates.
627 * @return list of current fingerprint items
Jim Millerce7eb6d2015-04-03 19:29:13 -0700628 *
629 * @hide
Jim Miller9f0753f2015-03-23 23:59:22 -0700630 */
Jim Millerf501b582015-06-03 16:36:31 -0700631 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700632 public List<Fingerprint> getEnrolledFingerprints(int userId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700633 if (mService != null) try {
Svetoslav4af76a52015-04-29 15:29:46 -0700634 return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
Jim Miller9f0753f2015-03-23 23:59:22 -0700635 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700636 throw e.rethrowFromSystemServer();
Jim Miller9f0753f2015-03-23 23:59:22 -0700637 }
638 return null;
639 }
640
641 /**
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700642 * Obtain the list of enrolled fingerprints templates.
643 * @return list of current fingerprint items
Jim Millerce7eb6d2015-04-03 19:29:13 -0700644 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700645 * @hide
646 */
Jim Millerf501b582015-06-03 16:36:31 -0700647 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700648 public List<Fingerprint> getEnrolledFingerprints() {
649 return getEnrolledFingerprints(UserHandle.myUserId());
650 }
651
652 /**
653 * Determine if there is at least one fingerprint enrolled.
654 *
655 * @return true if at least one fingerprint is enrolled, false otherwise
656 */
Jim Millerf501b582015-06-03 16:36:31 -0700657 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700658 public boolean hasEnrolledFingerprints() {
659 if (mService != null) try {
Clara Bayarri33fd3cf2016-02-19 16:54:49 +0000660 return mService.hasEnrolledFingerprints(
661 UserHandle.myUserId(), mContext.getOpPackageName());
662 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700663 throw e.rethrowFromSystemServer();
Clara Bayarri33fd3cf2016-02-19 16:54:49 +0000664 }
665 return false;
666 }
667
668 /**
669 * @hide
670 */
671 @RequiresPermission(allOf = {
672 USE_FINGERPRINT,
673 INTERACT_ACROSS_USERS})
674 public boolean hasEnrolledFingerprints(int userId) {
675 if (mService != null) try {
676 return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700677 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700678 throw e.rethrowFromSystemServer();
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700679 }
680 return false;
681 }
682
683 /**
684 * Determine if fingerprint hardware is present and functional.
685 *
686 * @return true if hardware is present and functional, false otherwise.
687 */
Jim Millerf501b582015-06-03 16:36:31 -0700688 @RequiresPermission(USE_FINGERPRINT)
Jim Miller9f0753f2015-03-23 23:59:22 -0700689 public boolean isHardwareDetected() {
690 if (mService != null) {
691 try {
692 long deviceId = 0; /* TODO: plumb hardware id to FPMS */
Svetoslav4af76a52015-04-29 15:29:46 -0700693 return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
Jim Miller9f0753f2015-03-23 23:59:22 -0700694 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700695 throw e.rethrowFromSystemServer();
Jim Miller9f0753f2015-03-23 23:59:22 -0700696 }
697 } else {
698 Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
699 }
700 return false;
701 }
Jim Miller08fa40c2014-04-29 18:18:47 -0700702
Andres Morales4d41a202015-04-16 14:12:38 -0700703 /**
704 * Retrieves the authenticator token for binding keys to the lifecycle
705 * of the current set of fingerprints. Used only by internal clients.
706 *
707 * @hide
708 */
709 public long getAuthenticatorId() {
710 if (mService != null) {
711 try {
Svetoslav4af76a52015-04-29 15:29:46 -0700712 return mService.getAuthenticatorId(mContext.getOpPackageName());
Andres Morales4d41a202015-04-16 14:12:38 -0700713 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700714 throw e.rethrowFromSystemServer();
Andres Morales4d41a202015-04-16 14:12:38 -0700715 }
716 } else {
717 Log.w(TAG, "getAuthenticatorId(): Service not connected!");
718 }
719 return 0;
720 }
721
Jim Millere0507bb2015-08-12 20:30:34 -0700722 /**
723 * Reset the lockout timer when asked to do so by keyguard.
724 *
725 * @param token an opaque token returned by password confirmation.
726 *
727 * @hide
728 */
729 public void resetTimeout(byte[] token) {
730 if (mService != null) {
731 try {
732 mService.resetTimeout(token);
733 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700734 throw e.rethrowFromSystemServer();
Jim Millere0507bb2015-08-12 20:30:34 -0700735 }
736 } else {
Jorim Jaggi3a464782015-08-28 16:59:13 -0700737 Log.w(TAG, "resetTimeout(): Service not connected!");
738 }
739 }
740
741 /**
742 * @hide
743 */
744 public void addLockoutResetCallback(final LockoutResetCallback callback) {
745 if (mService != null) {
746 try {
Jorim Jaggi5e354222015-09-04 14:17:58 -0700747 final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
Jorim Jaggi3a464782015-08-28 16:59:13 -0700748 mService.addLockoutResetCallback(
749 new IFingerprintServiceLockoutResetCallback.Stub() {
750
751 @Override
752 public void onLockoutReset(long deviceId) throws RemoteException {
Jorim Jaggi5e354222015-09-04 14:17:58 -0700753 final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
754 PowerManager.PARTIAL_WAKE_LOCK, "lockoutResetCallback");
755 wakeLock.acquire();
Jorim Jaggi3a464782015-08-28 16:59:13 -0700756 mHandler.post(new Runnable() {
757 @Override
758 public void run() {
Jorim Jaggi5e354222015-09-04 14:17:58 -0700759 try {
760 callback.onLockoutReset();
761 } finally {
762 wakeLock.release();
763 }
Jorim Jaggi3a464782015-08-28 16:59:13 -0700764 }
765 });
766 }
767 });
768 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700769 throw e.rethrowFromSystemServer();
Jorim Jaggi3a464782015-08-28 16:59:13 -0700770 }
771 } else {
772 Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
Jim Millere0507bb2015-08-12 20:30:34 -0700773 }
774 }
775
Alex Klyubin24e9e962015-04-30 13:30:48 -0700776 private class MyHandler extends Handler {
777 private MyHandler(Context context) {
778 super(context.getMainLooper());
779 }
780
Jim Millerf501b582015-06-03 16:36:31 -0700781 private MyHandler(Looper looper) {
782 super(looper);
783 }
784
Jim Millere0507bb2015-08-12 20:30:34 -0700785 @Override
Jim Miller08fa40c2014-04-29 18:18:47 -0700786 public void handleMessage(android.os.Message msg) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700787 switch(msg.what) {
788 case MSG_ENROLL_RESULT:
789 sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
790 break;
791 case MSG_ACQUIRED:
792 sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */);
793 break;
Jim Millerf501b582015-06-03 16:36:31 -0700794 case MSG_AUTHENTICATION_SUCCEEDED:
795 sendAuthenticatedSucceeded((Fingerprint) msg.obj);
796 break;
797 case MSG_AUTHENTICATION_FAILED:
798 sendAuthenticatedFailed();
Jim Miller9f0753f2015-03-23 23:59:22 -0700799 break;
800 case MSG_ERROR:
801 sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */);
802 break;
803 case MSG_REMOVED:
804 sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
805 msg.arg2 /* groupId */);
806 }
807 }
808
809 private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
810 if (mRemovalCallback != null) {
811 int reqFingerId = mRemovalFingerprint.getFingerId();
812 int reqGroupId = mRemovalFingerprint.getGroupId();
Jim Kayef8d1e212015-09-09 08:47:58 -0700813 if (reqFingerId != 0 && fingerId != reqFingerId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700814 Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
Jim Miller08fa40c2014-04-29 18:18:47 -0700815 }
Jim Miller1adb4a72015-09-14 18:58:08 -0700816 if (groupId != reqGroupId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700817 Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
818 }
Ricky Waif86f9862016-03-23 12:05:42 +0000819 mRemovalCallback.onRemovalSucceeded(new Fingerprint(null, groupId, fingerId,
820 deviceId));
Jim Miller9f0753f2015-03-23 23:59:22 -0700821 }
822 }
823
824 private void sendErrorResult(long deviceId, int errMsgId) {
825 if (mEnrollmentCallback != null) {
826 mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId));
827 } else if (mAuthenticationCallback != null) {
828 mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId));
829 } else if (mRemovalCallback != null) {
830 mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId,
831 getErrorString(errMsgId));
832 }
833 }
834
835 private void sendEnrollResult(Fingerprint fp, int remaining) {
836 if (mEnrollmentCallback != null) {
837 mEnrollmentCallback.onEnrollmentProgress(remaining);
838 }
839 }
840
Jim Millerf501b582015-06-03 16:36:31 -0700841 private void sendAuthenticatedSucceeded(Fingerprint fp) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700842 if (mAuthenticationCallback != null) {
Jim Millerf501b582015-06-03 16:36:31 -0700843 final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
844 mAuthenticationCallback.onAuthenticationSucceeded(result);
845 }
846 }
847
848 private void sendAuthenticatedFailed() {
849 if (mAuthenticationCallback != null) {
850 mAuthenticationCallback.onAuthenticationFailed();
Jim Miller9f0753f2015-03-23 23:59:22 -0700851 }
852 }
853
854 private void sendAcquiredResult(long deviceId, int acquireInfo) {
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700855 if (mAuthenticationCallback != null) {
856 mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
857 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700858 final String msg = getAcquiredString(acquireInfo);
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700859 if (msg == null) {
860 return;
861 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700862 if (mEnrollmentCallback != null) {
863 mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg);
864 } else if (mAuthenticationCallback != null) {
865 mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg);
866 }
867 }
Jim Miller08fa40c2014-04-29 18:18:47 -0700868 };
869
Jim Miller06e658f2014-06-17 15:59:40 -0700870 /**
871 * @hide
872 */
Jim Millera75961472014-06-06 15:00:49 -0700873 public FingerprintManager(Context context, IFingerprintService service) {
Jim Millerd08c2ac2014-05-14 16:30:38 -0700874 mContext = context;
Jim Millera75961472014-06-06 15:00:49 -0700875 mService = service;
876 if (mService == null) {
877 Slog.v(TAG, "FingerprintManagerService was null");
Jim Miller08fa40c2014-04-29 18:18:47 -0700878 }
Alex Klyubin24e9e962015-04-30 13:30:48 -0700879 mHandler = new MyHandler(context);
Jim Miller08fa40c2014-04-29 18:18:47 -0700880 }
881
Jim Miller08fa40c2014-04-29 18:18:47 -0700882 private int getCurrentUserId() {
883 try {
884 return ActivityManagerNative.getDefault().getCurrentUser().id;
885 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700886 throw e.rethrowFromSystemServer();
Jim Miller08fa40c2014-04-29 18:18:47 -0700887 }
888 }
889
Jim Millerfe6439f2015-04-11 18:07:57 -0700890 private void cancelEnrollment() {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700891 if (mService != null) try {
892 mService.cancelEnrollment(mToken);
893 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700894 throw e.rethrowFromSystemServer();
Jim Miller08fa40c2014-04-29 18:18:47 -0700895 }
896 }
Jim Millera75961472014-06-06 15:00:49 -0700897
Jim Millerce7eb6d2015-04-03 19:29:13 -0700898 private void cancelAuthentication(CryptoObject cryptoObject) {
899 if (mService != null) try {
Svetoslav4af76a52015-04-29 15:29:46 -0700900 mService.cancelAuthentication(mToken, mContext.getOpPackageName());
Jim Millerce7eb6d2015-04-03 19:29:13 -0700901 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700902 throw e.rethrowFromSystemServer();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700903 }
904 }
905
906 private String getErrorString(int errMsg) {
907 switch (errMsg) {
908 case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
909 return mContext.getString(
910 com.android.internal.R.string.fingerprint_error_unable_to_process);
911 case FINGERPRINT_ERROR_HW_UNAVAILABLE:
912 return mContext.getString(
913 com.android.internal.R.string.fingerprint_error_hw_not_available);
914 case FINGERPRINT_ERROR_NO_SPACE:
915 return mContext.getString(
916 com.android.internal.R.string.fingerprint_error_no_space);
917 case FINGERPRINT_ERROR_TIMEOUT:
Jim Millerfe6439f2015-04-11 18:07:57 -0700918 return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout);
919 case FINGERPRINT_ERROR_CANCELED:
920 return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled);
921 case FINGERPRINT_ERROR_LOCKOUT:
922 return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700923 default:
924 if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) {
925 int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE;
926 String[] msgArray = mContext.getResources().getStringArray(
927 com.android.internal.R.array.fingerprint_error_vendor);
928 if (msgNumber < msgArray.length) {
929 return msgArray[msgNumber];
930 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700931 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700932 return null;
933 }
934 }
935
936 private String getAcquiredString(int acquireInfo) {
937 switch (acquireInfo) {
938 case FINGERPRINT_ACQUIRED_GOOD:
939 return null;
940 case FINGERPRINT_ACQUIRED_PARTIAL:
941 return mContext.getString(
942 com.android.internal.R.string.fingerprint_acquired_partial);
943 case FINGERPRINT_ACQUIRED_INSUFFICIENT:
944 return mContext.getString(
945 com.android.internal.R.string.fingerprint_acquired_insufficient);
946 case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
947 return mContext.getString(
948 com.android.internal.R.string.fingerprint_acquired_imager_dirty);
949 case FINGERPRINT_ACQUIRED_TOO_SLOW:
950 return mContext.getString(
951 com.android.internal.R.string.fingerprint_acquired_too_slow);
952 case FINGERPRINT_ACQUIRED_TOO_FAST:
953 return mContext.getString(
954 com.android.internal.R.string.fingerprint_acquired_too_fast);
955 default:
956 if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) {
957 int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE;
958 String[] msgArray = mContext.getResources().getStringArray(
959 com.android.internal.R.array.fingerprint_acquired_vendor);
960 if (msgNumber < msgArray.length) {
961 return msgArray[msgNumber];
962 }
963 }
964 return null;
Jim Millerba67aee2015-02-20 16:21:26 -0800965 }
Jim Millerba67aee2015-02-20 16:21:26 -0800966 }
Jim Miller99d60192015-03-11 17:41:58 -0700967
Jim Miller9f0753f2015-03-23 23:59:22 -0700968 private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
969
Jim Millerf501b582015-06-03 16:36:31 -0700970 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -0700971 public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
972 mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
973 new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
Jim Miller99d60192015-03-11 17:41:58 -0700974 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700975
Jim Millerf501b582015-06-03 16:36:31 -0700976 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -0700977 public void onAcquired(long deviceId, int acquireInfo) {
978 mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
979 }
980
Jim Millerf501b582015-06-03 16:36:31 -0700981 @Override // binder call
982 public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) {
983 mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget();
Jim Miller9f0753f2015-03-23 23:59:22 -0700984 }
985
Jim Millerf501b582015-06-03 16:36:31 -0700986 @Override // binder call
987 public void onAuthenticationFailed(long deviceId) {
988 mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
989 }
990
991 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -0700992 public void onError(long deviceId, int error) {
993 mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
994 }
995
Jim Millerf501b582015-06-03 16:36:31 -0700996 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -0700997 public void onRemoved(long deviceId, int fingerId, int groupId) {
998 mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
999 }
1000 };
1001
Andres Morales4d41a202015-04-16 14:12:38 -07001002}