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;
22cf87df15310611ae4e5229b19c5a4942e54185b5Vishwath Mohanimport static android.Manifest.permission.USE_BIOMETRIC;
23959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport static android.Manifest.permission.USE_FINGERPRINT;
243121760e70fb6a1b8de0274c724170f7e87b7e5bSvet Ganovimport static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
25959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He
2680db9baf9766dc40f9d1b6bf60797ee5cc64a48cSasha Levitskiyimport android.app.ActivityManager;
27975f145c018de9affffee5e89d94ce0ed78ad9dfJim Millerimport android.app.ActivityManager.RunningAppProcessInfo;
285e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.app.AlarmManager;
294af76a51d5082c740609563e07cf35f30bc2224eSvetoslavimport android.app.AppOpsManager;
3009da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chynimport android.app.IActivityManager;
315e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.app.PendingIntent;
326005b3f87b063ee7ab7e8877a6a8c90b480f3341Fyodor Kupolovimport android.app.SynchronousUserSwitchObserver;
3309da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chynimport android.app.TaskStackListener;
345e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.content.BroadcastReceiver;
3529b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles Heimport android.content.ComponentName;
36a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.content.Context;
375e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.content.Intent;
385e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggiimport android.content.IntentFilter;
39f501b58de8f467a80fef49c704555781bc61ea6fJim Millerimport android.content.pm.PackageManager;
40cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Millerimport android.content.pm.UserInfo;
41ecf00cedb64d2e7b9082d540d49972fe391760adVishwath Mohanimport android.hardware.biometrics.IBiometricPromptReceiver;
42959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
43959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback;
44959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.fingerprint.Fingerprint;
45959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.fingerprint.FingerprintManager;
4627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport android.hardware.fingerprint.IFingerprintClientActiveCallback;
47959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.fingerprint.IFingerprintService;
483a464785088e7fd206666f640912729533948ce8Jorim Jaggiimport android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
49959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.hardware.fingerprint.IFingerprintServiceReceiver;
504af76a51d5082c740609563e07cf35f30bc2224eSvetoslavimport android.os.Binder;
517fe2053a55ed071bc28d44cb2f34dfc9f4efd520Andreas Huberimport android.os.Build;
5257e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggiimport android.os.Bundle;
533a464785088e7fd206666f640912729533948ce8Jorim Jaggiimport android.os.DeadObjectException;
5480db9baf9766dc40f9d1b6bf60797ee5cc64a48cSasha Levitskiyimport android.os.Environment;
55a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.Handler;
56a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.IBinder;
5740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Millerimport android.os.IHwBinder;
5857e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggiimport android.os.IRemoteCallback;
59dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Millerimport android.os.PowerManager;
6057e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggiimport android.os.PowerManager.WakeLock;
61a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.os.RemoteException;
6216ef71f4f5a01158fdc07dbbd0963aa2fb04e359Jim Millerimport android.os.SELinux;
63aae4a15a2288c20e73b995a590bde4626c887d03Kevin Chynimport android.os.ServiceManager;
64dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Millerimport android.os.SystemClock;
65599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Millerimport android.os.UserHandle;
66cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Millerimport android.os.UserManager;
67959ac8e04d3c25da11ed6fca1babf56a69a032baCharles Heimport android.security.KeyStore;
68a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport android.util.Slog;
695457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chynimport android.util.SparseBooleanArray;
705457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chynimport android.util.SparseIntArray;
711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onoratoimport android.util.proto.ProtoOutputStream;
72a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
73449e708abe4e1e85845d319dc701579a6b553c2cFyodor Kupolovimport com.android.internal.annotations.GuardedBy;
74c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport com.android.internal.logging.MetricsLogger;
75aae4a15a2288c20e73b995a590bde4626c887d03Kevin Chynimport com.android.internal.statusbar.IStatusBarService;
76fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils;
77e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolovimport com.android.server.SystemServerInitThreadPool;
78a7596147b43940cad3f76c53ed154ef088b9269bJim Millerimport com.android.server.SystemService;
79a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
80c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport org.json.JSONArray;
81c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport org.json.JSONException;
82c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport org.json.JSONObject;
83c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren
8480db9baf9766dc40f9d1b6bf60797ee5cc64a48cSasha Levitskiyimport java.io.File;
85c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport java.io.FileDescriptor;
86c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wrenimport java.io.PrintWriter;
873a464785088e7fd206666f640912729533948ce8Jorim Jaggiimport java.util.ArrayList;
884af76a51d5082c740609563e07cf35f30bc2224eSvetoslavimport java.util.Collections;
89bcc100aae93bdae85c3f3679dfdda0508450f94eJim Millerimport java.util.HashMap;
909f0753f5a378fc80da86305b33244acc6fc53f01Jim Millerimport java.util.List;
91da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles Heimport java.util.Map;
9227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaverimport java.util.concurrent.CopyOnWriteArrayList;
93a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
94a7596147b43940cad3f76c53ed154ef088b9269bJim Miller/**
95a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * A service to manage multiple clients that want to access the fingerprint HAL API.
96a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * The service is responsible for maintaining a list of clients and dispatching all
97edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn * fingerprint-related events.
98a7596147b43940cad3f76c53ed154ef088b9269bJim Miller *
99a7596147b43940cad3f76c53ed154ef088b9269bJim Miller * @hide
100a7596147b43940cad3f76c53ed154ef088b9269bJim Miller */
10140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Millerpublic class FingerprintService extends SystemService implements IHwBinder.DeathRecipient {
102cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    static final String TAG = "FingerprintService";
103cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    static final boolean DEBUG = true;
104edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn    private static final boolean CLEANUP_UNUSED_FP = true;
105be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    private static final String FP_DATA_DIR = "fpdata";
106be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    private static final int MSG_USER_SWITCHING = 10;
1075e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi    private static final String ACTION_LOCKOUT_RESET =
1085e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi            "com.android.server.fingerprint.ACTION_LOCKOUT_RESET";
1095457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn    private static final String KEY_LOCKOUT_RESET_USER = "lockout_reset_user";
110be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
111bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller    private class PerformanceStats {
112bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller        int accept; // number of accepted fingerprints
113bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller        int reject; // number of rejected fingerprints
114bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller        int acquire; // total number of acquisitions. Should be >= accept+reject due to poor image
115bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                     // acquisition in some cases (too fast, too slow, dirty sensor, etc.)
116bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller        int lockout; // total number of lockouts
117df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn        int permanentLockout; // total number of permanent lockouts
118bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller    }
119bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller
1203a464785088e7fd206666f640912729533948ce8Jorim Jaggi    private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
1213a464785088e7fd206666f640912729533948ce8Jorim Jaggi            new ArrayList<>();
12227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks =
12327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            new CopyOnWriteArrayList<>();
124da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He    private final Map<Integer, Long> mAuthenticatorIds =
125da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            Collections.synchronizedMap(new HashMap<>());
1264af76a51d5082c740609563e07cf35f30bc2224eSvetoslav    private final AppOpsManager mAppOps;
127af281ca0d3fad6aaafde0d1979123368390779dcJim Miller    private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
128df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn    private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5;
129df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn    private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20;
130df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn
1313d5e396583a845e63e102ff449d856c01125f550Jim Miller    private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms
132975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller    private final String mKeyguardPackage;
133959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He    private int mCurrentUserId = UserHandle.USER_NULL;
134cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance();
135cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private Context mContext;
136cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private long mHalDeviceId;
1375457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn    private SparseBooleanArray mTimedLockoutCleared;
1385457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn    private SparseIntArray mFailedAttempts;
139449e708abe4e1e85845d319dc701579a6b553c2cFyodor Kupolov    @GuardedBy("this")
14040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    private IBiometricsFingerprint mDaemon;
141aae4a15a2288c20e73b995a590bde4626c887d03Kevin Chyn    private IStatusBarService mStatusBarService;
14209da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn    private final IActivityManager mActivityManager;
143cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private final PowerManager mPowerManager;
144cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private final AlarmManager mAlarmManager;
145cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private final UserManager mUserManager;
146cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private ClientMonitor mCurrentClient;
147cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private ClientMonitor mPendingClient;
148bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller    private PerformanceStats mPerformanceStats;
149bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller
150d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn    private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration
151edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn    private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw fingerprints
152d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
153d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn    private class UserFingerprint {
154d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        Fingerprint f;
155d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        int userId;
156d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        public UserFingerprint(Fingerprint f, int userId) {
157d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            this.f = f;
158d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            this.userId = userId;
159d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
160d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn    }
161d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
162bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller    // Normal fingerprint authentications are tracked by mPerformanceMap.
16340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>();
164bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller
165bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller    // Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap.
16640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    private HashMap<Integer, PerformanceStats> mCryptoPerformanceMap = new HashMap<>();
167ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
168cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private Handler mHandler = new Handler() {
16980a776e5fecef1160aa9d2b9fdaf7bf9d9c95973Jim Miller        @Override
170a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        public void handleMessage(android.os.Message msg) {
171a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            switch (msg.what) {
172aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi                case MSG_USER_SWITCHING:
173aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi                    handleUserSwitching(msg.arg1);
174aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi                    break;
175aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi
176a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                default:
177a7596147b43940cad3f76c53ed154ef088b9269bJim Miller                    Slog.w(TAG, "Unknown message:" + msg.what);
178a7596147b43940cad3f76c53ed154ef088b9269bJim Miller            }
179a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
180a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    };
181be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
1825e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi    private final BroadcastReceiver mLockoutReceiver = new BroadcastReceiver() {
1835e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi        @Override
1845e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi        public void onReceive(Context context, Intent intent) {
1855e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi            if (ACTION_LOCKOUT_RESET.equals(intent.getAction())) {
1865457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                final int user = intent.getIntExtra(KEY_LOCKOUT_RESET_USER, 0);
1875457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                resetFailedAttemptsForUser(false /* clearAttemptCounter */, user);
1885e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi            }
1895e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi        }
1905e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi    };
1915e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi
1925457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn    private final Runnable mResetFailedAttemptsForCurrentUserRunnable = new Runnable() {
193fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller        @Override
194fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller        public void run() {
1955457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn            resetFailedAttemptsForUser(true /* clearAttemptCounter */,
1965457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                    ActivityManager.getCurrentUser());
197fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller        }
198fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    };
199a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
200cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private final Runnable mResetClientState = new Runnable() {
201cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        @Override
202cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        public void run() {
203cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            // Warning: if we get here, the driver never confirmed our call to cancel the current
204cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            // operation (authenticate, enroll, remove, enumerate, etc), which is
205cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            // really bad.  The result will be a 3-second delay in starting each new client.
206cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            // If you see this on a device, make certain the driver notifies with
207cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            // {@link FingerprintManager#FINGERPRINT_ERROR_CANCEL} in response to cancel()
208cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            // once it has successfully switched to the IDLE state in the fingerprint HAL.
209cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            // Additionally,{@link FingerprintManager#FINGERPRINT_ERROR_CANCEL} should only be sent
210cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            // in response to an actual cancel() call.
211cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            Slog.w(TAG, "Client "
212cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    + (mCurrentClient != null ? mCurrentClient.getOwnerString() : "null")
213cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    + " failed to respond to cancel, starting client "
214cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    + (mPendingClient != null ? mPendingClient.getOwnerString() : "null"));
215d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
216cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            mCurrentClient = null;
217cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            startClient(mPendingClient, false);
218cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        }
219cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    };
220cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller
22109da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn    private final TaskStackListener mTaskStackListener = new TaskStackListener() {
22209da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn        @Override
22309da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn        public void onTaskStackChanged() {
22409da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn            try {
22509da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                if (!(mCurrentClient instanceof AuthenticationClient)) {
22609da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                    return;
22709da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                }
228a792fa64ffb891e49b30642c1430e0ccfccd1429Kevin Chyn                final String currentClient = mCurrentClient.getOwnerString();
229a792fa64ffb891e49b30642c1430e0ccfccd1429Kevin Chyn                if (isKeyguard(currentClient)) {
23009da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                    return; // Keyguard is always allowed
23109da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                }
23209da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                List<ActivityManager.RunningTaskInfo> runningTasks = mActivityManager.getTasks(1);
23309da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                if (!runningTasks.isEmpty()) {
234da1b2ab430cbb07ec724c2b54d14d1f8c707134dKevin Chyn                    final String topPackage = runningTasks.get(0).topActivity.getPackageName();
235a792fa64ffb891e49b30642c1430e0ccfccd1429Kevin Chyn                    if (!topPackage.contentEquals(currentClient)) {
236da1b2ab430cbb07ec724c2b54d14d1f8c707134dKevin Chyn                        Slog.e(TAG, "Stopping background authentication, top: " + topPackage
237a792fa64ffb891e49b30642c1430e0ccfccd1429Kevin Chyn                                + " currentClient: " + currentClient);
238a792fa64ffb891e49b30642c1430e0ccfccd1429Kevin Chyn                        mCurrentClient.stop(false /* initiatedByClient */);
23909da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                    }
24009da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                }
24109da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn            } catch (RemoteException e) {
24209da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                Slog.e(TAG, "Unable to get running tasks", e);
24309da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn            }
24409da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn        }
24509da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn    };
24609da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn
247a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public FingerprintService(Context context) {
248a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        super(context);
249a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        mContext = context;
250975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
251975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller                com.android.internal.R.string.config_keyguardComponent)).getPackageName();
2524af76a51d5082c740609563e07cf35f30bc2224eSvetoslav        mAppOps = context.getSystemService(AppOpsManager.class);
2535e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi        mPowerManager = mContext.getSystemService(PowerManager.class);
2545e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi        mAlarmManager = mContext.getSystemService(AlarmManager.class);
2555e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi        mContext.registerReceiver(mLockoutReceiver, new IntentFilter(ACTION_LOCKOUT_RESET),
2565e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi                RESET_FINGERPRINT_LOCKOUT, null /* handler */);
257d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        mUserManager = UserManager.get(mContext);
2585457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        mTimedLockoutCleared = new SparseBooleanArray();
2595457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        mFailedAttempts = new SparseIntArray();
260aae4a15a2288c20e73b995a590bde4626c887d03Kevin Chyn        mStatusBarService = IStatusBarService.Stub.asInterface(
261aae4a15a2288c20e73b995a590bde4626c887d03Kevin Chyn                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
26209da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn        mActivityManager = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
26309da294c7a3fc65aa3d9b34bb332fa962fa04f4cKevin Chyn                .getService();
264be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    }
265be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
266be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    @Override
26740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    public void serviceDied(long cookie) {
26880e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn        Slog.v(TAG, "fingerprint HAL died");
269c57c8d934cf77673154bc81d767365b4d6cda33fJim Miller        MetricsLogger.count(mContext, "fingerprintd_died", 1);
27040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE,
27140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                0 /*vendorCode */);
272be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    }
273be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
27440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    public synchronized IBiometricsFingerprint getFingerprintDaemon() {
27540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        if (mDaemon == null) {
276edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn            Slog.v(TAG, "mDaemon was null, reconnect to fingerprint");
27740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            try {
27825d5eaa14ccdfa767588f9b15d05ec37d860fbc7Yifan Hong                mDaemon = IBiometricsFingerprint.getService();
27940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            } catch (java.util.NoSuchElementException e) {
28040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                // Service doesn't exist or cannot be opened. Logged below.
28140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            } catch (RemoteException e) {
28240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                Slog.e(TAG, "Failed to get biometric interface", e);
28340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            }
284449e708abe4e1e85845d319dc701579a6b553c2cFyodor Kupolov            if (mDaemon == null) {
28540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                Slog.w(TAG, "fingerprint HIDL not available");
28640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                return null;
28740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            }
28840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller
28940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            mDaemon.asBinder().linkToDeath(this, 0);
29040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller
29140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            try {
29240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                mHalDeviceId = mDaemon.setNotify(mDaemonCallback);
29340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            } catch (RemoteException e) {
29480e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn                Slog.e(TAG, "Failed to open fingerprint HAL", e);
29540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                mDaemon = null; // try again later!
29640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            }
29740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller
29840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
29940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            if (mHalDeviceId != 0) {
300da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He                loadAuthenticatorIds();
30140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                updateActiveGroup(ActivityManager.getCurrentUser(), null);
302edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                doFingerprintCleanupForUser(ActivityManager.getCurrentUser());
30340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            } else {
30440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                Slog.w(TAG, "Failed to open Fingerprint HAL!");
30540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
30640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                mDaemon = null;
307be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller            }
308be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
30940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        return mDaemon;
310be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    }
311be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
312da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He    /** Populates existing authenticator ids. To be used only during the start of the service. */
313da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He    private void loadAuthenticatorIds() {
314da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        // This operation can be expensive, so keep track of the elapsed time. Might need to move to
315da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        // background if it takes too long.
316da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        long t = System.currentTimeMillis();
317da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        mAuthenticatorIds.clear();
318da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
319da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            int userId = getUserOrWorkProfileId(null, user.id);
320da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            if (!mAuthenticatorIds.containsKey(userId)) {
321da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He                updateActiveGroup(userId, null);
322da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            }
323da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        }
324da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He
325da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        t = System.currentTimeMillis() - t;
326da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        if (t > 1000) {
327da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            Slog.w(TAG, "loadAuthenticatorIds() taking too long: " + t + "ms");
328da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        }
329da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He    }
330da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He
331edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn    /**
332edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn     * This method should be called upon connection to the daemon, and when user switches.
333edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn     * @param userId
334edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn     */
335edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn    private void doFingerprintCleanupForUser(int userId) {
336d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        if (CLEANUP_UNUSED_FP) {
337edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn            enumerateUser(userId);
338d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
339d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn    }
340d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
341edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn    private void clearEnumerateState() {
342edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn        if (DEBUG) Slog.v(TAG, "clearEnumerateState()");
343d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        mUnknownFingerprints.clear();
344d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn    }
345d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
346edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn    private void enumerateUser(int userId) {
347edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn        if (DEBUG) Slog.v(TAG, "Enumerating user(" + userId + ")");
348d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
349edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn        startEnumerate(mToken, userId, null, restricted, true /* internal */);
350d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn    }
351d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
352d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn    // Remove unknown fingerprints from hardware
353d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn    private void cleanupUnknownFingerprints() {
354d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        if (!mUnknownFingerprints.isEmpty()) {
355d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            UserFingerprint uf = mUnknownFingerprints.get(0);
356d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            mUnknownFingerprints.remove(uf);
357d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
358d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            startRemove(mToken, uf.f.getFingerId(), uf.f.getGroupId(), uf.userId, null,
359d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    restricted, true /* internal */);
360d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        } else {
361edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn            clearEnumerateState();
362d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
363d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn    }
364d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
36540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
366d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        ClientMonitor client = mCurrentClient;
367d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
368d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        if ( !(client instanceof InternalRemovalClient) && !(client instanceof EnumerateClient) ) {
369d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            return;
370d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
371d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        client.onEnumerationResult(fingerId, groupId, remaining);
372d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
373d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        // All fingerprints in hardware for this user were enumerated
374d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        if (remaining == 0) {
375d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            if (client instanceof InternalEnumerateClient) {
376edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                List<Fingerprint> unknownFingerprints =
377edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                        ((InternalEnumerateClient) client).getUnknownFingerprints();
378edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn
379edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                if (!unknownFingerprints.isEmpty()) {
380edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                    Slog.w(TAG, "Adding " + unknownFingerprints.size() +
381edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                            " fingerprints for deletion");
382edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                }
383edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                for (Fingerprint f : unknownFingerprints) {
384d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    mUnknownFingerprints.add(new UserFingerprint(f, client.getTargetUserId()));
385d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                }
386edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                removeClient(client);
387d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                cleanupUnknownFingerprints();
388edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn            } else {
389edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                removeClient(client);
390d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            }
391d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
392be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    }
393be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
39440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    protected void handleError(long deviceId, int error, int vendorCode) {
395cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        ClientMonitor client = mCurrentClient;
396d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        if (client instanceof InternalRemovalClient || client instanceof InternalEnumerateClient) {
397edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn            clearEnumerateState();
398d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
39940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        if (client != null && client.onError(error, vendorCode)) {
40007dbd63153b523f960eb7052a852661303aa7eacJim Miller            removeClient(client);
401be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
402df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn
403cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        if (DEBUG) Slog.v(TAG, "handleError(client="
404c1e61b83c2fc3fa7a7111ec72081a8fa647bc354Jim Miller                + (client != null ? client.getOwnerString() : "null") + ", error = " + error + ")");
405cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        // This is the magic code that starts the next client when the old client finishes.
406cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        if (error == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
407cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            mHandler.removeCallbacks(mResetClientState);
408cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            if (mPendingClient != null) {
409cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                if (DEBUG) Slog.v(TAG, "start pending client " + mPendingClient.getOwnerString());
410cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                startClient(mPendingClient, false);
411cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                mPendingClient = null;
412cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            }
4138eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller        } else if (error == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) {
4148eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller            // If we get HW_UNAVAILABLE, try to connect again later...
4158eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller            Slog.w(TAG, "Got ERROR_HW_UNAVAILABLE; try reconnecting next client.");
4168eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller            synchronized (this) {
4178eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller                mDaemon = null;
4188eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller                mHalDeviceId = 0;
419959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He                mCurrentUserId = UserHandle.USER_NULL;
4208eddd33a01ad8eeb99c380c14be181d7e4930c29Jim Miller            }
421cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        }
422be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    }
423be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
42440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) {
425d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        if (DEBUG) Slog.w(TAG, "Removed: fid=" + fingerId
426d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                + ", gid=" + groupId
427d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                + ", dev=" + deviceId
428d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                + ", rem=" + remaining);
429d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
430cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        ClientMonitor client = mCurrentClient;
43140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        if (client != null && client.onRemoved(fingerId, groupId, remaining)) {
432cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            removeClient(client);
43329b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He            // When the last fingerprint of a group is removed, update the authenticator id
43429b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He            if (!hasEnrolledFingerprints(groupId)) {
43529b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He                updateActiveGroup(groupId, null);
43629b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He            }
437ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
438d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        if (client instanceof InternalRemovalClient && !mUnknownFingerprints.isEmpty()) {
439d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            cleanupUnknownFingerprints();
440d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        } else if (client instanceof InternalRemovalClient){
441edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn            clearEnumerateState();
442d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
443be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    }
444be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
445a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller    protected void handleAuthenticated(long deviceId, int fingerId, int groupId,
446a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller            ArrayList<Byte> token) {
447cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        ClientMonitor client = mCurrentClient;
448a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller        if (fingerId != 0) {
449a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller            // Ugh...
450a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller            final byte[] byteToken = new byte[token.size()];
451a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller            for (int i = 0; i < token.size(); i++) {
452a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller                byteToken[i] = token.get(i);
453a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller            }
454a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller            // Send to Keystore
455da82e2cb7193032867f86b996467bcd117545616Brian Young            KeyStore.getInstance().addAuthToken(byteToken);
456a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller        }
457cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        if (client != null && client.onAuthenticated(fingerId, groupId)) {
458cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            removeClient(client);
459ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
460bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller        if (fingerId != 0) {
461bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller            mPerformanceStats.accept++;
462bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller        } else {
463bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller            mPerformanceStats.reject++;
464bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller        }
465be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    }
466be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
46740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    protected void handleAcquired(long deviceId, int acquiredInfo, int vendorCode) {
468cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        ClientMonitor client = mCurrentClient;
46940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        if (client != null && client.onAcquired(acquiredInfo, vendorCode)) {
470cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            removeClient(client);
471ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
472df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn        if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE
473bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                && client instanceof AuthenticationClient) {
474bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller            // ignore enrollment acquisitions or acquisitions when we're locked out
475bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller            mPerformanceStats.acquire++;
476bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller        }
477dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Miller    }
478be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
4798b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller    protected void handleEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
480cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        ClientMonitor client = mCurrentClient;
481cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        if (client != null && client.onEnrollResult(fingerId, groupId, remaining)) {
482cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            removeClient(client);
48329b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He            // When enrollment finishes, update this group's authenticator id, as the HAL has
48429b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He            // already generated a new authenticator id when the new fingerprint is enrolled.
48529b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He            updateActiveGroup(groupId, null);
486a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
487a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
488a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
4898b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller    private void userActivity() {
4908b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller        long now = SystemClock.uptimeMillis();
4918b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller        mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
4928b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller    }
4938b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller
4948b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller    void handleUserSwitching(int userId) {
495edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn        if (mCurrentClient instanceof InternalRemovalClient
496edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                || mCurrentClient instanceof InternalEnumerateClient) {
497edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn            Slog.w(TAG, "User switched while performing cleanup");
498edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn            removeClient(mCurrentClient);
499edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn            clearEnumerateState();
500edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn        }
501d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        updateActiveGroup(userId, null);
502edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn        doFingerprintCleanupForUser(userId);
5038b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller    }
5048b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller
505be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    private void removeClient(ClientMonitor client) {
506cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        if (client != null) {
507cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            client.destroy();
508cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            if (client != mCurrentClient && mCurrentClient != null) {
509cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                Slog.w(TAG, "Unexpected client: " + client.getOwnerString() + "expected: "
510cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                        + mCurrentClient != null ? mCurrentClient.getOwnerString() : "null");
511cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            }
512cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        }
513cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        if (mCurrentClient != null) {
514cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            if (DEBUG) Slog.v(TAG, "Done with client: " + client.getOwnerString());
515cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            mCurrentClient = null;
516fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller        }
51727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        if (mPendingClient == null) {
51827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            notifyClientActiveCallbacks(false);
51927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
520fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    }
521fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
522df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn    private int getLockoutMode() {
5235457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        final int currentUser = ActivityManager.getCurrentUser();
5245457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        final int failedAttempts = mFailedAttempts.get(currentUser, 0);
5255457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        if (failedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) {
526df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn            return AuthenticationClient.LOCKOUT_PERMANENT;
5275457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        } else if (failedAttempts > 0 &&
5285457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                mTimedLockoutCleared.get(currentUser, false) == false
5295457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                && (failedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) {
530df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn            return AuthenticationClient.LOCKOUT_TIMED;
531df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn        }
532df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn        return AuthenticationClient.LOCKOUT_NONE;
533fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller    }
534fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
5355457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn    private void scheduleLockoutResetForUser(int userId) {
5365457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
5375457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS,
5385457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                getLockoutResetIntentForUser(userId));
5395e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi    }
5405e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi
5415457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn    private void cancelLockoutResetForUser(int userId) {
5425457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        mAlarmManager.cancel(getLockoutResetIntentForUser(userId));
5435e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi    }
5445e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi
5455457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn    private PendingIntent getLockoutResetIntentForUser(int userId) {
5465457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        return PendingIntent.getBroadcast(mContext, userId,
5475457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                new Intent(ACTION_LOCKOUT_RESET).putExtra(KEY_LOCKOUT_RESET_USER, userId),
5485457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                PendingIntent.FLAG_UPDATE_CURRENT);
5495e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi    }
5505e354223d817477efac9a6a2e3ce3d9161e046a4Jorim Jaggi
551ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    public long startPreEnroll(IBinder token) {
55240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        IBiometricsFingerprint daemon = getFingerprintDaemon();
553be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        if (daemon == null) {
55480e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn            Slog.w(TAG, "startPreEnroll: no fingerprint HAL!");
555be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller            return 0;
556be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
557be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        try {
558be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller            return daemon.preEnroll();
559be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        } catch (RemoteException e) {
560be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller            Slog.e(TAG, "startPreEnroll failed", e);
561be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
562be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        return 0;
563ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
564ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
565e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    public int startPostEnroll(IBinder token) {
56640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        IBiometricsFingerprint daemon = getFingerprintDaemon();
567e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        if (daemon == null) {
56880e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn            Slog.w(TAG, "startPostEnroll: no fingerprint HAL!");
569e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            return 0;
570e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        }
571e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        try {
572e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            return daemon.postEnroll();
573e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        } catch (RemoteException e) {
574e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            Slog.e(TAG, "startPostEnroll failed", e);
575e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        }
576e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        return 0;
577e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy    }
578e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy
57980a776e5fecef1160aa9d2b9fdaf7bf9d9c95973Jim Miller    /**
58080e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn     * Calls fingerprint HAL to switch states to the new task. If there's already a current task,
581cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller     * it calls cancel() and sets mPendingClient to begin when the current task finishes
582cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller     * ({@link FingerprintManager#FINGERPRINT_ERROR_CANCELED}).
583cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller     * @param newClient the new client that wants to connect
584cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller     * @param initiatedByClient true for authenticate, remove and enroll
58580a776e5fecef1160aa9d2b9fdaf7bf9d9c95973Jim Miller     */
586cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
587cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        ClientMonitor currentClient = mCurrentClient;
588cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        if (currentClient != null) {
589cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
590d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            if (currentClient instanceof InternalEnumerateClient ||
591d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    currentClient instanceof InternalRemovalClient) {
592d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                // This condition means we're currently running internal diagnostics to
593d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                // remove extra fingerprints in the hardware and/or the software
594d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                // TODO: design an escape hatch in case client never finishes
595edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                if (newClient != null) {
596edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                    Slog.w(TAG, "Internal cleanup in progress but trying to start client "
597edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                            + newClient.getClass().getSuperclass().getSimpleName()
598edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                            + "(" + newClient.getOwnerString() + ")"
599edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                            + ", initiatedByClient = " + initiatedByClient);
600edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                }
601d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            }
602d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            else {
603d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                currentClient.stop(initiatedByClient);
604d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            }
605cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            mPendingClient = newClient;
606cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            mHandler.removeCallbacks(mResetClientState);
607cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
608cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        } else if (newClient != null) {
609cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            mCurrentClient = newClient;
610cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            if (DEBUG) Slog.v(TAG, "starting client "
611cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    + newClient.getClass().getSuperclass().getSimpleName()
612cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    + "(" + newClient.getOwnerString() + ")"
613edd71f9ab6d2cbbd13407e5284b06d64a3687634Kevin Chyn                    + ", initiatedByClient = " + initiatedByClient);
61427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            notifyClientActiveCallbacks(true);
61527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
616cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            newClient.start();
6171304137918e41d1ad98555d9d7daf77583407d3fJim Miller        }
618a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
619a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
6208f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller    void startRemove(IBinder token, int fingerId, int groupId, int userId,
621d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
622606f17154407bc53dd9fc894111b0927985d38ccIlya Matyukhin        if (token == null) {
623606f17154407bc53dd9fc894111b0927985d38ccIlya Matyukhin            Slog.w(TAG, "startRemove: token is null");
624606f17154407bc53dd9fc894111b0927985d38ccIlya Matyukhin            return;
625606f17154407bc53dd9fc894111b0927985d38ccIlya Matyukhin        }
626606f17154407bc53dd9fc894111b0927985d38ccIlya Matyukhin        if (receiver == null) {
627606f17154407bc53dd9fc894111b0927985d38ccIlya Matyukhin            Slog.w(TAG, "startRemove: receiver is null");
628606f17154407bc53dd9fc894111b0927985d38ccIlya Matyukhin            return;
629606f17154407bc53dd9fc894111b0927985d38ccIlya Matyukhin        }
630606f17154407bc53dd9fc894111b0927985d38ccIlya Matyukhin
63140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        IBiometricsFingerprint daemon = getFingerprintDaemon();
632be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        if (daemon == null) {
63380e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn            Slog.w(TAG, "startRemove: no fingerprint HAL!");
634be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller            return;
635be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
636f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
637d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        if (internal) {
638d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            Context context = getContext();
639d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            InternalRemovalClient client = new InternalRemovalClient(context, mHalDeviceId,
640d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    token, receiver, fingerId, groupId, userId, restricted,
641d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    context.getOpPackageName()) {
642d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                @Override
643d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                public void notifyUserActivity() {
644d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
645d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                }
646d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                @Override
647d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                public IBiometricsFingerprint getFingerprintDaemon() {
648d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    return FingerprintService.this.getFingerprintDaemon();
649d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                }
650d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            };
651d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            startClient(client, true);
652d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
653d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        else {
654d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
655d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    receiver, fingerId, groupId, userId, restricted, token.toString()) {
656d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                @Override
657d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                public void notifyUserActivity() {
658d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    FingerprintService.this.userActivity();
659d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                }
660d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
661d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                @Override
662d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                public IBiometricsFingerprint getFingerprintDaemon() {
663d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    return FingerprintService.this.getFingerprintDaemon();
664d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                }
665d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            };
666d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            startClient(client, true);
667d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
66840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    }
66940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller
67040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    void startEnumerate(IBinder token, int userId,
671d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
67240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        IBiometricsFingerprint daemon = getFingerprintDaemon();
67340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        if (daemon == null) {
67480e40ccf49bca22a6eb1846a582574092f3e0c1aKevin Chyn            Slog.w(TAG, "startEnumerate: no fingerprint HAL!");
67540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            return;
67640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        }
677d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        if (internal) {
678d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            List<Fingerprint> enrolledList = getEnrolledFingerprints(userId);
679d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            Context context = getContext();
680d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            InternalEnumerateClient client = new InternalEnumerateClient(context, mHalDeviceId,
681d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    token, receiver, userId, userId, restricted, context.getOpPackageName(),
682d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    enrolledList) {
683d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                @Override
684d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                public void notifyUserActivity() {
685f8ff36c47f9f8d60cf825e6b43eb75d1eae81df5Kevin Chyn
686d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                }
687d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
688d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                @Override
689d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                public IBiometricsFingerprint getFingerprintDaemon() {
690d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    return FingerprintService.this.getFingerprintDaemon();
691d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                }
692d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            };
693d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            startClient(client, true);
694d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
695d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        else {
696d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token,
697d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    receiver, userId, userId, restricted, token.toString()) {
698d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                @Override
699d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                public void notifyUserActivity() {
700d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    FingerprintService.this.userActivity();
701d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                }
702d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn
703d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                @Override
704d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                public IBiometricsFingerprint getFingerprintDaemon() {
705d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    return FingerprintService.this.getFingerprintDaemon();
706d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                }
707d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            };
708d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn            startClient(client, true);
709d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        }
710a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
711a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
712599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller    public List<Fingerprint> getEnrolledFingerprints(int userId) {
713599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller        return mFingerprintUtils.getFingerprintsForUser(mContext, userId);
7149f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller    }
7159f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
716599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller    public boolean hasEnrolledFingerprints(int userId) {
7171fd298bdcb192b6a513216773d4de58a505da665Jim Miller        if (userId != UserHandle.getCallingUserId()) {
71833fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri            checkPermission(INTERACT_ACROSS_USERS);
71933fd3cf2d90ca877b139e7f47824683b774f122aClara Bayarri        }
720599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller        return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0;
7212aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi    }
7222aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi
723f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    boolean hasPermission(String permission) {
724f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        return getContext().checkCallingOrSelfPermission(permission)
725f501b58de8f467a80fef49c704555781bc61ea6fJim Miller                == PackageManager.PERMISSION_GRANTED;
726f501b58de8f467a80fef49c704555781bc61ea6fJim Miller    }
727f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
728ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller    void checkPermission(String permission) {
7299f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        getContext().enforceCallingOrSelfPermission(permission,
7309f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller                "Must have " + permission + " permission.");
731a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
732a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
733494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales    int getEffectiveUserId(int userId) {
734494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales        UserManager um = UserManager.get(mContext);
735494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales        if (um != null) {
736494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales            final long callingIdentity = Binder.clearCallingIdentity();
737494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales            userId = um.getCredentialOwnerProfile(userId);
738494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales            Binder.restoreCallingIdentity(callingIdentity);
739494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales        } else {
740494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales            Slog.e(TAG, "Unable to acquire UserManager");
741494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales        }
742494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales        return userId;
743494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales    }
744494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales
745cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller    boolean isCurrentUserOrProfile(int userId) {
746cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller        UserManager um = UserManager.get(mContext);
747da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        if (um == null) {
748da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            Slog.e(TAG, "Unable to acquire UserManager");
749da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            return false;
750da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        }
751cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller
752da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        final long token = Binder.clearCallingIdentity();
753da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        try {
754da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            // Allow current user or profiles of the current user...
755959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He            for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) {
756da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He                if (profileId == userId) {
757da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He                    return true;
758da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He                }
759cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller            }
760da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        } finally {
761da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            Binder.restoreCallingIdentity(token);
762cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller        }
763959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He
764959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He        return false;
765cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller    }
766cb7d9e933234233410e1f761cb9804bb8b7a00d3Jim Miller
767975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller    private boolean isForegroundActivity(int uid, int pid) {
768975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        try {
769975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller            List<RunningAppProcessInfo> procs =
770dc589ac82b5fe2063f4cfd94c8ae26d43d5420a0Sudheer Shanka                    ActivityManager.getService().getRunningAppProcesses();
771975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller            int N = procs.size();
772975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller            for (int i = 0; i < N; i++) {
773975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller                RunningAppProcessInfo proc = procs.get(i);
774975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller                if (proc.pid == pid && proc.uid == uid
7753121760e70fb6a1b8de0274c724170f7e87b7e5bSvet Ganov                        && proc.importance <= IMPORTANCE_FOREGROUND_SERVICE) {
776975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller                    return true;
777975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller                }
778975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller            }
779975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        } catch (RemoteException e) {
780975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller            Slog.w(TAG, "am.getRunningAppProcesses() failed");
781975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        }
782975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        return false;
783975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller    }
784975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller
785975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller    /**
786975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller     * @param opPackageName name of package for caller
78737979c9db0a88039bb098645f4180dc04e987b96Jim Miller     * @param requireForeground only allow this call while app is in the foreground
788975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller     * @return true if caller can use fingerprint API
789975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller     */
79037979c9db0a88039bb098645f4180dc04e987b96Jim Miller    private boolean canUseFingerprint(String opPackageName, boolean requireForeground, int uid,
791f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn            int pid, int userId) {
792cf87df15310611ae4e5229b19c5a4942e54185b5Vishwath Mohan        if (getContext().checkCallingPermission(USE_FINGERPRINT)
793cf87df15310611ae4e5229b19c5a4942e54185b5Vishwath Mohan                != PackageManager.PERMISSION_GRANTED) {
794cf87df15310611ae4e5229b19c5a4942e54185b5Vishwath Mohan            checkPermission(USE_BIOMETRIC);
795cf87df15310611ae4e5229b19c5a4942e54185b5Vishwath Mohan        }
796cf87df15310611ae4e5229b19c5a4942e54185b5Vishwath Mohan
797d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        if (isKeyguard(opPackageName)) {
798975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller            return true; // Keyguard is always allowed
799975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        }
800f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn        if (!isCurrentUserOrProfile(userId)) {
801975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller            Slog.w(TAG,"Rejecting " + opPackageName + " ; not a current user or profile");
802975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller            return false;
803975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        }
804975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName)
805975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller                != AppOpsManager.MODE_ALLOWED) {
8061adb4a7693406e7f984d7b1512e0e6aa40aa40e2Jim Miller            Slog.w(TAG, "Rejecting " + opPackageName + " ; permission denied");
807975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller            return false;
808975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        }
80937979c9db0a88039bb098645f4180dc04e987b96Jim Miller        if (requireForeground && !(isForegroundActivity(uid, pid) || currentClient(opPackageName))){
8101adb4a7693406e7f984d7b1512e0e6aa40aa40e2Jim Miller            Slog.w(TAG, "Rejecting " + opPackageName + " ; not in foreground");
811975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller            return false;
812975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        }
813975f145c018de9affffee5e89d94ce0ed78ad9dfJim Miller        return true;
8144af76a51d5082c740609563e07cf35f30bc2224eSvetoslav    }
8154af76a51d5082c740609563e07cf35f30bc2224eSvetoslav
816d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    /**
81737979c9db0a88039bb098645f4180dc04e987b96Jim Miller     * @param opPackageName package of the caller
81837979c9db0a88039bb098645f4180dc04e987b96Jim Miller     * @return true if this is the same client currently using fingerprint
81937979c9db0a88039bb098645f4180dc04e987b96Jim Miller     */
82037979c9db0a88039bb098645f4180dc04e987b96Jim Miller    private boolean currentClient(String opPackageName) {
82137979c9db0a88039bb098645f4180dc04e987b96Jim Miller        return mCurrentClient != null && mCurrentClient.getOwnerString().equals(opPackageName);
82237979c9db0a88039bb098645f4180dc04e987b96Jim Miller    }
82337979c9db0a88039bb098645f4180dc04e987b96Jim Miller
82437979c9db0a88039bb098645f4180dc04e987b96Jim Miller    /**
825d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @param clientPackage
826d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @return true if this is keyguard package
827d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     */
828d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    private boolean isKeyguard(String clientPackage) {
829d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        return mKeyguardPackage.equals(clientPackage);
830d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    }
831d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri
8323a464785088e7fd206666f640912729533948ce8Jorim Jaggi    private void addLockoutResetMonitor(FingerprintServiceLockoutResetMonitor monitor) {
8333a464785088e7fd206666f640912729533948ce8Jorim Jaggi        if (!mLockoutMonitors.contains(monitor)) {
8343a464785088e7fd206666f640912729533948ce8Jorim Jaggi            mLockoutMonitors.add(monitor);
8353a464785088e7fd206666f640912729533948ce8Jorim Jaggi        }
8363a464785088e7fd206666f640912729533948ce8Jorim Jaggi    }
8373a464785088e7fd206666f640912729533948ce8Jorim Jaggi
8383a464785088e7fd206666f640912729533948ce8Jorim Jaggi    private void removeLockoutResetCallback(
8393a464785088e7fd206666f640912729533948ce8Jorim Jaggi            FingerprintServiceLockoutResetMonitor monitor) {
8403a464785088e7fd206666f640912729533948ce8Jorim Jaggi        mLockoutMonitors.remove(monitor);
8413a464785088e7fd206666f640912729533948ce8Jorim Jaggi    }
8423a464785088e7fd206666f640912729533948ce8Jorim Jaggi
8433a464785088e7fd206666f640912729533948ce8Jorim Jaggi    private void notifyLockoutResetMonitors() {
8443a464785088e7fd206666f640912729533948ce8Jorim Jaggi        for (int i = 0; i < mLockoutMonitors.size(); i++) {
8453a464785088e7fd206666f640912729533948ce8Jorim Jaggi            mLockoutMonitors.get(i).sendLockoutReset();
8463a464785088e7fd206666f640912729533948ce8Jorim Jaggi        }
8473a464785088e7fd206666f640912729533948ce8Jorim Jaggi    }
8483a464785088e7fd206666f640912729533948ce8Jorim Jaggi
84927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    private void notifyClientActiveCallbacks(boolean isActive) {
85027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        List<IFingerprintClientActiveCallback> callbacks = mClientActiveCallbacks;
85127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        for (int i = 0; i < callbacks.size(); i++) {
85227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            try {
85327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                callbacks.get(i).onClientActiveChanged(isActive);
85427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            } catch (RemoteException re) {
85527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                // If the remote is dead, stop notifying it
85627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                mClientActiveCallbacks.remove(callbacks.get(i));
857959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He            }
85827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
85927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver    }
86027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
861ff715ac551fcb09640acdf28278384ca2d5f85c0Tony Mak    private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
862cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                IFingerprintServiceReceiver receiver, int flags, boolean restricted,
863ecf00cedb64d2e7b9082d540d49972fe391760adVishwath Mohan                String opPackageName, Bundle bundle, IBiometricPromptReceiver dialogReceiver) {
864cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        updateActiveGroup(groupId, opPackageName);
865fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
866cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");
867cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller
868cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token,
869aae4a15a2288c20e73b995a590bde4626c887d03Kevin Chyn                receiver, mCurrentUserId, groupId, opId, restricted, opPackageName, bundle,
870aae4a15a2288c20e73b995a590bde4626c887d03Kevin Chyn                dialogReceiver, mStatusBarService) {
871cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            @Override
872d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn            public void onStart() {
873d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn                try {
874d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn                    mActivityManager.registerTaskStackListener(mTaskStackListener);
875d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn                } catch (RemoteException e) {
876d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn                    Slog.e(TAG, "Could not register task stack listener", e);
877d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn                }
878d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn            }
879d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn
880d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn            @Override
881d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn            public void onStop() {
882d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn                try {
883d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn                    mActivityManager.unregisterTaskStackListener(mTaskStackListener);
884d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn                } catch (RemoteException e) {
885d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn                    Slog.e(TAG, "Could not unregister task stack listener", e);
886d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn                }
887d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn            }
888d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn
889d4f43c2f55131f75410d387da2dd7d0878d7c8fcKevin Chyn            @Override
890df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn            public int handleFailedAttempt() {
8915457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                final int currentUser = ActivityManager.getCurrentUser();
8925457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1);
8935457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                mTimedLockoutCleared.put(ActivityManager.getCurrentUser(), false);
894df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                final int lockoutMode = getLockoutMode();
895df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) {
896df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                    mPerformanceStats.permanentLockout++;
897df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) {
898bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                    mPerformanceStats.lockout++;
899bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                }
900df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn
901df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                // Failing multiple times will continue to push out the lockout time
902df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
9035457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                    scheduleLockoutResetForUser(currentUser);
904df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                    return lockoutMode;
90516ef71f4f5a01158fdc07dbbd0963aa2fb04e359Jim Miller                }
906df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                return AuthenticationClient.LOCKOUT_NONE;
907fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            }
908fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
909cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            @Override
910cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            public void resetFailedAttempts() {
9115457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                FingerprintService.this.resetFailedAttemptsForUser(true /* clearAttemptCounter */,
9125457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn                        ActivityManager.getCurrentUser());
913fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            }
914fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
915cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            @Override
916cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            public void notifyUserActivity() {
917cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                FingerprintService.this.userActivity();
918fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            }
919fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
920cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            @Override
92140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            public IBiometricsFingerprint getFingerprintDaemon() {
922cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                return FingerprintService.this.getFingerprintDaemon();
923fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            }
924cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        };
925fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
926df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn        int lockoutMode = getLockoutMode();
927df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn        if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
928df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn            Slog.v(TAG, "In lockout mode(" + lockoutMode +
929df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                    ") ; disallowing authentication");
930df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn            int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?
931df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                    FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
932df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                    FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
933df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn            if (!client.onError(errorCode, 0 /* vendorCode */)) {
934df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                Slog.w(TAG, "Cannot send permanent lockout message to client");
9351304137918e41d1ad98555d9d7daf77583407d3fJim Miller            }
936cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            return;
937fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller        }
938cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        startClient(client, true /* initiatedByClient */);
939cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    }
940fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
941c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller    private void startEnrollment(IBinder token, byte [] cryptoToken, int userId,
942cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            IFingerprintServiceReceiver receiver, int flags, boolean restricted,
943cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            String opPackageName) {
944c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller        updateActiveGroup(userId, opPackageName);
945c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller
946c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller        final int groupId = userId; // default group for fingerprint enrollment
947cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller
948cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        EnrollClient client = new EnrollClient(getContext(), mHalDeviceId, token, receiver,
949c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller                userId, groupId, cryptoToken, restricted, opPackageName) {
950cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller
951cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            @Override
95240e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            public IBiometricsFingerprint getFingerprintDaemon() {
953cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                return FingerprintService.this.getFingerprintDaemon();
954dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Miller            }
955fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller
956cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            @Override
957cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            public void notifyUserActivity() {
958cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                FingerprintService.this.userActivity();
959fe6439f02db3a541d77a7afb27e3bca1ae7493edJim Miller            }
960cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        };
961cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        startClient(client, true /* initiatedByClient */);
962cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    }
963cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller
964df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn    // attempt counter should only be cleared when Keyguard goes away or when
965df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn    // a fingerprint is successfully authenticated
9665457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn    protected void resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId) {
967df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn        if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) {
968df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn            Slog.v(TAG, "Reset fingerprint lockout, clearAttemptCounter=" + clearAttemptCounter);
969df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn        }
970df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn        if (clearAttemptCounter) {
9715457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn            mFailedAttempts.put(userId, 0);
972ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
9735457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        mTimedLockoutCleared.put(userId, true);
974cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        // If we're asked to reset failed attempts externally (i.e. from Keyguard),
975cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        // the alarm might still be pending; remove it.
9765457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn        cancelLockoutResetForUser(userId);
977cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        notifyLockoutResetMonitors();
978ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller    }
979ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
9803883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn    private class FingerprintServiceLockoutResetMonitor implements IBinder.DeathRecipient {
9813a464785088e7fd206666f640912729533948ce8Jorim Jaggi
98257e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi        private static final long WAKELOCK_TIMEOUT_MS = 2000;
9833a464785088e7fd206666f640912729533948ce8Jorim Jaggi        private final IFingerprintServiceLockoutResetCallback mCallback;
98457e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi        private final WakeLock mWakeLock;
9853a464785088e7fd206666f640912729533948ce8Jorim Jaggi
9863a464785088e7fd206666f640912729533948ce8Jorim Jaggi        public FingerprintServiceLockoutResetMonitor(
9873a464785088e7fd206666f640912729533948ce8Jorim Jaggi                IFingerprintServiceLockoutResetCallback callback) {
9883a464785088e7fd206666f640912729533948ce8Jorim Jaggi            mCallback = callback;
98957e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi            mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
99057e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                    "lockout reset callback");
9913883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn            try {
9923883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn                mCallback.asBinder().linkToDeath(FingerprintServiceLockoutResetMonitor.this, 0);
9933883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn            } catch (RemoteException e) {
9943883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn                Slog.w(TAG, "caught remote exception in linkToDeath", e);
9953883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn            }
9963a464785088e7fd206666f640912729533948ce8Jorim Jaggi        }
9973a464785088e7fd206666f640912729533948ce8Jorim Jaggi
9983a464785088e7fd206666f640912729533948ce8Jorim Jaggi        public void sendLockoutReset() {
9993a464785088e7fd206666f640912729533948ce8Jorim Jaggi            if (mCallback != null) {
10003a464785088e7fd206666f640912729533948ce8Jorim Jaggi                try {
100157e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                    mWakeLock.acquire(WAKELOCK_TIMEOUT_MS);
100257e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                    mCallback.onLockoutReset(mHalDeviceId, new IRemoteCallback.Stub() {
100357e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi
100457e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                        @Override
100557e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                        public void sendResult(Bundle data) throws RemoteException {
100671d04218a7066d9b8467d7b717ac2bdab0950fd5Kevin Chyn                            releaseWakelock();
100757e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                        }
100857e2f4db3535fb059ac278499018951deddc4c82Jorim Jaggi                    });
10093a464785088e7fd206666f640912729533948ce8Jorim Jaggi                } catch (DeadObjectException e) {
10103a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    Slog.w(TAG, "Death object while invoking onLockoutReset: ", e);
10113a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    mHandler.post(mRemoveCallbackRunnable);
10123a464785088e7fd206666f640912729533948ce8Jorim Jaggi                } catch (RemoteException e) {
10133a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    Slog.w(TAG, "Failed to invoke onLockoutReset: ", e);
101471d04218a7066d9b8467d7b717ac2bdab0950fd5Kevin Chyn                    releaseWakelock();
10153a464785088e7fd206666f640912729533948ce8Jorim Jaggi                }
10163a464785088e7fd206666f640912729533948ce8Jorim Jaggi            }
10173a464785088e7fd206666f640912729533948ce8Jorim Jaggi        }
10183a464785088e7fd206666f640912729533948ce8Jorim Jaggi
10193a464785088e7fd206666f640912729533948ce8Jorim Jaggi        private final Runnable mRemoveCallbackRunnable = new Runnable() {
10203a464785088e7fd206666f640912729533948ce8Jorim Jaggi            @Override
10213a464785088e7fd206666f640912729533948ce8Jorim Jaggi            public void run() {
102271d04218a7066d9b8467d7b717ac2bdab0950fd5Kevin Chyn                releaseWakelock();
10233a464785088e7fd206666f640912729533948ce8Jorim Jaggi                removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this);
10243a464785088e7fd206666f640912729533948ce8Jorim Jaggi            }
10253a464785088e7fd206666f640912729533948ce8Jorim Jaggi        };
10263883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn
10273883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn        @Override
10283883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn        public void binderDied() {
10293883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn            Slog.e(TAG, "Lockout reset callback binder died");
10303883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn            mHandler.post(mRemoveCallbackRunnable);
10313883563d9277af0654fd7fca977e2e2437bb9509Kevin Chyn        }
103271d04218a7066d9b8467d7b717ac2bdab0950fd5Kevin Chyn
103371d04218a7066d9b8467d7b717ac2bdab0950fd5Kevin Chyn        private void releaseWakelock() {
103471d04218a7066d9b8467d7b717ac2bdab0950fd5Kevin Chyn            if (mWakeLock.isHeld()) {
103571d04218a7066d9b8467d7b717ac2bdab0950fd5Kevin Chyn                mWakeLock.release();
103671d04218a7066d9b8467d7b717ac2bdab0950fd5Kevin Chyn            }
103771d04218a7066d9b8467d7b717ac2bdab0950fd5Kevin Chyn        }
10383a464785088e7fd206666f640912729533948ce8Jorim Jaggi    }
10393a464785088e7fd206666f640912729533948ce8Jorim Jaggi
104040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller    private IBiometricsFingerprintClientCallback mDaemonCallback =
104140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            new IBiometricsFingerprintClientCallback.Stub() {
1042be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
1043be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override
10448b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller        public void onEnrollResult(final long deviceId, final int fingerId, final int groupId,
10458b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                final int remaining) {
10468b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            mHandler.post(new Runnable() {
10478b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                @Override
10488b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                public void run() {
10498b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                    handleEnrollResult(deviceId, fingerId, groupId, remaining);
10508b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                }
10518b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            });
1052be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
1053be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
1054be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override
105540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void onAcquired(final long deviceId, final int acquiredInfo, final int vendorCode) {
10568b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            mHandler.post(new Runnable() {
10578b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                @Override
10588b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                public void run() {
105940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    handleAcquired(deviceId, acquiredInfo, vendorCode);
10608b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                }
10618b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            });
1062be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
1063be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
1064be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override
1065a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller        public void onAuthenticated(final long deviceId, final int fingerId, final int groupId,
1066a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller                ArrayList<Byte> token) {
10678b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            mHandler.post(new Runnable() {
10688b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                @Override
10698b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                public void run() {
1070a8eaeeb7549f9783fee850a5921b56a949eb6498Jim Miller                    handleAuthenticated(deviceId, fingerId, groupId, token);
10718b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                }
10728b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            });
1073be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
1074be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
1075be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override
107640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void onError(final long deviceId, final int error, final int vendorCode) {
10778b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            mHandler.post(new Runnable() {
10788b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                @Override
10798b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                public void run() {
108040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    handleError(deviceId, error, vendorCode);
10818b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                }
10828b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            });
1083be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
1084be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
1085be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override
108640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void onRemoved(final long deviceId, final int fingerId, final int groupId, final int remaining) {
10878b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            mHandler.post(new Runnable() {
10888b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                @Override
10898b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                public void run() {
109040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    handleRemoved(deviceId, fingerId, groupId, remaining);
10918b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                }
10928b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            });
1093be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
1094be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
10959f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        @Override
109640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void onEnumerate(final long deviceId, final int fingerId, final int groupId,
109740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                final int remaining) {
10988b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            mHandler.post(new Runnable() {
10998b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                @Override
11008b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                public void run() {
110140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    handleEnumerate(deviceId, fingerId, groupId, remaining);
11028b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller                }
11038b3c25a34a0bfe5fa3ed697ee6a552ea1373f077Jim Miller            });
1104be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        }
1105be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    };
1106be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
1107be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
1108be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
1109ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public long preEnroll(IBinder token) {
1110ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller            checkPermission(MANAGE_FINGERPRINT);
1111ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            return startPreEnroll(token);
1112a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
1113a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
1114be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
1115e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        public int postEnroll(IBinder token) {
1116e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            checkPermission(MANAGE_FINGERPRINT);
1117e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy            return startPostEnroll(token);
1118e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        }
1119e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy
1120e0943cf5665b3d7b0870debda771032f77db094cSasha Levitskiy        @Override // Binder call
1121c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller        public void enroll(final IBinder token, final byte[] cryptoToken, final int userId,
1122cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                final IFingerprintServiceReceiver receiver, final int flags,
1123cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                final String opPackageName) {
1124ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            checkPermission(MANAGE_FINGERPRINT);
1125aae4a15a2288c20e73b995a590bde4626c887d03Kevin Chyn            final int limit = mContext.getResources().getInteger(
1126599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller                    com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
1127c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller
1128c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller            final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size();
1129599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller            if (enrolled >= limit) {
1130599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller                Slog.w(TAG, "Too many fingerprints registered");
1131599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller                return;
1132599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller            }
1133f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
1134494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales            // Group ID is arbitrarily set to parent profile user ID. It just represents
1135494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales            // the default fingerprints for the user.
1136c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller            if (!isCurrentUserOrProfile(userId)) {
113735fd93810541430615b2f1118abc756b717d379cClara Bayarri                return;
113835fd93810541430615b2f1118abc756b717d379cClara Bayarri            }
1139494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales
1140f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            final boolean restricted = isRestricted();
1141ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mHandler.post(new Runnable() {
1142ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                @Override
1143ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                public void run() {
1144c12eca8b5964dfc37836e1c0f2dad8c88c76d90fJim Miller                    startEnrollment(token, cryptoToken, userId, receiver, flags,
1145cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                            restricted, opPackageName);
1146ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                }
1147ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            });
1148a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
1149a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
1150f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        private boolean isRestricted() {
1151f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            // Only give privileged apps (like Settings) access to fingerprint info
1152f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            final boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
1153f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            return restricted;
1154f501b58de8f467a80fef49c704555781bc61ea6fJim Miller        }
1155f501b58de8f467a80fef49c704555781bc61ea6fJim Miller
1156be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
1157ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void cancelEnrollment(final IBinder token) {
1158ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            checkPermission(MANAGE_FINGERPRINT);
1159ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mHandler.post(new Runnable() {
1160ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                @Override
1161ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                public void run() {
1162cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    ClientMonitor client = mCurrentClient;
1163cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    if (client instanceof EnrollClient && client.getToken() == token) {
1164cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                        client.stop(client.getToken() == token);
1165cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    }
1166ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                }
1167ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            });
1168a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
1169a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
1170be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
1171ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void authenticate(final IBinder token, final long opId, final int groupId,
1172dca15d22e8f37d4bc2dfb6db4522ea166149525bJim Miller                final IFingerprintServiceReceiver receiver, final int flags,
1173aae4a15a2288c20e73b995a590bde4626c887d03Kevin Chyn                final String opPackageName, final Bundle bundle,
1174ecf00cedb64d2e7b9082d540d49972fe391760adVishwath Mohan                final IBiometricPromptReceiver dialogReceiver) {
1175ff715ac551fcb09640acdf28278384ca2d5f85c0Tony Mak            final int callingUid = Binder.getCallingUid();
117633fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn            final int callingPid = Binder.getCallingPid();
1177ff715ac551fcb09640acdf28278384ca2d5f85c0Tony Mak            final int callingUserId = UserHandle.getCallingUserId();
1178f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            final boolean restricted = isRestricted();
117933fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn
118033fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn            if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
118133fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                    callingUserId)) {
118233fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
118333fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                return;
118433fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn            }
118533fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn
1186ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mHandler.post(new Runnable() {
1187ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                @Override
1188ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                public void run() {
1189bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                    MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
1190bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller
1191bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                    // Get performance stats object for this user.
1192bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                    HashMap<Integer, PerformanceStats> pmap
1193bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                            = (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap;
1194bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                    PerformanceStats stats = pmap.get(mCurrentUserId);
1195bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                    if (stats == null) {
1196bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                        stats = new PerformanceStats();
1197bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                        pmap.put(mCurrentUserId, stats);
1198bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                    }
1199bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                    mPerformanceStats = stats;
1200bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller
1201ff715ac551fcb09640acdf28278384ca2d5f85c0Tony Mak                    startAuthentication(token, opId, callingUserId, groupId, receiver,
1202aae4a15a2288c20e73b995a590bde4626c887d03Kevin Chyn                            flags, restricted, opPackageName, bundle, dialogReceiver);
1203ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                }
1204ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            });
1205a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
1206a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
1207be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
1208cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller        public void cancelAuthentication(final IBinder token, final String opPackageName) {
120933fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn            final int callingUid = Binder.getCallingUid();
121033fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn            final int callingPid = Binder.getCallingPid();
1211f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn            final int callingUserId = UserHandle.getCallingUserId();
121233fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn
121333fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn            if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
121433fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                    callingUserId)) {
121533fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                if (DEBUG) Slog.v(TAG, "cancelAuthentication(): reject " + opPackageName);
121633fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                return;
121733fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn            }
121833fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn
1219ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mHandler.post(new Runnable() {
1220ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                @Override
1221ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                public void run() {
122233fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                    ClientMonitor client = mCurrentClient;
122333fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                    if (client instanceof AuthenticationClient) {
122433fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                        if (client.getToken() == token) {
122533fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                            if (DEBUG) Slog.v(TAG, "stop client " + client.getOwnerString());
122633fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                            client.stop(client.getToken() == token);
122733fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                        } else {
122833fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                            if (DEBUG) Slog.v(TAG, "can't stop client "
122933fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                                    + client.getOwnerString() + " since tokens don't match");
1230cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                        }
123133fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                    } else if (client != null) {
123233fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                        if (DEBUG) Slog.v(TAG, "can't cancel non-authenticating client "
123333fdf11c65e10556d204aafd644c4567226d9d62Kevin Chyn                                + client.getOwnerString());
1234cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller                    }
1235ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                }
1236ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            });
1237ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        }
1238ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller
1239be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
1240d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        public void setActiveUser(final int userId) {
1241d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            checkPermission(MANAGE_FINGERPRINT);
1242d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            mHandler.post(new Runnable() {
1243d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                @Override
1244d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                public void run() {
1245d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                    updateActiveGroup(userId, null);
1246d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                }
1247d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            });
1248d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        }
1249d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri
1250d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        @Override // Binder call
1251ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void remove(final IBinder token, final int fingerId, final int groupId,
12528f2aca0ee4ff0eff6226df05d1531d2f2fa2f3c1Jim Miller                final int userId, final IFingerprintServiceReceiver receiver) {
1253ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
1254f501b58de8f467a80fef49c704555781bc61ea6fJim Miller            final boolean restricted = isRestricted();
1255ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mHandler.post(new Runnable() {
1256ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                @Override
1257ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                public void run() {
1258d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    startRemove(token, fingerId, groupId, userId, receiver,
1259d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                            restricted, false /* internal */);
1260ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                }
1261ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            });
1262a7596147b43940cad3f76c53ed154ef088b9269bJim Miller        }
1263ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller
1264d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn        @Override // Binder call
126540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        public void enumerate(final IBinder token, final int userId,
126640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            final IFingerprintServiceReceiver receiver) {
126740e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
126840e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            final boolean restricted = isRestricted();
126940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            mHandler.post(new Runnable() {
127040e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                @Override
127140e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                public void run() {
1272d1f1a0b60a660cbff9efdf77c2aed11e1f7061f2Kevin Chyn                    startEnumerate(token, userId, receiver, restricted, false /* internal */);
127340e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                }
127440e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller            });
127540e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        }
127640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller
1277be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
12784af76a51d5082c740609563e07cf35f30bc2224eSvetoslav        public boolean isHardwareDetected(long deviceId, String opPackageName) {
1279cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
1280f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn                    Binder.getCallingUid(), Binder.getCallingPid(),
1281f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn                    UserHandle.getCallingUserId())) {
12824af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return false;
12834af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            }
1284959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He
1285959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He            final long token = Binder.clearCallingIdentity();
1286959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He            try {
1287959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He                IBiometricsFingerprint daemon = getFingerprintDaemon();
1288959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He                return daemon != null && mHalDeviceId != 0;
1289959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He            } finally {
1290959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He                Binder.restoreCallingIdentity(token);
1291959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He            }
1292ba67aee02cf864793129976cd8a8a46e60c60577Jim Miller        }
129399d6019bead4705b7e126e65b856d538417d4934Jim Miller
1294be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
1295ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller        public void rename(final int fingerId, final int groupId, final String name) {
129699d6019bead4705b7e126e65b856d538417d4934Jim Miller            checkPermission(MANAGE_FINGERPRINT);
129735fd93810541430615b2f1118abc756b717d379cClara Bayarri            if (!isCurrentUserOrProfile(groupId)) {
129835fd93810541430615b2f1118abc756b717d379cClara Bayarri                return;
129935fd93810541430615b2f1118abc756b717d379cClara Bayarri            }
1300ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            mHandler.post(new Runnable() {
1301ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                @Override
1302ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                public void run() {
1303494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales                    mFingerprintUtils.renameFingerprintForUser(mContext, fingerId,
130435fd93810541430615b2f1118abc756b717d379cClara Bayarri                            groupId, name);
1305ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller                }
1306ce7eb6daf06a88129da365eb2112537ce0bb1b75Jim Miller            });
130799d6019bead4705b7e126e65b856d538417d4934Jim Miller        }
13089f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller
1309be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
1310599ef0e3cd848bbf8faa45147ac680d04d3ba333Jim Miller        public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) {
1311cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
1312f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn                    Binder.getCallingUid(), Binder.getCallingPid(),
1313f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn                    UserHandle.getCallingUserId())) {
13144af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return Collections.emptyList();
13154af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            }
1316494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales
131735fd93810541430615b2f1118abc756b717d379cClara Bayarri            return FingerprintService.this.getEnrolledFingerprints(userId);
13189f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        }
13192aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi
1320be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
1321494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales        public boolean hasEnrolledFingerprints(int userId, String opPackageName) {
1322cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
1323f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn                    Binder.getCallingUid(), Binder.getCallingPid(),
1324f4023b570c0170bde67484b6c58952dc6ca93136Kevin Chyn                    UserHandle.getCallingUserId())) {
13254af76a51d5082c740609563e07cf35f30bc2224eSvetoslav                return false;
13264af76a51d5082c740609563e07cf35f30bc2224eSvetoslav            }
1327494d6e9b030e757cef996bcbfd68a80a7d1526e7Andres Morales
132835fd93810541430615b2f1118abc756b717d379cClara Bayarri            return FingerprintService.this.hasEnrolledFingerprints(userId);
13292aad7ee245857a46aae305fefc4e3c1bcdd4a586Jorim Jaggi        }
13304d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales
1331be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        @Override // Binder call
13324af76a51d5082c740609563e07cf35f30bc2224eSvetoslav        public long getAuthenticatorId(String opPackageName) {
1333a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // In this method, we're not checking whether the caller is permitted to use fingerprint
1334a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // API because current authenticator ID is leaked (in a more contrived way) via Android
1335a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // Keystore (android.security.keystore package): the user of that API can create a key
1336a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // which requires fingerprint authentication for its use, and then query the key's
1337a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // characteristics (hidden API) which returns, among other things, fingerprint
1338a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // authenticator ID which was active at key creation time.
1339a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            //
1340a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // Reason: The part of Android Keystore which runs inside an app's process invokes this
1341a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // method in certain cases. Those cases are not always where the developer demonstrates
1342a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // explicit intent to use fingerprint functionality. Thus, to avoiding throwing an
1343a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // unexpected SecurityException this method does not check whether its caller is
1344a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // permitted to use fingerprint API.
1345a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            //
1346a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // The permission check should be restored once Android Keystore no longer invokes this
1347a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin            // method from inside app processes.
1348a99b8b5e3fe456b74b9f86e12bebebb5e418f58eAlex Klyubin
1349cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller            return FingerprintService.this.getAuthenticatorId(opPackageName);
13504d41a203a08c55b3f3190519535ccee6557ea4feAndres Morales        }
1351c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren
1352c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren        @Override // Binder call
1353c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1354fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey            if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
1355c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren
1356c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren            final long ident = Binder.clearCallingIdentity();
1357c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren            try {
13581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                if (args.length > 0 && "--proto".equals(args[0])) {
13591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    dumpProto(fd);
13601754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                } else {
13611754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    dumpInternal(pw);
13621754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                }
1363c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren            } finally {
1364c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren                Binder.restoreCallingIdentity(ident);
1365c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren            }
1366c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren        }
1367959ac8e04d3c25da11ed6fca1babf56a69a032baCharles He
1368e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        @Override // Binder call
1369e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        public void resetTimeout(byte [] token) {
1370e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            checkPermission(RESET_FINGERPRINT_LOCKOUT);
1371e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller            // TODO: confirm security token when we move timeout management into the HAL layer.
13725457cba8bee14e3ca7239f9b30cc0f67be5d6a96Kevin Chyn            mHandler.post(mResetFailedAttemptsForCurrentUserRunnable);
13733a464785088e7fd206666f640912729533948ce8Jorim Jaggi        }
13743a464785088e7fd206666f640912729533948ce8Jorim Jaggi
13753a464785088e7fd206666f640912729533948ce8Jorim Jaggi        @Override
13763a464785088e7fd206666f640912729533948ce8Jorim Jaggi        public void addLockoutResetCallback(final IFingerprintServiceLockoutResetCallback callback)
13773a464785088e7fd206666f640912729533948ce8Jorim Jaggi                throws RemoteException {
13783a464785088e7fd206666f640912729533948ce8Jorim Jaggi            mHandler.post(new Runnable() {
13793a464785088e7fd206666f640912729533948ce8Jorim Jaggi                @Override
13803a464785088e7fd206666f640912729533948ce8Jorim Jaggi                public void run() {
13813a464785088e7fd206666f640912729533948ce8Jorim Jaggi                    addLockoutResetMonitor(
13823a464785088e7fd206666f640912729533948ce8Jorim Jaggi                            new FingerprintServiceLockoutResetMonitor(callback));
13833a464785088e7fd206666f640912729533948ce8Jorim Jaggi                }
13843a464785088e7fd206666f640912729533948ce8Jorim Jaggi            });
1385e0507bbbf95ae6d958c900f32122baf078d47d71Jim Miller        }
138627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
138727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        @Override
138827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        public boolean isClientActive() {
138927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            checkPermission(MANAGE_FINGERPRINT);
139027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            synchronized(FingerprintService.this) {
139127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver                return (mCurrentClient != null) || (mPendingClient != null);
139227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            }
139327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
139427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
139527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        @Override
139627fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        public void addClientActiveCallback(IFingerprintClientActiveCallback callback) {
139727fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            checkPermission(MANAGE_FINGERPRINT);
139827fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            mClientActiveCallbacks.add(callback);
139927fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
140027fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver
140127fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        @Override
140227fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        public void removeClientActiveCallback(IFingerprintClientActiveCallback callback) {
140327fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            checkPermission(MANAGE_FINGERPRINT);
140427fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver            mClientActiveCallbacks.remove(callback);
140527fcd9c97a2ceb50bab026237390207e5ee9e290Phil Weaver        }
1406c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren    }
1407c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren
1408c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren    private void dumpInternal(PrintWriter pw) {
1409c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren        JSONObject dump = new JSONObject();
1410c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren        try {
1411c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren            dump.put("service", "Fingerprint Manager");
1412c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren
1413c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren            JSONArray sets = new JSONArray();
1414c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren            for (UserInfo user : UserManager.get(getContext()).getUsers()) {
1415c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren                final int userId = user.getUserHandle().getIdentifier();
1416c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren                final int N = mFingerprintUtils.getFingerprintsForUser(mContext, userId).size();
1417bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                PerformanceStats stats = mPerformanceMap.get(userId);
1418bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                PerformanceStats cryptoStats = mCryptoPerformanceMap.get(userId);
1419c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren                JSONObject set = new JSONObject();
1420c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren                set.put("id", userId);
1421c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren                set.put("count", N);
1422bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                set.put("accept", (stats != null) ? stats.accept : 0);
1423bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                set.put("reject", (stats != null) ? stats.reject : 0);
1424bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                set.put("acquire", (stats != null) ? stats.acquire : 0);
1425bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                set.put("lockout", (stats != null) ? stats.lockout : 0);
1426df9d33e9039d8567ea82f67a76d95a7ae7ab8df8Kevin Chyn                set.put("permanentLockout", (stats != null) ? stats.permanentLockout : 0);
1427bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                // cryptoStats measures statistics about secure fingerprint transactions
1428bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                // (e.g. to unlock password storage, make secure purchases, etc.)
1429bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                set.put("acceptCrypto", (cryptoStats != null) ? cryptoStats.accept : 0);
1430bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                set.put("rejectCrypto", (cryptoStats != null) ? cryptoStats.reject : 0);
1431bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                set.put("acquireCrypto", (cryptoStats != null) ? cryptoStats.acquire : 0);
1432bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller                set.put("lockoutCrypto", (cryptoStats != null) ? cryptoStats.lockout : 0);
1433cd7c35cfae7265f7ed32836ee09b5c341487470bKweku Adams                set.put("permanentLockoutCrypto",
1434cd7c35cfae7265f7ed32836ee09b5c341487470bKweku Adams                    (cryptoStats != null) ? cryptoStats.permanentLockout : 0);
1435c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren                sets.put(set);
1436c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren            }
1437c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren
1438c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren            dump.put("prints", sets);
1439c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren        } catch (JSONException e) {
1440c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren            Slog.e(TAG, "dump formatting failure", e);
1441c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren        }
1442c510ad56a8e01626a711e60ba97b01fd2121a72fChris Wren        pw.println(dump);
1443a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
1444a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
14451754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    private void dumpProto(FileDescriptor fd) {
14461754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        final ProtoOutputStream proto = new ProtoOutputStream(fd);
14471754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        for (UserInfo user : UserManager.get(getContext()).getUsers()) {
14481754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            final int userId = user.getUserHandle().getIdentifier();
14491754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
14501754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            final long userToken = proto.start(FingerprintServiceDumpProto.USERS);
14511754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
14521754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            proto.write(FingerprintUserStatsProto.USER_ID, userId);
14531754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            proto.write(FingerprintUserStatsProto.NUM_FINGERPRINTS,
14541754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                    mFingerprintUtils.getFingerprintsForUser(mContext, userId).size());
14551754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
14561754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // Normal fingerprint authentications (e.g. lockscreen)
14571754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            final PerformanceStats normal = mPerformanceMap.get(userId);
14581754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (normal != null) {
14591754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                final long countsToken = proto.start(FingerprintUserStatsProto.NORMAL);
1460fd257d60900dab144877ac559326ece02a2d5b71Kweku Adams                proto.write(PerformanceStatsProto.ACCEPT, normal.accept);
1461fd257d60900dab144877ac559326ece02a2d5b71Kweku Adams                proto.write(PerformanceStatsProto.REJECT, normal.reject);
1462fd257d60900dab144877ac559326ece02a2d5b71Kweku Adams                proto.write(PerformanceStatsProto.ACQUIRE, normal.acquire);
1463fd257d60900dab144877ac559326ece02a2d5b71Kweku Adams                proto.write(PerformanceStatsProto.LOCKOUT, normal.lockout);
1464fd257d60900dab144877ac559326ece02a2d5b71Kweku Adams                proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, normal.permanentLockout);
14651754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                proto.end(countsToken);
14661754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
14671754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
14681754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // Statistics about secure fingerprint transactions (e.g. to unlock password
14691754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            // storage, make secure purchases, etc.)
14709310f5c9b88938c6d3b6081dcc8e1676aa5e5cf5Kevin Chyn            final PerformanceStats crypto = mCryptoPerformanceMap.get(userId);
14711754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            if (crypto != null) {
14721754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                final long countsToken = proto.start(FingerprintUserStatsProto.CRYPTO);
1473fd257d60900dab144877ac559326ece02a2d5b71Kweku Adams                proto.write(PerformanceStatsProto.ACCEPT, crypto.accept);
1474fd257d60900dab144877ac559326ece02a2d5b71Kweku Adams                proto.write(PerformanceStatsProto.REJECT, crypto.reject);
1475fd257d60900dab144877ac559326ece02a2d5b71Kweku Adams                proto.write(PerformanceStatsProto.ACQUIRE, crypto.acquire);
1476fd257d60900dab144877ac559326ece02a2d5b71Kweku Adams                proto.write(PerformanceStatsProto.LOCKOUT, crypto.lockout);
1477fd257d60900dab144877ac559326ece02a2d5b71Kweku Adams                proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, crypto.permanentLockout);
14781754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato                proto.end(countsToken);
14791754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            }
14801754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
14811754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato            proto.end(userToken);
14821754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        }
14831754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato        proto.flush();
148489a55cb83d8d9f9a187e9319936273042e91f8f9Kevin Chyn        mPerformanceMap.clear();
148589a55cb83d8d9f9a187e9319936273042e91f8f9Kevin Chyn        mCryptoPerformanceMap.clear();
14861754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato    }
14871754d744a7a34731ffc07af1bc3dbfcb06864ab0Joe Onorato
1488a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    @Override
1489a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    public void onStart() {
14909f0753f5a378fc80da86305b33244acc6fc53f01Jim Miller        publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
1491e29a5a11529dc7df82911b48b9f95461383cbcc2Fyodor Kupolov        SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart");
1492aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi        listenForUserSwitches();
1493a7596147b43940cad3f76c53ed154ef088b9269bJim Miller    }
1494a7596147b43940cad3f76c53ed154ef088b9269bJim Miller
1495d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    private void updateActiveGroup(int userId, String clientPackage) {
149640e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller        IBiometricsFingerprint daemon = getFingerprintDaemon();
1497bcc100aae93bdae85c3f3679dfdda0508450f94eJim Miller
1498be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller        if (daemon != null) {
1499be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller            try {
1500d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                userId = getUserOrWorkProfileId(clientPackage, userId);
1501d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                if (userId != mCurrentUserId) {
15025670247168820bdbfdc3c91b954ca6779ca401ecYifan Hong                    int firstSdkInt = Build.VERSION.FIRST_SDK_INT;
1503456461238f86e1ff42b5b07de22c3231bee9bc6fYifan Hong                    if (firstSdkInt < Build.VERSION_CODES.BASE) {
1504456461238f86e1ff42b5b07de22c3231bee9bc6fYifan Hong                        Slog.e(TAG, "First SDK version " + firstSdkInt + " is invalid; must be " +
1505456461238f86e1ff42b5b07de22c3231bee9bc6fYifan Hong                                "at least VERSION_CODES.BASE");
1506456461238f86e1ff42b5b07de22c3231bee9bc6fYifan Hong                    }
15077fe2053a55ed071bc28d44cb2f34dfc9f4efd520Andreas Huber                    File baseDir;
15085670247168820bdbfdc3c91b954ca6779ca401ecYifan Hong                    if (firstSdkInt <= Build.VERSION_CODES.O_MR1) {
15097fe2053a55ed071bc28d44cb2f34dfc9f4efd520Andreas Huber                        baseDir = Environment.getUserSystemDirectory(userId);
15107fe2053a55ed071bc28d44cb2f34dfc9f4efd520Andreas Huber                    } else {
15117fe2053a55ed071bc28d44cb2f34dfc9f4efd520Andreas Huber                        baseDir = Environment.getDataVendorDeDirectory(userId);
15127fe2053a55ed071bc28d44cb2f34dfc9f4efd520Andreas Huber                    }
15137fe2053a55ed071bc28d44cb2f34dfc9f4efd520Andreas Huber
15147fe2053a55ed071bc28d44cb2f34dfc9f4efd520Andreas Huber                    File fpDir = new File(baseDir, FP_DATA_DIR);
1515d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                    if (!fpDir.exists()) {
1516d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                        if (!fpDir.mkdir()) {
1517d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                            Slog.v(TAG, "Cannot make directory: " + fpDir.getAbsolutePath());
1518d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                            return;
1519d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                        }
1520d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                        // Calling mkdir() from this process will create a directory with our
1521d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                        // permissions (inherited from the containing dir). This command fixes
1522d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                        // the label.
1523d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                        if (!SELinux.restorecon(fpDir)) {
1524d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                            Slog.w(TAG, "Restorecons failed. Directory will have wrong label.");
1525d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                            return;
1526d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                        }
152716ef71f4f5a01158fdc07dbbd0963aa2fb04e359Jim Miller                    }
15287fe2053a55ed071bc28d44cb2f34dfc9f4efd520Andreas Huber
152940e4645e6e564b962bb73c85c5325ec54ad34cc1Jim Miller                    daemon.setActiveGroup(userId, fpDir.getAbsolutePath());
1530d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri                    mCurrentUserId = userId;
1531be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller                }
153229b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He                mAuthenticatorIds.put(userId,
153329b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He                        hasEnrolledFingerprints(userId) ? daemon.getAuthenticatorId() : 0L);
1534be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller            } catch (RemoteException e) {
1535be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller                Slog.e(TAG, "Failed to setActiveGroup():", e);
1536be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller            }
1537dbe780f293163c478933a1f2ce97189703656c10Jim Miller        }
1538aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi    }
1539aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi
1540d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    /**
1541d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @param clientPackage the package of the caller
1542d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @return the profile id
1543d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     */
1544d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    private int getUserOrWorkProfileId(String clientPackage, int userId) {
1545d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        if (!isKeyguard(clientPackage) && isWorkProfile(userId)) {
1546d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri            return userId;
1547d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        }
1548d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri        return getEffectiveUserId(userId);
1549d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    }
1550d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri
1551d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    /**
1552d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @param userId
1553d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     * @return true if this is a work profile
1554d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri     */
1555d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    private boolean isWorkProfile(int userId) {
1556da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        UserInfo userInfo = null;
1557da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        final long token = Binder.clearCallingIdentity();
1558da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        try {
1559da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            userInfo = mUserManager.getUserInfo(userId);
1560da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        } finally {
1561da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He            Binder.restoreCallingIdentity(token);
1562da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        }
1563da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        return userInfo != null && userInfo.isManagedProfile();
1564d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri    }
1565d1f722d906f66ef05cd329feb9edbed178314d46Clara Bayarri
1566aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi    private void listenForUserSwitches() {
1567aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi        try {
1568dc589ac82b5fe2063f4cfd94c8ae26d43d5420a0Sudheer Shanka            ActivityManager.getService().registerUserSwitchObserver(
15696005b3f87b063ee7ab7e8877a6a8c90b480f3341Fyodor Kupolov                new SynchronousUserSwitchObserver() {
1570be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller                    @Override
15716005b3f87b063ee7ab7e8877a6a8c90b480f3341Fyodor Kupolov                    public void onUserSwitching(int newUserId) throws RemoteException {
1572be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller                        mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */)
1573be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller                                .sendToTarget();
1574be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller                    }
15750b77ef9f5199b7cd0956f2bfe049cbd699ca03b4Fyodor Kupolov                }, TAG);
1576aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi        } catch (RemoteException e) {
1577aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi            Slog.w(TAG, "Failed to listen for user switching event" ,e);
1578aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi        }
1579aa4d32add72fa728f9cfe4eeb014b26eb5d091c2Jorim Jaggi    }
1580be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller
1581d0063106b67c9aa44d9473102a1116aad136f50fJim Miller    /***
1582d0063106b67c9aa44d9473102a1116aad136f50fJim Miller     * @param opPackageName the name of the calling package
1583da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He     * @return authenticator id for the calling user
1584d0063106b67c9aa44d9473102a1116aad136f50fJim Miller     */
1585cb2ce6f1f0deef80943ece093ae40bacc1f57c44Jim Miller    public long getAuthenticatorId(String opPackageName) {
1586da88f0e6b8bde99b1d65c73f20c9704b06cf5f5aCharles He        final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId());
158729b3a8ad26cc416c4fd6ca3444e9c22507bc3778Charles He        return mAuthenticatorIds.getOrDefault(userId, 0L);
1588be67542182e41a6e31cf002db72ec42ee717bd1cJim Miller    }
1589a7596147b43940cad3f76c53ed154ef088b9269bJim Miller}
1590