FingerprintManager.java revision da88f0e6b8bde99b1d65c73f20c9704b06cf5f5a
108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller/**
208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * Copyright (C) 2014 The Android Open Source Project
308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller *
408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * Licensed under the Apache License, Version 2.0 (the "License");
508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * you may not use this file except in compliance with the License.
608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * You may obtain a copy of the License at
708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller *
808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller *      http://www.apache.org/licenses/LICENSE-2.0
908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller *
1008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * Unless required by applicable law or agreed to in writing, software
1108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * distributed under the License is distributed on an "AS IS" BASIS,
1208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * See the License for the specific language governing permissions and
1408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * limitations under the License.
1508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller */
1608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
17ebbf205bc6e8292f74d8fc4652c70274a445f907Jim Millerpackage android.hardware.fingerprint;
1808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
19ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerimport android.annotation.NonNull;
20ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerimport android.annotation.Nullable;
21f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport android.annotation.RequiresPermission;
22dc589ac82b5fe2063f4cfd94c8ae26d43d5420a0Sudheer Shankaimport android.app.ActivityManager;
2308fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.content.Context;
24a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.Binder;
259f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport android.os.CancellationSignal;
26ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Millerimport android.os.CancellationSignal.OnCancelListener;
2708fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.os.Handler;
2808fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.os.IBinder;
2957e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggiimport android.os.IRemoteCallback;
30f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport android.os.Looper;
315e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.os.PowerManager;
3208fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.os.RemoteException;
3308fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.os.UserHandle;
34dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubinimport android.security.keystore.AndroidKeyStoreProvider;
3508fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.util.Log;
36a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.util.Slog;
3708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
389f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport java.security.Signature;
39ba67aee02cf864793129976cd8a8a46e60c60577Jim Millerimport java.util.List;
40ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
419f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport javax.crypto.Cipher;
42b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Millerimport javax.crypto.Mac;
439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
4433fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarriimport static android.Manifest.permission.INTERACT_ACROSS_USERS;
45f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport static android.Manifest.permission.USE_FINGERPRINT;
46f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport static android.Manifest.permission.MANAGE_FINGERPRINT;
47f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
4808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller/**
4908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * A class that coordinates access to the fingerprint hardware.
50ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p>
51ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Use {@link android.content.Context#getSystemService(java.lang.String)}
52ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * with argument {@link android.content.Context#FINGERPRINT_SERVICE} to get
53ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * an instance of this class.
5408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller */
5508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
5608fa40c5cb5229b7969b2a5146855a337870f45aJim Millerpublic class FingerprintManager {
5708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private static final String TAG = "FingerprintManager";
58d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    private static final boolean DEBUG = true;
5908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private static final int MSG_ENROLL_RESULT = 100;
60a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final int MSG_ACQUIRED = 101;
61f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
62f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_AUTHENTICATION_FAILED = 103;
63f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_ERROR = 104;
64f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_REMOVED = 105;
6540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    private static final int MSG_ENUMERATED = 106;
6608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
67ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
68ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // Error messages from fingerprint hardware during initilization, enrollment, authentication or
69ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // removal. Must agree with the list in fingerprint.h
70ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
7108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
72ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
73ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The hardware is unavailable. Try again later.
74ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
7508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
76ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
77ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
78ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned when the sensor was unable to process the current image.
79ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
80a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2;
81ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
82ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
83ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned when the current request has been running too long. This is intended to
84ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * prevent programs from waiting for the fingerprint sensor indefinitely. The timeout is
85ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * platform and sensor-specific, but is generally on the order of 30 seconds.
86ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
8708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
88ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
89ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
90ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned for operations like enrollment; the operation cannot be completed
91ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * because there's not enough storage remaining to complete the operation.
92ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
9308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
94ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
95ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
96ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The operation was canceled because the fingerprint sensor is unavailable. For example,
97ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * this may happen when the user is switched, the device is locked or another pending operation
98ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * prevents or disables it.
99ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ERROR_CANCELED = 5;
101ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
102ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
103ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The {@link FingerprintManager#remove(Fingerprint, RemovalCallback)} call failed. Typically
104ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * this will happen when the provided fingerprint id was incorrect.
105ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
106ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
107ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
108ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6;
109ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
110fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller   /**
111fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * The operation was canceled because the API is locked out due to too many attempts.
112fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     */
113fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    public static final int FINGERPRINT_ERROR_LOCKOUT = 7;
114fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
115ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
116ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Hardware vendors may extend this list if there are conditions that do not fall under one of
117ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * the above categories. Vendors are responsible for providing error strings for these errors.
118f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @hide
119ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
12040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    public static final int FINGERPRINT_ERROR_VENDOR = 8;
12140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    /**
12240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * @hide
12340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     */
1249f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000;
12508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
126ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
127ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // Image acquisition messages. Must agree with those in fingerprint.h
128ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
129ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
130ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
131ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The image acquired was good.
132ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
133a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_GOOD = 0;
134ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
135ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
136ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Only a partial fingerprint image was detected. During enrollment, the user should be
137ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * informed on what needs to happen to resolve this problem, e.g. "press firmly on sensor."
138ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
139a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1;
140ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
141ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
142ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was too noisy to process due to a detected condition (i.e. dry skin) or
143ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * a possibly dirty sensor (See {@link #FINGERPRINT_ACQUIRED_IMAGER_DIRTY}).
144ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
145a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2;
146ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
147ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
148ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was too noisy due to suspected or detected dirt on the sensor.
149ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * For example, it's reasonable return this after multiple
150ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * {@link #FINGERPRINT_ACQUIRED_INSUFFICIENT} or actual detection of dirt on the sensor
151ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * (stuck pixels, swaths, etc.). The user is expected to take action to clean the sensor
152ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * when this is returned.
153ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3;
155ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
156ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
157ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was unreadable due to lack of motion. This is most appropriate for
158ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * linear array sensors that require a swipe motion.
159ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4;
161ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
162ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
163ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was incomplete due to quick motion. While mostly appropriate for
164ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * linear array sensors,  this could also happen if the finger was moved during acquisition.
165ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The user should be asked to move the finger slower (linear) or leave the finger on the sensor
166ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * longer.
167ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5;
169ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
170ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
171ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Hardware vendors may extend this list if there are conditions that do not fall under one of
172ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * the above categories. Vendors are responsible for providing error strings for these errors.
173f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @hide
174ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
17540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    public static final int FINGERPRINT_ACQUIRED_VENDOR = 6;
17640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    /**
17740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * @hide
17840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     */
1799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
180a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
18108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private IFingerprintService mService;
182d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    private Context mContext;
183a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private IBinder mToken = new Binder();
1849f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private AuthenticationCallback mAuthenticationCallback;
1859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private EnrollmentCallback mEnrollmentCallback;
1869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private RemovalCallback mRemovalCallback;
18740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    private EnumerateCallback mEnumerateCallback;
1889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private CryptoObject mCryptoObject;
1899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private Fingerprint mRemovalFingerprint;
190f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private Handler mHandler;
191ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
192ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private class OnEnrollCancelListener implements OnCancelListener {
193ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        @Override
194ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onCancel() {
195fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            cancelEnrollment();
196ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
197ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
198ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
199ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private class OnAuthenticationCancelListener implements OnCancelListener {
200ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        private CryptoObject mCrypto;
201ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
202ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public OnAuthenticationCancelListener(CryptoObject crypto) {
203ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mCrypto = crypto;
204ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
205ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
206ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        @Override
207ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onCancel() {
208ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            cancelAuthentication(mCrypto);
209ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
210ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
21108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
2129f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
213ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * A wrapper class for the crypto objects supported by FingerprintManager. Currently the
214b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller     * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
2159f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
216f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    public static final class CryptoObject {
217ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
218b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Signature signature) {
219f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = signature;
220ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
221ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
222b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Cipher cipher) {
223f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = cipher;
224b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        }
225b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller
226b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Mac mac) {
227f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = mac;
228ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
229ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
230ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
231ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Get {@link Signature} object.
232ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return {@link Signature} object or null if this doesn't contain one.
233ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
234f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Signature getSignature() {
235f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Signature ? (Signature) mCrypto : null;
236f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
237ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
238ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
239ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Get {@link Cipher} object.
240ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return {@link Cipher} object or null if this doesn't contain one.
241ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
242f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Cipher getCipher() {
243f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Cipher ? (Cipher) mCrypto : null;
244f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
245ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
246ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
247b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         * Get {@link Mac} object.
248b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         * @return {@link Mac} object or null if this doesn't contain one.
249b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         */
250f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Mac getMac() {
251f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Mac ? (Mac) mCrypto : null;
252f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
253b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller
254b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        /**
255ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @hide
256ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return the opId associated with this object or 0 if none
257ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
258ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public long getOpId() {
259f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto != null ?
260f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0;
261ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
262ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
263f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private final Object mCrypto;
26408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    };
26508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
2669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
2679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
268f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     *     CancellationSignal, int, AuthenticationCallback, Handler)}.
2699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
270748bc36f2eebfdc67520c5025b48fefdfd8d7c01Jim Miller    public static class AuthenticationResult {
2719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private Fingerprint mFingerprint;
2729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private CryptoObject mCryptoObject;
273837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller        private int mUserId;
2749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
275f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        /**
276f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * Authentication result
277f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         *
278f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param crypto the crypto object
279f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param fingerprint the recognized fingerprint data, if allowed.
280f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @hide
281f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         */
282837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller        public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId) {
2839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mCryptoObject = crypto;
2849f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mFingerprint = fingerprint;
285837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller            mUserId = userId;
286ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
2879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
2889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
2899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Obtain the crypto object associated with this transaction
2909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
291f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         *     CancellationSignal, int, AuthenticationCallback, Handler)}.
2929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
2939f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public CryptoObject getCryptoObject() { return mCryptoObject; }
2949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
2959f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
296ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Obtain the Fingerprint associated with this operation. Applications are strongly
297ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * discouraged from associating specific fingers with specific applications or operations.
298ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         *
2999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @hide
3009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
3019f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public Fingerprint getFingerprint() { return mFingerprint; }
302837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller
303837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller        /**
304837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller         * Obtain the userId for which this fingerprint was authenticated.
305837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller         * @hide
306837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller         */
307837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller        public int getUserId() { return mUserId; }
3089f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
309ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
31006e658f324a937bec1c5ddbe9c3100c3d2fec371Jim Miller    /**
3119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
312f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link
313ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * FingerprintManager#authenticate(CryptoObject, CancellationSignal,
314f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
315ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * fingerprint events.
31606e658f324a937bec1c5ddbe9c3100c3d2fec371Jim Miller     */
3179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class AuthenticationCallback {
3189f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3199f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when an unrecoverable error has been encountered and the operation is complete.
3209f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * No further callbacks will be made on this object.
321f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param errorCode An integer identifying the error message
322ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString A human-readable error string that can be shown in UI
3239f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
324f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationError(int errorCode, CharSequence errString) { }
32508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3269f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
327ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a recoverable error has been encountered during authentication. The help
3289f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * string is provided to give the user guidance for what went wrong, such as
3299f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Sensor dirty, please clean it."
330f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param helpCode An integer identifying the error message
331ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpString A human-readable string that can be shown in UI
3329f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
333f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }
33408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3359f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when a fingerprint is recognized.
337ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param result An object containing authentication-related data
3389f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
339ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onAuthenticationSucceeded(AuthenticationResult result) { }
340ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
341ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
342ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a fingerprint is valid but not recognized.
343ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
344ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onAuthenticationFailed() { }
3454cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi
3464cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi        /**
3474cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         * Called when a fingerprint image has been acquired, but wasn't processed yet.
3484cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         *
3494cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants
3504cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         * @hide
3514cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         */
3524cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi        public void onAuthenticationAcquired(int acquireInfo) {}
3539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
35408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
3569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback,
3579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * CancellationSignal, int). Users of {@link #FingerprintManager()}
3589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * must provide an implementation of this to {@link FingerprintManager#enroll(long,
359f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events.
360ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
361ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
3629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
3639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class EnrollmentCallback {
3649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when an unrecoverable error has been encountered and the operation is complete.
3669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * No further callbacks will be made on this object.
367ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errMsgId An integer identifying the error message
368ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString A human-readable error string that can be shown in UI
3699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
370ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentError(int errMsgId, CharSequence errString) { }
371a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
3729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
373ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a recoverable error has been encountered during enrollment. The help
3749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * string is provided to give the user guidance for what went wrong, such as
3759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Sensor dirty, please clean it" or what they need to do next, such as
3769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Touch sensor again."
377ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpMsgId An integer identifying the error message
378ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpString A human-readable string that can be shown in UI
3799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
380ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { }
38108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called as each enrollment step progresses. Enrollment is considered complete when
384ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * remaining reaches 0. This function will not be called if enrollment fails. See
3859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
386ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param remaining The number of remaining steps
3879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
388ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentProgress(int remaining) { }
3899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
39008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
3929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#remove(int). Users of
3939f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link #FingerprintManager()} may optionally provide an implementation of this to
3949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to
3959f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * fingerprint template removal events.
396ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
397ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
3989f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
3999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class RemovalCallback {
4009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
4019f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when the given fingerprint can't be removed.
402ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param fp The fingerprint that the call attempted to remove
403ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errMsgId An associated error message id
404ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString An error message indicating why the fingerprint id can't be removed
4059f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
406ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { }
4079f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
4089f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
4099f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when a given fingerprint is successfully removed.
4109f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @param fingerprint the fingerprint template that was removed.
4119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
412ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onRemovalSucceeded(Fingerprint fingerprint) { }
41308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    };
41408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
41508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
41640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * Callback structure provided to {@link FingerprintManager#enumerate(int). Users of
41740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * {@link #FingerprintManager()} may optionally provide an implementation of this to
41840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * {@link FingerprintManager#enumerate(int, int, EnumerateCallback)} for listening to
41940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * fingerprint template removal events.
42040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     *
42140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * @hide
42240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     */
42340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    public static abstract class EnumerateCallback {
42440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        /**
42540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller         * Called when the given fingerprint can't be removed.
42640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller         * @param errMsgId An associated error message id
42740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller         * @param errString An error message indicating why the fingerprint id can't be removed
42840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller         */
42940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void onEnumerateError(int errMsgId, CharSequence errString) { }
43040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller
43140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        /**
43240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller         * Called when a given fingerprint is successfully removed.
43340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller         * @param fingerprint the fingerprint template that was removed.
43440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller         */
43540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void onEnumerate(Fingerprint fingerprint) { }
43640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    };
43740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller
43840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    /**
4393a464785088e7fd206666f640912729533948ce8Jorim Jaggi     * @hide
4403a464785088e7fd206666f640912729533948ce8Jorim Jaggi     */
4413a464785088e7fd206666f640912729533948ce8Jorim Jaggi    public static abstract class LockoutResetCallback {
4423a464785088e7fd206666f640912729533948ce8Jorim Jaggi
4433a464785088e7fd206666f640912729533948ce8Jorim Jaggi        /**
4443a464785088e7fd206666f640912729533948ce8Jorim Jaggi         * Called when lockout period expired and clients are allowed to listen for fingerprint
4453a464785088e7fd206666f640912729533948ce8Jorim Jaggi         * again.
4463a464785088e7fd206666f640912729533948ce8Jorim Jaggi         */
4473a464785088e7fd206666f640912729533948ce8Jorim Jaggi        public void onLockoutReset() { }
4483a464785088e7fd206666f640912729533948ce8Jorim Jaggi    };
4493a464785088e7fd206666f640912729533948ce8Jorim Jaggi
4503a464785088e7fd206666f640912729533948ce8Jorim Jaggi    /**
451ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Request authentication of a crypto object. This call warms up the fingerprint hardware
452ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * and starts scanning for a fingerprint. It terminates when
4539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
4545f69ca3be3005fd127c82f503d0692f807729688Jim Miller     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
4559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * which point the object is no longer valid. The operation can be canceled by using the
4569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * provided cancel object.
457d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller     *
4589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param crypto object associated with the call or null if none required.
4599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param cancel an object that can be used to cancel authentication
460ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @param flags optional flags; should be 0
461f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param callback an object to receive authentication events
462f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param handler an optional handler to handle callback events
463e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *
464e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     * @throws IllegalArgumentException if the crypto operation is not supported or is not backed
465e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *         by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
466e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *         facility</a>.
467e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     * @throws IllegalStateException if the crypto primitive is not initialized.
468d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller     */
469f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
470ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
471f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
472f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId());
473ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    }
474ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi
475ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    /**
476f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * Use the provided handler thread for events.
477f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param handler
478f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     */
479f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private void useHandler(Handler handler) {
480f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        if (handler != null) {
481f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler = new MyHandler(handler.getLooper());
482f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        } else if (mHandler.getLooper() != mContext.getMainLooper()){
483f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler = new MyHandler(mContext.getMainLooper());
484f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
485f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    }
486f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
487f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    /**
488f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * Per-user version
489ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi     * @hide
490ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi     */
491f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
492ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
493f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
4949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (callback == null) {
4959f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            throw new IllegalArgumentException("Must supply an authentication callback");
4969f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
4979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
498ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (cancel != null) {
499ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (cancel.isCanceled()) {
500ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                Log.w(TAG, "authentication already canceled");
501ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return;
502ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            } else {
503ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
504ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
505ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
5069f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
5079f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
508f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            useHandler(handler);
5099f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mAuthenticationCallback = callback;
5109f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mCryptoObject = crypto;
511ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            long sessionId = crypto != null ? crypto.getOpId() : 0;
5124af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
5134af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                    mContext.getOpPackageName());
5149f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
515ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception while authenticating: ", e);
516ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
517ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // Though this may not be a hardware issue, it will cause apps to give up or try
518ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // again later.
519ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
52040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
521ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
5229f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
523d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    }
524d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller
525d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    /**
5269f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Request fingerprint enrollment. This call warms up the fingerprint hardware
5279f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
5289f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback} object. It terminates when
5299f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or
5309f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at
5319f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * which point the object is no longer valid. The operation can be canceled by using the
5329f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * provided cancel object.
533fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * @param token a unique token provided by a recent creation or verification of device
534fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * credentials (e.g. pin, pattern or password).
5359f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param cancel an object that can be used to cancel enrollment
5369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param flags optional flags
537a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri     * @param userId the user to whom this fingerprint will belong to
538f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param callback an object to receive enrollment events
539ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
54008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
541f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
542f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    public void enroll(byte [] token, CancellationSignal cancel, int flags,
543a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri            int userId, EnrollmentCallback callback) {
544d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        if (userId == UserHandle.USER_CURRENT) {
545d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            userId = getCurrentUserId();
546d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        }
5479f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (callback == null) {
5489f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            throw new IllegalArgumentException("Must supply an enrollment callback");
54908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
5509f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
551ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (cancel != null) {
552ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (cancel.isCanceled()) {
553ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                Log.w(TAG, "enrollment already canceled");
554ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return;
555ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            } else {
556fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                cancel.setOnCancelListener(new OnEnrollCancelListener());
557ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
558ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
5599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
56008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) try {
5619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mEnrollmentCallback = callback;
562cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            mService.enroll(mToken, token, userId, mServiceReceiver, flags,
563cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    mContext.getOpPackageName());
564ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
565ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception in enroll: ", e);
566ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
567ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // Though this may not be a hardware issue, it will cause apps to give up or try
568ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // again later.
569ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
57040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
571ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
572ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
573ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
574ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
575ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
576ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Requests a pre-enrollment auth token to tie enrollment to the confirmation of
577ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * existing device credentials (e.g. pin/pattern/password).
578ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
579ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
580f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
581ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public long preEnroll() {
582ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        long result = 0;
583ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
584ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            result = mService.preEnroll(mToken);
58508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } catch (RemoteException e) {
586c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
58708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
588ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        return result;
58908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
59008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
59108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
592e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     * Finishes enrollment and cancels the current auth token.
593e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     * @hide
594e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     */
595e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    @RequiresPermission(MANAGE_FINGERPRINT)
596e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    public int postEnroll() {
597e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        int result = 0;
598e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        if (mService != null) try {
599e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            result = mService.postEnroll(mToken);
600e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        } catch (RemoteException e) {
601c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
602e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        }
603e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        return result;
604e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    }
605e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy
606e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    /**
607d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * Sets the active user. This is meant to be used to select the current profile for enrollment
608d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * to allow separate enrolled fingers for a work profile
609d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @param userId
610d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @hide
611d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     */
612d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    @RequiresPermission(MANAGE_FINGERPRINT)
613d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    public void setActiveUser(int userId) {
614d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        if (mService != null) try {
615d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            mService.setActiveUser(userId);
616d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        } catch (RemoteException e) {
617c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
618d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        }
619d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    }
620d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri
621d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    /**
6229f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Remove given fingerprint template from fingerprint hardware and/or protected storage.
6239f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param fp the fingerprint item to remove
624a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri     * @param userId the user who this fingerprint belongs to
6259f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param callback an optional callback to verify that fingerprint templates have been
626ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * successfully removed. May be null of no callback is required.
627ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
6289f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
62908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
630f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
631a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri    public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
6329f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
6339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mRemovalCallback = callback;
6349f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mRemovalFingerprint = fp;
6358f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller            mService.remove(mToken, fp.getFingerId(), fp.getGroupId(), userId, mServiceReceiver);
6369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
637ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception in remove: ", e);
638ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
639ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE,
64040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
64140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            }
64240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        }
64340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    }
64440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller
64540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    /**
64640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * Enumerate all fingerprint templates stored in hardware and/or protected storage.
64740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * @param userId the user who this fingerprint belongs to
64840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * @param callback an optional callback to verify that fingerprint templates have been
64940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * successfully removed. May be null of no callback is required.
65040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     *
65140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     * @hide
65240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller     */
65340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
65440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    public void enumerate(int userId, @NonNull EnumerateCallback callback) {
65540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        if (mService != null) try {
65640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            mEnumerateCallback = callback;
65740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            mService.enumerate(mToken, userId, mServiceReceiver);
65840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        } catch (RemoteException e) {
65940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            Log.w(TAG, "Remote exception in enumerate: ", e);
66040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            if (callback != null) {
66140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                callback.onEnumerateError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
66240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */));
663ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
66408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
66508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
66608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
66708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
6689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Renames the given fingerprint template
6699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param fpId the fingerprint id
670a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri     * @param userId the user who this fingerprint belongs to
6719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param newName the new name
672ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
6739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
67408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
675f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
676a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri    public void rename(int fpId, int userId, String newName) {
6779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        // Renames the given fpId
67808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) {
67908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            try {
680a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri                mService.rename(fpId, userId, newName);
68108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            } catch (RemoteException e) {
682c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
68308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            }
684a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        } else {
6859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.w(TAG, "rename(): Service not connected!");
68608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
68708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
68808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
6899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
6909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Obtain the list of enrolled fingerprints templates.
6919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @return list of current fingerprint items
692ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
693ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
6949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
695f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6962aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public List<Fingerprint> getEnrolledFingerprints(int userId) {
6979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
6984af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
69908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } catch (RemoteException e) {
700c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
70108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
7029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        return null;
70308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
70408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
70508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
7062aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Obtain the list of enrolled fingerprints templates.
7072aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return list of current fingerprint items
708ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
7099f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
71008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
711f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
7122aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public List<Fingerprint> getEnrolledFingerprints() {
7132aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        return getEnrolledFingerprints(UserHandle.myUserId());
7142aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    }
7152aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi
7162aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    /**
7172aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Determine if there is at least one fingerprint enrolled.
7182aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     *
7192aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return true if at least one fingerprint is enrolled, false otherwise
7202aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     */
721f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
7222aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public boolean hasEnrolledFingerprints() {
7232aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        if (mService != null) try {
72433fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri            return mService.hasEnrolledFingerprints(
72533fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri                    UserHandle.myUserId(), mContext.getOpPackageName());
72633fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri        } catch (RemoteException e) {
727c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
72833fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri        }
72933fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri        return false;
73033fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri    }
73133fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri
73233fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri    /**
73333fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri     * @hide
73433fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri     */
73533fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri    @RequiresPermission(allOf = {
73633fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri            USE_FINGERPRINT,
73733fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri            INTERACT_ACROSS_USERS})
73833fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri    public boolean hasEnrolledFingerprints(int userId) {
73933fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri        if (mService != null) try {
74033fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri            return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
7412aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        } catch (RemoteException e) {
742c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
7432aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        }
7442aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        return false;
7452aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    }
7462aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi
7472aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    /**
7482aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Determine if fingerprint hardware is present and functional.
7492aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     *
7502aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return true if hardware is present and functional, false otherwise.
7512aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     */
752f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
7539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public boolean isHardwareDetected() {
75408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) {
75508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            try {
7569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                long deviceId = 0; /* TODO: plumb hardware id to FPMS */
7574af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
75808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            } catch (RemoteException e) {
759c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
76008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            }
76108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } else {
7629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
763a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
7649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        return false;
765a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
766a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
7674d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    /**
7684d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * Retrieves the authenticator token for binding keys to the lifecycle
769da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He     * of the calling user's fingerprints. Used only by internal clients.
7704d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     *
7714d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * @hide
7724d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     */
7734d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    public long getAuthenticatorId() {
7744d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        if (mService != null) {
7754d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            try {
7764af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return mService.getAuthenticatorId(mContext.getOpPackageName());
7774d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            } catch (RemoteException e) {
778c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
7794d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            }
7804d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        } else {
7814d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            Log.w(TAG, "getAuthenticatorId(): Service not connected!");
7824d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        }
7834d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        return 0;
7844d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    }
7854d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales
786e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller    /**
787e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     * Reset the lockout timer when asked to do so by keyguard.
788e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     *
789e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     * @param token an opaque token returned by password confirmation.
790e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     *
791e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     * @hide
792e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     */
793e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller    public void resetTimeout(byte[] token) {
794e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        if (mService != null) {
795e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            try {
796e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller                mService.resetTimeout(token);
797e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            } catch (RemoteException e) {
798c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
799e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            }
800e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        } else {
8013a464785088e7fd206666f640912729533948ce8Jorim Jaggi            Log.w(TAG, "resetTimeout(): Service not connected!");
8023a464785088e7fd206666f640912729533948ce8Jorim Jaggi        }
8033a464785088e7fd206666f640912729533948ce8Jorim Jaggi    }
8043a464785088e7fd206666f640912729533948ce8Jorim Jaggi
8053a464785088e7fd206666f640912729533948ce8Jorim Jaggi    /**
8063a464785088e7fd206666f640912729533948ce8Jorim Jaggi     * @hide
8073a464785088e7fd206666f640912729533948ce8Jorim Jaggi     */
8083a464785088e7fd206666f640912729533948ce8Jorim Jaggi    public void addLockoutResetCallback(final LockoutResetCallback callback) {
8093a464785088e7fd206666f640912729533948ce8Jorim Jaggi        if (mService != null) {
8103a464785088e7fd206666f640912729533948ce8Jorim Jaggi            try {
8115e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
8123a464785088e7fd206666f640912729533948ce8Jorim Jaggi                mService.addLockoutResetCallback(
8133a464785088e7fd206666f640912729533948ce8Jorim Jaggi                        new IFingerprintServiceLockoutResetCallback.Stub() {
8143a464785088e7fd206666f640912729533948ce8Jorim Jaggi
8153a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    @Override
81657e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                    public void onLockoutReset(long deviceId, IRemoteCallback serverCallback)
81757e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                            throws RemoteException {
81857e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                        try {
81957e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                            final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
82057e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                                    PowerManager.PARTIAL_WAKE_LOCK, "lockoutResetCallback");
82157e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                            wakeLock.acquire();
82257e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                            mHandler.post(() -> {
8235e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                try {
8245e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                    callback.onLockoutReset();
8255e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                } finally {
8265e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                    wakeLock.release();
8275e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                }
82857e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                            });
82957e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                        } finally {
83057e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                            serverCallback.sendResult(null /* data */);
83157e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                        }
8323a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    }
8333a464785088e7fd206666f640912729533948ce8Jorim Jaggi                });
8343a464785088e7fd206666f640912729533948ce8Jorim Jaggi            } catch (RemoteException e) {
835c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
8363a464785088e7fd206666f640912729533948ce8Jorim Jaggi            }
8373a464785088e7fd206666f640912729533948ce8Jorim Jaggi        } else {
8383a464785088e7fd206666f640912729533948ce8Jorim Jaggi            Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
839e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        }
840e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller    }
841e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller
84224e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin    private class MyHandler extends Handler {
84324e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        private MyHandler(Context context) {
84424e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin            super(context.getMainLooper());
84524e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        }
84624e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin
847f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private MyHandler(Looper looper) {
848f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            super(looper);
849f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
850f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
851e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        @Override
8529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void handleMessage(android.os.Message msg) {
8539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            switch(msg.what) {
8549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ENROLL_RESULT:
8559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
8569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
8579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ACQUIRED:
85840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */,
85940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                            msg.arg2 /* vendorCode */);
8609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
861f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                case MSG_AUTHENTICATION_SUCCEEDED:
862837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller                    sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */);
863f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    break;
864f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                case MSG_AUTHENTICATION_FAILED:
865f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    sendAuthenticatedFailed();
8669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
8679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ERROR:
86840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */,
86940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                            msg.arg2 /* vendorCode */);
8709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
8719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_REMOVED:
8729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
8739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                            msg.arg2 /* groupId */);
87440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                case MSG_ENUMERATED:
87540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    sendEnumeratedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
87640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                            msg.arg2 /* groupId */);
8779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
87808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
8799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
8809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
8819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mRemovalCallback != null) {
8829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                int reqFingerId = mRemovalFingerprint.getFingerId();
8839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                int reqGroupId = mRemovalFingerprint.getGroupId();
8848f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller                if (reqFingerId != 0 && fingerId != 0  &&  fingerId != reqFingerId) {
8859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
8868f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller                    return;
8879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
8881adb4a7693406e7f984d7b1512e0e6aa40aa40e2Jim Miller                if (groupId != reqGroupId) {
8899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
8908f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller                    return;
8919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
892f86f986728b5844a48e2e7bbd4927d2f5500c682Ricky Wai                mRemovalCallback.onRemovalSucceeded(new Fingerprint(null, groupId, fingerId,
893f86f986728b5844a48e2e7bbd4927d2f5500c682Ricky Wai                        deviceId));
894a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
895a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
896a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
89740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        private void sendEnumeratedResult(long deviceId, int fingerId, int groupId) {
89840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            if (mEnumerateCallback != null) {
89940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                mEnumerateCallback.onEnumerate(new Fingerprint(null, groupId, fingerId, deviceId));
90040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            }
90140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        }
90240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller
90340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        private void sendErrorResult(long deviceId, int errMsgId, int vendorCode) {
90440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            // emulate HAL 2.1 behavior and send real errMsgId
90540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            final int clientErrMsgId = errMsgId == FINGERPRINT_ERROR_VENDOR
90640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    ? (vendorCode + FINGERPRINT_ERROR_VENDOR_BASE) : errMsgId;
9079f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
90840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                mEnrollmentCallback.onEnrollmentError(clientErrMsgId,
90940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                        getErrorString(errMsgId, vendorCode));
9109f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mAuthenticationCallback != null) {
91140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                mAuthenticationCallback.onAuthenticationError(clientErrMsgId,
91240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                        getErrorString(errMsgId, vendorCode));
9139f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mRemovalCallback != null) {
91440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                mRemovalCallback.onRemovalError(mRemovalFingerprint, clientErrMsgId,
91540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                        getErrorString(errMsgId, vendorCode));
91640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            } else if (mEnumerateCallback != null) {
91740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                mEnumerateCallback.onEnumerateError(clientErrMsgId,
91840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                        getErrorString(errMsgId, vendorCode));
9199f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
9209f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9219f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
9229f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendEnrollResult(Fingerprint fp, int remaining) {
9239f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
9249f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mEnrollmentCallback.onEnrollmentProgress(remaining);
9259f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
9269f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9279f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
928837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller        private void sendAuthenticatedSucceeded(Fingerprint fp, int userId) {
9299f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mAuthenticationCallback != null) {
930837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller                final AuthenticationResult result =
931837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller                        new AuthenticationResult(mCryptoObject, fp, userId);
932f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                mAuthenticationCallback.onAuthenticationSucceeded(result);
933f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            }
934f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
935f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
936f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private void sendAuthenticatedFailed() {
937f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            if (mAuthenticationCallback != null) {
938f501b58de8f467a80fef49c704555781bc61ea6fJim Miller               mAuthenticationCallback.onAuthenticationFailed();
9399f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
9409f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9419f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
94240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        private void sendAcquiredResult(long deviceId, int acquireInfo, int vendorCode) {
9434cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            if (mAuthenticationCallback != null) {
9444cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi                mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
9454cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            }
94640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            final String msg = getAcquiredString(acquireInfo, vendorCode);
9474cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            if (msg == null) {
9484cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi                return;
9494cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            }
95040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            // emulate HAL 2.1 behavior and send real acquiredInfo
95140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            final int clientInfo = acquireInfo == FINGERPRINT_ACQUIRED_VENDOR
95240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    ? (vendorCode + FINGERPRINT_ACQUIRED_VENDOR_BASE) : acquireInfo;
9539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
95440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                mEnrollmentCallback.onEnrollmentHelp(clientInfo, msg);
9559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mAuthenticationCallback != null) {
95640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                mAuthenticationCallback.onAuthenticationHelp(clientInfo, msg);
9579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
9589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
960ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
961ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    /**
962ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller     * @hide
963ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller     */
9649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public FingerprintManager(Context context, IFingerprintService service) {
9659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        mContext = context;
9669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        mService = service;
9679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService == null) {
9689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Slog.v(TAG, "FingerprintManagerService was null");
9699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
97024e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        mHandler = new MyHandler(context);
9719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    }
9729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
9739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private int getCurrentUserId() {
9749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        try {
975dc589ac82b5fe2063f4cfd94c8ae26d43d5420a0Sudheer Shanka            return ActivityManager.getService().getCurrentUser().id;
9769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
977c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
978ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
979ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    }
980ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
981fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    private void cancelEnrollment() {
982ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
983ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mService.cancelEnrollment(mToken);
984ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
985c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
986ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
987ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
988ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
989ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private void cancelAuthentication(CryptoObject cryptoObject) {
990ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
9914af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            mService.cancelAuthentication(mToken, mContext.getOpPackageName());
992ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
993c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
994ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
995ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
996ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
99740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    private String getErrorString(int errMsg, int vendorCode) {
998ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        switch (errMsg) {
999ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
1000ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
1001ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_unable_to_process);
1002ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_HW_UNAVAILABLE:
1003ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
1004ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_hw_not_available);
1005ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_NO_SPACE:
1006ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
1007ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_no_space);
1008ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_TIMEOUT:
1009fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout);
1010fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            case FINGERPRINT_ERROR_CANCELED:
1011fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled);
1012fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            case FINGERPRINT_ERROR_LOCKOUT:
1013fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout);
101440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            case FINGERPRINT_ERROR_VENDOR: {
1015ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    String[] msgArray = mContext.getResources().getStringArray(
1016ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                            com.android.internal.R.array.fingerprint_error_vendor);
101740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    if (vendorCode < msgArray.length) {
101840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                        return msgArray[vendorCode];
1019ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    }
10209f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
1021ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
102240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        Slog.w(TAG, "Invalid error message: " + errMsg + ", " + vendorCode);
102340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        return null;
1024ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    }
102599d6019bead4705b7e126e65b856d538417d4934Jim Miller
102640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    private String getAcquiredString(int acquireInfo, int vendorCode) {
1027ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        switch (acquireInfo) {
1028ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_GOOD:
1029ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return null;
1030ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_PARTIAL:
1031ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
1032ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_partial);
1033ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_INSUFFICIENT:
1034ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
1035ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_insufficient);
1036ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
1037ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
1038ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_imager_dirty);
1039ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_TOO_SLOW:
1040ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
1041ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_too_slow);
1042ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_TOO_FAST:
1043ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
1044ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_too_fast);
104540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            case FINGERPRINT_ACQUIRED_VENDOR: {
1046ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    String[] msgArray = mContext.getResources().getStringArray(
1047ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                            com.android.internal.R.array.fingerprint_acquired_vendor);
104840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    if (vendorCode < msgArray.length) {
104940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                        return msgArray[vendorCode];
1050ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    }
10519f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
105299d6019bead4705b7e126e65b856d538417d4934Jim Miller        }
105340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        Slog.w(TAG, "Invalid acquired message: " + acquireInfo + ", " + vendorCode);
105440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        return null;
105599d6019bead4705b7e126e65b856d538417d4934Jim Miller    }
10569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
10579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
10589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
1059f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
10609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
10619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
10629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
10639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
10649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
1065f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
106640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void onAcquired(long deviceId, int acquireInfo, int vendorCode) {
106740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, vendorCode, deviceId).sendToTarget();
10689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
10699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
1070f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
1071837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller        public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {
1072837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();
1073f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
1074f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
1075f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
1076f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationFailed(long deviceId) {
1077436ab6a91d64ef6036c67bb361d807e398fb2c4cFelipe Leme            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();
10789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
10799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
1080f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
108140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void onError(long deviceId, int error, int vendorCode) {
108240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            mHandler.obtainMessage(MSG_ERROR, error, vendorCode, deviceId).sendToTarget();
10839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
10849f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
1085f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
108640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void onRemoved(long deviceId, int fingerId, int groupId, int remaining) {
108740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            // TODO: propagate remaining
10889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
10899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
109040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller
109140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        @Override // binder call
109240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void onEnumerated(long deviceId, int fingerId, int groupId, int remaining) {
109340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            // TODO: propagate remaining
109440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            mHandler.obtainMessage(MSG_ENUMERATED, fingerId, groupId, deviceId).sendToTarget();
109540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        }
10969f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
10979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
10984d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales}
1099