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 17package com.android.server.fingerprint; 18 19import static android.Manifest.permission.INTERACT_ACROSS_USERS; 20import static android.Manifest.permission.MANAGE_FINGERPRINT; 21import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT; 22import static android.Manifest.permission.USE_FINGERPRINT; 23import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND; 24 25import android.app.ActivityManager; 26import android.app.ActivityManager.RunningAppProcessInfo; 27import android.app.AlarmManager; 28import android.app.AppOpsManager; 29import android.app.PendingIntent; 30import android.app.SynchronousUserSwitchObserver; 31import android.content.BroadcastReceiver; 32import android.content.ComponentName; 33import android.content.Context; 34import android.content.Intent; 35import android.content.IntentFilter; 36import android.content.pm.PackageManager; 37import android.content.pm.UserInfo; 38import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; 39import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback; 40import android.hardware.fingerprint.Fingerprint; 41import android.hardware.fingerprint.FingerprintManager; 42import android.hardware.fingerprint.IFingerprintClientActiveCallback; 43import android.hardware.fingerprint.IFingerprintService; 44import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback; 45import android.hardware.fingerprint.IFingerprintServiceReceiver; 46import android.os.Binder; 47import android.os.Bundle; 48import android.os.DeadObjectException; 49import android.os.Environment; 50import android.os.Handler; 51import android.os.IBinder; 52import android.os.IHwBinder; 53import android.os.IRemoteCallback; 54import android.os.PowerManager; 55import android.os.PowerManager.WakeLock; 56import android.os.RemoteException; 57import android.os.SELinux; 58import android.os.SystemClock; 59import android.os.UserHandle; 60import android.os.UserManager; 61import android.security.KeyStore; 62import android.service.fingerprint.FingerprintActionStatsProto; 63import android.service.fingerprint.FingerprintServiceDumpProto; 64import android.service.fingerprint.FingerprintUserStatsProto; 65import android.util.Slog; 66import android.util.proto.ProtoOutputStream; 67 68import com.android.internal.annotations.GuardedBy; 69import com.android.internal.logging.MetricsLogger; 70import com.android.internal.util.DumpUtils; 71import com.android.server.SystemServerInitThreadPool; 72import com.android.server.SystemService; 73 74import org.json.JSONArray; 75import org.json.JSONException; 76import org.json.JSONObject; 77 78import java.io.File; 79import java.io.FileDescriptor; 80import java.io.PrintWriter; 81import java.util.ArrayList; 82import java.util.Collections; 83import java.util.HashMap; 84import java.util.LinkedList; 85import java.util.List; 86import java.util.Map; 87import java.util.concurrent.CopyOnWriteArrayList; 88 89/** 90 * A service to manage multiple clients that want to access the fingerprint HAL API. 91 * The service is responsible for maintaining a list of clients and dispatching all 92 * fingerprint -related events. 93 * 94 * @hide 95 */ 96public class FingerprintService extends SystemService implements IHwBinder.DeathRecipient { 97 static final String TAG = "FingerprintService"; 98 static final boolean DEBUG = true; 99 private static final boolean CLEANUP_UNUSED_FP = false; 100 private static final String FP_DATA_DIR = "fpdata"; 101 private static final int MSG_USER_SWITCHING = 10; 102 private static final String ACTION_LOCKOUT_RESET = 103 "com.android.server.fingerprint.ACTION_LOCKOUT_RESET"; 104 105 private class PerformanceStats { 106 int accept; // number of accepted fingerprints 107 int reject; // number of rejected fingerprints 108 int acquire; // total number of acquisitions. Should be >= accept+reject due to poor image 109 // acquisition in some cases (too fast, too slow, dirty sensor, etc.) 110 int lockout; // total number of lockouts 111 int permanentLockout; // total number of permanent lockouts 112 } 113 114 private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors = 115 new ArrayList<>(); 116 private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks = 117 new CopyOnWriteArrayList<>(); 118 private final Map<Integer, Long> mAuthenticatorIds = 119 Collections.synchronizedMap(new HashMap<>()); 120 private final AppOpsManager mAppOps; 121 private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000; 122 private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5; 123 private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20; 124 125 private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms 126 private final String mKeyguardPackage; 127 private int mCurrentUserId = UserHandle.USER_NULL; 128 private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance(); 129 private Context mContext; 130 private long mHalDeviceId; 131 private boolean mTimedLockoutCleared; 132 private int mFailedAttempts; 133 @GuardedBy("this") 134 private IBiometricsFingerprint mDaemon; 135 private final PowerManager mPowerManager; 136 private final AlarmManager mAlarmManager; 137 private final UserManager mUserManager; 138 private ClientMonitor mCurrentClient; 139 private ClientMonitor mPendingClient; 140 private PerformanceStats mPerformanceStats; 141 142 143 private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration 144 private LinkedList<Integer> mEnumeratingUserIds = new LinkedList<>(); 145 private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw finterprints 146 147 private class UserFingerprint { 148 Fingerprint f; 149 int userId; 150 public UserFingerprint(Fingerprint f, int userId) { 151 this.f = f; 152 this.userId = userId; 153 } 154 } 155 156 // Normal fingerprint authentications are tracked by mPerformanceMap. 157 private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>(); 158 159 // Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap. 160 private HashMap<Integer, PerformanceStats> mCryptoPerformanceMap = new HashMap<>(); 161 162 private Handler mHandler = new Handler() { 163 @Override 164 public void handleMessage(android.os.Message msg) { 165 switch (msg.what) { 166 case MSG_USER_SWITCHING: 167 handleUserSwitching(msg.arg1); 168 break; 169 170 default: 171 Slog.w(TAG, "Unknown message:" + msg.what); 172 } 173 } 174 }; 175 176 private final BroadcastReceiver mLockoutReceiver = new BroadcastReceiver() { 177 @Override 178 public void onReceive(Context context, Intent intent) { 179 if (ACTION_LOCKOUT_RESET.equals(intent.getAction())) { 180 resetFailedAttempts(false /* clearAttemptCounter */); 181 } 182 } 183 }; 184 185 private final Runnable mResetFailedAttemptsRunnable = new Runnable() { 186 @Override 187 public void run() { 188 resetFailedAttempts(true /* clearAttemptCounter */); 189 } 190 }; 191 192 private final Runnable mResetClientState = new Runnable() { 193 @Override 194 public void run() { 195 // Warning: if we get here, the driver never confirmed our call to cancel the current 196 // operation (authenticate, enroll, remove, enumerate, etc), which is 197 // really bad. The result will be a 3-second delay in starting each new client. 198 // If you see this on a device, make certain the driver notifies with 199 // {@link FingerprintManager#FINGERPRINT_ERROR_CANCEL} in response to cancel() 200 // once it has successfully switched to the IDLE state in the fingerprint HAL. 201 // Additionally,{@link FingerprintManager#FINGERPRINT_ERROR_CANCEL} should only be sent 202 // in response to an actual cancel() call. 203 Slog.w(TAG, "Client " 204 + (mCurrentClient != null ? mCurrentClient.getOwnerString() : "null") 205 + " failed to respond to cancel, starting client " 206 + (mPendingClient != null ? mPendingClient.getOwnerString() : "null")); 207 208 mCurrentClient = null; 209 startClient(mPendingClient, false); 210 } 211 }; 212 213 public FingerprintService(Context context) { 214 super(context); 215 mContext = context; 216 mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString( 217 com.android.internal.R.string.config_keyguardComponent)).getPackageName(); 218 mAppOps = context.getSystemService(AppOpsManager.class); 219 mPowerManager = mContext.getSystemService(PowerManager.class); 220 mAlarmManager = mContext.getSystemService(AlarmManager.class); 221 mContext.registerReceiver(mLockoutReceiver, new IntentFilter(ACTION_LOCKOUT_RESET), 222 RESET_FINGERPRINT_LOCKOUT, null /* handler */); 223 mUserManager = UserManager.get(mContext); 224 } 225 226 @Override 227 public void serviceDied(long cookie) { 228 Slog.v(TAG, "fingerprint HAL died"); 229 MetricsLogger.count(mContext, "fingerprintd_died", 1); 230 handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, 231 0 /*vendorCode */); 232 } 233 234 public synchronized IBiometricsFingerprint getFingerprintDaemon() { 235 if (mDaemon == null) { 236 Slog.v(TAG, "mDeamon was null, reconnect to fingerprint"); 237 try { 238 mDaemon = IBiometricsFingerprint.getService(); 239 } catch (java.util.NoSuchElementException e) { 240 // Service doesn't exist or cannot be opened. Logged below. 241 } catch (RemoteException e) { 242 Slog.e(TAG, "Failed to get biometric interface", e); 243 } 244 if (mDaemon == null) { 245 Slog.w(TAG, "fingerprint HIDL not available"); 246 return null; 247 } 248 249 mDaemon.asBinder().linkToDeath(this, 0); 250 251 try { 252 mHalDeviceId = mDaemon.setNotify(mDaemonCallback); 253 } catch (RemoteException e) { 254 Slog.e(TAG, "Failed to open fingerprint HAL", e); 255 mDaemon = null; // try again later! 256 } 257 258 if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId); 259 if (mHalDeviceId != 0) { 260 loadAuthenticatorIds(); 261 updateActiveGroup(ActivityManager.getCurrentUser(), null); 262 doFingerprintCleanup(ActivityManager.getCurrentUser()); 263 } else { 264 Slog.w(TAG, "Failed to open Fingerprint HAL!"); 265 MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1); 266 mDaemon = null; 267 } 268 } 269 return mDaemon; 270 } 271 272 /** Populates existing authenticator ids. To be used only during the start of the service. */ 273 private void loadAuthenticatorIds() { 274 // This operation can be expensive, so keep track of the elapsed time. Might need to move to 275 // background if it takes too long. 276 long t = System.currentTimeMillis(); 277 mAuthenticatorIds.clear(); 278 for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) { 279 int userId = getUserOrWorkProfileId(null, user.id); 280 if (!mAuthenticatorIds.containsKey(userId)) { 281 updateActiveGroup(userId, null); 282 } 283 } 284 285 t = System.currentTimeMillis() - t; 286 if (t > 1000) { 287 Slog.w(TAG, "loadAuthenticatorIds() taking too long: " + t + "ms"); 288 } 289 } 290 291 private void doFingerprintCleanup(int userId) { 292 if (CLEANUP_UNUSED_FP) { 293 resetEnumerateState(); 294 mEnumeratingUserIds.push(userId); 295 enumerateNextUser(); 296 } 297 } 298 299 private void resetEnumerateState() { 300 if (DEBUG) Slog.v(TAG, "Enumerate cleaning up"); 301 mEnumeratingUserIds.clear(); 302 mUnknownFingerprints.clear(); 303 } 304 305 private void enumerateNextUser() { 306 int nextUser = mEnumeratingUserIds.getFirst(); 307 updateActiveGroup(nextUser, null); 308 boolean restricted = !hasPermission(MANAGE_FINGERPRINT); 309 310 if (DEBUG) Slog.v(TAG, "Enumerating user id " + nextUser + " of " 311 + mEnumeratingUserIds.size() + " remaining users"); 312 313 startEnumerate(mToken, nextUser, null, restricted, true /* internal */); 314 } 315 316 // Remove unknown fingerprints from hardware 317 private void cleanupUnknownFingerprints() { 318 if (!mUnknownFingerprints.isEmpty()) { 319 Slog.w(TAG, "unknown fingerprint size: " + mUnknownFingerprints.size()); 320 UserFingerprint uf = mUnknownFingerprints.get(0); 321 mUnknownFingerprints.remove(uf); 322 boolean restricted = !hasPermission(MANAGE_FINGERPRINT); 323 updateActiveGroup(uf.userId, null); 324 startRemove(mToken, uf.f.getFingerId(), uf.f.getGroupId(), uf.userId, null, 325 restricted, true /* internal */); 326 } else { 327 resetEnumerateState(); 328 } 329 } 330 331 protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) { 332 if (DEBUG) Slog.w(TAG, "Enumerate: fid=" + fingerId 333 + ", gid=" + groupId 334 + ", dev=" + deviceId 335 + ", rem=" + remaining); 336 337 ClientMonitor client = mCurrentClient; 338 339 if ( !(client instanceof InternalRemovalClient) && !(client instanceof EnumerateClient) ) { 340 return; 341 } 342 client.onEnumerationResult(fingerId, groupId, remaining); 343 344 // All fingerprints in hardware for this user were enumerated 345 if (remaining == 0) { 346 mEnumeratingUserIds.poll(); 347 348 if (client instanceof InternalEnumerateClient) { 349 List<Fingerprint> enrolled = ((InternalEnumerateClient) client).getEnumeratedList(); 350 Slog.w(TAG, "Added " + enrolled.size() + " enumerated fingerprints for deletion"); 351 for (Fingerprint f : enrolled) { 352 mUnknownFingerprints.add(new UserFingerprint(f, client.getTargetUserId())); 353 } 354 } 355 356 removeClient(client); 357 358 if (!mEnumeratingUserIds.isEmpty()) { 359 enumerateNextUser(); 360 } else if (client instanceof InternalEnumerateClient) { 361 if (DEBUG) Slog.v(TAG, "Finished enumerating all users"); 362 // This will start a chain of InternalRemovalClients 363 cleanupUnknownFingerprints(); 364 } 365 } 366 } 367 368 protected void handleError(long deviceId, int error, int vendorCode) { 369 ClientMonitor client = mCurrentClient; 370 if (client instanceof InternalRemovalClient || client instanceof InternalEnumerateClient) { 371 resetEnumerateState(); 372 } 373 if (client != null && client.onError(error, vendorCode)) { 374 removeClient(client); 375 } 376 377 if (DEBUG) Slog.v(TAG, "handleError(client=" 378 + (client != null ? client.getOwnerString() : "null") + ", error = " + error + ")"); 379 // This is the magic code that starts the next client when the old client finishes. 380 if (error == FingerprintManager.FINGERPRINT_ERROR_CANCELED) { 381 mHandler.removeCallbacks(mResetClientState); 382 if (mPendingClient != null) { 383 if (DEBUG) Slog.v(TAG, "start pending client " + mPendingClient.getOwnerString()); 384 startClient(mPendingClient, false); 385 mPendingClient = null; 386 } 387 } else if (error == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) { 388 // If we get HW_UNAVAILABLE, try to connect again later... 389 Slog.w(TAG, "Got ERROR_HW_UNAVAILABLE; try reconnecting next client."); 390 synchronized (this) { 391 mDaemon = null; 392 mHalDeviceId = 0; 393 mCurrentUserId = UserHandle.USER_NULL; 394 } 395 } 396 } 397 398 protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) { 399 if (DEBUG) Slog.w(TAG, "Removed: fid=" + fingerId 400 + ", gid=" + groupId 401 + ", dev=" + deviceId 402 + ", rem=" + remaining); 403 404 ClientMonitor client = mCurrentClient; 405 if (client != null && client.onRemoved(fingerId, groupId, remaining)) { 406 removeClient(client); 407 // When the last fingerprint of a group is removed, update the authenticator id 408 if (!hasEnrolledFingerprints(groupId)) { 409 updateActiveGroup(groupId, null); 410 } 411 } 412 if (client instanceof InternalRemovalClient && !mUnknownFingerprints.isEmpty()) { 413 cleanupUnknownFingerprints(); 414 } else if (client instanceof InternalRemovalClient){ 415 resetEnumerateState(); 416 } 417 } 418 419 protected void handleAuthenticated(long deviceId, int fingerId, int groupId, 420 ArrayList<Byte> token) { 421 ClientMonitor client = mCurrentClient; 422 if (fingerId != 0) { 423 // Ugh... 424 final byte[] byteToken = new byte[token.size()]; 425 for (int i = 0; i < token.size(); i++) { 426 byteToken[i] = token.get(i); 427 } 428 // Send to Keystore 429 KeyStore.getInstance().addAuthToken(byteToken); 430 } 431 if (client != null && client.onAuthenticated(fingerId, groupId)) { 432 removeClient(client); 433 } 434 if (fingerId != 0) { 435 mPerformanceStats.accept++; 436 } else { 437 mPerformanceStats.reject++; 438 } 439 } 440 441 protected void handleAcquired(long deviceId, int acquiredInfo, int vendorCode) { 442 ClientMonitor client = mCurrentClient; 443 if (client != null && client.onAcquired(acquiredInfo, vendorCode)) { 444 removeClient(client); 445 } 446 if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE 447 && client instanceof AuthenticationClient) { 448 // ignore enrollment acquisitions or acquisitions when we're locked out 449 mPerformanceStats.acquire++; 450 } 451 } 452 453 protected void handleEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { 454 ClientMonitor client = mCurrentClient; 455 if (client != null && client.onEnrollResult(fingerId, groupId, remaining)) { 456 removeClient(client); 457 // When enrollment finishes, update this group's authenticator id, as the HAL has 458 // already generated a new authenticator id when the new fingerprint is enrolled. 459 updateActiveGroup(groupId, null); 460 } 461 } 462 463 private void userActivity() { 464 long now = SystemClock.uptimeMillis(); 465 mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); 466 } 467 468 void handleUserSwitching(int userId) { 469 updateActiveGroup(userId, null); 470 doFingerprintCleanup(userId); 471 } 472 473 private void removeClient(ClientMonitor client) { 474 if (client != null) { 475 client.destroy(); 476 if (client != mCurrentClient && mCurrentClient != null) { 477 Slog.w(TAG, "Unexpected client: " + client.getOwnerString() + "expected: " 478 + mCurrentClient != null ? mCurrentClient.getOwnerString() : "null"); 479 } 480 } 481 if (mCurrentClient != null) { 482 if (DEBUG) Slog.v(TAG, "Done with client: " + client.getOwnerString()); 483 mCurrentClient = null; 484 } 485 if (mPendingClient == null) { 486 notifyClientActiveCallbacks(false); 487 } 488 } 489 490 private int getLockoutMode() { 491 if (mFailedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) { 492 return AuthenticationClient.LOCKOUT_PERMANENT; 493 } else if (mFailedAttempts > 0 && mTimedLockoutCleared == false && 494 (mFailedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) { 495 return AuthenticationClient.LOCKOUT_TIMED; 496 } 497 return AuthenticationClient.LOCKOUT_NONE; 498 } 499 500 private void scheduleLockoutReset() { 501 mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, 502 SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS, getLockoutResetIntent()); 503 } 504 505 private void cancelLockoutReset() { 506 mAlarmManager.cancel(getLockoutResetIntent()); 507 } 508 509 private PendingIntent getLockoutResetIntent() { 510 return PendingIntent.getBroadcast(mContext, 0, 511 new Intent(ACTION_LOCKOUT_RESET), PendingIntent.FLAG_UPDATE_CURRENT); 512 } 513 514 public long startPreEnroll(IBinder token) { 515 IBiometricsFingerprint daemon = getFingerprintDaemon(); 516 if (daemon == null) { 517 Slog.w(TAG, "startPreEnroll: no fingerprint HAL!"); 518 return 0; 519 } 520 try { 521 return daemon.preEnroll(); 522 } catch (RemoteException e) { 523 Slog.e(TAG, "startPreEnroll failed", e); 524 } 525 return 0; 526 } 527 528 public int startPostEnroll(IBinder token) { 529 IBiometricsFingerprint daemon = getFingerprintDaemon(); 530 if (daemon == null) { 531 Slog.w(TAG, "startPostEnroll: no fingerprint HAL!"); 532 return 0; 533 } 534 try { 535 return daemon.postEnroll(); 536 } catch (RemoteException e) { 537 Slog.e(TAG, "startPostEnroll failed", e); 538 } 539 return 0; 540 } 541 542 /** 543 * Calls fingerprint HAL to switch states to the new task. If there's already a current task, 544 * it calls cancel() and sets mPendingClient to begin when the current task finishes 545 * ({@link FingerprintManager#FINGERPRINT_ERROR_CANCELED}). 546 * @param newClient the new client that wants to connect 547 * @param initiatedByClient true for authenticate, remove and enroll 548 */ 549 private void startClient(ClientMonitor newClient, boolean initiatedByClient) { 550 ClientMonitor currentClient = mCurrentClient; 551 if (currentClient != null) { 552 if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString()); 553 if (currentClient instanceof InternalEnumerateClient || 554 currentClient instanceof InternalRemovalClient) { 555 // This condition means we're currently running internal diagnostics to 556 // remove extra fingerprints in the hardware and/or the software 557 // TODO: design an escape hatch in case client never finishes 558 } 559 else { 560 currentClient.stop(initiatedByClient); 561 } 562 mPendingClient = newClient; 563 mHandler.removeCallbacks(mResetClientState); 564 mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT); 565 } else if (newClient != null) { 566 mCurrentClient = newClient; 567 if (DEBUG) Slog.v(TAG, "starting client " 568 + newClient.getClass().getSuperclass().getSimpleName() 569 + "(" + newClient.getOwnerString() + ")" 570 + ", initiatedByClient = " + initiatedByClient + ")"); 571 notifyClientActiveCallbacks(true); 572 573 newClient.start(); 574 } 575 } 576 577 void startRemove(IBinder token, int fingerId, int groupId, int userId, 578 IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) { 579 IBiometricsFingerprint daemon = getFingerprintDaemon(); 580 if (daemon == null) { 581 Slog.w(TAG, "startRemove: no fingerprint HAL!"); 582 return; 583 } 584 585 if (internal) { 586 Context context = getContext(); 587 InternalRemovalClient client = new InternalRemovalClient(context, mHalDeviceId, 588 token, receiver, fingerId, groupId, userId, restricted, 589 context.getOpPackageName()) { 590 @Override 591 public void notifyUserActivity() { 592 593 } 594 @Override 595 public IBiometricsFingerprint getFingerprintDaemon() { 596 return FingerprintService.this.getFingerprintDaemon(); 597 } 598 }; 599 startClient(client, true); 600 } 601 else { 602 RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token, 603 receiver, fingerId, groupId, userId, restricted, token.toString()) { 604 @Override 605 public void notifyUserActivity() { 606 FingerprintService.this.userActivity(); 607 } 608 609 @Override 610 public IBiometricsFingerprint getFingerprintDaemon() { 611 return FingerprintService.this.getFingerprintDaemon(); 612 } 613 }; 614 startClient(client, true); 615 } 616 } 617 618 void startEnumerate(IBinder token, int userId, 619 IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) { 620 IBiometricsFingerprint daemon = getFingerprintDaemon(); 621 if (daemon == null) { 622 Slog.w(TAG, "startEnumerate: no fingerprint HAL!"); 623 return; 624 } 625 if (internal) { 626 List<Fingerprint> enrolledList = getEnrolledFingerprints(userId); 627 Context context = getContext(); 628 InternalEnumerateClient client = new InternalEnumerateClient(context, mHalDeviceId, 629 token, receiver, userId, userId, restricted, context.getOpPackageName(), 630 enrolledList) { 631 @Override 632 public void notifyUserActivity() { 633 634 } 635 636 @Override 637 public IBiometricsFingerprint getFingerprintDaemon() { 638 return FingerprintService.this.getFingerprintDaemon(); 639 } 640 }; 641 startClient(client, true); 642 } 643 else { 644 EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token, 645 receiver, userId, userId, restricted, token.toString()) { 646 @Override 647 public void notifyUserActivity() { 648 FingerprintService.this.userActivity(); 649 } 650 651 @Override 652 public IBiometricsFingerprint getFingerprintDaemon() { 653 return FingerprintService.this.getFingerprintDaemon(); 654 } 655 }; 656 startClient(client, true); 657 } 658 } 659 660 public List<Fingerprint> getEnrolledFingerprints(int userId) { 661 return mFingerprintUtils.getFingerprintsForUser(mContext, userId); 662 } 663 664 public boolean hasEnrolledFingerprints(int userId) { 665 if (userId != UserHandle.getCallingUserId()) { 666 checkPermission(INTERACT_ACROSS_USERS); 667 } 668 return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0; 669 } 670 671 boolean hasPermission(String permission) { 672 return getContext().checkCallingOrSelfPermission(permission) 673 == PackageManager.PERMISSION_GRANTED; 674 } 675 676 void checkPermission(String permission) { 677 getContext().enforceCallingOrSelfPermission(permission, 678 "Must have " + permission + " permission."); 679 } 680 681 int getEffectiveUserId(int userId) { 682 UserManager um = UserManager.get(mContext); 683 if (um != null) { 684 final long callingIdentity = Binder.clearCallingIdentity(); 685 userId = um.getCredentialOwnerProfile(userId); 686 Binder.restoreCallingIdentity(callingIdentity); 687 } else { 688 Slog.e(TAG, "Unable to acquire UserManager"); 689 } 690 return userId; 691 } 692 693 boolean isCurrentUserOrProfile(int userId) { 694 UserManager um = UserManager.get(mContext); 695 if (um == null) { 696 Slog.e(TAG, "Unable to acquire UserManager"); 697 return false; 698 } 699 700 final long token = Binder.clearCallingIdentity(); 701 try { 702 // Allow current user or profiles of the current user... 703 for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) { 704 if (profileId == userId) { 705 return true; 706 } 707 } 708 } finally { 709 Binder.restoreCallingIdentity(token); 710 } 711 712 return false; 713 } 714 715 private boolean isForegroundActivity(int uid, int pid) { 716 try { 717 List<RunningAppProcessInfo> procs = 718 ActivityManager.getService().getRunningAppProcesses(); 719 int N = procs.size(); 720 for (int i = 0; i < N; i++) { 721 RunningAppProcessInfo proc = procs.get(i); 722 if (proc.pid == pid && proc.uid == uid 723 && proc.importance == IMPORTANCE_FOREGROUND) { 724 return true; 725 } 726 } 727 } catch (RemoteException e) { 728 Slog.w(TAG, "am.getRunningAppProcesses() failed"); 729 } 730 return false; 731 } 732 733 /** 734 * @param opPackageName name of package for caller 735 * @param requireForeground only allow this call while app is in the foreground 736 * @return true if caller can use fingerprint API 737 */ 738 private boolean canUseFingerprint(String opPackageName, boolean requireForeground, int uid, 739 int pid, int userId) { 740 checkPermission(USE_FINGERPRINT); 741 if (isKeyguard(opPackageName)) { 742 return true; // Keyguard is always allowed 743 } 744 if (!isCurrentUserOrProfile(userId)) { 745 Slog.w(TAG,"Rejecting " + opPackageName + " ; not a current user or profile"); 746 return false; 747 } 748 if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName) 749 != AppOpsManager.MODE_ALLOWED) { 750 Slog.w(TAG, "Rejecting " + opPackageName + " ; permission denied"); 751 return false; 752 } 753 if (requireForeground && !(isForegroundActivity(uid, pid) || currentClient(opPackageName))){ 754 Slog.w(TAG, "Rejecting " + opPackageName + " ; not in foreground"); 755 return false; 756 } 757 return true; 758 } 759 760 /** 761 * @param opPackageName package of the caller 762 * @return true if this is the same client currently using fingerprint 763 */ 764 private boolean currentClient(String opPackageName) { 765 return mCurrentClient != null && mCurrentClient.getOwnerString().equals(opPackageName); 766 } 767 768 /** 769 * @param clientPackage 770 * @return true if this is keyguard package 771 */ 772 private boolean isKeyguard(String clientPackage) { 773 return mKeyguardPackage.equals(clientPackage); 774 } 775 776 private void addLockoutResetMonitor(FingerprintServiceLockoutResetMonitor monitor) { 777 if (!mLockoutMonitors.contains(monitor)) { 778 mLockoutMonitors.add(monitor); 779 } 780 } 781 782 private void removeLockoutResetCallback( 783 FingerprintServiceLockoutResetMonitor monitor) { 784 mLockoutMonitors.remove(monitor); 785 } 786 787 private void notifyLockoutResetMonitors() { 788 for (int i = 0; i < mLockoutMonitors.size(); i++) { 789 mLockoutMonitors.get(i).sendLockoutReset(); 790 } 791 } 792 793 private void notifyClientActiveCallbacks(boolean isActive) { 794 List<IFingerprintClientActiveCallback> callbacks = mClientActiveCallbacks; 795 for (int i = 0; i < callbacks.size(); i++) { 796 try { 797 callbacks.get(i).onClientActiveChanged(isActive); 798 } catch (RemoteException re) { 799 // If the remote is dead, stop notifying it 800 mClientActiveCallbacks.remove(callbacks.get(i)); 801 } 802 } 803 } 804 805 private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId, 806 IFingerprintServiceReceiver receiver, int flags, boolean restricted, 807 String opPackageName) { 808 updateActiveGroup(groupId, opPackageName); 809 810 if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")"); 811 812 AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token, 813 receiver, mCurrentUserId, groupId, opId, restricted, opPackageName) { 814 @Override 815 public int handleFailedAttempt() { 816 mFailedAttempts++; 817 mTimedLockoutCleared = false; 818 final int lockoutMode = getLockoutMode(); 819 if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) { 820 mPerformanceStats.permanentLockout++; 821 } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) { 822 mPerformanceStats.lockout++; 823 } 824 825 // Failing multiple times will continue to push out the lockout time 826 if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) { 827 scheduleLockoutReset(); 828 return lockoutMode; 829 } 830 return AuthenticationClient.LOCKOUT_NONE; 831 } 832 833 @Override 834 public void resetFailedAttempts() { 835 FingerprintService.this.resetFailedAttempts(true /* clearAttemptCounter */); 836 } 837 838 @Override 839 public void notifyUserActivity() { 840 FingerprintService.this.userActivity(); 841 } 842 843 @Override 844 public IBiometricsFingerprint getFingerprintDaemon() { 845 return FingerprintService.this.getFingerprintDaemon(); 846 } 847 }; 848 849 int lockoutMode = getLockoutMode(); 850 if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) { 851 Slog.v(TAG, "In lockout mode(" + lockoutMode + 852 ") ; disallowing authentication"); 853 int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ? 854 FingerprintManager.FINGERPRINT_ERROR_LOCKOUT : 855 FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT; 856 if (!client.onError(errorCode, 0 /* vendorCode */)) { 857 Slog.w(TAG, "Cannot send permanent lockout message to client"); 858 } 859 return; 860 } 861 startClient(client, true /* initiatedByClient */); 862 } 863 864 private void startEnrollment(IBinder token, byte [] cryptoToken, int userId, 865 IFingerprintServiceReceiver receiver, int flags, boolean restricted, 866 String opPackageName) { 867 updateActiveGroup(userId, opPackageName); 868 869 final int groupId = userId; // default group for fingerprint enrollment 870 871 EnrollClient client = new EnrollClient(getContext(), mHalDeviceId, token, receiver, 872 userId, groupId, cryptoToken, restricted, opPackageName) { 873 874 @Override 875 public IBiometricsFingerprint getFingerprintDaemon() { 876 return FingerprintService.this.getFingerprintDaemon(); 877 } 878 879 @Override 880 public void notifyUserActivity() { 881 FingerprintService.this.userActivity(); 882 } 883 }; 884 startClient(client, true /* initiatedByClient */); 885 } 886 887 // attempt counter should only be cleared when Keyguard goes away or when 888 // a fingerprint is successfully authenticated 889 protected void resetFailedAttempts(boolean clearAttemptCounter) { 890 if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) { 891 Slog.v(TAG, "Reset fingerprint lockout, clearAttemptCounter=" + clearAttemptCounter); 892 } 893 if (clearAttemptCounter) { 894 mFailedAttempts = 0; 895 } 896 mTimedLockoutCleared = true; 897 // If we're asked to reset failed attempts externally (i.e. from Keyguard), 898 // the alarm might still be pending; remove it. 899 cancelLockoutReset(); 900 notifyLockoutResetMonitors(); 901 } 902 903 private class FingerprintServiceLockoutResetMonitor { 904 905 private static final long WAKELOCK_TIMEOUT_MS = 2000; 906 private final IFingerprintServiceLockoutResetCallback mCallback; 907 private final WakeLock mWakeLock; 908 909 public FingerprintServiceLockoutResetMonitor( 910 IFingerprintServiceLockoutResetCallback callback) { 911 mCallback = callback; 912 mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 913 "lockout reset callback"); 914 } 915 916 public void sendLockoutReset() { 917 if (mCallback != null) { 918 try { 919 mWakeLock.acquire(WAKELOCK_TIMEOUT_MS); 920 mCallback.onLockoutReset(mHalDeviceId, new IRemoteCallback.Stub() { 921 922 @Override 923 public void sendResult(Bundle data) throws RemoteException { 924 mWakeLock.release(); 925 } 926 }); 927 } catch (DeadObjectException e) { 928 Slog.w(TAG, "Death object while invoking onLockoutReset: ", e); 929 mHandler.post(mRemoveCallbackRunnable); 930 } catch (RemoteException e) { 931 Slog.w(TAG, "Failed to invoke onLockoutReset: ", e); 932 } 933 } 934 } 935 936 private final Runnable mRemoveCallbackRunnable = new Runnable() { 937 @Override 938 public void run() { 939 if (mWakeLock.isHeld()) { 940 mWakeLock.release(); 941 } 942 removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this); 943 } 944 }; 945 } 946 947 private IBiometricsFingerprintClientCallback mDaemonCallback = 948 new IBiometricsFingerprintClientCallback.Stub() { 949 950 @Override 951 public void onEnrollResult(final long deviceId, final int fingerId, final int groupId, 952 final int remaining) { 953 mHandler.post(new Runnable() { 954 @Override 955 public void run() { 956 handleEnrollResult(deviceId, fingerId, groupId, remaining); 957 } 958 }); 959 } 960 961 @Override 962 public void onAcquired(final long deviceId, final int acquiredInfo, final int vendorCode) { 963 mHandler.post(new Runnable() { 964 @Override 965 public void run() { 966 handleAcquired(deviceId, acquiredInfo, vendorCode); 967 } 968 }); 969 } 970 971 @Override 972 public void onAuthenticated(final long deviceId, final int fingerId, final int groupId, 973 ArrayList<Byte> token) { 974 mHandler.post(new Runnable() { 975 @Override 976 public void run() { 977 handleAuthenticated(deviceId, fingerId, groupId, token); 978 } 979 }); 980 } 981 982 @Override 983 public void onError(final long deviceId, final int error, final int vendorCode) { 984 mHandler.post(new Runnable() { 985 @Override 986 public void run() { 987 handleError(deviceId, error, vendorCode); 988 } 989 }); 990 } 991 992 @Override 993 public void onRemoved(final long deviceId, final int fingerId, final int groupId, final int remaining) { 994 mHandler.post(new Runnable() { 995 @Override 996 public void run() { 997 handleRemoved(deviceId, fingerId, groupId, remaining); 998 } 999 }); 1000 } 1001 1002 @Override 1003 public void onEnumerate(final long deviceId, final int fingerId, final int groupId, 1004 final int remaining) { 1005 mHandler.post(new Runnable() { 1006 @Override 1007 public void run() { 1008 handleEnumerate(deviceId, fingerId, groupId, remaining); 1009 } 1010 }); 1011 } 1012 }; 1013 1014 private final class FingerprintServiceWrapper extends IFingerprintService.Stub { 1015 @Override // Binder call 1016 public long preEnroll(IBinder token) { 1017 checkPermission(MANAGE_FINGERPRINT); 1018 return startPreEnroll(token); 1019 } 1020 1021 @Override // Binder call 1022 public int postEnroll(IBinder token) { 1023 checkPermission(MANAGE_FINGERPRINT); 1024 return startPostEnroll(token); 1025 } 1026 1027 @Override // Binder call 1028 public void enroll(final IBinder token, final byte[] cryptoToken, final int userId, 1029 final IFingerprintServiceReceiver receiver, final int flags, 1030 final String opPackageName) { 1031 checkPermission(MANAGE_FINGERPRINT); 1032 final int limit = mContext.getResources().getInteger( 1033 com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser); 1034 1035 final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size(); 1036 if (enrolled >= limit) { 1037 Slog.w(TAG, "Too many fingerprints registered"); 1038 return; 1039 } 1040 1041 // Group ID is arbitrarily set to parent profile user ID. It just represents 1042 // the default fingerprints for the user. 1043 if (!isCurrentUserOrProfile(userId)) { 1044 return; 1045 } 1046 1047 final boolean restricted = isRestricted(); 1048 mHandler.post(new Runnable() { 1049 @Override 1050 public void run() { 1051 startEnrollment(token, cryptoToken, userId, receiver, flags, 1052 restricted, opPackageName); 1053 } 1054 }); 1055 } 1056 1057 private boolean isRestricted() { 1058 // Only give privileged apps (like Settings) access to fingerprint info 1059 final boolean restricted = !hasPermission(MANAGE_FINGERPRINT); 1060 return restricted; 1061 } 1062 1063 @Override // Binder call 1064 public void cancelEnrollment(final IBinder token) { 1065 checkPermission(MANAGE_FINGERPRINT); 1066 mHandler.post(new Runnable() { 1067 @Override 1068 public void run() { 1069 ClientMonitor client = mCurrentClient; 1070 if (client instanceof EnrollClient && client.getToken() == token) { 1071 client.stop(client.getToken() == token); 1072 } 1073 } 1074 }); 1075 } 1076 1077 @Override // Binder call 1078 public void authenticate(final IBinder token, final long opId, final int groupId, 1079 final IFingerprintServiceReceiver receiver, final int flags, 1080 final String opPackageName) { 1081 final int callingUid = Binder.getCallingUid(); 1082 final int callingUserId = UserHandle.getCallingUserId(); 1083 final int pid = Binder.getCallingPid(); 1084 final boolean restricted = isRestricted(); 1085 mHandler.post(new Runnable() { 1086 @Override 1087 public void run() { 1088 if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, 1089 callingUid, pid, callingUserId)) { 1090 if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName); 1091 return; 1092 } 1093 1094 MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0); 1095 1096 // Get performance stats object for this user. 1097 HashMap<Integer, PerformanceStats> pmap 1098 = (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap; 1099 PerformanceStats stats = pmap.get(mCurrentUserId); 1100 if (stats == null) { 1101 stats = new PerformanceStats(); 1102 pmap.put(mCurrentUserId, stats); 1103 } 1104 mPerformanceStats = stats; 1105 1106 startAuthentication(token, opId, callingUserId, groupId, receiver, 1107 flags, restricted, opPackageName); 1108 } 1109 }); 1110 } 1111 1112 @Override // Binder call 1113 public void cancelAuthentication(final IBinder token, final String opPackageName) { 1114 final int uid = Binder.getCallingUid(); 1115 final int pid = Binder.getCallingPid(); 1116 final int callingUserId = UserHandle.getCallingUserId(); 1117 mHandler.post(new Runnable() { 1118 @Override 1119 public void run() { 1120 if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, uid, pid, 1121 callingUserId)) { 1122 if (DEBUG) Slog.v(TAG, "cancelAuthentication(): reject " + opPackageName); 1123 } else { 1124 ClientMonitor client = mCurrentClient; 1125 if (client instanceof AuthenticationClient) { 1126 if (client.getToken() == token) { 1127 if (DEBUG) Slog.v(TAG, "stop client " + client.getOwnerString()); 1128 client.stop(client.getToken() == token); 1129 } else { 1130 if (DEBUG) Slog.v(TAG, "can't stop client " 1131 + client.getOwnerString() + " since tokens don't match"); 1132 } 1133 } else if (client != null) { 1134 if (DEBUG) Slog.v(TAG, "can't cancel non-authenticating client " 1135 + client.getOwnerString()); 1136 } 1137 } 1138 } 1139 }); 1140 } 1141 1142 @Override // Binder call 1143 public void setActiveUser(final int userId) { 1144 checkPermission(MANAGE_FINGERPRINT); 1145 mHandler.post(new Runnable() { 1146 @Override 1147 public void run() { 1148 updateActiveGroup(userId, null); 1149 } 1150 }); 1151 } 1152 1153 @Override // Binder call 1154 public void remove(final IBinder token, final int fingerId, final int groupId, 1155 final int userId, final IFingerprintServiceReceiver receiver) { 1156 checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission 1157 final boolean restricted = isRestricted(); 1158 mHandler.post(new Runnable() { 1159 @Override 1160 public void run() { 1161 startRemove(token, fingerId, groupId, userId, receiver, 1162 restricted, false /* internal */); 1163 } 1164 }); 1165 } 1166 1167 @Override // Binder call 1168 public void enumerate(final IBinder token, final int userId, 1169 final IFingerprintServiceReceiver receiver) { 1170 checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission 1171 final boolean restricted = isRestricted(); 1172 mHandler.post(new Runnable() { 1173 @Override 1174 public void run() { 1175 startEnumerate(token, userId, receiver, restricted, false /* internal */); 1176 } 1177 }); 1178 } 1179 1180 @Override // Binder call 1181 public boolean isHardwareDetected(long deviceId, String opPackageName) { 1182 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 1183 Binder.getCallingUid(), Binder.getCallingPid(), 1184 UserHandle.getCallingUserId())) { 1185 return false; 1186 } 1187 1188 final long token = Binder.clearCallingIdentity(); 1189 try { 1190 IBiometricsFingerprint daemon = getFingerprintDaemon(); 1191 return daemon != null && mHalDeviceId != 0; 1192 } finally { 1193 Binder.restoreCallingIdentity(token); 1194 } 1195 } 1196 1197 @Override // Binder call 1198 public void rename(final int fingerId, final int groupId, final String name) { 1199 checkPermission(MANAGE_FINGERPRINT); 1200 if (!isCurrentUserOrProfile(groupId)) { 1201 return; 1202 } 1203 mHandler.post(new Runnable() { 1204 @Override 1205 public void run() { 1206 mFingerprintUtils.renameFingerprintForUser(mContext, fingerId, 1207 groupId, name); 1208 } 1209 }); 1210 } 1211 1212 @Override // Binder call 1213 public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) { 1214 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 1215 Binder.getCallingUid(), Binder.getCallingPid(), 1216 UserHandle.getCallingUserId())) { 1217 return Collections.emptyList(); 1218 } 1219 1220 return FingerprintService.this.getEnrolledFingerprints(userId); 1221 } 1222 1223 @Override // Binder call 1224 public boolean hasEnrolledFingerprints(int userId, String opPackageName) { 1225 if (!canUseFingerprint(opPackageName, false /* foregroundOnly */, 1226 Binder.getCallingUid(), Binder.getCallingPid(), 1227 UserHandle.getCallingUserId())) { 1228 return false; 1229 } 1230 1231 return FingerprintService.this.hasEnrolledFingerprints(userId); 1232 } 1233 1234 @Override // Binder call 1235 public long getAuthenticatorId(String opPackageName) { 1236 // In this method, we're not checking whether the caller is permitted to use fingerprint 1237 // API because current authenticator ID is leaked (in a more contrived way) via Android 1238 // Keystore (android.security.keystore package): the user of that API can create a key 1239 // which requires fingerprint authentication for its use, and then query the key's 1240 // characteristics (hidden API) which returns, among other things, fingerprint 1241 // authenticator ID which was active at key creation time. 1242 // 1243 // Reason: The part of Android Keystore which runs inside an app's process invokes this 1244 // method in certain cases. Those cases are not always where the developer demonstrates 1245 // explicit intent to use fingerprint functionality. Thus, to avoiding throwing an 1246 // unexpected SecurityException this method does not check whether its caller is 1247 // permitted to use fingerprint API. 1248 // 1249 // The permission check should be restored once Android Keystore no longer invokes this 1250 // method from inside app processes. 1251 1252 return FingerprintService.this.getAuthenticatorId(opPackageName); 1253 } 1254 1255 @Override // Binder call 1256 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1257 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1258 1259 final long ident = Binder.clearCallingIdentity(); 1260 try { 1261 if (args.length > 0 && "--proto".equals(args[0])) { 1262 dumpProto(fd); 1263 } else { 1264 dumpInternal(pw); 1265 } 1266 } finally { 1267 Binder.restoreCallingIdentity(ident); 1268 } 1269 } 1270 1271 @Override // Binder call 1272 public void resetTimeout(byte [] token) { 1273 checkPermission(RESET_FINGERPRINT_LOCKOUT); 1274 // TODO: confirm security token when we move timeout management into the HAL layer. 1275 mHandler.post(mResetFailedAttemptsRunnable); 1276 } 1277 1278 @Override 1279 public void addLockoutResetCallback(final IFingerprintServiceLockoutResetCallback callback) 1280 throws RemoteException { 1281 mHandler.post(new Runnable() { 1282 @Override 1283 public void run() { 1284 addLockoutResetMonitor( 1285 new FingerprintServiceLockoutResetMonitor(callback)); 1286 } 1287 }); 1288 } 1289 1290 @Override 1291 public boolean isClientActive() { 1292 checkPermission(MANAGE_FINGERPRINT); 1293 synchronized(FingerprintService.this) { 1294 return (mCurrentClient != null) || (mPendingClient != null); 1295 } 1296 } 1297 1298 @Override 1299 public void addClientActiveCallback(IFingerprintClientActiveCallback callback) { 1300 checkPermission(MANAGE_FINGERPRINT); 1301 mClientActiveCallbacks.add(callback); 1302 } 1303 1304 @Override 1305 public void removeClientActiveCallback(IFingerprintClientActiveCallback callback) { 1306 checkPermission(MANAGE_FINGERPRINT); 1307 mClientActiveCallbacks.remove(callback); 1308 } 1309 } 1310 1311 private void dumpInternal(PrintWriter pw) { 1312 JSONObject dump = new JSONObject(); 1313 try { 1314 dump.put("service", "Fingerprint Manager"); 1315 1316 JSONArray sets = new JSONArray(); 1317 for (UserInfo user : UserManager.get(getContext()).getUsers()) { 1318 final int userId = user.getUserHandle().getIdentifier(); 1319 final int N = mFingerprintUtils.getFingerprintsForUser(mContext, userId).size(); 1320 PerformanceStats stats = mPerformanceMap.get(userId); 1321 PerformanceStats cryptoStats = mCryptoPerformanceMap.get(userId); 1322 JSONObject set = new JSONObject(); 1323 set.put("id", userId); 1324 set.put("count", N); 1325 set.put("accept", (stats != null) ? stats.accept : 0); 1326 set.put("reject", (stats != null) ? stats.reject : 0); 1327 set.put("acquire", (stats != null) ? stats.acquire : 0); 1328 set.put("lockout", (stats != null) ? stats.lockout : 0); 1329 set.put("permanentLockout", (stats != null) ? stats.permanentLockout : 0); 1330 // cryptoStats measures statistics about secure fingerprint transactions 1331 // (e.g. to unlock password storage, make secure purchases, etc.) 1332 set.put("acceptCrypto", (cryptoStats != null) ? cryptoStats.accept : 0); 1333 set.put("rejectCrypto", (cryptoStats != null) ? cryptoStats.reject : 0); 1334 set.put("acquireCrypto", (cryptoStats != null) ? cryptoStats.acquire : 0); 1335 set.put("lockoutCrypto", (cryptoStats != null) ? cryptoStats.lockout : 0); 1336 sets.put(set); 1337 } 1338 1339 dump.put("prints", sets); 1340 } catch (JSONException e) { 1341 Slog.e(TAG, "dump formatting failure", e); 1342 } 1343 pw.println(dump); 1344 } 1345 1346 private void dumpProto(FileDescriptor fd) { 1347 final ProtoOutputStream proto = new ProtoOutputStream(fd); 1348 for (UserInfo user : UserManager.get(getContext()).getUsers()) { 1349 final int userId = user.getUserHandle().getIdentifier(); 1350 1351 final long userToken = proto.start(FingerprintServiceDumpProto.USERS); 1352 1353 proto.write(FingerprintUserStatsProto.USER_ID, userId); 1354 proto.write(FingerprintUserStatsProto.NUM_FINGERPRINTS, 1355 mFingerprintUtils.getFingerprintsForUser(mContext, userId).size()); 1356 1357 // Normal fingerprint authentications (e.g. lockscreen) 1358 final PerformanceStats normal = mPerformanceMap.get(userId); 1359 if (normal != null) { 1360 final long countsToken = proto.start(FingerprintUserStatsProto.NORMAL); 1361 proto.write(FingerprintActionStatsProto.ACCEPT, normal.accept); 1362 proto.write(FingerprintActionStatsProto.REJECT, normal.reject); 1363 proto.write(FingerprintActionStatsProto.ACQUIRE, normal.acquire); 1364 proto.write(FingerprintActionStatsProto.LOCKOUT, normal.lockout); 1365 proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, normal.lockout); 1366 proto.end(countsToken); 1367 } 1368 1369 // Statistics about secure fingerprint transactions (e.g. to unlock password 1370 // storage, make secure purchases, etc.) 1371 final PerformanceStats crypto = mCryptoPerformanceMap.get(userId); 1372 if (crypto != null) { 1373 final long countsToken = proto.start(FingerprintUserStatsProto.CRYPTO); 1374 proto.write(FingerprintActionStatsProto.ACCEPT, crypto.accept); 1375 proto.write(FingerprintActionStatsProto.REJECT, crypto.reject); 1376 proto.write(FingerprintActionStatsProto.ACQUIRE, crypto.acquire); 1377 proto.write(FingerprintActionStatsProto.LOCKOUT, crypto.lockout); 1378 proto.write(FingerprintActionStatsProto.LOCKOUT_PERMANENT, crypto.lockout); 1379 proto.end(countsToken); 1380 } 1381 1382 proto.end(userToken); 1383 } 1384 proto.flush(); 1385 } 1386 1387 @Override 1388 public void onStart() { 1389 publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); 1390 SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart"); 1391 listenForUserSwitches(); 1392 } 1393 1394 private void updateActiveGroup(int userId, String clientPackage) { 1395 IBiometricsFingerprint daemon = getFingerprintDaemon(); 1396 1397 if (daemon != null) { 1398 try { 1399 userId = getUserOrWorkProfileId(clientPackage, userId); 1400 if (userId != mCurrentUserId) { 1401 final File systemDir = Environment.getUserSystemDirectory(userId); 1402 final File fpDir = new File(systemDir, FP_DATA_DIR); 1403 if (!fpDir.exists()) { 1404 if (!fpDir.mkdir()) { 1405 Slog.v(TAG, "Cannot make directory: " + fpDir.getAbsolutePath()); 1406 return; 1407 } 1408 // Calling mkdir() from this process will create a directory with our 1409 // permissions (inherited from the containing dir). This command fixes 1410 // the label. 1411 if (!SELinux.restorecon(fpDir)) { 1412 Slog.w(TAG, "Restorecons failed. Directory will have wrong label."); 1413 return; 1414 } 1415 } 1416 daemon.setActiveGroup(userId, fpDir.getAbsolutePath()); 1417 mCurrentUserId = userId; 1418 } 1419 mAuthenticatorIds.put(userId, 1420 hasEnrolledFingerprints(userId) ? daemon.getAuthenticatorId() : 0L); 1421 } catch (RemoteException e) { 1422 Slog.e(TAG, "Failed to setActiveGroup():", e); 1423 } 1424 } 1425 } 1426 1427 /** 1428 * @param clientPackage the package of the caller 1429 * @return the profile id 1430 */ 1431 private int getUserOrWorkProfileId(String clientPackage, int userId) { 1432 if (!isKeyguard(clientPackage) && isWorkProfile(userId)) { 1433 return userId; 1434 } 1435 return getEffectiveUserId(userId); 1436 } 1437 1438 /** 1439 * @param userId 1440 * @return true if this is a work profile 1441 */ 1442 private boolean isWorkProfile(int userId) { 1443 UserInfo userInfo = null; 1444 final long token = Binder.clearCallingIdentity(); 1445 try { 1446 userInfo = mUserManager.getUserInfo(userId); 1447 } finally { 1448 Binder.restoreCallingIdentity(token); 1449 } 1450 return userInfo != null && userInfo.isManagedProfile(); 1451 } 1452 1453 private void listenForUserSwitches() { 1454 try { 1455 ActivityManager.getService().registerUserSwitchObserver( 1456 new SynchronousUserSwitchObserver() { 1457 @Override 1458 public void onUserSwitching(int newUserId) throws RemoteException { 1459 mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */) 1460 .sendToTarget(); 1461 } 1462 }, TAG); 1463 } catch (RemoteException e) { 1464 Slog.w(TAG, "Failed to listen for user switching event" ,e); 1465 } 1466 } 1467 1468 /*** 1469 * @param opPackageName the name of the calling package 1470 * @return authenticator id for the calling user 1471 */ 1472 public long getAuthenticatorId(String opPackageName) { 1473 final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId()); 1474 return mAuthenticatorIds.getOrDefault(userId, 0L); 1475 } 1476} 1477