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