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 android.app.ActivityManager; 20 import android.app.ActivityManagerNative; 21 import android.app.AppOpsManager; 22 import android.app.IUserSwitchObserver; 23 import android.content.ContentResolver; 24 import android.content.Context; 25 import android.content.pm.PackageManager; 26 import android.content.pm.UserInfo; 27 import android.os.Binder; 28 import android.os.Environment; 29 import android.os.Handler; 30 import android.os.IBinder; 31 import android.os.IRemoteCallback; 32 import android.os.Looper; 33 import android.os.MessageQueue; 34 import android.os.PowerManager; 35 import android.os.RemoteException; 36 import android.os.SELinux; 37 import android.os.ServiceManager; 38 import android.os.SystemClock; 39 import android.os.UserHandle; 40 import android.os.UserManager; 41 import android.util.Slog; 42 43 import com.android.server.SystemService; 44 45 import android.hardware.fingerprint.Fingerprint; 46 import android.hardware.fingerprint.FingerprintManager; 47 import android.hardware.fingerprint.IFingerprintService; 48 import android.hardware.fingerprint.IFingerprintDaemon; 49 import android.hardware.fingerprint.IFingerprintDaemonCallback; 50 import android.hardware.fingerprint.IFingerprintServiceReceiver; 51 52 import static android.Manifest.permission.MANAGE_FINGERPRINT; 53 import static android.Manifest.permission.USE_FINGERPRINT; 54 55 import java.io.File; 56 import java.util.ArrayList; 57 import java.util.Arrays; 58 import java.util.Collections; 59 import java.util.List; 60 import java.util.NoSuchElementException; 61 62 /** 63 * A service to manage multiple clients that want to access the fingerprint HAL API. 64 * The service is responsible for maintaining a list of clients and dispatching all 65 * fingerprint -related events. 66 * 67 * @hide 68 */ 69 public class FingerprintService extends SystemService implements IBinder.DeathRecipient { 70 private static final String TAG = "FingerprintService"; 71 private static final boolean DEBUG = true; 72 private static final String FP_DATA_DIR = "fpdata"; 73 private static final String FINGERPRINTD = "android.hardware.fingerprint.IFingerprintDaemon"; 74 private static final int MSG_USER_SWITCHING = 10; 75 private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute 76 77 private ClientMonitor mAuthClient = null; 78 private ClientMonitor mEnrollClient = null; 79 private ClientMonitor mRemoveClient = null; 80 private final AppOpsManager mAppOps; 81 82 private static final long MS_PER_SEC = 1000; 83 private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000; 84 private static final int MAX_FAILED_ATTEMPTS = 5; 85 private static final int FINGERPRINT_ACQUIRED_GOOD = 0; 86 87 Handler mHandler = new Handler() { 88 @Override 89 public void handleMessage(android.os.Message msg) { 90 switch (msg.what) { 91 case MSG_USER_SWITCHING: 92 handleUserSwitching(msg.arg1); 93 break; 94 95 default: 96 Slog.w(TAG, "Unknown message:" + msg.what); 97 } 98 } 99 }; 100 101 private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance(); 102 private Context mContext; 103 private long mHalDeviceId; 104 private int mFailedAttempts; 105 private IFingerprintDaemon mDaemon; 106 private PowerManager mPowerManager; 107 108 private final Runnable mLockoutReset = new Runnable() { 109 @Override 110 public void run() { 111 resetFailedAttempts(); 112 } 113 }; 114 FingerprintService(Context context)115 public FingerprintService(Context context) { 116 super(context); 117 mContext = context; 118 mAppOps = context.getSystemService(AppOpsManager.class); 119 mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 120 } 121 122 @Override binderDied()123 public void binderDied() { 124 Slog.v(TAG, "fingerprintd died"); 125 mDaemon = null; 126 dispatchError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); 127 } 128 getFingerprintDaemon()129 public IFingerprintDaemon getFingerprintDaemon() { 130 if (mDaemon == null) { 131 mDaemon = IFingerprintDaemon.Stub.asInterface(ServiceManager.getService(FINGERPRINTD)); 132 if (mDaemon != null) { 133 try { 134 mDaemon.asBinder().linkToDeath(this, 0); 135 mDaemon.init(mDaemonCallback); 136 mHalDeviceId = mDaemon.openHal(); 137 if (mHalDeviceId != 0) { 138 updateActiveGroup(ActivityManager.getCurrentUser()); 139 } else { 140 Slog.w(TAG, "Failed to open Fingerprint HAL!"); 141 mDaemon = null; 142 } 143 } catch (RemoteException e) { 144 Slog.e(TAG, "Failed to open fingeprintd HAL", e); 145 mDaemon = null; // try again later! 146 } 147 } else { 148 Slog.w(TAG, "fingerprint service not available"); 149 } 150 } 151 return mDaemon; 152 } 153 dispatchEnumerate(long deviceId, int[] fingerIds, int[] groupIds)154 protected void dispatchEnumerate(long deviceId, int[] fingerIds, int[] groupIds) { 155 if (fingerIds.length != groupIds.length) { 156 Slog.w(TAG, "fingerIds and groupIds differ in length: f[]=" 157 + fingerIds + ", g[]=" + groupIds); 158 return; 159 } 160 if (DEBUG) Slog.w(TAG, "Enumerate: f[]=" + fingerIds + ", g[]=" + groupIds); 161 // TODO: update fingerprint/name pairs 162 } 163 dispatchRemoved(long deviceId, int fingerId, int groupId)164 protected void dispatchRemoved(long deviceId, int fingerId, int groupId) { 165 final ClientMonitor client = mRemoveClient; 166 if (fingerId != 0) { 167 removeTemplateForUser(mRemoveClient, fingerId); 168 } 169 if (client != null && client.sendRemoved(fingerId, groupId)) { 170 removeClient(mRemoveClient); 171 } 172 } 173 dispatchError(long deviceId, int error)174 protected void dispatchError(long deviceId, int error) { 175 if (mEnrollClient != null) { 176 final IBinder token = mEnrollClient.token; 177 if (mEnrollClient.sendError(error)) { 178 stopEnrollment(token, false); 179 } 180 } else if (mAuthClient != null) { 181 final IBinder token = mAuthClient.token; 182 if (mAuthClient.sendError(error)) { 183 stopAuthentication(token, false); 184 } 185 } else if (mRemoveClient != null) { 186 if (mRemoveClient.sendError(error)) removeClient(mRemoveClient); 187 } 188 } 189 dispatchAuthenticated(long deviceId, int fingerId, int groupId)190 protected void dispatchAuthenticated(long deviceId, int fingerId, int groupId) { 191 if (mAuthClient != null) { 192 final IBinder token = mAuthClient.token; 193 if (mAuthClient.sendAuthenticated(fingerId, groupId)) { 194 stopAuthentication(token, false); 195 removeClient(mAuthClient); 196 } 197 } 198 } 199 dispatchAcquired(long deviceId, int acquiredInfo)200 protected void dispatchAcquired(long deviceId, int acquiredInfo) { 201 if (mEnrollClient != null) { 202 if (mEnrollClient.sendAcquired(acquiredInfo)) { 203 removeClient(mEnrollClient); 204 } 205 } else if (mAuthClient != null) { 206 if (mAuthClient.sendAcquired(acquiredInfo)) { 207 removeClient(mAuthClient); 208 } 209 } 210 } 211 userActivity()212 private void userActivity() { 213 long now = SystemClock.uptimeMillis(); 214 mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); 215 } 216 handleUserSwitching(int userId)217 void handleUserSwitching(int userId) { 218 updateActiveGroup(userId); 219 } 220 dispatchEnrollResult(long deviceId, int fingerId, int groupId, int remaining)221 protected void dispatchEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { 222 if (mEnrollClient != null) { 223 if (mEnrollClient.sendEnrollResult(fingerId, groupId, remaining)) { 224 if (remaining == 0) { 225 addTemplateForUser(mEnrollClient, fingerId); 226 removeClient(mEnrollClient); 227 } 228 } 229 } 230 } 231 removeClient(ClientMonitor client)232 private void removeClient(ClientMonitor client) { 233 if (client == null) return; 234 client.destroy(); 235 if (client == mAuthClient) { 236 mAuthClient = null; 237 } else if (client == mEnrollClient) { 238 mEnrollClient = null; 239 } else if (client == mRemoveClient) { 240 mRemoveClient = null; 241 } 242 } 243 inLockoutMode()244 private boolean inLockoutMode() { 245 return mFailedAttempts > MAX_FAILED_ATTEMPTS; 246 } 247 resetFailedAttempts()248 private void resetFailedAttempts() { 249 if (DEBUG && inLockoutMode()) { 250 Slog.v(TAG, "Reset fingerprint lockout"); 251 } 252 mFailedAttempts = 0; 253 } 254 handleFailedAttempt(ClientMonitor clientMonitor)255 private boolean handleFailedAttempt(ClientMonitor clientMonitor) { 256 mFailedAttempts++; 257 if (mFailedAttempts > MAX_FAILED_ATTEMPTS) { 258 // Failing multiple times will continue to push out the lockout time. 259 mHandler.removeCallbacks(mLockoutReset); 260 mHandler.postDelayed(mLockoutReset, FAIL_LOCKOUT_TIMEOUT_MS); 261 if (clientMonitor != null 262 && !clientMonitor.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) { 263 Slog.w(TAG, "Cannot send lockout message to client"); 264 } 265 return true; 266 } 267 return false; 268 } 269 removeTemplateForUser(ClientMonitor clientMonitor, int fingerId)270 private void removeTemplateForUser(ClientMonitor clientMonitor, int fingerId) { 271 mFingerprintUtils.removeFingerprintIdForUser(mContext, fingerId, clientMonitor.userId); 272 } 273 addTemplateForUser(ClientMonitor clientMonitor, int fingerId)274 private void addTemplateForUser(ClientMonitor clientMonitor, int fingerId) { 275 mFingerprintUtils.addFingerprintForUser(mContext, fingerId, clientMonitor.userId); 276 } 277 startEnrollment(IBinder token, byte[] cryptoToken, int groupId, IFingerprintServiceReceiver receiver, int flags, boolean restricted)278 void startEnrollment(IBinder token, byte[] cryptoToken, int groupId, 279 IFingerprintServiceReceiver receiver, int flags, boolean restricted) { 280 IFingerprintDaemon daemon = getFingerprintDaemon(); 281 if (daemon == null) { 282 Slog.w(TAG, "enroll: no fingeprintd!"); 283 return; 284 } 285 stopPendingOperations(true); 286 mEnrollClient = new ClientMonitor(token, receiver, groupId, restricted); 287 final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC); 288 try { 289 final int result = daemon.enroll(cryptoToken, groupId, timeout); 290 if (result != 0) { 291 Slog.w(TAG, "startEnroll failed, result=" + result); 292 } 293 } catch (RemoteException e) { 294 Slog.e(TAG, "startEnroll failed", e); 295 } 296 } 297 startPreEnroll(IBinder token)298 public long startPreEnroll(IBinder token) { 299 IFingerprintDaemon daemon = getFingerprintDaemon(); 300 if (daemon == null) { 301 Slog.w(TAG, "startPreEnroll: no fingeprintd!"); 302 return 0; 303 } 304 try { 305 return daemon.preEnroll(); 306 } catch (RemoteException e) { 307 Slog.e(TAG, "startPreEnroll failed", e); 308 } 309 return 0; 310 } 311 startPostEnroll(IBinder token)312 public int startPostEnroll(IBinder token) { 313 IFingerprintDaemon daemon = getFingerprintDaemon(); 314 if (daemon == null) { 315 Slog.w(TAG, "startPostEnroll: no fingeprintd!"); 316 return 0; 317 } 318 try { 319 return daemon.postEnroll(); 320 } catch (RemoteException e) { 321 Slog.e(TAG, "startPostEnroll failed", e); 322 } 323 return 0; 324 } 325 stopPendingOperations(boolean initiatedByClient)326 private void stopPendingOperations(boolean initiatedByClient) { 327 if (mEnrollClient != null) { 328 stopEnrollment(mEnrollClient.token, initiatedByClient); 329 } 330 if (mAuthClient != null) { 331 stopAuthentication(mAuthClient.token, initiatedByClient); 332 } 333 // mRemoveClient is allowed to continue 334 } 335 336 /** 337 * Stop enrollment in progress and inform client if they initiated it. 338 * 339 * @param token token for client 340 * @param initiatedByClient if this call is the result of client action (e.g. calling cancel) 341 */ stopEnrollment(IBinder token, boolean initiatedByClient)342 void stopEnrollment(IBinder token, boolean initiatedByClient) { 343 IFingerprintDaemon daemon = getFingerprintDaemon(); 344 if (daemon == null) { 345 Slog.w(TAG, "stopEnrollment: no fingeprintd!"); 346 return; 347 } 348 final ClientMonitor client = mEnrollClient; 349 if (client == null || client.token != token) return; 350 if (initiatedByClient) { 351 try { 352 int result = daemon.cancelEnrollment(); 353 if (result != 0) { 354 Slog.w(TAG, "startEnrollCancel failed, result = " + result); 355 } 356 } catch (RemoteException e) { 357 Slog.e(TAG, "stopEnrollment failed", e); 358 } 359 client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED); 360 } 361 removeClient(mEnrollClient); 362 } 363 startAuthentication(IBinder token, long opId, int groupId, IFingerprintServiceReceiver receiver, int flags, boolean restricted)364 void startAuthentication(IBinder token, long opId, int groupId, 365 IFingerprintServiceReceiver receiver, int flags, boolean restricted) { 366 IFingerprintDaemon daemon = getFingerprintDaemon(); 367 if (daemon == null) { 368 Slog.w(TAG, "startAuthentication: no fingeprintd!"); 369 return; 370 } 371 stopPendingOperations(true); 372 mAuthClient = new ClientMonitor(token, receiver, groupId, restricted); 373 if (inLockoutMode()) { 374 Slog.v(TAG, "In lockout mode; disallowing authentication"); 375 if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) { 376 Slog.w(TAG, "Cannot send timeout message to client"); 377 } 378 mAuthClient = null; 379 return; 380 } 381 try { 382 final int result = daemon.authenticate(opId, groupId); 383 if (result != 0) { 384 Slog.w(TAG, "startAuthentication failed, result=" + result); 385 } 386 } catch (RemoteException e) { 387 Slog.e(TAG, "startAuthentication failed", e); 388 } 389 } 390 391 /** 392 * Stop authentication in progress and inform client if they initiated it. 393 * 394 * @param token token for client 395 * @param initiatedByClient if this call is the result of client action (e.g. calling cancel) 396 */ stopAuthentication(IBinder token, boolean initiatedByClient)397 void stopAuthentication(IBinder token, boolean initiatedByClient) { 398 IFingerprintDaemon daemon = getFingerprintDaemon(); 399 if (daemon == null) { 400 Slog.w(TAG, "stopAuthentication: no fingeprintd!"); 401 return; 402 } 403 final ClientMonitor client = mAuthClient; 404 if (client == null || client.token != token) return; 405 if (initiatedByClient) { 406 try { 407 int result = daemon.cancelAuthentication(); 408 if (result != 0) { 409 Slog.w(TAG, "stopAuthentication failed, result=" + result); 410 } 411 } catch (RemoteException e) { 412 Slog.e(TAG, "stopAuthentication failed", e); 413 } 414 client.sendError(FingerprintManager.FINGERPRINT_ERROR_CANCELED); 415 } 416 removeClient(mAuthClient); 417 } 418 startRemove(IBinder token, int fingerId, int userId, IFingerprintServiceReceiver receiver, boolean restricted)419 void startRemove(IBinder token, int fingerId, int userId, 420 IFingerprintServiceReceiver receiver, boolean restricted) { 421 IFingerprintDaemon daemon = getFingerprintDaemon(); 422 if (daemon == null) { 423 Slog.w(TAG, "startRemove: no fingeprintd!"); 424 return; 425 } 426 427 mRemoveClient = new ClientMonitor(token, receiver, userId, restricted); 428 // The fingerprint template ids will be removed when we get confirmation from the HAL 429 try { 430 final int result = daemon.remove(fingerId, userId); 431 if (result != 0) { 432 Slog.w(TAG, "startRemove with id = " + fingerId + " failed, result=" + result); 433 } 434 } catch (RemoteException e) { 435 Slog.e(TAG, "startRemove failed", e); 436 } 437 } 438 getEnrolledFingerprints(int userId)439 public List<Fingerprint> getEnrolledFingerprints(int userId) { 440 return mFingerprintUtils.getFingerprintsForUser(mContext, userId); 441 } 442 hasEnrolledFingerprints(int userId)443 public boolean hasEnrolledFingerprints(int userId) { 444 return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0; 445 } 446 hasPermission(String permission)447 boolean hasPermission(String permission) { 448 return getContext().checkCallingOrSelfPermission(permission) 449 == PackageManager.PERMISSION_GRANTED; 450 } 451 checkPermission(String permission)452 void checkPermission(String permission) { 453 getContext().enforceCallingOrSelfPermission(permission, 454 "Must have " + permission + " permission."); 455 } 456 getEffectiveUserId(int userId)457 int getEffectiveUserId(int userId) { 458 UserManager um = UserManager.get(mContext); 459 if (um != null) { 460 final long callingIdentity = Binder.clearCallingIdentity(); 461 userId = um.getCredentialOwnerProfile(userId); 462 Binder.restoreCallingIdentity(callingIdentity); 463 } else { 464 Slog.e(TAG, "Unable to acquire UserManager"); 465 } 466 return userId; 467 } 468 isCurrentUserOrProfile(int userId)469 boolean isCurrentUserOrProfile(int userId) { 470 UserManager um = UserManager.get(mContext); 471 472 // Allow current user or profiles of the current user... 473 List<UserInfo> profiles = um.getEnabledProfiles(userId); 474 final int n = profiles.size(); 475 for (int i = 0; i < n; i++) { 476 if (profiles.get(i).id == userId) { 477 return true; 478 } 479 } 480 return false; 481 } 482 canUseFingerprint(String opPackageName)483 private boolean canUseFingerprint(String opPackageName) { 484 checkPermission(USE_FINGERPRINT); 485 return mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, Binder.getCallingUid(), 486 opPackageName) == AppOpsManager.MODE_ALLOWED; 487 } 488 489 private class ClientMonitor implements IBinder.DeathRecipient { 490 IBinder token; 491 IFingerprintServiceReceiver receiver; 492 int userId; 493 boolean restricted; // True if client does not have MANAGE_FINGERPRINT permission 494 ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId, boolean restricted)495 public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId, 496 boolean restricted) { 497 this.token = token; 498 this.receiver = receiver; 499 this.userId = userId; 500 this.restricted = restricted; 501 try { 502 token.linkToDeath(this, 0); 503 } catch (RemoteException e) { 504 Slog.w(TAG, "caught remote exception in linkToDeath: ", e); 505 } 506 } 507 destroy()508 public void destroy() { 509 if (token != null) { 510 try { 511 token.unlinkToDeath(this, 0); 512 } catch (NoSuchElementException e) { 513 // TODO: remove when duplicate call bug is found 514 Slog.e(TAG, "destroy(): " + this + ":", new Exception("here")); 515 } 516 token = null; 517 } 518 receiver = null; 519 } 520 521 @Override binderDied()522 public void binderDied() { 523 token = null; 524 removeClient(this); 525 receiver = null; 526 } 527 528 @Override finalize()529 protected void finalize() throws Throwable { 530 try { 531 if (token != null) { 532 if (DEBUG) Slog.w(TAG, "removing leaked reference: " + token); 533 removeClient(this); 534 } 535 } finally { 536 super.finalize(); 537 } 538 } 539 540 /* 541 * @return true if we're done. 542 */ sendRemoved(int fingerId, int groupId)543 private boolean sendRemoved(int fingerId, int groupId) { 544 if (receiver == null) return true; // client not listening 545 try { 546 receiver.onRemoved(mHalDeviceId, fingerId, groupId); 547 return fingerId == 0; 548 } catch (RemoteException e) { 549 Slog.w(TAG, "Failed to notify Removed:", e); 550 } 551 return false; 552 } 553 554 /* 555 * @return true if we're done. 556 */ sendEnrollResult(int fpId, int groupId, int remaining)557 private boolean sendEnrollResult(int fpId, int groupId, int remaining) { 558 if (receiver == null) return true; // client not listening 559 FingerprintUtils.vibrateFingerprintSuccess(getContext()); 560 try { 561 receiver.onEnrollResult(mHalDeviceId, fpId, groupId, remaining); 562 return remaining == 0; 563 } catch (RemoteException e) { 564 Slog.w(TAG, "Failed to notify EnrollResult:", e); 565 return true; 566 } 567 } 568 569 /* 570 * @return true if we're done. 571 */ sendAuthenticated(int fpId, int groupId)572 private boolean sendAuthenticated(int fpId, int groupId) { 573 boolean result = false; 574 boolean authenticated = fpId != 0; 575 if (receiver != null) { 576 try { 577 if (!authenticated) { 578 receiver.onAuthenticationFailed(mHalDeviceId); 579 } else { 580 Fingerprint fp = !restricted ? 581 new Fingerprint("" /* TODO */, groupId, fpId, mHalDeviceId) : null; 582 receiver.onAuthenticationSucceeded(mHalDeviceId, fp); 583 } 584 } catch (RemoteException e) { 585 Slog.w(TAG, "Failed to notify Authenticated:", e); 586 result = true; // client failed 587 } 588 } else { 589 result = true; // client not listening 590 } 591 if (fpId == 0) { 592 FingerprintUtils.vibrateFingerprintError(getContext()); 593 result |= handleFailedAttempt(this); 594 } else { 595 FingerprintUtils.vibrateFingerprintSuccess(getContext()); 596 result |= true; // we have a valid fingerprint 597 mLockoutReset.run(); 598 } 599 return result; 600 } 601 602 /* 603 * @return true if we're done. 604 */ sendAcquired(int acquiredInfo)605 private boolean sendAcquired(int acquiredInfo) { 606 if (receiver == null) return true; // client not listening 607 try { 608 receiver.onAcquired(mHalDeviceId, acquiredInfo); 609 return false; // acquisition continues... 610 } catch (RemoteException e) { 611 Slog.w(TAG, "Failed to invoke sendAcquired:", e); 612 return true; // client failed 613 } 614 finally { 615 // Good scans will keep the device awake 616 if (acquiredInfo == FINGERPRINT_ACQUIRED_GOOD) { 617 userActivity(); 618 } 619 } 620 } 621 622 /* 623 * @return true if we're done. 624 */ sendError(int error)625 private boolean sendError(int error) { 626 if (receiver != null) { 627 try { 628 receiver.onError(mHalDeviceId, error); 629 } catch (RemoteException e) { 630 Slog.w(TAG, "Failed to invoke sendError:", e); 631 } 632 } 633 return true; // errors always terminate progress 634 } 635 } 636 637 private IFingerprintDaemonCallback mDaemonCallback = new IFingerprintDaemonCallback.Stub() { 638 639 @Override 640 public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { 641 dispatchEnrollResult(deviceId, fingerId, groupId, remaining); 642 } 643 644 @Override 645 public void onAcquired(long deviceId, int acquiredInfo) { 646 dispatchAcquired(deviceId, acquiredInfo); 647 } 648 649 @Override 650 public void onAuthenticated(long deviceId, int fingerId, int groupId) { 651 dispatchAuthenticated(deviceId, fingerId, groupId); 652 } 653 654 @Override 655 public void onError(long deviceId, int error) { 656 dispatchError(deviceId, error); 657 } 658 659 @Override 660 public void onRemoved(long deviceId, int fingerId, int groupId) { 661 dispatchRemoved(deviceId, fingerId, groupId); 662 } 663 664 @Override 665 public void onEnumerate(long deviceId, int[] fingerIds, int[] groupIds) { 666 dispatchEnumerate(deviceId, fingerIds, groupIds); 667 } 668 669 }; 670 671 private final class FingerprintServiceWrapper extends IFingerprintService.Stub { 672 private static final String KEYGUARD_PACKAGE = "com.android.systemui"; 673 674 @Override // Binder call preEnroll(IBinder token)675 public long preEnroll(IBinder token) { 676 checkPermission(MANAGE_FINGERPRINT); 677 return startPreEnroll(token); 678 } 679 680 @Override // Binder call postEnroll(IBinder token)681 public int postEnroll(IBinder token) { 682 checkPermission(MANAGE_FINGERPRINT); 683 return startPostEnroll(token); 684 } 685 686 @Override // Binder call enroll(final IBinder token, final byte[] cryptoToken, final int groupId, final IFingerprintServiceReceiver receiver, final int flags)687 public void enroll(final IBinder token, final byte[] cryptoToken, final int groupId, 688 final IFingerprintServiceReceiver receiver, final int flags) { 689 checkPermission(MANAGE_FINGERPRINT); 690 final int limit = mContext.getResources().getInteger( 691 com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser); 692 final int callingUid = Binder.getCallingUid(); 693 final int userId = UserHandle.getUserId(callingUid); 694 final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size(); 695 if (enrolled >= limit) { 696 Slog.w(TAG, "Too many fingerprints registered"); 697 return; 698 } 699 final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length); 700 701 // Group ID is arbitrarily set to parent profile user ID. It just represents 702 // the default fingerprints for the user. 703 final int effectiveGroupId = getEffectiveUserId(groupId); 704 705 final boolean restricted = isRestricted(); 706 mHandler.post(new Runnable() { 707 @Override 708 public void run() { 709 startEnrollment(token, cryptoClone, effectiveGroupId, receiver, flags, restricted); 710 } 711 }); 712 } 713 isRestricted()714 private boolean isRestricted() { 715 // Only give privileged apps (like Settings) access to fingerprint info 716 final boolean restricted = !hasPermission(MANAGE_FINGERPRINT); 717 return restricted; 718 } 719 720 @Override // Binder call cancelEnrollment(final IBinder token)721 public void cancelEnrollment(final IBinder token) { 722 checkPermission(MANAGE_FINGERPRINT); 723 mHandler.post(new Runnable() { 724 @Override 725 public void run() { 726 stopEnrollment(token, true); 727 } 728 }); 729 } 730 731 @Override // Binder call authenticate(final IBinder token, final long opId, final int groupId, final IFingerprintServiceReceiver receiver, final int flags, final String opPackageName)732 public void authenticate(final IBinder token, final long opId, final int groupId, 733 final IFingerprintServiceReceiver receiver, final int flags, 734 final String opPackageName) { 735 if (!isCurrentUserOrProfile(UserHandle.getCallingUserId())) { 736 Slog.w(TAG, "Can't authenticate non-current user"); 737 return; 738 } 739 if (!canUseFingerprint(opPackageName)) { 740 Slog.w(TAG, "Calling not granted permission to use fingerprint"); 741 return; 742 } 743 744 // Group ID is arbitrarily set to parent profile user ID. It just represents 745 // the default fingerprints for the user. 746 final int effectiveGroupId = getEffectiveUserId(groupId); 747 748 final boolean restricted = isRestricted(); 749 mHandler.post(new Runnable() { 750 @Override 751 public void run() { 752 startAuthentication(token, opId, effectiveGroupId, receiver, flags, restricted); 753 } 754 }); 755 } 756 757 @Override // Binder call cancelAuthentication(final IBinder token, String opPackageName)758 public void cancelAuthentication(final IBinder token, String opPackageName) { 759 if (!canUseFingerprint(opPackageName)) { 760 return; 761 } 762 mHandler.post(new Runnable() { 763 @Override 764 public void run() { 765 stopAuthentication(token, true); 766 } 767 }); 768 } 769 770 @Override // Binder call remove(final IBinder token, final int fingerId, final int groupId, final IFingerprintServiceReceiver receiver)771 public void remove(final IBinder token, final int fingerId, final int groupId, 772 final IFingerprintServiceReceiver receiver) { 773 checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission 774 final boolean restricted = isRestricted(); 775 776 // Group ID is arbitrarily set to parent profile user ID. It just represents 777 // the default fingerprints for the user. 778 final int effectiveGroupId = getEffectiveUserId(groupId); 779 mHandler.post(new Runnable() { 780 @Override 781 public void run() { 782 startRemove(token, fingerId, effectiveGroupId, receiver, restricted); 783 } 784 }); 785 786 } 787 788 @Override // Binder call isHardwareDetected(long deviceId, String opPackageName)789 public boolean isHardwareDetected(long deviceId, String opPackageName) { 790 if (!canUseFingerprint(opPackageName)) { 791 return false; 792 } 793 return mHalDeviceId != 0; 794 } 795 796 @Override // Binder call rename(final int fingerId, final int groupId, final String name)797 public void rename(final int fingerId, final int groupId, final String name) { 798 checkPermission(MANAGE_FINGERPRINT); 799 800 // Group ID is arbitrarily set to parent profile user ID. It just represents 801 // the default fingerprints for the user. 802 final int effectiveGroupId = getEffectiveUserId(groupId); 803 mHandler.post(new Runnable() { 804 @Override 805 public void run() { 806 mFingerprintUtils.renameFingerprintForUser(mContext, fingerId, 807 effectiveGroupId, name); 808 } 809 }); 810 } 811 812 @Override // Binder call getEnrolledFingerprints(int userId, String opPackageName)813 public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) { 814 if (!canUseFingerprint(opPackageName)) { 815 return Collections.emptyList(); 816 } 817 int effectiveUserId = getEffectiveUserId(userId); 818 819 return FingerprintService.this.getEnrolledFingerprints(effectiveUserId); 820 } 821 822 @Override // Binder call hasEnrolledFingerprints(int userId, String opPackageName)823 public boolean hasEnrolledFingerprints(int userId, String opPackageName) { 824 if (!canUseFingerprint(opPackageName)) { 825 return false; 826 } 827 828 int effectiveUserId = getEffectiveUserId(userId); 829 return FingerprintService.this.hasEnrolledFingerprints(effectiveUserId); 830 } 831 832 @Override // Binder call getAuthenticatorId(String opPackageName)833 public long getAuthenticatorId(String opPackageName) { 834 // In this method, we're not checking whether the caller is permitted to use fingerprint 835 // API because current authenticator ID is leaked (in a more contrived way) via Android 836 // Keystore (android.security.keystore package): the user of that API can create a key 837 // which requires fingerprint authentication for its use, and then query the key's 838 // characteristics (hidden API) which returns, among other things, fingerprint 839 // authenticator ID which was active at key creation time. 840 // 841 // Reason: The part of Android Keystore which runs inside an app's process invokes this 842 // method in certain cases. Those cases are not always where the developer demonstrates 843 // explicit intent to use fingerprint functionality. Thus, to avoiding throwing an 844 // unexpected SecurityException this method does not check whether its caller is 845 // permitted to use fingerprint API. 846 // 847 // The permission check should be restored once Android Keystore no longer invokes this 848 // method from inside app processes. 849 850 return FingerprintService.this.getAuthenticatorId(); 851 } 852 } 853 854 @Override onStart()855 public void onStart() { 856 publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper()); 857 IFingerprintDaemon daemon = getFingerprintDaemon(); 858 if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId); 859 listenForUserSwitches(); 860 } 861 updateActiveGroup(int userId)862 private void updateActiveGroup(int userId) { 863 IFingerprintDaemon daemon = getFingerprintDaemon(); 864 if (daemon != null) { 865 try { 866 userId = getEffectiveUserId(userId); 867 final File systemDir = Environment.getUserSystemDirectory(userId); 868 final File fpDir = new File(systemDir, FP_DATA_DIR); 869 if (!fpDir.exists()) { 870 if (!fpDir.mkdir()) { 871 Slog.v(TAG, "Cannot make directory: " + fpDir.getAbsolutePath()); 872 return; 873 } 874 // Calling mkdir() from this process will create a directory with our 875 // permissions (inherited from the containing dir). This command fixes 876 // the label. 877 if (!SELinux.restorecon(fpDir)) { 878 Slog.w(TAG, "Restorecons failed. Directory will have wrong label."); 879 return; 880 } 881 } 882 daemon.setActiveGroup(userId, fpDir.getAbsolutePath().getBytes()); 883 } catch (RemoteException e) { 884 Slog.e(TAG, "Failed to setActiveGroup():", e); 885 } 886 } 887 } 888 listenForUserSwitches()889 private void listenForUserSwitches() { 890 try { 891 ActivityManagerNative.getDefault().registerUserSwitchObserver( 892 new IUserSwitchObserver.Stub() { 893 @Override 894 public void onUserSwitching(int newUserId, IRemoteCallback reply) { 895 mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */) 896 .sendToTarget(); 897 } 898 @Override 899 public void onUserSwitchComplete(int newUserId) throws RemoteException { 900 // Ignore. 901 } 902 @Override 903 public void onForegroundProfileSwitch(int newProfileId) { 904 // Ignore. 905 } 906 }); 907 } catch (RemoteException e) { 908 Slog.w(TAG, "Failed to listen for user switching event" ,e); 909 } 910 } 911 getAuthenticatorId()912 public long getAuthenticatorId() { 913 IFingerprintDaemon daemon = getFingerprintDaemon(); 914 if (daemon != null) { 915 try { 916 return daemon.getAuthenticatorId(); 917 } catch (RemoteException e) { 918 Slog.e(TAG, "getAuthenticatorId failed", e); 919 } 920 } 921 return 0; 922 } 923 924 } 925