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