FingerprintManager.java revision 8f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1
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
4333fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarriimport static android.Manifest.permission.INTERACT_ACROSS_USERS;
44f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport static android.Manifest.permission.USE_FINGERPRINT;
45f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport static android.Manifest.permission.MANAGE_FINGERPRINT;
46f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
4708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller/**
4808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller * A class that coordinates access to the fingerprint hardware.
49ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * <p>
50ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * Use {@link android.content.Context#getSystemService(java.lang.String)}
51ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * with argument {@link android.content.Context#FINGERPRINT_SERVICE} to get
52ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller * an instance of this class.
5308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller */
5408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
5508fa40c5cb5229b7969b2a5146855a337870f45aJim Millerpublic class FingerprintManager {
5608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private static final String TAG = "FingerprintManager";
57d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    private static final boolean DEBUG = true;
5808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private static final int MSG_ENROLL_RESULT = 100;
59a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private static final int MSG_ACQUIRED = 101;
60f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
61f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_AUTHENTICATION_FAILED = 103;
62f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_ERROR = 104;
63f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private static final int MSG_REMOVED = 105;
6408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
65ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
66ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // Error messages from fingerprint hardware during initilization, enrollment, authentication or
67ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // removal. Must agree with the list in fingerprint.h
68ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
6908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
70ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
71ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The hardware is unavailable. Try again later.
72ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
7308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1;
74ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
75ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
76ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned when the sensor was unable to process the current image.
77ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
78a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2;
79ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
80ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
81ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned when the current request has been running too long. This is intended to
82ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * prevent programs from waiting for the fingerprint sensor indefinitely. The timeout is
83ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * platform and sensor-specific, but is generally on the order of 30 seconds.
84ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
8508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_TIMEOUT = 3;
86ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
87ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
88ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Error state returned for operations like enrollment; the operation cannot be completed
89ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * because there's not enough storage remaining to complete the operation.
90ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
9108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    public static final int FINGERPRINT_ERROR_NO_SPACE = 4;
92ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
93ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
94ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The operation was canceled because the fingerprint sensor is unavailable. For example,
95ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * this may happen when the user is switched, the device is locked or another pending operation
96ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * prevents or disables it.
97ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
989f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ERROR_CANCELED = 5;
99ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
100ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
101ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The {@link FingerprintManager#remove(Fingerprint, RemovalCallback)} call failed. Typically
102ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * this will happen when the provided fingerprint id was incorrect.
103ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
104ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
105ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
106ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public static final int FINGERPRINT_ERROR_UNABLE_TO_REMOVE = 6;
107ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
108fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller   /**
109fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * The operation was canceled because the API is locked out due to too many attempts.
110fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     */
111fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    public static final int FINGERPRINT_ERROR_LOCKOUT = 7;
112fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
113ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
114ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Hardware vendors may extend this list if there are conditions that do not fall under one of
115ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * the above categories. Vendors are responsible for providing error strings for these errors.
116f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @hide
117ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1189f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000;
11908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
120ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
121ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    // Image acquisition messages. Must agree with those in fingerprint.h
122ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    //
123ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
124ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
125ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The image acquired was good.
126ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
127a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_GOOD = 0;
128ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
129ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
130ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Only a partial fingerprint image was detected. During enrollment, the user should be
131ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * informed on what needs to happen to resolve this problem, e.g. "press firmly on sensor."
132ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
133a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1;
134ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
135ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
136ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was too noisy to process due to a detected condition (i.e. dry skin) or
137ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * a possibly dirty sensor (See {@link #FINGERPRINT_ACQUIRED_IMAGER_DIRTY}).
138ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
139a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public static final int FINGERPRINT_ACQUIRED_INSUFFICIENT = 2;
140ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
141ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
142ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was too noisy due to suspected or detected dirt on the sensor.
143ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * For example, it's reasonable return this after multiple
144ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * {@link #FINGERPRINT_ACQUIRED_INSUFFICIENT} or actual detection of dirt on the sensor
145ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * (stuck pixels, swaths, etc.). The user is expected to take action to clean the sensor
146ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * when this is returned.
147ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1489f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_IMAGER_DIRTY = 3;
149ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
150ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
151ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was unreadable due to lack of motion. This is most appropriate for
152ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * linear array sensors that require a swipe motion.
153ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4;
155ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
156ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
157ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The fingerprint image was incomplete due to quick motion. While mostly appropriate for
158ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * linear array sensors,  this could also happen if the finger was moved during acquisition.
159ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * The user should be asked to move the finger slower (linear) or leave the finger on the sensor
160ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * longer.
161ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5;
163ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
164ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
165ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Hardware vendors may extend this list if there are conditions that do not fall under one of
166ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * the above categories. Vendors are responsible for providing error strings for these errors.
167f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @hide
168ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
1699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
170a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
17108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    private IFingerprintService mService;
172d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    private Context mContext;
173a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    private IBinder mToken = new Binder();
1749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private AuthenticationCallback mAuthenticationCallback;
1759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private EnrollmentCallback mEnrollmentCallback;
1769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private RemovalCallback mRemovalCallback;
1779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private CryptoObject mCryptoObject;
1789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private Fingerprint mRemovalFingerprint;
179f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private Handler mHandler;
180ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
181ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private class OnEnrollCancelListener implements OnCancelListener {
182ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        @Override
183ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onCancel() {
184fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            cancelEnrollment();
185ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
186ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
187ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
188ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private class OnAuthenticationCancelListener implements OnCancelListener {
189ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        private CryptoObject mCrypto;
190ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
191ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public OnAuthenticationCancelListener(CryptoObject crypto) {
192ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mCrypto = crypto;
193ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
194ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
195ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        @Override
196ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onCancel() {
197ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            cancelAuthentication(mCrypto);
198ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
199ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
20008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
2019f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
202ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * A wrapper class for the crypto objects supported by FingerprintManager. Currently the
203b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller     * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
2049f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
205f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    public static final class CryptoObject {
206ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
207b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Signature signature) {
208f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = signature;
209ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
210ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
211b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Cipher cipher) {
212f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = cipher;
213b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        }
214b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller
215b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        public CryptoObject(@NonNull Mac mac) {
216f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mCrypto = mac;
217ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
218ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
219ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
220ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Get {@link Signature} object.
221ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return {@link Signature} object or null if this doesn't contain one.
222ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
223f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Signature getSignature() {
224f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Signature ? (Signature) mCrypto : null;
225f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
226ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
227ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
228ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Get {@link Cipher} object.
229ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return {@link Cipher} object or null if this doesn't contain one.
230ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
231f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Cipher getCipher() {
232f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Cipher ? (Cipher) mCrypto : null;
233f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
234ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
235ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
236b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         * Get {@link Mac} object.
237b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         * @return {@link Mac} object or null if this doesn't contain one.
238b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller         */
239f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public Mac getMac() {
240f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto instanceof Mac ? (Mac) mCrypto : null;
241f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
242b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller
243b62dc82b0c7208f106077b46fc7118da6baa6e13Jim Miller        /**
244ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @hide
245ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @return the opId associated with this object or 0 if none
246ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
247ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public long getOpId() {
248f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return mCrypto != null ?
249f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0;
250ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
251ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
252f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private final Object mCrypto;
25308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    };
25408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
2559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
2569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
257f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     *     CancellationSignal, int, AuthenticationCallback, Handler)}.
2589f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
259748bc36f2eebfdc67520c5025b48fefdfd8d7c01Jim Miller    public static class AuthenticationResult {
2609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private Fingerprint mFingerprint;
2619f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private CryptoObject mCryptoObject;
2629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
263f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        /**
264f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * Authentication result
265f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         *
266f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param crypto the crypto object
267f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param fingerprint the recognized fingerprint data, if allowed.
268f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @hide
269f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         */
2709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) {
2719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mCryptoObject = crypto;
2729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mFingerprint = fingerprint;
273ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
2749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
2759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
2769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Obtain the crypto object associated with this transaction
2779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
278f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         *     CancellationSignal, int, AuthenticationCallback, Handler)}.
2799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
2809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public CryptoObject getCryptoObject() { return mCryptoObject; }
2819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
2829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
283ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Obtain the Fingerprint associated with this operation. Applications are strongly
284ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * discouraged from associating specific fingers with specific applications or operations.
285ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         *
2869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @hide
2879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
2889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public Fingerprint getFingerprint() { return mFingerprint; }
2899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
290ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
29106e658f324a937bec1c5ddbe9c3100c3d2fec371Jim Miller    /**
2929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
293f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link
294ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * FingerprintManager#authenticate(CryptoObject, CancellationSignal,
295f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
296ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * fingerprint events.
29706e658f324a937bec1c5ddbe9c3100c3d2fec371Jim Miller     */
2989f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class AuthenticationCallback {
2999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when an unrecoverable error has been encountered and the operation is complete.
3019f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * No further callbacks will be made on this object.
302f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param errorCode An integer identifying the error message
303ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString A human-readable error string that can be shown in UI
3049f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
305f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationError(int errorCode, CharSequence errString) { }
30608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3079f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
308ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a recoverable error has been encountered during authentication. The help
3099f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * string is provided to give the user guidance for what went wrong, such as
3109f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Sensor dirty, please clean it."
311f501b58de8f467a80fef49c704555781bc61ea6fJim Miller         * @param helpCode An integer identifying the error message
312ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpString A human-readable string that can be shown in UI
3139f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
314f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }
31508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when a fingerprint is recognized.
318ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param result An object containing authentication-related data
3199f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
320ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onAuthenticationSucceeded(AuthenticationResult result) { }
321ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
322ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        /**
323ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a fingerprint is valid but not recognized.
324ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         */
325ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onAuthenticationFailed() { }
3264cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi
3274cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi        /**
3284cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         * Called when a fingerprint image has been acquired, but wasn't processed yet.
3294cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         *
3304cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         * @param acquireInfo one of FINGERPRINT_ACQUIRED_* constants
3314cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         * @hide
3324cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi         */
3334cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi        public void onAuthenticationAcquired(int acquireInfo) {}
3349f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
33508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
3379f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback,
3389f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * CancellationSignal, int). Users of {@link #FingerprintManager()}
3399f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * must provide an implementation of this to {@link FingerprintManager#enroll(long,
340f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events.
341ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
342ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
3439f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
3449f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class EnrollmentCallback {
3459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3469f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when an unrecoverable error has been encountered and the operation is complete.
3479f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * No further callbacks will be made on this object.
348ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errMsgId An integer identifying the error message
349ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString A human-readable error string that can be shown in UI
3509f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
351ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentError(int errMsgId, CharSequence errString) { }
352a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
3539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
354ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * Called when a recoverable error has been encountered during enrollment. The help
3559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * string is provided to give the user guidance for what went wrong, such as
3569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Sensor dirty, please clean it" or what they need to do next, such as
3579f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * "Touch sensor again."
358ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpMsgId An integer identifying the error message
359ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param helpString A human-readable string that can be shown in UI
3609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
361ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) { }
36208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called as each enrollment step progresses. Enrollment is considered complete when
365ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * remaining reaches 0. This function will not be called if enrollment fails. See
3669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)}
367ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param remaining The number of remaining steps
3689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
369ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onEnrollmentProgress(int remaining) { }
3709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
37108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
3729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
3739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Callback structure provided to {@link FingerprintManager#remove(int). Users of
3749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link #FingerprintManager()} may optionally provide an implementation of this to
3759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link FingerprintManager#remove(int, int, RemovalCallback)} for listening to
3769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * fingerprint template removal events.
377ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
378ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
3799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
3809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public static abstract class RemovalCallback {
3819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when the given fingerprint can't be removed.
383ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param fp The fingerprint that the call attempted to remove
384ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errMsgId An associated error message id
385ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller         * @param errString An error message indicating why the fingerprint id can't be removed
3869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
387ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onRemovalError(Fingerprint fp, int errMsgId, CharSequence errString) { }
3889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
3899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        /**
3909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * Called when a given fingerprint is successfully removed.
3919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         * @param fingerprint the fingerprint template that was removed.
3929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller         */
393ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void onRemovalSucceeded(Fingerprint fingerprint) { }
39408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    };
39508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
39608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
3973a464785088e7fd206666f640912729533948ce8Jorim Jaggi     * @hide
3983a464785088e7fd206666f640912729533948ce8Jorim Jaggi     */
3993a464785088e7fd206666f640912729533948ce8Jorim Jaggi    public static abstract class LockoutResetCallback {
4003a464785088e7fd206666f640912729533948ce8Jorim Jaggi
4013a464785088e7fd206666f640912729533948ce8Jorim Jaggi        /**
4023a464785088e7fd206666f640912729533948ce8Jorim Jaggi         * Called when lockout period expired and clients are allowed to listen for fingerprint
4033a464785088e7fd206666f640912729533948ce8Jorim Jaggi         * again.
4043a464785088e7fd206666f640912729533948ce8Jorim Jaggi         */
4053a464785088e7fd206666f640912729533948ce8Jorim Jaggi        public void onLockoutReset() { }
4063a464785088e7fd206666f640912729533948ce8Jorim Jaggi    };
4073a464785088e7fd206666f640912729533948ce8Jorim Jaggi
4083a464785088e7fd206666f640912729533948ce8Jorim Jaggi    /**
409ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Request authentication of a crypto object. This call warms up the fingerprint hardware
410ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * and starts scanning for a fingerprint. It terminates when
4119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
4125f69ca3be3005fd127c82f503d0692f807729688Jim Miller     * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
4139f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * which point the object is no longer valid. The operation can be canceled by using the
4149f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * provided cancel object.
415d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller     *
4169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param crypto object associated with the call or null if none required.
4179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param cancel an object that can be used to cancel authentication
418ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @param flags optional flags; should be 0
419f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param callback an object to receive authentication events
420f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param handler an optional handler to handle callback events
421e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *
422e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     * @throws IllegalArgumentException if the crypto operation is not supported or is not backed
423e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *         by <a href="{@docRoot}training/articles/keystore.html">Android Keystore
424e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     *         facility</a>.
425e4c58e46419bdc1cbe94516bdded71f017534d9cJim Miller     * @throws IllegalStateException if the crypto primitive is not initialized.
426d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller     */
427f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
428ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
429f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
430f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId());
431ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    }
432ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi
433ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    /**
434f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * Use the provided handler thread for events.
435f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param handler
436f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     */
437f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    private void useHandler(Handler handler) {
438f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        if (handler != null) {
439f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler = new MyHandler(handler.getLooper());
440f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        } else if (mHandler.getLooper() != mContext.getMainLooper()){
441f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler = new MyHandler(mContext.getMainLooper());
442f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
443f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    }
444f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
445f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    /**
446f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * Per-user version
447ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi     * @hide
448ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi     */
449f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
450ccdfa93f609d3f306a35902df323939e266a7ab3Jorim Jaggi    public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
451f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
4529f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (callback == null) {
4539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            throw new IllegalArgumentException("Must supply an authentication callback");
4549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
4559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
456ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (cancel != null) {
457ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (cancel.isCanceled()) {
458ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                Log.w(TAG, "authentication already canceled");
459ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return;
460ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            } else {
461ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
462ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
463ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
4649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
4659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
466f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            useHandler(handler);
4679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mAuthenticationCallback = callback;
4689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mCryptoObject = crypto;
469ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            long sessionId = crypto != null ? crypto.getOpId() : 0;
4704af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
4714af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                    mContext.getOpPackageName());
4729f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
473ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception while authenticating: ", e);
474ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
475ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // Though this may not be a hardware issue, it will cause apps to give up or try
476ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // again later.
477ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
478ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
479ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
4809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
481d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    }
482d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller
483d08c2aceb238b02d8348518a2c87693054c6ce37Jim Miller    /**
4849f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Request fingerprint enrollment. This call warms up the fingerprint hardware
4859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * and starts scanning for fingerprints. Progress will be indicated by callbacks to the
4869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback} object. It terminates when
4879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback#onEnrollmentError(int, CharSequence)} or
4889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * {@link EnrollmentCallback#onEnrollmentProgress(int) is called with remaining == 0, at
4899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * which point the object is no longer valid. The operation can be canceled by using the
4909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * provided cancel object.
491fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * @param token a unique token provided by a recent creation or verification of device
492fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller     * credentials (e.g. pin, pattern or password).
4939f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param cancel an object that can be used to cancel enrollment
4949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param flags optional flags
495a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri     * @param userId the user to whom this fingerprint will belong to
496f501b58de8f467a80fef49c704555781bc61ea6fJim Miller     * @param callback an object to receive enrollment events
497ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
49808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
499f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
500f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    public void enroll(byte [] token, CancellationSignal cancel, int flags,
501a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri            int userId, EnrollmentCallback callback) {
502d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        if (userId == UserHandle.USER_CURRENT) {
503d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            userId = getCurrentUserId();
504d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        }
5059f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (callback == null) {
5069f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            throw new IllegalArgumentException("Must supply an enrollment callback");
50708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
5089f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
509ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (cancel != null) {
510ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (cancel.isCanceled()) {
511ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                Log.w(TAG, "enrollment already canceled");
512ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return;
513ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            } else {
514fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                cancel.setOnCancelListener(new OnEnrollCancelListener());
515ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
516ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
5179f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
51808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) try {
5199f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mEnrollmentCallback = callback;
520cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            mService.enroll(mToken, token, userId, mServiceReceiver, flags,
521cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    mContext.getOpPackageName());
522ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
523ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception in enroll: ", e);
524ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
525ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // Though this may not be a hardware issue, it will cause apps to give up or try
526ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                // again later.
527ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onEnrollmentError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
528ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
529ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
530ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
531ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
532ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
533ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    /**
534ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * Requests a pre-enrollment auth token to tie enrollment to the confirmation of
535ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * existing device credentials (e.g. pin/pattern/password).
536ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
537ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     */
538f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
539ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public long preEnroll() {
540ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        long result = 0;
541ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
542ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            result = mService.preEnroll(mToken);
54308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } catch (RemoteException e) {
544c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
54508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
546ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        return result;
54708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
54808fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
54908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
550e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     * Finishes enrollment and cancels the current auth token.
551e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     * @hide
552e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy     */
553e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    @RequiresPermission(MANAGE_FINGERPRINT)
554e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    public int postEnroll() {
555e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        int result = 0;
556e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        if (mService != null) try {
557e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            result = mService.postEnroll(mToken);
558e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        } catch (RemoteException e) {
559c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
560e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        }
561e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        return result;
562e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    }
563e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy
564e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    /**
565d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * Sets the active user. This is meant to be used to select the current profile for enrollment
566d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * to allow separate enrolled fingers for a work profile
567d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @param userId
568d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @hide
569d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     */
570d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    @RequiresPermission(MANAGE_FINGERPRINT)
571d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    public void setActiveUser(int userId) {
572d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        if (mService != null) try {
573d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            mService.setActiveUser(userId);
574d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        } catch (RemoteException e) {
575c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
576d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        }
577d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    }
578d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri
579d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    /**
5809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Remove given fingerprint template from fingerprint hardware and/or protected storage.
5819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param fp the fingerprint item to remove
582a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri     * @param userId the user who this fingerprint belongs to
5839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param callback an optional callback to verify that fingerprint templates have been
584ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * successfully removed. May be null of no callback is required.
585ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
5869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
58708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
588f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
589a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri    public void remove(Fingerprint fp, int userId, RemovalCallback callback) {
5909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
5919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mRemovalCallback = callback;
5929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mRemovalFingerprint = fp;
5938f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller            mService.remove(mToken, fp.getFingerId(), fp.getGroupId(), userId, mServiceReceiver);
5949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
595ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            Log.w(TAG, "Remote exception in remove: ", e);
596ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            if (callback != null) {
597ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                callback.onRemovalError(fp, FINGERPRINT_ERROR_HW_UNAVAILABLE,
598ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
599ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            }
60008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
60108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
60208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
60308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
6049f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Renames the given fingerprint template
6059f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param fpId the fingerprint id
606a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri     * @param userId the user who this fingerprint belongs to
6079f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @param newName the new name
608ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
6099f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
61008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
611f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(MANAGE_FINGERPRINT)
612a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri    public void rename(int fpId, int userId, String newName) {
6139f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        // Renames the given fpId
61408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) {
61508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            try {
616a5c1a77fad0ea3e2cbdf1dec773800cd77d6562eClara Bayarri                mService.rename(fpId, userId, newName);
61708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            } catch (RemoteException e) {
618c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
61908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            }
620a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        } else {
6219f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.w(TAG, "rename(): Service not connected!");
62208fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
62308fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
62408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
6259f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    /**
6269f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * Obtain the list of enrolled fingerprints templates.
6279f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @return list of current fingerprint items
628ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
629ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     * @hide
6309f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     */
631f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6322aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public List<Fingerprint> getEnrolledFingerprints(int userId) {
6339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService != null) try {
6344af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
63508fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } catch (RemoteException e) {
636c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
63708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
6389f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        return null;
63908fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    }
64008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller
64108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller    /**
6422aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Obtain the list of enrolled fingerprints templates.
6432aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return list of current fingerprint items
644ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller     *
6459f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller     * @hide
64608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller     */
647f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6482aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public List<Fingerprint> getEnrolledFingerprints() {
6492aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        return getEnrolledFingerprints(UserHandle.myUserId());
6502aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    }
6512aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi
6522aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    /**
6532aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Determine if there is at least one fingerprint enrolled.
6542aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     *
6552aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return true if at least one fingerprint is enrolled, false otherwise
6562aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     */
657f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6582aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    public boolean hasEnrolledFingerprints() {
6592aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        if (mService != null) try {
66033fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri            return mService.hasEnrolledFingerprints(
66133fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri                    UserHandle.myUserId(), mContext.getOpPackageName());
66233fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri        } catch (RemoteException e) {
663c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
66433fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri        }
66533fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri        return false;
66633fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri    }
66733fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri
66833fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri    /**
66933fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri     * @hide
67033fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri     */
67133fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri    @RequiresPermission(allOf = {
67233fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri            USE_FINGERPRINT,
67333fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri            INTERACT_ACROSS_USERS})
67433fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri    public boolean hasEnrolledFingerprints(int userId) {
67533fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri        if (mService != null) try {
67633fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri            return mService.hasEnrolledFingerprints(userId, mContext.getOpPackageName());
6772aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        } catch (RemoteException e) {
678c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
6792aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        }
6802aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        return false;
6812aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    }
6822aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi
6832aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    /**
6842aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * Determine if fingerprint hardware is present and functional.
6852aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     *
6862aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     * @return true if hardware is present and functional, false otherwise.
6872aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi     */
688f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    @RequiresPermission(USE_FINGERPRINT)
6899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public boolean isHardwareDetected() {
69008fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        if (mService != null) {
69108fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            try {
6929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                long deviceId = 0; /* TODO: plumb hardware id to FPMS */
6934af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return mService.isHardwareDetected(deviceId, mContext.getOpPackageName());
69408fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            } catch (RemoteException e) {
695c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
69608fa40c5cb5229b7969b2a5146855a337870f45aJim Miller            }
69708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        } else {
6989f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Log.w(TAG, "isFingerprintHardwareDetected(): Service not connected!");
699a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
7009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        return false;
701a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
702a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
7034d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    /**
7044d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * Retrieves the authenticator token for binding keys to the lifecycle
7054d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * of the current set of fingerprints. Used only by internal clients.
7064d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     *
7074d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     * @hide
7084d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales     */
7094d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    public long getAuthenticatorId() {
7104d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        if (mService != null) {
7114d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            try {
7124af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return mService.getAuthenticatorId(mContext.getOpPackageName());
7134d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            } catch (RemoteException e) {
714c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
7154d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            }
7164d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        } else {
7174d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales            Log.w(TAG, "getAuthenticatorId(): Service not connected!");
7184d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        }
7194d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        return 0;
7204d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales    }
7214d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales
722e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller    /**
723e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     * Reset the lockout timer when asked to do so by keyguard.
724e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     *
725e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     * @param token an opaque token returned by password confirmation.
726e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     *
727e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     * @hide
728e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller     */
729e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller    public void resetTimeout(byte[] token) {
730e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        if (mService != null) {
731e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            try {
732e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller                mService.resetTimeout(token);
733e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            } catch (RemoteException e) {
734c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
735e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            }
736e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        } else {
7373a464785088e7fd206666f640912729533948ce8Jorim Jaggi            Log.w(TAG, "resetTimeout(): Service not connected!");
7383a464785088e7fd206666f640912729533948ce8Jorim Jaggi        }
7393a464785088e7fd206666f640912729533948ce8Jorim Jaggi    }
7403a464785088e7fd206666f640912729533948ce8Jorim Jaggi
7413a464785088e7fd206666f640912729533948ce8Jorim Jaggi    /**
7423a464785088e7fd206666f640912729533948ce8Jorim Jaggi     * @hide
7433a464785088e7fd206666f640912729533948ce8Jorim Jaggi     */
7443a464785088e7fd206666f640912729533948ce8Jorim Jaggi    public void addLockoutResetCallback(final LockoutResetCallback callback) {
7453a464785088e7fd206666f640912729533948ce8Jorim Jaggi        if (mService != null) {
7463a464785088e7fd206666f640912729533948ce8Jorim Jaggi            try {
7475e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                final PowerManager powerManager = mContext.getSystemService(PowerManager.class);
7483a464785088e7fd206666f640912729533948ce8Jorim Jaggi                mService.addLockoutResetCallback(
7493a464785088e7fd206666f640912729533948ce8Jorim Jaggi                        new IFingerprintServiceLockoutResetCallback.Stub() {
7503a464785088e7fd206666f640912729533948ce8Jorim Jaggi
7513a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    @Override
7523a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    public void onLockoutReset(long deviceId) throws RemoteException {
7535e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                        final PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
7545e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                PowerManager.PARTIAL_WAKE_LOCK, "lockoutResetCallback");
7555e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                        wakeLock.acquire();
7563a464785088e7fd206666f640912729533948ce8Jorim Jaggi                        mHandler.post(new Runnable() {
7573a464785088e7fd206666f640912729533948ce8Jorim Jaggi                            @Override
7583a464785088e7fd206666f640912729533948ce8Jorim Jaggi                            public void run() {
7595e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                try {
7605e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                    callback.onLockoutReset();
7615e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                } finally {
7625e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                    wakeLock.release();
7635e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                                }
7643a464785088e7fd206666f640912729533948ce8Jorim Jaggi                            }
7653a464785088e7fd206666f640912729533948ce8Jorim Jaggi                        });
7663a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    }
7673a464785088e7fd206666f640912729533948ce8Jorim Jaggi                });
7683a464785088e7fd206666f640912729533948ce8Jorim Jaggi            } catch (RemoteException e) {
769c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey                throw e.rethrowFromSystemServer();
7703a464785088e7fd206666f640912729533948ce8Jorim Jaggi            }
7713a464785088e7fd206666f640912729533948ce8Jorim Jaggi        } else {
7723a464785088e7fd206666f640912729533948ce8Jorim Jaggi            Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
773e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        }
774e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller    }
775e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller
77624e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin    private class MyHandler extends Handler {
77724e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        private MyHandler(Context context) {
77824e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin            super(context.getMainLooper());
77924e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        }
78024e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin
781f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private MyHandler(Looper looper) {
782f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            super(looper);
783f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
784f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
785e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        @Override
7869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void handleMessage(android.os.Message msg) {
7879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            switch(msg.what) {
7889f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ENROLL_RESULT:
7899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendEnrollResult((Fingerprint) msg.obj, msg.arg1 /* remaining */);
7909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
7919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ACQUIRED:
7929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */);
7939f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
794f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                case MSG_AUTHENTICATION_SUCCEEDED:
795f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    sendAuthenticatedSucceeded((Fingerprint) msg.obj);
796f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    break;
797f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                case MSG_AUTHENTICATION_FAILED:
798f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                    sendAuthenticatedFailed();
7999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
8009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_ERROR:
8019f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */);
8029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    break;
8039f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                case MSG_REMOVED:
8049f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    sendRemovedResult((Long) msg.obj /* deviceId */, msg.arg1 /* fingerId */,
8059f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                            msg.arg2 /* groupId */);
8069f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
80708fa40c5cb5229b7969b2a5146855a337870f45aJim Miller        }
8089f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
8099f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendRemovedResult(long deviceId, int fingerId, int groupId) {
8109f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mRemovalCallback != null) {
8119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                int reqFingerId = mRemovalFingerprint.getFingerId();
8129f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                int reqGroupId = mRemovalFingerprint.getGroupId();
8138f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller                if (reqFingerId != 0 && fingerId != 0  &&  fingerId != reqFingerId) {
8149f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    Log.w(TAG, "Finger id didn't match: " + fingerId + " != " + reqFingerId);
8158f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller                    return;
8169f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
8171adb4a7693406e7f984d7b1512e0e6aa40aa40e2Jim Miller                if (groupId != reqGroupId) {
8189f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    Log.w(TAG, "Group id didn't match: " + groupId + " != " + reqGroupId);
8198f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller                    return;
8209f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
821f86f986728b5844a48e2e7bbd4927d2f5500c682Ricky Wai                mRemovalCallback.onRemovalSucceeded(new Fingerprint(null, groupId, fingerId,
822f86f986728b5844a48e2e7bbd4927d2f5500c682Ricky Wai                        deviceId));
823a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
824a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
825a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
8269f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendErrorResult(long deviceId, int errMsgId) {
8279f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
8289f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mEnrollmentCallback.onEnrollmentError(errMsgId, getErrorString(errMsgId));
8299f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mAuthenticationCallback != null) {
8309f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mAuthenticationCallback.onAuthenticationError(errMsgId, getErrorString(errMsgId));
8319f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mRemovalCallback != null) {
8329f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mRemovalCallback.onRemovalError(mRemovalFingerprint, errMsgId,
8339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                        getErrorString(errMsgId));
8349f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
8359f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8369f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
8379f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendEnrollResult(Fingerprint fp, int remaining) {
8389f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
8399f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mEnrollmentCallback.onEnrollmentProgress(remaining);
8409f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
8419f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8429f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
843f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private void sendAuthenticatedSucceeded(Fingerprint fp) {
8449f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mAuthenticationCallback != null) {
845f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
846f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                mAuthenticationCallback.onAuthenticationSucceeded(result);
847f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            }
848f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
849f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
850f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private void sendAuthenticatedFailed() {
851f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            if (mAuthenticationCallback != null) {
852f501b58de8f467a80fef49c704555781bc61ea6fJim Miller               mAuthenticationCallback.onAuthenticationFailed();
8539f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
8549f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8559f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
8569f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        private void sendAcquiredResult(long deviceId, int acquireInfo) {
8574cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            if (mAuthenticationCallback != null) {
8584cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi                mAuthenticationCallback.onAuthenticationAcquired(acquireInfo);
8594cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            }
8609f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            final String msg = getAcquiredString(acquireInfo);
8614cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            if (msg == null) {
8624cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi                return;
8634cfdcf5b0551e5656ea379c428e78b812c2e5cbeJorim Jaggi            }
8649f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            if (mEnrollmentCallback != null) {
8659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mEnrollmentCallback.onEnrollmentHelp(acquireInfo, msg);
8669f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            } else if (mAuthenticationCallback != null) {
8679f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                mAuthenticationCallback.onAuthenticationHelp(acquireInfo, msg);
8689f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            }
8699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
8709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
871ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
872ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    /**
873ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller     * @hide
874ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller     */
8759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    public FingerprintManager(Context context, IFingerprintService service) {
8769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        mContext = context;
8779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        mService = service;
8789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        if (mService == null) {
8799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            Slog.v(TAG, "FingerprintManagerService was null");
8809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
88124e9e966a85c416a94482fcd10dbdd10ceeb9e6cAlex Klyubin        mHandler = new MyHandler(context);
8829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    }
8839f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
8849f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private int getCurrentUserId() {
8859f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        try {
8869f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            return ActivityManagerNative.getDefault().getCurrentUser().id;
8879f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        } catch (RemoteException e) {
888c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
889ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
890ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    }
891ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
892fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    private void cancelEnrollment() {
893ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
894ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mService.cancelEnrollment(mToken);
895ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
896c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
897ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
898ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
899ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
900ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private void cancelAuthentication(CryptoObject cryptoObject) {
901ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        if (mService != null) try {
9024af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            mService.cancelAuthentication(mToken, mContext.getOpPackageName());
903ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        } catch (RemoteException e) {
904c53962d4ede82a03b62f0c8bb86bd0da090a15ebJeff Sharkey            throw e.rethrowFromSystemServer();
905ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
906ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
907ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
908ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private String getErrorString(int errMsg) {
909ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        switch (errMsg) {
910ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_UNABLE_TO_PROCESS:
911ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
912ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_unable_to_process);
913ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_HW_UNAVAILABLE:
914ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
915ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_hw_not_available);
916ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_NO_SPACE:
917ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
918ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_error_no_space);
919ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ERROR_TIMEOUT:
920fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_timeout);
921fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            case FINGERPRINT_ERROR_CANCELED:
922fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_canceled);
923fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            case FINGERPRINT_ERROR_LOCKOUT:
924fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller                return mContext.getString(com.android.internal.R.string.fingerprint_error_lockout);
925ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            default:
926ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                if (errMsg >= FINGERPRINT_ERROR_VENDOR_BASE) {
927ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    int msgNumber = errMsg - FINGERPRINT_ERROR_VENDOR_BASE;
928ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    String[] msgArray = mContext.getResources().getStringArray(
929ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                            com.android.internal.R.array.fingerprint_error_vendor);
930ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    if (msgNumber < msgArray.length) {
931ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        return msgArray[msgNumber];
932ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    }
9339f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
934ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return null;
935ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
936ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    }
93799d6019bead4705b7e126e65b856d538417d4934Jim Miller
938ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    private String getAcquiredString(int acquireInfo) {
939ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        switch (acquireInfo) {
940ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_GOOD:
941ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return null;
942ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_PARTIAL:
943ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
944ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_partial);
945ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_INSUFFICIENT:
946ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
947ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_insufficient);
948ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_IMAGER_DIRTY:
949ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
950ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_imager_dirty);
951ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_TOO_SLOW:
952ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
953ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_too_slow);
954ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            case FINGERPRINT_ACQUIRED_TOO_FAST:
955ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return mContext.getString(
956ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    com.android.internal.R.string.fingerprint_acquired_too_fast);
957ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            default:
958ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                if (acquireInfo >= FINGERPRINT_ACQUIRED_VENDOR_BASE) {
959ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    int msgNumber = acquireInfo - FINGERPRINT_ACQUIRED_VENDOR_BASE;
960ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    String[] msgArray = mContext.getResources().getStringArray(
961ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                            com.android.internal.R.array.fingerprint_acquired_vendor);
962ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    if (msgNumber < msgArray.length) {
963ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                        return msgArray[msgNumber];
964ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                    }
9659f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                }
966ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                return null;
96799d6019bead4705b7e126e65b856d538417d4934Jim Miller        }
96899d6019bead4705b7e126e65b856d538417d4934Jim Miller    }
9699f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
9709f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
9719f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
972f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
9739f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
9749f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
9759f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                    new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
9769f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
978f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
9799f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onAcquired(long deviceId, int acquireInfo) {
9809f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
9819f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9829f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
983f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
984f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) {
985f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget();
986f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
987f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
988f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
989f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        public void onAuthenticationFailed(long deviceId) {
990f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
9919f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9929f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
993f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
9949f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onError(long deviceId, int error) {
9959f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
9969f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
9979f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
998f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        @Override // binder call
9999f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        public void onRemoved(long deviceId, int fingerId, int groupId) {
10009f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller            mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
10019f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
10029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    };
10039f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
10044d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales}
1005