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