diff options
| author | 2022-08-17 18:16:40 +0000 | |
|---|---|---|
| committer | 2022-08-17 18:16:40 +0000 | |
| commit | 8f5bb9d31c36d4528223201db403812a99a01b96 (patch) | |
| tree | 6e139ae5632db5a5d5f50faf1c7c5939a5a0b655 | |
| parent | 294f4a1e79e5989ba441e88b6f2c2c1bcc9e7a2e (diff) | |
Revert "Copy startup & callback mechanism from fingerprint to face service."
This reverts commit 294f4a1e79e5989ba441e88b6f2c2c1bcc9e7a2e.
Reason for revert: b/242845336 (a few cts tests seem to pass on device locally but fail on cf postsubmit)
Change-Id: Icf36d403f96fc7a24d5191e7f43f43354a32b54f
31 files changed, 605 insertions, 1354 deletions
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java index 7247ef77afb4..7092e43596ec 100644 --- a/core/java/android/hardware/face/FaceManager.java +++ b/core/java/android/hardware/face/FaceManager.java @@ -29,7 +29,6 @@ import android.content.Context; import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricFaceConstants; -import android.hardware.biometrics.BiometricStateListener; import android.hardware.biometrics.CryptoObject; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.os.Binder; @@ -675,45 +674,6 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } /** - * Forwards BiometricStateListener to FaceService. - * - * @param listener new BiometricStateListener being added - * @hide - */ - public void registerBiometricStateListener(@NonNull BiometricStateListener listener) { - try { - mService.registerBiometricStateListener(listener); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } - - /** - * Adds a callback that gets called when the service registers all of the face - * authenticators (HALs). - * - * If the face authenticators are already registered when the callback is added, the - * callback is invoked immediately. - * - * The callback is automatically removed after it's invoked. - * - * @hide - */ - @RequiresPermission(USE_BIOMETRIC_INTERNAL) - public void addAuthenticatorsRegisteredCallback( - IFaceAuthenticatorsRegisteredCallback callback) { - if (mService != null) { - try { - mService.addAuthenticatorsRegisteredCallback(callback); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } - } else { - Slog.w(TAG, "addAuthenticatorsRegisteredCallback(): Service not connected!"); - } - } - - /** * @hide */ @RequiresPermission(USE_BIOMETRIC_INTERNAL) diff --git a/core/java/android/hardware/face/IFaceAuthenticatorsRegisteredCallback.aidl b/core/java/android/hardware/face/IFaceAuthenticatorsRegisteredCallback.aidl deleted file mode 100644 index 78f978d21ed7..000000000000 --- a/core/java/android/hardware/face/IFaceAuthenticatorsRegisteredCallback.aidl +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.hardware.face; - -import android.hardware.face.FaceSensorPropertiesInternal; -import java.util.List; - -/** - * Callback to notify FaceManager that FaceService has registered all of the - * face authenticators (HALs). - * See {@link android.hardware.face.IFaceService#registerAuthenticators}. - * - * @hide - */ -oneway interface IFaceAuthenticatorsRegisteredCallback { - /** - * Notifies FaceManager that all of the face authenticators have been registered. - * - * @param sensors A consolidated list of sensor properties for all of the authenticators. - */ - void onAllAuthenticatorsRegistered(in List<FaceSensorPropertiesInternal> sensors); -} diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index 9b56f43a0f22..369248edd580 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -17,11 +17,9 @@ package android.hardware.face; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; -import android.hardware.biometrics.IBiometricStateListener; import android.hardware.biometrics.IInvalidationCallback; import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; -import android.hardware.face.IFaceAuthenticatorsRegisteredCallback; import android.hardware.face.IFaceServiceReceiver; import android.hardware.face.Face; import android.hardware.face.FaceSensorPropertiesInternal; @@ -165,11 +163,4 @@ interface IFaceService { // hidlSensors must be non-null and empty. See AuthService.java @EnforcePermission("USE_BIOMETRIC_INTERNAL") void registerAuthenticators(in List<FaceSensorPropertiesInternal> hidlSensors); - - // Adds a callback which gets called when the service registers all of the face - // authenticators. The callback is automatically removed after it's invoked. - void addAuthenticatorsRegisteredCallback(IFaceAuthenticatorsRegisteredCallback callback); - - // Registers BiometricStateListener. - void registerBiometricStateListener(IBiometricStateListener listener); } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index 1ba9a0471c88..cc7ed183ed64 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -202,10 +202,8 @@ interface IFingerprintService { void setSidefpsController(in ISidefpsController controller); // Registers BiometricStateListener. - @EnforcePermission("USE_BIOMETRIC_INTERNAL") void registerBiometricStateListener(IBiometricStateListener listener); // Sends a power button pressed event to all listeners. - @EnforcePermission("USE_BIOMETRIC_INTERNAL") oneway void onPowerPressed(); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index d27b9ced66a7..8b5e3c11b2f6 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -54,7 +54,6 @@ import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.database.ContentObserver; import android.hardware.SensorPrivacyManager; -import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricSourceType; @@ -2020,13 +2019,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // in case authenticators aren't registered yet at this point: mAuthController.addCallback(new AuthController.Callback() { @Override - public void onAllAuthenticatorsRegistered( - @BiometricAuthenticator.Modality int modality) { + public void onAllAuthenticatorsRegistered() { mainExecutor.execute(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE)); } @Override - public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) { + public void onEnrollmentsChanged() { mainExecutor.execute(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE)); } }); diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index d6974dfac570..06e1828ef9f4 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -16,7 +16,6 @@ package com.android.keyguard; -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT; import static com.android.keyguard.LockIconView.ICON_FINGERPRINT; @@ -30,7 +29,6 @@ import android.content.res.Resources; import android.graphics.PointF; import android.graphics.Rect; import android.graphics.drawable.AnimatedStateListDrawable; -import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.biometrics.BiometricSourceType; import android.os.Process; import android.os.VibrationAttributes; @@ -703,17 +701,13 @@ public class LockIconViewController extends ViewController<LockIconView> impleme private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() { @Override - public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) { - if (modality == TYPE_FINGERPRINT) { - updateUdfpsConfig(); - } + public void onAllAuthenticatorsRegistered() { + updateUdfpsConfig(); } @Override - public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) { - if (modality == TYPE_FINGERPRINT) { - updateUdfpsConfig(); - } + public void onEnrollmentsChanged() { + updateUdfpsConfig(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index 282f25104c44..47ff59cfc281 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -46,7 +46,6 @@ import android.hardware.biometrics.PromptInfo; import android.hardware.display.DisplayManager; import android.hardware.face.FaceManager; import android.hardware.face.FaceSensorPropertiesInternal; -import android.hardware.face.IFaceAuthenticatorsRegisteredCallback; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; @@ -157,6 +156,25 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba } }; + private final IFingerprintAuthenticatorsRegisteredCallback + mFingerprintAuthenticatorsRegisteredCallback = + new IFingerprintAuthenticatorsRegisteredCallback.Stub() { + @Override + public void onAllAuthenticatorsRegistered( + List<FingerprintSensorPropertiesInternal> sensors) { + mHandler.post(() -> handleAllFingerprintAuthenticatorsRegistered(sensors)); + } + }; + + private final BiometricStateListener mBiometricStateListener = + new BiometricStateListener() { + @Override + public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { + mHandler.post( + () -> handleEnrollmentsChanged(userId, sensorId, hasEnrollments)); + } + }; + @VisibleForTesting final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override @@ -231,8 +249,8 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba List<FingerprintSensorPropertiesInternal> sensors) { mExecution.assertIsMainThread(); if (DEBUG) { - Log.d(TAG, "handleAllFingerprintAuthenticatorsRegistered | sensors: " - + Arrays.toString(sensors.toArray())); + Log.d(TAG, "handleAllAuthenticatorsRegistered | sensors: " + Arrays.toString( + sensors.toArray())); } mAllFingerprintAuthenticatorsRegistered = true; mFpProps = sensors; @@ -274,42 +292,15 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba mSidefpsController = mSidefpsControllerFactory.get(); } - mFingerprintManager.registerBiometricStateListener(new BiometricStateListener() { - @Override - public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { - mHandler.post(() -> handleEnrollmentsChanged( - TYPE_FINGERPRINT, userId, sensorId, hasEnrollments)); - } - }); + mFingerprintManager.registerBiometricStateListener(mBiometricStateListener); updateFingerprintLocation(); for (Callback cb : mCallbacks) { - cb.onAllAuthenticatorsRegistered(TYPE_FINGERPRINT); + cb.onAllAuthenticatorsRegistered(); } } - private void handleAllFaceAuthenticatorsRegistered(List<FaceSensorPropertiesInternal> sensors) { - mExecution.assertIsMainThread(); - if (DEBUG) { - Log.d(TAG, "handleAllFaceAuthenticatorsRegistered | sensors: " + Arrays.toString( - sensors.toArray())); - } - - mFaceManager.registerBiometricStateListener(new BiometricStateListener() { - @Override - public void onEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { - mHandler.post(() -> handleEnrollmentsChanged( - TYPE_FACE, userId, sensorId, hasEnrollments)); - } - }); - - for (Callback cb : mCallbacks) { - cb.onAllAuthenticatorsRegistered(TYPE_FACE); - } - } - - private void handleEnrollmentsChanged(@Modality int modality, int userId, int sensorId, - boolean hasEnrollments) { + private void handleEnrollmentsChanged(int userId, int sensorId, boolean hasEnrollments) { mExecution.assertIsMainThread(); Log.d(TAG, "handleEnrollmentsChanged, userId: " + userId + ", sensorId: " + sensorId + ", hasEnrollments: " + hasEnrollments); @@ -323,7 +314,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba } } for (Callback cb : mCallbacks) { - cb.onEnrollmentsChanged(modality); + cb.onEnrollmentsChanged(); } } @@ -709,26 +700,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba if (mFingerprintManager != null) { mFingerprintManager.addAuthenticatorsRegisteredCallback( - new IFingerprintAuthenticatorsRegisteredCallback.Stub() { - @Override - public void onAllAuthenticatorsRegistered( - List<FingerprintSensorPropertiesInternal> sensors) { - mHandler.post(() -> - handleAllFingerprintAuthenticatorsRegistered(sensors)); - } - }); - } - if (mFaceManager != null) { - mFaceManager.addAuthenticatorsRegisteredCallback( - new IFaceAuthenticatorsRegisteredCallback.Stub() { - @Override - public void onAllAuthenticatorsRegistered( - List<FaceSensorPropertiesInternal> sensors) { - mHandler.post(() -> - handleAllFaceAuthenticatorsRegistered(sensors)); - } - } - ); + mFingerprintAuthenticatorsRegisteredCallback); } mStableDisplaySize = mDisplayManager.getStableDisplaySize(); @@ -1144,13 +1116,13 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba * Called when authenticators are registered. If authenticators are already * registered before this call, this callback will never be triggered. */ - default void onAllAuthenticatorsRegistered(@Modality int modality) {} + default void onAllAuthenticatorsRegistered() {} /** - * Called when enrollments have changed. This is called after boot and on changes to + * Called when UDFPS enrollments have changed. This is called after boot and on changes to * enrollment. */ - default void onEnrollmentsChanged(@Modality int modality) {} + default void onEnrollmentsChanged() {} /** * Called when the biometric prompt starts showing. diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt index fd3f6007d8a9..38fab8ffbfad 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt @@ -308,7 +308,7 @@ class AuthRippleController @Inject constructor( private val authControllerCallback = object : AuthController.Callback { - override fun onAllAuthenticatorsRegistered(modality: Int) { + override fun onAllAuthenticatorsRegistered() { updateUdfpsDependentParams() updateSensorLocation() } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java index 7da2cf150147..a9e310d25f9c 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java @@ -16,15 +16,12 @@ package com.android.systemui.doze; -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; - import static com.android.systemui.doze.DozeMachine.State.DOZE; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSED; import static com.android.systemui.doze.DozeMachine.State.DOZE_AOD_PAUSING; import static com.android.systemui.doze.DozeMachine.State.DOZE_PULSE_DONE; -import android.hardware.biometrics.BiometricAuthenticator; import android.os.Handler; import android.util.Log; import android.view.Display; @@ -235,17 +232,13 @@ public class DozeScreenState implements DozeMachine.Part { private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() { @Override - public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) { - if (modality == TYPE_FINGERPRINT) { - updateUdfpsController(); - } + public void onAllAuthenticatorsRegistered() { + updateUdfpsController(); } @Override - public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) { - if (modality == TYPE_FINGERPRINT) { - updateUdfpsController(); - } + public void onEnrollmentsChanged() { + updateUdfpsController(); } }; } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java index 997a6e554364..da6c163b1eea 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java @@ -16,8 +16,6 @@ package com.android.systemui.doze; -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; - import static com.android.systemui.doze.DozeLog.REASON_SENSOR_QUICK_PICKUP; import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS; import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_DISPLAY; @@ -31,7 +29,6 @@ import android.hardware.Sensor; import android.hardware.SensorManager; import android.hardware.TriggerEvent; import android.hardware.TriggerEventListener; -import android.hardware.biometrics.BiometricAuthenticator; import android.hardware.display.AmbientDisplayConfiguration; import android.net.Uri; import android.os.Handler; @@ -838,17 +835,13 @@ public class DozeSensors { private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() { @Override - public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) { - if (modality == TYPE_FINGERPRINT) { - updateUdfpsEnrolled(); - } + public void onAllAuthenticatorsRegistered() { + updateUdfpsEnrolled(); } @Override - public void onEnrollmentsChanged(@BiometricAuthenticator.Modality int modality) { - if (modality == TYPE_FINGERPRINT) { - updateUdfpsEnrolled(); - } + public void onEnrollmentsChanged() { + updateUdfpsEnrolled(); } private void updateUdfpsEnrolled() { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index cde30af447f6..c67737136b3b 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -16,7 +16,6 @@ package com.android.keyguard; -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT; import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE; import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID; @@ -1006,7 +1005,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { // WHEN udfps is now enrolled when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true); - callback.onEnrollmentsChanged(TYPE_FINGERPRINT); + callback.onEnrollmentsChanged(); // THEN isUdfspEnrolled is TRUE assertThat(mKeyguardUpdateMonitor.isUdfpsEnrolled()).isTrue(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java index e0d1f7a19130..d158892e4ec5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java @@ -60,9 +60,6 @@ import android.hardware.biometrics.PromptInfo; import android.hardware.biometrics.SensorProperties; import android.hardware.display.DisplayManager; import android.hardware.face.FaceManager; -import android.hardware.face.FaceSensorProperties; -import android.hardware.face.FaceSensorPropertiesInternal; -import android.hardware.face.IFaceAuthenticatorsRegisteredCallback; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; @@ -157,9 +154,7 @@ public class AuthControllerTest extends SysuiTestCase { @Mock private InteractionJankMonitor mInteractionJankMonitor; @Captor - ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mFpAuthenticatorsRegisteredCaptor; - @Captor - ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mFaceAuthenticatorsRegisteredCaptor; + ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor; @Captor ArgumentCaptor<BiometricStateListener> mBiometricStateCaptor; @Captor @@ -198,38 +193,25 @@ public class AuthControllerTest extends SysuiTestCase { when(mDisplayManager.getStableDisplaySize()).thenReturn(new Point()); when(mFingerprintManager.isHardwareDetected()).thenReturn(true); - when(mFaceManager.isHardwareDetected()).thenReturn(true); - - final List<ComponentInfoInternal> fpComponentInfo = List.of( - new ComponentInfoInternal("faceSensor" /* componentId */, - "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */, - "00000001" /* serialNumber */, "" /* softwareVersion */)); - final List<ComponentInfoInternal> faceComponentInfo = List.of( - new ComponentInfoInternal("matchingAlgorithm" /* componentId */, - "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */, - "vendor/version/revision" /* softwareVersion */)); - - final List<FingerprintSensorPropertiesInternal> fpProps = List.of( - new FingerprintSensorPropertiesInternal( - 1 /* sensorId */, - SensorProperties.STRENGTH_STRONG, - 1 /* maxEnrollmentsPerUser */, - fpComponentInfo, - FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, - true /* resetLockoutRequireHardwareAuthToken */)); - when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(fpProps); - - final List<FaceSensorPropertiesInternal> faceProps = List.of( - new FaceSensorPropertiesInternal( - 2 /* sensorId */, - SensorProperties.STRENGTH_STRONG, - 1 /* maxEnrollmentsPerUser */, - fpComponentInfo, - FaceSensorProperties.TYPE_RGB, - true /* supportsFaceDetection */, - true /* supportsSelfIllumination */, - true /* resetLockoutRequireHardwareAuthToken */)); - when(mFaceManager.getSensorPropertiesInternal()).thenReturn(faceProps); + + final List<ComponentInfoInternal> componentInfo = new ArrayList<>(); + componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */, + "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */, + "00000001" /* serialNumber */, "" /* softwareVersion */)); + componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */, + "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */, + "vendor/version/revision" /* softwareVersion */)); + + FingerprintSensorPropertiesInternal prop = new FingerprintSensorPropertiesInternal( + 1 /* sensorId */, + SensorProperties.STRENGTH_STRONG, + 1 /* maxEnrollmentsPerUser */, + componentInfo, + FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, + true /* resetLockoutRequireHardwareAuthToken */); + List<FingerprintSensorPropertiesInternal> props = new ArrayList<>(); + props.add(prop); + when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(props); mAuthController = new TestableAuthController(mContextSpy, mExecution, mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager, @@ -237,15 +219,12 @@ public class AuthControllerTest extends SysuiTestCase { mAuthController.start(); verify(mFingerprintManager).addAuthenticatorsRegisteredCallback( - mFpAuthenticatorsRegisteredCaptor.capture()); - verify(mFaceManager).addAuthenticatorsRegisteredCallback( - mFaceAuthenticatorsRegisteredCaptor.capture()); + mAuthenticatorsRegisteredCaptor.capture()); when(mStatusBarStateController.isDozing()).thenReturn(false); verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture()); - mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(fpProps); - mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(faceProps); + mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(props); // Ensures that the operations posted on the handler get executed. mTestableLooper.processAllMessages(); @@ -258,7 +237,6 @@ public class AuthControllerTest extends SysuiTestCase { throws RemoteException { // This test is sensitive to prior FingerprintManager interactions. reset(mFingerprintManager); - reset(mFaceManager); // This test requires an uninitialized AuthController. AuthController authController = new TestableAuthController(mContextSpy, mExecution, @@ -268,27 +246,21 @@ public class AuthControllerTest extends SysuiTestCase { authController.start(); verify(mFingerprintManager).addAuthenticatorsRegisteredCallback( - mFpAuthenticatorsRegisteredCaptor.capture()); - verify(mFaceManager).addAuthenticatorsRegisteredCallback( - mFaceAuthenticatorsRegisteredCaptor.capture()); + mAuthenticatorsRegisteredCaptor.capture()); mTestableLooper.processAllMessages(); verify(mFingerprintManager, never()).registerBiometricStateListener(any()); - verify(mFaceManager, never()).registerBiometricStateListener(any()); - mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of()); - mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of()); + mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(new ArrayList<>()); mTestableLooper.processAllMessages(); verify(mFingerprintManager).registerBiometricStateListener(any()); - verify(mFaceManager).registerBiometricStateListener(any()); } @Test public void testDoesNotCrash_afterEnrollmentsChangedForUnknownSensor() throws RemoteException { // This test is sensitive to prior FingerprintManager interactions. reset(mFingerprintManager); - reset(mFaceManager); // This test requires an uninitialized AuthController. AuthController authController = new TestableAuthController(mContextSpy, mExecution, @@ -298,25 +270,18 @@ public class AuthControllerTest extends SysuiTestCase { authController.start(); verify(mFingerprintManager).addAuthenticatorsRegisteredCallback( - mFpAuthenticatorsRegisteredCaptor.capture()); - verify(mFaceManager).addAuthenticatorsRegisteredCallback( - mFaceAuthenticatorsRegisteredCaptor.capture()); + mAuthenticatorsRegisteredCaptor.capture()); // Emulates a device with no authenticators (empty list). - mFpAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of()); - mFaceAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(List.of()); + mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(new ArrayList<>()); mTestableLooper.processAllMessages(); verify(mFingerprintManager).registerBiometricStateListener( mBiometricStateCaptor.capture()); - verify(mFaceManager).registerBiometricStateListener( - mBiometricStateCaptor.capture()); // Enrollments changed for an unknown sensor. - for (BiometricStateListener listener : mBiometricStateCaptor.getAllValues()) { - listener.onEnrollmentsChanged(0 /* userId */, - 0xbeef /* sensorId */, true /* hasEnrollments */); - } + mBiometricStateCaptor.getValue().onEnrollmentsChanged(0 /* userId */, + 0xbeef /* sensorId */, true /* hasEnrollments */); mTestableLooper.processAllMessages(); // Nothing should crash. @@ -862,3 +827,4 @@ public class AuthControllerTest extends SysuiTestCase { } } } + diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java index b33f9a7f3933..9ffc5a57cef6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java @@ -16,8 +16,6 @@ package com.android.systemui.doze; -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; - import static com.android.systemui.doze.DozeLog.REASON_SENSOR_TAP; import static com.android.systemui.doze.DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS; import static com.android.systemui.plugins.SensorManagerPlugin.Sensor.TYPE_WAKE_LOCK_SCREEN; @@ -414,7 +412,7 @@ public class DozeSensorsTest extends SysuiTestCase { // WHEN enrollment changes to TRUE when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(true); - mAuthControllerCallback.onEnrollmentsChanged(TYPE_FINGERPRINT); + mAuthControllerCallback.onEnrollmentsChanged(); // THEN mConfigured = TRUE assertTrue(triggerSensor.mConfigured); diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java index 5ec6bdf3c00b..24d051508fde 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java @@ -16,8 +16,6 @@ package com.android.systemui.keyguard; -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; - import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.keyguard.LockIconView.ICON_LOCK; import static com.android.keyguard.LockIconView.ICON_UNLOCK; @@ -221,7 +219,7 @@ public class LockIconViewControllerTest extends SysuiTestCase { Pair<Float, PointF> udfps = setupUdfps(); // WHEN all authenticators are registered - mAuthControllerCallback.onAllAuthenticatorsRegistered(TYPE_FINGERPRINT); + mAuthControllerCallback.onAllAuthenticatorsRegistered(); mDelayableExecutor.runAllReady(); // THEN lock icon view location is updated with the same coordinates as auth controller vals diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java deleted file mode 100644 index 0f1fe68ad1d7..000000000000 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceProvider.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.biometrics.sensors; - -import android.annotation.NonNull; -import android.hardware.biometrics.SensorPropertiesInternal; -import android.util.proto.ProtoOutputStream; - -import java.io.FileDescriptor; -import java.io.PrintWriter; -import java.util.List; - -/** - * Common attributes for all biometric service providers. - * - * @param <T> Internal settings type. - */ -public interface BiometricServiceProvider<T extends SensorPropertiesInternal> { - - /** Checks if the specified sensor is owned by this provider. */ - boolean containsSensor(int sensorId); - - /** All sensor properties. */ - @NonNull - List<T> getSensorProperties(); - - /** Properties for the given sensor id. */ - @NonNull - T getSensorProperties(int sensorId); - - boolean isHardwareDetected(int sensorId); - - /** If the user has any enrollments for the given sensor. */ - boolean hasEnrollments(int sensorId, int userId); - - long getAuthenticatorId(int sensorId, int userId); - - @LockoutTracker.LockoutMode - int getLockoutModeForUser(int sensorId, int userId); - - void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, - boolean clearSchedulerBuffer); - - void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd); - - void dumpInternal(int sensorId, @NonNull PrintWriter pw); -} diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceRegistry.java b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceRegistry.java deleted file mode 100644 index 7574523f0662..000000000000 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceRegistry.java +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.biometrics.sensors; - - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.hardware.biometrics.IBiometricAuthenticator; -import android.hardware.biometrics.IBiometricService; -import android.hardware.biometrics.SensorPropertiesInternal; -import android.os.Handler; -import android.os.IInterface; -import android.os.Process; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.util.Pair; -import android.util.Slog; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.server.ServiceThread; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.function.Supplier; - -/** - * Container for all BiometricServiceProvider implementations. - * - * @param <T> The service provider type. - * @param <P> The internal properties type. - * @param <C> The registration callback for {@link #invokeRegisteredCallback(IInterface, List)}. - */ -public abstract class BiometricServiceRegistry<T extends BiometricServiceProvider<P>, - P extends SensorPropertiesInternal, - C extends IInterface> { - - private static final String TAG = "BiometricServiceRegistry"; - - // Volatile so they can be read without a lock once all services are registered. - // But, ideally remove this and provide immutable copies via the callback instead. - @Nullable - private volatile List<T> mServiceProviders; - @Nullable - private volatile List<P> mAllProps; - - @NonNull - private final Supplier<IBiometricService> mBiometricServiceSupplier; - @NonNull - private final RemoteCallbackList<C> mRegisteredCallbacks = new RemoteCallbackList<>(); - - public BiometricServiceRegistry(@NonNull Supplier<IBiometricService> biometricSupplier) { - mBiometricServiceSupplier = biometricSupplier; - } - - /** - * Register an implementation by creating a new authenticator and initializing it via - * {@link IBiometricService#registerAuthenticator(int, int, int, IBiometricAuthenticator)} - * using the given properties. - * - * @param service service to register with - * @param props internal properties to initialize the authenticator - */ - protected abstract void registerService(@NonNull IBiometricService service, @NonNull P props); - - /** - * Invoke the callback to notify clients that all authenticators have been registered. - * - * @param callback callback to invoke - * @param allProps properties of all authenticators - */ - protected abstract void invokeRegisteredCallback(@NonNull C callback, - @NonNull List<P> allProps) throws RemoteException; - - /** - * Register all authenticators in a background thread. - * - * @param serviceProvider Supplier function that will be invoked on the background thread. - */ - public void registerAll(Supplier<List<T>> serviceProvider) { - // Some HAL might not be started before the system service and will cause the code below - // to wait, and some of the operations below might take a significant amount of time to - // complete (calls to the HALs). To avoid blocking the rest of system server we put - // this on a background thread. - final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, - true /* allowIo */); - thread.start(); - final Handler handler = new Handler(thread.getLooper()); - handler.post(() -> registerAllInBackground(serviceProvider)); - thread.quitSafely(); - } - - /** Register authenticators now, only called by {@link #registerAll(Supplier).} */ - @VisibleForTesting - public void registerAllInBackground(Supplier<List<T>> serviceProvider) { - List<T> providers = serviceProvider.get(); - if (providers == null) { - providers = new ArrayList<>(); - } - - final IBiometricService biometricService = mBiometricServiceSupplier.get(); - if (biometricService == null) { - throw new IllegalStateException("biometric service cannot be null"); - } - - // Register each sensor individually with BiometricService - final List<P> allProps = new ArrayList<>(); - for (T provider : providers) { - final List<P> props = provider.getSensorProperties(); - for (P prop : props) { - registerService(biometricService, prop); - } - allProps.addAll(props); - } - - finishRegistration(providers, allProps); - } - - private synchronized void finishRegistration( - @NonNull List<T> providers, @NonNull List<P> allProps) { - mServiceProviders = Collections.unmodifiableList(providers); - mAllProps = Collections.unmodifiableList(allProps); - broadcastAllAuthenticatorsRegistered(); - } - - /** - * Add a callback that will be invoked once the work from {@link #registerAll(Supplier)} - * has finished registering all providers (executes immediately if already done). - * - * @param callback registration callback - */ - public synchronized void addAllRegisteredCallback(@Nullable C callback) { - if (callback == null) { - Slog.e(TAG, "addAllRegisteredCallback, callback is null"); - return; - } - - final boolean registered = mRegisteredCallbacks.register(callback); - final boolean allRegistered = mServiceProviders != null; - if (registered && allRegistered) { - broadcastAllAuthenticatorsRegistered(); - } else if (!registered) { - Slog.e(TAG, "addAllRegisteredCallback failed to register callback"); - } - } - - private synchronized void broadcastAllAuthenticatorsRegistered() { - final int n = mRegisteredCallbacks.beginBroadcast(); - for (int i = 0; i < n; ++i) { - final C cb = mRegisteredCallbacks.getBroadcastItem(i); - try { - invokeRegisteredCallback(cb, mAllProps); - } catch (RemoteException e) { - Slog.e(TAG, "Remote exception in broadcastAllAuthenticatorsRegistered", e); - } finally { - mRegisteredCallbacks.unregister(cb); - } - } - mRegisteredCallbacks.finishBroadcast(); - } - - /** - * Get a list of registered providers. - * - * Undefined until {@link #registerAll(Supplier)} has fired the completion callback. - */ - @NonNull - public List<T> getProviders() { - return mServiceProviders != null ? mServiceProviders : Collections.emptyList(); - } - - /** - * Gets the provider for given sensor id or null if not registered. - * - * Undefined until {@link #registerAll(Supplier)} has fired the completion callback. - */ - @Nullable - public T getProviderForSensor(int sensorId) { - if (mServiceProviders != null) { - for (T provider : mServiceProviders) { - if (provider.containsSensor(sensorId)) { - return provider; - } - } - } - return null; - } - - /** - * For devices with only a single provider, returns that provider. - * If no providers, or multiple providers exist, returns null. - * - * Undefined until {@link #registerAll(Supplier)} has fired the completion callback. - */ - @Nullable - public Pair<Integer, T> getSingleProvider() { - if (mAllProps == null || mAllProps.size() != 1) { - Slog.e(TAG, "Multiple sensors found: " + mAllProps.size()); - return null; - } - - final int sensorId = mAllProps.get(0).sensorId; - final T provider = getProviderForSensor(sensorId); - if (provider != null) { - return new Pair<>(sensorId, provider); - } - - Slog.e(TAG, "Single sensor, but provider not found"); - return null; - } - - /** - * Get the properties for all providers. - * - * Undefined until {@link #registerAll(Supplier)} has fired the completion callback. - */ - @NonNull - public List<P> getAllProperties() { - return mAllProps != null ? mAllProps : Collections.emptyList(); - } -} diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java index f8543162f95e..0d789f7a1840 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricStateCallback.java @@ -23,64 +23,32 @@ import static android.hardware.biometrics.BiometricStateListener.STATE_IDLE; import static android.hardware.biometrics.BiometricStateListener.STATE_KEYGUARD_AUTH; import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricStateListener; import android.hardware.biometrics.IBiometricStateListener; -import android.hardware.biometrics.SensorPropertiesInternal; import android.os.RemoteException; -import android.os.UserManager; import android.util.Slog; import com.android.server.biometrics.Utils; -import java.util.Collections; -import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; /** * A callback for receiving notifications about biometric sensor state changes. - * - * @param <T> service provider type - * @param <P> internal property type */ -public class BiometricStateCallback<T extends BiometricServiceProvider<P>, - P extends SensorPropertiesInternal> implements ClientMonitorCallback { +public class BiometricStateCallback implements ClientMonitorCallback { private static final String TAG = "BiometricStateCallback"; @NonNull - private final CopyOnWriteArrayList<IBiometricStateListener> mBiometricStateListeners = - new CopyOnWriteArrayList<>(); - @NonNull - private final UserManager mUserManager; - @BiometricStateListener.State - private int mBiometricState; - @NonNull - private List<T> mProviders = List.of(); + private final CopyOnWriteArrayList<IBiometricStateListener> + mBiometricStateListeners = new CopyOnWriteArrayList<>(); - /** - * Create a new callback that must be {@link #start(List)}ed. - * - * @param userManager user manager - */ - public BiometricStateCallback(@NonNull UserManager userManager) { - mBiometricState = STATE_IDLE; - mUserManager = userManager; - } + private @BiometricStateListener.State int mBiometricState; - /** - * This should be called when the service has been initialized and all providers are ready. - * - * @param allProviders all registered biometric service providers - */ - public synchronized void start(@NonNull List<T> allProviders) { - mProviders = Collections.unmodifiableList(allProviders); - broadcastCurrentEnrollmentState(null /* listener */); + public BiometricStateCallback() { + mBiometricState = STATE_IDLE; } - /** Get the current state. */ - @BiometricStateListener.State public int getBiometricState() { return mBiometricState; } @@ -152,43 +120,23 @@ public class BiometricStateCallback<T extends BiometricServiceProvider<P>, } /** - * Enables clients to register a BiometricStateListener. For example, this is used to forward - * fingerprint sensor state changes to SideFpsEventHandler. - * - * @param listener listener to register + * This should be invoked when: + * 1) Enrolled --> None-enrolled + * 2) None-enrolled --> enrolled + * 3) HAL becomes ready + * 4) Listener is registered */ - public synchronized void registerBiometricStateListener( - @NonNull IBiometricStateListener listener) { - mBiometricStateListeners.add(listener); - broadcastCurrentEnrollmentState(listener); - } - - private synchronized void broadcastCurrentEnrollmentState( - @Nullable IBiometricStateListener listener) { - for (T provider : mProviders) { - for (SensorPropertiesInternal prop : provider.getSensorProperties()) { - for (UserInfo userInfo : mUserManager.getAliveUsers()) { - final boolean enrolled = provider.hasEnrollments(prop.sensorId, userInfo.id); - if (listener != null) { - notifyEnrollmentStateChanged( - listener, userInfo.id, prop.sensorId, enrolled); - } else { - notifyAllEnrollmentStateChanged( - userInfo.id, prop.sensorId, enrolled); - } - } - } - } - } - - private void notifyAllEnrollmentStateChanged(int userId, int sensorId, + public void notifyAllEnrollmentStateChanged(int userId, int sensorId, boolean hasEnrollments) { for (IBiometricStateListener listener : mBiometricStateListeners) { notifyEnrollmentStateChanged(listener, userId, sensorId, hasEnrollments); } } - private void notifyEnrollmentStateChanged(@NonNull IBiometricStateListener listener, + /** + * Notifies the listener of enrollment state changes. + */ + public void notifyEnrollmentStateChanged(@NonNull IBiometricStateListener listener, int userId, int sensorId, boolean hasEnrollments) { try { listener.onEnrollmentsChanged(userId, sensorId, hasEnrollments); @@ -196,4 +144,14 @@ public class BiometricStateCallback<T extends BiometricServiceProvider<P>, Slog.e(TAG, "Remote exception", e); } } + + /** + * Enables clients to register a BiometricStateListener. For example, this is used to forward + * fingerprint sensor state changes to SideFpsEventHandler. + * + * @param listener + */ + public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) { + mBiometricStateListeners.add(listener); + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java index 271bce9890c6..79e65cc6d2e5 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java @@ -17,18 +17,20 @@ package com.android.server.biometrics.sensors.face; import static android.Manifest.permission.INTERACT_ACROSS_USERS; +import static android.Manifest.permission.MANAGE_BIOMETRIC; import static android.Manifest.permission.MANAGE_FACE; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.content.Context; +import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricSensorReceiver; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; -import android.hardware.biometrics.IBiometricStateListener; import android.hardware.biometrics.IInvalidationCallback; import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; @@ -37,18 +39,18 @@ import android.hardware.biometrics.face.SensorProps; import android.hardware.face.Face; import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.face.FaceServiceReceiver; -import android.hardware.face.IFaceAuthenticatorsRegisteredCallback; import android.hardware.face.IFaceService; import android.hardware.face.IFaceServiceReceiver; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; import android.os.NativeHandle; +import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.ShellCallback; import android.os.UserHandle; -import android.os.UserManager; import android.util.Pair; import android.util.Slog; import android.util.proto.ProtoOutputStream; @@ -56,10 +58,10 @@ import android.view.Surface; import com.android.internal.util.DumpUtils; import com.android.internal.widget.LockPatternUtils; +import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.biometrics.Utils; import com.android.server.biometrics.log.BiometricContext; -import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; @@ -86,10 +88,51 @@ public class FaceService extends SystemService { private final LockoutResetDispatcher mLockoutResetDispatcher; private final LockPatternUtils mLockPatternUtils; @NonNull - private final FaceServiceRegistry mRegistry; + private final List<ServiceProvider> mServiceProviders; + + @Nullable + private ServiceProvider getProviderForSensor(int sensorId) { + for (ServiceProvider provider : mServiceProviders) { + if (provider.containsSensor(sensorId)) { + return provider; + } + } + return null; + } + + /** + * For devices with only a single provider, returns that provider. If no providers, or multiple + * providers exist, returns null. + */ + @Nullable + private Pair<Integer, ServiceProvider> getSingleProvider() { + final List<FaceSensorPropertiesInternal> properties = getSensorProperties(); + if (properties.size() != 1) { + Slog.e(TAG, "Multiple sensors found: " + properties.size()); + return null; + } + + // Theoretically we can just return the first provider, but maybe this is easier to + // understand. + final int sensorId = properties.get(0).sensorId; + for (ServiceProvider provider : mServiceProviders) { + if (provider.containsSensor(sensorId)) { + return new Pair<>(sensorId, provider); + } + } + + Slog.e(TAG, "Single sensor, but provider not found"); + return null; + } + @NonNull - private final BiometricStateCallback<ServiceProvider, FaceSensorPropertiesInternal> - mBiometricStateCallback; + private List<FaceSensorPropertiesInternal> getSensorProperties() { + final List<FaceSensorPropertiesInternal> properties = new ArrayList<>(); + for (ServiceProvider provider : mServiceProviders) { + properties.addAll(provider.getSensorProperties()); + } + return properties; + } /** * Receives the incoming binder calls from FaceManager. @@ -99,7 +142,8 @@ public class FaceService extends SystemService { @Override public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, @NonNull String opPackageName) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for createTestSession, sensorId: " + sensorId); @@ -112,8 +156,9 @@ public class FaceService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer) { + final ProtoOutputStream proto = new ProtoOutputStream(); - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider != null) { provider.dumpProtoState(sensorId, proto, clearSchedulerBuffer); } @@ -125,14 +170,16 @@ public class FaceService extends SystemService { @Override // Binder call public List<FaceSensorPropertiesInternal> getSensorPropertiesInternal( String opPackageName) { - return mRegistry.getAllProperties(); + + return FaceService.this.getSensorProperties(); } @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public FaceSensorPropertiesInternal getSensorProperties(int sensorId, @NonNull String opPackageName) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "No matching sensor for getSensorProperties, sensorId: " + sensorId + ", caller: " + opPackageName); @@ -146,7 +193,8 @@ public class FaceService extends SystemService { @Override // Binder call public void generateChallenge(IBinder token, int sensorId, int userId, IFaceServiceReceiver receiver, String opPackageName) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId); return; @@ -159,7 +207,8 @@ public class FaceService extends SystemService { @Override // Binder call public void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName, long challenge) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId); return; @@ -173,7 +222,8 @@ public class FaceService extends SystemService { public long enroll(int userId, final IBinder token, final byte[] hardwareAuthToken, final IFaceServiceReceiver receiver, final String opPackageName, final int[] disabledFeatures, Surface previewSurface, boolean debugConsent) { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for enroll"); return -1; @@ -195,7 +245,8 @@ public class FaceService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_BIOMETRIC) @Override // Binder call public void cancelEnrollment(final IBinder token, long requestId) { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for cancelEnrollment"); return; @@ -209,6 +260,7 @@ public class FaceService extends SystemService { public long authenticate(final IBinder token, final long operationId, int userId, final IFaceServiceReceiver receiver, final String opPackageName, boolean isKeyguardBypassEnabled) { + // TODO(b/152413782): If the sensor supports face detect and the device is encrypted or // lockdown, something wrong happened. See similar path in FingerprintService. @@ -221,7 +273,7 @@ public class FaceService extends SystemService { // permission. final boolean isKeyguard = Utils.isKeyguard(getContext(), opPackageName); - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for authenticate"); return -1; @@ -249,7 +301,7 @@ public class FaceService extends SystemService { return -1; } - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for detectFace"); return -1; @@ -266,7 +318,8 @@ public class FaceService extends SystemService { IBinder token, long operationId, int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for prepareForAuthentication"); return; @@ -283,7 +336,8 @@ public class FaceService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public void startPreparedClient(int sensorId, int cookie) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for startPreparedClient"); return; @@ -296,7 +350,8 @@ public class FaceService extends SystemService { @Override // Binder call public void cancelAuthentication(final IBinder token, final String opPackageName, final long requestId) { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for cancelAuthentication"); return; @@ -315,7 +370,7 @@ public class FaceService extends SystemService { return; } - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for cancelFaceDetect"); return; @@ -328,7 +383,8 @@ public class FaceService extends SystemService { @Override // Binder call public void cancelAuthenticationFromService(int sensorId, final IBinder token, final String opPackageName, final long requestId) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for cancelAuthenticationFromService"); return; @@ -341,7 +397,8 @@ public class FaceService extends SystemService { @Override // Binder call public void remove(final IBinder token, final int faceId, final int userId, final IFaceServiceReceiver receiver, final String opPackageName) { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for remove"); return; @@ -355,6 +412,7 @@ public class FaceService extends SystemService { @Override // Binder call public void removeAll(final IBinder token, final int userId, final IFaceServiceReceiver receiver, final String opPackageName) { + final FaceServiceReceiver internalReceiver = new FaceServiceReceiver() { int sensorsFinishedRemoving = 0; final int numSensors = getSensorPropertiesInternal( @@ -374,7 +432,7 @@ public class FaceService extends SystemService { // This effectively iterates through all sensors, but has to do so by finding all // sensors under each provider. - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { List<FaceSensorPropertiesInternal> props = provider.getSensorProperties(); for (FaceSensorPropertiesInternal prop : props) { provider.scheduleRemoveAll(prop.sensorId, token, userId, internalReceiver, @@ -409,27 +467,27 @@ public class FaceService extends SystemService { try { if (args.length > 1 && "--proto".equals(args[0]) && "--state".equals(args[1])) { final ProtoOutputStream proto = new ProtoOutputStream(fd); - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) { provider.dumpProtoState(props.sensorId, proto, false); } } proto.flush(); } else if (args.length > 0 && "--proto".equals(args[0])) { - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) { provider.dumpProtoMetrics(props.sensorId, fd); } } } else if (args.length > 1 && "--hal".equals(args[0])) { - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) { provider.dumpHal(props.sensorId, fd, Arrays.copyOfRange(args, 1, args.length, args.getClass())); } } } else { - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) { pw.println("Dumping for sensorId: " + props.sensorId + ", provider: " + provider.getClass().getSimpleName()); @@ -446,9 +504,10 @@ public class FaceService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public boolean isHardwareDetected(int sensorId, String opPackageName) { + final long token = Binder.clearCallingIdentity(); try { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for isHardwareDetected, caller: " + opPackageName); return false; @@ -462,11 +521,12 @@ public class FaceService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public List<Face> getEnrolledFaces(int sensorId, int userId, String opPackageName) { + if (userId != UserHandle.getCallingUserId()) { Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS); } - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for getEnrolledFaces, caller: " + opPackageName); return Collections.emptyList(); @@ -478,11 +538,12 @@ public class FaceService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public boolean hasEnrolledFaces(int sensorId, int userId, String opPackageName) { + if (userId != UserHandle.getCallingUserId()) { Utils.checkPermission(getContext(), INTERACT_ACROSS_USERS); } - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for hasEnrolledFaces, caller: " + opPackageName); return false; @@ -494,7 +555,8 @@ public class FaceService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public @LockoutTracker.LockoutMode int getLockoutModeForUser(int sensorId, int userId) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for getLockoutModeForUser"); return LockoutTracker.LOCKOUT_NONE; @@ -507,7 +569,8 @@ public class FaceService extends SystemService { @Override public void invalidateAuthenticatorId(int sensorId, int userId, IInvalidationCallback callback) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for invalidateAuthenticatorId"); return; @@ -519,7 +582,7 @@ public class FaceService extends SystemService { @Override // Binder call public long getAuthenticatorId(int sensorId, int userId) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for getAuthenticatorId"); return 0; @@ -532,7 +595,8 @@ public class FaceService extends SystemService { @Override // Binder call public void resetLockout(IBinder token, int sensorId, int userId, byte[] hardwareAuthToken, String opPackageName) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for resetLockout, caller: " + opPackageName); return; @@ -546,7 +610,8 @@ public class FaceService extends SystemService { public void setFeature(final IBinder token, int userId, int feature, boolean enabled, final byte[] hardwareAuthToken, IFaceServiceReceiver receiver, final String opPackageName) { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for setFeature"); return; @@ -560,7 +625,8 @@ public class FaceService extends SystemService { @Override public void getFeature(final IBinder token, int userId, int feature, IFaceServiceReceiver receiver, final String opPackageName) { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for getFeature"); return; @@ -570,14 +636,18 @@ public class FaceService extends SystemService { new ClientMonitorCallbackConverter(receiver), opPackageName); } - private List<ServiceProvider> getAidlProviders() { - final List<ServiceProvider> providers = new ArrayList<>(); + private void addHidlProviders(@NonNull List<FaceSensorPropertiesInternal> hidlSensors) { + for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) { + mServiceProviders.add( + Face10.newInstance(getContext(), hidlSensor, mLockoutResetDispatcher)); + } + } + private void addAidlProviders() { final String[] instances = ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR); if (instances == null || instances.length == 0) { - return providers; + return; } - for (String instance : instances) { final String fqName = IFace.DESCRIPTOR + "/" + instance; final IFace face = IFace.Stub.asInterface( @@ -590,41 +660,53 @@ public class FaceService extends SystemService { final SensorProps[] props = face.getSensorProps(); final FaceProvider provider = new FaceProvider(getContext(), props, instance, mLockoutResetDispatcher, BiometricContext.getInstance(getContext())); - providers.add(provider); + mServiceProviders.add(provider); } catch (RemoteException e) { Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); } } - - return providers; } @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public void registerAuthenticators( @NonNull List<FaceSensorPropertiesInternal> hidlSensors) { - mRegistry.registerAll(() -> { - final List<ServiceProvider> providers = new ArrayList<>(); - for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) { - providers.add( - Face10.newInstance(getContext(), hidlSensor, mLockoutResetDispatcher)); + + // Some HAL might not be started before the system service and will cause the code below + // to wait, and some of the operations below might take a significant amount of time to + // complete (calls to the HALs). To avoid blocking the rest of system server we put + // this on a background thread. + final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, + true /* allowIo */); + thread.start(); + final Handler handler = new Handler(thread.getLooper()); + + handler.post(() -> { + addHidlProviders(hidlSensors); + addAidlProviders(); + + final IBiometricService biometricService = IBiometricService.Stub.asInterface( + ServiceManager.getService(Context.BIOMETRIC_SERVICE)); + + // Register each sensor individually with BiometricService + for (ServiceProvider provider : mServiceProviders) { + final List<FaceSensorPropertiesInternal> props = provider.getSensorProperties(); + for (FaceSensorPropertiesInternal prop : props) { + final int sensorId = prop.sensorId; + final @BiometricManager.Authenticators.Types int strength = + Utils.propertyStrengthToAuthenticatorStrength(prop.sensorStrength); + final FaceAuthenticator authenticator = new FaceAuthenticator( + mServiceWrapper, sensorId); + try { + biometricService.registerAuthenticator(sensorId, TYPE_FACE, strength, + authenticator); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when registering sensorId: " + sensorId); + } + } } - providers.addAll(getAidlProviders()); - return providers; }); } - - @Override - public void addAuthenticatorsRegisteredCallback( - IFaceAuthenticatorsRegisteredCallback callback) { - Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); - mRegistry.addAllRegisteredCallback(callback); - } - - @Override - public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) { - mBiometricStateCallback.registerBiometricStateListener(listener); - } } public FaceService(Context context) { @@ -632,16 +714,7 @@ public class FaceService extends SystemService { mServiceWrapper = new FaceServiceWrapper(); mLockoutResetDispatcher = new LockoutResetDispatcher(context); mLockPatternUtils = new LockPatternUtils(context); - mBiometricStateCallback = new BiometricStateCallback<>(UserManager.get(context)); - mRegistry = new FaceServiceRegistry(mServiceWrapper, - () -> IBiometricService.Stub.asInterface( - ServiceManager.getService(Context.BIOMETRIC_SERVICE))); - mRegistry.addAllRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() { - @Override - public void onAllAuthenticatorsRegistered(List<FaceSensorPropertiesInternal> sensors) { - mBiometricStateCallback.start(mRegistry.getProviders()); - } - }); + mServiceProviders = new ArrayList<>(); } @Override @@ -679,7 +752,7 @@ public class FaceService extends SystemService { if (Utils.isVirtualEnabled(getContext())) { Slog.i(TAG, "Sync virtual enrollments"); final int userId = ActivityManager.getCurrentUser(); - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { for (FaceSensorPropertiesInternal props : provider.getSensorProperties()) { provider.scheduleInternalCleanup(props.sensorId, userId, null /* callback */, true /* favorHalEnrollments */); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceServiceRegistry.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceServiceRegistry.java deleted file mode 100644 index 0f0a81d24473..000000000000 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceServiceRegistry.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.biometrics.sensors.face; - -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.hardware.biometrics.BiometricManager; -import android.hardware.biometrics.IBiometricService; -import android.hardware.face.FaceSensorPropertiesInternal; -import android.hardware.face.IFaceAuthenticatorsRegisteredCallback; -import android.hardware.face.IFaceService; -import android.os.RemoteException; -import android.util.Slog; - -import com.android.server.biometrics.Utils; -import com.android.server.biometrics.sensors.BiometricServiceRegistry; - -import java.util.List; -import java.util.function.Supplier; - -/** Registry for {@link IFaceService} providers. */ -public class FaceServiceRegistry extends BiometricServiceRegistry<ServiceProvider, - FaceSensorPropertiesInternal, IFaceAuthenticatorsRegisteredCallback> { - - private static final String TAG = "FaceServiceRegistry"; - - @NonNull - private final IFaceService mService; - - /** Creates a new registry tied to the given service. */ - public FaceServiceRegistry(@NonNull IFaceService service, - @Nullable Supplier<IBiometricService> biometricSupplier) { - super(biometricSupplier); - mService = service; - } - - @Override - protected void registerService(@NonNull IBiometricService service, - @NonNull FaceSensorPropertiesInternal props) { - @BiometricManager.Authenticators.Types final int strength = - Utils.propertyStrengthToAuthenticatorStrength(props.sensorStrength); - try { - service.registerAuthenticator(props.sensorId, TYPE_FACE, strength, - new FaceAuthenticator(mService, props.sensorId)); - } catch (RemoteException e) { - Slog.e(TAG, "Remote exception when registering sensorId: " + props.sensorId); - } - } - - @Override - protected void invokeRegisteredCallback(@NonNull IFaceAuthenticatorsRegisteredCallback callback, - @NonNull List<FaceSensorPropertiesInternal> allProps) throws RemoteException { - callback.onAllAuthenticatorsRegistered(allProps); - } -} diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java index 4efaedbd5530..6f98365332e2 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java @@ -26,13 +26,15 @@ import android.hardware.face.FaceManager; import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.face.IFaceServiceReceiver; import android.os.IBinder; +import android.util.proto.ProtoOutputStream; import android.view.Surface; -import com.android.server.biometrics.sensors.BiometricServiceProvider; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; +import com.android.server.biometrics.sensors.LockoutTracker; import java.io.FileDescriptor; +import java.io.PrintWriter; import java.util.List; /** @@ -54,11 +56,24 @@ import java.util.List; * to check (e.g. via {@link FaceManager#getSensorPropertiesInternal()}) that the code path isn't * taken. ServiceProviders will provide a no-op for unsupported operations to fail safely. */ -public interface ServiceProvider extends BiometricServiceProvider<FaceSensorPropertiesInternal> { +public interface ServiceProvider { + /** + * Checks if the specified sensor is owned by this provider. + */ + boolean containsSensor(int sensorId); + + @NonNull + List<FaceSensorPropertiesInternal> getSensorProperties(); + + @NonNull + FaceSensorPropertiesInternal getSensorProperties(int sensorId); @NonNull List<Face> getEnrolledFaces(int sensorId, int userId); + @LockoutTracker.LockoutMode + int getLockoutModeForUser(int sensorId, int userId); + /** * Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to be * invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient} @@ -69,6 +84,10 @@ public interface ServiceProvider extends BiometricServiceProvider<FaceSensorProp + " this method"); } + long getAuthenticatorId(int sensorId, int userId); + + boolean isHardwareDetected(int sensorId); + void scheduleGenerateChallenge(int sensorId, int userId, @NonNull IBinder token, @NonNull IFaceServiceReceiver receiver, String opPackageName); @@ -123,6 +142,13 @@ public interface ServiceProvider extends BiometricServiceProvider<FaceSensorProp void scheduleInternalCleanup(int sensorId, int userId, @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments); + void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, + boolean clearSchedulerBuffer); + + void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd); + + void dumpInternal(int sensorId, @NonNull PrintWriter pw); + @NonNull ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, @NonNull String opPackageName); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java index 6bff179e8eb7..19d54c84c706 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java @@ -285,11 +285,6 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { } @Override - public boolean hasEnrollments(int sensorId, int userId) { - return !getEnrolledFaces(sensorId, userId).isEmpty(); - } - - @Override public void scheduleInvalidateAuthenticatorId(int sensorId, int userId, @NonNull IInvalidationCallback callback) { mHandler.post(() -> { diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java index c0a119ff5f1e..65289122747c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java @@ -484,11 +484,6 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { } @Override - public boolean hasEnrollments(int sensorId, int userId) { - return !getEnrolledFaces(sensorId, userId).isEmpty(); - } - - @Override @LockoutTracker.LockoutMode public int getLockoutModeForUser(int sensorId, int userId) { return mLockoutTracker.getLockoutModeForUser(userId); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index 7e2742edd47a..2ba449ae089e 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -17,11 +17,14 @@ package com.android.server.biometrics.sensors.fingerprint; import static android.Manifest.permission.INTERACT_ACROSS_USERS; +import static android.Manifest.permission.MANAGE_BIOMETRIC; import static android.Manifest.permission.MANAGE_FINGERPRINT; +import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT; import static android.Manifest.permission.TEST_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; import static android.Manifest.permission.USE_FINGERPRINT; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_USER_CANCELED; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_VENDOR; @@ -33,6 +36,8 @@ import android.app.ActivityManager; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; +import android.content.pm.UserInfo; +import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricPrompt; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricSensorReceiver; @@ -60,6 +65,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Process; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; @@ -73,9 +79,11 @@ import android.util.Slog; import android.util.proto.ProtoOutputStream; import com.android.internal.R; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.DumpUtils; import com.android.internal.widget.LockPatternUtils; +import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.biometrics.Utils; import com.android.server.biometrics.log.BiometricContext; @@ -107,32 +115,74 @@ public class FingerprintService extends SystemService { protected static final String TAG = "FingerprintService"; + private final Object mLock = new Object(); private final AppOpsManager mAppOps; private final LockoutResetDispatcher mLockoutResetDispatcher; private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher; private final LockPatternUtils mLockPatternUtils; - @NonNull - private final BiometricContext mBiometricContext; - @NonNull - private final Supplier<String[]> mAidlInstanceNameSupplier; - @NonNull - private final Function<String, IFingerprint> mIFingerprintProvider; - @NonNull - private final BiometricStateCallback<ServiceProvider, FingerprintSensorPropertiesInternal> - mBiometricStateCallback; - @NonNull - private final Handler mHandler; - @NonNull - private final FingerprintServiceRegistry mRegistry; + @NonNull private final List<ServiceProvider> mServiceProviders; + @NonNull private final BiometricStateCallback mBiometricStateCallback; + @NonNull private final Handler mHandler; + @NonNull private final BiometricContext mBiometricContext; + @NonNull private final Supplier<IBiometricService> mBiometricServiceSupplier; + @NonNull private final Function<String, IFingerprint> mIFingerprintProvider; + + @GuardedBy("mLock") + @NonNull private final RemoteCallbackList<IFingerprintAuthenticatorsRegisteredCallback> + mAuthenticatorsRegisteredCallbacks; + + @GuardedBy("mLock") + @NonNull private final List<FingerprintSensorPropertiesInternal> mSensorProps; + + /** + * Registers BiometricStateListener in list stored by FingerprintService + * @param listener new BiometricStateListener being added + */ + public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) { + mBiometricStateCallback.registerBiometricStateListener(listener); + broadcastCurrentEnrollmentState(listener); + } - /** Receives the incoming binder calls from FingerprintManager. */ - @VisibleForTesting - final IFingerprintService.Stub mServiceWrapper = new IFingerprintService.Stub() { + /** + * @param listener if non-null, notifies only this listener. if null, notifies all listeners + * in {@link BiometricStateCallback}. This is slightly ugly, but reduces + * redundant code. + */ + private void broadcastCurrentEnrollmentState(@Nullable IBiometricStateListener listener) { + final UserManager um = UserManager.get(getContext()); + synchronized (mLock) { + // Update the new listener with current state of all sensors + for (FingerprintSensorPropertiesInternal prop : mSensorProps) { + final ServiceProvider provider = getProviderForSensor(prop.sensorId); + for (UserInfo userInfo : um.getAliveUsers()) { + final boolean enrolled = !provider + .getEnrolledFingerprints(prop.sensorId, userInfo.id).isEmpty(); + + // Defer this work and allow the loop to release the lock sooner + mHandler.post(() -> { + if (listener != null) { + mBiometricStateCallback.notifyEnrollmentStateChanged( + listener, userInfo.id, prop.sensorId, enrolled); + } else { + mBiometricStateCallback.notifyAllEnrollmentStateChanged( + userInfo.id, prop.sensorId, enrolled); + } + }); + } + } + } + } + + /** + * Receives the incoming binder calls from FingerprintManager. + */ + private final IFingerprintService.Stub mServiceWrapper = new IFingerprintService.Stub() { @android.annotation.EnforcePermission(android.Manifest.permission.TEST_BIOMETRIC) @Override public ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, @NonNull String opPackageName) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for createTestSession, sensorId: " + sensorId); @@ -145,8 +195,9 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public byte[] dumpSensorServiceStateProto(int sensorId, boolean clearSchedulerBuffer) { + final ProtoOutputStream proto = new ProtoOutputStream(); - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider != null) { provider.dumpProtoState(sensorId, proto, clearSchedulerBuffer); } @@ -161,14 +212,16 @@ public class FingerprintService extends SystemService { != PackageManager.PERMISSION_GRANTED) { Utils.checkPermission(getContext(), TEST_BIOMETRIC); } - return mRegistry.getAllProperties(); + + return FingerprintService.this.getSensorProperties(); } @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public FingerprintSensorPropertiesInternal getSensorProperties(int sensorId, @NonNull String opPackageName) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "No matching sensor for getSensorProperties, sensorId: " + sensorId + ", caller: " + opPackageName); @@ -181,7 +234,8 @@ public class FingerprintService extends SystemService { @Override // Binder call public void generateChallenge(IBinder token, int sensorId, int userId, IFingerprintServiceReceiver receiver, String opPackageName) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "No matching sensor for generateChallenge, sensorId: " + sensorId); return; @@ -194,7 +248,8 @@ public class FingerprintService extends SystemService { @Override // Binder call public void revokeChallenge(IBinder token, int sensorId, int userId, String opPackageName, long challenge) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "No matching sensor for revokeChallenge, sensorId: " + sensorId); return; @@ -209,7 +264,8 @@ public class FingerprintService extends SystemService { public long enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName, @FingerprintManager.EnrollReason int enrollReason) { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for enroll"); return -1; @@ -222,7 +278,8 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_FINGERPRINT) @Override // Binder call public void cancelEnrollment(final IBinder token, long requestId) { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for cancelEnrollment"); return; @@ -282,10 +339,10 @@ public class FingerprintService extends SystemService { final Pair<Integer, ServiceProvider> provider; if (sensorId == FingerprintManager.SENSOR_ID_ANY) { - provider = mRegistry.getSingleProvider(); + provider = getSingleProvider(); } else { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); - provider = new Pair<>(sensorId, mRegistry.getProviderForSensor(sensorId)); + provider = new Pair<>(sensorId, getProviderForSensor(sensorId)); } if (provider == null) { Slog.w(TAG, "Null provider for authenticate"); @@ -317,6 +374,7 @@ public class FingerprintService extends SystemService { final IFingerprintServiceReceiver receiver, final String opPackageName, boolean ignoreEnrollmentState) throws PackageManager.NameNotFoundException { + final Context context = getUiContext(); final Context promptContext = context.createPackageContextAsUser( opPackageName, 0 /* flags */, UserHandle.getUserHandleForUid(uId)); @@ -410,7 +468,7 @@ public class FingerprintService extends SystemService { return -1; } - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for detectFingerprint"); return -1; @@ -426,7 +484,8 @@ public class FingerprintService extends SystemService { public void prepareForAuthentication(int sensorId, IBinder token, long operationId, int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for prepareForAuthentication"); return; @@ -442,7 +501,8 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.MANAGE_BIOMETRIC) @Override // Binder call public void startPreparedClient(int sensorId, int cookie) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for startPreparedClient"); return; @@ -472,7 +532,7 @@ public class FingerprintService extends SystemService { return; } - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for cancelAuthentication"); return; @@ -493,7 +553,7 @@ public class FingerprintService extends SystemService { // For IBiometricsFingerprint2.1, cancelling fingerprint detect is the same as // cancelling authentication. - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for cancelFingerprintDetect"); return; @@ -506,9 +566,11 @@ public class FingerprintService extends SystemService { @Override // Binder call public void cancelAuthenticationFromService(final int sensorId, final IBinder token, final String opPackageName, final long requestId) { + + Slog.d(TAG, "cancelAuthenticationFromService, sensorId: " + sensorId); - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for cancelAuthenticationFromService"); return; @@ -521,7 +583,8 @@ public class FingerprintService extends SystemService { @Override // Binder call public void remove(final IBinder token, final int fingerId, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName) { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for remove"); return; @@ -554,7 +617,7 @@ public class FingerprintService extends SystemService { // This effectively iterates through all sensors, but has to do so by finding all // sensors under each provider. - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { List<FingerprintSensorPropertiesInternal> props = provider.getSensorProperties(); for (FingerprintSensorPropertiesInternal prop : props) { provider.scheduleRemoveAll(prop.sensorId, token, internalReceiver, userId, @@ -589,7 +652,7 @@ public class FingerprintService extends SystemService { try { if (args.length > 1 && "--proto".equals(args[0]) && "--state".equals(args[1])) { final ProtoOutputStream proto = new ProtoOutputStream(fd); - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { for (FingerprintSensorPropertiesInternal props : provider.getSensorProperties()) { provider.dumpProtoState(props.sensorId, proto, false); @@ -597,14 +660,14 @@ public class FingerprintService extends SystemService { } proto.flush(); } else if (args.length > 0 && "--proto".equals(args[0])) { - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { for (FingerprintSensorPropertiesInternal props : provider.getSensorProperties()) { provider.dumpProtoMetrics(props.sensorId, fd); } } } else { - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { for (FingerprintSensorPropertiesInternal props : provider.getSensorProperties()) { pw.println("Dumping for sensorId: " + props.sensorId @@ -635,7 +698,7 @@ public class FingerprintService extends SystemService { final long token = Binder.clearCallingIdentity(); try { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for isHardwareDetectedDeprecated, caller: " + opPackageName); @@ -650,7 +713,8 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public boolean isHardwareDetected(int sensorId, String opPackageName) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for isHardwareDetected, caller: " + opPackageName); return false; @@ -666,7 +730,7 @@ public class FingerprintService extends SystemService { return; } - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for rename"); return; @@ -717,7 +781,8 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) public boolean hasEnrolledFingerprints(int sensorId, int userId, String opPackageName) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for hasEnrolledFingerprints, caller: " + opPackageName); return false; @@ -729,7 +794,8 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public @LockoutTracker.LockoutMode int getLockoutModeForUser(int sensorId, int userId) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for getLockoutModeForUser"); return LockoutTracker.LOCKOUT_NONE; @@ -741,7 +807,8 @@ public class FingerprintService extends SystemService { @Override public void invalidateAuthenticatorId(int sensorId, int userId, IInvalidationCallback callback) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for invalidateAuthenticatorId"); return; @@ -752,7 +819,8 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override // Binder call public long getAuthenticatorId(int sensorId, int userId) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for getAuthenticatorId"); return 0; @@ -764,7 +832,8 @@ public class FingerprintService extends SystemService { @Override // Binder call public void resetLockout(IBinder token, int sensorId, int userId, @Nullable byte[] hardwareAuthToken, String opPackageName) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "Null provider for resetLockout, caller: " + opPackageName); return; @@ -795,38 +864,55 @@ public class FingerprintService extends SystemService { @Override // Binder call public void registerAuthenticators( @NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) { - mRegistry.registerAll(() -> { - final List<ServiceProvider> providers = new ArrayList<>(); - providers.addAll(getHidlProviders(hidlSensors)); + + // Some HAL might not be started before the system service and will cause the code below + // to wait, and some of the operations below might take a significant amount of time to + // complete (calls to the HALs). To avoid blocking the rest of system server we put + // this on a background thread. + final ServiceThread thread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, + true /* allowIo */); + thread.start(); + final Handler handler = new Handler(thread.getLooper()); + handler.post(() -> { List<String> aidlSensors = new ArrayList<>(); - final String[] instances = mAidlInstanceNameSupplier.get(); + final String[] instances = + ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR); if (instances != null) { aidlSensors.addAll(Lists.newArrayList(instances)); } - providers.addAll(getAidlProviders( - Utils.filterAvailableHalInstances(getContext(), aidlSensors))); - return providers; + registerAuthenticatorsForService(aidlSensors, hidlSensors); }); + thread.quitSafely(); } @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public void addAuthenticatorsRegisteredCallback( IFingerprintAuthenticatorsRegisteredCallback callback) { - mRegistry.addAllRegisteredCallback(callback); - } + if (callback == null) { + Slog.e(TAG, "addAuthenticatorsRegisteredCallback, callback is null"); + return; + } - @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) - @Override - public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) { - mBiometricStateCallback.registerBiometricStateListener(listener); + final boolean registered; + final boolean hasSensorProps; + synchronized (mLock) { + registered = mAuthenticatorsRegisteredCallbacks.register(callback); + hasSensorProps = !mSensorProps.isEmpty(); + } + if (registered && hasSensorProps) { + broadcastAllAuthenticatorsRegistered(); + } else if (!registered) { + Slog.e(TAG, "addAuthenticatorsRegisteredCallback failed to register callback"); + } } @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public void onPointerDown(long requestId, int sensorId, int x, int y, float minor, float major) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "No matching provider for onFingerDown, sensorId: " + sensorId); return; @@ -837,7 +923,8 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public void onPointerUp(long requestId, int sensorId) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "No matching provider for onFingerUp, sensorId: " + sensorId); return; @@ -848,7 +935,8 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public void onUiReady(long requestId, int sensorId) { - final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId); + + final ServiceProvider provider = getProviderForSensor(sensorId); if (provider == null) { Slog.w(TAG, "No matching provider for onUiReady, sensorId: " + sensorId); return; @@ -859,7 +947,8 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public void setUdfpsOverlayController(@NonNull IUdfpsOverlayController controller) { - for (ServiceProvider provider : mRegistry.getProviders()) { + + for (ServiceProvider provider : mServiceProviders) { provider.setUdfpsOverlayController(controller); } } @@ -867,15 +956,22 @@ public class FingerprintService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override public void setSidefpsController(@NonNull ISidefpsController controller) { - for (ServiceProvider provider : mRegistry.getProviders()) { + + for (ServiceProvider provider : mServiceProviders) { provider.setSidefpsController(controller); } } - @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) + @Override + public void registerBiometricStateListener(@NonNull IBiometricStateListener listener) { + Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); + FingerprintService.this.registerBiometricStateListener(listener); + } + @Override public void onPowerPressed() { - for (ServiceProvider provider : mRegistry.getProviders()) { + Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); + for (ServiceProvider provider : mServiceProviders) { provider.onPowerPressed(); } } @@ -885,7 +981,6 @@ public class FingerprintService extends SystemService { this(context, BiometricContext.getInstance(context), () -> IBiometricService.Stub.asInterface( ServiceManager.getService(Context.BIOMETRIC_SERVICE)), - () -> ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR), (fqName) -> IFingerprint.Stub.asInterface( Binder.allowBlocking(ServiceManager.waitForDeclaredService(fqName)))); } @@ -893,34 +988,61 @@ public class FingerprintService extends SystemService { @VisibleForTesting FingerprintService(Context context, BiometricContext biometricContext, - Supplier<IBiometricService> biometricServiceSupplier, - Supplier<String[]> aidlInstanceNameSupplier, + Supplier<IBiometricService> biometricServiceProvider, Function<String, IFingerprint> fingerprintProvider) { super(context); mBiometricContext = biometricContext; - mAidlInstanceNameSupplier = aidlInstanceNameSupplier; + mBiometricServiceSupplier = biometricServiceProvider; mIFingerprintProvider = fingerprintProvider; mAppOps = context.getSystemService(AppOpsManager.class); mGestureAvailabilityDispatcher = new GestureAvailabilityDispatcher(); mLockoutResetDispatcher = new LockoutResetDispatcher(context); mLockPatternUtils = new LockPatternUtils(context); - mBiometricStateCallback = new BiometricStateCallback<>(UserManager.get(context)); + mServiceProviders = new ArrayList<>(); + mBiometricStateCallback = new BiometricStateCallback(); + mAuthenticatorsRegisteredCallbacks = new RemoteCallbackList<>(); + mSensorProps = new ArrayList<>(); mHandler = new Handler(Looper.getMainLooper()); - mRegistry = new FingerprintServiceRegistry(mServiceWrapper, biometricServiceSupplier); - mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() { - @Override - public void onAllAuthenticatorsRegistered( - List<FingerprintSensorPropertiesInternal> sensors) { - mBiometricStateCallback.start(mRegistry.getProviders()); - } - }); } - @NonNull - private List<ServiceProvider> getHidlProviders( + @VisibleForTesting + void registerAuthenticatorsForService(@NonNull List<String> aidlInstanceNames, @NonNull List<FingerprintSensorPropertiesInternal> hidlSensors) { - final List<ServiceProvider> providers = new ArrayList<>(); + addHidlProviders(hidlSensors); + addAidlProviders(Utils.filterAvailableHalInstances(getContext(), aidlInstanceNames)); + + final IBiometricService biometricService = mBiometricServiceSupplier.get(); + + // Register each sensor individually with BiometricService + for (ServiceProvider provider : mServiceProviders) { + final List<FingerprintSensorPropertiesInternal> props = + provider.getSensorProperties(); + for (FingerprintSensorPropertiesInternal prop : props) { + final int sensorId = prop.sensorId; + @BiometricManager.Authenticators.Types final int strength = + Utils.propertyStrengthToAuthenticatorStrength(prop.sensorStrength); + final FingerprintAuthenticator authenticator = new FingerprintAuthenticator( + mServiceWrapper, sensorId); + try { + biometricService.registerAuthenticator(sensorId, TYPE_FINGERPRINT, + strength, authenticator); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when registering sensorId: " + sensorId); + } + } + } + + synchronized (mLock) { + for (ServiceProvider provider : mServiceProviders) { + mSensorProps.addAll(provider.getSensorProperties()); + } + } + broadcastCurrentEnrollmentState(null); // broadcasts to all listeners + broadcastAllAuthenticatorsRegistered(); + } + + private void addHidlProviders(List<FingerprintSensorPropertiesInternal> hidlSensors) { for (FingerprintSensorPropertiesInternal hidlSensor : hidlSensors) { final Fingerprint21 fingerprint21; if ((Build.IS_USERDEBUG || Build.IS_ENG) @@ -937,16 +1059,11 @@ public class FingerprintService extends SystemService { mBiometricStateCallback, hidlSensor, mHandler, mLockoutResetDispatcher, mGestureAvailabilityDispatcher); } - providers.add(fingerprint21); + mServiceProviders.add(fingerprint21); } - - return providers; } - @NonNull - private List<ServiceProvider> getAidlProviders(@NonNull List<String> instances) { - final List<ServiceProvider> providers = new ArrayList<>(); - + private void addAidlProviders(List<String> instances) { for (String instance : instances) { final String fqName = IFingerprint.DESCRIPTOR + "/" + instance; final IFingerprint fp = mIFingerprintProvider.apply(fqName); @@ -958,7 +1075,7 @@ public class FingerprintService extends SystemService { mLockoutResetDispatcher, mGestureAvailabilityDispatcher, mBiometricContext); Slog.i(TAG, "Adding AIDL provider: " + fqName); - providers.add(provider); + mServiceProviders.add(provider); } catch (RemoteException e) { Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); } @@ -966,8 +1083,38 @@ public class FingerprintService extends SystemService { Slog.e(TAG, "Unable to get declared service: " + fqName); } } + } - return providers; + // Notifies the callbacks that all of the authenticators have been registered and removes the + // invoked callbacks from the callback list. + private void broadcastAllAuthenticatorsRegistered() { + // Make a local copy of the data so it can be used outside of the synchronized block when + // making Binder calls. + final List<IFingerprintAuthenticatorsRegisteredCallback> callbacks = new ArrayList<>(); + final List<FingerprintSensorPropertiesInternal> props; + synchronized (mLock) { + if (!mSensorProps.isEmpty()) { + props = new ArrayList<>(mSensorProps); + } else { + Slog.e(TAG, "mSensorProps is empty"); + return; + } + final int n = mAuthenticatorsRegisteredCallbacks.beginBroadcast(); + for (int i = 0; i < n; ++i) { + final IFingerprintAuthenticatorsRegisteredCallback cb = + mAuthenticatorsRegisteredCallbacks.getBroadcastItem(i); + callbacks.add(cb); + mAuthenticatorsRegisteredCallbacks.unregister(cb); + } + mAuthenticatorsRegisteredCallbacks.finishBroadcast(); + } + for (IFingerprintAuthenticatorsRegisteredCallback cb : callbacks) { + try { + cb.onAllAuthenticatorsRegistered(props); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception in onAllAuthenticatorsRegistered", e); + } + } } @Override @@ -975,9 +1122,51 @@ public class FingerprintService extends SystemService { publishBinderService(Context.FINGERPRINT_SERVICE, mServiceWrapper); } + @Nullable + private ServiceProvider getProviderForSensor(int sensorId) { + for (ServiceProvider provider : mServiceProviders) { + if (provider.containsSensor(sensorId)) { + return provider; + } + } + return null; + } + + /** + * For devices with only a single provider, returns that provider. If multiple providers, + * returns the first one. If no providers, returns null. + */ + @Nullable + private Pair<Integer, ServiceProvider> getSingleProvider() { + final List<FingerprintSensorPropertiesInternal> properties = getSensorProperties(); + if (properties.isEmpty()) { + Slog.e(TAG, "No providers found"); + return null; + } + + // Theoretically we can just return the first provider, but maybe this is easier to + // understand. + final int sensorId = properties.get(0).sensorId; + for (ServiceProvider provider : mServiceProviders) { + if (provider.containsSensor(sensorId)) { + return new Pair<>(sensorId, provider); + } + } + + Slog.e(TAG, "Provider not found"); + return null; + } + + @NonNull + private List<FingerprintSensorPropertiesInternal> getSensorProperties() { + synchronized (mLock) { + return mSensorProps; + } + } + @NonNull private List<Fingerprint> getEnrolledFingerprintsDeprecated(int userId, String opPackageName) { - final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider(); + final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for getEnrolledFingerprintsDeprecated, caller: " + opPackageName); @@ -1040,7 +1229,7 @@ public class FingerprintService extends SystemService { if (Utils.isVirtualEnabled(getContext())) { Slog.i(TAG, "Sync virtual enrollments"); final int userId = ActivityManager.getCurrentUser(); - for (ServiceProvider provider : mRegistry.getProviders()) { + for (ServiceProvider provider : mServiceProviders) { for (FingerprintSensorPropertiesInternal props : provider.getSensorProperties()) { provider.scheduleInternalCleanup(props.sensorId, userId, null /* callback */, true /* favorHalEnrollments */); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistry.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistry.java deleted file mode 100644 index 33810b764f23..000000000000 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistry.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.biometrics.sensors.fingerprint; - -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.hardware.biometrics.BiometricManager; -import android.hardware.biometrics.IBiometricService; -import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; -import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; -import android.hardware.fingerprint.IFingerprintService; -import android.os.RemoteException; -import android.util.Slog; - -import com.android.server.biometrics.Utils; -import com.android.server.biometrics.sensors.BiometricServiceRegistry; - -import java.util.List; -import java.util.function.Supplier; - -/** Registry for {@link IFingerprintService} providers. */ -public class FingerprintServiceRegistry extends BiometricServiceRegistry<ServiceProvider, - FingerprintSensorPropertiesInternal, IFingerprintAuthenticatorsRegisteredCallback> { - - private static final String TAG = "FingerprintServiceRegistry"; - - @NonNull - private final IFingerprintService mService; - - /** Creates a new registry tied to the given service. */ - public FingerprintServiceRegistry(@NonNull IFingerprintService service, - @Nullable Supplier<IBiometricService> biometricSupplier) { - super(biometricSupplier); - mService = service; - } - - @Override - protected void registerService(@NonNull IBiometricService service, - @NonNull FingerprintSensorPropertiesInternal props) { - @BiometricManager.Authenticators.Types final int strength = - Utils.propertyStrengthToAuthenticatorStrength(props.sensorStrength); - try { - service.registerAuthenticator(props.sensorId, TYPE_FINGERPRINT, strength, - new FingerprintAuthenticator(mService, props.sensorId)); - } catch (RemoteException e) { - Slog.e(TAG, "Remote exception when registering sensorId: " + props.sensorId); - } - } - - @Override - protected void invokeRegisteredCallback( - @NonNull IFingerprintAuthenticatorsRegisteredCallback callback, - @NonNull List<FingerprintSensorPropertiesInternal> allProps) throws RemoteException { - callback.onAllAuthenticatorsRegistered(allProps); - } -} diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java index 9075e7ec2080..275d7e445a75 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java @@ -28,11 +28,14 @@ import android.hardware.fingerprint.IFingerprintServiceReceiver; import android.hardware.fingerprint.ISidefpsController; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.IBinder; +import android.util.proto.ProtoOutputStream; -import com.android.server.biometrics.sensors.BiometricServiceProvider; import com.android.server.biometrics.sensors.ClientMonitorCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; +import com.android.server.biometrics.sensors.LockoutTracker; +import java.io.FileDescriptor; +import java.io.PrintWriter; import java.util.List; /** @@ -56,8 +59,23 @@ import java.util.List; * fail safely. */ @SuppressWarnings("deprecation") -public interface ServiceProvider extends - BiometricServiceProvider<FingerprintSensorPropertiesInternal> { +public interface ServiceProvider { + /** + * Checks if the specified sensor is owned by this provider. + */ + boolean containsSensor(int sensorId); + + @NonNull + List<FingerprintSensorPropertiesInternal> getSensorProperties(); + + /** + * Returns the internal properties of the specified sensor, if owned by this provider. + * + * @param sensorId The ID of a fingerprint sensor, or -1 for any sensor. + * @return An object representing the internal properties of the specified sensor. + */ + @Nullable + FingerprintSensorPropertiesInternal getSensorProperties(int sensorId); void scheduleResetLockout(int sensorId, int userId, @Nullable byte[] hardwareAuthToken); @@ -108,11 +126,16 @@ public interface ServiceProvider extends void scheduleInternalCleanup(int sensorId, int userId, @Nullable ClientMonitorCallback callback, boolean favorHalEnrollments); + boolean isHardwareDetected(int sensorId); + void rename(int sensorId, int fingerId, int userId, @NonNull String name); @NonNull List<Fingerprint> getEnrolledFingerprints(int sensorId, int userId); + @LockoutTracker.LockoutMode + int getLockoutModeForUser(int sensorId, int userId); + /** * Requests for the authenticatorId (whose source of truth is in the TEE or equivalent) to * be invalidated. See {@link com.android.server.biometrics.sensors.InvalidationRequesterClient} @@ -120,6 +143,7 @@ public interface ServiceProvider extends void scheduleInvalidateAuthenticatorId(int sensorId, int userId, @NonNull IInvalidationCallback callback); + long getAuthenticatorId(int sensorId, int userId); void onPointerDown(long requestId, int sensorId, int x, int y, float minor, float major); @@ -137,6 +161,13 @@ public interface ServiceProvider extends */ void setSidefpsController(@NonNull ISidefpsController controller); + void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto, + boolean clearSchedulerBuffer); + + void dumpProtoMetrics(int sensorId, @NonNull FileDescriptor fd); + + void dumpInternal(int sensorId, @NonNull PrintWriter pw); + @NonNull ITestSession createTestSession(int sensorId, @NonNull ITestSessionCallback callback, @NonNull String opPackageName); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 3fe6332fcaa0..2dc005206b42 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -565,11 +565,6 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } @Override - public boolean hasEnrollments(int sensorId, int userId) { - return !getEnrolledFingerprints(sensorId, userId).isEmpty(); - } - - @Override public void scheduleInvalidateAuthenticatorId(int sensorId, int userId, @NonNull IInvalidationCallback callback) { mHandler.post(() -> { diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index 0e6df8e0df77..ed482f013869 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -789,11 +789,6 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } @Override - public boolean hasEnrollments(int sensorId, int userId) { - return !getEnrolledFingerprints(sensorId, userId).isEmpty(); - } - - @Override @LockoutTracker.LockoutMode public int getLockoutModeForUser(int sensorId, int userId) { return mLockoutTracker.getLockoutModeForUser(userId); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceRegistryTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceRegistryTest.java deleted file mode 100644 index 8cd58abcdf0f..000000000000 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/FaceServiceRegistryTest.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.biometrics.sensors.face; - -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; -import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_STRONG; -import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_WEAK; -import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG; -import static android.hardware.biometrics.SensorProperties.STRENGTH_WEAK; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.hardware.biometrics.IBiometricService; -import android.hardware.face.FaceSensorProperties; -import android.hardware.face.FaceSensorPropertiesInternal; -import android.hardware.face.IFaceAuthenticatorsRegisteredCallback; -import android.hardware.face.IFaceService; -import android.platform.test.annotations.Presubmit; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -import java.util.ArrayList; -import java.util.List; - -@Presubmit -@SmallTest -public class FaceServiceRegistryTest { - - private static final int SENSOR_ID_1 = 1; - private static final int SENSOR_ID_2 = 2; - - @Rule - public final MockitoRule mockito = MockitoJUnit.rule(); - - @Mock - private IBiometricService mBiometricService; - @Mock - private IFaceService mFaceService; - @Mock - private ServiceProvider mProvider1; - @Mock - private ServiceProvider mProvider2; - @Captor - private ArgumentCaptor<Integer> mIdCaptor; - @Captor - private ArgumentCaptor<Integer> mStrengthCaptor; - - private FaceSensorPropertiesInternal mProvider1Props; - private FaceSensorPropertiesInternal mProvider2Props; - private FaceServiceRegistry mRegistry; - - @Before - public void setup() { - mProvider1Props = new FaceSensorPropertiesInternal(SENSOR_ID_1, - STRENGTH_WEAK, 5 /* maxEnrollmentsPerUser */, - List.of(), FaceSensorProperties.TYPE_RGB, - true /* supportsFace Detection */, - true /* supportsSelfIllumination */, - false /* resetLockoutRequiresHardwareAuthToken */); - mProvider2Props = new FaceSensorPropertiesInternal(SENSOR_ID_2, - STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */, - List.of(), FaceSensorProperties.TYPE_IR, - true /* supportsFace Detection */, - true /* supportsSelfIllumination */, - false /* resetLockoutRequiresHardwareAuthToken */); - - when(mProvider1.getSensorProperties()).thenReturn(List.of(mProvider1Props)); - when(mProvider1.containsSensor(eq(SENSOR_ID_1))).thenReturn(true); - when(mProvider2.getSensorProperties()).thenReturn(List.of(mProvider2Props)); - when(mProvider2.containsSensor(eq(SENSOR_ID_2))).thenReturn(true); - mRegistry = new FaceServiceRegistry(mFaceService, () -> mBiometricService); - } - - @Test - public void registersAllProviders() throws Exception { - mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2)); - - assertThat(mRegistry.getProviders()).containsExactly(mProvider1, mProvider2); - assertThat(mRegistry.getAllProperties()).containsExactly(mProvider1Props, mProvider2Props); - verify(mBiometricService, times(2)).registerAuthenticator( - mIdCaptor.capture(), eq(TYPE_FACE), mStrengthCaptor.capture(), any()); - assertThat(mIdCaptor.getAllValues()).containsExactly(SENSOR_ID_1, SENSOR_ID_2); - assertThat(mStrengthCaptor.getAllValues()) - .containsExactly(BIOMETRIC_WEAK, BIOMETRIC_STRONG); - } - - @Test - public void getsProviderById() { - mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2)); - - assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1); - assertThat(mRegistry.getProviderForSensor(SENSOR_ID_2)).isSameInstanceAs(mProvider2); - assertThat(mRegistry.getProviderForSensor(500)).isNull(); - } - - @Test - public void getsSingleProvider() { - mRegistry.registerAllInBackground(() -> List.of(mProvider1)); - - assertThat(mRegistry.getSingleProvider().second).isSameInstanceAs(mProvider1); - assertThat(mRegistry.getProviders()).containsExactly(mProvider1); - assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1); - } - - @Test - public void registersListenerBeforeAllRegistered() { - final List<FaceSensorPropertiesInternal> all = new ArrayList<>(); - mRegistry.addAllRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() { - @Override - public void onAllAuthenticatorsRegistered( - List<FaceSensorPropertiesInternal> sensors) { - all.addAll(sensors); - } - }); - - mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2)); - - assertThat(all).containsExactly(mProvider1Props, mProvider2Props); - } - - @Test - public void registersListenerAfterAllRegistered() { - mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2)); - - final List<FaceSensorPropertiesInternal> all = new ArrayList<>(); - mRegistry.addAllRegisteredCallback(new IFaceAuthenticatorsRegisteredCallback.Stub() { - @Override - public void onAllAuthenticatorsRegistered( - List<FaceSensorPropertiesInternal> sensors) { - all.addAll(sensors); - } - }); - - assertThat(all).containsExactly(mProvider1Props, mProvider2Props); - } -} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java index 0e30782eaece..5f88c99b1d1e 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/BiometricStateCallbackTest.java @@ -16,8 +16,6 @@ package com.android.server.biometrics.sensors.fingerprint; -import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG; - import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; @@ -26,70 +24,35 @@ import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricStateListener; -import android.hardware.biometrics.SensorPropertiesInternal; -import android.os.UserManager; import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import com.android.server.biometrics.sensors.AuthenticationClient; -import com.android.server.biometrics.sensors.BiometricServiceProvider; import com.android.server.biometrics.sensors.BiometricStateCallback; import com.android.server.biometrics.sensors.EnrollClient; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -import java.util.List; +import org.mockito.MockitoAnnotations; @Presubmit @SmallTest public class BiometricStateCallbackTest { - private static final int USER_ID = 10; - private static final int SENSOR_ID = 2; - - @Rule - public final MockitoRule mockito = MockitoJUnit.rule(); - - private BiometricStateCallback<FakeProvider, SensorPropertiesInternal> mCallback; + private BiometricStateCallback mCallback; @Mock - private UserManager mUserManager; - @Mock - private BiometricStateListener mBiometricStateListener; - @Mock - private FakeProvider mFakeProvider; - - private SensorPropertiesInternal mFakeProviderProps; + BiometricStateListener mBiometricStateListener; @Before public void setup() { - mFakeProviderProps = new SensorPropertiesInternal(SENSOR_ID, STRENGTH_STRONG, - 5 /* maxEnrollmentsPerUser */, List.of(), - false /* resetLockoutRequiresHardwareAuthToken */, - false /* resetLockoutRequiresChallenge */); - when(mFakeProvider.getSensorProperties()).thenReturn(List.of(mFakeProviderProps)); - when(mFakeProvider.getSensorProperties(eq(SENSOR_ID))).thenReturn(mFakeProviderProps); - when(mFakeProvider.hasEnrollments(eq(SENSOR_ID), eq(USER_ID))).thenReturn(true); - when(mUserManager.getAliveUsers()).thenReturn( - List.of(new UserInfo(USER_ID, "name", 0))); - - mCallback = new BiometricStateCallback<>(mUserManager); - mCallback.registerBiometricStateListener(mBiometricStateListener); - } - - @Test - public void startNotifiesEnrollments() { - mCallback.start(List.of(mFakeProvider)); + MockitoAnnotations.initMocks(this); - verify(mBiometricStateListener).onEnrollmentsChanged(eq(USER_ID), eq(SENSOR_ID), eq(true)); + mCallback = new BiometricStateCallback(); + mCallback.registerBiometricStateListener(mBiometricStateListener); } @Test @@ -139,6 +102,4 @@ public class BiometricStateCallbackTest { verify(mBiometricStateListener, never()).onEnrollmentsChanged(anyInt(), anyInt(), anyBoolean()); } - - private interface FakeProvider extends BiometricServiceProvider<SensorPropertiesInternal> {} } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistryTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistryTest.java deleted file mode 100644 index 67d94a8f02d8..000000000000 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceRegistryTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.biometrics.sensors.fingerprint; - -import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; -import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_STRONG; -import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_WEAK; -import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG; -import static android.hardware.biometrics.SensorProperties.STRENGTH_WEAK; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.hardware.biometrics.IBiometricService; -import android.hardware.fingerprint.FingerprintSensorProperties; -import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; -import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; -import android.hardware.fingerprint.IFingerprintService; -import android.platform.test.annotations.Presubmit; - -import androidx.test.filters.SmallTest; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnit; -import org.mockito.junit.MockitoRule; - -import java.util.ArrayList; -import java.util.List; - -@Presubmit -@SmallTest -public class FingerprintServiceRegistryTest { - - private static final int SENSOR_ID_1 = 1; - private static final int SENSOR_ID_2 = 2; - - @Rule - public final MockitoRule mockito = MockitoJUnit.rule(); - - @Mock - private IBiometricService mBiometricService; - @Mock - private IFingerprintService mFingerprintService; - @Mock - private ServiceProvider mProvider1; - @Mock - private ServiceProvider mProvider2; - @Captor - private ArgumentCaptor<Integer> mIdCaptor; - @Captor - private ArgumentCaptor<Integer> mStrengthCaptor; - - private FingerprintSensorPropertiesInternal mProvider1Props; - private FingerprintSensorPropertiesInternal mProvider2Props; - private FingerprintServiceRegistry mRegistry; - - @Before - public void setup() { - mProvider1Props = new FingerprintSensorPropertiesInternal(SENSOR_ID_1, - STRENGTH_WEAK, 5 /* maxEnrollmentsPerUser */, - List.of(), FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, - false /* resetLockoutRequiresHardwareAuthToken */); - mProvider2Props = new FingerprintSensorPropertiesInternal(SENSOR_ID_2, - STRENGTH_STRONG, 5 /* maxEnrollmentsPerUser */, - List.of(), FingerprintSensorProperties.TYPE_UNKNOWN, - false /* resetLockoutRequiresHardwareAuthToken */); - - when(mProvider1.getSensorProperties()).thenReturn(List.of(mProvider1Props)); - when(mProvider1.containsSensor(eq(SENSOR_ID_1))).thenReturn(true); - when(mProvider2.getSensorProperties()).thenReturn(List.of(mProvider2Props)); - when(mProvider2.containsSensor(eq(SENSOR_ID_2))).thenReturn(true); - mRegistry = new FingerprintServiceRegistry(mFingerprintService, () -> mBiometricService); - } - - @Test - public void registersAllProviders() throws Exception { - mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2)); - - assertThat(mRegistry.getProviders()).containsExactly(mProvider1, mProvider2); - assertThat(mRegistry.getAllProperties()).containsExactly(mProvider1Props, mProvider2Props); - verify(mBiometricService, times(2)).registerAuthenticator( - mIdCaptor.capture(), eq(TYPE_FINGERPRINT), mStrengthCaptor.capture(), any()); - assertThat(mIdCaptor.getAllValues()).containsExactly(SENSOR_ID_1, SENSOR_ID_2); - assertThat(mStrengthCaptor.getAllValues()) - .containsExactly(BIOMETRIC_WEAK, BIOMETRIC_STRONG); - } - - @Test - public void getsProviderById() { - mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2)); - - assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1); - assertThat(mRegistry.getProviderForSensor(SENSOR_ID_2)).isSameInstanceAs(mProvider2); - assertThat(mRegistry.getProviderForSensor(500)).isNull(); - } - - @Test - public void getsSingleProvider() { - mRegistry.registerAllInBackground(() -> List.of(mProvider1)); - - assertThat(mRegistry.getSingleProvider().second).isSameInstanceAs(mProvider1); - assertThat(mRegistry.getProviders()).containsExactly(mProvider1); - assertThat(mRegistry.getProviderForSensor(SENSOR_ID_1)).isSameInstanceAs(mProvider1); - } - - @Test - public void registersListenerBeforeAllRegistered() { - final List<FingerprintSensorPropertiesInternal> all = new ArrayList<>(); - mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() { - @Override - public void onAllAuthenticatorsRegistered( - List<FingerprintSensorPropertiesInternal> sensors) { - all.addAll(sensors); - } - }); - - mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2)); - - assertThat(all).containsExactly(mProvider1Props, mProvider2Props); - } - - @Test - public void registersListenerAfterAllRegistered() { - mRegistry.registerAllInBackground(() -> List.of(mProvider1, mProvider2)); - - final List<FingerprintSensorPropertiesInternal> all = new ArrayList<>(); - mRegistry.addAllRegisteredCallback(new IFingerprintAuthenticatorsRegisteredCallback.Stub() { - @Override - public void onAllAuthenticatorsRegistered( - List<FingerprintSensorPropertiesInternal> sensors) { - all.addAll(sensors); - } - }); - - assertThat(all).containsExactly(mProvider1Props, mProvider2Props); - } -} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java index a4048a27dfb5..ca3677e3b5ff 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/FingerprintServiceTest.java @@ -32,8 +32,7 @@ import android.hardware.biometrics.fingerprint.FingerprintSensorType; import android.hardware.biometrics.fingerprint.IFingerprint; import android.hardware.biometrics.fingerprint.SensorLocation; import android.hardware.biometrics.fingerprint.SensorProps; -import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; -import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback; +import android.os.RemoteException; import android.platform.test.annotations.Presubmit; import android.provider.Settings; import android.testing.TestableContext; @@ -53,8 +52,6 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; @Presubmit @SmallTest @@ -97,12 +94,9 @@ public class FingerprintServiceTest { mContext.getTestablePermissions().setPermission( USE_BIOMETRIC_INTERNAL, PackageManager.PERMISSION_GRANTED); - } - private void initServiceWith(String... aidlInstances) { mService = new FingerprintService(mContext, mBiometricContext, () -> mIBiometricService, - () -> aidlInstances, (fqName) -> { if (fqName.endsWith(NAME_DEFAULT)) return mIFingerprintDefault; if (fqName.endsWith(NAME_VIRTUAL)) return mIFingerprintVirtual; @@ -111,50 +105,29 @@ public class FingerprintServiceTest { } @Test - public void registerAuthenticators_defaultOnly() throws Exception { - initServiceWith(NAME_DEFAULT, NAME_VIRTUAL); - - mService.mServiceWrapper.registerAuthenticators(List.of()); - waitForRegistration(); + public void registerAuthenticators_defaultOnly() throws RemoteException { + mService.registerAuthenticatorsForService(List.of(NAME_DEFAULT, NAME_VIRTUAL), List.of()); verify(mIBiometricService).registerAuthenticator(eq(ID_DEFAULT), anyInt(), anyInt(), any()); } @Test - public void registerAuthenticators_virtualOnly() throws Exception { - initServiceWith(NAME_DEFAULT, NAME_VIRTUAL); + public void registerAuthenticators_virtualOnly() throws RemoteException { Settings.Secure.putInt(mSettingsRule.mockContentResolver(mContext), Settings.Secure.BIOMETRIC_VIRTUAL_ENABLED, 1); - mService.mServiceWrapper.registerAuthenticators(List.of()); - waitForRegistration(); + mService.registerAuthenticatorsForService(List.of(NAME_DEFAULT, NAME_VIRTUAL), List.of()); verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any()); } @Test - public void registerAuthenticators_virtualAlwaysWhenNoOther() throws Exception { - initServiceWith(NAME_VIRTUAL); - - mService.mServiceWrapper.registerAuthenticators(List.of()); - waitForRegistration(); + public void registerAuthenticators_virtualAlwaysWhenNoOther() throws RemoteException { + mService.registerAuthenticatorsForService(List.of(NAME_VIRTUAL), List.of()); verify(mIBiometricService).registerAuthenticator(eq(ID_VIRTUAL), anyInt(), anyInt(), any()); } - private void waitForRegistration() throws Exception { - final CountDownLatch latch = new CountDownLatch(1); - mService.mServiceWrapper.addAuthenticatorsRegisteredCallback( - new IFingerprintAuthenticatorsRegisteredCallback.Stub() { - @Override - public void onAllAuthenticatorsRegistered( - List<FingerprintSensorPropertiesInternal> sensors) { - latch.countDown(); - } - }); - latch.await(5, TimeUnit.SECONDS); - } - private static SensorProps createProps(int id, byte strength, byte type) { final SensorProps props = new SensorProps(); props.commonProps = new CommonProps(); |