blob: abd02f0ecc9b73805a6f37565759cbce604d1868 [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;
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000520 mService.enroll(mToken, token, userId, mServiceReceiver, flags);
Jim Miller9f0753f2015-03-23 23:59:22 -0700521 } catch (RemoteException e) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700522 Log.w(TAG, "Remote exception in enroll: ", e);
523 if (callback != null) {
524 // Though this may not be a hardware issue, it will cause apps to give up or try
525 // again later.
526 callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
527 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
528 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700529 }
530 }
531
532 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700533 * Requests a pre-enrollment auth token to tie enrollment to the confirmation of
534 * existing device credentials (e.g. pin/pattern/password).
535 * @hide
536 */
Jim Millerf501b582015-06-03 16:36:31 -0700537 @RequiresPermission(MANAGE_FINGERPRINT)
Jim Millerce7eb6d2015-04-03 19:29:13 -0700538 public long preEnroll() {
539 long result = 0;
540 if (mService != null) try {
541 result = mService.preEnroll(mToken);
542 } catch (RemoteException e) {
543 Log.w(TAG, "Remote exception in enroll: ", e);
544 }
545 return result;
546 }
547
548 /**
Sasha Levitskiye0943cf2015-07-08 13:22:20 -0700549 * Finishes enrollment and cancels the current auth token.
550 * @hide
551 */
552 @RequiresPermission(MANAGE_FINGERPRINT)
553 public int postEnroll() {
554 int result = 0;
555 if (mService != null) try {
556 result = mService.postEnroll(mToken);
557 } catch (RemoteException e) {
558 Log.w(TAG, "Remote exception in post enroll: ", e);
559 }
560 return result;
561 }
562
563 /**
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000564 * Sets the active user. This is meant to be used to select the current profile for enrollment
565 * to allow separate enrolled fingers for a work profile
566 * @param userId
567 * @hide
568 */
569 @RequiresPermission(MANAGE_FINGERPRINT)
570 public void setActiveUser(int userId) {
571 if (mService != null) try {
572 mService.setActiveUser(userId);
573 } catch (RemoteException e) {
574 Log.w(TAG, "Remote exception in setActiveUser: ", e);
575 }
576 }
577
578 /**
Jim Miller9f0753f2015-03-23 23:59:22 -0700579 * Remove given fingerprint template from fingerprint hardware and/or protected storage.
580 * @param fp the fingerprint item to remove
Clara Bayarria5c1a772016-01-26 16:36:14 +0000581 * @param userId the user who this fingerprint belongs to
Jim Miller9f0753f2015-03-23 23:59:22 -0700582 * @param callback an optional callback to verify that fingerprint templates have been
Jim Millerce7eb6d2015-04-03 19:29:13 -0700583 * successfully removed. May be null of no callback is required.
584 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700585 * @hide
586 */
Jim Millerf501b582015-06-03 16:36:31 -0700587 @RequiresPermission(MANAGE_FINGERPRINT)
Clara Bayarria5c1a772016-01-26 16:36:14 +0000588 public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700589 if (mService != null) try {
590 mRemovalCallback = callback;
591 mRemovalFingerprint = fp;
Clara Bayarria5c1a772016-01-26 16:36:14 +0000592 mService.remove(mToken, fp.getFingerId(), userId, mServiceReceiver);
Jim Miller9f0753f2015-03-23 23:59:22 -0700593 } catch (RemoteException e) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700594 Log.w(TAG, "Remote exception in remove: ", e);
595 if (callback != null) {
596 callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE,
597 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
598 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700599 }
600 }
601
602 /**
603 * Renames the given fingerprint template
604 * @param fpId the fingerprint id
Clara Bayarria5c1a772016-01-26 16:36:14 +0000605 * @param userId the user who this fingerprint belongs to
Jim Miller9f0753f2015-03-23 23:59:22 -0700606 * @param newName the new name
Jim Millerce7eb6d2015-04-03 19:29:13 -0700607 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700608 * @hide
609 */
Jim Millerf501b582015-06-03 16:36:31 -0700610 @RequiresPermission(MANAGE_FINGERPRINT)
Clara Bayarria5c1a772016-01-26 16:36:14 +0000611 public void rename(int fpId, int userId, String newName) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700612 // Renames the given fpId
613 if (mService != null) {
614 try {
Clara Bayarria5c1a772016-01-26 16:36:14 +0000615 mService.rename(fpId, userId, newName);
Jim Miller9f0753f2015-03-23 23:59:22 -0700616 } catch (RemoteException e) {
617 Log.v(TAG, "Remote exception in rename(): ", e);
618 }
619 } else {
620 Log.w(TAG, "rename(): Service not connected!");
621 }
622 }
623
624 /**
625 * Obtain the list of enrolled fingerprints templates.
626 * @return list of current fingerprint items
Jim Millerce7eb6d2015-04-03 19:29:13 -0700627 *
628 * @hide
Jim Miller9f0753f2015-03-23 23:59:22 -0700629 */
Jim Millerf501b582015-06-03 16:36:31 -0700630 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700631 public List<Fingerprint> getEnrolledFingerprints(int userId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700632 if (mService != null) try {
Svetoslav4af76a52015-04-29 15:29:46 -0700633 return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
Jim Miller9f0753f2015-03-23 23:59:22 -0700634 } catch (RemoteException e) {
635 Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
636 }
637 return null;
638 }
639
640 /**
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700641 * Obtain the list of enrolled fingerprints templates.
642 * @return list of current fingerprint items
Jim Millerce7eb6d2015-04-03 19:29:13 -0700643 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700644 * @hide
645 */
Jim Millerf501b582015-06-03 16:36:31 -0700646 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700647 public List<Fingerprint> getEnrolledFingerprints() {
648 return getEnrolledFingerprints(UserHandle.myUserId());
649 }
650
651 /**
652 * Determine if there is at least one fingerprint enrolled.
653 *
654 * @return true if at least one fingerprint is enrolled, false otherwise
655 */
Jim Millerf501b582015-06-03 16:36:31 -0700656 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700657 public boolean hasEnrolledFingerprints() {
658 if (mService != null) try {
Clara Bayarri33fd3cf2016-02-19 16:54:49 +0000659 return mService.hasEnrolledFingerprints(
660 UserHandle.myUserId(), mContext.getOpPackageName());
661 } catch (RemoteException e) {
662 Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
663 }
664 return false;
665 }
666
667 /**
668 * @hide
669 */
670 @RequiresPermission(allOf = {
671 USE_FINGERPRINT,
672 INTERACT_ACROSS_USERS})
673 public boolean hasEnrolledFingerprints(int userId) {
674 if (mService != null) try {
675 return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700676 } catch (RemoteException e) {
677 Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
678 }
679 return false;
680 }
681
682 /**
683 * Determine if fingerprint hardware is present and functional.
684 *
685 * @return true if hardware is present and functional, false otherwise.
686 */
Jim Millerf501b582015-06-03 16:36:31 -0700687 @RequiresPermission(USE_FINGERPRINT)
Jim Miller9f0753f2015-03-23 23:59:22 -0700688 public boolean isHardwareDetected() {
689 if (mService != null) {
690 try {
691 long deviceId = 0; /* TODO: plumb hardware id to FPMS */
Svetoslav4af76a52015-04-29 15:29:46 -0700692 return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
Jim Miller9f0753f2015-03-23 23:59:22 -0700693 } catch (RemoteException e) {
694 Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e);
695 }
696 } else {
697 Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
698 }
699 return false;
700 }
Jim Miller08fa40c2014-04-29 18:18:47 -0700701
Andres Morales4d41a202015-04-16 14:12:38 -0700702 /**
703 * Retrieves the authenticator token for binding keys to the lifecycle
704 * of the current set of fingerprints. Used only by internal clients.
705 *
706 * @hide
707 */
708 public long getAuthenticatorId() {
709 if (mService != null) {
710 try {
Svetoslav4af76a52015-04-29 15:29:46 -0700711 return mService.getAuthenticatorId(mContext.getOpPackageName());
Andres Morales4d41a202015-04-16 14:12:38 -0700712 } catch (RemoteException e) {
713 Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
714 }
715 } else {
716 Log.w(TAG, "getAuthenticatorId(): Service not connected!");
717 }
718 return 0;
719 }
720
Jim Millere0507bb2015-08-12 20:30:34 -0700721 /**
722 * Reset the lockout timer when asked to do so by keyguard.
723 *
724 * @param token an opaque token returned by password confirmation.
725 *
726 * @hide
727 */
728 public void resetTimeout(byte[] token) {
729 if (mService != null) {
730 try {
731 mService.resetTimeout(token);
732 } catch (RemoteException e) {
Jorim Jaggi3a464782015-08-28 16:59:13 -0700733 Log.v(TAG, "Remote exception in resetTimeout(): ", e);
Jim Millere0507bb2015-08-12 20:30:34 -0700734 }
735 } else {
Jorim Jaggi3a464782015-08-28 16:59:13 -0700736 Log.w(TAG, "resetTimeout(): Service not connected!");
737 }
738 }
739
740 /**
741 * @hide
742 */
743 public void addLockoutResetCallback(final LockoutResetCallback callback) {
744 if (mService != null) {
745 try {
Jorim Jaggi5e354222015-09-04 14:17:58 -0700746 final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
Jorim Jaggi3a464782015-08-28 16:59:13 -0700747 mService.addLockoutResetCallback(
748 new IFingerprintServiceLockoutResetCallback.Stub() {
749
750 @Override
751 public void onLockoutReset(long deviceId) throws RemoteException {
Jorim Jaggi5e354222015-09-04 14:17:58 -0700752 final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
753 PowerManager.PARTIAL_WAKE_LOCK, "lockoutResetCallback");
754 wakeLock.acquire();
Jorim Jaggi3a464782015-08-28 16:59:13 -0700755 mHandler.post(new Runnable() {
756 @Override
757 public void run() {
Jorim Jaggi5e354222015-09-04 14:17:58 -0700758 try {
759 callback.onLockoutReset();
760 } finally {
761 wakeLock.release();
762 }
Jorim Jaggi3a464782015-08-28 16:59:13 -0700763 }
764 });
765 }
766 });
767 } catch (RemoteException e) {
768 Log.v(TAG, "Remote exception in addLockoutResetCallback(): ", e);
769 }
770 } else {
771 Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
Jim Millere0507bb2015-08-12 20:30:34 -0700772 }
773 }
774
Alex Klyubin24e9e962015-04-30 13:30:48 -0700775 private class MyHandler extends Handler {
776 private MyHandler(Context context) {
777 super(context.getMainLooper());
778 }
779
Jim Millerf501b582015-06-03 16:36:31 -0700780 private MyHandler(Looper looper) {
781 super(looper);
782 }
783
Jim Millere0507bb2015-08-12 20:30:34 -0700784 @Override
Jim Miller08fa40c2014-04-29 18:18:47 -0700785 public void handleMessage(android.os.Message msg) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700786 switch(msg.what) {
787 case MSG_ENROLL_RESULT:
788 sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
789 break;
790 case MSG_ACQUIRED:
791 sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */);
792 break;
Jim Millerf501b582015-06-03 16:36:31 -0700793 case MSG_AUTHENTICATION_SUCCEEDED:
794 sendAuthenticatedSucceeded((Fingerprint) msg.obj);
795 break;
796 case MSG_AUTHENTICATION_FAILED:
797 sendAuthenticatedFailed();
Jim Miller9f0753f2015-03-23 23:59:22 -0700798 break;
799 case MSG_ERROR:
800 sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */);
801 break;
802 case MSG_REMOVED:
803 sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
804 msg.arg2 /* groupId */);
805 }
806 }
807
808 private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
809 if (mRemovalCallback != null) {
810 int reqFingerId = mRemovalFingerprint.getFingerId();
811 int reqGroupId = mRemovalFingerprint.getGroupId();
Jim Kayef8d1e212015-09-09 08:47:58 -0700812 if (reqFingerId != 0 && fingerId != reqFingerId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700813 Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
Jim Miller08fa40c2014-04-29 18:18:47 -0700814 }
Jim Miller1adb4a72015-09-14 18:58:08 -0700815 if (groupId != reqGroupId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700816 Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
817 }
818 mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint);
819 }
820 }
821
822 private void sendErrorResult(long deviceId, int errMsgId) {
823 if (mEnrollmentCallback != null) {
824 mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId));
825 } else if (mAuthenticationCallback != null) {
826 mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId));
827 } else if (mRemovalCallback != null) {
828 mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId,
829 getErrorString(errMsgId));
830 }
831 }
832
833 private void sendEnrollResult(Fingerprint fp, int remaining) {
834 if (mEnrollmentCallback != null) {
835 mEnrollmentCallback.onEnrollmentProgress(remaining);
836 }
837 }
838
Jim Millerf501b582015-06-03 16:36:31 -0700839 private void sendAuthenticatedSucceeded(Fingerprint fp) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700840 if (mAuthenticationCallback != null) {
Jim Millerf501b582015-06-03 16:36:31 -0700841 final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
842 mAuthenticationCallback.onAuthenticationSucceeded(result);
843 }
844 }
845
846 private void sendAuthenticatedFailed() {
847 if (mAuthenticationCallback != null) {
848 mAuthenticationCallback.onAuthenticationFailed();
Jim Miller9f0753f2015-03-23 23:59:22 -0700849 }
850 }
851
852 private void sendAcquiredResult(long deviceId, int acquireInfo) {
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700853 if (mAuthenticationCallback != null) {
854 mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
855 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700856 final String msg = getAcquiredString(acquireInfo);
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700857 if (msg == null) {
858 return;
859 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700860 if (mEnrollmentCallback != null) {
861 mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg);
862 } else if (mAuthenticationCallback != null) {
863 mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg);
864 }
865 }
Jim Miller08fa40c2014-04-29 18:18:47 -0700866 };
867
Jim Miller06e658f2014-06-17 15:59:40 -0700868 /**
869 * @hide
870 */
Jim Millera75961472014-06-06 15:00:49 -0700871 public FingerprintManager(Context context, IFingerprintService service) {
Jim Millerd08c2ac2014-05-14 16:30:38 -0700872 mContext = context;
Jim Millera75961472014-06-06 15:00:49 -0700873 mService = service;
874 if (mService == null) {
875 Slog.v(TAG, "FingerprintManagerService was null");
Jim Miller08fa40c2014-04-29 18:18:47 -0700876 }
Alex Klyubin24e9e962015-04-30 13:30:48 -0700877 mHandler = new MyHandler(context);
Jim Miller08fa40c2014-04-29 18:18:47 -0700878 }
879
Jim Miller08fa40c2014-04-29 18:18:47 -0700880 private int getCurrentUserId() {
881 try {
882 return ActivityManagerNative.getDefault().getCurrentUser().id;
883 } catch (RemoteException e) {
884 Log.w(TAG, "Failed to get current user id\n");
885 return UserHandle.USER_NULL;
886 }
887 }
888
Jim Millerfe6439f2015-04-11 18:07:57 -0700889 private void cancelEnrollment() {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700890 if (mService != null) try {
891 mService.cancelEnrollment(mToken);
892 } catch (RemoteException e) {
893 if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
Jim Miller08fa40c2014-04-29 18:18:47 -0700894 }
895 }
Jim Millera75961472014-06-06 15:00:49 -0700896
Jim Millerce7eb6d2015-04-03 19:29:13 -0700897 private void cancelAuthentication(CryptoObject cryptoObject) {
898 if (mService != null) try {
Svetoslav4af76a52015-04-29 15:29:46 -0700899 mService.cancelAuthentication(mToken, mContext.getOpPackageName());
Jim Millerce7eb6d2015-04-03 19:29:13 -0700900 } catch (RemoteException e) {
901 if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
902 }
903 }
904
905 private String getErrorString(int errMsg) {
906 switch (errMsg) {
907 case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
908 return mContext.getString(
909 com.android.internal.R.string.fingerprint_error_unable_to_process);
910 case FINGERPRINT_ERROR_HW_UNAVAILABLE:
911 return mContext.getString(
912 com.android.internal.R.string.fingerprint_error_hw_not_available);
913 case FINGERPRINT_ERROR_NO_SPACE:
914 return mContext.getString(
915 com.android.internal.R.string.fingerprint_error_no_space);
916 case FINGERPRINT_ERROR_TIMEOUT:
Jim Millerfe6439f2015-04-11 18:07:57 -0700917 return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout);
918 case FINGERPRINT_ERROR_CANCELED:
919 return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled);
920 case FINGERPRINT_ERROR_LOCKOUT:
921 return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700922 default:
923 if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) {
924 int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE;
925 String[] msgArray = mContext.getResources().getStringArray(
926 com.android.internal.R.array.fingerprint_error_vendor);
927 if (msgNumber < msgArray.length) {
928 return msgArray[msgNumber];
929 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700930 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700931 return null;
932 }
933 }
934
935 private String getAcquiredString(int acquireInfo) {
936 switch (acquireInfo) {
937 case FINGERPRINT_ACQUIRED_GOOD:
938 return null;
939 case FINGERPRINT_ACQUIRED_PARTIAL:
940 return mContext.getString(
941 com.android.internal.R.string.fingerprint_acquired_partial);
942 case FINGERPRINT_ACQUIRED_INSUFFICIENT:
943 return mContext.getString(
944 com.android.internal.R.string.fingerprint_acquired_insufficient);
945 case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
946 return mContext.getString(
947 com.android.internal.R.string.fingerprint_acquired_imager_dirty);
948 case FINGERPRINT_ACQUIRED_TOO_SLOW:
949 return mContext.getString(
950 com.android.internal.R.string.fingerprint_acquired_too_slow);
951 case FINGERPRINT_ACQUIRED_TOO_FAST:
952 return mContext.getString(
953 com.android.internal.R.string.fingerprint_acquired_too_fast);
954 default:
955 if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) {
956 int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE;
957 String[] msgArray = mContext.getResources().getStringArray(
958 com.android.internal.R.array.fingerprint_acquired_vendor);
959 if (msgNumber < msgArray.length) {
960 return msgArray[msgNumber];
961 }
962 }
963 return null;
Jim Millerba67aee2015-02-20 16:21:26 -0800964 }
Jim Millerba67aee2015-02-20 16:21:26 -0800965 }
Jim Miller99d60192015-03-11 17:41:58 -0700966
Jim Miller9f0753f2015-03-23 23:59:22 -0700967 private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
968
Jim Millerf501b582015-06-03 16:36:31 -0700969 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -0700970 public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
971 mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
972 new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
Jim Miller99d60192015-03-11 17:41:58 -0700973 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700974
Jim Millerf501b582015-06-03 16:36:31 -0700975 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -0700976 public void onAcquired(long deviceId, int acquireInfo) {
977 mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
978 }
979
Jim Millerf501b582015-06-03 16:36:31 -0700980 @Override // binder call
981 public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) {
982 mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget();
Jim Miller9f0753f2015-03-23 23:59:22 -0700983 }
984
Jim Millerf501b582015-06-03 16:36:31 -0700985 @Override // binder call
986 public void onAuthenticationFailed(long deviceId) {
987 mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
988 }
989
990 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -0700991 public void onError(long deviceId, int error) {
992 mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
993 }
994
Jim Millerf501b582015-06-03 16:36:31 -0700995 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -0700996 public void onRemoved(long deviceId, int fingerId, int groupId) {
997 mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
998 }
999 };
1000
Andres Morales4d41a202015-04-16 14:12:38 -07001001}