1 /* 2 * 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 17 package com.android.server.fingerprint; 18 19 import static android.Manifest.permission.INTERACT_ACROSS_USERS; 20 import static android.Manifest.permission.MANAGE_FINGERPRINT; 21 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT; 22 import static android.Manifest.permission.USE_BIOMETRIC; 23 import static android.Manifest.permission.USE_FINGERPRINT; 24 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; 25 26 import android.app.ActivityManager; 27 import android.app.ActivityManager.RunningAppProcessInfo; 28 import android.app.AlarmManager; 29 import android.app.AppOpsManager; 30 import android.app.IActivityManager; 31 import android.app.PendingIntent; 32 import android.app.SynchronousUserSwitchObserver; 33 import android.app.TaskStackListener; 34 import android.content.BroadcastReceiver; 35 import android.content.ComponentName; 36 import android.content.Context; 37 import android.content.Intent; 38 import android.content.IntentFilter; 39 import android.content.pm.PackageManager; 40 import android.content.pm.UserInfo; 41 import android.hardware.biometrics.IBiometricPromptReceiver; 42 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; 43 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback; 44 import android.hardware.fingerprint.Fingerprint; 45 import android.hardware.fingerprint.FingerprintManager; 46 import android.hardware.fingerprint.IFingerprintClientActiveCallback; 47 import android.hardware.fingerprint.IFingerprintService; 48 import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback; 49 import android.hardware.fingerprint.IFingerprintServiceReceiver; 50 import android.os.Binder; 51 import android.os.Build; 52 import android.os.Bundle; 53 import android.os.DeadObjectException; 54 import android.os.Environment; 55 import android.os.Handler; 56 import android.os.IBinder; 57 import android.os.IHwBinder; 58 import android.os.IRemoteCallback; 59 import android.os.PowerManager; 60 import android.os.PowerManager.WakeLock; 61 import android.os.RemoteException; 62 import android.os.SELinux; 63 import android.os.ServiceManager; 64 import android.os.SystemClock; 65 import android.os.UserHandle; 66 import android.os.UserManager; 67 import android.security.KeyStore; 68 import android.util.Slog; 69 import android.util.SparseBooleanArray; 70 import android.util.SparseIntArray; 71 import android.util.proto.ProtoOutputStream; 72 73 import com.android.internal.annotations.GuardedBy; 74 import com.android.internal.logging.MetricsLogger; 75 import com.android.internal.statusbar.IStatusBarService; 76 import com.android.internal.util.DumpUtils; 77 import com.android.server.SystemServerInitThreadPool; 78 import com.android.server.SystemService; 79 80 import org.json.JSONArray; 81 import org.json.JSONException; 82 import org.json.JSONObject; 83 84 import java.io.File; 85 import java.io.FileDescriptor; 86 import java.io.PrintWriter; 87 import java.util.ArrayList; 88 import java.util.Collections; 89 import java.util.HashMap; 90 import java.util.List; 91 import java.util.Map; 92 import java.util.concurrent.CopyOnWriteArrayList; 93 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 97 * fingerprint-related events. 98 * 99 * @hide 100 */ 101 public class FingerprintService extends SystemService implements IHwBinder.DeathRecipient { 102 static final String TAG = "FingerprintService"; 103 static final boolean DEBUG = true; 104 private static final boolean CLEANUP_UNUSED_FP = true; 105 private static final String FP_DATA_DIR = "fpdata"; 106 private static final int MSG_USER_SWITCHING = 10; 107 private static final String ACTION_LOCKOUT_RESET = 108 "com.android.server.fingerprint.ACTION_LOCKOUT_RESET"; 109 private static final String KEY_LOCKOUT_RESET_USER = "lockout_reset_user"; 110 111 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 117 int permanentLockout; // total number of permanent lockouts 118 } 119 120 private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors = 121 new ArrayList<>(); 122 private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks = 123 new CopyOnWriteArrayList<>(); 124 private final Map<Integer, Long> mAuthenticatorIds = 125 Collections.synchronizedMap(new HashMap<>()); 126 private final AppOpsManager mAppOps; 127 private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000; 128 private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5; 129 private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20; 130 131 private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms 132 private final String mKeyguardPackage; 133 private int mCurrentUserId = UserHandle.USER_NULL; 134 private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance(); 135 private Context mContext; 136 private long mHalDeviceId; 137 private SparseBooleanArray mTimedLockoutCleared; 138 private SparseIntArray mFailedAttempts; 139 @GuardedBy("this") 140 private IBiometricsFingerprint mDaemon; 141 private IStatusBarService mStatusBarService; 142 private final IActivityManager mActivityManager; 143 private final PowerManager mPowerManager; 144 private final AlarmManager mAlarmManager; 145 private final UserManager mUserManager; 146 private ClientMonitor mCurrentClient; 147 private ClientMonitor mPendingClient; 148 private PerformanceStats mPerformanceStats; 149 150 private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration 151 private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw fingerprints 152 153 private class UserFingerprint { 154 Fingerprint f; 155 int userId; UserFingerprint(Fingerprint f, int userId)156 public UserFingerprint(Fingerprint f, int userId) { 157 this.f = f; 158 this.userId = userId; 159 } 160 } 161 162 // Normal fingerprint authentications are tracked by mPerformanceMap. 163 private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>(); 164 165 // Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap. 166 private HashMap<Integer, PerformanceStats> mCryptoPerformanceMap = new HashMap<>(); 167 168 private Handler mHandler = new Handler() { 169 @Override 170 public void handleMessage(android.os.Message msg) { 171 switch (msg.what) { 172 case MSG_USER_SWITCHING: 173 handleUserSwitching(msg.arg1); 174 break; 175 176 default: 177 Slog.w(TAG, "Unknown message:" + msg.what); 178 } 179 } 180 }; 181 182 private final BroadcastReceiver mLockoutReceiver = new BroadcastReceiver() { 183 @Override 184 public void onReceive(Context context, Intent intent) { 185 if (ACTION_LOCKOUT_RESET.equals(intent.getAction())) { 186 final int user = intent.getIntExtra(KEY_LOCKOUT_RESET_USER, 0); 187 resetFailedAttemptsForUser(false /* clearAttemptCounter */, user); 188 } 189 } 190 }; 191 192 private final Runnable mResetFailedAttemptsForCurrentUserRunnable = new Runnable() { 193 @Override 194 public void run() { 195 resetFailedAttemptsForUser(true /* clearAttemptCounter */, 196 ActivityManager.getCurrentUser()); 197 } 198 }; 199 200 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")); 215 216 mCurrentClient = null; 217 startClient(mPendingClient, false); 218 } 219 }; 220 221 private final TaskStackListener mTaskStackListener = new TaskStackListener() { 222 @Override 223 public void onTaskStackChanged() { 224 try { 225 if (!(mCurrentClient instanceof AuthenticationClient)) { 226 return; 227 } 228 final String currentClient = mCurrentClient.getOwnerString(); 229 if (isKeyguard(currentClient)) { 230 return; // Keyguard is always allowed 231 } 232 List<ActivityManager.RunningTaskInfo> runningTasks = mActivityManager.getTasks(1); 233 if (!runningTasks.isEmpty()) { 234 final String topPackage = runningTasks.get(0).topActivity.getPackageName(); 235 if (!topPackage.contentEquals(currentClient)) { 236 Slog.e(TAG, "Stopping background authentication, top: " + topPackage 237 + " currentClient: " + currentClient); 238 mCurrentClient.stop(false /* initiatedByClient */); 239 } 240 } 241 } catch (RemoteException e) { 242 Slog.e(TAG, "Unable to get running tasks", e); 243 } 244 } 245 }; 246 FingerprintService(Context context)247 public FingerprintService(Context context) { 248 super(context); 249 mContext = context; 250 mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString( 251 com.android.internal.R.string.config_keyguardComponent)).getPackageName(); 252 mAppOps = context.getSystemService(AppOpsManager.class); 253 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 */); 257 mUserManager = UserManager.get(mContext); 258 mTimedLockoutCleared = new SparseBooleanArray(); 259 mFailedAttempts = new SparseIntArray(); 260 mStatusBarService = IStatusBarService.Stub.asInterface( 261 ServiceManager.getService(Context.STATUS_BAR_SERVICE)); 262 mActivityManager = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE)) 263 .getService(); 264 } 265 266 @Override serviceDied(long cookie)267 public void serviceDied(long cookie) { 268 Slog.v(TAG, "fingerprint HAL died"); 269 MetricsLogger.count(mContext, "fingerprintd_died", 1); 270 handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, 271 0 /*vendorCode */); 272 } 273 getFingerprintDaemon()274 public synchronized IBiometricsFingerprint getFingerprintDaemon() { 275 if (mDaemon == null) { 276 Slog.v(TAG, "mDaemon was null, reconnect to fingerprint"); 277 try { 278 mDaemon = IBiometricsFingerprint.getService(); 279 } 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); 283 } 284 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) { 294 Slog.e(TAG, "Failed to open fingerprint HAL", e); 295 mDaemon = null; // try again later! 296 } 297 298 if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId); 299 if (mHalDeviceId != 0) { 300 loadAuthenticatorIds(); 301 updateActiveGroup(ActivityManager.getCurrentUser(), null); 302 doFingerprintCleanupForUser(ActivityManager.getCurrentUser()); 303 } else { 304 Slog.w(TAG, "Failed to open Fingerprint HAL!"); 305 MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1); 306 mDaemon = null; 307 } 308 } 309 return mDaemon; 310 } 311 312 /** Populates existing authenticator ids. To be used only during the start of the service. */ loadAuthenticatorIds()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(); 317 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 331 /** 332 * This method should be called upon connection to the daemon, and when user switches. 333 * @param userId 334 */ doFingerprintCleanupForUser(int userId)335 private void doFingerprintCleanupForUser(int userId) { 336 if (CLEANUP_UNUSED_FP) { 337 enumerateUser(userId); 338 } 339 } 340 clearEnumerateState()341 private void clearEnumerateState() { 342 if (DEBUG) Slog.v(TAG, "clearEnumerateState()"); 343 mUnknownFingerprints.clear(); 344 } 345 enumerateUser(int userId)346 private void enumerateUser(int userId) { 347 if (DEBUG) Slog.v(TAG, "Enumerating user(" + userId + ")"); 348 boolean restricted = !hasPermission(MANAGE_FINGERPRINT); 349 startEnumerate(mToken, userId, null, restricted, true /* internal */); 350 } 351 352 // Remove unknown fingerprints from hardware cleanupUnknownFingerprints()353 private void cleanupUnknownFingerprints() { 354 if (!mUnknownFingerprints.isEmpty()) { 355 UserFingerprint uf = mUnknownFingerprints.get(0); 356 mUnknownFingerprints.remove(uf); 357 boolean restricted = !hasPermission(MANAGE_FINGERPRINT); 358 startRemove(mToken, uf.f.getFingerId(), uf.f.getGroupId(), uf.userId, null, 359 restricted, true /* internal */); 360 } else { 361 clearEnumerateState(); 362 } 363 } 364 handleEnumerate(long deviceId, int fingerId, int groupId, int remaining)365 protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) { 366 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) { 375 if (client instanceof InternalEnumerateClient) { 376 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) { 384 mUnknownFingerprints.add(new UserFingerprint(f, client.getTargetUserId())); 385 } 386 removeClient(client); 387 cleanupUnknownFingerprints(); 388 } else { 389 removeClient(client); 390 } 391 } 392 } 393 handleError(long deviceId, int error, int vendorCode)394 protected void handleError(long deviceId, int error, int vendorCode) { 395 ClientMonitor client = mCurrentClient; 396 if (client instanceof InternalRemovalClient || client instanceof InternalEnumerateClient) { 397 clearEnumerateState(); 398 } 399 if (client != null && client.onError(error, vendorCode)) { 400 removeClient(client); 401 } 402 403 if (DEBUG) Slog.v(TAG, "handleError(client=" 404 + (client != null ? client.getOwnerString() : "null") + ", error = " + error + ")"); 405 // 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 } 413 } 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; 419 mCurrentUserId = UserHandle.USER_NULL; 420 } 421 } 422 } 423 handleRemoved(long deviceId, int fingerId, int groupId, int remaining)424 protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) { 425 if (DEBUG) Slog.w(TAG, "Removed: fid=" + fingerId 426 + ", gid=" + groupId 427 + ", dev=" + deviceId 428 + ", rem=" + remaining); 429 430 ClientMonitor client = mCurrentClient; 431 if (client != null && client.onRemoved(fingerId, groupId, remaining)) { 432 removeClient(client); 433 // When the last fingerprint of a group is removed, update the authenticator id 434 if (!hasEnrolledFingerprints(groupId)) { 435 updateActiveGroup(groupId, null); 436 } 437 } 438 if (client instanceof InternalRemovalClient && !mUnknownFingerprints.isEmpty()) { 439 cleanupUnknownFingerprints(); 440 } else if (client instanceof InternalRemovalClient){ 441 clearEnumerateState(); 442 } 443 } 444 handleAuthenticated(long deviceId, int fingerId, int groupId, ArrayList<Byte> token)445 protected void handleAuthenticated(long deviceId, int fingerId, int groupId, 446 ArrayList<Byte> token) { 447 ClientMonitor client = mCurrentClient; 448 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 455 KeyStore.getInstance().addAuthToken(byteToken); 456 } 457 if (client != null && client.onAuthenticated(fingerId, groupId)) { 458 removeClient(client); 459 } 460 if (fingerId != 0) { 461 mPerformanceStats.accept++; 462 } else { 463 mPerformanceStats.reject++; 464 } 465 } 466 handleAcquired(long deviceId, int acquiredInfo, int vendorCode)467 protected void handleAcquired(long deviceId, int acquiredInfo, int vendorCode) { 468 ClientMonitor client = mCurrentClient; 469 if (client != null && client.onAcquired(acquiredInfo, vendorCode)) { 470 removeClient(client); 471 } 472 if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE 473 && client instanceof AuthenticationClient) { 474 // ignore enrollment acquisitions or acquisitions when we're locked out 475 mPerformanceStats.acquire++; 476 } 477 } 478 handleEnrollResult(long deviceId, int fingerId, int groupId, int remaining)479 protected void handleEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { 480 ClientMonitor client = mCurrentClient; 481 if (client != null && client.onEnrollResult(fingerId, groupId, remaining)) { 482 removeClient(client); 483 // 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); 486 } 487 } 488 userActivity()489 private void userActivity() { 490 long now = SystemClock.uptimeMillis(); 491 mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); 492 } 493 handleUserSwitching(int userId)494 void handleUserSwitching(int userId) { 495 if (mCurrentClient instanceof InternalRemovalClient 496 || mCurrentClient instanceof InternalEnumerateClient) { 497 Slog.w(TAG, "User switched while performing cleanup"); 498 removeClient(mCurrentClient); 499 clearEnumerateState(); 500 } 501 updateActiveGroup(userId, null); 502 doFingerprintCleanupForUser(userId); 503 } 504 removeClient(ClientMonitor client)505 private void removeClient(ClientMonitor client) { 506 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; 516 } 517 if (mPendingClient == null) { 518 notifyClientActiveCallbacks(false); 519 } 520 } 521 getLockoutMode()522 private int getLockoutMode() { 523 final int currentUser = ActivityManager.getCurrentUser(); 524 final int failedAttempts = mFailedAttempts.get(currentUser, 0); 525 if (failedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) { 526 return AuthenticationClient.LOCKOUT_PERMANENT; 527 } else if (failedAttempts > 0 && 528 mTimedLockoutCleared.get(currentUser, false) == false 529 && (failedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) { 530 return AuthenticationClient.LOCKOUT_TIMED; 531 } 532 return AuthenticationClient.LOCKOUT_NONE; 533 } 534 scheduleLockoutResetForUser(int userId)535 private void scheduleLockoutResetForUser(int userId) { 536 mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, 537 SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS, 538 getLockoutResetIntentForUser(userId)); 539 } 540 cancelLockoutResetForUser(int userId)541 private void cancelLockoutResetForUser(int userId) { 542 mAlarmManager.cancel(getLockoutResetIntentForUser(userId)); 543 } 544 getLockoutResetIntentForUser(int userId)545 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); 549 } 550 startPreEnroll(IBinder token)551 public long startPreEnroll(IBinder token) { 552 IBiometricsFingerprint daemon = getFingerprintDaemon(); 553 if (daemon == null) { 554 Slog.w(TAG, "startPreEnroll: no fingerprint HAL!"); 555 return 0; 556 } 557 try { 558 return daemon.preEnroll(); 559 } catch (RemoteException e) { 560 Slog.e(TAG, "startPreEnroll failed", e); 561 } 562 return 0; 563 } 564 startPostEnroll(IBinder token)565 public int startPostEnroll(IBinder token) { 566 IBiometricsFingerprint daemon = getFingerprintDaemon(); 567 if (daemon == null) { 568 Slog.w(TAG, "startPostEnroll: no fingerprint HAL!"); 569 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 579 /** 580 * Calls fingerprint HAL to switch states to the new task. If there's already a current task, 581 * 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 585 */ startClient(ClientMonitor newClient, boolean initiatedByClient)586 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()); 590 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 595 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 } 601 } 602 else { 603 currentClient.stop(initiatedByClient); 604 } 605 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() + ")" 613 + ", initiatedByClient = " + initiatedByClient); 614 notifyClientActiveCallbacks(true); 615 616 newClient.start(); 617 } 618 } 619 startRemove(IBinder token, int fingerId, int groupId, int userId, IFingerprintServiceReceiver receiver, boolean restricted, boolean internal)620 void startRemove(IBinder token, int fingerId, int groupId, int userId, 621 IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) { 622 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 631 IBiometricsFingerprint daemon = getFingerprintDaemon(); 632 if (daemon == null) { 633 Slog.w(TAG, "startRemove: no fingerprint HAL!"); 634 return; 635 } 636 637 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 } 668 } 669 startEnumerate(IBinder token, int userId, IFingerprintServiceReceiver receiver, boolean restricted, boolean internal)670 void startEnumerate(IBinder token, int userId, 671 IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) { 672 IBiometricsFingerprint daemon = getFingerprintDaemon(); 673 if (daemon == null) { 674 Slog.w(TAG, "startEnumerate: no fingerprint HAL!"); 675 return; 676 } 677 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() { 685 686 } 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 } 710 } 711 getEnrolledFingerprints(int userId)712 public List<Fingerprint> getEnrolledFingerprints(int userId) { 713 return mFingerprintUtils.getFingerprintsForUser(mContext, userId); 714 } 715 hasEnrolledFingerprints(int userId)716 public boolean hasEnrolledFingerprints(int userId) { 717 if (userId != UserHandle.getCallingUserId()) { 718 checkPermission(INTERACT_ACROSS_USERS); 719 } 720 return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0; 721 } 722 hasPermission(String permission)723 boolean hasPermission(String permission) { 724 return getContext().checkCallingOrSelfPermission(permission) 725 == PackageManager.PERMISSION_GRANTED; 726 } 727 checkPermission(String permission)728 void checkPermission(String permission) { 729 getContext().enforceCallingOrSelfPermission(permission, 730 "Must have " + permission + " permission."); 731 } 732 getEffectiveUserId(int userId)733 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 isCurrentUserOrProfile(int userId)745 boolean isCurrentUserOrProfile(int userId) { 746 UserManager um = UserManager.get(mContext); 747 if (um == null) { 748 Slog.e(TAG, "Unable to acquire UserManager"); 749 return false; 750 } 751 752 final long token = Binder.clearCallingIdentity(); 753 try { 754 // Allow current user or profiles of the current user... 755 for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) { 756 if (profileId == userId) { 757 return true; 758 } 759 } 760 } finally { 761 Binder.restoreCallingIdentity(token); 762 } 763 764 return false; 765 } 766 isForegroundActivity(int uid, int pid)767 private boolean isForegroundActivity(int uid, int pid) { 768 try { 769 List<RunningAppProcessInfo> procs = 770 ActivityManager.getService().getRunningAppProcesses(); 771 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 775 && proc.importance <= IMPORTANCE_FOREGROUND_SERVICE) { 776 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 787 * @param requireForeground only allow this call while app is in the foreground 788 * @return true if caller can use fingerprint API 789 */ canUseFingerprint(String opPackageName, boolean requireForeground, int uid, int pid, int userId)790 private boolean canUseFingerprint(String opPackageName, boolean requireForeground, int uid, 791 int pid, int userId) { 792 if (getContext().checkCallingPermission(USE_FINGERPRINT) 793 != PackageManager.PERMISSION_GRANTED) { 794 checkPermission(USE_BIOMETRIC); 795 } 796 797 if (isKeyguard(opPackageName)) { 798 return true; // Keyguard is always allowed 799 } 800 if (!isCurrentUserOrProfile(userId)) { 801 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) { 806 Slog.w(TAG, "Rejecting " + opPackageName + " ; permission denied"); 807 return false; 808 } 809 if (requireForeground && !(isForegroundActivity(uid, pid) || currentClient(opPackageName))){ 810 Slog.w(TAG, "Rejecting " + opPackageName + " ; not in foreground"); 811 return false; 812 } 813 return true; 814 } 815 816 /** 817 * @param opPackageName package of the caller 818 * @return true if this is the same client currently using fingerprint 819 */ currentClient(String opPackageName)820 private boolean currentClient(String opPackageName) { 821 return mCurrentClient != null && mCurrentClient.getOwnerString().equals(opPackageName); 822 } 823 824 /** 825 * @param clientPackage 826 * @return true if this is keyguard package 827 */ isKeyguard(String clientPackage)828 private boolean isKeyguard(String clientPackage) { 829 return mKeyguardPackage.equals(clientPackage); 830 } 831 addLockoutResetMonitor(FingerprintServiceLockoutResetMonitor monitor)832 private void addLockoutResetMonitor(FingerprintServiceLockoutResetMonitor monitor) { 833 if (!mLockoutMonitors.contains(monitor)) { 834 mLockoutMonitors.add(monitor); 835 } 836 } 837 removeLockoutResetCallback( FingerprintServiceLockoutResetMonitor monitor)838 private void removeLockoutResetCallback( 839 FingerprintServiceLockoutResetMonitor monitor) { 840 mLockoutMonitors.remove(monitor); 841 } 842 notifyLockoutResetMonitors()843 private void notifyLockoutResetMonitors() { 844 for (int i = 0; i < mLockoutMonitors.size(); i++) { 845 mLockoutMonitors.get(i).sendLockoutReset(); 846 } 847 } 848 notifyClientActiveCallbacks(boolean isActive)849 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)); 857 } 858 } 859 } 860 startAuthentication(IBinder token, long opId, int callingUserId, int groupId, IFingerprintServiceReceiver receiver, int flags, boolean restricted, String opPackageName, Bundle bundle, IBiometricPromptReceiver dialogReceiver)861 private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId, 862 IFingerprintServiceReceiver receiver, int flags, boolean restricted, 863 String opPackageName, Bundle bundle, IBiometricPromptReceiver dialogReceiver) { 864 updateActiveGroup(groupId, opPackageName); 865 866 if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")"); 867 868 AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token, 869 receiver, mCurrentUserId, groupId, opId, restricted, opPackageName, bundle, 870 dialogReceiver, mStatusBarService) { 871 @Override 872 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 890 public int handleFailedAttempt() { 891 final int currentUser = ActivityManager.getCurrentUser(); 892 mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1); 893 mTimedLockoutCleared.put(ActivityManager.getCurrentUser(), false); 894 final int lockoutMode = getLockoutMode(); 895 if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) { 896 mPerformanceStats.permanentLockout++; 897 } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) { 898 mPerformanceStats.lockout++; 899 } 900 901 // Failing multiple times will continue to push out the lockout time 902 if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) { 903 scheduleLockoutResetForUser(currentUser); 904 return lockoutMode; 905 } 906 return AuthenticationClient.LOCKOUT_NONE; 907 } 908 909 @Override 910 public void resetFailedAttempts() { 911 FingerprintService.this.resetFailedAttemptsForUser(true /* clearAttemptCounter */, 912 ActivityManager.getCurrentUser()); 913 } 914 915 @Override 916 public void notifyUserActivity() { 917 FingerprintService.this.userActivity(); 918 } 919 920 @Override 921 public IBiometricsFingerprint getFingerprintDaemon() { 922 return FingerprintService.this.getFingerprintDaemon(); 923 } 924 }; 925 926 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"); 935 } 936 return; 937 } 938 startClient(client, true /* initiatedByClient */); 939 } 940 startEnrollment(IBinder token, byte [] cryptoToken, int userId, IFingerprintServiceReceiver receiver, int flags, boolean restricted, String opPackageName)941 private void startEnrollment(IBinder token, byte [] cryptoToken, int userId, 942 IFingerprintServiceReceiver receiver, int flags, boolean restricted, 943 String opPackageName) { 944 updateActiveGroup(userId, opPackageName); 945 946 final int groupId = userId; // default group for fingerprint enrollment 947 948 EnrollClient client = new EnrollClient(getContext(), mHalDeviceId, token, receiver, 949 userId, groupId, cryptoToken, restricted, opPackageName) { 950 951 @Override 952 public IBiometricsFingerprint getFingerprintDaemon() { 953 return FingerprintService.this.getFingerprintDaemon(); 954 } 955 956 @Override 957 public void notifyUserActivity() { 958 FingerprintService.this.userActivity(); 959 } 960 }; 961 startClient(client, true /* initiatedByClient */); 962 } 963 964 // attempt counter should only be cleared when Keyguard goes away or when 965 // a fingerprint is successfully authenticated resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId)966 protected void resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId) { 967 if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) { 968 Slog.v(TAG, "Reset fingerprint lockout, clearAttemptCounter=" + clearAttemptCounter); 969 } 970 if (clearAttemptCounter) { 971 mFailedAttempts.put(userId, 0); 972 } 973 mTimedLockoutCleared.put(userId, true); 974 // If we're asked to reset failed attempts externally (i.e. from Keyguard), 975 // the alarm might still be pending; remove it. 976 cancelLockoutResetForUser(userId); 977 notifyLockoutResetMonitors(); 978 } 979 980 private class FingerprintServiceLockoutResetMonitor implements IBinder.DeathRecipient { 981 982 private static final long WAKELOCK_TIMEOUT_MS = 2000; 983 private final IFingerprintServiceLockoutResetCallback mCallback; 984 private final WakeLock mWakeLock; 985 FingerprintServiceLockoutResetMonitor( IFingerprintServiceLockoutResetCallback callback)986 public FingerprintServiceLockoutResetMonitor( 987 IFingerprintServiceLockoutResetCallback callback) { 988 mCallback = callback; 989 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 990 "lockout reset callback"); 991 try { 992 mCallback.asBinder().linkToDeath(FingerprintServiceLockoutResetMonitor.this, 0); 993 } catch (RemoteException e) { 994 Slog.w(TAG, "caught remote exception in linkToDeath", e); 995 } 996 } 997 sendLockoutReset()998 public void sendLockoutReset() { 999 if (mCallback != null) { 1000 try { 1001 mWakeLock.acquire(WAKELOCK_TIMEOUT_MS); 1002 mCallback.onLockoutReset(mHalDeviceId, new IRemoteCallback.Stub() { 1003 1004 @Override 1005 public void sendResult(Bundle data) throws RemoteException { 1006 releaseWakelock(); 1007 } 1008 }); 1009 } 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); 1014 releaseWakelock(); 1015 } 1016 } 1017 } 1018 1019 private final Runnable mRemoveCallbackRunnable = new Runnable() { 1020 @Override 1021 public void run() { 1022 releaseWakelock(); 1023 removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this); 1024 } 1025 }; 1026 1027 @Override binderDied()1028 public void binderDied() { 1029 Slog.e(TAG, "Lockout reset callback binder died"); 1030 mHandler.post(mRemoveCallbackRunnable); 1031 } 1032 releaseWakelock()1033 private void releaseWakelock() { 1034 if (mWakeLock.isHeld()) { 1035 mWakeLock.release(); 1036 } 1037 } 1038 } 1039 1040 private IBiometricsFingerprintClientCallback mDaemonCallback = 1041 new IBiometricsFingerprintClientCallback.Stub() { 1042 1043 @Override 1044 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 }); 1052 } 1053 1054 @Override 1055 public void onAcquired(final long deviceId, final int acquiredInfo, final int vendorCode) { 1056 mHandler.post(new Runnable() { 1057 @Override 1058 public void run() { 1059 handleAcquired(deviceId, acquiredInfo, vendorCode); 1060 } 1061 }); 1062 } 1063 1064 @Override 1065 public void onAuthenticated(final long deviceId, final int fingerId, final int groupId, 1066 ArrayList<Byte> token) { 1067 mHandler.post(new Runnable() { 1068 @Override 1069 public void run() { 1070 handleAuthenticated(deviceId, fingerId, groupId, token); 1071 } 1072 }); 1073 } 1074 1075 @Override 1076 public void onError(final long deviceId, final int error, final int vendorCode) { 1077 mHandler.post(new Runnable() { 1078 @Override 1079 public void run() { 1080 handleError(deviceId, error, vendorCode); 1081 } 1082 }); 1083 } 1084 1085 @Override 1086 public void onRemoved(final long deviceId, final int fingerId, final int groupId, final int remaining) { 1087 mHandler.post(new Runnable() { 1088 @Override 1089 public void run() { 1090 handleRemoved(deviceId, fingerId, groupId, remaining); 1091 } 1092 }); 1093 } 1094 1095 @Override 1096 public void onEnumerate(final long deviceId, final int fingerId, final int groupId, 1097 final int remaining) { 1098 mHandler.post(new Runnable() { 1099 @Override 1100 public void run() { 1101 handleEnumerate(deviceId, fingerId, groupId, remaining); 1102 } 1103 }); 1104 } 1105 }; 1106 1107 private final class FingerprintServiceWrapper extends IFingerprintService.Stub { 1108 @Override // Binder call preEnroll(IBinder token)1109 public long preEnroll(IBinder token) { 1110 checkPermission(MANAGE_FINGERPRINT); 1111 return startPreEnroll(token); 1112 } 1113 1114 @Override // Binder call postEnroll(IBinder token)1115 public int postEnroll(IBinder token) { 1116 checkPermission(MANAGE_FINGERPRINT); 1117 return startPostEnroll(token); 1118 } 1119 1120 @Override // Binder call enroll(final IBinder token, final byte[] cryptoToken, final int userId, final IFingerprintServiceReceiver receiver, final int flags, final String opPackageName)1121 public void enroll(final IBinder token, final byte[] cryptoToken, final int userId, 1122 final IFingerprintServiceReceiver receiver, final int flags, 1123 final String opPackageName) { 1124 checkPermission(MANAGE_FINGERPRINT); 1125 final int limit = mContext.getResources().getInteger( 1126 com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser); 1127 1128 final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size(); 1129 if (enrolled >= limit) { 1130 Slog.w(TAG, "Too many fingerprints registered"); 1131 return; 1132 } 1133 1134 // Group ID is arbitrarily set to parent profile user ID. It just represents 1135 // the default fingerprints for the user. 1136 if (!isCurrentUserOrProfile(userId)) { 1137 return; 1138 } 1139 1140 final boolean restricted = isRestricted(); 1141 mHandler.post(new Runnable() { 1142 @Override 1143 public void run() { 1144 startEnrollment(token, cryptoToken, userId, receiver, flags, 1145 restricted, opPackageName); 1146 } 1147 }); 1148 } 1149 isRestricted()1150 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 1156 @Override // Binder call cancelEnrollment(final IBinder token)1157 public void cancelEnrollment(final IBinder token) { 1158 checkPermission(MANAGE_FINGERPRINT); 1159 mHandler.post(new Runnable() { 1160 @Override 1161 public void run() { 1162 ClientMonitor client = mCurrentClient; 1163 if (client instanceof EnrollClient && client.getToken() == token) { 1164 client.stop(client.getToken() == token); 1165 } 1166 } 1167 }); 1168 } 1169 1170 @Override // Binder call authenticate(final IBinder token, final long opId, final int groupId, final IFingerprintServiceReceiver receiver, final int flags, final String opPackageName, final Bundle bundle, final IBiometricPromptReceiver dialogReceiver)1171 public void authenticate(final IBinder token, final long opId, final int groupId, 1172 final IFingerprintServiceReceiver receiver, final int flags, 1173 final String opPackageName, final Bundle bundle, 1174 final IBiometricPromptReceiver dialogReceiver) { 1175 final int callingUid = Binder.getCallingUid(); 1176 final int callingPid = Binder.getCallingPid(); 1177 final int callingUserId = UserHandle.getCallingUserId(); 1178 final boolean restricted = isRestricted(); 1179 1180 if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, callingPid, 1181 callingUserId)) { 1182 if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName); 1183 return; 1184 } 1185 1186 mHandler.post(new Runnable() { 1187 @Override 1188 public void run() { 1189 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 1201 startAuthentication(token, opId, callingUserId, groupId, receiver, 1202 flags, restricted, opPackageName, bundle, dialogReceiver); 1203 } 1204 }); 1205 } 1206 1207 @Override // Binder call cancelAuthentication(final IBinder token, final String opPackageName)1208 public void cancelAuthentication(final IBinder token, final String opPackageName) { 1209 final int callingUid = Binder.getCallingUid(); 1210 final int callingPid = Binder.getCallingPid(); 1211 final int callingUserId = UserHandle.getCallingUserId(); 1212 1213 if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, callingPid, 1214 callingUserId)) { 1215 if (DEBUG) Slog.v(TAG, "cancelAuthentication(): reject " + opPackageName); 1216 return; 1217 } 1218 1219 mHandler.post(new Runnable() { 1220 @Override 1221 public void run() { 1222 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"); 1230 } 1231 } else if (client != null) { 1232 if (DEBUG) Slog.v(TAG, "can't cancel non-authenticating client " 1233 + client.getOwnerString()); 1234 } 1235 } 1236 }); 1237 } 1238 1239 @Override // Binder call setActiveUser(final int userId)1240 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 remove(final IBinder token, final int fingerId, final int groupId, final int userId, final IFingerprintServiceReceiver receiver)1251 public void remove(final IBinder token, final int fingerId, final int groupId, 1252 final int userId, final IFingerprintServiceReceiver receiver) { 1253 checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission 1254 final boolean restricted = isRestricted(); 1255 mHandler.post(new Runnable() { 1256 @Override 1257 public void run() { 1258 startRemove(token, fingerId, groupId, userId, receiver, 1259 restricted, false /* internal */); 1260 } 1261 }); 1262 } 1263 1264 @Override // Binder call enumerate(final IBinder token, final int userId, final IFingerprintServiceReceiver receiver)1265 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() { 1272 startEnumerate(token, userId, receiver, restricted, false /* internal */); 1273 } 1274 }); 1275 } 1276 1277 @Override // Binder call isHardwareDetected(long deviceId, String opPackageName)1278 public boolean isHardwareDetected(long deviceId, String opPackageName) { 1279 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 1280 Binder.getCallingUid(), Binder.getCallingPid(), 1281 UserHandle.getCallingUserId())) { 1282 return false; 1283 } 1284 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 } 1292 } 1293 1294 @Override // Binder call rename(final int fingerId, final int groupId, final String name)1295 public void rename(final int fingerId, final int groupId, final String name) { 1296 checkPermission(MANAGE_FINGERPRINT); 1297 if (!isCurrentUserOrProfile(groupId)) { 1298 return; 1299 } 1300 mHandler.post(new Runnable() { 1301 @Override 1302 public void run() { 1303 mFingerprintUtils.renameFingerprintForUser(mContext, fingerId, 1304 groupId, name); 1305 } 1306 }); 1307 } 1308 1309 @Override // Binder call getEnrolledFingerprints(int userId, String opPackageName)1310 public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) { 1311 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 1312 Binder.getCallingUid(), Binder.getCallingPid(), 1313 UserHandle.getCallingUserId())) { 1314 return Collections.emptyList(); 1315 } 1316 1317 return FingerprintService.this.getEnrolledFingerprints(userId); 1318 } 1319 1320 @Override // Binder call hasEnrolledFingerprints(int userId, String opPackageName)1321 public boolean hasEnrolledFingerprints(int userId, String opPackageName) { 1322 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 1323 Binder.getCallingUid(), Binder.getCallingPid(), 1324 UserHandle.getCallingUserId())) { 1325 return false; 1326 } 1327 1328 return FingerprintService.this.hasEnrolledFingerprints(userId); 1329 } 1330 1331 @Override // Binder call getAuthenticatorId(String opPackageName)1332 public long getAuthenticatorId(String opPackageName) { 1333 // 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 1349 return FingerprintService.this.getAuthenticatorId(opPackageName); 1350 } 1351 1352 @Override // Binder call dump(FileDescriptor fd, PrintWriter pw, String[] args)1353 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1354 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1355 1356 final long ident = Binder.clearCallingIdentity(); 1357 try { 1358 if (args.length > 0 && "--proto".equals(args[0])) { 1359 dumpProto(fd); 1360 } else { 1361 dumpInternal(pw); 1362 } 1363 } finally { 1364 Binder.restoreCallingIdentity(ident); 1365 } 1366 } 1367 1368 @Override // Binder call resetTimeout(byte [] token)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. 1372 mHandler.post(mResetFailedAttemptsForCurrentUserRunnable); 1373 } 1374 1375 @Override addLockoutResetCallback(final IFingerprintServiceLockoutResetCallback callback)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 }); 1385 } 1386 1387 @Override isClientActive()1388 public boolean isClientActive() { 1389 checkPermission(MANAGE_FINGERPRINT); 1390 synchronized(FingerprintService.this) { 1391 return (mCurrentClient != null) || (mPendingClient != null); 1392 } 1393 } 1394 1395 @Override addClientActiveCallback(IFingerprintClientActiveCallback callback)1396 public void addClientActiveCallback(IFingerprintClientActiveCallback callback) { 1397 checkPermission(MANAGE_FINGERPRINT); 1398 mClientActiveCallbacks.add(callback); 1399 } 1400 1401 @Override removeClientActiveCallback(IFingerprintClientActiveCallback callback)1402 public void removeClientActiveCallback(IFingerprintClientActiveCallback callback) { 1403 checkPermission(MANAGE_FINGERPRINT); 1404 mClientActiveCallbacks.remove(callback); 1405 } 1406 } 1407 dumpInternal(PrintWriter pw)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(); 1417 PerformanceStats stats = mPerformanceMap.get(userId); 1418 PerformanceStats cryptoStats = mCryptoPerformanceMap.get(userId); 1419 JSONObject set = new JSONObject(); 1420 set.put("id", userId); 1421 set.put("count", N); 1422 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); 1426 set.put("permanentLockout", (stats != null) ? stats.permanentLockout : 0); 1427 // 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); 1433 set.put("permanentLockoutCrypto", 1434 (cryptoStats != null) ? cryptoStats.permanentLockout : 0); 1435 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); 1443 } 1444 dumpProto(FileDescriptor fd)1445 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); 1460 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); 1465 proto.end(countsToken); 1466 } 1467 1468 // Statistics about secure fingerprint transactions (e.g. to unlock password 1469 // storage, make secure purchases, etc.) 1470 final PerformanceStats crypto = mCryptoPerformanceMap.get(userId); 1471 if (crypto != null) { 1472 final long countsToken = proto.start(FingerprintUserStatsProto.CRYPTO); 1473 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); 1478 proto.end(countsToken); 1479 } 1480 1481 proto.end(userToken); 1482 } 1483 proto.flush(); 1484 mPerformanceMap.clear(); 1485 mCryptoPerformanceMap.clear(); 1486 } 1487 1488 @Override onStart()1489 public void onStart() { 1490 publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); 1491 SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart"); 1492 listenForUserSwitches(); 1493 } 1494 updateActiveGroup(int userId, String clientPackage)1495 private void updateActiveGroup(int userId, String clientPackage) { 1496 IBiometricsFingerprint daemon = getFingerprintDaemon(); 1497 1498 if (daemon != null) { 1499 try { 1500 userId = getUserOrWorkProfileId(clientPackage, userId); 1501 if (userId != mCurrentUserId) { 1502 int firstSdkInt = Build.VERSION.FIRST_SDK_INT; 1503 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 } 1507 File baseDir; 1508 if (firstSdkInt <= Build.VERSION_CODES.O_MR1) { 1509 baseDir = Environment.getUserSystemDirectory(userId); 1510 } else { 1511 baseDir = Environment.getDataVendorDeDirectory(userId); 1512 } 1513 1514 File fpDir = new File(baseDir, FP_DATA_DIR); 1515 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 } 1527 } 1528 1529 daemon.setActiveGroup(userId, fpDir.getAbsolutePath()); 1530 mCurrentUserId = userId; 1531 } 1532 mAuthenticatorIds.put(userId, 1533 hasEnrolledFingerprints(userId) ? daemon.getAuthenticatorId() : 0L); 1534 } catch (RemoteException e) { 1535 Slog.e(TAG, "Failed to setActiveGroup():", e); 1536 } 1537 } 1538 } 1539 1540 /** 1541 * @param clientPackage the package of the caller 1542 * @return the profile id 1543 */ getUserOrWorkProfileId(String clientPackage, int userId)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 */ isWorkProfile(int userId)1555 private boolean isWorkProfile(int userId) { 1556 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(); 1564 } 1565 listenForUserSwitches()1566 private void listenForUserSwitches() { 1567 try { 1568 ActivityManager.getService().registerUserSwitchObserver( 1569 new SynchronousUserSwitchObserver() { 1570 @Override 1571 public void onUserSwitching(int newUserId) throws RemoteException { 1572 mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */) 1573 .sendToTarget(); 1574 } 1575 }, TAG); 1576 } catch (RemoteException e) { 1577 Slog.w(TAG, "Failed to listen for user switching event" ,e); 1578 } 1579 } 1580 1581 /*** 1582 * @param opPackageName the name of the calling package 1583 * @return authenticator id for the calling user 1584 */ getAuthenticatorId(String opPackageName)1585 public long getAuthenticatorId(String opPackageName) { 1586 final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId()); 1587 return mAuthenticatorIds.getOrDefault(userId, 0L); 1588 } 1589 } 1590