blob: 06329e571b433ecc8b79cb59f2dd02247451782a [file] [log] [blame]
Charles He959ac8e2017-03-27 21:16:20 +01001/*
Jim Millera75961472014-06-06 15:00:49 -07002 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.fingerprint;
18
Charles He959ac8e2017-03-27 21:16:20 +010019import static android.Manifest.permission.INTERACT_ACROSS_USERS;
20import static android.Manifest.permission.MANAGE_FINGERPRINT;
21import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
Vishwath Mohancf87df12018-03-20 22:57:17 -070022import static android.Manifest.permission.USE_BIOMETRIC;
Charles He959ac8e2017-03-27 21:16:20 +010023import static android.Manifest.permission.USE_FINGERPRINT;
Svet Ganov31217602018-05-18 19:59:25 -070024import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
Charles He959ac8e2017-03-27 21:16:20 +010025
Sasha Levitskiy80db9ba2015-05-08 14:31:48 -070026import android.app.ActivityManager;
Jim Miller975f1452015-08-31 18:18:22 -070027import android.app.ActivityManager.RunningAppProcessInfo;
Jorim Jaggi5e354222015-09-04 14:17:58 -070028import android.app.AlarmManager;
Svetoslav4af76a52015-04-29 15:29:46 -070029import android.app.AppOpsManager;
Kevin Chyn09da2942018-03-09 13:13:11 -080030import android.app.IActivityManager;
Jorim Jaggi5e354222015-09-04 14:17:58 -070031import android.app.PendingIntent;
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -080032import android.app.SynchronousUserSwitchObserver;
Kevin Chyn09da2942018-03-09 13:13:11 -080033import android.app.TaskStackListener;
Jorim Jaggi5e354222015-09-04 14:17:58 -070034import android.content.BroadcastReceiver;
Charles He29b3a8a2017-05-04 16:02:38 +010035import android.content.ComponentName;
Jim Millera75961472014-06-06 15:00:49 -070036import android.content.Context;
Jorim Jaggi5e354222015-09-04 14:17:58 -070037import android.content.Intent;
38import android.content.IntentFilter;
Jim Millerf501b582015-06-03 16:36:31 -070039import android.content.pm.PackageManager;
Jim Millercb7d9e92015-06-16 15:05:48 -070040import android.content.pm.UserInfo;
Vishwath Mohanecf00ce2018-04-05 10:28:24 -070041import android.hardware.biometrics.IBiometricPromptReceiver;
Charles He959ac8e2017-03-27 21:16:20 +010042import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
43import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback;
44import android.hardware.fingerprint.Fingerprint;
45import android.hardware.fingerprint.FingerprintManager;
Phil Weaver27fcd9c2017-01-20 15:57:24 -080046import android.hardware.fingerprint.IFingerprintClientActiveCallback;
Charles He959ac8e2017-03-27 21:16:20 +010047import android.hardware.fingerprint.IFingerprintService;
Jorim Jaggi3a464782015-08-28 16:59:13 -070048import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
Charles He959ac8e2017-03-27 21:16:20 +010049import android.hardware.fingerprint.IFingerprintServiceReceiver;
Svetoslav4af76a52015-04-29 15:29:46 -070050import android.os.Binder;
Andreas Huber7fe20532018-01-22 11:26:44 -080051import android.os.Build;
Jorim Jaggi57e2f4d2016-11-24 14:38:18 +010052import android.os.Bundle;
Jorim Jaggi3a464782015-08-28 16:59:13 -070053import android.os.DeadObjectException;
Sasha Levitskiy80db9ba2015-05-08 14:31:48 -070054import android.os.Environment;
Jim Millera75961472014-06-06 15:00:49 -070055import android.os.Handler;
56import android.os.IBinder;
Jim Miller40e46452016-12-16 18:38:53 -080057import android.os.IHwBinder;
Jorim Jaggi57e2f4d2016-11-24 14:38:18 +010058import android.os.IRemoteCallback;
Jim Millerdca15d22015-06-16 20:55:13 -070059import android.os.PowerManager;
Jorim Jaggi57e2f4d2016-11-24 14:38:18 +010060import android.os.PowerManager.WakeLock;
Jim Millera75961472014-06-06 15:00:49 -070061import android.os.RemoteException;
Jim Miller16ef71f2015-05-21 17:02:21 -070062import android.os.SELinux;
Kevin Chynaae4a152018-01-18 11:48:09 -080063import android.os.ServiceManager;
Jim Millerdca15d22015-06-16 20:55:13 -070064import android.os.SystemClock;
Jim Miller599ef0e2015-06-15 20:39:44 -070065import android.os.UserHandle;
Jim Millercb7d9e92015-06-16 15:05:48 -070066import android.os.UserManager;
Charles He959ac8e2017-03-27 21:16:20 +010067import android.security.KeyStore;
Jim Millera75961472014-06-06 15:00:49 -070068import android.util.Slog;
Kevin Chyn5457cba2017-08-30 15:28:28 -070069import android.util.SparseBooleanArray;
70import android.util.SparseIntArray;
Joe Onorato1754d742016-11-21 17:51:35 -080071import android.util.proto.ProtoOutputStream;
Jim Millera75961472014-06-06 15:00:49 -070072
Fyodor Kupolov449e7082016-10-31 15:06:12 -070073import com.android.internal.annotations.GuardedBy;
Chris Wrenc510ad52015-08-14 15:43:15 -040074import com.android.internal.logging.MetricsLogger;
Kevin Chynaae4a152018-01-18 11:48:09 -080075import com.android.internal.statusbar.IStatusBarService;
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -060076import com.android.internal.util.DumpUtils;
Fyodor Kupolove29a5a12016-12-16 16:14:17 -080077import com.android.server.SystemServerInitThreadPool;
Jim Millera75961472014-06-06 15:00:49 -070078import com.android.server.SystemService;
79
Chris Wrenc510ad52015-08-14 15:43:15 -040080import org.json.JSONArray;
81import org.json.JSONException;
82import org.json.JSONObject;
83
Sasha Levitskiy80db9ba2015-05-08 14:31:48 -070084import java.io.File;
Chris Wrenc510ad52015-08-14 15:43:15 -040085import java.io.FileDescriptor;
86import java.io.PrintWriter;
Jorim Jaggi3a464782015-08-28 16:59:13 -070087import java.util.ArrayList;
Svetoslav4af76a52015-04-29 15:29:46 -070088import java.util.Collections;
Jim Millerbcc100a2016-07-06 14:16:49 -070089import java.util.HashMap;
Jim Miller9f0753f2015-03-23 23:59:22 -070090import java.util.List;
Charles Heda88f0e2017-02-02 18:29:13 +000091import java.util.Map;
Phil Weaver27fcd9c2017-01-20 15:57:24 -080092import java.util.concurrent.CopyOnWriteArrayList;
Jim Millera75961472014-06-06 15:00:49 -070093
94/**
95 * A service to manage multiple clients that want to access the fingerprint HAL API.
96 * The service is responsible for maintaining a list of clients and dispatching all
Kevin Chynedd71f92017-09-01 16:09:57 -070097 * fingerprint-related events.
Jim Millera75961472014-06-06 15:00:49 -070098 *
99 * @hide
100 */
Jim Miller40e46452016-12-16 18:38:53 -0800101public class FingerprintService extends SystemService implements IHwBinder.DeathRecipient {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700102 static final String TAG = "FingerprintService";
103 static final boolean DEBUG = true;
Kevin Chynedd71f92017-09-01 16:09:57 -0700104 private static final boolean CLEANUP_UNUSED_FP = true;
Jim Millerbe675422015-05-11 20:45:25 -0700105 private static final String FP_DATA_DIR = "fpdata";
Jim Millerbe675422015-05-11 20:45:25 -0700106 private static final int MSG_USER_SWITCHING = 10;
Jorim Jaggi5e354222015-09-04 14:17:58 -0700107 private static final String ACTION_LOCKOUT_RESET =
108 "com.android.server.fingerprint.ACTION_LOCKOUT_RESET";
Kevin Chyn5457cba2017-08-30 15:28:28 -0700109 private static final String KEY_LOCKOUT_RESET_USER = "lockout_reset_user";
Jim Millerbe675422015-05-11 20:45:25 -0700110
Jim Millerbcc100a2016-07-06 14:16:49 -0700111 private class PerformanceStats {
112 int accept; // number of accepted fingerprints
113 int reject; // number of rejected fingerprints
114 int acquire; // total number of acquisitions. Should be >= accept+reject due to poor image
115 // acquisition in some cases (too fast, too slow, dirty sensor, etc.)
116 int lockout; // total number of lockouts
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700117 int permanentLockout; // total number of permanent lockouts
Jim Millerbcc100a2016-07-06 14:16:49 -0700118 }
119
Jorim Jaggi3a464782015-08-28 16:59:13 -0700120 private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
121 new ArrayList<>();
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800122 private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks =
123 new CopyOnWriteArrayList<>();
Charles Heda88f0e2017-02-02 18:29:13 +0000124 private final Map<Integer, Long> mAuthenticatorIds =
125 Collections.synchronizedMap(new HashMap<>());
Svetoslav4af76a52015-04-29 15:29:46 -0700126 private final AppOpsManager mAppOps;
Jim Milleraf281ca2015-04-20 19:04:21 -0700127 private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700128 private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5;
129 private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20;
130
Jim Miller3d5e3962016-06-08 01:52:50 +0000131 private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms
Jim Miller975f1452015-08-31 18:18:22 -0700132 private final String mKeyguardPackage;
Charles He959ac8e2017-03-27 21:16:20 +0100133 private int mCurrentUserId = UserHandle.USER_NULL;
Jim Millercb2ce6f2016-04-13 20:28:18 -0700134 private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance();
135 private Context mContext;
136 private long mHalDeviceId;
Kevin Chyn5457cba2017-08-30 15:28:28 -0700137 private SparseBooleanArray mTimedLockoutCleared;
138 private SparseIntArray mFailedAttempts;
Fyodor Kupolov449e7082016-10-31 15:06:12 -0700139 @GuardedBy("this")
Jim Miller40e46452016-12-16 18:38:53 -0800140 private IBiometricsFingerprint mDaemon;
Kevin Chynaae4a152018-01-18 11:48:09 -0800141 private IStatusBarService mStatusBarService;
Kevin Chyn09da2942018-03-09 13:13:11 -0800142 private final IActivityManager mActivityManager;
Jim Millercb2ce6f2016-04-13 20:28:18 -0700143 private final PowerManager mPowerManager;
144 private final AlarmManager mAlarmManager;
145 private final UserManager mUserManager;
146 private ClientMonitor mCurrentClient;
147 private ClientMonitor mPendingClient;
Jim Millerbcc100a2016-07-06 14:16:49 -0700148 private PerformanceStats mPerformanceStats;
149
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700150 private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration
Kevin Chynedd71f92017-09-01 16:09:57 -0700151 private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw fingerprints
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700152
153 private class UserFingerprint {
154 Fingerprint f;
155 int userId;
156 public UserFingerprint(Fingerprint f, int userId) {
157 this.f = f;
158 this.userId = userId;
159 }
160 }
161
Jim Millerbcc100a2016-07-06 14:16:49 -0700162 // Normal fingerprint authentications are tracked by mPerformanceMap.
Jim Miller40e46452016-12-16 18:38:53 -0800163 private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>();
Jim Millerbcc100a2016-07-06 14:16:49 -0700164
165 // Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap.
Jim Miller40e46452016-12-16 18:38:53 -0800166 private HashMap<Integer, PerformanceStats> mCryptoPerformanceMap = new HashMap<>();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700167
Jim Millercb2ce6f2016-04-13 20:28:18 -0700168 private Handler mHandler = new Handler() {
Jim Miller80a776e2015-07-15 18:57:14 -0700169 @Override
Jim Millera75961472014-06-06 15:00:49 -0700170 public void handleMessage(android.os.Message msg) {
171 switch (msg.what) {
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -0700172 case MSG_USER_SWITCHING:
173 handleUserSwitching(msg.arg1);
174 break;
175
Jim Millera75961472014-06-06 15:00:49 -0700176 default:
177 Slog.w(TAG, "Unknown message:" + msg.what);
178 }
179 }
180 };
Jim Millerbe675422015-05-11 20:45:25 -0700181
Jorim Jaggi5e354222015-09-04 14:17:58 -0700182 private final BroadcastReceiver mLockoutReceiver = new BroadcastReceiver() {
183 @Override
184 public void onReceive(Context context, Intent intent) {
185 if (ACTION_LOCKOUT_RESET.equals(intent.getAction())) {
Kevin Chyn5457cba2017-08-30 15:28:28 -0700186 final int user = intent.getIntExtra(KEY_LOCKOUT_RESET_USER, 0);
187 resetFailedAttemptsForUser(false /* clearAttemptCounter */, user);
Jorim Jaggi5e354222015-09-04 14:17:58 -0700188 }
189 }
190 };
191
Kevin Chyn5457cba2017-08-30 15:28:28 -0700192 private final Runnable mResetFailedAttemptsForCurrentUserRunnable = new Runnable() {
Jim Millerfe6439f2015-04-11 18:07:57 -0700193 @Override
194 public void run() {
Kevin Chyn5457cba2017-08-30 15:28:28 -0700195 resetFailedAttemptsForUser(true /* clearAttemptCounter */,
196 ActivityManager.getCurrentUser());
Jim Millerfe6439f2015-04-11 18:07:57 -0700197 }
198 };
Jim Millera75961472014-06-06 15:00:49 -0700199
Jim Millercb2ce6f2016-04-13 20:28:18 -0700200 private final Runnable mResetClientState = new Runnable() {
201 @Override
202 public void run() {
203 // Warning: if we get here, the driver never confirmed our call to cancel the current
204 // operation (authenticate, enroll, remove, enumerate, etc), which is
205 // really bad. The result will be a 3-second delay in starting each new client.
206 // If you see this on a device, make certain the driver notifies with
207 // {@link FingerprintManager#FINGERPRINT_ERROR_CANCEL} in response to cancel()
208 // once it has successfully switched to the IDLE state in the fingerprint HAL.
209 // Additionally,{@link FingerprintManager#FINGERPRINT_ERROR_CANCEL} should only be sent
210 // in response to an actual cancel() call.
211 Slog.w(TAG, "Client "
212 + (mCurrentClient != null ? mCurrentClient.getOwnerString() : "null")
213 + " failed to respond to cancel, starting client "
214 + (mPendingClient != null ? mPendingClient.getOwnerString() : "null"));
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700215
Jim Millercb2ce6f2016-04-13 20:28:18 -0700216 mCurrentClient = null;
217 startClient(mPendingClient, false);
218 }
219 };
220
Kevin Chyn09da2942018-03-09 13:13:11 -0800221 private final TaskStackListener mTaskStackListener = new TaskStackListener() {
222 @Override
223 public void onTaskStackChanged() {
224 try {
225 if (!(mCurrentClient instanceof AuthenticationClient)) {
226 return;
227 }
Kevin Chyna792fa62018-04-16 19:09:10 -0700228 final String currentClient = mCurrentClient.getOwnerString();
229 if (isKeyguard(currentClient)) {
Kevin Chyn09da2942018-03-09 13:13:11 -0800230 return; // Keyguard is always allowed
231 }
232 List<ActivityManager.RunningTaskInfo> runningTasks = mActivityManager.getTasks(1);
233 if (!runningTasks.isEmpty()) {
Kevin Chynda1b2ab2018-04-11 12:28:59 -0700234 final String topPackage = runningTasks.get(0).topActivity.getPackageName();
Kevin Chyna792fa62018-04-16 19:09:10 -0700235 if (!topPackage.contentEquals(currentClient)) {
Kevin Chynda1b2ab2018-04-11 12:28:59 -0700236 Slog.e(TAG, "Stopping background authentication, top: " + topPackage
Kevin Chyna792fa62018-04-16 19:09:10 -0700237 + " currentClient: " + currentClient);
238 mCurrentClient.stop(false /* initiatedByClient */);
Kevin Chyn09da2942018-03-09 13:13:11 -0800239 }
240 }
241 } catch (RemoteException e) {
242 Slog.e(TAG, "Unable to get running tasks", e);
243 }
244 }
245 };
246
Jim Millera75961472014-06-06 15:00:49 -0700247 public FingerprintService(Context context) {
248 super(context);
249 mContext = context;
Jim Miller975f1452015-08-31 18:18:22 -0700250 mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
251 com.android.internal.R.string.config_keyguardComponent)).getPackageName();
Svetoslav4af76a52015-04-29 15:29:46 -0700252 mAppOps = context.getSystemService(AppOpsManager.class);
Jorim Jaggi5e354222015-09-04 14:17:58 -0700253 mPowerManager = mContext.getSystemService(PowerManager.class);
254 mAlarmManager = mContext.getSystemService(AlarmManager.class);
255 mContext.registerReceiver(mLockoutReceiver, new IntentFilter(ACTION_LOCKOUT_RESET),
256 RESET_FINGERPRINT_LOCKOUT, null /* handler */);
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000257 mUserManager = UserManager.get(mContext);
Kevin Chyn5457cba2017-08-30 15:28:28 -0700258 mTimedLockoutCleared = new SparseBooleanArray();
259 mFailedAttempts = new SparseIntArray();
Kevin Chynaae4a152018-01-18 11:48:09 -0800260 mStatusBarService = IStatusBarService.Stub.asInterface(
261 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
Kevin Chyn09da2942018-03-09 13:13:11 -0800262 mActivityManager = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
263 .getService();
Jim Millera75961472014-06-06 15:00:49 -0700264 }
265
Jim Millerbe675422015-05-11 20:45:25 -0700266 @Override
Jim Miller40e46452016-12-16 18:38:53 -0800267 public void serviceDied(long cookie) {
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700268 Slog.v(TAG, "fingerprint HAL died");
Jim Millerc57c8d92016-09-30 17:17:59 -0700269 MetricsLogger.count(mContext, "fingerprintd_died", 1);
Jim Miller40e46452016-12-16 18:38:53 -0800270 handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE,
271 0 /*vendorCode */);
Jim Millera75961472014-06-06 15:00:49 -0700272 }
273
Jim Miller40e46452016-12-16 18:38:53 -0800274 public synchronized IBiometricsFingerprint getFingerprintDaemon() {
275 if (mDaemon == null) {
Kevin Chynedd71f92017-09-01 16:09:57 -0700276 Slog.v(TAG, "mDaemon was null, reconnect to fingerprint");
Jim Miller40e46452016-12-16 18:38:53 -0800277 try {
Yifan Hong25d5eaa2017-03-16 15:25:43 -0700278 mDaemon = IBiometricsFingerprint.getService();
Jim Miller40e46452016-12-16 18:38:53 -0800279 } catch (java.util.NoSuchElementException e) {
280 // Service doesn't exist or cannot be opened. Logged below.
281 } catch (RemoteException e) {
282 Slog.e(TAG, "Failed to get biometric interface", e);
Jim Millera75961472014-06-06 15:00:49 -0700283 }
Jim Miller40e46452016-12-16 18:38:53 -0800284 if (mDaemon == null) {
285 Slog.w(TAG, "fingerprint HIDL not available");
286 return null;
287 }
288
289 mDaemon.asBinder().linkToDeath(this, 0);
290
291 try {
292 mHalDeviceId = mDaemon.setNotify(mDaemonCallback);
293 } catch (RemoteException e) {
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700294 Slog.e(TAG, "Failed to open fingerprint HAL", e);
Jim Miller40e46452016-12-16 18:38:53 -0800295 mDaemon = null; // try again later!
296 }
297
298 if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
299 if (mHalDeviceId != 0) {
Charles Heda88f0e2017-02-02 18:29:13 +0000300 loadAuthenticatorIds();
Jim Miller40e46452016-12-16 18:38:53 -0800301 updateActiveGroup(ActivityManager.getCurrentUser(), null);
Kevin Chynedd71f92017-09-01 16:09:57 -0700302 doFingerprintCleanupForUser(ActivityManager.getCurrentUser());
Jim Miller40e46452016-12-16 18:38:53 -0800303 } else {
304 Slog.w(TAG, "Failed to open Fingerprint HAL!");
305 MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
306 mDaemon = null;
307 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700308 }
Jim Miller40e46452016-12-16 18:38:53 -0800309 return mDaemon;
Jim Millerbe675422015-05-11 20:45:25 -0700310 }
311
Charles Heda88f0e2017-02-02 18:29:13 +0000312 /** Populates existing authenticator ids. To be used only during the start of the service. */
313 private void loadAuthenticatorIds() {
314 // This operation can be expensive, so keep track of the elapsed time. Might need to move to
315 // background if it takes too long.
316 long t = System.currentTimeMillis();
Charles Heda88f0e2017-02-02 18:29:13 +0000317 mAuthenticatorIds.clear();
318 for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
319 int userId = getUserOrWorkProfileId(null, user.id);
320 if (!mAuthenticatorIds.containsKey(userId)) {
321 updateActiveGroup(userId, null);
322 }
323 }
324
325 t = System.currentTimeMillis() - t;
326 if (t > 1000) {
327 Slog.w(TAG, "loadAuthenticatorIds() taking too long: " + t + "ms");
328 }
329 }
330
Kevin Chynedd71f92017-09-01 16:09:57 -0700331 /**
332 * This method should be called upon connection to the daemon, and when user switches.
333 * @param userId
334 */
335 private void doFingerprintCleanupForUser(int userId) {
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700336 if (CLEANUP_UNUSED_FP) {
Kevin Chynedd71f92017-09-01 16:09:57 -0700337 enumerateUser(userId);
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700338 }
339 }
340
Kevin Chynedd71f92017-09-01 16:09:57 -0700341 private void clearEnumerateState() {
342 if (DEBUG) Slog.v(TAG, "clearEnumerateState()");
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700343 mUnknownFingerprints.clear();
344 }
345
Kevin Chynedd71f92017-09-01 16:09:57 -0700346 private void enumerateUser(int userId) {
347 if (DEBUG) Slog.v(TAG, "Enumerating user(" + userId + ")");
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700348 boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
Kevin Chynedd71f92017-09-01 16:09:57 -0700349 startEnumerate(mToken, userId, null, restricted, true /* internal */);
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700350 }
351
352 // Remove unknown fingerprints from hardware
353 private void cleanupUnknownFingerprints() {
354 if (!mUnknownFingerprints.isEmpty()) {
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700355 UserFingerprint uf = mUnknownFingerprints.get(0);
356 mUnknownFingerprints.remove(uf);
357 boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700358 startRemove(mToken, uf.f.getFingerId(), uf.f.getGroupId(), uf.userId, null,
359 restricted, true /* internal */);
360 } else {
Kevin Chynedd71f92017-09-01 16:09:57 -0700361 clearEnumerateState();
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700362 }
363 }
364
Jim Miller40e46452016-12-16 18:38:53 -0800365 protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700366 ClientMonitor client = mCurrentClient;
367
368 if ( !(client instanceof InternalRemovalClient) && !(client instanceof EnumerateClient) ) {
369 return;
370 }
371 client.onEnumerationResult(fingerId, groupId, remaining);
372
373 // All fingerprints in hardware for this user were enumerated
374 if (remaining == 0) {
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700375 if (client instanceof InternalEnumerateClient) {
Kevin Chynedd71f92017-09-01 16:09:57 -0700376 List<Fingerprint> unknownFingerprints =
377 ((InternalEnumerateClient) client).getUnknownFingerprints();
378
379 if (!unknownFingerprints.isEmpty()) {
380 Slog.w(TAG, "Adding " + unknownFingerprints.size() +
381 " fingerprints for deletion");
382 }
383 for (Fingerprint f : unknownFingerprints) {
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700384 mUnknownFingerprints.add(new UserFingerprint(f, client.getTargetUserId()));
385 }
Kevin Chynedd71f92017-09-01 16:09:57 -0700386 removeClient(client);
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700387 cleanupUnknownFingerprints();
Kevin Chynedd71f92017-09-01 16:09:57 -0700388 } else {
389 removeClient(client);
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700390 }
391 }
Jim Millerbe675422015-05-11 20:45:25 -0700392 }
393
Jim Miller40e46452016-12-16 18:38:53 -0800394 protected void handleError(long deviceId, int error, int vendorCode) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700395 ClientMonitor client = mCurrentClient;
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700396 if (client instanceof InternalRemovalClient || client instanceof InternalEnumerateClient) {
Kevin Chynedd71f92017-09-01 16:09:57 -0700397 clearEnumerateState();
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700398 }
Jim Miller40e46452016-12-16 18:38:53 -0800399 if (client != null && client.onError(error, vendorCode)) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700400 removeClient(client);
Jim Millerbe675422015-05-11 20:45:25 -0700401 }
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700402
Jim Millercb2ce6f2016-04-13 20:28:18 -0700403 if (DEBUG) Slog.v(TAG, "handleError(client="
Jim Millerc1e61b82016-04-18 13:00:40 -0700404 + (client != null ? client.getOwnerString() : "null") + ", error = " + error + ")");
Jim Millercb2ce6f2016-04-13 20:28:18 -0700405 // This is the magic code that starts the next client when the old client finishes.
406 if (error == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
407 mHandler.removeCallbacks(mResetClientState);
408 if (mPendingClient != null) {
409 if (DEBUG) Slog.v(TAG, "start pending client " + mPendingClient.getOwnerString());
410 startClient(mPendingClient, false);
411 mPendingClient = null;
412 }
Jim Miller8eddd332017-03-22 16:40:10 -0700413 } else if (error == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) {
414 // If we get HW_UNAVAILABLE, try to connect again later...
415 Slog.w(TAG, "Got ERROR_HW_UNAVAILABLE; try reconnecting next client.");
416 synchronized (this) {
417 mDaemon = null;
418 mHalDeviceId = 0;
Charles He959ac8e2017-03-27 21:16:20 +0100419 mCurrentUserId = UserHandle.USER_NULL;
Jim Miller8eddd332017-03-22 16:40:10 -0700420 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700421 }
422 }
423
Jim Miller40e46452016-12-16 18:38:53 -0800424 protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) {
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700425 if (DEBUG) Slog.w(TAG, "Removed: fid=" + fingerId
426 + ", gid=" + groupId
427 + ", dev=" + deviceId
428 + ", rem=" + remaining);
429
Jim Millercb2ce6f2016-04-13 20:28:18 -0700430 ClientMonitor client = mCurrentClient;
Jim Miller40e46452016-12-16 18:38:53 -0800431 if (client != null && client.onRemoved(fingerId, groupId, remaining)) {
Jim Miller07dbd632016-04-05 18:22:30 -0700432 removeClient(client);
Charles He29b3a8a2017-05-04 16:02:38 +0100433 // When the last fingerprint of a group is removed, update the authenticator id
434 if (!hasEnrolledFingerprints(groupId)) {
435 updateActiveGroup(groupId, null);
436 }
Jim Millerbe675422015-05-11 20:45:25 -0700437 }
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700438 if (client instanceof InternalRemovalClient && !mUnknownFingerprints.isEmpty()) {
439 cleanupUnknownFingerprints();
440 } else if (client instanceof InternalRemovalClient){
Kevin Chynedd71f92017-09-01 16:09:57 -0700441 clearEnumerateState();
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700442 }
Jim Millerbe675422015-05-11 20:45:25 -0700443 }
444
Jim Millera8eaeeb2017-01-24 14:47:04 -0800445 protected void handleAuthenticated(long deviceId, int fingerId, int groupId,
446 ArrayList<Byte> token) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700447 ClientMonitor client = mCurrentClient;
Jim Millera8eaeeb2017-01-24 14:47:04 -0800448 if (fingerId != 0) {
449 // Ugh...
450 final byte[] byteToken = new byte[token.size()];
451 for (int i = 0; i < token.size(); i++) {
452 byteToken[i] = token.get(i);
453 }
454 // Send to Keystore
Brian Youngda82e2c2018-02-22 23:36:34 +0000455 KeyStore.getInstance().addAuthToken(byteToken);
Jim Millera8eaeeb2017-01-24 14:47:04 -0800456 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700457 if (client != null && client.onAuthenticated(fingerId, groupId)) {
458 removeClient(client);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700459 }
Jim Millerbcc100a2016-07-06 14:16:49 -0700460 if (fingerId != 0) {
461 mPerformanceStats.accept++;
462 } else {
463 mPerformanceStats.reject++;
464 }
Jim Millerbe675422015-05-11 20:45:25 -0700465 }
466
Jim Miller40e46452016-12-16 18:38:53 -0800467 protected void handleAcquired(long deviceId, int acquiredInfo, int vendorCode) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700468 ClientMonitor client = mCurrentClient;
Jim Miller40e46452016-12-16 18:38:53 -0800469 if (client != null && client.onAcquired(acquiredInfo, vendorCode)) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700470 removeClient(client);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700471 }
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700472 if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE
Jim Millerbcc100a2016-07-06 14:16:49 -0700473 && client instanceof AuthenticationClient) {
474 // ignore enrollment acquisitions or acquisitions when we're locked out
475 mPerformanceStats.acquire++;
476 }
Jim Millerdca15d22015-06-16 20:55:13 -0700477 }
Jim Millerbe675422015-05-11 20:45:25 -0700478
Jim Miller8b3c25a2015-08-28 17:29:49 -0700479 protected void handleEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700480 ClientMonitor client = mCurrentClient;
481 if (client != null && client.onEnrollResult(fingerId, groupId, remaining)) {
482 removeClient(client);
Charles He29b3a8a2017-05-04 16:02:38 +0100483 // When enrollment finishes, update this group's authenticator id, as the HAL has
484 // already generated a new authenticator id when the new fingerprint is enrolled.
485 updateActiveGroup(groupId, null);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700486 }
Jim Millerce7eb6d2015-04-03 19:29:13 -0700487 }
488
Jim Miller8b3c25a2015-08-28 17:29:49 -0700489 private void userActivity() {
490 long now = SystemClock.uptimeMillis();
491 mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
492 }
493
494 void handleUserSwitching(int userId) {
Kevin Chynedd71f92017-09-01 16:09:57 -0700495 if (mCurrentClient instanceof InternalRemovalClient
496 || mCurrentClient instanceof InternalEnumerateClient) {
497 Slog.w(TAG, "User switched while performing cleanup");
498 removeClient(mCurrentClient);
499 clearEnumerateState();
500 }
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000501 updateActiveGroup(userId, null);
Kevin Chynedd71f92017-09-01 16:09:57 -0700502 doFingerprintCleanupForUser(userId);
Jim Miller8b3c25a2015-08-28 17:29:49 -0700503 }
504
Jim Millerbe675422015-05-11 20:45:25 -0700505 private void removeClient(ClientMonitor client) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700506 if (client != null) {
507 client.destroy();
508 if (client != mCurrentClient && mCurrentClient != null) {
509 Slog.w(TAG, "Unexpected client: " + client.getOwnerString() + "expected: "
510 + mCurrentClient != null ? mCurrentClient.getOwnerString() : "null");
511 }
512 }
513 if (mCurrentClient != null) {
514 if (DEBUG) Slog.v(TAG, "Done with client: " + client.getOwnerString());
515 mCurrentClient = null;
Jim Millerfe6439f2015-04-11 18:07:57 -0700516 }
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800517 if (mPendingClient == null) {
518 notifyClientActiveCallbacks(false);
519 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700520 }
521
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700522 private int getLockoutMode() {
Kevin Chyn5457cba2017-08-30 15:28:28 -0700523 final int currentUser = ActivityManager.getCurrentUser();
524 final int failedAttempts = mFailedAttempts.get(currentUser, 0);
525 if (failedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) {
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700526 return AuthenticationClient.LOCKOUT_PERMANENT;
Kevin Chyn5457cba2017-08-30 15:28:28 -0700527 } else if (failedAttempts > 0 &&
528 mTimedLockoutCleared.get(currentUser, false) == false
529 && (failedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) {
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700530 return AuthenticationClient.LOCKOUT_TIMED;
531 }
532 return AuthenticationClient.LOCKOUT_NONE;
Jim Millerfe6439f2015-04-11 18:07:57 -0700533 }
534
Kevin Chyn5457cba2017-08-30 15:28:28 -0700535 private void scheduleLockoutResetForUser(int userId) {
536 mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
537 SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS,
538 getLockoutResetIntentForUser(userId));
Jorim Jaggi5e354222015-09-04 14:17:58 -0700539 }
540
Kevin Chyn5457cba2017-08-30 15:28:28 -0700541 private void cancelLockoutResetForUser(int userId) {
542 mAlarmManager.cancel(getLockoutResetIntentForUser(userId));
Jorim Jaggi5e354222015-09-04 14:17:58 -0700543 }
544
Kevin Chyn5457cba2017-08-30 15:28:28 -0700545 private PendingIntent getLockoutResetIntentForUser(int userId) {
546 return PendingIntent.getBroadcast(mContext, userId,
547 new Intent(ACTION_LOCKOUT_RESET).putExtra(KEY_LOCKOUT_RESET_USER, userId),
548 PendingIntent.FLAG_UPDATE_CURRENT);
Jorim Jaggi5e354222015-09-04 14:17:58 -0700549 }
550
Jim Millerce7eb6d2015-04-03 19:29:13 -0700551 public long startPreEnroll(IBinder token) {
Jim Miller40e46452016-12-16 18:38:53 -0800552 IBiometricsFingerprint daemon = getFingerprintDaemon();
Jim Millerbe675422015-05-11 20:45:25 -0700553 if (daemon == null) {
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700554 Slog.w(TAG, "startPreEnroll: no fingerprint HAL!");
Jim Millerbe675422015-05-11 20:45:25 -0700555 return 0;
556 }
557 try {
558 return daemon.preEnroll();
559 } catch (RemoteException e) {
560 Slog.e(TAG, "startPreEnroll failed", e);
561 }
562 return 0;
Jim Millerce7eb6d2015-04-03 19:29:13 -0700563 }
564
Sasha Levitskiye0943cf2015-07-08 13:22:20 -0700565 public int startPostEnroll(IBinder token) {
Jim Miller40e46452016-12-16 18:38:53 -0800566 IBiometricsFingerprint daemon = getFingerprintDaemon();
Sasha Levitskiye0943cf2015-07-08 13:22:20 -0700567 if (daemon == null) {
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700568 Slog.w(TAG, "startPostEnroll: no fingerprint HAL!");
Sasha Levitskiye0943cf2015-07-08 13:22:20 -0700569 return 0;
570 }
571 try {
572 return daemon.postEnroll();
573 } catch (RemoteException e) {
574 Slog.e(TAG, "startPostEnroll failed", e);
575 }
576 return 0;
577 }
578
Jim Miller80a776e2015-07-15 18:57:14 -0700579 /**
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700580 * Calls fingerprint HAL to switch states to the new task. If there's already a current task,
Jim Millercb2ce6f2016-04-13 20:28:18 -0700581 * it calls cancel() and sets mPendingClient to begin when the current task finishes
582 * ({@link FingerprintManager#FINGERPRINT_ERROR_CANCELED}).
583 * @param newClient the new client that wants to connect
584 * @param initiatedByClient true for authenticate, remove and enroll
Jim Miller80a776e2015-07-15 18:57:14 -0700585 */
Jim Millercb2ce6f2016-04-13 20:28:18 -0700586 private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
587 ClientMonitor currentClient = mCurrentClient;
588 if (currentClient != null) {
589 if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700590 if (currentClient instanceof InternalEnumerateClient ||
591 currentClient instanceof InternalRemovalClient) {
592 // This condition means we're currently running internal diagnostics to
593 // remove extra fingerprints in the hardware and/or the software
594 // TODO: design an escape hatch in case client never finishes
Kevin Chynedd71f92017-09-01 16:09:57 -0700595 if (newClient != null) {
596 Slog.w(TAG, "Internal cleanup in progress but trying to start client "
597 + newClient.getClass().getSuperclass().getSimpleName()
598 + "(" + newClient.getOwnerString() + ")"
599 + ", initiatedByClient = " + initiatedByClient);
600 }
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700601 }
602 else {
603 currentClient.stop(initiatedByClient);
604 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700605 mPendingClient = newClient;
606 mHandler.removeCallbacks(mResetClientState);
607 mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
608 } else if (newClient != null) {
609 mCurrentClient = newClient;
610 if (DEBUG) Slog.v(TAG, "starting client "
611 + newClient.getClass().getSuperclass().getSimpleName()
612 + "(" + newClient.getOwnerString() + ")"
Kevin Chynedd71f92017-09-01 16:09:57 -0700613 + ", initiatedByClient = " + initiatedByClient);
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800614 notifyClientActiveCallbacks(true);
615
Jim Millercb2ce6f2016-04-13 20:28:18 -0700616 newClient.start();
Jim Millera75961472014-06-06 15:00:49 -0700617 }
618 }
619
Jim Miller8f2aca02016-04-20 13:34:11 -0700620 void startRemove(IBinder token, int fingerId, int groupId, int userId,
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700621 IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
Ilya Matyukhin606f1712018-04-26 14:28:45 -0700622 if (token == null) {
623 Slog.w(TAG, "startRemove: token is null");
624 return;
625 }
626 if (receiver == null) {
627 Slog.w(TAG, "startRemove: receiver is null");
628 return;
629 }
630
Jim Miller40e46452016-12-16 18:38:53 -0800631 IBiometricsFingerprint daemon = getFingerprintDaemon();
Jim Millerbe675422015-05-11 20:45:25 -0700632 if (daemon == null) {
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700633 Slog.w(TAG, "startRemove: no fingerprint HAL!");
Jim Millerbe675422015-05-11 20:45:25 -0700634 return;
635 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700636
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700637 if (internal) {
638 Context context = getContext();
639 InternalRemovalClient client = new InternalRemovalClient(context, mHalDeviceId,
640 token, receiver, fingerId, groupId, userId, restricted,
641 context.getOpPackageName()) {
642 @Override
643 public void notifyUserActivity() {
644
645 }
646 @Override
647 public IBiometricsFingerprint getFingerprintDaemon() {
648 return FingerprintService.this.getFingerprintDaemon();
649 }
650 };
651 startClient(client, true);
652 }
653 else {
654 RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
655 receiver, fingerId, groupId, userId, restricted, token.toString()) {
656 @Override
657 public void notifyUserActivity() {
658 FingerprintService.this.userActivity();
659 }
660
661 @Override
662 public IBiometricsFingerprint getFingerprintDaemon() {
663 return FingerprintService.this.getFingerprintDaemon();
664 }
665 };
666 startClient(client, true);
667 }
Jim Miller40e46452016-12-16 18:38:53 -0800668 }
669
670 void startEnumerate(IBinder token, int userId,
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700671 IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
Jim Miller40e46452016-12-16 18:38:53 -0800672 IBiometricsFingerprint daemon = getFingerprintDaemon();
673 if (daemon == null) {
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700674 Slog.w(TAG, "startEnumerate: no fingerprint HAL!");
Jim Miller40e46452016-12-16 18:38:53 -0800675 return;
676 }
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700677 if (internal) {
678 List<Fingerprint> enrolledList = getEnrolledFingerprints(userId);
679 Context context = getContext();
680 InternalEnumerateClient client = new InternalEnumerateClient(context, mHalDeviceId,
681 token, receiver, userId, userId, restricted, context.getOpPackageName(),
682 enrolledList) {
683 @Override
684 public void notifyUserActivity() {
Jim Miller40e46452016-12-16 18:38:53 -0800685
Kevin Chynd1f1a0b2017-04-03 13:37:48 -0700686 }
687
688 @Override
689 public IBiometricsFingerprint getFingerprintDaemon() {
690 return FingerprintService.this.getFingerprintDaemon();
691 }
692 };
693 startClient(client, true);
694 }
695 else {
696 EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token,
697 receiver, userId, userId, restricted, token.toString()) {
698 @Override
699 public void notifyUserActivity() {
700 FingerprintService.this.userActivity();
701 }
702
703 @Override
704 public IBiometricsFingerprint getFingerprintDaemon() {
705 return FingerprintService.this.getFingerprintDaemon();
706 }
707 };
708 startClient(client, true);
709 }
Jim Millera75961472014-06-06 15:00:49 -0700710 }
711
Jim Miller599ef0e2015-06-15 20:39:44 -0700712 public List<Fingerprint> getEnrolledFingerprints(int userId) {
713 return mFingerprintUtils.getFingerprintsForUser(mContext, userId);
Jim Miller9f0753f2015-03-23 23:59:22 -0700714 }
715
Jim Miller599ef0e2015-06-15 20:39:44 -0700716 public boolean hasEnrolledFingerprints(int userId) {
Jim Miller1fd298b2016-02-25 16:42:28 -0800717 if (userId != UserHandle.getCallingUserId()) {
Clara Bayarri33fd3cf2016-02-19 16:54:49 +0000718 checkPermission(INTERACT_ACROSS_USERS);
719 }
Jim Miller599ef0e2015-06-15 20:39:44 -0700720 return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0;
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -0700721 }
722
Jim Millerf501b582015-06-03 16:36:31 -0700723 boolean hasPermission(String permission) {
724 return getContext().checkCallingOrSelfPermission(permission)
725 == PackageManager.PERMISSION_GRANTED;
726 }
727
Jim Millerba67aee2015-02-20 16:21:26 -0800728 void checkPermission(String permission) {
Jim Miller9f0753f2015-03-23 23:59:22 -0700729 getContext().enforceCallingOrSelfPermission(permission,
730 "Must have " + permission + " permission.");
Jim Millera75961472014-06-06 15:00:49 -0700731 }
732
Andres Morales494d6e92015-08-06 15:01:41 -0700733 int getEffectiveUserId(int userId) {
734 UserManager um = UserManager.get(mContext);
735 if (um != null) {
736 final long callingIdentity = Binder.clearCallingIdentity();
737 userId = um.getCredentialOwnerProfile(userId);
738 Binder.restoreCallingIdentity(callingIdentity);
739 } else {
740 Slog.e(TAG, "Unable to acquire UserManager");
741 }
742 return userId;
743 }
744
Jim Millercb7d9e92015-06-16 15:05:48 -0700745 boolean isCurrentUserOrProfile(int userId) {
746 UserManager um = UserManager.get(mContext);
Charles Heda88f0e2017-02-02 18:29:13 +0000747 if (um == null) {
748 Slog.e(TAG, "Unable to acquire UserManager");
749 return false;
Jim Millercb7d9e92015-06-16 15:05:48 -0700750 }
Charles Heda88f0e2017-02-02 18:29:13 +0000751
752 final long token = Binder.clearCallingIdentity();
753 try {
754 // Allow current user or profiles of the current user...
Charles He959ac8e2017-03-27 21:16:20 +0100755 for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) {
Charles Heda88f0e2017-02-02 18:29:13 +0000756 if (profileId == userId) {
757 return true;
758 }
759 }
Charles Heda88f0e2017-02-02 18:29:13 +0000760 } finally {
761 Binder.restoreCallingIdentity(token);
762 }
Charles He959ac8e2017-03-27 21:16:20 +0100763
764 return false;
Jim Millercb7d9e92015-06-16 15:05:48 -0700765 }
766
Jim Miller975f1452015-08-31 18:18:22 -0700767 private boolean isForegroundActivity(int uid, int pid) {
768 try {
769 List<RunningAppProcessInfo> procs =
Sudheer Shankadc589ac2016-11-10 15:30:17 -0800770 ActivityManager.getService().getRunningAppProcesses();
Jim Miller975f1452015-08-31 18:18:22 -0700771 int N = procs.size();
772 for (int i = 0; i < N; i++) {
773 RunningAppProcessInfo proc = procs.get(i);
774 if (proc.pid == pid && proc.uid == uid
Svet Ganov31217602018-05-18 19:59:25 -0700775 && proc.importance <= IMPORTANCE_FOREGROUND_SERVICE) {
Jim Miller975f1452015-08-31 18:18:22 -0700776 return true;
777 }
778 }
779 } catch (RemoteException e) {
780 Slog.w(TAG, "am.getRunningAppProcesses() failed");
781 }
782 return false;
783 }
784
785 /**
786 * @param opPackageName name of package for caller
Jim Miller37979c92016-08-05 18:54:58 -0700787 * @param requireForeground only allow this call while app is in the foreground
Jim Miller975f1452015-08-31 18:18:22 -0700788 * @return true if caller can use fingerprint API
789 */
Jim Miller37979c92016-08-05 18:54:58 -0700790 private boolean canUseFingerprint(String opPackageName, boolean requireForeground, int uid,
Kevin Chynf4023b52017-04-07 16:29:19 -0700791 int pid, int userId) {
Vishwath Mohancf87df12018-03-20 22:57:17 -0700792 if (getContext().checkCallingPermission(USE_FINGERPRINT)
793 != PackageManager.PERMISSION_GRANTED) {
794 checkPermission(USE_BIOMETRIC);
795 }
796
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000797 if (isKeyguard(opPackageName)) {
Jim Miller975f1452015-08-31 18:18:22 -0700798 return true; // Keyguard is always allowed
799 }
Kevin Chynf4023b52017-04-07 16:29:19 -0700800 if (!isCurrentUserOrProfile(userId)) {
Jim Miller975f1452015-08-31 18:18:22 -0700801 Slog.w(TAG,"Rejecting " + opPackageName + " ; not a current user or profile");
802 return false;
803 }
804 if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName)
805 != AppOpsManager.MODE_ALLOWED) {
Jim Miller1adb4a72015-09-14 18:58:08 -0700806 Slog.w(TAG, "Rejecting " + opPackageName + " ; permission denied");
Jim Miller975f1452015-08-31 18:18:22 -0700807 return false;
808 }
Jim Miller37979c92016-08-05 18:54:58 -0700809 if (requireForeground && !(isForegroundActivity(uid, pid) || currentClient(opPackageName))){
Jim Miller1adb4a72015-09-14 18:58:08 -0700810 Slog.w(TAG, "Rejecting " + opPackageName + " ; not in foreground");
Jim Miller975f1452015-08-31 18:18:22 -0700811 return false;
812 }
813 return true;
Svetoslav4af76a52015-04-29 15:29:46 -0700814 }
815
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000816 /**
Jim Miller37979c92016-08-05 18:54:58 -0700817 * @param opPackageName package of the caller
818 * @return true if this is the same client currently using fingerprint
819 */
820 private boolean currentClient(String opPackageName) {
821 return mCurrentClient != null && mCurrentClient.getOwnerString().equals(opPackageName);
822 }
823
824 /**
Clara Bayarrid1f722d2016-01-07 14:17:39 +0000825 * @param clientPackage
826 * @return true if this is keyguard package
827 */
828 private boolean isKeyguard(String clientPackage) {
829 return mKeyguardPackage.equals(clientPackage);
830 }
831
Jorim Jaggi3a464782015-08-28 16:59:13 -0700832 private void addLockoutResetMonitor(FingerprintServiceLockoutResetMonitor monitor) {
833 if (!mLockoutMonitors.contains(monitor)) {
834 mLockoutMonitors.add(monitor);
835 }
836 }
837
838 private void removeLockoutResetCallback(
839 FingerprintServiceLockoutResetMonitor monitor) {
840 mLockoutMonitors.remove(monitor);
841 }
842
843 private void notifyLockoutResetMonitors() {
844 for (int i = 0; i < mLockoutMonitors.size(); i++) {
845 mLockoutMonitors.get(i).sendLockoutReset();
846 }
847 }
848
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800849 private void notifyClientActiveCallbacks(boolean isActive) {
850 List<IFingerprintClientActiveCallback> callbacks = mClientActiveCallbacks;
851 for (int i = 0; i < callbacks.size(); i++) {
852 try {
853 callbacks.get(i).onClientActiveChanged(isActive);
854 } catch (RemoteException re) {
855 // If the remote is dead, stop notifying it
856 mClientActiveCallbacks.remove(callbacks.get(i));
Charles He959ac8e2017-03-27 21:16:20 +0100857 }
Phil Weaver27fcd9c2017-01-20 15:57:24 -0800858 }
859 }
860
Tony Makff715ac2016-04-19 20:44:12 +0100861 private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
Jim Millercb2ce6f2016-04-13 20:28:18 -0700862 IFingerprintServiceReceiver receiver, int flags, boolean restricted,
Vishwath Mohanecf00ce2018-04-05 10:28:24 -0700863 String opPackageName, Bundle bundle, IBiometricPromptReceiver dialogReceiver) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700864 updateActiveGroup(groupId, opPackageName);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700865
Jim Millercb2ce6f2016-04-13 20:28:18 -0700866 if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");
Jim Millerfe6439f2015-04-11 18:07:57 -0700867
Jim Millercb2ce6f2016-04-13 20:28:18 -0700868 AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token,
Kevin Chynaae4a152018-01-18 11:48:09 -0800869 receiver, mCurrentUserId, groupId, opId, restricted, opPackageName, bundle,
870 dialogReceiver, mStatusBarService) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700871 @Override
Kevin Chynd4f43c22018-03-12 17:33:13 -0700872 public void onStart() {
873 try {
874 mActivityManager.registerTaskStackListener(mTaskStackListener);
875 } catch (RemoteException e) {
876 Slog.e(TAG, "Could not register task stack listener", e);
877 }
878 }
879
880 @Override
881 public void onStop() {
882 try {
883 mActivityManager.unregisterTaskStackListener(mTaskStackListener);
884 } catch (RemoteException e) {
885 Slog.e(TAG, "Could not unregister task stack listener", e);
886 }
887 }
888
889 @Override
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700890 public int handleFailedAttempt() {
Kevin Chyn5457cba2017-08-30 15:28:28 -0700891 final int currentUser = ActivityManager.getCurrentUser();
892 mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1);
893 mTimedLockoutCleared.put(ActivityManager.getCurrentUser(), false);
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700894 final int lockoutMode = getLockoutMode();
895 if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) {
896 mPerformanceStats.permanentLockout++;
897 } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) {
Jim Millerbcc100a2016-07-06 14:16:49 -0700898 mPerformanceStats.lockout++;
899 }
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700900
901 // Failing multiple times will continue to push out the lockout time
902 if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
Kevin Chyn5457cba2017-08-30 15:28:28 -0700903 scheduleLockoutResetForUser(currentUser);
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700904 return lockoutMode;
Jim Miller16ef71f2015-05-21 17:02:21 -0700905 }
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700906 return AuthenticationClient.LOCKOUT_NONE;
Jim Millerfe6439f2015-04-11 18:07:57 -0700907 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700908
Jim Millercb2ce6f2016-04-13 20:28:18 -0700909 @Override
910 public void resetFailedAttempts() {
Kevin Chyn5457cba2017-08-30 15:28:28 -0700911 FingerprintService.this.resetFailedAttemptsForUser(true /* clearAttemptCounter */,
912 ActivityManager.getCurrentUser());
Jim Millercb2ce6f2016-04-13 20:28:18 -0700913 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700914
Jim Millercb2ce6f2016-04-13 20:28:18 -0700915 @Override
916 public void notifyUserActivity() {
917 FingerprintService.this.userActivity();
Jim Millerfe6439f2015-04-11 18:07:57 -0700918 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700919
Jim Millercb2ce6f2016-04-13 20:28:18 -0700920 @Override
Jim Miller40e46452016-12-16 18:38:53 -0800921 public IBiometricsFingerprint getFingerprintDaemon() {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700922 return FingerprintService.this.getFingerprintDaemon();
Jim Millerfe6439f2015-04-11 18:07:57 -0700923 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700924 };
Jim Millerfe6439f2015-04-11 18:07:57 -0700925
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700926 int lockoutMode = getLockoutMode();
927 if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
928 Slog.v(TAG, "In lockout mode(" + lockoutMode +
929 ") ; disallowing authentication");
930 int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?
931 FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
932 FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
933 if (!client.onError(errorCode, 0 /* vendorCode */)) {
934 Slog.w(TAG, "Cannot send permanent lockout message to client");
Jim Millerfe6439f2015-04-11 18:07:57 -0700935 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700936 return;
Jim Millerfe6439f2015-04-11 18:07:57 -0700937 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700938 startClient(client, true /* initiatedByClient */);
939 }
Jim Millerfe6439f2015-04-11 18:07:57 -0700940
Jim Millerc12eca82016-04-28 15:12:53 -0700941 private void startEnrollment(IBinder token, byte [] cryptoToken, int userId,
Jim Millercb2ce6f2016-04-13 20:28:18 -0700942 IFingerprintServiceReceiver receiver, int flags, boolean restricted,
943 String opPackageName) {
Jim Millerc12eca82016-04-28 15:12:53 -0700944 updateActiveGroup(userId, opPackageName);
945
946 final int groupId = userId; // default group for fingerprint enrollment
Jim Millerfe6439f2015-04-11 18:07:57 -0700947
Jim Millercb2ce6f2016-04-13 20:28:18 -0700948 EnrollClient client = new EnrollClient(getContext(), mHalDeviceId, token, receiver,
Jim Millerc12eca82016-04-28 15:12:53 -0700949 userId, groupId, cryptoToken, restricted, opPackageName) {
Jim Millerfe6439f2015-04-11 18:07:57 -0700950
Jim Millercb2ce6f2016-04-13 20:28:18 -0700951 @Override
Jim Miller40e46452016-12-16 18:38:53 -0800952 public IBiometricsFingerprint getFingerprintDaemon() {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700953 return FingerprintService.this.getFingerprintDaemon();
Jim Millerfe6439f2015-04-11 18:07:57 -0700954 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700955
956 @Override
957 public void notifyUserActivity() {
958 FingerprintService.this.userActivity();
959 }
960 };
961 startClient(client, true /* initiatedByClient */);
962 }
963
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700964 // attempt counter should only be cleared when Keyguard goes away or when
965 // a fingerprint is successfully authenticated
Kevin Chyn5457cba2017-08-30 15:28:28 -0700966 protected void resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId) {
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700967 if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) {
968 Slog.v(TAG, "Reset fingerprint lockout, clearAttemptCounter=" + clearAttemptCounter);
Jim Millerce7eb6d2015-04-03 19:29:13 -0700969 }
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700970 if (clearAttemptCounter) {
Kevin Chyn5457cba2017-08-30 15:28:28 -0700971 mFailedAttempts.put(userId, 0);
Kevin Chyndf9d33e2017-05-03 21:40:12 -0700972 }
Kevin Chyn5457cba2017-08-30 15:28:28 -0700973 mTimedLockoutCleared.put(userId, true);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700974 // If we're asked to reset failed attempts externally (i.e. from Keyguard),
975 // the alarm might still be pending; remove it.
Kevin Chyn5457cba2017-08-30 15:28:28 -0700976 cancelLockoutResetForUser(userId);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700977 notifyLockoutResetMonitors();
Jim Millerce7eb6d2015-04-03 19:29:13 -0700978 }
979
Kevin Chyn38835632018-02-14 12:46:45 -0800980 private class FingerprintServiceLockoutResetMonitor implements IBinder.DeathRecipient {
Jorim Jaggi3a464782015-08-28 16:59:13 -0700981
Jorim Jaggi57e2f4d2016-11-24 14:38:18 +0100982 private static final long WAKELOCK_TIMEOUT_MS = 2000;
Jorim Jaggi3a464782015-08-28 16:59:13 -0700983 private final IFingerprintServiceLockoutResetCallback mCallback;
Jorim Jaggi57e2f4d2016-11-24 14:38:18 +0100984 private final WakeLock mWakeLock;
Jorim Jaggi3a464782015-08-28 16:59:13 -0700985
986 public FingerprintServiceLockoutResetMonitor(
987 IFingerprintServiceLockoutResetCallback callback) {
988 mCallback = callback;
Jorim Jaggi57e2f4d2016-11-24 14:38:18 +0100989 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
990 "lockout reset callback");
Kevin Chyn38835632018-02-14 12:46:45 -0800991 try {
992 mCallback.asBinder().linkToDeath(FingerprintServiceLockoutResetMonitor.this, 0);
993 } catch (RemoteException e) {
994 Slog.w(TAG, "caught remote exception in linkToDeath", e);
995 }
Jorim Jaggi3a464782015-08-28 16:59:13 -0700996 }
997
998 public void sendLockoutReset() {
999 if (mCallback != null) {
1000 try {
Jorim Jaggi57e2f4d2016-11-24 14:38:18 +01001001 mWakeLock.acquire(WAKELOCK_TIMEOUT_MS);
1002 mCallback.onLockoutReset(mHalDeviceId, new IRemoteCallback.Stub() {
1003
1004 @Override
1005 public void sendResult(Bundle data) throws RemoteException {
Kevin Chyn71d04212018-02-28 18:12:03 -08001006 releaseWakelock();
Jorim Jaggi57e2f4d2016-11-24 14:38:18 +01001007 }
1008 });
Jorim Jaggi3a464782015-08-28 16:59:13 -07001009 } catch (DeadObjectException e) {
1010 Slog.w(TAG, "Death object while invoking onLockoutReset: ", e);
1011 mHandler.post(mRemoveCallbackRunnable);
1012 } catch (RemoteException e) {
1013 Slog.w(TAG, "Failed to invoke onLockoutReset: ", e);
Kevin Chyn71d04212018-02-28 18:12:03 -08001014 releaseWakelock();
Jorim Jaggi3a464782015-08-28 16:59:13 -07001015 }
1016 }
1017 }
1018
1019 private final Runnable mRemoveCallbackRunnable = new Runnable() {
1020 @Override
1021 public void run() {
Kevin Chyn71d04212018-02-28 18:12:03 -08001022 releaseWakelock();
Jorim Jaggi3a464782015-08-28 16:59:13 -07001023 removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this);
1024 }
1025 };
Kevin Chyn38835632018-02-14 12:46:45 -08001026
1027 @Override
1028 public void binderDied() {
1029 Slog.e(TAG, "Lockout reset callback binder died");
1030 mHandler.post(mRemoveCallbackRunnable);
1031 }
Kevin Chyn71d04212018-02-28 18:12:03 -08001032
1033 private void releaseWakelock() {
1034 if (mWakeLock.isHeld()) {
1035 mWakeLock.release();
1036 }
1037 }
Jorim Jaggi3a464782015-08-28 16:59:13 -07001038 }
1039
Jim Miller40e46452016-12-16 18:38:53 -08001040 private IBiometricsFingerprintClientCallback mDaemonCallback =
1041 new IBiometricsFingerprintClientCallback.Stub() {
Jim Millerbe675422015-05-11 20:45:25 -07001042
Jim Miller9f0753f2015-03-23 23:59:22 -07001043 @Override
Jim Miller8b3c25a2015-08-28 17:29:49 -07001044 public void onEnrollResult(final long deviceId, final int fingerId, final int groupId,
1045 final int remaining) {
1046 mHandler.post(new Runnable() {
1047 @Override
1048 public void run() {
1049 handleEnrollResult(deviceId, fingerId, groupId, remaining);
1050 }
1051 });
Jim Millerbe675422015-05-11 20:45:25 -07001052 }
1053
1054 @Override
Jim Miller40e46452016-12-16 18:38:53 -08001055 public void onAcquired(final long deviceId, final int acquiredInfo, final int vendorCode) {
Jim Miller8b3c25a2015-08-28 17:29:49 -07001056 mHandler.post(new Runnable() {
1057 @Override
1058 public void run() {
Jim Miller40e46452016-12-16 18:38:53 -08001059 handleAcquired(deviceId, acquiredInfo, vendorCode);
Jim Miller8b3c25a2015-08-28 17:29:49 -07001060 }
1061 });
Jim Millerbe675422015-05-11 20:45:25 -07001062 }
1063
1064 @Override
Jim Millera8eaeeb2017-01-24 14:47:04 -08001065 public void onAuthenticated(final long deviceId, final int fingerId, final int groupId,
1066 ArrayList<Byte> token) {
Jim Miller8b3c25a2015-08-28 17:29:49 -07001067 mHandler.post(new Runnable() {
1068 @Override
1069 public void run() {
Jim Millera8eaeeb2017-01-24 14:47:04 -08001070 handleAuthenticated(deviceId, fingerId, groupId, token);
Jim Miller8b3c25a2015-08-28 17:29:49 -07001071 }
1072 });
Jim Millerbe675422015-05-11 20:45:25 -07001073 }
1074
1075 @Override
Jim Miller40e46452016-12-16 18:38:53 -08001076 public void onError(final long deviceId, final int error, final int vendorCode) {
Jim Miller8b3c25a2015-08-28 17:29:49 -07001077 mHandler.post(new Runnable() {
1078 @Override
1079 public void run() {
Jim Miller40e46452016-12-16 18:38:53 -08001080 handleError(deviceId, error, vendorCode);
Jim Miller8b3c25a2015-08-28 17:29:49 -07001081 }
1082 });
Jim Millerbe675422015-05-11 20:45:25 -07001083 }
1084
1085 @Override
Jim Miller40e46452016-12-16 18:38:53 -08001086 public void onRemoved(final long deviceId, final int fingerId, final int groupId, final int remaining) {
Jim Miller8b3c25a2015-08-28 17:29:49 -07001087 mHandler.post(new Runnable() {
1088 @Override
1089 public void run() {
Jim Miller40e46452016-12-16 18:38:53 -08001090 handleRemoved(deviceId, fingerId, groupId, remaining);
Jim Miller8b3c25a2015-08-28 17:29:49 -07001091 }
1092 });
Jim Millerbe675422015-05-11 20:45:25 -07001093 }
1094
1095 @Override
Jim Miller40e46452016-12-16 18:38:53 -08001096 public void onEnumerate(final long deviceId, final int fingerId, final int groupId,
1097 final int remaining) {
Jim Miller8b3c25a2015-08-28 17:29:49 -07001098 mHandler.post(new Runnable() {
1099 @Override
1100 public void run() {
Jim Miller40e46452016-12-16 18:38:53 -08001101 handleEnumerate(deviceId, fingerId, groupId, remaining);
Jim Miller8b3c25a2015-08-28 17:29:49 -07001102 }
1103 });
Jim Millerbe675422015-05-11 20:45:25 -07001104 }
Jim Millerbe675422015-05-11 20:45:25 -07001105 };
1106
1107 private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
1108 @Override // Binder call
Jim Millerce7eb6d2015-04-03 19:29:13 -07001109 public long preEnroll(IBinder token) {
Jim Millerba67aee2015-02-20 16:21:26 -08001110 checkPermission(MANAGE_FINGERPRINT);
Jim Millerce7eb6d2015-04-03 19:29:13 -07001111 return startPreEnroll(token);
Jim Millera75961472014-06-06 15:00:49 -07001112 }
1113
Jim Millerbe675422015-05-11 20:45:25 -07001114 @Override // Binder call
Sasha Levitskiye0943cf2015-07-08 13:22:20 -07001115 public int postEnroll(IBinder token) {
1116 checkPermission(MANAGE_FINGERPRINT);
1117 return startPostEnroll(token);
1118 }
1119
1120 @Override // Binder call
Jim Millerc12eca82016-04-28 15:12:53 -07001121 public void enroll(final IBinder token, final byte[] cryptoToken, final int userId,
Jim Millercb2ce6f2016-04-13 20:28:18 -07001122 final IFingerprintServiceReceiver receiver, final int flags,
1123 final String opPackageName) {
Jim Millerce7eb6d2015-04-03 19:29:13 -07001124 checkPermission(MANAGE_FINGERPRINT);
Kevin Chynaae4a152018-01-18 11:48:09 -08001125 final int limit = mContext.getResources().getInteger(
Jim Miller599ef0e2015-06-15 20:39:44 -07001126 com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
Jim Millerc12eca82016-04-28 15:12:53 -07001127
1128 final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size();
Jim Miller599ef0e2015-06-15 20:39:44 -07001129 if (enrolled >= limit) {
1130 Slog.w(TAG, "Too many fingerprints registered");
1131 return;
1132 }
Jim Millerf501b582015-06-03 16:36:31 -07001133
Andres Morales494d6e92015-08-06 15:01:41 -07001134 // Group ID is arbitrarily set to parent profile user ID. It just represents
1135 // the default fingerprints for the user.
Jim Millerc12eca82016-04-28 15:12:53 -07001136 if (!isCurrentUserOrProfile(userId)) {
Clara Bayarri35fd93812016-02-29 17:49:18 -08001137 return;
1138 }
Andres Morales494d6e92015-08-06 15:01:41 -07001139
Jim Millerf501b582015-06-03 16:36:31 -07001140 final boolean restricted = isRestricted();
Jim Millerce7eb6d2015-04-03 19:29:13 -07001141 mHandler.post(new Runnable() {
1142 @Override
1143 public void run() {
Jim Millerc12eca82016-04-28 15:12:53 -07001144 startEnrollment(token, cryptoToken, userId, receiver, flags,
Jim Millercb2ce6f2016-04-13 20:28:18 -07001145 restricted, opPackageName);
Jim Millerce7eb6d2015-04-03 19:29:13 -07001146 }
1147 });
1148 }
1149
Jim Millerf501b582015-06-03 16:36:31 -07001150 private boolean isRestricted() {
1151 // Only give privileged apps (like Settings) access to fingerprint info
1152 final boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
1153 return restricted;
1154 }
1155
Jim Millerbe675422015-05-11 20:45:25 -07001156 @Override // Binder call
Jim Millerce7eb6d2015-04-03 19:29:13 -07001157 public void cancelEnrollment(final IBinder token) {
1158 checkPermission(MANAGE_FINGERPRINT);
1159 mHandler.post(new Runnable() {
1160 @Override
1161 public void run() {
Jim Millercb2ce6f2016-04-13 20:28:18 -07001162 ClientMonitor client = mCurrentClient;
1163 if (client instanceof EnrollClient && client.getToken() == token) {
1164 client.stop(client.getToken() == token);
1165 }
Jim Millerce7eb6d2015-04-03 19:29:13 -07001166 }
1167 });
1168 }
1169
Jim Millerbe675422015-05-11 20:45:25 -07001170 @Override // Binder call
Jim Millerce7eb6d2015-04-03 19:29:13 -07001171 public void authenticate(final IBinder token, final long opId, final int groupId,
Jim Millerdca15d22015-06-16 20:55:13 -07001172 final IFingerprintServiceReceiver receiver, final int flags,
Kevin Chynaae4a152018-01-18 11:48:09 -08001173 final String opPackageName, final Bundle bundle,
Vishwath Mohanecf00ce2018-04-05 10:28:24 -07001174 final IBiometricPromptReceiver dialogReceiver) {
Tony Makff715ac2016-04-19 20:44:12 +01001175 final int callingUid = Binder.getCallingUid();
Kevin Chyn33fdf112017-08-09 11:45:21 -07001176 final int callingPid = Binder.getCallingPid();
Tony Makff715ac2016-04-19 20:44:12 +01001177 final int callingUserId = UserHandle.getCallingUserId();
Jim Millerf501b582015-06-03 16:36:31 -07001178 final boolean restricted = isRestricted();
Kevin Chyn33fdf112017-08-09 11:45:21 -07001179
1180 if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
1181 callingUserId)) {
1182 if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
1183 return;
1184 }
1185
Jim Millerce7eb6d2015-04-03 19:29:13 -07001186 mHandler.post(new Runnable() {
1187 @Override
1188 public void run() {
Jim Millerbcc100a2016-07-06 14:16:49 -07001189 MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
1190
1191 // Get performance stats object for this user.
1192 HashMap<Integer, PerformanceStats> pmap
1193 = (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap;
1194 PerformanceStats stats = pmap.get(mCurrentUserId);
1195 if (stats == null) {
1196 stats = new PerformanceStats();
1197 pmap.put(mCurrentUserId, stats);
1198 }
1199 mPerformanceStats = stats;
1200
Tony Makff715ac2016-04-19 20:44:12 +01001201 startAuthentication(token, opId, callingUserId, groupId, receiver,
Kevin Chynaae4a152018-01-18 11:48:09 -08001202 flags, restricted, opPackageName, bundle, dialogReceiver);
Jim Millerce7eb6d2015-04-03 19:29:13 -07001203 }
1204 });
1205 }
1206
Jim Millerbe675422015-05-11 20:45:25 -07001207 @Override // Binder call
Jim Millercb2ce6f2016-04-13 20:28:18 -07001208 public void cancelAuthentication(final IBinder token, final String opPackageName) {
Kevin Chyn33fdf112017-08-09 11:45:21 -07001209 final int callingUid = Binder.getCallingUid();
1210 final int callingPid = Binder.getCallingPid();
Kevin Chynf4023b52017-04-07 16:29:19 -07001211 final int callingUserId = UserHandle.getCallingUserId();
Kevin Chyn33fdf112017-08-09 11:45:21 -07001212
1213 if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
1214 callingUserId)) {
1215 if (DEBUG) Slog.v(TAG, "cancelAuthentication(): reject " + opPackageName);
1216 return;
1217 }
1218
Jim Millerce7eb6d2015-04-03 19:29:13 -07001219 mHandler.post(new Runnable() {
1220 @Override
1221 public void run() {
Kevin Chyn33fdf112017-08-09 11:45:21 -07001222 ClientMonitor client = mCurrentClient;
1223 if (client instanceof AuthenticationClient) {
1224 if (client.getToken() == token) {
1225 if (DEBUG) Slog.v(TAG, "stop client " + client.getOwnerString());
1226 client.stop(client.getToken() == token);
1227 } else {
1228 if (DEBUG) Slog.v(TAG, "can't stop client "
1229 + client.getOwnerString() + " since tokens don't match");
Jim Millercb2ce6f2016-04-13 20:28:18 -07001230 }
Kevin Chyn33fdf112017-08-09 11:45:21 -07001231 } else if (client != null) {
1232 if (DEBUG) Slog.v(TAG, "can't cancel non-authenticating client "
1233 + client.getOwnerString());
Jim Millercb2ce6f2016-04-13 20:28:18 -07001234 }
Jim Millerce7eb6d2015-04-03 19:29:13 -07001235 }
1236 });
Jim Millerba67aee2015-02-20 16:21:26 -08001237 }
Jim Miller99d60192015-03-11 17:41:58 -07001238
Jim Millerbe675422015-05-11 20:45:25 -07001239 @Override // Binder call
Clara Bayarrid1f722d2016-01-07 14:17:39 +00001240 public void setActiveUser(final int userId) {
1241 checkPermission(MANAGE_FINGERPRINT);
1242 mHandler.post(new Runnable() {
1243 @Override
1244 public void run() {
1245 updateActiveGroup(userId, null);
1246 }
1247 });
1248 }
1249
1250 @Override // Binder call
Jim Millerce7eb6d2015-04-03 19:29:13 -07001251 public void remove(final IBinder token, final int fingerId, final int groupId,
Jim Miller8f2aca02016-04-20 13:34:11 -07001252 final int userId, final IFingerprintServiceReceiver receiver) {
Jim Miller9f0753f2015-03-23 23:59:22 -07001253 checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
Jim Millerf501b582015-06-03 16:36:31 -07001254 final boolean restricted = isRestricted();
Jim Millerce7eb6d2015-04-03 19:29:13 -07001255 mHandler.post(new Runnable() {
1256 @Override
1257 public void run() {
Kevin Chynd1f1a0b2017-04-03 13:37:48 -07001258 startRemove(token, fingerId, groupId, userId, receiver,
1259 restricted, false /* internal */);
Jim Millerce7eb6d2015-04-03 19:29:13 -07001260 }
1261 });
Jim Miller9f0753f2015-03-23 23:59:22 -07001262 }
1263
Kevin Chynd1f1a0b2017-04-03 13:37:48 -07001264 @Override // Binder call
Jim Miller40e46452016-12-16 18:38:53 -08001265 public void enumerate(final IBinder token, final int userId,
1266 final IFingerprintServiceReceiver receiver) {
1267 checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
1268 final boolean restricted = isRestricted();
1269 mHandler.post(new Runnable() {
1270 @Override
1271 public void run() {
Kevin Chynd1f1a0b2017-04-03 13:37:48 -07001272 startEnumerate(token, userId, receiver, restricted, false /* internal */);
Jim Miller40e46452016-12-16 18:38:53 -08001273 }
1274 });
Jim Miller40e46452016-12-16 18:38:53 -08001275 }
1276
Jim Millerbe675422015-05-11 20:45:25 -07001277 @Override // Binder call
Svetoslav4af76a52015-04-29 15:29:46 -07001278 public boolean isHardwareDetected(long deviceId, String opPackageName) {
Jim Millercb2ce6f2016-04-13 20:28:18 -07001279 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
Kevin Chynf4023b52017-04-07 16:29:19 -07001280 Binder.getCallingUid(), Binder.getCallingPid(),
1281 UserHandle.getCallingUserId())) {
Svetoslav4af76a52015-04-29 15:29:46 -07001282 return false;
1283 }
Charles He959ac8e2017-03-27 21:16:20 +01001284
1285 final long token = Binder.clearCallingIdentity();
1286 try {
1287 IBiometricsFingerprint daemon = getFingerprintDaemon();
1288 return daemon != null && mHalDeviceId != 0;
1289 } finally {
1290 Binder.restoreCallingIdentity(token);
1291 }
Jim Miller9f0753f2015-03-23 23:59:22 -07001292 }
1293
Jim Millerbe675422015-05-11 20:45:25 -07001294 @Override // Binder call
Jim Millerce7eb6d2015-04-03 19:29:13 -07001295 public void rename(final int fingerId, final int groupId, final String name) {
Jim Miller99d60192015-03-11 17:41:58 -07001296 checkPermission(MANAGE_FINGERPRINT);
Clara Bayarri35fd93812016-02-29 17:49:18 -08001297 if (!isCurrentUserOrProfile(groupId)) {
1298 return;
1299 }
Jim Millerce7eb6d2015-04-03 19:29:13 -07001300 mHandler.post(new Runnable() {
1301 @Override
1302 public void run() {
Andres Morales494d6e92015-08-06 15:01:41 -07001303 mFingerprintUtils.renameFingerprintForUser(mContext, fingerId,
Clara Bayarri35fd93812016-02-29 17:49:18 -08001304 groupId, name);
Jim Millerce7eb6d2015-04-03 19:29:13 -07001305 }
1306 });
Jim Miller99d60192015-03-11 17:41:58 -07001307 }
Jim Miller9f0753f2015-03-23 23:59:22 -07001308
Jim Millerbe675422015-05-11 20:45:25 -07001309 @Override // Binder call
Jim Miller599ef0e2015-06-15 20:39:44 -07001310 public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) {
Jim Millercb2ce6f2016-04-13 20:28:18 -07001311 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
Kevin Chynf4023b52017-04-07 16:29:19 -07001312 Binder.getCallingUid(), Binder.getCallingPid(),
1313 UserHandle.getCallingUserId())) {
Svetoslav4af76a52015-04-29 15:29:46 -07001314 return Collections.emptyList();
1315 }
Andres Morales494d6e92015-08-06 15:01:41 -07001316
Clara Bayarri35fd93812016-02-29 17:49:18 -08001317 return FingerprintService.this.getEnrolledFingerprints(userId);
Jim Miller9f0753f2015-03-23 23:59:22 -07001318 }
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -07001319
Jim Millerbe675422015-05-11 20:45:25 -07001320 @Override // Binder call
Andres Morales494d6e92015-08-06 15:01:41 -07001321 public boolean hasEnrolledFingerprints(int userId, String opPackageName) {
Jim Millercb2ce6f2016-04-13 20:28:18 -07001322 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
Kevin Chynf4023b52017-04-07 16:29:19 -07001323 Binder.getCallingUid(), Binder.getCallingPid(),
1324 UserHandle.getCallingUserId())) {
Svetoslav4af76a52015-04-29 15:29:46 -07001325 return false;
1326 }
Andres Morales494d6e92015-08-06 15:01:41 -07001327
Clara Bayarri35fd93812016-02-29 17:49:18 -08001328 return FingerprintService.this.hasEnrolledFingerprints(userId);
Jorim Jaggi2aad7ee2015-04-14 15:25:06 -07001329 }
Andres Morales4d41a202015-04-16 14:12:38 -07001330
Jim Millerbe675422015-05-11 20:45:25 -07001331 @Override // Binder call
Svetoslav4af76a52015-04-29 15:29:46 -07001332 public long getAuthenticatorId(String opPackageName) {
Alex Klyubina99b8b52015-06-11 13:27:34 -07001333 // In this method, we're not checking whether the caller is permitted to use fingerprint
1334 // API because current authenticator ID is leaked (in a more contrived way) via Android
1335 // Keystore (android.security.keystore package): the user of that API can create a key
1336 // which requires fingerprint authentication for its use, and then query the key's
1337 // characteristics (hidden API) which returns, among other things, fingerprint
1338 // authenticator ID which was active at key creation time.
1339 //
1340 // Reason: The part of Android Keystore which runs inside an app's process invokes this
1341 // method in certain cases. Those cases are not always where the developer demonstrates
1342 // explicit intent to use fingerprint functionality. Thus, to avoiding throwing an
1343 // unexpected SecurityException this method does not check whether its caller is
1344 // permitted to use fingerprint API.
1345 //
1346 // The permission check should be restored once Android Keystore no longer invokes this
1347 // method from inside app processes.
1348
Jim Millercb2ce6f2016-04-13 20:28:18 -07001349 return FingerprintService.this.getAuthenticatorId(opPackageName);
Andres Morales4d41a202015-04-16 14:12:38 -07001350 }
Chris Wrenc510ad52015-08-14 15:43:15 -04001351
1352 @Override // Binder call
1353 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Jeff Sharkeyfe9a53b2017-03-31 14:08:23 -06001354 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
Chris Wrenc510ad52015-08-14 15:43:15 -04001355
1356 final long ident = Binder.clearCallingIdentity();
1357 try {
Joe Onorato1754d742016-11-21 17:51:35 -08001358 if (args.length > 0 && "--proto".equals(args[0])) {
1359 dumpProto(fd);
1360 } else {
1361 dumpInternal(pw);
1362 }
Chris Wrenc510ad52015-08-14 15:43:15 -04001363 } finally {
1364 Binder.restoreCallingIdentity(ident);
1365 }
1366 }
Charles He959ac8e2017-03-27 21:16:20 +01001367
Jim Millere0507bb2015-08-12 20:30:34 -07001368 @Override // Binder call
1369 public void resetTimeout(byte [] token) {
1370 checkPermission(RESET_FINGERPRINT_LOCKOUT);
1371 // TODO: confirm security token when we move timeout management into the HAL layer.
Kevin Chyn5457cba2017-08-30 15:28:28 -07001372 mHandler.post(mResetFailedAttemptsForCurrentUserRunnable);
Jorim Jaggi3a464782015-08-28 16:59:13 -07001373 }
1374
1375 @Override
1376 public void addLockoutResetCallback(final IFingerprintServiceLockoutResetCallback callback)
1377 throws RemoteException {
1378 mHandler.post(new Runnable() {
1379 @Override
1380 public void run() {
1381 addLockoutResetMonitor(
1382 new FingerprintServiceLockoutResetMonitor(callback));
1383 }
1384 });
Jim Millere0507bb2015-08-12 20:30:34 -07001385 }
Phil Weaver27fcd9c2017-01-20 15:57:24 -08001386
1387 @Override
1388 public boolean isClientActive() {
1389 checkPermission(MANAGE_FINGERPRINT);
1390 synchronized(FingerprintService.this) {
1391 return (mCurrentClient != null) || (mPendingClient != null);
1392 }
1393 }
1394
1395 @Override
1396 public void addClientActiveCallback(IFingerprintClientActiveCallback callback) {
1397 checkPermission(MANAGE_FINGERPRINT);
1398 mClientActiveCallbacks.add(callback);
1399 }
1400
1401 @Override
1402 public void removeClientActiveCallback(IFingerprintClientActiveCallback callback) {
1403 checkPermission(MANAGE_FINGERPRINT);
1404 mClientActiveCallbacks.remove(callback);
1405 }
Chris Wrenc510ad52015-08-14 15:43:15 -04001406 }
1407
1408 private void dumpInternal(PrintWriter pw) {
1409 JSONObject dump = new JSONObject();
1410 try {
1411 dump.put("service", "Fingerprint Manager");
1412
1413 JSONArray sets = new JSONArray();
1414 for (UserInfo user : UserManager.get(getContext()).getUsers()) {
1415 final int userId = user.getUserHandle().getIdentifier();
1416 final int N = mFingerprintUtils.getFingerprintsForUser(mContext, userId).size();
Jim Millerbcc100a2016-07-06 14:16:49 -07001417 PerformanceStats stats = mPerformanceMap.get(userId);
1418 PerformanceStats cryptoStats = mCryptoPerformanceMap.get(userId);
Chris Wrenc510ad52015-08-14 15:43:15 -04001419 JSONObject set = new JSONObject();
1420 set.put("id", userId);
1421 set.put("count", N);
Jim Millerbcc100a2016-07-06 14:16:49 -07001422 set.put("accept", (stats != null) ? stats.accept : 0);
1423 set.put("reject", (stats != null) ? stats.reject : 0);
1424 set.put("acquire", (stats != null) ? stats.acquire : 0);
1425 set.put("lockout", (stats != null) ? stats.lockout : 0);
Kevin Chyndf9d33e2017-05-03 21:40:12 -07001426 set.put("permanentLockout", (stats != null) ? stats.permanentLockout : 0);
Jim Millerbcc100a2016-07-06 14:16:49 -07001427 // cryptoStats measures statistics about secure fingerprint transactions
1428 // (e.g. to unlock password storage, make secure purchases, etc.)
1429 set.put("acceptCrypto", (cryptoStats != null) ? cryptoStats.accept : 0);
1430 set.put("rejectCrypto", (cryptoStats != null) ? cryptoStats.reject : 0);
1431 set.put("acquireCrypto", (cryptoStats != null) ? cryptoStats.acquire : 0);
1432 set.put("lockoutCrypto", (cryptoStats != null) ? cryptoStats.lockout : 0);
Kweku Adamscd7c35c2017-09-14 16:45:06 -07001433 set.put("permanentLockoutCrypto",
1434 (cryptoStats != null) ? cryptoStats.permanentLockout : 0);
Chris Wrenc510ad52015-08-14 15:43:15 -04001435 sets.put(set);
1436 }
1437
1438 dump.put("prints", sets);
1439 } catch (JSONException e) {
1440 Slog.e(TAG, "dump formatting failure", e);
1441 }
1442 pw.println(dump);
Jim Millera75961472014-06-06 15:00:49 -07001443 }
1444
Joe Onorato1754d742016-11-21 17:51:35 -08001445 private void dumpProto(FileDescriptor fd) {
1446 final ProtoOutputStream proto = new ProtoOutputStream(fd);
1447 for (UserInfo user : UserManager.get(getContext()).getUsers()) {
1448 final int userId = user.getUserHandle().getIdentifier();
1449
1450 final long userToken = proto.start(FingerprintServiceDumpProto.USERS);
1451
1452 proto.write(FingerprintUserStatsProto.USER_ID, userId);
1453 proto.write(FingerprintUserStatsProto.NUM_FINGERPRINTS,
1454 mFingerprintUtils.getFingerprintsForUser(mContext, userId).size());
1455
1456 // Normal fingerprint authentications (e.g. lockscreen)
1457 final PerformanceStats normal = mPerformanceMap.get(userId);
1458 if (normal != null) {
1459 final long countsToken = proto.start(FingerprintUserStatsProto.NORMAL);
Kweku Adamsfd257d62017-10-25 17:53:50 -07001460 proto.write(PerformanceStatsProto.ACCEPT, normal.accept);
1461 proto.write(PerformanceStatsProto.REJECT, normal.reject);
1462 proto.write(PerformanceStatsProto.ACQUIRE, normal.acquire);
1463 proto.write(PerformanceStatsProto.LOCKOUT, normal.lockout);
1464 proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, normal.permanentLockout);
Joe Onorato1754d742016-11-21 17:51:35 -08001465 proto.end(countsToken);
1466 }
1467
1468 // Statistics about secure fingerprint transactions (e.g. to unlock password
1469 // storage, make secure purchases, etc.)
Kevin Chyn9310f5c2017-02-21 17:22:54 -08001470 final PerformanceStats crypto = mCryptoPerformanceMap.get(userId);
Joe Onorato1754d742016-11-21 17:51:35 -08001471 if (crypto != null) {
1472 final long countsToken = proto.start(FingerprintUserStatsProto.CRYPTO);
Kweku Adamsfd257d62017-10-25 17:53:50 -07001473 proto.write(PerformanceStatsProto.ACCEPT, crypto.accept);
1474 proto.write(PerformanceStatsProto.REJECT, crypto.reject);
1475 proto.write(PerformanceStatsProto.ACQUIRE, crypto.acquire);
1476 proto.write(PerformanceStatsProto.LOCKOUT, crypto.lockout);
1477 proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, crypto.permanentLockout);
Joe Onorato1754d742016-11-21 17:51:35 -08001478 proto.end(countsToken);
1479 }
1480
1481 proto.end(userToken);
1482 }
1483 proto.flush();
Kevin Chyn89a55cb2018-03-29 14:52:59 -07001484 mPerformanceMap.clear();
1485 mCryptoPerformanceMap.clear();
Joe Onorato1754d742016-11-21 17:51:35 -08001486 }
1487
Jim Millera75961472014-06-06 15:00:49 -07001488 @Override
1489 public void onStart() {
Jim Miller9f0753f2015-03-23 23:59:22 -07001490 publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
Fyodor Kupolove29a5a12016-12-16 16:14:17 -08001491 SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart");
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -07001492 listenForUserSwitches();
Jim Millera75961472014-06-06 15:00:49 -07001493 }
1494
Clara Bayarrid1f722d2016-01-07 14:17:39 +00001495 private void updateActiveGroup(int userId, String clientPackage) {
Jim Miller40e46452016-12-16 18:38:53 -08001496 IBiometricsFingerprint daemon = getFingerprintDaemon();
Jim Millerbcc100a2016-07-06 14:16:49 -07001497
Jim Millerbe675422015-05-11 20:45:25 -07001498 if (daemon != null) {
1499 try {
Clara Bayarrid1f722d2016-01-07 14:17:39 +00001500 userId = getUserOrWorkProfileId(clientPackage, userId);
1501 if (userId != mCurrentUserId) {
Yifan Hong56702472018-05-17 18:51:05 -07001502 int firstSdkInt = Build.VERSION.FIRST_SDK_INT;
Yifan Hong45646122018-05-21 12:38:10 -07001503 if (firstSdkInt < Build.VERSION_CODES.BASE) {
1504 Slog.e(TAG, "First SDK version " + firstSdkInt + " is invalid; must be " +
1505 "at least VERSION_CODES.BASE");
1506 }
Andreas Huber7fe20532018-01-22 11:26:44 -08001507 File baseDir;
Yifan Hong56702472018-05-17 18:51:05 -07001508 if (firstSdkInt <= Build.VERSION_CODES.O_MR1) {
Andreas Huber7fe20532018-01-22 11:26:44 -08001509 baseDir = Environment.getUserSystemDirectory(userId);
1510 } else {
1511 baseDir = Environment.getDataVendorDeDirectory(userId);
1512 }
1513
1514 File fpDir = new File(baseDir, FP_DATA_DIR);
Clara Bayarrid1f722d2016-01-07 14:17:39 +00001515 if (!fpDir.exists()) {
1516 if (!fpDir.mkdir()) {
1517 Slog.v(TAG, "Cannot make directory: " + fpDir.getAbsolutePath());
1518 return;
1519 }
1520 // Calling mkdir() from this process will create a directory with our
1521 // permissions (inherited from the containing dir). This command fixes
1522 // the label.
1523 if (!SELinux.restorecon(fpDir)) {
1524 Slog.w(TAG, "Restorecons failed. Directory will have wrong label.");
1525 return;
1526 }
Jim Millerbe675422015-05-11 20:45:25 -07001527 }
Andreas Huber7fe20532018-01-22 11:26:44 -08001528
Jim Miller40e46452016-12-16 18:38:53 -08001529 daemon.setActiveGroup(userId, fpDir.getAbsolutePath());
Clara Bayarrid1f722d2016-01-07 14:17:39 +00001530 mCurrentUserId = userId;
Jim Millerbe675422015-05-11 20:45:25 -07001531 }
Charles He29b3a8a2017-05-04 16:02:38 +01001532 mAuthenticatorIds.put(userId,
1533 hasEnrolledFingerprints(userId) ? daemon.getAuthenticatorId() : 0L);
Jim Millerbe675422015-05-11 20:45:25 -07001534 } catch (RemoteException e) {
1535 Slog.e(TAG, "Failed to setActiveGroup():", e);
1536 }
Jim Millerdbe780f2015-05-18 13:55:00 -07001537 }
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -07001538 }
1539
Clara Bayarrid1f722d2016-01-07 14:17:39 +00001540 /**
1541 * @param clientPackage the package of the caller
1542 * @return the profile id
1543 */
1544 private int getUserOrWorkProfileId(String clientPackage, int userId) {
1545 if (!isKeyguard(clientPackage) && isWorkProfile(userId)) {
1546 return userId;
1547 }
1548 return getEffectiveUserId(userId);
1549 }
1550
1551 /**
1552 * @param userId
1553 * @return true if this is a work profile
1554 */
1555 private boolean isWorkProfile(int userId) {
Charles Heda88f0e2017-02-02 18:29:13 +00001556 UserInfo userInfo = null;
1557 final long token = Binder.clearCallingIdentity();
1558 try {
1559 userInfo = mUserManager.getUserInfo(userId);
1560 } finally {
1561 Binder.restoreCallingIdentity(token);
1562 }
1563 return userInfo != null && userInfo.isManagedProfile();
Clara Bayarrid1f722d2016-01-07 14:17:39 +00001564 }
1565
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -07001566 private void listenForUserSwitches() {
1567 try {
Sudheer Shankadc589ac2016-11-10 15:30:17 -08001568 ActivityManager.getService().registerUserSwitchObserver(
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -08001569 new SynchronousUserSwitchObserver() {
Jim Millerbe675422015-05-11 20:45:25 -07001570 @Override
Fyodor Kupolov6005b3f2015-11-23 17:41:50 -08001571 public void onUserSwitching(int newUserId) throws RemoteException {
Jim Millerbe675422015-05-11 20:45:25 -07001572 mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */)
1573 .sendToTarget();
1574 }
Fyodor Kupolov0b77ef92016-06-20 17:16:52 -07001575 }, TAG);
Jorim Jaggiaa4d32a2015-05-13 16:30:04 -07001576 } catch (RemoteException e) {
1577 Slog.w(TAG, "Failed to listen for user switching event" ,e);
1578 }
1579 }
Jim Millerbe675422015-05-11 20:45:25 -07001580
Jim Millerd0063102016-06-28 16:43:57 -07001581 /***
1582 * @param opPackageName the name of the calling package
Charles Heda88f0e2017-02-02 18:29:13 +00001583 * @return authenticator id for the calling user
Jim Millerd0063102016-06-28 16:43:57 -07001584 */
Jim Millercb2ce6f2016-04-13 20:28:18 -07001585 public long getAuthenticatorId(String opPackageName) {
Charles Heda88f0e2017-02-02 18:29:13 +00001586 final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId());
Charles He29b3a8a2017-05-04 16:02:38 +01001587 return mAuthenticatorIds.getOrDefault(userId, 0L);
Jim Millerbe675422015-05-11 20:45:25 -07001588 }
Jim Millera75961472014-06-06 15:00:49 -07001589}