blob: cdf7013deb26d7a6e5c2adc52325080e01c2cf3b [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;
Sudheer Shankadc589ac2016-11-10 15:30:17 -080022import android.app.ActivityManager;
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;
Jim Miller837fa7e2016-08-08 20:16:22 -0700262 private int mUserId;
Jim Miller9f0753f2015-03-23 23:59:22 -0700263
Jim Millerf501b582015-06-03 16:36:31 -0700264 /**
265 * Authentication result
266 *
267 * @param crypto the crypto object
268 * @param fingerprint the recognized fingerprint data, if allowed.
269 * @hide
270 */
Jim Miller837fa7e2016-08-08 20:16:22 -0700271 public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700272 mCryptoObject = crypto;
273 mFingerprint = fingerprint;
Jim Miller837fa7e2016-08-08 20:16:22 -0700274 mUserId = userId;
Jim Miller9f0753f2015-03-23 23:59:22 -0700275 }
276
277 /**
278 * Obtain the crypto object associated with this transaction
279 * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
Jim Millerf501b582015-06-03 16:36:31 -0700280 * CancellationSignal, int, AuthenticationCallback, Handler)}.
Jim Miller9f0753f2015-03-23 23:59:22 -0700281 */
282 public CryptoObject getCryptoObject() { return mCryptoObject; }
283
284 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700285 * Obtain the Fingerprint associated with this operation. Applications are strongly
286 * discouraged from associating specific fingers with specific applications or operations.
287 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700288 * @hide
289 */
290 public Fingerprint getFingerprint() { return mFingerprint; }
Jim Miller837fa7e2016-08-08 20:16:22 -0700291
292 /**
293 * Obtain the userId for which this fingerprint was authenticated.
294 * @hide
295 */
296 public int getUserId() { return mUserId; }
Jim Miller9f0753f2015-03-23 23:59:22 -0700297 };
298
299 /**
300 * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
Jim Millerf501b582015-06-03 16:36:31 -0700301 * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link
Jim Millerce7eb6d2015-04-03 19:29:13 -0700302 * FingerprintManager#authenticate(CryptoObject, CancellationSignal,
Jim Millerf501b582015-06-03 16:36:31 -0700303 * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
Jim Millerce7eb6d2015-04-03 19:29:13 -0700304 * fingerprint events.
Jim Miller9f0753f2015-03-23 23:59:22 -0700305 */
306 public static abstract class AuthenticationCallback {
307 /**
308 * Called when an unrecoverable error has been encountered and the operation is complete.
309 * No further callbacks will be made on this object.
Jim Millerf501b582015-06-03 16:36:31 -0700310 * @param errorCode An integer identifying the error message
Jim Millerce7eb6d2015-04-03 19:29:13 -0700311 * @param errString A human-readable error string that can be shown in UI
Jim Miller9f0753f2015-03-23 23:59:22 -0700312 */
Jim Millerf501b582015-06-03 16:36:31 -0700313 public void onAuthenticationError(int errorCode, CharSequence errString) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700314
315 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700316 * Called when a recoverable error has been encountered during authentication. The help
Jim Miller9f0753f2015-03-23 23:59:22 -0700317 * string is provided to give the user guidance for what went wrong, such as
318 * "Sensor dirty, please clean it."
Jim Millerf501b582015-06-03 16:36:31 -0700319 * @param helpCode An integer identifying the error message
Jim Millerce7eb6d2015-04-03 19:29:13 -0700320 * @param helpString A human-readable string that can be shown in UI
Jim Miller9f0753f2015-03-23 23:59:22 -0700321 */
Jim Millerf501b582015-06-03 16:36:31 -0700322 public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700323
324 /**
325 * Called when a fingerprint is recognized.
Jim Millerce7eb6d2015-04-03 19:29:13 -0700326 * @param result An object containing authentication-related data
Jim Miller9f0753f2015-03-23 23:59:22 -0700327 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700328 public void onAuthenticationSucceeded(AuthenticationResult result) { }
329
330 /**
331 * Called when a fingerprint is valid but not recognized.
332 */
333 public void onAuthenticationFailed() { }
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700334
335 /**
336 * Called when a fingerprint image has been acquired, but wasn't processed yet.
337 *
338 * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants
339 * @hide
340 */
341 public void onAuthenticationAcquired(int acquireInfo) {}
Jim Miller9f0753f2015-03-23 23:59:22 -0700342 };
343
344 /**
345 * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback,
346 * CancellationSignal, int). Users of {@link #FingerprintManager()}
347 * must provide an implementation of this to {@link FingerprintManager#enroll(long,
Jim Millerf501b582015-06-03 16:36:31 -0700348 * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events.
Jim Millerce7eb6d2015-04-03 19:29:13 -0700349 *
350 * @hide
Jim Miller9f0753f2015-03-23 23:59:22 -0700351 */
352 public static abstract class EnrollmentCallback {
353 /**
354 * Called when an unrecoverable error has been encountered and the operation is complete.
355 * No further callbacks will be made on this object.
Jim Millerce7eb6d2015-04-03 19:29:13 -0700356 * @param errMsgId An integer identifying the error message
357 * @param errString A human-readable error string that can be shown in UI
Jim Miller9f0753f2015-03-23 23:59:22 -0700358 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700359 public void onEnrollmentError(int errMsgId, CharSequence errString) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700360
361 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700362 * Called when a recoverable error has been encountered during enrollment. The help
Jim Miller9f0753f2015-03-23 23:59:22 -0700363 * string is provided to give the user guidance for what went wrong, such as
364 * "Sensor dirty, please clean it" or what they need to do next, such as
365 * "Touch sensor again."
Jim Millerce7eb6d2015-04-03 19:29:13 -0700366 * @param helpMsgId An integer identifying the error message
367 * @param helpString A human-readable string that can be shown in UI
Jim Miller9f0753f2015-03-23 23:59:22 -0700368 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700369 public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700370
371 /**
372 * Called as each enrollment step progresses. Enrollment is considered complete when
Jim Millerce7eb6d2015-04-03 19:29:13 -0700373 * remaining reaches 0. This function will not be called if enrollment fails. See
Jim Miller9f0753f2015-03-23 23:59:22 -0700374 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
Jim Millerce7eb6d2015-04-03 19:29:13 -0700375 * @param remaining The number of remaining steps
Jim Miller9f0753f2015-03-23 23:59:22 -0700376 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700377 public void onEnrollmentProgress(int remaining) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700378 };
379
380 /**
381 * Callback structure provided to {@link FingerprintManager#remove(int). Users of
382 * {@link #FingerprintManager()} may optionally provide an implementation of this to
383 * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to
384 * fingerprint template removal events.
Jim Millerce7eb6d2015-04-03 19:29:13 -0700385 *
386 * @hide
Jim Miller9f0753f2015-03-23 23:59:22 -0700387 */
388 public static abstract class RemovalCallback {
389 /**
390 * Called when the given fingerprint can't be removed.
Jim Millerce7eb6d2015-04-03 19:29:13 -0700391 * @param fp The fingerprint that the call attempted to remove
392 * @param errMsgId An associated error message id
393 * @param errString An error message indicating why the fingerprint id can't be removed
Jim Miller9f0753f2015-03-23 23:59:22 -0700394 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700395 public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700396
397 /**
398 * Called when a given fingerprint is successfully removed.
399 * @param fingerprint the fingerprint template that was removed.
400 */
Jim Millerce7eb6d2015-04-03 19:29:13 -0700401 public void onRemovalSucceeded(Fingerprint fingerprint) { }
Jim Miller9f0753f2015-03-23 23:59:22 -0700402 };
403
404 /**
Jorim Jaggi3a464782015-08-28 16:59:13 -0700405 * @hide
406 */
407 public static abstract class LockoutResetCallback {
408
409 /**
410 * Called when lockout period expired and clients are allowed to listen for fingerprint
411 * again.
412 */
413 public void onLockoutReset() { }
414 };
415
416 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700417 * Request authentication of a crypto object. This call warms up the fingerprint hardware
418 * and starts scanning for a fingerprint. It terminates when
Jim Miller9f0753f2015-03-23 23:59:22 -0700419 * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
Jim Miller5f69ca32015-08-19 22:03:43 -0700420 * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
Jim Miller9f0753f2015-03-23 23:59:22 -0700421 * which point the object is no longer valid. The operation can be canceled by using the
422 * provided cancel object.
423 *
424 * @param crypto object associated with the call or null if none required.
Jim Miller9f0753f2015-03-23 23:59:22 -0700425 * @param cancel an object that can be used to cancel authentication
Jim Millerce7eb6d2015-04-03 19:29:13 -0700426 * @param flags optional flags; should be 0
Jim Millerf501b582015-06-03 16:36:31 -0700427 * @param callback an object to receive authentication events
428 * @param handler an optional handler to handle callback events
Jim Millere4c58e42015-06-09 13:48:57 -0700429 *
430 * @throws IllegalArgumentException if the crypto operation is not supported or is not backed
431 * by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
432 * facility</a>.
433 * @throws IllegalStateException if the crypto primitive is not initialized.
Jim Miller9f0753f2015-03-23 23:59:22 -0700434 */
Jim Millerf501b582015-06-03 16:36:31 -0700435 @RequiresPermission(USE_FINGERPRINT)
Jim Millerce7eb6d2015-04-03 19:29:13 -0700436 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
Jim Millerf501b582015-06-03 16:36:31 -0700437 int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
438 authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId());
Jorim Jaggiccdfa932015-04-13 16:29:48 -0700439 }
440
441 /**
Jim Millerf501b582015-06-03 16:36:31 -0700442 * Use the provided handler thread for events.
443 * @param handler
444 */
445 private void useHandler(Handler handler) {
446 if (handler != null) {
447 mHandler = new MyHandler(handler.getLooper());
448 } else if (mHandler.getLooper() != mContext.getMainLooper()){
449 mHandler = new MyHandler(mContext.getMainLooper());
450 }
451 }
452
453 /**
454 * Per-user version
Jorim Jaggiccdfa932015-04-13 16:29:48 -0700455 * @hide
456 */
Jim Millerf501b582015-06-03 16:36:31 -0700457 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggiccdfa932015-04-13 16:29:48 -0700458 public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
Jim Millerf501b582015-06-03 16:36:31 -0700459 int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700460 if (callback == null) {
461 throw new IllegalArgumentException("Must supply an authentication callback");
462 }
463
Jim Millerce7eb6d2015-04-03 19:29:13 -0700464 if (cancel != null) {
465 if (cancel.isCanceled()) {
466 Log.w(TAG, "authentication already canceled");
467 return;
468 } else {
469 cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
470 }
471 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700472
473 if (mService != null) try {
Jim Millerf501b582015-06-03 16:36:31 -0700474 useHandler(handler);
Jim Miller9f0753f2015-03-23 23:59:22 -0700475 mAuthenticationCallback = callback;
476 mCryptoObject = crypto;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700477 long sessionId = crypto != null ? crypto.getOpId() : 0;
Svetoslav4af76a52015-04-29 15:29:46 -0700478 mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
479 mContext.getOpPackageName());
Jim Miller9f0753f2015-03-23 23:59:22 -0700480 } catch (RemoteException e) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700481 Log.w(TAG, "Remote exception while authenticating: ", e);
482 if (callback != null) {
483 // Though this may not be a hardware issue, it will cause apps to give up or try
484 // again later.
485 callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
486 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
487 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700488 }
489 }
490
491 /**
492 * Request fingerprint enrollment. This call warms up the fingerprint hardware
493 * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
494 * {@link EnrollmentCallback} object. It terminates when
495 * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or
496 * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at
497 * which point the object is no longer valid. The operation can be canceled by using the
498 * provided cancel object.
Jim Millerfe6439f2015-04-11 18:07:57 -0700499 * @param token a unique token provided by a recent creation or verification of device
500 * credentials (e.g. pin, pattern or password).
Jim Miller9f0753f2015-03-23 23:59:22 -0700501 * @param cancel an object that can be used to cancel enrollment
502 * @param flags optional flags
Clara Bayarria5c1a772016-01-26 16:36:14 +0000503 * @param userId the user to whom this fingerprint will belong to
Jim Millerf501b582015-06-03 16:36:31 -0700504 * @param callback an object to receive enrollment events
Jim Millerce7eb6d2015-04-03 19:29:13 -0700505 * @hide
Jim Miller9f0753f2015-03-23 23:59:22 -0700506 */
Jim Millerf501b582015-06-03 16:36:31 -0700507 @RequiresPermission(MANAGE_FINGERPRINT)
508 public void enroll(byte [] token, CancellationSignal cancel, int flags,
Clara Bayarria5c1a772016-01-26 16:36:14 +0000509 int userId, EnrollmentCallback callback) {
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000510 if (userId == UserHandle.USER_CURRENT) {
511 userId = getCurrentUserId();
512 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700513 if (callback == null) {
514 throw new IllegalArgumentException("Must supply an enrollment callback");
515 }
516
Jim Millerce7eb6d2015-04-03 19:29:13 -0700517 if (cancel != null) {
518 if (cancel.isCanceled()) {
519 Log.w(TAG, "enrollment already canceled");
520 return;
521 } else {
Jim Millerfe6439f2015-04-11 18:07:57 -0700522 cancel.setOnCancelListener(new OnEnrollCancelListener());
Jim Millerce7eb6d2015-04-03 19:29:13 -0700523 }
524 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700525
526 if (mService != null) try {
527 mEnrollmentCallback = callback;
Jim Millercb2ce6f2016-04-13 20:28:18 -0700528 mService.enroll(mToken, token, userId, mServiceReceiver, flags,
529 mContext.getOpPackageName());
Jim Miller9f0753f2015-03-23 23:59:22 -0700530 } catch (RemoteException e) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700531 Log.w(TAG, "Remote exception in enroll: ", e);
532 if (callback != null) {
533 // Though this may not be a hardware issue, it will cause apps to give up or try
534 // again later.
535 callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
536 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
537 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700538 }
539 }
540
541 /**
Jim Millerce7eb6d2015-04-03 19:29:13 -0700542 * Requests a pre-enrollment auth token to tie enrollment to the confirmation of
543 * existing device credentials (e.g. pin/pattern/password).
544 * @hide
545 */
Jim Millerf501b582015-06-03 16:36:31 -0700546 @RequiresPermission(MANAGE_FINGERPRINT)
Jim Millerce7eb6d2015-04-03 19:29:13 -0700547 public long preEnroll() {
548 long result = 0;
549 if (mService != null) try {
550 result = mService.preEnroll(mToken);
551 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700552 throw e.rethrowFromSystemServer();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700553 }
554 return result;
555 }
556
557 /**
Sasha Levitskiye0943cf2015-07-08 13:22:20 -0700558 * Finishes enrollment and cancels the current auth token.
559 * @hide
560 */
561 @RequiresPermission(MANAGE_FINGERPRINT)
562 public int postEnroll() {
563 int result = 0;
564 if (mService != null) try {
565 result = mService.postEnroll(mToken);
566 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700567 throw e.rethrowFromSystemServer();
Sasha Levitskiye0943cf2015-07-08 13:22:20 -0700568 }
569 return result;
570 }
571
572 /**
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000573 * Sets the active user. This is meant to be used to select the current profile for enrollment
574 * to allow separate enrolled fingers for a work profile
575 * @param userId
576 * @hide
577 */
578 @RequiresPermission(MANAGE_FINGERPRINT)
579 public void setActiveUser(int userId) {
580 if (mService != null) try {
581 mService.setActiveUser(userId);
582 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700583 throw e.rethrowFromSystemServer();
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000584 }
585 }
586
587 /**
Jim Miller9f0753f2015-03-23 23:59:22 -0700588 * Remove given fingerprint template from fingerprint hardware and/or protected storage.
589 * @param fp the fingerprint item to remove
Clara Bayarria5c1a772016-01-26 16:36:14 +0000590 * @param userId the user who this fingerprint belongs to
Jim Miller9f0753f2015-03-23 23:59:22 -0700591 * @param callback an optional callback to verify that fingerprint templates have been
Jim Millerce7eb6d2015-04-03 19:29:13 -0700592 * successfully removed. May be null of no callback is required.
593 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700594 * @hide
595 */
Jim Millerf501b582015-06-03 16:36:31 -0700596 @RequiresPermission(MANAGE_FINGERPRINT)
Clara Bayarria5c1a772016-01-26 16:36:14 +0000597 public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700598 if (mService != null) try {
599 mRemovalCallback = callback;
600 mRemovalFingerprint = fp;
Jim Miller8f2aca02016-04-20 13:34:11 -0700601 mService.remove(mToken, fp.getFingerId(), fp.getGroupId(), userId, mServiceReceiver);
Jim Miller9f0753f2015-03-23 23:59:22 -0700602 } catch (RemoteException e) {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700603 Log.w(TAG, "Remote exception in remove: ", e);
604 if (callback != null) {
605 callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE,
606 getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
607 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700608 }
609 }
610
611 /**
612 * Renames the given fingerprint template
613 * @param fpId the fingerprint id
Clara Bayarria5c1a772016-01-26 16:36:14 +0000614 * @param userId the user who this fingerprint belongs to
Jim Miller9f0753f2015-03-23 23:59:22 -0700615 * @param newName the new name
Jim Millerce7eb6d2015-04-03 19:29:13 -0700616 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700617 * @hide
618 */
Jim Millerf501b582015-06-03 16:36:31 -0700619 @RequiresPermission(MANAGE_FINGERPRINT)
Clara Bayarria5c1a772016-01-26 16:36:14 +0000620 public void rename(int fpId, int userId, String newName) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700621 // Renames the given fpId
622 if (mService != null) {
623 try {
Clara Bayarria5c1a772016-01-26 16:36:14 +0000624 mService.rename(fpId, userId, newName);
Jim Miller9f0753f2015-03-23 23:59:22 -0700625 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700626 throw e.rethrowFromSystemServer();
Jim Miller9f0753f2015-03-23 23:59:22 -0700627 }
628 } else {
629 Log.w(TAG, "rename(): Service not connected!");
630 }
631 }
632
633 /**
634 * Obtain the list of enrolled fingerprints templates.
635 * @return list of current fingerprint items
Jim Millerce7eb6d2015-04-03 19:29:13 -0700636 *
637 * @hide
Jim Miller9f0753f2015-03-23 23:59:22 -0700638 */
Jim Millerf501b582015-06-03 16:36:31 -0700639 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700640 public List<Fingerprint> getEnrolledFingerprints(int userId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700641 if (mService != null) try {
Svetoslav4af76a52015-04-29 15:29:46 -0700642 return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
Jim Miller9f0753f2015-03-23 23:59:22 -0700643 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700644 throw e.rethrowFromSystemServer();
Jim Miller9f0753f2015-03-23 23:59:22 -0700645 }
646 return null;
647 }
648
649 /**
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700650 * Obtain the list of enrolled fingerprints templates.
651 * @return list of current fingerprint items
Jim Millerce7eb6d2015-04-03 19:29:13 -0700652 *
Jim Miller9f0753f2015-03-23 23:59:22 -0700653 * @hide
654 */
Jim Millerf501b582015-06-03 16:36:31 -0700655 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700656 public List<Fingerprint> getEnrolledFingerprints() {
657 return getEnrolledFingerprints(UserHandle.myUserId());
658 }
659
660 /**
661 * Determine if there is at least one fingerprint enrolled.
662 *
663 * @return true if at least one fingerprint is enrolled, false otherwise
664 */
Jim Millerf501b582015-06-03 16:36:31 -0700665 @RequiresPermission(USE_FINGERPRINT)
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700666 public boolean hasEnrolledFingerprints() {
667 if (mService != null) try {
Clara Bayarri33fd3cf2016-02-19 16:54:49 +0000668 return mService.hasEnrolledFingerprints(
669 UserHandle.myUserId(), mContext.getOpPackageName());
670 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700671 throw e.rethrowFromSystemServer();
Clara Bayarri33fd3cf2016-02-19 16:54:49 +0000672 }
673 return false;
674 }
675
676 /**
677 * @hide
678 */
679 @RequiresPermission(allOf = {
680 USE_FINGERPRINT,
681 INTERACT_ACROSS_USERS})
682 public boolean hasEnrolledFingerprints(int userId) {
683 if (mService != null) try {
684 return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700685 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700686 throw e.rethrowFromSystemServer();
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700687 }
688 return false;
689 }
690
691 /**
692 * Determine if fingerprint hardware is present and functional.
693 *
694 * @return true if hardware is present and functional, false otherwise.
695 */
Jim Millerf501b582015-06-03 16:36:31 -0700696 @RequiresPermission(USE_FINGERPRINT)
Jim Miller9f0753f2015-03-23 23:59:22 -0700697 public boolean isHardwareDetected() {
698 if (mService != null) {
699 try {
700 long deviceId = 0; /* TODO: plumb hardware id to FPMS */
Svetoslav4af76a52015-04-29 15:29:46 -0700701 return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
Jim Miller9f0753f2015-03-23 23:59:22 -0700702 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700703 throw e.rethrowFromSystemServer();
Jim Miller9f0753f2015-03-23 23:59:22 -0700704 }
705 } else {
706 Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
707 }
708 return false;
709 }
Jim Miller08fa40c2014-04-29 18:18:47 -0700710
Andres Morales4d41a202015-04-16 14:12:38 -0700711 /**
712 * Retrieves the authenticator token for binding keys to the lifecycle
713 * of the current set of fingerprints. Used only by internal clients.
714 *
715 * @hide
716 */
717 public long getAuthenticatorId() {
718 if (mService != null) {
719 try {
Svetoslav4af76a52015-04-29 15:29:46 -0700720 return mService.getAuthenticatorId(mContext.getOpPackageName());
Andres Morales4d41a202015-04-16 14:12:38 -0700721 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700722 throw e.rethrowFromSystemServer();
Andres Morales4d41a202015-04-16 14:12:38 -0700723 }
724 } else {
725 Log.w(TAG, "getAuthenticatorId(): Service not connected!");
726 }
727 return 0;
728 }
729
Jim Millere0507bb2015-08-12 20:30:34 -0700730 /**
731 * Reset the lockout timer when asked to do so by keyguard.
732 *
733 * @param token an opaque token returned by password confirmation.
734 *
735 * @hide
736 */
737 public void resetTimeout(byte[] token) {
738 if (mService != null) {
739 try {
740 mService.resetTimeout(token);
741 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700742 throw e.rethrowFromSystemServer();
Jim Millere0507bb2015-08-12 20:30:34 -0700743 }
744 } else {
Jorim Jaggi3a464782015-08-28 16:59:13 -0700745 Log.w(TAG, "resetTimeout(): Service not connected!");
746 }
747 }
748
749 /**
750 * @hide
751 */
752 public void addLockoutResetCallback(final LockoutResetCallback callback) {
753 if (mService != null) {
754 try {
Jorim Jaggi5e354222015-09-04 14:17:58 -0700755 final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
Jorim Jaggi3a464782015-08-28 16:59:13 -0700756 mService.addLockoutResetCallback(
757 new IFingerprintServiceLockoutResetCallback.Stub() {
758
759 @Override
760 public void onLockoutReset(long deviceId) throws RemoteException {
Jorim Jaggi5e354222015-09-04 14:17:58 -0700761 final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
762 PowerManager.PARTIAL_WAKE_LOCK, "lockoutResetCallback");
763 wakeLock.acquire();
Jorim Jaggi3a464782015-08-28 16:59:13 -0700764 mHandler.post(new Runnable() {
765 @Override
766 public void run() {
Jorim Jaggi5e354222015-09-04 14:17:58 -0700767 try {
768 callback.onLockoutReset();
769 } finally {
770 wakeLock.release();
771 }
Jorim Jaggi3a464782015-08-28 16:59:13 -0700772 }
773 });
774 }
775 });
776 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700777 throw e.rethrowFromSystemServer();
Jorim Jaggi3a464782015-08-28 16:59:13 -0700778 }
779 } else {
780 Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
Jim Millere0507bb2015-08-12 20:30:34 -0700781 }
782 }
783
Alex Klyubin24e9e962015-04-30 13:30:48 -0700784 private class MyHandler extends Handler {
785 private MyHandler(Context context) {
786 super(context.getMainLooper());
787 }
788
Jim Millerf501b582015-06-03 16:36:31 -0700789 private MyHandler(Looper looper) {
790 super(looper);
791 }
792
Jim Millere0507bb2015-08-12 20:30:34 -0700793 @Override
Jim Miller08fa40c2014-04-29 18:18:47 -0700794 public void handleMessage(android.os.Message msg) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700795 switch(msg.what) {
796 case MSG_ENROLL_RESULT:
797 sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
798 break;
799 case MSG_ACQUIRED:
800 sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */);
801 break;
Jim Millerf501b582015-06-03 16:36:31 -0700802 case MSG_AUTHENTICATION_SUCCEEDED:
Jim Miller837fa7e2016-08-08 20:16:22 -0700803 sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */);
Jim Millerf501b582015-06-03 16:36:31 -0700804 break;
805 case MSG_AUTHENTICATION_FAILED:
806 sendAuthenticatedFailed();
Jim Miller9f0753f2015-03-23 23:59:22 -0700807 break;
808 case MSG_ERROR:
809 sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */);
810 break;
811 case MSG_REMOVED:
812 sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
813 msg.arg2 /* groupId */);
814 }
815 }
816
817 private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
818 if (mRemovalCallback != null) {
819 int reqFingerId = mRemovalFingerprint.getFingerId();
820 int reqGroupId = mRemovalFingerprint.getGroupId();
Jim Miller8f2aca02016-04-20 13:34:11 -0700821 if (reqFingerId != 0 && fingerId != 0 && fingerId != reqFingerId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700822 Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
Jim Miller8f2aca02016-04-20 13:34:11 -0700823 return;
Jim Miller08fa40c2014-04-29 18:18:47 -0700824 }
Jim Miller1adb4a72015-09-14 18:58:08 -0700825 if (groupId != reqGroupId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700826 Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
Jim Miller8f2aca02016-04-20 13:34:11 -0700827 return;
Jim Miller9f0753f2015-03-23 23:59:22 -0700828 }
Ricky Waif86f9862016-03-23 12:05:42 +0000829 mRemovalCallback.onRemovalSucceeded(new Fingerprint(null, groupId, fingerId,
830 deviceId));
Jim Miller9f0753f2015-03-23 23:59:22 -0700831 }
832 }
833
834 private void sendErrorResult(long deviceId, int errMsgId) {
835 if (mEnrollmentCallback != null) {
836 mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId));
837 } else if (mAuthenticationCallback != null) {
838 mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId));
839 } else if (mRemovalCallback != null) {
840 mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId,
841 getErrorString(errMsgId));
842 }
843 }
844
845 private void sendEnrollResult(Fingerprint fp, int remaining) {
846 if (mEnrollmentCallback != null) {
847 mEnrollmentCallback.onEnrollmentProgress(remaining);
848 }
849 }
850
Jim Miller837fa7e2016-08-08 20:16:22 -0700851 private void sendAuthenticatedSucceeded(Fingerprint fp, int userId) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700852 if (mAuthenticationCallback != null) {
Jim Miller837fa7e2016-08-08 20:16:22 -0700853 final AuthenticationResult result =
854 new AuthenticationResult(mCryptoObject, fp, userId);
Jim Millerf501b582015-06-03 16:36:31 -0700855 mAuthenticationCallback.onAuthenticationSucceeded(result);
856 }
857 }
858
859 private void sendAuthenticatedFailed() {
860 if (mAuthenticationCallback != null) {
861 mAuthenticationCallback.onAuthenticationFailed();
Jim Miller9f0753f2015-03-23 23:59:22 -0700862 }
863 }
864
865 private void sendAcquiredResult(long deviceId, int acquireInfo) {
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700866 if (mAuthenticationCallback != null) {
867 mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
868 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700869 final String msg = getAcquiredString(acquireInfo);
Jorim Jaggi4cfdcf52015-07-09 12:13:59 -0700870 if (msg == null) {
871 return;
872 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700873 if (mEnrollmentCallback != null) {
874 mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg);
875 } else if (mAuthenticationCallback != null) {
876 mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg);
877 }
878 }
Jim Miller08fa40c2014-04-29 18:18:47 -0700879 };
880
Jim Miller06e658f2014-06-17 15:59:40 -0700881 /**
882 * @hide
883 */
Jim Millera75961472014-06-06 15:00:49 -0700884 public FingerprintManager(Context context, IFingerprintService service) {
Jim Millerd08c2ac2014-05-14 16:30:38 -0700885 mContext = context;
Jim Millera75961472014-06-06 15:00:49 -0700886 mService = service;
887 if (mService == null) {
888 Slog.v(TAG, "FingerprintManagerService was null");
Jim Miller08fa40c2014-04-29 18:18:47 -0700889 }
Alex Klyubin24e9e962015-04-30 13:30:48 -0700890 mHandler = new MyHandler(context);
Jim Miller08fa40c2014-04-29 18:18:47 -0700891 }
892
Jim Miller08fa40c2014-04-29 18:18:47 -0700893 private int getCurrentUserId() {
894 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800895 return ActivityManager.getService().getCurrentUser().id;
Jim Miller08fa40c2014-04-29 18:18:47 -0700896 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700897 throw e.rethrowFromSystemServer();
Jim Miller08fa40c2014-04-29 18:18:47 -0700898 }
899 }
900
Jim Millerfe6439f2015-04-11 18:07:57 -0700901 private void cancelEnrollment() {
Jim Millerce7eb6d2015-04-03 19:29:13 -0700902 if (mService != null) try {
903 mService.cancelEnrollment(mToken);
904 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700905 throw e.rethrowFromSystemServer();
Jim Miller08fa40c2014-04-29 18:18:47 -0700906 }
907 }
Jim Millera75961472014-06-06 15:00:49 -0700908
Jim Millerce7eb6d2015-04-03 19:29:13 -0700909 private void cancelAuthentication(CryptoObject cryptoObject) {
910 if (mService != null) try {
Svetoslav4af76a52015-04-29 15:29:46 -0700911 mService.cancelAuthentication(mToken, mContext.getOpPackageName());
Jim Millerce7eb6d2015-04-03 19:29:13 -0700912 } catch (RemoteException e) {
Jeff Sharkeyc53962d2016-03-01 19:27:23 -0700913 throw e.rethrowFromSystemServer();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700914 }
915 }
916
917 private String getErrorString(int errMsg) {
918 switch (errMsg) {
919 case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
920 return mContext.getString(
921 com.android.internal.R.string.fingerprint_error_unable_to_process);
922 case FINGERPRINT_ERROR_HW_UNAVAILABLE:
923 return mContext.getString(
924 com.android.internal.R.string.fingerprint_error_hw_not_available);
925 case FINGERPRINT_ERROR_NO_SPACE:
926 return mContext.getString(
927 com.android.internal.R.string.fingerprint_error_no_space);
928 case FINGERPRINT_ERROR_TIMEOUT:
Jim Millerfe6439f2015-04-11 18:07:57 -0700929 return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout);
930 case FINGERPRINT_ERROR_CANCELED:
931 return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled);
932 case FINGERPRINT_ERROR_LOCKOUT:
933 return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700934 default:
935 if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) {
936 int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE;
937 String[] msgArray = mContext.getResources().getStringArray(
938 com.android.internal.R.array.fingerprint_error_vendor);
939 if (msgNumber < msgArray.length) {
940 return msgArray[msgNumber];
941 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700942 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700943 return null;
944 }
945 }
946
947 private String getAcquiredString(int acquireInfo) {
948 switch (acquireInfo) {
949 case FINGERPRINT_ACQUIRED_GOOD:
950 return null;
951 case FINGERPRINT_ACQUIRED_PARTIAL:
952 return mContext.getString(
953 com.android.internal.R.string.fingerprint_acquired_partial);
954 case FINGERPRINT_ACQUIRED_INSUFFICIENT:
955 return mContext.getString(
956 com.android.internal.R.string.fingerprint_acquired_insufficient);
957 case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
958 return mContext.getString(
959 com.android.internal.R.string.fingerprint_acquired_imager_dirty);
960 case FINGERPRINT_ACQUIRED_TOO_SLOW:
961 return mContext.getString(
962 com.android.internal.R.string.fingerprint_acquired_too_slow);
963 case FINGERPRINT_ACQUIRED_TOO_FAST:
964 return mContext.getString(
965 com.android.internal.R.string.fingerprint_acquired_too_fast);
966 default:
967 if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) {
968 int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE;
969 String[] msgArray = mContext.getResources().getStringArray(
970 com.android.internal.R.array.fingerprint_acquired_vendor);
971 if (msgNumber < msgArray.length) {
972 return msgArray[msgNumber];
973 }
974 }
975 return null;
Jim Millerba67aee2015-02-20 16:21:26 -0800976 }
Jim Millerba67aee2015-02-20 16:21:26 -0800977 }
Jim Miller99d60192015-03-11 17:41:58 -0700978
Jim Miller9f0753f2015-03-23 23:59:22 -0700979 private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
980
Jim Millerf501b582015-06-03 16:36:31 -0700981 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -0700982 public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
983 mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
984 new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
Jim Miller99d60192015-03-11 17:41:58 -0700985 }
Jim Miller9f0753f2015-03-23 23:59:22 -0700986
Jim Millerf501b582015-06-03 16:36:31 -0700987 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -0700988 public void onAcquired(long deviceId, int acquireInfo) {
989 mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
990 }
991
Jim Millerf501b582015-06-03 16:36:31 -0700992 @Override // binder call
Jim Miller837fa7e2016-08-08 20:16:22 -0700993 public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {
994 mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();
Jim Miller9f0753f2015-03-23 23:59:22 -0700995 }
996
Jim Millerf501b582015-06-03 16:36:31 -0700997 @Override // binder call
998 public void onAuthenticationFailed(long deviceId) {
999 mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
1000 }
1001
1002 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -07001003 public void onError(long deviceId, int error) {
1004 mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
1005 }
1006
Jim Millerf501b582015-06-03 16:36:31 -07001007 @Override // binder call
Jim Miller9f0753f2015-03-23 23:59:22 -07001008 public void onRemoved(long deviceId, int fingerId, int groupId) {
1009 mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
1010 }
1011 };
1012
Andres Morales4d41a202015-04-16 14:12:38 -07001013}