FingerprintManager.java revision e0943cf5665b3d7b0870debda771032f77db094c
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;
2208fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.app.ActivityManagerNative;
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;
29f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport android.os.Looper;
3008fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.os.RemoteException;
3108fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.os.UserHandle;
32dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubinimport android.security.keystore.AndroidKeyStoreProvider;
3308fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.util.Log;
34a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.util.Slog;
3508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
369f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport java.security.Signature;
37ba67aee02cf864793129976cd8a8a46e60c60577Jim Millerimport java.util.List;
38ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
399f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport javax.crypto.Cipher;
40b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Millerimport javax.crypto.Mac;
419f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
42f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport static android.Manifest.permission.USE_FINGERPRINT;
43f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport static android.Manifest.permission.MANAGE_FINGERPRINT;
44f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
4508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller/**
4608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * A class that coordinates access to the fingerprint hardware.
47ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p>
48ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Use {@link android.content.Context#getSystemService(java.lang.String)}
49ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * with argument {@link android.content.Context#FINGERPRINT_SERVICE} to get
50ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * an instance of this class.
5108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller */
5208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
5308fa40c5cb5229b7969b2a5146855a337870f45aJim Millerpublic class FingerprintManager {
5408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private static final String TAG = "FingerprintManager";
55d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    private static final boolean DEBUG = true;
5608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private static final int MSG_ENROLL_RESULT = 100;
57a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final int MSG_ACQUIRED = 101;
58f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
59f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_AUTHENTICATION_FAILED = 103;
60f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_ERROR = 104;
61f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_REMOVED = 105;
6208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
63ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
64ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // Error messages from fingerprint hardware during initilization, enrollment, authentication or
65ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // removal. Must agree with the list in fingerprint.h
66ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
6708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
68ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
69ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The hardware is unavailable. Try again later.
70ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
7108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
72ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
73ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
74ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned when the sensor was unable to process the current image.
75ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
76a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2;
77ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
78ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
79ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned when the current request has been running too long. This is intended to
80ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * prevent programs from waiting for the fingerprint sensor indefinitely. The timeout is
81ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * platform and sensor-specific, but is generally on the order of 30 seconds.
82ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
8308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
84ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
85ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
86ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned for operations like enrollment; the operation cannot be completed
87ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * because there's not enough storage remaining to complete the operation.
88ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
8908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
90ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
91ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
92ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The operation was canceled because the fingerprint sensor is unavailable. For example,
93ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * this may happen when the user is switched, the device is locked or another pending operation
94ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * prevents or disables it.
95ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
969f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ERROR_CANCELED = 5;
97ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
98ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
99ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The {@link FingerprintManager#remove(Fingerprint, RemovalCallback)} call failed. Typically
100ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * this will happen when the provided fingerprint id was incorrect.
101ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
102ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
103ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
104ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6;
105ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
106fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller   /**
107fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * The operation was canceled because the API is locked out due to too many attempts.
108fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     */
109fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    public static final int FINGERPRINT_ERROR_LOCKOUT = 7;
110fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
111ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
112ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Hardware vendors may extend this list if there are conditions that do not fall under one of
113ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * the above categories. Vendors are responsible for providing error strings for these errors.
114f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @hide
115ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000;
11708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
118ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
119ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // Image acquisition messages. Must agree with those in fingerprint.h
120ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
121ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
122ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
123ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The image acquired was good.
124ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
125a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_GOOD = 0;
126ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
127ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
128ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Only a partial fingerprint image was detected. During enrollment, the user should be
129ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * informed on what needs to happen to resolve this problem, e.g. "press firmly on sensor."
130ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
131a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1;
132ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
133ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
134ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was too noisy to process due to a detected condition (i.e. dry skin) or
135ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * a possibly dirty sensor (See {@link #FINGERPRINT_ACQUIRED_IMAGER_DIRTY}).
136ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
137a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2;
138ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
139ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
140ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was too noisy due to suspected or detected dirt on the sensor.
141ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * For example, it's reasonable return this after multiple
142ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * {@link #FINGERPRINT_ACQUIRED_INSUFFICIENT} or actual detection of dirt on the sensor
143ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * (stuck pixels, swaths, etc.). The user is expected to take action to clean the sensor
144ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * when this is returned.
145ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3;
147ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
148ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
149ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was unreadable due to lack of motion. This is most appropriate for
150ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * linear array sensors that require a swipe motion.
151ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4;
153ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
154ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
155ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was incomplete due to quick motion. While mostly appropriate for
156ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * linear array sensors,  this could also happen if the finger was moved during acquisition.
157ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The user should be asked to move the finger slower (linear) or leave the finger on the sensor
158ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * longer.
159ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5;
161ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
162ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
163ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Hardware vendors may extend this list if there are conditions that do not fall under one of
164ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * the above categories. Vendors are responsible for providing error strings for these errors.
165f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @hide
166ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
168a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
16908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private IFingerprintService mService;
170d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    private Context mContext;
171a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private IBinder mToken = new Binder();
1729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private AuthenticationCallback mAuthenticationCallback;
1739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private EnrollmentCallback mEnrollmentCallback;
1749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private RemovalCallback mRemovalCallback;
1759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private CryptoObject mCryptoObject;
1769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private Fingerprint mRemovalFingerprint;
177f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private Handler mHandler;
178ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
179ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private class OnEnrollCancelListener implements OnCancelListener {
180ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        @Override
181ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onCancel() {
182fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            cancelEnrollment();
183ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
184ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
185ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
186ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private class OnAuthenticationCancelListener implements OnCancelListener {
187ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        private CryptoObject mCrypto;
188ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
189ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public OnAuthenticationCancelListener(CryptoObject crypto) {
190ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mCrypto = crypto;
191ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
192ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
193ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        @Override
194ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onCancel() {
195ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            cancelAuthentication(mCrypto);
196ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
197ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
19808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
1999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
200ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * A wrapper class for the crypto objects supported by FingerprintManager. Currently the
201b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller     * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
2029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
203f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    public static final class CryptoObject {
204ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
205b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Signature signature) {
206f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = signature;
207ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
208ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
209b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Cipher cipher) {
210f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = cipher;
211b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        }
212b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller
213b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Mac mac) {
214f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = mac;
215ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
216ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
217ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
218ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Get {@link Signature} object.
219ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return {@link Signature} object or null if this doesn't contain one.
220ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
221f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Signature getSignature() {
222f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Signature ? (Signature) mCrypto : null;
223f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
224ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
225ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
226ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Get {@link Cipher} object.
227ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return {@link Cipher} object or null if this doesn't contain one.
228ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
229f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Cipher getCipher() {
230f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Cipher ? (Cipher) mCrypto : null;
231f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
232ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
233ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
234b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         * Get {@link Mac} object.
235b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         * @return {@link Mac} object or null if this doesn't contain one.
236b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         */
237f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Mac getMac() {
238f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Mac ? (Mac) mCrypto : null;
239f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
240b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller
241b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        /**
242ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @hide
243ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return the opId associated with this object or 0 if none
244ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
245ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public long getOpId() {
246f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto != null ?
247f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0;
248ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
249ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
250f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private final Object mCrypto;
25108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    };
25208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
2539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
2549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
255f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     *     CancellationSignal, int, AuthenticationCallback, Handler)}.
2569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
2579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final class AuthenticationResult {
2589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private Fingerprint mFingerprint;
2599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private CryptoObject mCryptoObject;
2609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
261f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        /**
262f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * Authentication result
263f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         *
264f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param crypto the crypto object
265f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param fingerprint the recognized fingerprint data, if allowed.
266f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @hide
267f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         */
2689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) {
2699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mCryptoObject = crypto;
2709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mFingerprint = fingerprint;
271ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
2729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
2739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
2749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Obtain the crypto object associated with this transaction
2759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
276f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         *     CancellationSignal, int, AuthenticationCallback, Handler)}.
2779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
2789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public CryptoObject getCryptoObject() { return mCryptoObject; }
2799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
2809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
281ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Obtain the Fingerprint associated with this operation. Applications are strongly
282ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * discouraged from associating specific fingers with specific applications or operations.
283ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         *
2849f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @hide
2859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
2869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public Fingerprint getFingerprint() { return mFingerprint; }
2879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
288ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
28906e658f324a937bec1c5ddbe9c3100c3d2fec371Jim Miller    /**
2909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
291f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link
292ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * FingerprintManager#authenticate(CryptoObject, CancellationSignal,
293f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
294ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * fingerprint events.
29506e658f324a937bec1c5ddbe9c3100c3d2fec371Jim Miller     */
2969f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class AuthenticationCallback {
2979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
2989f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when an unrecoverable error has been encountered and the operation is complete.
2999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * No further callbacks will be made on this object.
300f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param errorCode An integer identifying the error message
301ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString A human-readable error string that can be shown in UI
3029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
303f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationError(int errorCode, CharSequence errString) { }
30408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3059f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
306ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a recoverable error has been encountered during authentication. The help
3079f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * string is provided to give the user guidance for what went wrong, such as
3089f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Sensor dirty, please clean it."
309f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param helpCode An integer identifying the error message
310ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpString A human-readable string that can be shown in UI
3119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
312f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }
31308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3149f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3159f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when a fingerprint is recognized.
316ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param result An object containing authentication-related data
3179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
318ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onAuthenticationSucceeded(AuthenticationResult result) { }
319ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
320ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
321ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a fingerprint is valid but not recognized.
322ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
323ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onAuthenticationFailed() { }
3249f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
32508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3269f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
3279f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback,
3289f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * CancellationSignal, int). Users of {@link #FingerprintManager()}
3299f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * must provide an implementation of this to {@link FingerprintManager#enroll(long,
330f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events.
331ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
332ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
3339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
3349f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class EnrollmentCallback {
3359f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when an unrecoverable error has been encountered and the operation is complete.
3379f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * No further callbacks will be made on this object.
338ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errMsgId An integer identifying the error message
339ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString A human-readable error string that can be shown in UI
3409f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
341ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentError(int errMsgId, CharSequence errString) { }
342a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
3439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
344ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a recoverable error has been encountered during enrollment. The help
3459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * string is provided to give the user guidance for what went wrong, such as
3469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Sensor dirty, please clean it" or what they need to do next, such as
3479f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Touch sensor again."
348ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpMsgId An integer identifying the error message
349ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpString A human-readable string that can be shown in UI
3509f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
351ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { }
35208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called as each enrollment step progresses. Enrollment is considered complete when
355ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * remaining reaches 0. This function will not be called if enrollment fails. See
3569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
357ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param remaining The number of remaining steps
3589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
359ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentProgress(int remaining) { }
3609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
36108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
3639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#remove(int). Users of
3649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link #FingerprintManager()} may optionally provide an implementation of this to
3659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to
3669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * fingerprint template removal events.
367ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
368ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
3699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
3709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class RemovalCallback {
3719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when the given fingerprint can't be removed.
373ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param fp The fingerprint that the call attempted to remove
374ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errMsgId An associated error message id
375ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString An error message indicating why the fingerprint id can't be removed
3769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
377ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { }
3789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
3799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when a given fingerprint is successfully removed.
3819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @param fingerprint the fingerprint template that was removed.
3829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
383ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onRemovalSucceeded(Fingerprint fingerprint) { }
38408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    };
38508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
38608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
387ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Request authentication of a crypto object. This call warms up the fingerprint hardware
388ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * and starts scanning for a fingerprint. It terminates when
3899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
3909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at
3919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * which point the object is no longer valid. The operation can be canceled by using the
3929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * provided cancel object.
393d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller     *
3949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param crypto object associated with the call or null if none required.
3959f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param cancel an object that can be used to cancel authentication
396ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @param flags optional flags; should be 0
397f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param callback an object to receive authentication events
398f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param handler an optional handler to handle callback events
399e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *
400e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     * @throws IllegalArgumentException if the crypto operation is not supported or is not backed
401e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *         by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
402e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *         facility</a>.
403e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     * @throws IllegalStateException if the crypto primitive is not initialized.
404d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller     */
405f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
406ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
407f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
408f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId());
409ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    }
410ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi
411ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    /**
412f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * Use the provided handler thread for events.
413f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param handler
414f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     */
415f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private void useHandler(Handler handler) {
416f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        if (handler != null) {
417f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler = new MyHandler(handler.getLooper());
418f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        } else if (mHandler.getLooper() != mContext.getMainLooper()){
419f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler = new MyHandler(mContext.getMainLooper());
420f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
421f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    }
422f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
423f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    /**
424f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * Per-user version
425ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi     * @hide
426ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi     */
427f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
428ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
429f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
4309f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (callback == null) {
4319f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            throw new IllegalArgumentException("Must supply an authentication callback");
4329f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
4339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
434ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (cancel != null) {
435ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (cancel.isCanceled()) {
436ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                Log.w(TAG, "authentication already canceled");
437ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return;
438ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            } else {
439ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
440ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
441ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
4429f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
4439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
444f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            useHandler(handler);
4459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mAuthenticationCallback = callback;
4469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mCryptoObject = crypto;
447ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            long sessionId = crypto != null ? crypto.getOpId() : 0;
4484af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
4494af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                    mContext.getOpPackageName());
4509f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
451ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception while authenticating: ", e);
452ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
453ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // Though this may not be a hardware issue, it will cause apps to give up or try
454ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // again later.
455ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
456ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
457ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
4589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
459d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    }
460d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller
461d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    /**
4629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Request fingerprint enrollment. This call warms up the fingerprint hardware
4639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
4649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback} object. It terminates when
4659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or
4669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at
4679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * which point the object is no longer valid. The operation can be canceled by using the
4689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * provided cancel object.
469fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * @param token a unique token provided by a recent creation or verification of device
470fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * credentials (e.g. pin, pattern or password).
4719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param cancel an object that can be used to cancel enrollment
4729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param flags optional flags
473f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param callback an object to receive enrollment events
474ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
47508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
476f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
477f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    public void enroll(byte [] token, CancellationSignal cancel, int flags,
478f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            EnrollmentCallback callback) {
4799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (callback == null) {
4809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            throw new IllegalArgumentException("Must supply an enrollment callback");
48108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
4829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
483ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (cancel != null) {
484ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (cancel.isCanceled()) {
485ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                Log.w(TAG, "enrollment already canceled");
486ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return;
487ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            } else {
488fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                cancel.setOnCancelListener(new OnEnrollCancelListener());
489ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
490ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
4919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
49208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) try {
4939f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mEnrollmentCallback = callback;
494fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            mService.enroll(mToken, token, getCurrentUserId(), mServiceReceiver, flags);
495ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
496ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception in enroll: ", e);
497ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
498ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // Though this may not be a hardware issue, it will cause apps to give up or try
499ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // again later.
500ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
501ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
502ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
503ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
504ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
505ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
506ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
507ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Requests a pre-enrollment auth token to tie enrollment to the confirmation of
508ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * existing device credentials (e.g. pin/pattern/password).
509ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
510ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
511f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
512ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public long preEnroll() {
513ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        long result = 0;
514ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
515ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            result = mService.preEnroll(mToken);
51608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } catch (RemoteException e) {
517ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception in enroll: ", e);
51808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
519ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        return result;
52008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
52108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
52208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
523e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     * Finishes enrollment and cancels the current auth token.
524e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     * @hide
525e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     */
526e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    @RequiresPermission(MANAGE_FINGERPRINT)
527e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    public int postEnroll() {
528e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        int result = 0;
529e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        if (mService != null) try {
530e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            result = mService.postEnroll(mToken);
531e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        } catch (RemoteException e) {
532e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            Log.w(TAG, "Remote exception in post enroll: ", e);
533e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        }
534e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        return result;
535e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    }
536e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy
537e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    /**
5389f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Remove given fingerprint template from fingerprint hardware and/or protected storage.
5399f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param fp the fingerprint item to remove
5409f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param callback an optional callback to verify that fingerprint templates have been
541ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * successfully removed. May be null of no callback is required.
542ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
5439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
54408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
545f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
5469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public void remove(Fingerprint fp, RemovalCallback callback) {
5479f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
5489f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mRemovalCallback = callback;
5499f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mRemovalFingerprint = fp;
550ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mService.remove(mToken, fp.getFingerId(), getCurrentUserId(), mServiceReceiver);
5519f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
552ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception in remove: ", e);
553ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
554ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE,
555ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
556ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
55708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
55808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
55908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
56008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
5619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Renames the given fingerprint template
5629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param fpId the fingerprint id
5639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param newName the new name
564ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
5659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
56608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
567f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
5689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public void rename(int fpId, String newName) {
5699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        // Renames the given fpId
57008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) {
57108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            try {
5729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mService.rename(fpId, getCurrentUserId(), newName);
57308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            } catch (RemoteException e) {
5749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                Log.v(TAG, "Remote exception in rename(): ", e);
57508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            }
576a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        } else {
5779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.w(TAG, "rename(): Service not connected!");
57808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
57908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
58008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
5819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
5829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Obtain the list of enrolled fingerprints templates.
5839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @return list of current fingerprint items
584ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
585ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
5869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
587f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
5882aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public List<Fingerprint> getEnrolledFingerprints(int userId) {
5899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
5904af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
59108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } catch (RemoteException e) {
5929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
59308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
5949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        return null;
59508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
59608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
59708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
5982aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Obtain the list of enrolled fingerprints templates.
5992aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return list of current fingerprint items
600ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
6019f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
60208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
603f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6042aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public List<Fingerprint> getEnrolledFingerprints() {
6052aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        return getEnrolledFingerprints(UserHandle.myUserId());
6062aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    }
6072aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi
6082aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    /**
6092aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Determine if there is at least one fingerprint enrolled.
6102aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     *
6112aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return true if at least one fingerprint is enrolled, false otherwise
6122aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     */
613f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6142aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public boolean hasEnrolledFingerprints() {
6152aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        if (mService != null) try {
6164af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            return mService.hasEnrolledFingerprints(UserHandle.myUserId(),
6174af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                    mContext.getOpPackageName());
6182aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        } catch (RemoteException e) {
6192aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi            Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
6202aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        }
6212aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        return false;
6222aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    }
6232aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi
6242aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    /**
6252aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Determine if fingerprint hardware is present and functional.
6262aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     *
6272aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return true if hardware is present and functional, false otherwise.
6282aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     */
629f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6309f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public boolean isHardwareDetected() {
63108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) {
63208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            try {
6339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                long deviceId = 0; /* TODO: plumb hardware id to FPMS */
6344af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
63508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            } catch (RemoteException e) {
6369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e);
63708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            }
63808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } else {
6399f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
640a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
6419f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        return false;
642a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
643a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
6444d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    /**
6454d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * Retrieves the authenticator token for binding keys to the lifecycle
6464d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * of the current set of fingerprints. Used only by internal clients.
6474d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     *
6484d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * @hide
6494d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     */
6504d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    public long getAuthenticatorId() {
6514d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        if (mService != null) {
6524d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            try {
6534af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return mService.getAuthenticatorId(mContext.getOpPackageName());
6544d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            } catch (RemoteException e) {
6554d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales                Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
6564d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            }
6574d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        } else {
6584d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            Log.w(TAG, "getAuthenticatorId(): Service not connected!");
6594d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        }
6604d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        return 0;
6614d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    }
6624d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales
66324e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin    private class MyHandler extends Handler {
66424e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        private MyHandler(Context context) {
66524e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin            super(context.getMainLooper());
66624e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        }
66724e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin
668f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private MyHandler(Looper looper) {
669f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            super(looper);
670f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
671f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
6729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void handleMessage(android.os.Message msg) {
6739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            switch(msg.what) {
6749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ENROLL_RESULT:
6759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
6769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
6779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ACQUIRED:
6789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */);
6799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
680f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                case MSG_AUTHENTICATION_SUCCEEDED:
681f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    sendAuthenticatedSucceeded((Fingerprint) msg.obj);
682f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    break;
683f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                case MSG_AUTHENTICATION_FAILED:
684f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    sendAuthenticatedFailed();
6859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
6869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ERROR:
6879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */);
6889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
6899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_REMOVED:
6909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
6919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                            msg.arg2 /* groupId */);
6929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
69308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
6949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
6959f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
6969f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mRemovalCallback != null) {
6979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                int reqFingerId = mRemovalFingerprint.getFingerId();
6989f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                int reqGroupId = mRemovalFingerprint.getGroupId();
6999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                if (fingerId != reqFingerId) {
7009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
7019f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
7029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                if (fingerId != reqFingerId) {
7039f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
7049f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
7059f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint);
706a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
707a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
708a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
7099f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendErrorResult(long deviceId, int errMsgId) {
7109f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
7119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId));
7129f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mAuthenticationCallback != null) {
7139f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId));
7149f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mRemovalCallback != null) {
7159f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId,
7169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                        getErrorString(errMsgId));
7179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
7189f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
7199f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
7209f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendEnrollResult(Fingerprint fp, int remaining) {
7219f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
7229f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mEnrollmentCallback.onEnrollmentProgress(remaining);
7239f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
7249f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
7259f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
726f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private void sendAuthenticatedSucceeded(Fingerprint fp) {
7279f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mAuthenticationCallback != null) {
728f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
729f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                mAuthenticationCallback.onAuthenticationSucceeded(result);
730f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            }
731f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
732f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
733f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private void sendAuthenticatedFailed() {
734f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            if (mAuthenticationCallback != null) {
735f501b58de8f467a80fef49c704555781bc61ea6fJim Miller               mAuthenticationCallback.onAuthenticationFailed();
7369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
7379f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
7389f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
7399f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendAcquiredResult(long deviceId, int acquireInfo) {
7409f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            final String msg = getAcquiredString(acquireInfo);
7419f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (msg == null) return;
7429f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
7439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
7449f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg);
7459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mAuthenticationCallback != null) {
7469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg);
7479f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
7489f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
7499f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
750ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
751ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    /**
752ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller     * @hide
753ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller     */
7549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public FingerprintManager(Context context, IFingerprintService service) {
7559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        mContext = context;
7569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        mService = service;
7579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService == null) {
7589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Slog.v(TAG, "FingerprintManagerService was null");
7599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
76024e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        mHandler = new MyHandler(context);
7619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    }
7629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
7639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private int getCurrentUserId() {
7649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        try {
7659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            return ActivityManagerNative.getDefault().getCurrentUser().id;
7669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
7679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.w(TAG, "Failed to get current user id\n");
7689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            return UserHandle.USER_NULL;
769ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
770ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    }
771ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
772fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    private void cancelEnrollment() {
773ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
774ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mService.cancelEnrollment(mToken);
775ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
776ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
777ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
778ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
779ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
780ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private void cancelAuthentication(CryptoObject cryptoObject) {
781ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
7824af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            mService.cancelAuthentication(mToken, mContext.getOpPackageName());
783ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
784ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
785ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
786ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
787ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
788ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private String getErrorString(int errMsg) {
789ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        switch (errMsg) {
790ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
791ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
792ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_unable_to_process);
793ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_HW_UNAVAILABLE:
794ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
795ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_hw_not_available);
796ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_NO_SPACE:
797ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
798ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_no_space);
799ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_TIMEOUT:
800fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout);
801fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            case FINGERPRINT_ERROR_CANCELED:
802fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled);
803fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            case FINGERPRINT_ERROR_LOCKOUT:
804fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout);
805ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            default:
806ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) {
807ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE;
808ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    String[] msgArray = mContext.getResources().getStringArray(
809ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                            com.android.internal.R.array.fingerprint_error_vendor);
810ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    if (msgNumber < msgArray.length) {
811ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        return msgArray[msgNumber];
812ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    }
8139f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
814ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return null;
815ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
816ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    }
81799d6019bead4705b7e126e65b856d538417d4934Jim Miller
818ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private String getAcquiredString(int acquireInfo) {
819ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        switch (acquireInfo) {
820ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_GOOD:
821ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return null;
822ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_PARTIAL:
823ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
824ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_partial);
825ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_INSUFFICIENT:
826ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
827ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_insufficient);
828ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
829ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
830ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_imager_dirty);
831ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_TOO_SLOW:
832ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
833ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_too_slow);
834ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_TOO_FAST:
835ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
836ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_too_fast);
837ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            default:
838ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) {
839ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE;
840ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    String[] msgArray = mContext.getResources().getStringArray(
841ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                            com.android.internal.R.array.fingerprint_acquired_vendor);
842ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    if (msgNumber < msgArray.length) {
843ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        return msgArray[msgNumber];
844ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    }
8459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
846ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return null;
84799d6019bead4705b7e126e65b856d538417d4934Jim Miller        }
84899d6019bead4705b7e126e65b856d538417d4934Jim Miller    }
8499f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
8509f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
8519f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
852f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
8539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
8549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
8559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
8569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
858f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
8599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onAcquired(long deviceId, int acquireInfo) {
8609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
8619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
863f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
864f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) {
865f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget();
866f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
867f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
868f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
869f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationFailed(long deviceId) {
870f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
8719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
873f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
8749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onError(long deviceId, int error) {
8759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
8769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
878f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
8799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onRemoved(long deviceId, int fingerId, int groupId) {
8809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
8819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
8839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
8844d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales}
8854d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales
886