1959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He/* 2a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * Copyright (C) 2014 The Android Open Source Project 3a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * 4a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * Licensed under the Apache License, Version 2.0 (the "License"); 5a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * you may not use this file except in compliance with the License. 6a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * You may obtain a copy of the License at 7a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * 8a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * http://www.apache.org/licenses/LICENSE-2.0 9a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * 10a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * Unless required by applicable law or agreed to in writing, software 11a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * distributed under the License is distributed on an "AS IS" BASIS, 12a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * See the License for the specific language governing permissions and 14a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * limitations under the License. 15a7596147b43940cad3f76c53ed154ef088b9269bJim Miller */ 16a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 17a7596147b43940cad3f76c53ed154ef088b9269bJim Millerpackage com.android.server.fingerprint; 18a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 19959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport static android.Manifest.permission.INTERACT_ACROSS_USERS; 20959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport static android.Manifest.permission.MANAGE_FINGERPRINT; 21959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT; 22959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport static android.Manifest.permission.USE_FINGERPRINT; 2329b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles Heimport static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; 24959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He 2580db9baf9766dc40f9d1b6bf60797ee5cc64a48cSasha Levitskiyimport android.app.ActivityManager; 26975f145c018de9affffee5e89d94ce0ed78ad9dfJim Millerimport android.app.ActivityManager.RunningAppProcessInfo; 275e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.app.AlarmManager; 284af76a51d5082c740609563e07cf35f30bc2224eSvetoslavimport android.app.AppOpsManager; 295e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.app.PendingIntent; 306005b3f87b063ee7ab7e8877a6a8c90b480f3341Fyodor Kupolovimport android.app.SynchronousUserSwitchObserver; 315e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.content.BroadcastReceiver; 3229b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles Heimport android.content.ComponentName; 33a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.content.Context; 345e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.content.Intent; 355e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.content.IntentFilter; 36f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport android.content.pm.PackageManager; 37cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Millerimport android.content.pm.UserInfo; 38959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; 39959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback; 40959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.fingerprint.Fingerprint; 41959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.fingerprint.FingerprintManager; 4227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.hardware.fingerprint.IFingerprintClientActiveCallback; 43959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.fingerprint.IFingerprintService; 443a464785088e7fd206666f640912729533948ce8Jorim Jaggiimport android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback; 45959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.fingerprint.IFingerprintServiceReceiver; 464af76a51d5082c740609563e07cf35f30bc2224eSvetoslavimport android.os.Binder; 4757e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggiimport android.os.Bundle; 483a464785088e7fd206666f640912729533948ce8Jorim Jaggiimport android.os.DeadObjectException; 4980db9baf9766dc40f9d1b6bf60797ee5cc64a48cSasha Levitskiyimport android.os.Environment; 50a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.Handler; 51a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.IBinder; 5240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Millerimport android.os.IHwBinder; 5357e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggiimport android.os.IRemoteCallback; 54dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Millerimport android.os.PowerManager; 5557e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggiimport android.os.PowerManager.WakeLock; 56a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.RemoteException; 5716ef71f4f5a01158fdc07dbbd0963aa2fb04e359Jim Millerimport android.os.SELinux; 58dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Millerimport android.os.SystemClock; 59599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Millerimport android.os.UserHandle; 60cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Millerimport android.os.UserManager; 61959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.security.KeyStore; 621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoimport android.service.fingerprint.FingerprintActionStatsProto; 631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoimport android.service.fingerprint.FingerprintServiceDumpProto; 641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoimport android.service.fingerprint.FingerprintUserStatsProto; 65a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.util.Slog; 661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoimport android.util.proto.ProtoOutputStream; 67a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 68449e708abe4e1e85845d319dc701579a6b553c2cFyodor Kupolovimport com.android.internal.annotations.GuardedBy; 69c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport com.android.internal.logging.MetricsLogger; 70fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils; 71e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport com.android.server.SystemServerInitThreadPool; 72a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport com.android.server.SystemService; 73a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 74c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport org.json.JSONArray; 75c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport org.json.JSONException; 76c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport org.json.JSONObject; 77c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren 7880db9baf9766dc40f9d1b6bf60797ee5cc64a48cSasha Levitskiyimport java.io.File; 79c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport java.io.FileDescriptor; 80c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport java.io.PrintWriter; 813a464785088e7fd206666f640912729533948ce8Jorim Jaggiimport java.util.ArrayList; 824af76a51d5082c740609563e07cf35f30bc2224eSvetoslavimport java.util.Collections; 83bcc100aae93bdae85c3f3679dfdda0508450f94eJim Millerimport java.util.HashMap; 8429b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles Heimport java.util.LinkedList; 859f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport java.util.List; 86da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles Heimport java.util.Map; 8727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport java.util.concurrent.CopyOnWriteArrayList; 88a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 89a7596147b43940cad3f76c53ed154ef088b9269bJim Miller/** 90a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * A service to manage multiple clients that want to access the fingerprint HAL API. 91a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * The service is responsible for maintaining a list of clients and dispatching all 92a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * fingerprint -related events. 93a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * 94a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * @hide 95a7596147b43940cad3f76c53ed154ef088b9269bJim Miller */ 9640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Millerpublic class FingerprintService extends SystemService implements IHwBinder.DeathRecipient { 97cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller static final String TAG = "FingerprintService"; 98cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller static final boolean DEBUG = true; 99d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn private static final boolean CLEANUP_UNUSED_FP = false; 100be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller private static final String FP_DATA_DIR = "fpdata"; 101be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller private static final int MSG_USER_SWITCHING = 10; 1025e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi private static final String ACTION_LOCKOUT_RESET = 1035e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi "com.android.server.fingerprint.ACTION_LOCKOUT_RESET"; 104be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 105bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller private class PerformanceStats { 106bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller int accept; // number of accepted fingerprints 107bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller int reject; // number of rejected fingerprints 108bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller int acquire; // total number of acquisitions. Should be >= accept+reject due to poor image 109bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller // acquisition in some cases (too fast, too slow, dirty sensor, etc.) 110bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller int lockout; // total number of lockouts 111df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn int permanentLockout; // total number of permanent lockouts 112bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller } 113bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller 1143a464785088e7fd206666f640912729533948ce8Jorim Jaggi private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors = 1153a464785088e7fd206666f640912729533948ce8Jorim Jaggi new ArrayList<>(); 11627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks = 11727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver new CopyOnWriteArrayList<>(); 118da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He private final Map<Integer, Long> mAuthenticatorIds = 119da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He Collections.synchronizedMap(new HashMap<>()); 1204af76a51d5082c740609563e07cf35f30bc2224eSvetoslav private final AppOpsManager mAppOps; 121af281ca0d3fad6aaafde0d1979123368390779dcJim Miller private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000; 122df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5; 123df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20; 124df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn 1253d5e396583a845e63e102ff449d856c01125f550Jim Miller private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms 126975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller private final String mKeyguardPackage; 127959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He private int mCurrentUserId = UserHandle.USER_NULL; 128cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance(); 129cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private Context mContext; 130cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private long mHalDeviceId; 131df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn private boolean mTimedLockoutCleared; 132cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private int mFailedAttempts; 133449e708abe4e1e85845d319dc701579a6b553c2cFyodor Kupolov @GuardedBy("this") 13440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller private IBiometricsFingerprint mDaemon; 135cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private final PowerManager mPowerManager; 136cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private final AlarmManager mAlarmManager; 137cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private final UserManager mUserManager; 138cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private ClientMonitor mCurrentClient; 139cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private ClientMonitor mPendingClient; 140bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller private PerformanceStats mPerformanceStats; 141bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller 142d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 143d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration 144d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn private LinkedList<Integer> mEnumeratingUserIds = new LinkedList<>(); 145d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw finterprints 146d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 147d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn private class UserFingerprint { 148d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn Fingerprint f; 149d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn int userId; 150d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn public UserFingerprint(Fingerprint f, int userId) { 151d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn this.f = f; 152d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn this.userId = userId; 153d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 154d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 155d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 156bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller // Normal fingerprint authentications are tracked by mPerformanceMap. 15740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>(); 158bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller 159bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller // Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap. 16040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller private HashMap<Integer, PerformanceStats> mCryptoPerformanceMap = new HashMap<>(); 161ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 162cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private Handler mHandler = new Handler() { 16380a776e5fecef1160aa9d2b9fdaf7bf9d9c95973Jim Miller @Override 164a7596147b43940cad3f76c53ed154ef088b9269bJim Miller public void handleMessage(android.os.Message msg) { 165a7596147b43940cad3f76c53ed154ef088b9269bJim Miller switch (msg.what) { 166aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi case MSG_USER_SWITCHING: 167aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi handleUserSwitching(msg.arg1); 168aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi break; 169aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi 170a7596147b43940cad3f76c53ed154ef088b9269bJim Miller default: 171a7596147b43940cad3f76c53ed154ef088b9269bJim Miller Slog.w(TAG, "Unknown message:" + msg.what); 172a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 173a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 174a7596147b43940cad3f76c53ed154ef088b9269bJim Miller }; 175be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 1765e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi private final BroadcastReceiver mLockoutReceiver = new BroadcastReceiver() { 1775e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi @Override 1785e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi public void onReceive(Context context, Intent intent) { 1795e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi if (ACTION_LOCKOUT_RESET.equals(intent.getAction())) { 180df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn resetFailedAttempts(false /* clearAttemptCounter */); 1815e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi } 1825e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi } 1835e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi }; 1845e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi 1855e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi private final Runnable mResetFailedAttemptsRunnable = new Runnable() { 186fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller @Override 187fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller public void run() { 188df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn resetFailedAttempts(true /* clearAttemptCounter */); 189fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 190fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller }; 191a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 192cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private final Runnable mResetClientState = new Runnable() { 193cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller @Override 194cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller public void run() { 195cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // Warning: if we get here, the driver never confirmed our call to cancel the current 196cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // operation (authenticate, enroll, remove, enumerate, etc), which is 197cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // really bad. The result will be a 3-second delay in starting each new client. 198cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // If you see this on a device, make certain the driver notifies with 199cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // {@link FingerprintManager#FINGERPRINT_ERROR_CANCEL} in response to cancel() 200cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // once it has successfully switched to the IDLE state in the fingerprint HAL. 201cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // Additionally,{@link FingerprintManager#FINGERPRINT_ERROR_CANCEL} should only be sent 202cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // in response to an actual cancel() call. 203cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller Slog.w(TAG, "Client " 204cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller + (mCurrentClient != null ? mCurrentClient.getOwnerString() : "null") 205cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller + " failed to respond to cancel, starting client " 206cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller + (mPendingClient != null ? mPendingClient.getOwnerString() : "null")); 207d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 208cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller mCurrentClient = null; 209cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller startClient(mPendingClient, false); 210cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 211cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller }; 212cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller 213a7596147b43940cad3f76c53ed154ef088b9269bJim Miller public FingerprintService(Context context) { 214a7596147b43940cad3f76c53ed154ef088b9269bJim Miller super(context); 215a7596147b43940cad3f76c53ed154ef088b9269bJim Miller mContext = context; 216975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString( 217975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller com.android.internal.R.string.config_keyguardComponent)).getPackageName(); 2184af76a51d5082c740609563e07cf35f30bc2224eSvetoslav mAppOps = context.getSystemService(AppOpsManager.class); 2195e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi mPowerManager = mContext.getSystemService(PowerManager.class); 2205e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi mAlarmManager = mContext.getSystemService(AlarmManager.class); 2215e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi mContext.registerReceiver(mLockoutReceiver, new IntentFilter(ACTION_LOCKOUT_RESET), 2225e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi RESET_FINGERPRINT_LOCKOUT, null /* handler */); 223d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri mUserManager = UserManager.get(mContext); 224be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 225be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 226be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override 22740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller public void serviceDied(long cookie) { 22880e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn Slog.v(TAG, "fingerprint HAL died"); 229c57c8d934cf77673154bc81d767365b4d6cda33fJim Miller MetricsLogger.count(mContext, "fingerprintd_died", 1); 23040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, 23140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller 0 /*vendorCode */); 232be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 233be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 23440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller public synchronized IBiometricsFingerprint getFingerprintDaemon() { 23540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller if (mDaemon == null) { 2368eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller Slog.v(TAG, "mDeamon was null, reconnect to fingerprint"); 23740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller try { 23825d5eaa14ccdfa767588f9b15d05ec37d860fbc7Yifan Hong mDaemon = IBiometricsFingerprint.getService(); 23940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } catch (java.util.NoSuchElementException e) { 24040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller // Service doesn't exist or cannot be opened. Logged below. 24140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } catch (RemoteException e) { 24240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller Slog.e(TAG, "Failed to get biometric interface", e); 24340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } 244449e708abe4e1e85845d319dc701579a6b553c2cFyodor Kupolov if (mDaemon == null) { 24540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller Slog.w(TAG, "fingerprint HIDL not available"); 24640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller return null; 24740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } 24840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller 24940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller mDaemon.asBinder().linkToDeath(this, 0); 25040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller 25140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller try { 25240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller mHalDeviceId = mDaemon.setNotify(mDaemonCallback); 25340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } catch (RemoteException e) { 25480e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn Slog.e(TAG, "Failed to open fingerprint HAL", e); 25540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller mDaemon = null; // try again later! 25640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } 25740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller 25840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId); 25940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller if (mHalDeviceId != 0) { 260da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He loadAuthenticatorIds(); 26140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller updateActiveGroup(ActivityManager.getCurrentUser(), null); 262d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn doFingerprintCleanup(ActivityManager.getCurrentUser()); 26340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } else { 26440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller Slog.w(TAG, "Failed to open Fingerprint HAL!"); 26540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1); 26640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller mDaemon = null; 267be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 268be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 26940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller return mDaemon; 270be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 271be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 272da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He /** Populates existing authenticator ids. To be used only during the start of the service. */ 273da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He private void loadAuthenticatorIds() { 274da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He // This operation can be expensive, so keep track of the elapsed time. Might need to move to 275da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He // background if it takes too long. 276da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He long t = System.currentTimeMillis(); 277da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He mAuthenticatorIds.clear(); 278da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) { 279da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He int userId = getUserOrWorkProfileId(null, user.id); 280da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He if (!mAuthenticatorIds.containsKey(userId)) { 281da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He updateActiveGroup(userId, null); 282da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He } 283da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He } 284da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He 285da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He t = System.currentTimeMillis() - t; 286da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He if (t > 1000) { 287da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He Slog.w(TAG, "loadAuthenticatorIds() taking too long: " + t + "ms"); 288da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He } 289da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He } 290da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He 291d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn private void doFingerprintCleanup(int userId) { 292d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (CLEANUP_UNUSED_FP) { 293d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn resetEnumerateState(); 294d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn mEnumeratingUserIds.push(userId); 295d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn enumerateNextUser(); 296d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 297d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 298d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 299d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn private void resetEnumerateState() { 300d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (DEBUG) Slog.v(TAG, "Enumerate cleaning up"); 301d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn mEnumeratingUserIds.clear(); 302d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn mUnknownFingerprints.clear(); 303d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 304d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 305d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn private void enumerateNextUser() { 306d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn int nextUser = mEnumeratingUserIds.getFirst(); 307d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn updateActiveGroup(nextUser, null); 308d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn boolean restricted = !hasPermission(MANAGE_FINGERPRINT); 309d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 310d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (DEBUG) Slog.v(TAG, "Enumerating user id " + nextUser + " of " 311d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn + mEnumeratingUserIds.size() + " remaining users"); 312d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 313d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn startEnumerate(mToken, nextUser, null, restricted, true /* internal */); 314d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 315d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 316d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn // Remove unknown fingerprints from hardware 317d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn private void cleanupUnknownFingerprints() { 318d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (!mUnknownFingerprints.isEmpty()) { 319d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn Slog.w(TAG, "unknown fingerprint size: " + mUnknownFingerprints.size()); 320d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn UserFingerprint uf = mUnknownFingerprints.get(0); 321d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn mUnknownFingerprints.remove(uf); 322d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn boolean restricted = !hasPermission(MANAGE_FINGERPRINT); 323d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn updateActiveGroup(uf.userId, null); 324d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn startRemove(mToken, uf.f.getFingerId(), uf.f.getGroupId(), uf.userId, null, 325d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn restricted, true /* internal */); 326d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } else { 327d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn resetEnumerateState(); 328d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 329d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 330d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 33140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) { 332d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId 333d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn + ", gid=" + groupId 334d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn + ", dev=" + deviceId 335d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn + ", rem=" + remaining); 336d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 337d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn ClientMonitor client = mCurrentClient; 338d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 339d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if ( !(client instanceof InternalRemovalClient) && !(client instanceof EnumerateClient) ) { 340d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn return; 341d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 342d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn client.onEnumerationResult(fingerId, groupId, remaining); 343d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 344d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn // All fingerprints in hardware for this user were enumerated 345d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (remaining == 0) { 346d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn mEnumeratingUserIds.poll(); 347d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 348d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (client instanceof InternalEnumerateClient) { 349d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn List<Fingerprint> enrolled = ((InternalEnumerateClient) client).getEnumeratedList(); 350d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn Slog.w(TAG, "Added " + enrolled.size() + " enumerated fingerprints for deletion"); 351d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn for (Fingerprint f : enrolled) { 352d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn mUnknownFingerprints.add(new UserFingerprint(f, client.getTargetUserId())); 353d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 354d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 355d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 356d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn removeClient(client); 357d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 358d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (!mEnumeratingUserIds.isEmpty()) { 359d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn enumerateNextUser(); 360d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } else if (client instanceof InternalEnumerateClient) { 361d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (DEBUG) Slog.v(TAG, "Finished enumerating all users"); 362d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn // This will start a chain of InternalRemovalClients 363d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn cleanupUnknownFingerprints(); 364d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 365d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 366be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 367be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 36840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller protected void handleError(long deviceId, int error, int vendorCode) { 369cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller ClientMonitor client = mCurrentClient; 370d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (client instanceof InternalRemovalClient || client instanceof InternalEnumerateClient) { 371d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn resetEnumerateState(); 372d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 37340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller if (client != null && client.onError(error, vendorCode)) { 37407dbd63153b523f960eb7052a852661303aa7eacJim Miller removeClient(client); 375be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 376df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn 377cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "handleError(client=" 378c1e61b83c2fc3fa7a7111ec72081a8fa647bc354Jim Miller + (client != null ? client.getOwnerString() : "null") + ", error = " + error + ")"); 379cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // This is the magic code that starts the next client when the old client finishes. 380cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (error == FingerprintManager.FINGERPRINT_ERROR_CANCELED) { 381cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller mHandler.removeCallbacks(mResetClientState); 382cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (mPendingClient != null) { 383cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "start pending client " + mPendingClient.getOwnerString()); 384cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller startClient(mPendingClient, false); 385cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller mPendingClient = null; 386cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 3878eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller } else if (error == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) { 3888eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller // If we get HW_UNAVAILABLE, try to connect again later... 3898eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller Slog.w(TAG, "Got ERROR_HW_UNAVAILABLE; try reconnecting next client."); 3908eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller synchronized (this) { 3918eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller mDaemon = null; 3928eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller mHalDeviceId = 0; 393959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He mCurrentUserId = UserHandle.USER_NULL; 3948eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller } 395cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 396be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 397be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 39840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) { 399d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (DEBUG) Slog.w(TAG, "Removed: fid=" + fingerId 400d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn + ", gid=" + groupId 401d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn + ", dev=" + deviceId 402d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn + ", rem=" + remaining); 403d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 404cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller ClientMonitor client = mCurrentClient; 40540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller if (client != null && client.onRemoved(fingerId, groupId, remaining)) { 406cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller removeClient(client); 40729b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He // When the last fingerprint of a group is removed, update the authenticator id 40829b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He if (!hasEnrolledFingerprints(groupId)) { 40929b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He updateActiveGroup(groupId, null); 41029b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He } 411ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 412d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (client instanceof InternalRemovalClient && !mUnknownFingerprints.isEmpty()) { 413d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn cleanupUnknownFingerprints(); 414d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } else if (client instanceof InternalRemovalClient){ 415d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn resetEnumerateState(); 416d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 417be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 418be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 419a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller protected void handleAuthenticated(long deviceId, int fingerId, int groupId, 420a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller ArrayList<Byte> token) { 421cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller ClientMonitor client = mCurrentClient; 422a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller if (fingerId != 0) { 423a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller // Ugh... 424a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller final byte[] byteToken = new byte[token.size()]; 425a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller for (int i = 0; i < token.size(); i++) { 426a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller byteToken[i] = token.get(i); 427a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller } 428a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller // Send to Keystore 429a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller KeyStore.getInstance().addAuthToken(byteToken); 430a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller } 431cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (client != null && client.onAuthenticated(fingerId, groupId)) { 432cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller removeClient(client); 433ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 434bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller if (fingerId != 0) { 435bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller mPerformanceStats.accept++; 436bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller } else { 437bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller mPerformanceStats.reject++; 438bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller } 439be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 440be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 44140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller protected void handleAcquired(long deviceId, int acquiredInfo, int vendorCode) { 442cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller ClientMonitor client = mCurrentClient; 44340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller if (client != null && client.onAcquired(acquiredInfo, vendorCode)) { 444cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller removeClient(client); 445ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 446df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE 447bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller && client instanceof AuthenticationClient) { 448bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller // ignore enrollment acquisitions or acquisitions when we're locked out 449bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller mPerformanceStats.acquire++; 450bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller } 451dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Miller } 452be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 4538b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller protected void handleEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { 454cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller ClientMonitor client = mCurrentClient; 455cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (client != null && client.onEnrollResult(fingerId, groupId, remaining)) { 456cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller removeClient(client); 45729b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He // When enrollment finishes, update this group's authenticator id, as the HAL has 45829b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He // already generated a new authenticator id when the new fingerprint is enrolled. 45929b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He updateActiveGroup(groupId, null); 460a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 461a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 462a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 4638b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller private void userActivity() { 4648b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller long now = SystemClock.uptimeMillis(); 4658b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); 4668b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller } 4678b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller 4688b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller void handleUserSwitching(int userId) { 469d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri updateActiveGroup(userId, null); 470d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn doFingerprintCleanup(userId); 4718b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller } 4728b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller 473be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller private void removeClient(ClientMonitor client) { 474cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (client != null) { 475cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller client.destroy(); 476cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (client != mCurrentClient && mCurrentClient != null) { 477cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller Slog.w(TAG, "Unexpected client: " + client.getOwnerString() + "expected: " 478cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller + mCurrentClient != null ? mCurrentClient.getOwnerString() : "null"); 479cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 480cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 481cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (mCurrentClient != null) { 482cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "Done with client: " + client.getOwnerString()); 483cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller mCurrentClient = null; 484fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 48527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver if (mPendingClient == null) { 48627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver notifyClientActiveCallbacks(false); 48727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver } 488fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 489fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller 490df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn private int getLockoutMode() { 491df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn if (mFailedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) { 492df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn return AuthenticationClient.LOCKOUT_PERMANENT; 493df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn } else if (mFailedAttempts > 0 && mTimedLockoutCleared == false && 494df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn (mFailedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) { 495df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn return AuthenticationClient.LOCKOUT_TIMED; 496df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn } 497df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn return AuthenticationClient.LOCKOUT_NONE; 498fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 499fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller 5005e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi private void scheduleLockoutReset() { 5015e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 5025e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS, getLockoutResetIntent()); 5035e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi } 5045e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi 5055e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi private void cancelLockoutReset() { 5065e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi mAlarmManager.cancel(getLockoutResetIntent()); 5075e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi } 5085e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi 5095e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi private PendingIntent getLockoutResetIntent() { 5105e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi return PendingIntent.getBroadcast(mContext, 0, 5115e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi new Intent(ACTION_LOCKOUT_RESET), PendingIntent.FLAG_UPDATE_CURRENT); 5125e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi } 5135e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi 514ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public long startPreEnroll(IBinder token) { 51540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller IBiometricsFingerprint daemon = getFingerprintDaemon(); 516be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller if (daemon == null) { 51780e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn Slog.w(TAG, "startPreEnroll: no fingerprint HAL!"); 518be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller return 0; 519be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 520be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller try { 521be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller return daemon.preEnroll(); 522be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } catch (RemoteException e) { 523be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller Slog.e(TAG, "startPreEnroll failed", e); 524be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 525be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller return 0; 526ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 527ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 528e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy public int startPostEnroll(IBinder token) { 52940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller IBiometricsFingerprint daemon = getFingerprintDaemon(); 530e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy if (daemon == null) { 53180e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn Slog.w(TAG, "startPostEnroll: no fingerprint HAL!"); 532e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy return 0; 533e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy } 534e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy try { 535e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy return daemon.postEnroll(); 536e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy } catch (RemoteException e) { 537e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy Slog.e(TAG, "startPostEnroll failed", e); 538e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy } 539e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy return 0; 540e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy } 541e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy 54280a776e5fecef1160aa9d2b9fdaf7bf9d9c95973Jim Miller /** 54380e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn * Calls fingerprint HAL to switch states to the new task. If there's already a current task, 544cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller * it calls cancel() and sets mPendingClient to begin when the current task finishes 545cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller * ({@link FingerprintManager#FINGERPRINT_ERROR_CANCELED}). 546cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller * @param newClient the new client that wants to connect 547cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller * @param initiatedByClient true for authenticate, remove and enroll 54880a776e5fecef1160aa9d2b9fdaf7bf9d9c95973Jim Miller */ 549cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller private void startClient(ClientMonitor newClient, boolean initiatedByClient) { 550cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller ClientMonitor currentClient = mCurrentClient; 551cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (currentClient != null) { 552cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString()); 553d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (currentClient instanceof InternalEnumerateClient || 554d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn currentClient instanceof InternalRemovalClient) { 555d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn // This condition means we're currently running internal diagnostics to 556d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn // remove extra fingerprints in the hardware and/or the software 557d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn // TODO: design an escape hatch in case client never finishes 558d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 559d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn else { 560d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn currentClient.stop(initiatedByClient); 561d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 562cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller mPendingClient = newClient; 563cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller mHandler.removeCallbacks(mResetClientState); 564cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT); 565cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } else if (newClient != null) { 566cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller mCurrentClient = newClient; 567cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "starting client " 568cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller + newClient.getClass().getSuperclass().getSimpleName() 569cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller + "(" + newClient.getOwnerString() + ")" 570cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller + ", initiatedByClient = " + initiatedByClient + ")"); 57127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver notifyClientActiveCallbacks(true); 57227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver 573cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller newClient.start(); 5741304137918e41d1ad98555d9d7daf77583407d3fJim Miller } 575a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 576a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 5778f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller void startRemove(IBinder token, int fingerId, int groupId, int userId, 578d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) { 57940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller IBiometricsFingerprint daemon = getFingerprintDaemon(); 580be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller if (daemon == null) { 58180e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn Slog.w(TAG, "startRemove: no fingerprint HAL!"); 582be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller return; 583be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 584f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 585d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (internal) { 586d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn Context context = getContext(); 587d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn InternalRemovalClient client = new InternalRemovalClient(context, mHalDeviceId, 588d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn token, receiver, fingerId, groupId, userId, restricted, 589d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn context.getOpPackageName()) { 590d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn @Override 591d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn public void notifyUserActivity() { 592d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 593d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 594d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn @Override 595d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn public IBiometricsFingerprint getFingerprintDaemon() { 596d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn return FingerprintService.this.getFingerprintDaemon(); 597d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 598d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn }; 599d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn startClient(client, true); 600d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 601d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn else { 602d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token, 603d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn receiver, fingerId, groupId, userId, restricted, token.toString()) { 604d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn @Override 605d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn public void notifyUserActivity() { 606d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn FingerprintService.this.userActivity(); 607d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 608d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 609d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn @Override 610d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn public IBiometricsFingerprint getFingerprintDaemon() { 611d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn return FingerprintService.this.getFingerprintDaemon(); 612d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 613d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn }; 614d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn startClient(client, true); 615d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 61640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } 61740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller 61840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller void startEnumerate(IBinder token, int userId, 619d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) { 62040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller IBiometricsFingerprint daemon = getFingerprintDaemon(); 62140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller if (daemon == null) { 62280e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn Slog.w(TAG, "startEnumerate: no fingerprint HAL!"); 62340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller return; 62440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } 625d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn if (internal) { 626d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn List<Fingerprint> enrolledList = getEnrolledFingerprints(userId); 627d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn Context context = getContext(); 628d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn InternalEnumerateClient client = new InternalEnumerateClient(context, mHalDeviceId, 629d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn token, receiver, userId, userId, restricted, context.getOpPackageName(), 630d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn enrolledList) { 631d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn @Override 632d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn public void notifyUserActivity() { 633f8ff36c47f9f8d60cf825e6b43eb75d1eae81df5Kevin Chyn 634d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 635d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 636d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn @Override 637d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn public IBiometricsFingerprint getFingerprintDaemon() { 638d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn return FingerprintService.this.getFingerprintDaemon(); 639d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 640d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn }; 641d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn startClient(client, true); 642d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 643d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn else { 644d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token, 645d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn receiver, userId, userId, restricted, token.toString()) { 646d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn @Override 647d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn public void notifyUserActivity() { 648d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn FingerprintService.this.userActivity(); 649d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 650d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn 651d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn @Override 652d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn public IBiometricsFingerprint getFingerprintDaemon() { 653d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn return FingerprintService.this.getFingerprintDaemon(); 654d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 655d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn }; 656d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn startClient(client, true); 657d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn } 658a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 659a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 660599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller public List<Fingerprint> getEnrolledFingerprints(int userId) { 661599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller return mFingerprintUtils.getFingerprintsForUser(mContext, userId); 6629f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 6639f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 664599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller public boolean hasEnrolledFingerprints(int userId) { 6651fd298bdcb192b6a513216773d4de58a505da665Jim Miller if (userId != UserHandle.getCallingUserId()) { 66633fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri checkPermission(INTERACT_ACROSS_USERS); 66733fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri } 668599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0; 6692aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi } 6702aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi 671f501b58de8f467a80fef49c704555781bc61ea6fJim Miller boolean hasPermission(String permission) { 672f501b58de8f467a80fef49c704555781bc61ea6fJim Miller return getContext().checkCallingOrSelfPermission(permission) 673f501b58de8f467a80fef49c704555781bc61ea6fJim Miller == PackageManager.PERMISSION_GRANTED; 674f501b58de8f467a80fef49c704555781bc61ea6fJim Miller } 675f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 676ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller void checkPermission(String permission) { 6779f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller getContext().enforceCallingOrSelfPermission(permission, 6789f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller "Must have " + permission + " permission."); 679a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 680a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 681494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales int getEffectiveUserId(int userId) { 682494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales UserManager um = UserManager.get(mContext); 683494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales if (um != null) { 684494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales final long callingIdentity = Binder.clearCallingIdentity(); 685494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales userId = um.getCredentialOwnerProfile(userId); 686494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales Binder.restoreCallingIdentity(callingIdentity); 687494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales } else { 688494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales Slog.e(TAG, "Unable to acquire UserManager"); 689494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales } 690494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales return userId; 691494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales } 692494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales 693cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller boolean isCurrentUserOrProfile(int userId) { 694cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller UserManager um = UserManager.get(mContext); 695da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He if (um == null) { 696da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He Slog.e(TAG, "Unable to acquire UserManager"); 697da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He return false; 698da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He } 699cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller 700da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He final long token = Binder.clearCallingIdentity(); 701da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He try { 702da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He // Allow current user or profiles of the current user... 703959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) { 704da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He if (profileId == userId) { 705da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He return true; 706da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He } 707cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller } 708da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He } finally { 709da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He Binder.restoreCallingIdentity(token); 710cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller } 711959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He 712959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He return false; 713cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller } 714cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller 715975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller private boolean isForegroundActivity(int uid, int pid) { 716975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller try { 717975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller List<RunningAppProcessInfo> procs = 718dc589ac82b5fe2063f4cfd94c8ae26d43d5420a0Sudheer Shanka ActivityManager.getService().getRunningAppProcesses(); 719975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller int N = procs.size(); 720975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller for (int i = 0; i < N; i++) { 721975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller RunningAppProcessInfo proc = procs.get(i); 722975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller if (proc.pid == pid && proc.uid == uid 723975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller && proc.importance == IMPORTANCE_FOREGROUND) { 724975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller return true; 725975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller } 726975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller } 727975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller } catch (RemoteException e) { 728975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller Slog.w(TAG, "am.getRunningAppProcesses() failed"); 729975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller } 730975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller return false; 731975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller } 732975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller 733975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller /** 734975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller * @param opPackageName name of package for caller 73537979c9db0a88039bb098645f4180dc04e987b96Jim Miller * @param requireForeground only allow this call while app is in the foreground 736975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller * @return true if caller can use fingerprint API 737975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller */ 73837979c9db0a88039bb098645f4180dc04e987b96Jim Miller private boolean canUseFingerprint(String opPackageName, boolean requireForeground, int uid, 739f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn int pid, int userId) { 7404af76a51d5082c740609563e07cf35f30bc2224eSvetoslav checkPermission(USE_FINGERPRINT); 741d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri if (isKeyguard(opPackageName)) { 742975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller return true; // Keyguard is always allowed 743975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller } 744f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn if (!isCurrentUserOrProfile(userId)) { 745975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller Slog.w(TAG,"Rejecting " + opPackageName + " ; not a current user or profile"); 746975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller return false; 747975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller } 748975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName) 749975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller != AppOpsManager.MODE_ALLOWED) { 7501adb4a7693406e7f984d7b1512e0e6aa40aa40e2Jim Miller Slog.w(TAG, "Rejecting " + opPackageName + " ; permission denied"); 751975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller return false; 752975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller } 75337979c9db0a88039bb098645f4180dc04e987b96Jim Miller if (requireForeground && !(isForegroundActivity(uid, pid) || currentClient(opPackageName))){ 7541adb4a7693406e7f984d7b1512e0e6aa40aa40e2Jim Miller Slog.w(TAG, "Rejecting " + opPackageName + " ; not in foreground"); 755975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller return false; 756975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller } 757975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller return true; 7584af76a51d5082c740609563e07cf35f30bc2224eSvetoslav } 7594af76a51d5082c740609563e07cf35f30bc2224eSvetoslav 760d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri /** 76137979c9db0a88039bb098645f4180dc04e987b96Jim Miller * @param opPackageName package of the caller 76237979c9db0a88039bb098645f4180dc04e987b96Jim Miller * @return true if this is the same client currently using fingerprint 76337979c9db0a88039bb098645f4180dc04e987b96Jim Miller */ 76437979c9db0a88039bb098645f4180dc04e987b96Jim Miller private boolean currentClient(String opPackageName) { 76537979c9db0a88039bb098645f4180dc04e987b96Jim Miller return mCurrentClient != null && mCurrentClient.getOwnerString().equals(opPackageName); 76637979c9db0a88039bb098645f4180dc04e987b96Jim Miller } 76737979c9db0a88039bb098645f4180dc04e987b96Jim Miller 76837979c9db0a88039bb098645f4180dc04e987b96Jim Miller /** 769d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri * @param clientPackage 770d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri * @return true if this is keyguard package 771d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri */ 772d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri private boolean isKeyguard(String clientPackage) { 773d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri return mKeyguardPackage.equals(clientPackage); 774d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri } 775d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri 7763a464785088e7fd206666f640912729533948ce8Jorim Jaggi private void addLockoutResetMonitor(FingerprintServiceLockoutResetMonitor monitor) { 7773a464785088e7fd206666f640912729533948ce8Jorim Jaggi if (!mLockoutMonitors.contains(monitor)) { 7783a464785088e7fd206666f640912729533948ce8Jorim Jaggi mLockoutMonitors.add(monitor); 7793a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 7803a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 7813a464785088e7fd206666f640912729533948ce8Jorim Jaggi 7823a464785088e7fd206666f640912729533948ce8Jorim Jaggi private void removeLockoutResetCallback( 7833a464785088e7fd206666f640912729533948ce8Jorim Jaggi FingerprintServiceLockoutResetMonitor monitor) { 7843a464785088e7fd206666f640912729533948ce8Jorim Jaggi mLockoutMonitors.remove(monitor); 7853a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 7863a464785088e7fd206666f640912729533948ce8Jorim Jaggi 7873a464785088e7fd206666f640912729533948ce8Jorim Jaggi private void notifyLockoutResetMonitors() { 7883a464785088e7fd206666f640912729533948ce8Jorim Jaggi for (int i = 0; i < mLockoutMonitors.size(); i++) { 7893a464785088e7fd206666f640912729533948ce8Jorim Jaggi mLockoutMonitors.get(i).sendLockoutReset(); 7903a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 7913a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 7923a464785088e7fd206666f640912729533948ce8Jorim Jaggi 79327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver private void notifyClientActiveCallbacks(boolean isActive) { 79427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver List<IFingerprintClientActiveCallback> callbacks = mClientActiveCallbacks; 79527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver for (int i = 0; i < callbacks.size(); i++) { 79627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver try { 79727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver callbacks.get(i).onClientActiveChanged(isActive); 79827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver } catch (RemoteException re) { 79927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver // If the remote is dead, stop notifying it 80027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver mClientActiveCallbacks.remove(callbacks.get(i)); 801959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He } 80227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver } 80327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver } 80427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver 805ff715ac551fcb09640acdf28278384ca2d5f85c0Tony Mak private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId, 806cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller IFingerprintServiceReceiver receiver, int flags, boolean restricted, 807cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller String opPackageName) { 808cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller updateActiveGroup(groupId, opPackageName); 809fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller 810cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")"); 811cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller 812cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token, 813837fa7e56dc4e91feaf104bd09ef5e03065b1b86Jim Miller receiver, mCurrentUserId, groupId, opId, restricted, opPackageName) { 814cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller @Override 815df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn public int handleFailedAttempt() { 816cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller mFailedAttempts++; 817df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn mTimedLockoutCleared = false; 818df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn final int lockoutMode = getLockoutMode(); 819df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) { 820df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn mPerformanceStats.permanentLockout++; 821df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) { 822bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller mPerformanceStats.lockout++; 823bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller } 824df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn 825df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn // Failing multiple times will continue to push out the lockout time 826df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) { 827cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller scheduleLockoutReset(); 828df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn return lockoutMode; 82916ef71f4f5a01158fdc07dbbd0963aa2fb04e359Jim Miller } 830df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn return AuthenticationClient.LOCKOUT_NONE; 831fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 832fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller 833cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller @Override 834cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller public void resetFailedAttempts() { 835df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn FingerprintService.this.resetFailedAttempts(true /* clearAttemptCounter */); 836fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 837fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller 838cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller @Override 839cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller public void notifyUserActivity() { 840cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller FingerprintService.this.userActivity(); 841fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 842fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller 843cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller @Override 84440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller public IBiometricsFingerprint getFingerprintDaemon() { 845cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller return FingerprintService.this.getFingerprintDaemon(); 846fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 847cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller }; 848fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller 849df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn int lockoutMode = getLockoutMode(); 850df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) { 851df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn Slog.v(TAG, "In lockout mode(" + lockoutMode + 852df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn ") ; disallowing authentication"); 853df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ? 854df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn FingerprintManager.FINGERPRINT_ERROR_LOCKOUT : 855df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT; 856df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn if (!client.onError(errorCode, 0 /* vendorCode */)) { 857df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn Slog.w(TAG, "Cannot send permanent lockout message to client"); 8581304137918e41d1ad98555d9d7daf77583407d3fJim Miller } 859cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller return; 860fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 861cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller startClient(client, true /* initiatedByClient */); 862cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 863fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller 864c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller private void startEnrollment(IBinder token, byte [] cryptoToken, int userId, 865cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller IFingerprintServiceReceiver receiver, int flags, boolean restricted, 866cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller String opPackageName) { 867c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller updateActiveGroup(userId, opPackageName); 868c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller 869c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller final int groupId = userId; // default group for fingerprint enrollment 870cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller 871cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller EnrollClient client = new EnrollClient(getContext(), mHalDeviceId, token, receiver, 872c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller userId, groupId, cryptoToken, restricted, opPackageName) { 873cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller 874cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller @Override 87540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller public IBiometricsFingerprint getFingerprintDaemon() { 876cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller return FingerprintService.this.getFingerprintDaemon(); 877dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Miller } 878fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller 879cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller @Override 880cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller public void notifyUserActivity() { 881cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller FingerprintService.this.userActivity(); 882fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller } 883cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller }; 884cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller startClient(client, true /* initiatedByClient */); 885cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 886cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller 887df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn // attempt counter should only be cleared when Keyguard goes away or when 888df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn // a fingerprint is successfully authenticated 889df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn protected void resetFailedAttempts(boolean clearAttemptCounter) { 890df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) { 891df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn Slog.v(TAG, "Reset fingerprint lockout, clearAttemptCounter=" + clearAttemptCounter); 892df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn } 893df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn if (clearAttemptCounter) { 894df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn mFailedAttempts = 0; 895ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 896df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn mTimedLockoutCleared = true; 897cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // If we're asked to reset failed attempts externally (i.e. from Keyguard), 898cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller // the alarm might still be pending; remove it. 899cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller cancelLockoutReset(); 900cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller notifyLockoutResetMonitors(); 901ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 902ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 9033a464785088e7fd206666f640912729533948ce8Jorim Jaggi private class FingerprintServiceLockoutResetMonitor { 9043a464785088e7fd206666f640912729533948ce8Jorim Jaggi 90557e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi private static final long WAKELOCK_TIMEOUT_MS = 2000; 9063a464785088e7fd206666f640912729533948ce8Jorim Jaggi private final IFingerprintServiceLockoutResetCallback mCallback; 90757e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi private final WakeLock mWakeLock; 9083a464785088e7fd206666f640912729533948ce8Jorim Jaggi 9093a464785088e7fd206666f640912729533948ce8Jorim Jaggi public FingerprintServiceLockoutResetMonitor( 9103a464785088e7fd206666f640912729533948ce8Jorim Jaggi IFingerprintServiceLockoutResetCallback callback) { 9113a464785088e7fd206666f640912729533948ce8Jorim Jaggi mCallback = callback; 91257e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 91357e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi "lockout reset callback"); 9143a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 9153a464785088e7fd206666f640912729533948ce8Jorim Jaggi 9163a464785088e7fd206666f640912729533948ce8Jorim Jaggi public void sendLockoutReset() { 9173a464785088e7fd206666f640912729533948ce8Jorim Jaggi if (mCallback != null) { 9183a464785088e7fd206666f640912729533948ce8Jorim Jaggi try { 91957e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi mWakeLock.acquire(WAKELOCK_TIMEOUT_MS); 92057e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi mCallback.onLockoutReset(mHalDeviceId, new IRemoteCallback.Stub() { 92157e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi 92257e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi @Override 92357e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi public void sendResult(Bundle data) throws RemoteException { 92457e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi mWakeLock.release(); 92557e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi } 92657e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi }); 9273a464785088e7fd206666f640912729533948ce8Jorim Jaggi } catch (DeadObjectException e) { 9283a464785088e7fd206666f640912729533948ce8Jorim Jaggi Slog.w(TAG, "Death object while invoking onLockoutReset: ", e); 9293a464785088e7fd206666f640912729533948ce8Jorim Jaggi mHandler.post(mRemoveCallbackRunnable); 9303a464785088e7fd206666f640912729533948ce8Jorim Jaggi } catch (RemoteException e) { 9313a464785088e7fd206666f640912729533948ce8Jorim Jaggi Slog.w(TAG, "Failed to invoke onLockoutReset: ", e); 9323a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 9333a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 9343a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 9353a464785088e7fd206666f640912729533948ce8Jorim Jaggi 9363a464785088e7fd206666f640912729533948ce8Jorim Jaggi private final Runnable mRemoveCallbackRunnable = new Runnable() { 9373a464785088e7fd206666f640912729533948ce8Jorim Jaggi @Override 9383a464785088e7fd206666f640912729533948ce8Jorim Jaggi public void run() { 93957e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi if (mWakeLock.isHeld()) { 94057e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi mWakeLock.release(); 94157e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi } 9423a464785088e7fd206666f640912729533948ce8Jorim Jaggi removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this); 9433a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 9443a464785088e7fd206666f640912729533948ce8Jorim Jaggi }; 9453a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 9463a464785088e7fd206666f640912729533948ce8Jorim Jaggi 94740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller private IBiometricsFingerprintClientCallback mDaemonCallback = 94840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller new IBiometricsFingerprintClientCallback.Stub() { 949be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 950be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override 9518b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller public void onEnrollResult(final long deviceId, final int fingerId, final int groupId, 9528b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller final int remaining) { 9538b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller mHandler.post(new Runnable() { 9548b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller @Override 9558b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller public void run() { 9568b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller handleEnrollResult(deviceId, fingerId, groupId, remaining); 9578b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller } 9588b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller }); 959be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 960be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 961be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override 96240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller public void onAcquired(final long deviceId, final int acquiredInfo, final int vendorCode) { 9638b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller mHandler.post(new Runnable() { 9648b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller @Override 9658b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller public void run() { 96640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller handleAcquired(deviceId, acquiredInfo, vendorCode); 9678b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller } 9688b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller }); 969be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 970be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 971be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override 972a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller public void onAuthenticated(final long deviceId, final int fingerId, final int groupId, 973a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller ArrayList<Byte> token) { 9748b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller mHandler.post(new Runnable() { 9758b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller @Override 9768b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller public void run() { 977a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller handleAuthenticated(deviceId, fingerId, groupId, token); 9788b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller } 9798b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller }); 980be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 981be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 982be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override 98340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller public void onError(final long deviceId, final int error, final int vendorCode) { 9848b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller mHandler.post(new Runnable() { 9858b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller @Override 9868b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller public void run() { 98740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller handleError(deviceId, error, vendorCode); 9888b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller } 9898b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller }); 990be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 991be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 992be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override 99340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller public void onRemoved(final long deviceId, final int fingerId, final int groupId, final int remaining) { 9948b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller mHandler.post(new Runnable() { 9958b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller @Override 9968b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller public void run() { 99740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller handleRemoved(deviceId, fingerId, groupId, remaining); 9988b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller } 9998b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller }); 1000be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 1001be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 10029f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller @Override 100340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller public void onEnumerate(final long deviceId, final int fingerId, final int groupId, 100440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller final int remaining) { 10058b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller mHandler.post(new Runnable() { 10068b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller @Override 10078b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller public void run() { 100840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller handleEnumerate(deviceId, fingerId, groupId, remaining); 10098b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller } 10108b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller }); 1011be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 1012be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller }; 1013be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 1014be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller private final class FingerprintServiceWrapper extends IFingerprintService.Stub { 1015be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 1016ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public long preEnroll(IBinder token) { 1017ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller checkPermission(MANAGE_FINGERPRINT); 1018ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller return startPreEnroll(token); 1019a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 1020a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 1021be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 1022e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy public int postEnroll(IBinder token) { 1023e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy checkPermission(MANAGE_FINGERPRINT); 1024e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy return startPostEnroll(token); 1025e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy } 1026e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy 1027e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy @Override // Binder call 1028c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller public void enroll(final IBinder token, final byte[] cryptoToken, final int userId, 1029cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller final IFingerprintServiceReceiver receiver, final int flags, 1030cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller final String opPackageName) { 1031ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller checkPermission(MANAGE_FINGERPRINT); 1032599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller final int limit = mContext.getResources().getInteger( 1033599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser); 1034c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller 1035c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size(); 1036599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller if (enrolled >= limit) { 1037599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller Slog.w(TAG, "Too many fingerprints registered"); 1038599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller return; 1039599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller } 1040f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 1041494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales // Group ID is arbitrarily set to parent profile user ID. It just represents 1042494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales // the default fingerprints for the user. 1043c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller if (!isCurrentUserOrProfile(userId)) { 104435fd93810541430615b2f1118abc756b717d379cClara Bayarri return; 104535fd93810541430615b2f1118abc756b717d379cClara Bayarri } 1046494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales 1047f501b58de8f467a80fef49c704555781bc61ea6fJim Miller final boolean restricted = isRestricted(); 1048ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller mHandler.post(new Runnable() { 1049ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @Override 1050ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void run() { 1051c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller startEnrollment(token, cryptoToken, userId, receiver, flags, 1052cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller restricted, opPackageName); 1053ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 1054ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller }); 1055a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 1056a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 1057f501b58de8f467a80fef49c704555781bc61ea6fJim Miller private boolean isRestricted() { 1058f501b58de8f467a80fef49c704555781bc61ea6fJim Miller // Only give privileged apps (like Settings) access to fingerprint info 1059f501b58de8f467a80fef49c704555781bc61ea6fJim Miller final boolean restricted = !hasPermission(MANAGE_FINGERPRINT); 1060f501b58de8f467a80fef49c704555781bc61ea6fJim Miller return restricted; 1061f501b58de8f467a80fef49c704555781bc61ea6fJim Miller } 1062f501b58de8f467a80fef49c704555781bc61ea6fJim Miller 1063be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 1064ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void cancelEnrollment(final IBinder token) { 1065ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller checkPermission(MANAGE_FINGERPRINT); 1066ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller mHandler.post(new Runnable() { 1067ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @Override 1068ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void run() { 1069cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller ClientMonitor client = mCurrentClient; 1070cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (client instanceof EnrollClient && client.getToken() == token) { 1071cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller client.stop(client.getToken() == token); 1072cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 1073ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 1074ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller }); 1075a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 1076a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 1077be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 1078ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void authenticate(final IBinder token, final long opId, final int groupId, 1079dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Miller final IFingerprintServiceReceiver receiver, final int flags, 1080dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Miller final String opPackageName) { 1081ff715ac551fcb09640acdf28278384ca2d5f85c0Tony Mak final int callingUid = Binder.getCallingUid(); 1082ff715ac551fcb09640acdf28278384ca2d5f85c0Tony Mak final int callingUserId = UserHandle.getCallingUserId(); 1083cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller final int pid = Binder.getCallingPid(); 1084f501b58de8f467a80fef49c704555781bc61ea6fJim Miller final boolean restricted = isRestricted(); 1085ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller mHandler.post(new Runnable() { 1086ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @Override 1087ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void run() { 1088cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, 1089f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn callingUid, pid, callingUserId)) { 1090cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName); 1091cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller return; 1092cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 1093bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller 1094bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0); 1095bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller 1096bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller // Get performance stats object for this user. 1097bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller HashMap<Integer, PerformanceStats> pmap 1098bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller = (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap; 1099bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller PerformanceStats stats = pmap.get(mCurrentUserId); 1100bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller if (stats == null) { 1101bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller stats = new PerformanceStats(); 1102bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller pmap.put(mCurrentUserId, stats); 1103bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller } 1104bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller mPerformanceStats = stats; 1105bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller 1106ff715ac551fcb09640acdf28278384ca2d5f85c0Tony Mak startAuthentication(token, opId, callingUserId, groupId, receiver, 1107d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri flags, restricted, opPackageName); 1108ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 1109ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller }); 1110a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 1111a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 1112be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 1113cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller public void cancelAuthentication(final IBinder token, final String opPackageName) { 1114cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller final int uid = Binder.getCallingUid(); 1115cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller final int pid = Binder.getCallingPid(); 1116f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn final int callingUserId = UserHandle.getCallingUserId(); 1117ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller mHandler.post(new Runnable() { 1118ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @Override 1119ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void run() { 1120f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, uid, pid, 1121f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn callingUserId)) { 1122cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "cancelAuthentication(): reject " + opPackageName); 1123cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } else { 1124cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller ClientMonitor client = mCurrentClient; 1125cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (client instanceof AuthenticationClient) { 1126cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (client.getToken() == token) { 1127cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "stop client " + client.getOwnerString()); 1128cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller client.stop(client.getToken() == token); 1129cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } else { 1130cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "can't stop client " 1131cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller + client.getOwnerString() + " since tokens don't match"); 1132cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 1133cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } else if (client != null) { 1134cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (DEBUG) Slog.v(TAG, "can't cancel non-authenticating client " 1135cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller + client.getOwnerString()); 1136cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 1137cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller } 1138ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 1139ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller }); 1140ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 1141ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller 1142be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 1143d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri public void setActiveUser(final int userId) { 1144d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri checkPermission(MANAGE_FINGERPRINT); 1145d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri mHandler.post(new Runnable() { 1146d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri @Override 1147d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri public void run() { 1148d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri updateActiveGroup(userId, null); 1149d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri } 1150d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri }); 1151d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri } 1152d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri 1153d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri @Override // Binder call 1154ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void remove(final IBinder token, final int fingerId, final int groupId, 11558f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller final int userId, final IFingerprintServiceReceiver receiver) { 1156ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission 1157f501b58de8f467a80fef49c704555781bc61ea6fJim Miller final boolean restricted = isRestricted(); 1158ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller mHandler.post(new Runnable() { 1159ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @Override 1160ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void run() { 1161d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn startRemove(token, fingerId, groupId, userId, receiver, 1162d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn restricted, false /* internal */); 1163ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 1164ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller }); 1165a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 1166ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller 1167d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn @Override // Binder call 116840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller public void enumerate(final IBinder token, final int userId, 116940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller final IFingerprintServiceReceiver receiver) { 117040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission 117140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller final boolean restricted = isRestricted(); 117240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller mHandler.post(new Runnable() { 117340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller @Override 117440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller public void run() { 1175d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn startEnumerate(token, userId, receiver, restricted, false /* internal */); 117640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } 117740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller }); 117840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller } 117940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller 1180be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 11814af76a51d5082c740609563e07cf35f30bc2224eSvetoslav public boolean isHardwareDetected(long deviceId, String opPackageName) { 1182cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 1183f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn Binder.getCallingUid(), Binder.getCallingPid(), 1184f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn UserHandle.getCallingUserId())) { 11854af76a51d5082c740609563e07cf35f30bc2224eSvetoslav return false; 11864af76a51d5082c740609563e07cf35f30bc2224eSvetoslav } 1187959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He 1188959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He final long token = Binder.clearCallingIdentity(); 1189959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He try { 1190959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He IBiometricsFingerprint daemon = getFingerprintDaemon(); 1191959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He return daemon != null && mHalDeviceId != 0; 1192959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He } finally { 1193959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He Binder.restoreCallingIdentity(token); 1194959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He } 1195ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller } 119699d6019bead4705b7e126e65b856d538417d4934Jim Miller 1197be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 1198ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void rename(final int fingerId, final int groupId, final String name) { 119999d6019bead4705b7e126e65b856d538417d4934Jim Miller checkPermission(MANAGE_FINGERPRINT); 120035fd93810541430615b2f1118abc756b717d379cClara Bayarri if (!isCurrentUserOrProfile(groupId)) { 120135fd93810541430615b2f1118abc756b717d379cClara Bayarri return; 120235fd93810541430615b2f1118abc756b717d379cClara Bayarri } 1203ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller mHandler.post(new Runnable() { 1204ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller @Override 1205ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller public void run() { 1206494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales mFingerprintUtils.renameFingerprintForUser(mContext, fingerId, 120735fd93810541430615b2f1118abc756b717d379cClara Bayarri groupId, name); 1208ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller } 1209ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller }); 121099d6019bead4705b7e126e65b856d538417d4934Jim Miller } 12119f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller 1212be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 1213599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) { 1214cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 1215f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn Binder.getCallingUid(), Binder.getCallingPid(), 1216f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn UserHandle.getCallingUserId())) { 12174af76a51d5082c740609563e07cf35f30bc2224eSvetoslav return Collections.emptyList(); 12184af76a51d5082c740609563e07cf35f30bc2224eSvetoslav } 1219494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales 122035fd93810541430615b2f1118abc756b717d379cClara Bayarri return FingerprintService.this.getEnrolledFingerprints(userId); 12219f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller } 12222aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi 1223be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 1224494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales public boolean hasEnrolledFingerprints(int userId, String opPackageName) { 1225cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 1226f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn Binder.getCallingUid(), Binder.getCallingPid(), 1227f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn UserHandle.getCallingUserId())) { 12284af76a51d5082c740609563e07cf35f30bc2224eSvetoslav return false; 12294af76a51d5082c740609563e07cf35f30bc2224eSvetoslav } 1230494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales 123135fd93810541430615b2f1118abc756b717d379cClara Bayarri return FingerprintService.this.hasEnrolledFingerprints(userId); 12322aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi } 12334d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales 1234be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override // Binder call 12354af76a51d5082c740609563e07cf35f30bc2224eSvetoslav public long getAuthenticatorId(String opPackageName) { 1236a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // In this method, we're not checking whether the caller is permitted to use fingerprint 1237a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // API because current authenticator ID is leaked (in a more contrived way) via Android 1238a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // Keystore (android.security.keystore package): the user of that API can create a key 1239a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // which requires fingerprint authentication for its use, and then query the key's 1240a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // characteristics (hidden API) which returns, among other things, fingerprint 1241a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // authenticator ID which was active at key creation time. 1242a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // 1243a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // Reason: The part of Android Keystore which runs inside an app's process invokes this 1244a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // method in certain cases. Those cases are not always where the developer demonstrates 1245a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // explicit intent to use fingerprint functionality. Thus, to avoiding throwing an 1246a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // unexpected SecurityException this method does not check whether its caller is 1247a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // permitted to use fingerprint API. 1248a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // 1249a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // The permission check should be restored once Android Keystore no longer invokes this 1250a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin // method from inside app processes. 1251a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin 1252cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller return FingerprintService.this.getAuthenticatorId(opPackageName); 12534d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales } 1254c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren 1255c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren @Override // Binder call 1256c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1257fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1258c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren 1259c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren final long ident = Binder.clearCallingIdentity(); 1260c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren try { 12611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (args.length > 0 && "--proto".equals(args[0])) { 12621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato dumpProto(fd); 12631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } else { 12641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato dumpInternal(pw); 12651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 1266c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren } finally { 1267c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren Binder.restoreCallingIdentity(ident); 1268c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren } 1269c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren } 1270959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He 1271e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller @Override // Binder call 1272e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller public void resetTimeout(byte [] token) { 1273e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller checkPermission(RESET_FINGERPRINT_LOCKOUT); 1274e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller // TODO: confirm security token when we move timeout management into the HAL layer. 12755e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi mHandler.post(mResetFailedAttemptsRunnable); 12763a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 12773a464785088e7fd206666f640912729533948ce8Jorim Jaggi 12783a464785088e7fd206666f640912729533948ce8Jorim Jaggi @Override 12793a464785088e7fd206666f640912729533948ce8Jorim Jaggi public void addLockoutResetCallback(final IFingerprintServiceLockoutResetCallback callback) 12803a464785088e7fd206666f640912729533948ce8Jorim Jaggi throws RemoteException { 12813a464785088e7fd206666f640912729533948ce8Jorim Jaggi mHandler.post(new Runnable() { 12823a464785088e7fd206666f640912729533948ce8Jorim Jaggi @Override 12833a464785088e7fd206666f640912729533948ce8Jorim Jaggi public void run() { 12843a464785088e7fd206666f640912729533948ce8Jorim Jaggi addLockoutResetMonitor( 12853a464785088e7fd206666f640912729533948ce8Jorim Jaggi new FingerprintServiceLockoutResetMonitor(callback)); 12863a464785088e7fd206666f640912729533948ce8Jorim Jaggi } 12873a464785088e7fd206666f640912729533948ce8Jorim Jaggi }); 1288e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller } 128927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver 129027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver @Override 129127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver public boolean isClientActive() { 129227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver checkPermission(MANAGE_FINGERPRINT); 129327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver synchronized(FingerprintService.this) { 129427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver return (mCurrentClient != null) || (mPendingClient != null); 129527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver } 129627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver } 129727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver 129827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver @Override 129927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver public void addClientActiveCallback(IFingerprintClientActiveCallback callback) { 130027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver checkPermission(MANAGE_FINGERPRINT); 130127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver mClientActiveCallbacks.add(callback); 130227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver } 130327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver 130427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver @Override 130527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver public void removeClientActiveCallback(IFingerprintClientActiveCallback callback) { 130627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver checkPermission(MANAGE_FINGERPRINT); 130727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver mClientActiveCallbacks.remove(callback); 130827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver } 1309c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren } 1310c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren 1311c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren private void dumpInternal(PrintWriter pw) { 1312c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren JSONObject dump = new JSONObject(); 1313c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren try { 1314c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren dump.put("service", "Fingerprint Manager"); 1315c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren 1316c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren JSONArray sets = new JSONArray(); 1317c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren for (UserInfo user : UserManager.get(getContext()).getUsers()) { 1318c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren final int userId = user.getUserHandle().getIdentifier(); 1319c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren final int N = mFingerprintUtils.getFingerprintsForUser(mContext, userId).size(); 1320bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller PerformanceStats stats = mPerformanceMap.get(userId); 1321bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller PerformanceStats cryptoStats = mCryptoPerformanceMap.get(userId); 1322c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren JSONObject set = new JSONObject(); 1323c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren set.put("id", userId); 1324c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren set.put("count", N); 1325bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller set.put("accept", (stats != null) ? stats.accept : 0); 1326bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller set.put("reject", (stats != null) ? stats.reject : 0); 1327bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller set.put("acquire", (stats != null) ? stats.acquire : 0); 1328bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller set.put("lockout", (stats != null) ? stats.lockout : 0); 1329df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn set.put("permanentLockout", (stats != null) ? stats.permanentLockout : 0); 1330bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller // cryptoStats measures statistics about secure fingerprint transactions 1331bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller // (e.g. to unlock password storage, make secure purchases, etc.) 1332bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller set.put("acceptCrypto", (cryptoStats != null) ? cryptoStats.accept : 0); 1333bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller set.put("rejectCrypto", (cryptoStats != null) ? cryptoStats.reject : 0); 1334bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller set.put("acquireCrypto", (cryptoStats != null) ? cryptoStats.acquire : 0); 1335bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller set.put("lockoutCrypto", (cryptoStats != null) ? cryptoStats.lockout : 0); 1336c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren sets.put(set); 1337c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren } 1338c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren 1339c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren dump.put("prints", sets); 1340c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren } catch (JSONException e) { 1341c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren Slog.e(TAG, "dump formatting failure", e); 1342c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren } 1343c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren pw.println(dump); 1344a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 1345a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 13461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato private void dumpProto(FileDescriptor fd) { 13471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato final ProtoOutputStream proto = new ProtoOutputStream(fd); 13481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato for (UserInfo user : UserManager.get(getContext()).getUsers()) { 13491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato final int userId = user.getUserHandle().getIdentifier(); 13501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 13511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato final long userToken = proto.start(FingerprintServiceDumpProto.USERS); 13521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 13531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.write(FingerprintUserStatsProto.USER_ID, userId); 13541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.write(FingerprintUserStatsProto.NUM_FINGERPRINTS, 13551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato mFingerprintUtils.getFingerprintsForUser(mContext, userId).size()); 13561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 13571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Normal fingerprint authentications (e.g. lockscreen) 13581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato final PerformanceStats normal = mPerformanceMap.get(userId); 13591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (normal != null) { 13601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato final long countsToken = proto.start(FingerprintUserStatsProto.NORMAL); 13611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.write(FingerprintActionStatsProto.ACCEPT, normal.accept); 13621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.write(FingerprintActionStatsProto.REJECT, normal.reject); 13631754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.write(FingerprintActionStatsProto.ACQUIRE, normal.acquire); 13641754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.write(FingerprintActionStatsProto.LOCKOUT, normal.lockout); 1365df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, normal.lockout); 13661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.end(countsToken); 13671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 13681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 13691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // Statistics about secure fingerprint transactions (e.g. to unlock password 13701754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato // storage, make secure purchases, etc.) 13719310f5c9b88938c6d3b6081dcc8e1676aa5e5cf5Kevin Chyn final PerformanceStats crypto = mCryptoPerformanceMap.get(userId); 13721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato if (crypto != null) { 13731754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato final long countsToken = proto.start(FingerprintUserStatsProto.CRYPTO); 13741754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.write(FingerprintActionStatsProto.ACCEPT, crypto.accept); 13751754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.write(FingerprintActionStatsProto.REJECT, crypto.reject); 13761754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.write(FingerprintActionStatsProto.ACQUIRE, crypto.acquire); 13771754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.write(FingerprintActionStatsProto.LOCKOUT, crypto.lockout); 1378df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, crypto.lockout); 13791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.end(countsToken); 13801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 13811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 13821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.end(userToken); 13831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 13841754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato proto.flush(); 13851754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato } 13861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato 1387a7596147b43940cad3f76c53ed154ef088b9269bJim Miller @Override 1388a7596147b43940cad3f76c53ed154ef088b9269bJim Miller public void onStart() { 13899f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); 1390e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart"); 1391aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi listenForUserSwitches(); 1392a7596147b43940cad3f76c53ed154ef088b9269bJim Miller } 1393a7596147b43940cad3f76c53ed154ef088b9269bJim Miller 1394d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri private void updateActiveGroup(int userId, String clientPackage) { 139540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller IBiometricsFingerprint daemon = getFingerprintDaemon(); 1396bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller 1397be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller if (daemon != null) { 1398be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller try { 1399d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri userId = getUserOrWorkProfileId(clientPackage, userId); 1400d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri if (userId != mCurrentUserId) { 1401d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri final File systemDir = Environment.getUserSystemDirectory(userId); 1402d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri final File fpDir = new File(systemDir, FP_DATA_DIR); 1403d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri if (!fpDir.exists()) { 1404d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri if (!fpDir.mkdir()) { 1405d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri Slog.v(TAG, "Cannot make directory: " + fpDir.getAbsolutePath()); 1406d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri return; 1407d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri } 1408d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri // Calling mkdir() from this process will create a directory with our 1409d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri // permissions (inherited from the containing dir). This command fixes 1410d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri // the label. 1411d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri if (!SELinux.restorecon(fpDir)) { 1412d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri Slog.w(TAG, "Restorecons failed. Directory will have wrong label."); 1413d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri return; 1414d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri } 141516ef71f4f5a01158fdc07dbbd0963aa2fb04e359Jim Miller } 141640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller daemon.setActiveGroup(userId, fpDir.getAbsolutePath()); 1417d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri mCurrentUserId = userId; 1418be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 141929b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He mAuthenticatorIds.put(userId, 142029b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He hasEnrolledFingerprints(userId) ? daemon.getAuthenticatorId() : 0L); 1421be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } catch (RemoteException e) { 1422be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller Slog.e(TAG, "Failed to setActiveGroup():", e); 1423be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 1424dbe780f293163c478933a1f2ce97189703656c10Jim Miller } 1425aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi } 1426aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi 1427d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri /** 1428d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri * @param clientPackage the package of the caller 1429d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri * @return the profile id 1430d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri */ 1431d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri private int getUserOrWorkProfileId(String clientPackage, int userId) { 1432d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri if (!isKeyguard(clientPackage) && isWorkProfile(userId)) { 1433d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri return userId; 1434d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri } 1435d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri return getEffectiveUserId(userId); 1436d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri } 1437d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri 1438d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri /** 1439d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri * @param userId 1440d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri * @return true if this is a work profile 1441d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri */ 1442d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri private boolean isWorkProfile(int userId) { 1443da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He UserInfo userInfo = null; 1444da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He final long token = Binder.clearCallingIdentity(); 1445da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He try { 1446da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He userInfo = mUserManager.getUserInfo(userId); 1447da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He } finally { 1448da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He Binder.restoreCallingIdentity(token); 1449da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He } 1450da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He return userInfo != null && userInfo.isManagedProfile(); 1451d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri } 1452d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri 1453aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi private void listenForUserSwitches() { 1454aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi try { 1455dc589ac82b5fe2063f4cfd94c8ae26d43d5420a0Sudheer Shanka ActivityManager.getService().registerUserSwitchObserver( 14566005b3f87b063ee7ab7e8877a6a8c90b480f3341Fyodor Kupolov new SynchronousUserSwitchObserver() { 1457be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller @Override 14586005b3f87b063ee7ab7e8877a6a8c90b480f3341Fyodor Kupolov public void onUserSwitching(int newUserId) throws RemoteException { 1459be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */) 1460be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller .sendToTarget(); 1461be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 14620b77ef9f5199b7cd0956f2bfe049cbd699ca03b4Fyodor Kupolov }, TAG); 1463aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi } catch (RemoteException e) { 1464aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi Slog.w(TAG, "Failed to listen for user switching event" ,e); 1465aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi } 1466aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi } 1467be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller 1468d0063106b67c9aa44d9473102a1116aad136f50fJim Miller /*** 1469d0063106b67c9aa44d9473102a1116aad136f50fJim Miller * @param opPackageName the name of the calling package 1470da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He * @return authenticator id for the calling user 1471d0063106b67c9aa44d9473102a1116aad136f50fJim Miller */ 1472cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller public long getAuthenticatorId(String opPackageName) { 1473da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId()); 147429b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He return mAuthenticatorIds.getOrDefault(userId, 0L); 1475be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller } 1476a7596147b43940cad3f76c53ed154ef088b9269bJim Miller} 1477