FingerprintManager.java revision d1f722d906f66ef05cd329feb9edbed178314d46
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;
305e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.os.PowerManager;
3108fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.os.RemoteException;
3208fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.os.UserHandle;
33dcdaf87ed0aa99073638bcfe645949f130f0c7adAlex Klyubinimport android.security.keystore.AndroidKeyStoreProvider;
3408fa40c5cb5229b7969b2a5146855a337870f45aJim Millerimport android.util.Log;
35a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.util.Slog;
3608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
379f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport java.security.Signature;
38ba67aee02cf864793129976cd8a8a46e60c60577Jim Millerimport java.util.List;
39ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
409f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport javax.crypto.Cipher;
41b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Millerimport javax.crypto.Mac;
429f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
43f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport static android.Manifest.permission.USE_FINGERPRINT;
44f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport static android.Manifest.permission.MANAGE_FINGERPRINT;
45f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
4608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller/**
4708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * A class that coordinates access to the fingerprint hardware.
48ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p>
49ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Use {@link android.content.Context#getSystemService(java.lang.String)}
50ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * with argument {@link android.content.Context#FINGERPRINT_SERVICE} to get
51ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * an instance of this class.
5208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller */
5308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
5408fa40c5cb5229b7969b2a5146855a337870f45aJim Millerpublic class FingerprintManager {
5508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private static final String TAG = "FingerprintManager";
56d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    private static final boolean DEBUG = true;
5708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private static final int MSG_ENROLL_RESULT = 100;
58a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final int MSG_ACQUIRED = 101;
59f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
60f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_AUTHENTICATION_FAILED = 103;
61f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_ERROR = 104;
62f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_REMOVED = 105;
6308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
64ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
65ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // Error messages from fingerprint hardware during initilization, enrollment, authentication or
66ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // removal. Must agree with the list in fingerprint.h
67ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
6808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
69ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
70ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The hardware is unavailable. Try again later.
71ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
7208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
73ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
74ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
75ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned when the sensor was unable to process the current image.
76ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
77a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2;
78ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
79ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
80ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned when the current request has been running too long. This is intended to
81ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * prevent programs from waiting for the fingerprint sensor indefinitely. The timeout is
82ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * platform and sensor-specific, but is generally on the order of 30 seconds.
83ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
8408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
85ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
86ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
87ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned for operations like enrollment; the operation cannot be completed
88ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * because there's not enough storage remaining to complete the operation.
89ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
9008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
91ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
92ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
93ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The operation was canceled because the fingerprint sensor is unavailable. For example,
94ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * this may happen when the user is switched, the device is locked or another pending operation
95ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * prevents or disables it.
96ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ERROR_CANCELED = 5;
98ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
99ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
100ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The {@link FingerprintManager#remove(Fingerprint, RemovalCallback)} call failed. Typically
101ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * this will happen when the provided fingerprint id was incorrect.
102ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
103ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
104ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
105ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6;
106ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
107fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller   /**
108fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * The operation was canceled because the API is locked out due to too many attempts.
109fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     */
110fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    public static final int FINGERPRINT_ERROR_LOCKOUT = 7;
111fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
112ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
113ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Hardware vendors may extend this list if there are conditions that do not fall under one of
114ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * the above categories. Vendors are responsible for providing error strings for these errors.
115f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @hide
116ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000;
11808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
119ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
120ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // Image acquisition messages. Must agree with those in fingerprint.h
121ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
122ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
123ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
124ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The image acquired was good.
125ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
126a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_GOOD = 0;
127ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
128ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
129ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Only a partial fingerprint image was detected. During enrollment, the user should be
130ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * informed on what needs to happen to resolve this problem, e.g. "press firmly on sensor."
131ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
132a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1;
133ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
134ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
135ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was too noisy to process due to a detected condition (i.e. dry skin) or
136ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * a possibly dirty sensor (See {@link #FINGERPRINT_ACQUIRED_IMAGER_DIRTY}).
137ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
138a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2;
139ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
140ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
141ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was too noisy due to suspected or detected dirt on the sensor.
142ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * For example, it's reasonable return this after multiple
143ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * {@link #FINGERPRINT_ACQUIRED_INSUFFICIENT} or actual detection of dirt on the sensor
144ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * (stuck pixels, swaths, etc.). The user is expected to take action to clean the sensor
145ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * when this is returned.
146ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1479f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3;
148ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
149ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
150ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was unreadable due to lack of motion. This is most appropriate for
151ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * linear array sensors that require a swipe motion.
152ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4;
154ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
155ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
156ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was incomplete due to quick motion. While mostly appropriate for
157ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * linear array sensors,  this could also happen if the finger was moved during acquisition.
158ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The user should be asked to move the finger slower (linear) or leave the finger on the sensor
159ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * longer.
160ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5;
162ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
163ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
164ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Hardware vendors may extend this list if there are conditions that do not fall under one of
165ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * the above categories. Vendors are responsible for providing error strings for these errors.
166f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @hide
167ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
169a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
17008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private IFingerprintService mService;
171d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    private Context mContext;
172a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private IBinder mToken = new Binder();
1739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private AuthenticationCallback mAuthenticationCallback;
1749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private EnrollmentCallback mEnrollmentCallback;
1759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private RemovalCallback mRemovalCallback;
1769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private CryptoObject mCryptoObject;
1779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private Fingerprint mRemovalFingerprint;
178f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private Handler mHandler;
179ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
180ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private class OnEnrollCancelListener implements OnCancelListener {
181ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        @Override
182ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onCancel() {
183fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            cancelEnrollment();
184ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
185ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
186ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
187ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private class OnAuthenticationCancelListener implements OnCancelListener {
188ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        private CryptoObject mCrypto;
189ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
190ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public OnAuthenticationCancelListener(CryptoObject crypto) {
191ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mCrypto = crypto;
192ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
193ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
194ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        @Override
195ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onCancel() {
196ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            cancelAuthentication(mCrypto);
197ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
198ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
19908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
2009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
201ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * A wrapper class for the crypto objects supported by FingerprintManager. Currently the
202b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller     * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
2039f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
204f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    public static final class CryptoObject {
205ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
206b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Signature signature) {
207f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = signature;
208ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
209ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
210b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Cipher cipher) {
211f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = cipher;
212b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        }
213b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller
214b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Mac mac) {
215f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = mac;
216ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
217ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
218ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
219ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Get {@link Signature} object.
220ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return {@link Signature} object or null if this doesn't contain one.
221ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
222f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Signature getSignature() {
223f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Signature ? (Signature) mCrypto : null;
224f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
225ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
226ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
227ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Get {@link Cipher} object.
228ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return {@link Cipher} object or null if this doesn't contain one.
229ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
230f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Cipher getCipher() {
231f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Cipher ? (Cipher) mCrypto : null;
232f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
233ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
234ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
235b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         * Get {@link Mac} object.
236b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         * @return {@link Mac} object or null if this doesn't contain one.
237b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         */
238f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Mac getMac() {
239f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Mac ? (Mac) mCrypto : null;
240f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
241b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller
242b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        /**
243ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @hide
244ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return the opId associated with this object or 0 if none
245ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
246ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public long getOpId() {
247f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto != null ?
248f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0;
249ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
250ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
251f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private final Object mCrypto;
25208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    };
25308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
2549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
2559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
256f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     *     CancellationSignal, int, AuthenticationCallback, Handler)}.
2579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
258748bc36f2eebfdc67520c5025b48fefdfd8d7c01Jim Miller    public static class AuthenticationResult {
2599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private Fingerprint mFingerprint;
2609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private CryptoObject mCryptoObject;
2619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
262f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        /**
263f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * Authentication result
264f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         *
265f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param crypto the crypto object
266f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param fingerprint the recognized fingerprint data, if allowed.
267f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @hide
268f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         */
2699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) {
2709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mCryptoObject = crypto;
2719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mFingerprint = fingerprint;
272ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
2739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
2749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
2759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Obtain the crypto object associated with this transaction
2769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
277f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         *     CancellationSignal, int, AuthenticationCallback, Handler)}.
2789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
2799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public CryptoObject getCryptoObject() { return mCryptoObject; }
2809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
2819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
282ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Obtain the Fingerprint associated with this operation. Applications are strongly
283ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * discouraged from associating specific fingers with specific applications or operations.
284ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         *
2859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @hide
2869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
2879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public Fingerprint getFingerprint() { return mFingerprint; }
2889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
289ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
29006e658f324a937bec1c5ddbe9c3100c3d2fec371Jim Miller    /**
2919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
292f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link
293ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * FingerprintManager#authenticate(CryptoObject, CancellationSignal,
294f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
295ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * fingerprint events.
29606e658f324a937bec1c5ddbe9c3100c3d2fec371Jim Miller     */
2979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class AuthenticationCallback {
2989f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
2999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when an unrecoverable error has been encountered and the operation is complete.
3009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * No further callbacks will be made on this object.
301f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param errorCode An integer identifying the error message
302ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString A human-readable error string that can be shown in UI
3039f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
304f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationError(int errorCode, CharSequence errString) { }
30508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3069f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
307ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a recoverable error has been encountered during authentication. The help
3089f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * string is provided to give the user guidance for what went wrong, such as
3099f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Sensor dirty, please clean it."
310f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param helpCode An integer identifying the error message
311ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpString A human-readable string that can be shown in UI
3129f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
313f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }
31408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3159f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when a fingerprint is recognized.
317ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param result An object containing authentication-related data
3189f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
319ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onAuthenticationSucceeded(AuthenticationResult result) { }
320ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
321ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
322ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a fingerprint is valid but not recognized.
323ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
324ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onAuthenticationFailed() { }
3254cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi
3264cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi        /**
3274cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         * Called when a fingerprint image has been acquired, but wasn't processed yet.
3284cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         *
3294cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants
3304cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         * @hide
3314cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         */
3324cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi        public void onAuthenticationAcquired(int acquireInfo) {}
3339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
33408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3359f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
3369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback,
3379f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * CancellationSignal, int). Users of {@link #FingerprintManager()}
3389f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * must provide an implementation of this to {@link FingerprintManager#enroll(long,
339f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events.
340ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
341ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
3429f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
3439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class EnrollmentCallback {
3449f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when an unrecoverable error has been encountered and the operation is complete.
3469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * No further callbacks will be made on this object.
347ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errMsgId An integer identifying the error message
348ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString A human-readable error string that can be shown in UI
3499f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
350ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentError(int errMsgId, CharSequence errString) { }
351a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
3529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
353ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a recoverable error has been encountered during enrollment. The help
3549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * string is provided to give the user guidance for what went wrong, such as
3559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Sensor dirty, please clean it" or what they need to do next, such as
3569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Touch sensor again."
357ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpMsgId An integer identifying the error message
358ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpString A human-readable string that can be shown in UI
3599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
360ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { }
36108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called as each enrollment step progresses. Enrollment is considered complete when
364ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * remaining reaches 0. This function will not be called if enrollment fails. See
3659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
366ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param remaining The number of remaining steps
3679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
368ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentProgress(int remaining) { }
3699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
37008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
3729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#remove(int). Users of
3739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link #FingerprintManager()} may optionally provide an implementation of this to
3749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to
3759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * fingerprint template removal events.
376ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
377ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
3789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
3799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class RemovalCallback {
3809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when the given fingerprint can't be removed.
382ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param fp The fingerprint that the call attempted to remove
383ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errMsgId An associated error message id
384ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString An error message indicating why the fingerprint id can't be removed
3859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
386ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { }
3879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
3889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when a given fingerprint is successfully removed.
3909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @param fingerprint the fingerprint template that was removed.
3919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
392ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onRemovalSucceeded(Fingerprint fingerprint) { }
39308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    };
39408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
39508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
3963a464785088e7fd206666f640912729533948ce8Jorim Jaggi     * @hide
3973a464785088e7fd206666f640912729533948ce8Jorim Jaggi     */
3983a464785088e7fd206666f640912729533948ce8Jorim Jaggi    public static abstract class LockoutResetCallback {
3993a464785088e7fd206666f640912729533948ce8Jorim Jaggi
4003a464785088e7fd206666f640912729533948ce8Jorim Jaggi        /**
4013a464785088e7fd206666f640912729533948ce8Jorim Jaggi         * Called when lockout period expired and clients are allowed to listen for fingerprint
4023a464785088e7fd206666f640912729533948ce8Jorim Jaggi         * again.
4033a464785088e7fd206666f640912729533948ce8Jorim Jaggi         */
4043a464785088e7fd206666f640912729533948ce8Jorim Jaggi        public void onLockoutReset() { }
4053a464785088e7fd206666f640912729533948ce8Jorim Jaggi    };
4063a464785088e7fd206666f640912729533948ce8Jorim Jaggi
4073a464785088e7fd206666f640912729533948ce8Jorim Jaggi    /**
408ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Request authentication of a crypto object. This call warms up the fingerprint hardware
409ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * and starts scanning for a fingerprint. It terminates when
4109f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
4115f69ca3be3005fd127c82f503d0692f807729688Jim Miller     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
4129f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * which point the object is no longer valid. The operation can be canceled by using the
4139f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * provided cancel object.
414d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller     *
4159f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param crypto object associated with the call or null if none required.
4169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param cancel an object that can be used to cancel authentication
417ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @param flags optional flags; should be 0
418f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param callback an object to receive authentication events
419f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param handler an optional handler to handle callback events
420e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *
421e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     * @throws IllegalArgumentException if the crypto operation is not supported or is not backed
422e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *         by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
423e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *         facility</a>.
424e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     * @throws IllegalStateException if the crypto primitive is not initialized.
425d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller     */
426f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
427ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
428f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
429f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId());
430ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    }
431ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi
432ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    /**
433f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * Use the provided handler thread for events.
434f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param handler
435f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     */
436f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private void useHandler(Handler handler) {
437f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        if (handler != null) {
438f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler = new MyHandler(handler.getLooper());
439f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        } else if (mHandler.getLooper() != mContext.getMainLooper()){
440f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler = new MyHandler(mContext.getMainLooper());
441f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
442f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    }
443f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
444f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    /**
445f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * Per-user version
446ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi     * @hide
447ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi     */
448f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
449ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
450f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
4519f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (callback == null) {
4529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            throw new IllegalArgumentException("Must supply an authentication callback");
4539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
4549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
455ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (cancel != null) {
456ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (cancel.isCanceled()) {
457ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                Log.w(TAG, "authentication already canceled");
458ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return;
459ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            } else {
460ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
461ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
462ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
4639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
4649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
465f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            useHandler(handler);
4669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mAuthenticationCallback = callback;
4679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mCryptoObject = crypto;
468ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            long sessionId = crypto != null ? crypto.getOpId() : 0;
4694af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
4704af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                    mContext.getOpPackageName());
4719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
472ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception while authenticating: ", e);
473ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
474ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // Though this may not be a hardware issue, it will cause apps to give up or try
475ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // again later.
476ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
477ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
478ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
4799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
480d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    }
481d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller
482d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    /**
4839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Request fingerprint enrollment. This call warms up the fingerprint hardware
4849f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
4859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback} object. It terminates when
4869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or
4879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at
4889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * which point the object is no longer valid. The operation can be canceled by using the
4899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * provided cancel object.
490fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * @param token a unique token provided by a recent creation or verification of device
491fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * credentials (e.g. pin, pattern or password).
4929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param cancel an object that can be used to cancel enrollment
4939f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param flags optional flags
494f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param callback an object to receive enrollment events
495ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
49608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
497f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
498f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    public void enroll(byte [] token, CancellationSignal cancel, int flags,
499d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            EnrollmentCallback callback, int userId) {
500d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        if (userId == UserHandle.USER_CURRENT) {
501d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            userId = getCurrentUserId();
502d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        }
5039f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (callback == null) {
5049f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            throw new IllegalArgumentException("Must supply an enrollment callback");
50508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
5069f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
507ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (cancel != null) {
508ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (cancel.isCanceled()) {
509ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                Log.w(TAG, "enrollment already canceled");
510ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return;
511ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            } else {
512fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                cancel.setOnCancelListener(new OnEnrollCancelListener());
513ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
514ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
5159f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
51608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) try {
5179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mEnrollmentCallback = callback;
518d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            mService.enroll(mToken, token, userId, mServiceReceiver, flags);
519ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
520ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception in enroll: ", e);
521ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
522ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // Though this may not be a hardware issue, it will cause apps to give up or try
523ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // again later.
524ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
525ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
526ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
527ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
528ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
529ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
530ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
531ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Requests a pre-enrollment auth token to tie enrollment to the confirmation of
532ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * existing device credentials (e.g. pin/pattern/password).
533ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
534ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
535f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
536ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public long preEnroll() {
537ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        long result = 0;
538ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
539ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            result = mService.preEnroll(mToken);
54008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } catch (RemoteException e) {
541ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception in enroll: ", e);
54208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
543ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        return result;
54408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
54508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
54608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
547e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     * Finishes enrollment and cancels the current auth token.
548e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     * @hide
549e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     */
550e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    @RequiresPermission(MANAGE_FINGERPRINT)
551e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    public int postEnroll() {
552e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        int result = 0;
553e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        if (mService != null) try {
554e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            result = mService.postEnroll(mToken);
555e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        } catch (RemoteException e) {
556e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            Log.w(TAG, "Remote exception in post enroll: ", e);
557e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        }
558e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        return result;
559e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    }
560e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy
561e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    /**
562d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * Sets the active user. This is meant to be used to select the current profile for enrollment
563d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * to allow separate enrolled fingers for a work profile
564d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @param userId
565d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @hide
566d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     */
567d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    @RequiresPermission(MANAGE_FINGERPRINT)
568d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    public void setActiveUser(int userId) {
569d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        if (mService != null) try {
570d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            mService.setActiveUser(userId);
571d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        } catch (RemoteException e) {
572d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            Log.w(TAG, "Remote exception in setActiveUser: ", e);
573d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        }
574d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    }
575d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri
576d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    /**
5779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Remove given fingerprint template from fingerprint hardware and/or protected storage.
5789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param fp the fingerprint item to remove
5799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param callback an optional callback to verify that fingerprint templates have been
580ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * successfully removed. May be null of no callback is required.
581ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
5829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
58308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
584f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
5859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public void remove(Fingerprint fp, RemovalCallback callback) {
5869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
5879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mRemovalCallback = callback;
5889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mRemovalFingerprint = fp;
589ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mService.remove(mToken, fp.getFingerId(), getCurrentUserId(), mServiceReceiver);
5909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
591ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception in remove: ", e);
592ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
593ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE,
594ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
595ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
59608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
59708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
59808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
59908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
6009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Renames the given fingerprint template
6019f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param fpId the fingerprint id
6029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param newName the new name
603ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
6049f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
60508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
606f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
6079f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public void rename(int fpId, String newName) {
6089f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        // Renames the given fpId
60908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) {
61008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            try {
6119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mService.rename(fpId, getCurrentUserId(), newName);
61208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            } catch (RemoteException e) {
6139f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                Log.v(TAG, "Remote exception in rename(): ", e);
61408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            }
615a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        } else {
6169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.w(TAG, "rename(): Service not connected!");
61708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
61808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
61908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
6209f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
6219f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Obtain the list of enrolled fingerprints templates.
6229f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @return list of current fingerprint items
623ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
624ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
6259f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
626f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6272aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public List<Fingerprint> getEnrolledFingerprints(int userId) {
6289f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
6294af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
63008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } catch (RemoteException e) {
6319f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
63208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
6339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        return null;
63408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
63508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
63608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
6372aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Obtain the list of enrolled fingerprints templates.
6382aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return list of current fingerprint items
639ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
6409f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
64108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
642f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6432aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public List<Fingerprint> getEnrolledFingerprints() {
6442aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        return getEnrolledFingerprints(UserHandle.myUserId());
6452aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    }
6462aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi
6472aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    /**
6482aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Determine if there is at least one fingerprint enrolled.
6492aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     *
6502aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return true if at least one fingerprint is enrolled, false otherwise
6512aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     */
652f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6532aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public boolean hasEnrolledFingerprints() {
6542aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        if (mService != null) try {
6554af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            return mService.hasEnrolledFingerprints(UserHandle.myUserId(),
6564af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                    mContext.getOpPackageName());
6572aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        } catch (RemoteException e) {
6582aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi            Log.v(TAG, "Remote exception in getEnrolledFingerprints: ", e);
6592aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        }
6602aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        return false;
6612aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    }
6622aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi
6632aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    /**
6642aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Determine if fingerprint hardware is present and functional.
6652aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     *
6662aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return true if hardware is present and functional, false otherwise.
6672aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     */
668f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public boolean isHardwareDetected() {
67008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) {
67108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            try {
6729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                long deviceId = 0; /* TODO: plumb hardware id to FPMS */
6734af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
67408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            } catch (RemoteException e) {
6759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                Log.v(TAG, "Remote exception in isFingerprintHardwareDetected(): ", e);
67608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            }
67708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } else {
6789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
679a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
6809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        return false;
681a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
682a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
6834d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    /**
6844d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * Retrieves the authenticator token for binding keys to the lifecycle
6854d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * of the current set of fingerprints. Used only by internal clients.
6864d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     *
6874d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * @hide
6884d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     */
6894d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    public long getAuthenticatorId() {
6904d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        if (mService != null) {
6914d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            try {
6924af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return mService.getAuthenticatorId(mContext.getOpPackageName());
6934d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            } catch (RemoteException e) {
6944d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales                Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
6954d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            }
6964d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        } else {
6974d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            Log.w(TAG, "getAuthenticatorId(): Service not connected!");
6984d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        }
6994d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        return 0;
7004d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    }
7014d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales
702e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller    /**
703e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     * Reset the lockout timer when asked to do so by keyguard.
704e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     *
705e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     * @param token an opaque token returned by password confirmation.
706e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     *
707e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     * @hide
708e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     */
709e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller    public void resetTimeout(byte[] token) {
710e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        if (mService != null) {
711e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            try {
712e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller                mService.resetTimeout(token);
713e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            } catch (RemoteException e) {
7143a464785088e7fd206666f640912729533948ce8Jorim Jaggi                Log.v(TAG, "Remote exception in resetTimeout(): ", e);
715e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            }
716e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        } else {
7173a464785088e7fd206666f640912729533948ce8Jorim Jaggi            Log.w(TAG, "resetTimeout(): Service not connected!");
7183a464785088e7fd206666f640912729533948ce8Jorim Jaggi        }
7193a464785088e7fd206666f640912729533948ce8Jorim Jaggi    }
7203a464785088e7fd206666f640912729533948ce8Jorim Jaggi
7213a464785088e7fd206666f640912729533948ce8Jorim Jaggi    /**
7223a464785088e7fd206666f640912729533948ce8Jorim Jaggi     * @hide
7233a464785088e7fd206666f640912729533948ce8Jorim Jaggi     */
7243a464785088e7fd206666f640912729533948ce8Jorim Jaggi    public void addLockoutResetCallback(final LockoutResetCallback callback) {
7253a464785088e7fd206666f640912729533948ce8Jorim Jaggi        if (mService != null) {
7263a464785088e7fd206666f640912729533948ce8Jorim Jaggi            try {
7275e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
7283a464785088e7fd206666f640912729533948ce8Jorim Jaggi                mService.addLockoutResetCallback(
7293a464785088e7fd206666f640912729533948ce8Jorim Jaggi                        new IFingerprintServiceLockoutResetCallback.Stub() {
7303a464785088e7fd206666f640912729533948ce8Jorim Jaggi
7313a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    @Override
7323a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    public void onLockoutReset(long deviceId) throws RemoteException {
7335e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                        final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
7345e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                PowerManager.PARTIAL_WAKE_LOCK, "lockoutResetCallback");
7355e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                        wakeLock.acquire();
7363a464785088e7fd206666f640912729533948ce8Jorim Jaggi                        mHandler.post(new Runnable() {
7373a464785088e7fd206666f640912729533948ce8Jorim Jaggi                            @Override
7383a464785088e7fd206666f640912729533948ce8Jorim Jaggi                            public void run() {
7395e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                try {
7405e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                    callback.onLockoutReset();
7415e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                } finally {
7425e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                    wakeLock.release();
7435e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                }
7443a464785088e7fd206666f640912729533948ce8Jorim Jaggi                            }
7453a464785088e7fd206666f640912729533948ce8Jorim Jaggi                        });
7463a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    }
7473a464785088e7fd206666f640912729533948ce8Jorim Jaggi                });
7483a464785088e7fd206666f640912729533948ce8Jorim Jaggi            } catch (RemoteException e) {
7493a464785088e7fd206666f640912729533948ce8Jorim Jaggi                Log.v(TAG, "Remote exception in addLockoutResetCallback(): ", e);
7503a464785088e7fd206666f640912729533948ce8Jorim Jaggi            }
7513a464785088e7fd206666f640912729533948ce8Jorim Jaggi        } else {
7523a464785088e7fd206666f640912729533948ce8Jorim Jaggi            Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
753e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        }
754e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller    }
755e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller
75624e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin    private class MyHandler extends Handler {
75724e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        private MyHandler(Context context) {
75824e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin            super(context.getMainLooper());
75924e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        }
76024e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin
761f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private MyHandler(Looper looper) {
762f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            super(looper);
763f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
764f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
765e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        @Override
7669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void handleMessage(android.os.Message msg) {
7679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            switch(msg.what) {
7689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ENROLL_RESULT:
7699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
7709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
7719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ACQUIRED:
7729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */);
7739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
774f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                case MSG_AUTHENTICATION_SUCCEEDED:
775f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    sendAuthenticatedSucceeded((Fingerprint) msg.obj);
776f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    break;
777f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                case MSG_AUTHENTICATION_FAILED:
778f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    sendAuthenticatedFailed();
7799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
7809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ERROR:
7819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */);
7829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
7839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_REMOVED:
7849f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
7859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                            msg.arg2 /* groupId */);
7869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
78708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
7889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
7899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
7909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mRemovalCallback != null) {
7919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                int reqFingerId = mRemovalFingerprint.getFingerId();
7929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                int reqGroupId = mRemovalFingerprint.getGroupId();
793f8d1e21e16e0126fa7677d8293e4e8c07d11fa51Jim Kaye                if (reqFingerId != 0  &&  fingerId != reqFingerId) {
7949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
7959f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
7961adb4a7693406e7f984d7b1512e0e6aa40aa40e2Jim Miller                if (groupId != reqGroupId) {
7979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
7989f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
7999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mRemovalCallback.onRemovalSucceeded(mRemovalFingerprint);
800a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
801a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
802a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
8039f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendErrorResult(long deviceId, int errMsgId) {
8049f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
8059f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId));
8069f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mAuthenticationCallback != null) {
8079f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId));
8089f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mRemovalCallback != null) {
8099f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId,
8109f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                        getErrorString(errMsgId));
8119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
8129f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8139f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
8149f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendEnrollResult(Fingerprint fp, int remaining) {
8159f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
8169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mEnrollmentCallback.onEnrollmentProgress(remaining);
8179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
8189f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8199f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
820f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private void sendAuthenticatedSucceeded(Fingerprint fp) {
8219f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mAuthenticationCallback != null) {
822f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
823f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                mAuthenticationCallback.onAuthenticationSucceeded(result);
824f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            }
825f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
826f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
827f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private void sendAuthenticatedFailed() {
828f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            if (mAuthenticationCallback != null) {
829f501b58de8f467a80fef49c704555781bc61ea6fJim Miller               mAuthenticationCallback.onAuthenticationFailed();
8309f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
8319f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8329f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
8339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendAcquiredResult(long deviceId, int acquireInfo) {
8344cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            if (mAuthenticationCallback != null) {
8354cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi                mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
8364cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            }
8379f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            final String msg = getAcquiredString(acquireInfo);
8384cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            if (msg == null) {
8394cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi                return;
8404cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            }
8419f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
8429f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg);
8439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mAuthenticationCallback != null) {
8449f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg);
8459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
8469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8479f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
848ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
849ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    /**
850ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller     * @hide
851ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller     */
8529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public FingerprintManager(Context context, IFingerprintService service) {
8539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        mContext = context;
8549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        mService = service;
8559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService == null) {
8569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Slog.v(TAG, "FingerprintManagerService was null");
8579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
85824e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        mHandler = new MyHandler(context);
8599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    }
8609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
8619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private int getCurrentUserId() {
8629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        try {
8639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            return ActivityManagerNative.getDefault().getCurrentUser().id;
8649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
8659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.w(TAG, "Failed to get current user id\n");
8669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            return UserHandle.USER_NULL;
867ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
868ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    }
869ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
870fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    private void cancelEnrollment() {
871ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
872ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mService.cancelEnrollment(mToken);
873ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
874ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
875ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
876ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
877ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
878ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private void cancelAuthentication(CryptoObject cryptoObject) {
879ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
8804af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            mService.cancelAuthentication(mToken, mContext.getOpPackageName());
881ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
882ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (DEBUG) Log.w(TAG, "Remote exception while canceling enrollment");
883ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
884ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
885ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
886ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private String getErrorString(int errMsg) {
887ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        switch (errMsg) {
888ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
889ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
890ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_unable_to_process);
891ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_HW_UNAVAILABLE:
892ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
893ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_hw_not_available);
894ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_NO_SPACE:
895ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
896ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_no_space);
897ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_TIMEOUT:
898fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout);
899fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            case FINGERPRINT_ERROR_CANCELED:
900fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled);
901fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            case FINGERPRINT_ERROR_LOCKOUT:
902fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout);
903ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            default:
904ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) {
905ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE;
906ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    String[] msgArray = mContext.getResources().getStringArray(
907ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                            com.android.internal.R.array.fingerprint_error_vendor);
908ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    if (msgNumber < msgArray.length) {
909ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        return msgArray[msgNumber];
910ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    }
9119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
912ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return null;
913ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
914ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    }
91599d6019bead4705b7e126e65b856d538417d4934Jim Miller
916ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private String getAcquiredString(int acquireInfo) {
917ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        switch (acquireInfo) {
918ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_GOOD:
919ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return null;
920ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_PARTIAL:
921ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
922ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_partial);
923ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_INSUFFICIENT:
924ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
925ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_insufficient);
926ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
927ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
928ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_imager_dirty);
929ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_TOO_SLOW:
930ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
931ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_too_slow);
932ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_TOO_FAST:
933ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
934ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_too_fast);
935ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            default:
936ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) {
937ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE;
938ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    String[] msgArray = mContext.getResources().getStringArray(
939ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                            com.android.internal.R.array.fingerprint_acquired_vendor);
940ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    if (msgNumber < msgArray.length) {
941ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        return msgArray[msgNumber];
942ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    }
9439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
944ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return null;
94599d6019bead4705b7e126e65b856d538417d4934Jim Miller        }
94699d6019bead4705b7e126e65b856d538417d4934Jim Miller    }
9479f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
9489f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
9499f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
950f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
9519f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
9529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
9539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
9549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
956f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
9579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onAcquired(long deviceId, int acquireInfo) {
9589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
9599f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
961f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
962f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) {
963f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget();
964f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
965f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
966f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
967f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationFailed(long deviceId) {
968f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
9699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
971f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
9729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onError(long deviceId, int error) {
9739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
9749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
976f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
9779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onRemoved(long deviceId, int fingerId, int groupId) {
9789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
9799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
9819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
9824d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales}
983