1 /* 2 * Copyright (C) 2019 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.biometrics; 18 19 20 // TODO(b/141025588): Create separate internal and external permissions for AuthService. 21 // TODO(b/141025588): Get rid of the USE_FINGERPRINT permission. 22 23 import static android.Manifest.permission.SET_BIOMETRIC_DIALOG_ADVANCED; 24 import static android.Manifest.permission.TEST_BIOMETRIC; 25 import static android.Manifest.permission.USE_BIOMETRIC; 26 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; 27 import static android.Manifest.permission.USE_FINGERPRINT; 28 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS; 29 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE; 30 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_CANCELED; 31 import static android.hardware.biometrics.BiometricManager.Authenticators; 32 33 import android.annotation.NonNull; 34 import android.app.AppOpsManager; 35 import android.content.Context; 36 import android.content.pm.PackageManager; 37 import android.hardware.biometrics.AuthenticationStateListener; 38 import android.hardware.biometrics.BiometricAuthenticator; 39 import android.hardware.biometrics.BiometricManager; 40 import android.hardware.biometrics.ComponentInfoInternal; 41 import android.hardware.biometrics.Flags; 42 import android.hardware.biometrics.IAuthService; 43 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; 44 import android.hardware.biometrics.IBiometricService; 45 import android.hardware.biometrics.IBiometricServiceReceiver; 46 import android.hardware.biometrics.IInvalidationCallback; 47 import android.hardware.biometrics.ITestSession; 48 import android.hardware.biometrics.ITestSessionCallback; 49 import android.hardware.biometrics.PromptInfo; 50 import android.hardware.biometrics.SensorLocationInternal; 51 import android.hardware.biometrics.SensorPropertiesInternal; 52 import android.hardware.biometrics.face.IFace; 53 import android.hardware.biometrics.fingerprint.IFingerprint; 54 import android.hardware.face.FaceSensorConfigurations; 55 import android.hardware.face.FaceSensorProperties; 56 import android.hardware.face.FaceSensorPropertiesInternal; 57 import android.hardware.face.IFaceService; 58 import android.hardware.fingerprint.FingerprintSensorConfigurations; 59 import android.hardware.fingerprint.FingerprintSensorProperties; 60 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; 61 import android.hardware.fingerprint.IFingerprintService; 62 import android.hardware.iris.IIrisService; 63 import android.os.Binder; 64 import android.os.Build; 65 import android.os.IBinder; 66 import android.os.RemoteException; 67 import android.os.ServiceManager; 68 import android.os.SystemProperties; 69 import android.os.UserHandle; 70 import android.provider.Settings; 71 import android.util.Slog; 72 73 import com.android.internal.R; 74 import com.android.internal.annotations.VisibleForTesting; 75 import com.android.internal.util.ArrayUtils; 76 import com.android.server.SystemService; 77 import com.android.server.companion.virtual.VirtualDeviceManagerInternal; 78 79 import java.util.ArrayList; 80 import java.util.Arrays; 81 import java.util.List; 82 83 /** 84 * System service that provides an interface for authenticating with biometrics and 85 * PIN/pattern/password to BiometricPrompt and lock screen. 86 */ 87 public class AuthService extends SystemService { 88 private static final String TAG = "AuthService"; 89 private static final String SETTING_HIDL_DISABLED = 90 "com.android.server.biometrics.AuthService.hidlDisabled"; 91 private static final int DEFAULT_HIDL_DISABLED = 0; 92 private static final String SYSPROP_FIRST_API_LEVEL = "ro.board.first_api_level"; 93 private static final String SYSPROP_API_LEVEL = "ro.board.api_level"; 94 95 private final Injector mInjector; 96 97 private IBiometricService mBiometricService; 98 @VisibleForTesting 99 final IAuthService.Stub mImpl; 100 101 /** 102 * Class for injecting dependencies into AuthService. 103 * TODO(b/141025588): Replace with a dependency injection framework (e.g. Guice, Dagger). 104 */ 105 @VisibleForTesting 106 public static class Injector { 107 108 /** 109 * Allows to mock BiometricService for testing. 110 */ 111 @VisibleForTesting getBiometricService()112 public IBiometricService getBiometricService() { 113 return IBiometricService.Stub.asInterface( 114 ServiceManager.getService(Context.BIOMETRIC_SERVICE)); 115 } 116 117 /** 118 * Allows to stub publishBinderService(...) for testing. 119 */ 120 @VisibleForTesting publishBinderService(AuthService service, IAuthService.Stub impl)121 public void publishBinderService(AuthService service, IAuthService.Stub impl) { 122 service.publishBinderService(Context.AUTH_SERVICE, impl); 123 } 124 125 /** 126 * Allows to test with various device sensor configurations. 127 */ 128 @VisibleForTesting getConfiguration(Context context)129 public String[] getConfiguration(Context context) { 130 return context.getResources().getStringArray(R.array.config_biometric_sensors); 131 } 132 133 /** 134 * Allows to test with various device sensor configurations. 135 */ 136 @VisibleForTesting getFingerprintConfiguration(Context context)137 public String[] getFingerprintConfiguration(Context context) { 138 return getConfiguration(context); 139 } 140 141 /** 142 * Allows to test with various device sensor configurations. 143 */ 144 @VisibleForTesting getFaceConfiguration(Context context)145 public String[] getFaceConfiguration(Context context) { 146 return getConfiguration(context); 147 } 148 149 /** 150 * Allows to test with various device sensor configurations. 151 */ 152 @VisibleForTesting getIrisConfiguration(Context context)153 public String[] getIrisConfiguration(Context context) { 154 return getConfiguration(context); 155 } 156 157 /** 158 * Allows us to mock FingerprintService for testing 159 */ 160 @VisibleForTesting getFingerprintService()161 public IFingerprintService getFingerprintService() { 162 return IFingerprintService.Stub.asInterface( 163 ServiceManager.getService(Context.FINGERPRINT_SERVICE)); 164 } 165 166 /** 167 * Allows us to mock FaceService for testing 168 */ 169 @VisibleForTesting getFaceService()170 public IFaceService getFaceService() { 171 return IFaceService.Stub.asInterface( 172 ServiceManager.getService(Context.FACE_SERVICE)); 173 } 174 175 /** 176 * Allows us to mock IrisService for testing 177 */ 178 @VisibleForTesting getIrisService()179 public IIrisService getIrisService() { 180 return IIrisService.Stub.asInterface( 181 ServiceManager.getService(Context.IRIS_SERVICE)); 182 } 183 184 @VisibleForTesting getAppOps(Context context)185 public AppOpsManager getAppOps(Context context) { 186 return context.getSystemService(AppOpsManager.class); 187 } 188 189 /** 190 * Allows to ignore HIDL HALs on debug builds based on a secure setting. 191 */ 192 @VisibleForTesting isHidlDisabled(Context context)193 public boolean isHidlDisabled(Context context) { 194 if (Build.IS_ENG || Build.IS_USERDEBUG) { 195 return Settings.Secure.getIntForUser(context.getContentResolver(), 196 SETTING_HIDL_DISABLED, DEFAULT_HIDL_DISABLED, UserHandle.USER_CURRENT) == 1; 197 } 198 return false; 199 } 200 201 /** 202 * Allows to test with various fingerprint aidl instances. 203 */ 204 @VisibleForTesting getFingerprintAidlInstances()205 public String[] getFingerprintAidlInstances() { 206 return ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR); 207 } 208 209 /** 210 * Allows to test with various face aidl instances. 211 */ 212 @VisibleForTesting getFaceAidlInstances()213 public String[] getFaceAidlInstances() { 214 return ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR); 215 } 216 217 /** 218 * Allows to test with handlers. 219 */ getBiometricHandlerProvider()220 public BiometricHandlerProvider getBiometricHandlerProvider() { 221 return BiometricHandlerProvider.getInstance(); 222 } 223 } 224 225 private final class AuthServiceImpl extends IAuthService.Stub { 226 @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC) 227 @Override createTestSession(int sensorId, @NonNull ITestSessionCallback callback, @NonNull String opPackageName)228 public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, 229 @NonNull String opPackageName) throws RemoteException { 230 231 super.createTestSession_enforcePermission(); 232 233 final long identity = Binder.clearCallingIdentity(); 234 try { 235 return mInjector.getBiometricService() 236 .createTestSession(sensorId, callback, opPackageName); 237 } finally { 238 Binder.restoreCallingIdentity(identity); 239 } 240 } 241 242 @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC) 243 @Override getSensorProperties(String opPackageName)244 public List<SensorPropertiesInternal> getSensorProperties(String opPackageName) 245 throws RemoteException { 246 247 super.getSensorProperties_enforcePermission(); 248 249 final long identity = Binder.clearCallingIdentity(); 250 try { 251 // Get the result from BiometricService, since it is the source of truth for all 252 // biometric sensors. 253 return mInjector.getBiometricService().getSensorProperties(opPackageName); 254 } finally { 255 Binder.restoreCallingIdentity(identity); 256 } 257 } 258 259 @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC) 260 @Override getUiPackage()261 public String getUiPackage() { 262 263 super.getUiPackage_enforcePermission(); 264 265 return getContext().getResources() 266 .getString(R.string.config_biometric_prompt_ui_package); 267 } 268 269 @Override authenticate(IBinder token, long sessionId, int userId, IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo)270 public long authenticate(IBinder token, long sessionId, int userId, 271 IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo) 272 throws RemoteException { 273 // Only allow internal clients to authenticate with a different userId. 274 final int callingUserId = UserHandle.getCallingUserId(); 275 final int callingUid = Binder.getCallingUid(); 276 final int callingPid = Binder.getCallingPid(); 277 if (userId == callingUserId) { 278 checkPermission(); 279 } else { 280 Slog.w(TAG, "User " + callingUserId + " is requesting authentication of userid: " 281 + userId); 282 checkInternalPermission(); 283 } 284 285 if (!checkAppOps(callingUid, opPackageName, "authenticate()")) { 286 authenticateFastFail("Denied by app ops: " + opPackageName, receiver); 287 return -1; 288 } 289 290 if (token == null || receiver == null || opPackageName == null || promptInfo == null) { 291 authenticateFastFail( 292 "Unable to authenticate, one or more null arguments", receiver); 293 return -1; 294 } 295 296 if (!Utils.isForeground(callingUid, callingPid)) { 297 authenticateFastFail("Caller is not foreground: " + opPackageName, receiver); 298 return -1; 299 } 300 301 if (promptInfo.requiresTestOrInternalPermission()) { 302 if (getContext().checkCallingOrSelfPermission(TEST_BIOMETRIC) 303 != PackageManager.PERMISSION_GRANTED) { 304 checkInternalPermission(); 305 } 306 } 307 308 // Only allow internal clients to enable non-public options. 309 if (promptInfo.requiresInternalPermission()) { 310 checkInternalPermission(); 311 } 312 if (promptInfo.requiresAdvancedPermission()) { 313 checkBiometricAdvancedPermission(); 314 } 315 316 final long identity = Binder.clearCallingIdentity(); 317 try { 318 VirtualDeviceManagerInternal vdm = getLocalService( 319 VirtualDeviceManagerInternal.class); 320 if (vdm != null) { 321 vdm.onAuthenticationPrompt(callingUid); 322 } 323 return mBiometricService.authenticate( 324 token, sessionId, userId, receiver, opPackageName, promptInfo); 325 } finally { 326 Binder.restoreCallingIdentity(identity); 327 } 328 } 329 authenticateFastFail(String message, IBiometricServiceReceiver receiver)330 private void authenticateFastFail(String message, IBiometricServiceReceiver receiver) { 331 // notify caller in cases where authentication is aborted before calling into 332 // IBiometricService without raising an exception 333 Slog.e(TAG, "authenticateFastFail: " + message); 334 try { 335 receiver.onError(TYPE_NONE, BIOMETRIC_ERROR_CANCELED, 0 /*vendorCode */); 336 } catch (RemoteException e) { 337 Slog.e(TAG, "authenticateFastFail failed to notify caller", e); 338 } 339 } 340 341 @Override cancelAuthentication(IBinder token, String opPackageName, long requestId)342 public void cancelAuthentication(IBinder token, String opPackageName, long requestId) 343 throws RemoteException { 344 checkPermission(); 345 346 if (token == null || opPackageName == null) { 347 Slog.e(TAG, "Unable to cancel authentication, one or more null arguments"); 348 return; 349 } 350 351 final long identity = Binder.clearCallingIdentity(); 352 try { 353 mBiometricService.cancelAuthentication(token, opPackageName, requestId); 354 } finally { 355 Binder.restoreCallingIdentity(identity); 356 } 357 } 358 359 @Override canAuthenticate(String opPackageName, int userId, @Authenticators.Types int authenticators)360 public int canAuthenticate(String opPackageName, int userId, 361 @Authenticators.Types int authenticators) throws RemoteException { 362 363 // Only allow internal clients to call canAuthenticate with a different userId. 364 final int callingUserId = UserHandle.getCallingUserId(); 365 366 if (userId != callingUserId) { 367 checkInternalPermission(); 368 } else { 369 checkPermission(); 370 } 371 372 final long identity = Binder.clearCallingIdentity(); 373 try { 374 final int result = mBiometricService.canAuthenticate( 375 opPackageName, userId, callingUserId, authenticators); 376 Slog.d(TAG, "canAuthenticate" 377 + ", userId: " + userId 378 + ", callingUserId: " + callingUserId 379 + ", authenticators: " + authenticators 380 + ", result: " + result); 381 return result; 382 } finally { 383 Binder.restoreCallingIdentity(identity); 384 } 385 } 386 387 @Override getLastAuthenticationTime(int userId, @Authenticators.Types int authenticators)388 public long getLastAuthenticationTime(int userId, 389 @Authenticators.Types int authenticators) throws RemoteException { 390 // Only allow internal clients to call getLastAuthenticationTime with a different 391 // userId. 392 final int callingUserId = UserHandle.getCallingUserId(); 393 394 if (userId != callingUserId) { 395 checkInternalPermission(); 396 } else { 397 checkPermission(); 398 } 399 400 final long identity = Binder.clearCallingIdentity(); 401 try { 402 // We can't do this above because we need the READ_DEVICE_CONFIG permission, which 403 // the calling user may not possess. 404 if (!Flags.lastAuthenticationTime()) { 405 throw new UnsupportedOperationException(); 406 } 407 408 return mBiometricService.getLastAuthenticationTime(userId, authenticators); 409 } finally { 410 Binder.restoreCallingIdentity(identity); 411 } 412 } 413 414 @Override hasEnrolledBiometrics(int userId, String opPackageName)415 public boolean hasEnrolledBiometrics(int userId, String opPackageName) 416 throws RemoteException { 417 checkInternalPermission(); 418 final long identity = Binder.clearCallingIdentity(); 419 try { 420 return mBiometricService.hasEnrolledBiometrics(userId, opPackageName); 421 } finally { 422 Binder.restoreCallingIdentity(identity); 423 } 424 } 425 426 @Override registerEnabledOnKeyguardCallback( IBiometricEnabledOnKeyguardCallback callback)427 public void registerEnabledOnKeyguardCallback( 428 IBiometricEnabledOnKeyguardCallback callback) throws RemoteException { 429 checkInternalPermission(); 430 final long identity = Binder.clearCallingIdentity(); 431 try { 432 mBiometricService.registerEnabledOnKeyguardCallback(callback); 433 } finally { 434 Binder.restoreCallingIdentity(identity); 435 } 436 } 437 438 @Override registerAuthenticationStateListener(AuthenticationStateListener listener)439 public void registerAuthenticationStateListener(AuthenticationStateListener listener) 440 throws RemoteException { 441 checkInternalPermission(); 442 final IFingerprintService fingerprintService = mInjector.getFingerprintService(); 443 if (fingerprintService != null) { 444 fingerprintService.registerAuthenticationStateListener(listener); 445 } 446 final IFaceService faceService = mInjector.getFaceService(); 447 if (faceService != null) { 448 faceService.registerAuthenticationStateListener(listener); 449 } 450 } 451 452 @Override unregisterAuthenticationStateListener(AuthenticationStateListener listener)453 public void unregisterAuthenticationStateListener(AuthenticationStateListener listener) 454 throws RemoteException { 455 checkInternalPermission(); 456 final IFingerprintService fingerprintService = mInjector.getFingerprintService(); 457 if (fingerprintService != null) { 458 fingerprintService.unregisterAuthenticationStateListener(listener); 459 } 460 final IFaceService faceService = mInjector.getFaceService(); 461 if (faceService != null) { 462 faceService.unregisterAuthenticationStateListener(listener); 463 } 464 } 465 466 @Override invalidateAuthenticatorIds(int userId, int fromSensorId, IInvalidationCallback callback)467 public void invalidateAuthenticatorIds(int userId, int fromSensorId, 468 IInvalidationCallback callback) throws RemoteException { 469 checkInternalPermission(); 470 471 final long identity = Binder.clearCallingIdentity(); 472 try { 473 mBiometricService.invalidateAuthenticatorIds(userId, fromSensorId, callback); 474 } finally { 475 Binder.restoreCallingIdentity(identity); 476 } 477 } 478 479 @Override getAuthenticatorIds(int userId)480 public long[] getAuthenticatorIds(int userId) throws RemoteException { 481 // In this method, we're not checking whether the caller is permitted to use face 482 // API because current authenticator ID is leaked (in a more contrived way) via Android 483 // Keystore (android.security.keystore package): the user of that API can create a key 484 // which requires face authentication for its use, and then query the key's 485 // characteristics (hidden API) which returns, among other things, face 486 // authenticator ID which was active at key creation time. 487 // 488 // Reason: The part of Android Keystore which runs inside an app's process invokes this 489 // method in certain cases. Those cases are not always where the developer demonstrates 490 // explicit intent to use biometric functionality. Thus, to avoiding throwing an 491 // unexpected SecurityException this method does not check whether its caller is 492 // permitted to use face API. 493 // 494 // The permission check should be restored once Android Keystore no longer invokes this 495 // method from inside app processes. 496 497 final int callingUserId = UserHandle.getCallingUserId(); 498 if (userId != callingUserId) { 499 getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL, 500 "Must have " + USE_BIOMETRIC_INTERNAL + " permission."); 501 } 502 final long identity = Binder.clearCallingIdentity(); 503 try { 504 return mBiometricService.getAuthenticatorIds(userId); 505 } finally { 506 Binder.restoreCallingIdentity(identity); 507 } 508 } 509 510 @Override resetLockoutTimeBound(IBinder token, String opPackageName, int fromSensorId, int userId, byte[] hardwareAuthToken)511 public void resetLockoutTimeBound(IBinder token, String opPackageName, int fromSensorId, 512 int userId, byte[] hardwareAuthToken) throws RemoteException { 513 checkInternalPermission(); 514 515 final long identity = Binder.clearCallingIdentity(); 516 try { 517 mBiometricService.resetLockoutTimeBound(token, opPackageName, fromSensorId, userId, 518 hardwareAuthToken); 519 } finally { 520 Binder.restoreCallingIdentity(identity); 521 } 522 } 523 524 @Override resetLockout(int userId, byte[] hardwareAuthToken)525 public void resetLockout(int userId, byte[] hardwareAuthToken) throws RemoteException { 526 checkInternalPermission(); 527 final long identity = Binder.clearCallingIdentity(); 528 try { 529 mBiometricService.resetLockout(userId, hardwareAuthToken); 530 } finally { 531 Binder.restoreCallingIdentity(identity); 532 } 533 } 534 535 @Override getButtonLabel( int userId, String opPackageName, @Authenticators.Types int authenticators)536 public CharSequence getButtonLabel( 537 int userId, 538 String opPackageName, 539 @Authenticators.Types int authenticators) throws RemoteException { 540 541 // Only allow internal clients to call getButtonLabel with a different userId. 542 final int callingUserId = UserHandle.getCallingUserId(); 543 544 if (userId != callingUserId) { 545 checkInternalPermission(); 546 } else { 547 checkPermission(); 548 } 549 550 final long identity = Binder.clearCallingIdentity(); 551 try { 552 @BiometricAuthenticator.Modality final int modality = 553 mBiometricService.getCurrentModality( 554 opPackageName, userId, callingUserId, authenticators); 555 556 final String result; 557 switch (getCredentialBackupModality(modality)) { 558 case BiometricAuthenticator.TYPE_NONE: 559 result = null; 560 break; 561 case BiometricAuthenticator.TYPE_CREDENTIAL: 562 result = getContext().getString(R.string.screen_lock_app_setting_name); 563 break; 564 case BiometricAuthenticator.TYPE_FINGERPRINT: 565 result = getContext().getString(R.string.fingerprint_app_setting_name); 566 break; 567 case BiometricAuthenticator.TYPE_FACE: 568 result = getContext().getString(R.string.face_app_setting_name); 569 break; 570 default: 571 result = getContext().getString(R.string.biometric_app_setting_name); 572 break; 573 } 574 575 return result; 576 } finally { 577 Binder.restoreCallingIdentity(identity); 578 } 579 } 580 581 @Override getPromptMessage( int userId, String opPackageName, @Authenticators.Types int authenticators)582 public CharSequence getPromptMessage( 583 int userId, 584 String opPackageName, 585 @Authenticators.Types int authenticators) throws RemoteException { 586 587 // Only allow internal clients to call getButtonLabel with a different userId. 588 final int callingUserId = UserHandle.getCallingUserId(); 589 590 if (userId != callingUserId) { 591 checkInternalPermission(); 592 } else { 593 checkPermission(); 594 } 595 596 final long identity = Binder.clearCallingIdentity(); 597 try { 598 @BiometricAuthenticator.Modality final int modality = 599 mBiometricService.getCurrentModality( 600 opPackageName, userId, callingUserId, authenticators); 601 602 final boolean isCredentialAllowed = Utils.isCredentialRequested(authenticators); 603 604 final String result; 605 switch (getCredentialBackupModality(modality)) { 606 case BiometricAuthenticator.TYPE_NONE: 607 result = null; 608 break; 609 610 case BiometricAuthenticator.TYPE_CREDENTIAL: 611 result = getContext().getString( 612 R.string.screen_lock_dialog_default_subtitle); 613 break; 614 615 case BiometricAuthenticator.TYPE_FINGERPRINT: 616 if (isCredentialAllowed) { 617 result = getContext().getString( 618 R.string.fingerprint_or_screen_lock_dialog_default_subtitle); 619 } else { 620 result = getContext().getString( 621 R.string.fingerprint_dialog_default_subtitle); 622 } 623 break; 624 625 case BiometricAuthenticator.TYPE_FACE: 626 if (isCredentialAllowed) { 627 result = getContext().getString( 628 R.string.face_or_screen_lock_dialog_default_subtitle); 629 } else { 630 result = getContext().getString(R.string.face_dialog_default_subtitle); 631 } 632 break; 633 634 default: 635 if (isCredentialAllowed) { 636 result = getContext().getString( 637 R.string.biometric_or_screen_lock_dialog_default_subtitle); 638 } else { 639 result = getContext().getString( 640 R.string.biometric_dialog_default_subtitle); 641 } 642 break; 643 } 644 645 return result; 646 } finally { 647 Binder.restoreCallingIdentity(identity); 648 } 649 } 650 651 @Override getSettingName( int userId, String opPackageName, @Authenticators.Types int authenticators)652 public CharSequence getSettingName( 653 int userId, 654 String opPackageName, 655 @Authenticators.Types int authenticators) throws RemoteException { 656 657 // Only allow internal clients to call getButtonLabel with a different userId. 658 final int callingUserId = UserHandle.getCallingUserId(); 659 660 if (userId != callingUserId) { 661 checkInternalPermission(); 662 } else { 663 checkPermission(); 664 } 665 666 final long identity = Binder.clearCallingIdentity(); 667 try { 668 @BiometricAuthenticator.Modality final int modality = 669 mBiometricService.getSupportedModalities(authenticators); 670 671 final String result; 672 switch (modality) { 673 // Handle the case of a single supported modality. 674 case BiometricAuthenticator.TYPE_NONE: 675 result = null; 676 break; 677 case BiometricAuthenticator.TYPE_CREDENTIAL: 678 result = getContext().getString(R.string.screen_lock_app_setting_name); 679 break; 680 case BiometricAuthenticator.TYPE_IRIS: 681 result = getContext().getString(R.string.biometric_app_setting_name); 682 break; 683 case BiometricAuthenticator.TYPE_FINGERPRINT: 684 result = getContext().getString(R.string.fingerprint_app_setting_name); 685 break; 686 case BiometricAuthenticator.TYPE_FACE: 687 result = getContext().getString(R.string.face_app_setting_name); 688 break; 689 690 // Handle other possible modality combinations. 691 default: 692 if ((modality & BiometricAuthenticator.TYPE_CREDENTIAL) == 0) { 693 // 2+ biometric modalities are supported (but not device credential). 694 result = getContext().getString(R.string.biometric_app_setting_name); 695 } else { 696 @BiometricAuthenticator.Modality final int biometricModality = 697 modality & ~BiometricAuthenticator.TYPE_CREDENTIAL; 698 if (biometricModality == BiometricAuthenticator.TYPE_FINGERPRINT) { 699 // Only device credential and fingerprint are supported. 700 result = getContext().getString( 701 R.string.fingerprint_or_screen_lock_app_setting_name); 702 } else if (biometricModality == BiometricAuthenticator.TYPE_FACE) { 703 // Only device credential and face are supported. 704 result = getContext().getString( 705 R.string.face_or_screen_lock_app_setting_name); 706 } else { 707 // Device credential and 1+ other biometric(s) are supported. 708 result = getContext().getString( 709 R.string.biometric_or_screen_lock_app_setting_name); 710 } 711 } 712 break; 713 } 714 return result; 715 } finally { 716 Binder.restoreCallingIdentity(identity); 717 } 718 } 719 } 720 AuthService(Context context)721 public AuthService(Context context) { 722 this(context, new Injector()); 723 } 724 AuthService(Context context, Injector injector)725 public AuthService(Context context, Injector injector) { 726 super(context); 727 728 mInjector = injector; 729 mImpl = new AuthServiceImpl(); 730 } 731 732 733 /** 734 * Registration of all HIDL and AIDL biometric HALs starts here. 735 * The flow looks like this: 736 * AuthService 737 * └── .onStart() 738 * └── .registerAuthenticators(...) 739 * ├── FaceService.registerAuthenticators(...) 740 * │ └── for (p : serviceProviders) 741 * │ └── for (s : p.sensors) 742 * │ └── BiometricService.registerAuthenticator(s) 743 * │ 744 * ├── FingerprintService.registerAuthenticators(...) 745 * │ └── for (p : serviceProviders) 746 * │ └── for (s : p.sensors) 747 * │ └── BiometricService.registerAuthenticator(s) 748 * │ 749 * └── IrisService.registerAuthenticators(...) 750 * └── for (p : serviceProviders) 751 * └── for (s : p.sensors) 752 * └── BiometricService.registerAuthenticator(s) 753 */ 754 @Override onStart()755 public void onStart() { 756 mBiometricService = mInjector.getBiometricService(); 757 758 final SensorConfig[] hidlConfigs; 759 if (!mInjector.isHidlDisabled(getContext())) { 760 final int firstApiLevel = SystemProperties.getInt(SYSPROP_FIRST_API_LEVEL, 0); 761 final int apiLevel = SystemProperties.getInt(SYSPROP_API_LEVEL, firstApiLevel); 762 String[] configStrings = mInjector.getConfiguration(getContext()); 763 if (configStrings.length == 0 && apiLevel == Build.VERSION_CODES.R) { 764 // For backwards compatibility with R where biometrics could work without being 765 // configured in config_biometric_sensors. In the absence of a vendor provided 766 // configuration, we assume the weakest biometric strength (i.e. convenience). 767 Slog.w(TAG, "Found R vendor partition without config_biometric_sensors"); 768 configStrings = generateRSdkCompatibleConfiguration(); 769 } 770 hidlConfigs = new SensorConfig[configStrings.length]; 771 for (int i = 0; i < configStrings.length; ++i) { 772 hidlConfigs[i] = new SensorConfig(configStrings[i]); 773 } 774 } else { 775 hidlConfigs = null; 776 } 777 778 registerAuthenticators(); 779 mInjector.publishBinderService(this, mImpl); 780 } 781 registerAuthenticators()782 private void registerAuthenticators() { 783 BiometricHandlerProvider handlerProvider = mInjector.getBiometricHandlerProvider(); 784 785 registerFingerprintSensors(mInjector.getFingerprintAidlInstances(), 786 mInjector.getFingerprintConfiguration(getContext()), getContext(), 787 mInjector.getFingerprintService(), handlerProvider); 788 registerFaceSensors(mInjector.getFaceAidlInstances(), 789 mInjector.getFaceConfiguration(getContext()), getContext(), 790 mInjector.getFaceService(), handlerProvider); 791 registerIrisSensors(mInjector.getIrisConfiguration(getContext())); 792 } 793 registerIrisSensors(String[] hidlConfigStrings)794 private void registerIrisSensors(String[] hidlConfigStrings) { 795 final SensorConfig[] hidlConfigs; 796 if (!mInjector.isHidlDisabled(getContext())) { 797 final int firstApiLevel = SystemProperties.getInt(SYSPROP_FIRST_API_LEVEL, 0); 798 final int apiLevel = SystemProperties.getInt(SYSPROP_API_LEVEL, firstApiLevel); 799 if (hidlConfigStrings.length == 0 && apiLevel == Build.VERSION_CODES.R) { 800 // For backwards compatibility with R where biometrics could work without being 801 // configured in config_biometric_sensors. In the absence of a vendor provided 802 // configuration, we assume the weakest biometric strength (i.e. convenience). 803 Slog.w(TAG, "Found R vendor partition without config_biometric_sensors"); 804 hidlConfigStrings = generateRSdkCompatibleConfiguration(); 805 } 806 hidlConfigs = new SensorConfig[hidlConfigStrings.length]; 807 for (int i = 0; i < hidlConfigStrings.length; ++i) { 808 hidlConfigs[i] = new SensorConfig(hidlConfigStrings[i]); 809 } 810 } else { 811 hidlConfigs = null; 812 } 813 814 final List<SensorPropertiesInternal> hidlIrisSensors = new ArrayList<>(); 815 816 if (hidlConfigs != null) { 817 for (SensorConfig sensor : hidlConfigs) { 818 switch (sensor.modality) { 819 case TYPE_IRIS: 820 hidlIrisSensors.add(getHidlIrisSensorProps(sensor.id, sensor.strength)); 821 break; 822 823 default: 824 Slog.e(TAG, "Unknown modality: " + sensor.modality); 825 } 826 } 827 } 828 829 final IIrisService irisService = mInjector.getIrisService(); 830 if (irisService != null) { 831 try { 832 irisService.registerAuthenticators(hidlIrisSensors); 833 } catch (RemoteException e) { 834 Slog.e(TAG, "RemoteException when registering iris authenticators", e); 835 } 836 } else if (hidlIrisSensors.size() > 0) { 837 Slog.e(TAG, "HIDL iris configuration exists, but IrisService is null."); 838 } 839 } 840 841 /** 842 * This method is invoked on {@link BiometricHandlerProvider.mFaceHandler}. 843 */ registerFaceSensors(final String[] faceAidlInstances, final String[] hidlConfigStrings, final Context context, final IFaceService faceService, final BiometricHandlerProvider handlerProvider)844 private static void registerFaceSensors(final String[] faceAidlInstances, 845 final String[] hidlConfigStrings, final Context context, 846 final IFaceService faceService, final BiometricHandlerProvider handlerProvider) { 847 if ((hidlConfigStrings == null || hidlConfigStrings.length == 0) 848 && (faceAidlInstances == null || faceAidlInstances.length == 0)) { 849 Slog.d(TAG, "No face sensors."); 850 return; 851 } 852 853 handlerProvider.getFaceHandler().post(() -> { 854 final FaceSensorConfigurations mFaceSensorConfigurations = 855 new FaceSensorConfigurations(hidlConfigStrings != null 856 && hidlConfigStrings.length > 0); 857 858 if (hidlConfigStrings != null && hidlConfigStrings.length > 0) { 859 mFaceSensorConfigurations.addHidlConfigs(hidlConfigStrings, context); 860 } 861 862 if (faceAidlInstances != null && faceAidlInstances.length > 0) { 863 mFaceSensorConfigurations.addAidlConfigs(faceAidlInstances); 864 } 865 866 if (faceService != null) { 867 try { 868 faceService.registerAuthenticators(mFaceSensorConfigurations); 869 } catch (RemoteException e) { 870 Slog.e(TAG, "RemoteException when registering face authenticators", e); 871 } 872 } else if (mFaceSensorConfigurations.hasSensorConfigurations()) { 873 Slog.e(TAG, "Face configuration exists, but FaceService is null."); 874 } 875 }); 876 } 877 878 /** 879 * This method is invoked on {@link BiometricHandlerProvider.mFingerprintHandler}. 880 */ registerFingerprintSensors(final String[] fingerprintAidlInstances, final String[] hidlConfigStrings, final Context context, final IFingerprintService fingerprintService, final BiometricHandlerProvider handlerProvider)881 private static void registerFingerprintSensors(final String[] fingerprintAidlInstances, 882 final String[] hidlConfigStrings, final Context context, 883 final IFingerprintService fingerprintService, 884 final BiometricHandlerProvider handlerProvider) { 885 if ((hidlConfigStrings == null || hidlConfigStrings.length == 0) 886 && (fingerprintAidlInstances == null || fingerprintAidlInstances.length == 0)) { 887 Slog.d(TAG, "No fingerprint sensors."); 888 return; 889 } 890 891 handlerProvider.getFingerprintHandler().post(() -> { 892 final FingerprintSensorConfigurations mFingerprintSensorConfigurations = 893 new FingerprintSensorConfigurations(!(hidlConfigStrings != null 894 && hidlConfigStrings.length > 0)); 895 896 if (hidlConfigStrings != null && hidlConfigStrings.length > 0) { 897 mFingerprintSensorConfigurations.addHidlSensors(hidlConfigStrings, context); 898 } 899 900 if (fingerprintAidlInstances != null && fingerprintAidlInstances.length > 0) { 901 mFingerprintSensorConfigurations.addAidlSensors(fingerprintAidlInstances); 902 } 903 904 if (fingerprintService != null) { 905 try { 906 fingerprintService.registerAuthenticators(mFingerprintSensorConfigurations); 907 } catch (RemoteException e) { 908 Slog.e(TAG, "RemoteException when registering fingerprint authenticators", e); 909 } 910 } else if (mFingerprintSensorConfigurations.hasSensorConfigurations()) { 911 Slog.e(TAG, "Fingerprint configuration exists, but FingerprintService is null."); 912 } 913 }); 914 } 915 916 /** 917 * Generates an array of string configs with entries that correspond to the biometric features 918 * declared on the device. Returns an empty array if no biometric features are declared. 919 * Biometrics are assumed to be of the weakest strength class, i.e. convenience. 920 */ generateRSdkCompatibleConfiguration()921 private @NonNull String[] generateRSdkCompatibleConfiguration() { 922 final PackageManager pm = getContext().getPackageManager(); 923 final ArrayList<String> modalities = new ArrayList<>(); 924 if (pm.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) { 925 modalities.add(String.valueOf(BiometricAuthenticator.TYPE_FINGERPRINT)); 926 } 927 if (pm.hasSystemFeature(PackageManager.FEATURE_FACE)) { 928 modalities.add(String.valueOf(BiometricAuthenticator.TYPE_FACE)); 929 } 930 final String strength = String.valueOf(Authenticators.BIOMETRIC_CONVENIENCE); 931 final String[] configStrings = new String[modalities.size()]; 932 for (int i = 0; i < modalities.size(); ++i) { 933 final String id = String.valueOf(i); 934 final String modality = modalities.get(i); 935 configStrings[i] = String.join(":" /* delimiter */, id, modality, strength); 936 } 937 Slog.d(TAG, "Generated config_biometric_sensors: " + Arrays.toString(configStrings)); 938 return configStrings; 939 } 940 checkInternalPermission()941 private void checkInternalPermission() { 942 getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL, 943 "Must have USE_BIOMETRIC_INTERNAL permission"); 944 } 945 checkBiometricAdvancedPermission()946 private void checkBiometricAdvancedPermission() { 947 getContext().enforceCallingOrSelfPermission(SET_BIOMETRIC_DIALOG_ADVANCED, 948 "Must have SET_BIOMETRIC_DIALOG_ADVANCED permission"); 949 } 950 checkPermission()951 private void checkPermission() { 952 if (getContext().checkCallingOrSelfPermission(USE_FINGERPRINT) 953 != PackageManager.PERMISSION_GRANTED) { 954 getContext().enforceCallingOrSelfPermission(USE_BIOMETRIC, 955 "Must have USE_BIOMETRIC permission"); 956 } 957 } 958 checkAppOps(int uid, String opPackageName, String reason)959 private boolean checkAppOps(int uid, String opPackageName, String reason) { 960 return mInjector.getAppOps(getContext()).noteOp(AppOpsManager.OP_USE_BIOMETRIC, uid, 961 opPackageName, null /* attributionTag */, reason) == AppOpsManager.MODE_ALLOWED; 962 } 963 964 @BiometricAuthenticator.Modality getCredentialBackupModality(@iometricAuthenticator.Modality int modality)965 private static int getCredentialBackupModality(@BiometricAuthenticator.Modality int modality) { 966 return modality == BiometricAuthenticator.TYPE_CREDENTIAL 967 ? modality : (modality & ~BiometricAuthenticator.TYPE_CREDENTIAL); 968 } 969 970 getHidlFingerprintSensorProps(int sensorId, @BiometricManager.Authenticators.Types int strength)971 private FingerprintSensorPropertiesInternal getHidlFingerprintSensorProps(int sensorId, 972 @BiometricManager.Authenticators.Types int strength) { 973 // The existence of config_udfps_sensor_props indicates that the sensor is UDFPS. 974 final int[] udfpsProps = getContext().getResources().getIntArray( 975 com.android.internal.R.array.config_udfps_sensor_props); 976 977 final boolean isUdfps = !ArrayUtils.isEmpty(udfpsProps); 978 979 // config_is_powerbutton_fps indicates whether device has a power button fingerprint sensor. 980 final boolean isPowerbuttonFps = getContext().getResources().getBoolean( 981 R.bool.config_is_powerbutton_fps); 982 983 final @FingerprintSensorProperties.SensorType int sensorType; 984 if (isUdfps) { 985 sensorType = FingerprintSensorProperties.TYPE_UDFPS_OPTICAL; 986 } else if (isPowerbuttonFps) { 987 sensorType = FingerprintSensorProperties.TYPE_POWER_BUTTON; 988 } else { 989 sensorType = FingerprintSensorProperties.TYPE_REAR; 990 } 991 992 // IBiometricsFingerprint@2.1 does not manage timeout below the HAL, so the Gatekeeper HAT 993 // cannot be checked. 994 final boolean resetLockoutRequiresHardwareAuthToken = false; 995 final int maxEnrollmentsPerUser = getContext().getResources().getInteger( 996 R.integer.config_fingerprintMaxTemplatesPerUser); 997 998 final List<ComponentInfoInternal> componentInfo = new ArrayList<>(); 999 if (isUdfps && udfpsProps.length == 3) { 1000 return new FingerprintSensorPropertiesInternal(sensorId, 1001 Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, 1002 componentInfo, sensorType, true /* halControlsIllumination */, 1003 resetLockoutRequiresHardwareAuthToken, 1004 List.of(new SensorLocationInternal("" /* display */, udfpsProps[0], 1005 udfpsProps[1], udfpsProps[2]))); 1006 } else { 1007 return new FingerprintSensorPropertiesInternal(sensorId, 1008 Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, 1009 componentInfo, sensorType, resetLockoutRequiresHardwareAuthToken); 1010 } 1011 } 1012 getHidlFaceSensorProps(int sensorId, @BiometricManager.Authenticators.Types int strength)1013 private FaceSensorPropertiesInternal getHidlFaceSensorProps(int sensorId, 1014 @BiometricManager.Authenticators.Types int strength) { 1015 final boolean supportsSelfIllumination = getContext().getResources().getBoolean( 1016 R.bool.config_faceAuthSupportsSelfIllumination); 1017 final int maxTemplatesAllowed = getContext().getResources().getInteger( 1018 R.integer.config_faceMaxTemplatesPerUser); 1019 final List<ComponentInfoInternal> componentInfo = new ArrayList<>(); 1020 final boolean supportsFaceDetect = false; 1021 final boolean resetLockoutRequiresChallenge = true; 1022 return new FaceSensorPropertiesInternal(sensorId, 1023 Utils.authenticatorStrengthToPropertyStrength(strength), maxTemplatesAllowed, 1024 componentInfo, FaceSensorProperties.TYPE_UNKNOWN, supportsFaceDetect, 1025 supportsSelfIllumination, resetLockoutRequiresChallenge); 1026 } 1027 getHidlIrisSensorProps(int sensorId, @BiometricManager.Authenticators.Types int strength)1028 private SensorPropertiesInternal getHidlIrisSensorProps(int sensorId, 1029 @BiometricManager.Authenticators.Types int strength) { 1030 final int maxEnrollmentsPerUser = 1; 1031 final List<ComponentInfoInternal> componentInfo = new ArrayList<>(); 1032 final boolean resetLockoutRequiresHardwareAuthToken = false; 1033 final boolean resetLockoutRequiresChallenge = false; 1034 return new SensorPropertiesInternal(sensorId, 1035 Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, 1036 componentInfo, resetLockoutRequiresHardwareAuthToken, 1037 resetLockoutRequiresChallenge); 1038 } 1039 } 1040