From e1b53af498e7d3b78f00f6cb59519c2b5e3bc0ea Mon Sep 17 00:00:00 2001 From: Ilya Matyukhin Date: Tue, 20 Apr 2021 19:32:28 -0700 Subject: [PATCH] Consolidate registration of HIDL and AIDL HALs This CL establishes a single flow of registration for both HIDL and AIDL HALs. The registration of both is done on a separate thread to avoid blocking system server. Previously, only AIDL registration was done on a separate thread. Bug: 184677066 Test: atest CtsBiometricsTestCases Test: atest AuthServiceTest Test: atest Fingerprint21Test Test: atest Face10Test Change-Id: I4442db15a7b690bb34c6eb7e8793ab4411cbd6d2 --- .../biometrics/SensorPropertiesInternal.java | 2 +- .../android/hardware/face/IFaceService.aidl | 6 +- .../FingerprintSensorPropertiesInternal.java | 29 --- .../fingerprint/IFingerprintService.aidl | 6 +- .../android/hardware/iris/IIrisService.aidl | 8 +- .../server/biometrics/AuthService.java | 237 +++++++++++++----- .../sensors/BiometricServiceCallback.java | 28 --- .../sensors/face/FaceAuthenticator.java | 2 +- .../biometrics/sensors/face/FaceService.java | 126 +++++----- .../biometrics/sensors/face/hidl/Face10.java | 30 +-- .../fingerprint/FingerprintAuthenticator.java | 3 +- .../fingerprint/FingerprintService.java | 151 +++++------ .../fingerprint/hidl/Fingerprint21.java | 57 ++--- .../hidl/Fingerprint21UdfpsMock.java | 25 +- .../sensors/iris/IrisAuthenticator.java | 2 +- .../biometrics/sensors/iris/IrisService.java | 48 +++- .../java/com/android/server/SystemServer.java | 11 - .../server/biometrics/AuthServiceTest.java | 56 ++++- .../sensors/face/hidl/Face10Test.java | 21 +- .../fingerprint/hidl/Fingerprint21Test.java | 28 ++- 20 files changed, 504 insertions(+), 372 deletions(-) delete mode 100644 services/core/java/com/android/server/biometrics/sensors/BiometricServiceCallback.java diff --git a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java index 17b2abf9f5d1e..f365ee6066d08 100644 --- a/core/java/android/hardware/biometrics/SensorPropertiesInternal.java +++ b/core/java/android/hardware/biometrics/SensorPropertiesInternal.java @@ -44,7 +44,7 @@ public class SensorPropertiesInternal implements Parcelable { prop.resetLockoutRequiresHardwareAuthToken, prop.resetLockoutRequiresChallenge); } - protected SensorPropertiesInternal(int sensorId, @SensorProperties.Strength int sensorStrength, + public SensorPropertiesInternal(int sensorId, @SensorProperties.Strength int sensorStrength, int maxEnrollmentsPerUser, @NonNull List componentInfo, boolean resetLockoutRequiresHardwareAuthToken, boolean resetLockoutRequiresChallenge) { this.sensorId = sensorId; diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index 0b44150afa4df..270d662a02a0a 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -127,6 +127,8 @@ interface IFaceService { void getFeature(IBinder token, int userId, int feature, IFaceServiceReceiver receiver, String opPackageName); - // Give FaceService its ID. See AuthService.java - void initializeConfiguration(int sensorId, int strength); + // Registers all HIDL and AIDL sensors. Only HIDL sensor properties need to be provided, because + // AIDL sensor properties are retrieved directly from the available HALs. If no HIDL HALs exist, + // hidlSensors must be non-null and empty. See AuthService.java + void registerAuthenticators(in List hidlSensors); } diff --git a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java index 58f6e62af3205..4ffe5f1896614 100644 --- a/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java +++ b/core/java/android/hardware/fingerprint/FingerprintSensorPropertiesInternal.java @@ -20,7 +20,6 @@ import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFP import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC; import android.annotation.NonNull; -import android.content.Context; import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.SensorProperties; import android.hardware.biometrics.SensorPropertiesInternal; @@ -92,34 +91,6 @@ public class FingerprintSensorPropertiesInternal extends SensorPropertiesInterna 1636 /* sensorLocationY */, 130 /* sensorRadius */); } - /** - * Initializes SensorProperties with specified values and values obtained from resources using - * context. - */ - // TODO(b/179175438): Remove this constructor once all HALs move to AIDL. - public FingerprintSensorPropertiesInternal(@NonNull Context context, int sensorId, - @SensorProperties.Strength int strength, int maxEnrollmentsPerUser, - @NonNull List componentInfo, - @FingerprintSensorProperties.SensorType int sensorType, - boolean resetLockoutRequiresHardwareAuthToken) { - super(sensorId, strength, maxEnrollmentsPerUser, componentInfo, - resetLockoutRequiresHardwareAuthToken, false /* resetLockoutRequiresChallenge */); - this.sensorType = sensorType; - - int[] props = context.getResources().getIntArray( - com.android.internal.R.array.config_udfps_sensor_props); - if (props != null && props.length == 3) { - this.sensorLocationX = props[0]; - this.sensorLocationY = props[1]; - this.sensorRadius = props[2]; - } else { - // Fake coordinates that could be used for the fake UDFPS mode. - this.sensorLocationX = 540; - this.sensorLocationY = 1636; - this.sensorRadius = 130; - } - } - protected FingerprintSensorPropertiesInternal(Parcel in) { super(in); sensorType = in.readInt(); diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index 3bceacb5e479a..0e3cdd6b650a5 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -144,8 +144,10 @@ interface IFingerprintService { // Removes a callback set by addClientActiveCallback void removeClientActiveCallback(IFingerprintClientActiveCallback callback); - // Give FingerprintService its ID. See AuthService.java - void initializeConfiguration(int sensorId, int strength); + // Registers all HIDL and AIDL sensors. Only HIDL sensor properties need to be provided, because + // AIDL sensor properties are retrieved directly from the available HALs. If no HIDL HALs exist, + // hidlSensors must be non-null and empty. See AuthService.java + void registerAuthenticators(in List hidlSensors); // Notifies about a finger touching the sensor area. void onPointerDown(int sensorId, int x, int y, float minor, float major); diff --git a/core/java/android/hardware/iris/IIrisService.aidl b/core/java/android/hardware/iris/IIrisService.aidl index 3d26318343bef..98057d5482261 100644 --- a/core/java/android/hardware/iris/IIrisService.aidl +++ b/core/java/android/hardware/iris/IIrisService.aidl @@ -15,12 +15,16 @@ */ package android.hardware.iris; +import android.hardware.biometrics.SensorPropertiesInternal; + /** * Communication channel from client to the iris service. These methods are all require the * MANAGE_BIOMETRIC signature permission. * @hide */ interface IIrisService { - // Give IrisService its ID. See AuthService.java - void initializeConfiguration(int sensorId, int strength); + // Registers all HIDL and AIDL sensors. Only HIDL sensor properties need to be provided, because + // AIDL sensor properties are retrieved directly from the available HALs. If no HIDL HALs exist, + // hidlSensors must be non-null and empty. See AuthService.java + void registerAuthenticators(in List hidlSensors); } diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java index 88e47a0efd835..e34b183119814 100644 --- a/services/core/java/com/android/server/biometrics/AuthService.java +++ b/services/core/java/com/android/server/biometrics/AuthService.java @@ -30,12 +30,14 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS; import static android.hardware.biometrics.BiometricManager.Authenticators; import android.annotation.NonNull; +import android.annotation.Nullable; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.biometrics.BiometricAuthenticator; +import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.IAuthService; -import android.hardware.biometrics.IBiometricAuthenticator; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.IBiometricServiceReceiver; @@ -44,7 +46,11 @@ import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; import android.hardware.biometrics.PromptInfo; import android.hardware.biometrics.SensorPropertiesInternal; +import android.hardware.face.FaceSensorProperties; +import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.face.IFaceService; +import android.hardware.fingerprint.FingerprintSensorProperties; +import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IFingerprintService; import android.hardware.iris.IIrisService; import android.os.Binder; @@ -58,11 +64,10 @@ import android.util.Slog; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.ArrayUtils; import com.android.server.SystemService; -import com.android.server.biometrics.sensors.face.FaceAuthenticator; -import com.android.server.biometrics.sensors.fingerprint.FingerprintAuthenticator; -import com.android.server.biometrics.sensors.iris.IrisAuthenticator; +import java.util.ArrayList; import java.util.List; /** @@ -574,81 +579,119 @@ public class AuthService extends SystemService { mImpl = new AuthServiceImpl(); } + + /** + * Registration of all HIDL and AIDL biometric HALs starts here. + * The flow looks like this: + * AuthService + * └── .onStart() + * └── .registerAuthenticators(...) + * ├── FaceService.registerAuthenticators(...) + * │ └── for (p : serviceProviders) + * │ └── for (s : p.sensors) + * │ └── BiometricService.registerAuthenticator(s) + * │ + * ├── FingerprintService.registerAuthenticators(...) + * │ └── for (p : serviceProviders) + * │ └── for (s : p.sensors) + * │ └── BiometricService.registerAuthenticator(s) + * │ + * └── IrisService.registerAuthenticators(...) + * └── for (p : serviceProviders) + * └── for (s : p.sensors) + * └── BiometricService.registerAuthenticator(s) + */ @Override public void onStart() { mBiometricService = mInjector.getBiometricService(); + final SensorConfig[] hidlConfigs; if (!mInjector.isHidlDisabled(getContext())) { - final String[] configs = mInjector.getConfiguration(getContext()); - for (String config : configs) { - try { - registerAuthenticator(new SensorConfig(config)); - } catch (RemoteException e) { - Slog.e(TAG, "Remote exception", e); - } + final String[] configStrings = mInjector.getConfiguration(getContext()); + hidlConfigs = new SensorConfig[configStrings.length]; + for (int i = 0; i < configStrings.length; ++i) { + hidlConfigs[i] = new SensorConfig(configStrings[i]); } + } else { + hidlConfigs = null; } + // Registers HIDL and AIDL authenticators, but only HIDL configs need to be provided. + registerAuthenticators(hidlConfigs); + mInjector.publishBinderService(this, mImpl); } - private void registerAuthenticator(SensorConfig config) throws RemoteException { - Slog.d(TAG, "Registering ID: " + config.id - + " Modality: " + config.modality - + " Strength: " + config.strength); + /** + * Registers HIDL and AIDL authenticators for all of the available modalities. + * + * @param hidlSensors Array of {@link SensorConfig} configuration for all of the HIDL sensors + * available on the device. This array may contain configuration for + * different modalities and different sensors of the same modality in + * arbitrary order. Can be null if no HIDL sensors exist on the device. + */ + private void registerAuthenticators(@Nullable SensorConfig[] hidlSensors) { + List hidlFingerprintSensors = new ArrayList<>(); + List hidlFaceSensors = new ArrayList<>(); + // Iris doesn't have IrisSensorPropertiesInternal, using SensorPropertiesInternal instead. + List hidlIrisSensors = new ArrayList<>(); - final IBiometricAuthenticator.Stub authenticator; + if (hidlSensors != null) { + for (SensorConfig sensor : hidlSensors) { + Slog.d(TAG, "Registering HIDL ID: " + sensor.id + " Modality: " + sensor.modality + + " Strength: " + sensor.strength); + switch (sensor.modality) { + case TYPE_FINGERPRINT: + hidlFingerprintSensors.add( + getHidlFingerprintSensorProps(sensor.id, sensor.strength)); + break; - switch (config.modality) { - case TYPE_FINGERPRINT: - final IFingerprintService fingerprintService = mInjector.getFingerprintService(); - if (fingerprintService == null) { - Slog.e(TAG, "Attempting to register with null FingerprintService." - + " Please check your device configuration."); - return; + case TYPE_FACE: + hidlFaceSensors.add(getHidlFaceSensorProps(sensor.id, sensor.strength)); + break; + + case TYPE_IRIS: + hidlIrisSensors.add(getHidlIrisSensorProps(sensor.id, sensor.strength)); + break; + + default: + Slog.e(TAG, "Unknown modality: " + sensor.modality); } - - // Initialize this outside of FingerprintAuthenticator. Only HIDL HALs require - // initialization from here. AIDL HALs are initialized by FingerprintService since - // the HAL interface provides ID, strength, and other configuration information. - fingerprintService.initializeConfiguration(config.id, config.strength); - authenticator = new FingerprintAuthenticator(fingerprintService, config.id); - break; - - case TYPE_FACE: - final IFaceService faceService = mInjector.getFaceService(); - if (faceService == null) { - Slog.e(TAG, "Attempting to register with null FaceService. Please check " - + " your device configuration."); - return; - } - - // Initialize this outside of FingerprintAuthenticator. Only HIDL HALs require - // initialization from here. AIDL HALs are initialized by FaceService since - // the HAL interface provides ID, strength, and other configuration information. - faceService.initializeConfiguration(config.id, config.strength); - authenticator = new FaceAuthenticator(faceService, config.id); - break; - - case TYPE_IRIS: - final IIrisService irisService = mInjector.getIrisService(); - if (irisService == null) { - Slog.e(TAG, "Attempting to register with null IrisService. Please check" - + " your device configuration."); - return; - } - - irisService.initializeConfiguration(config.id, config.strength); - authenticator = new IrisAuthenticator(irisService, config.id); - break; - - default: - Slog.e(TAG, "Unknown modality: " + config.modality); - return; + } } - mBiometricService.registerAuthenticator(config.id, config.modality, config.strength, - authenticator); + final IFingerprintService fingerprintService = mInjector.getFingerprintService(); + if (fingerprintService != null) { + try { + fingerprintService.registerAuthenticators(hidlFingerprintSensors); + } catch (RemoteException e) { + Slog.e(TAG, "RemoteException when registering fingerprint authenticators", e); + } + } else if (hidlFingerprintSensors.size() > 0) { + Slog.e(TAG, "HIDL fingerprint configuration exists, but FingerprintService is null."); + } + + final IFaceService faceService = mInjector.getFaceService(); + if (faceService != null) { + try { + faceService.registerAuthenticators(hidlFaceSensors); + } catch (RemoteException e) { + Slog.e(TAG, "RemoteException when registering face authenticators", e); + } + } else if (hidlFaceSensors.size() > 0) { + Slog.e(TAG, "HIDL face configuration exists, but FaceService is null."); + } + + final IIrisService irisService = mInjector.getIrisService(); + if (irisService != null) { + try { + irisService.registerAuthenticators(hidlIrisSensors); + } catch (RemoteException e) { + Slog.e(TAG, "RemoteException when registering iris authenticators", e); + } + } else if (hidlIrisSensors.size() > 0) { + Slog.e(TAG, "HIDL iris configuration exists, but IrisService is null."); + } } private void checkInternalPermission() { @@ -674,4 +717,72 @@ public class AuthService extends SystemService { return modality == BiometricAuthenticator.TYPE_CREDENTIAL ? modality : (modality & ~BiometricAuthenticator.TYPE_CREDENTIAL); } + + + private FingerprintSensorPropertiesInternal getHidlFingerprintSensorProps(int sensorId, + @BiometricManager.Authenticators.Types int strength) { + // The existence of config_udfps_sensor_props indicates that the sensor is UDFPS. + final int[] udfpsProps = getContext().getResources().getIntArray( + com.android.internal.R.array.config_udfps_sensor_props); + + final boolean isUdfps = !ArrayUtils.isEmpty(udfpsProps); + + // config_is_powerbutton_fps indicates whether device has a power button fingerprint sensor. + final boolean isPowerbuttonFps = getContext().getResources().getBoolean( + R.bool.config_is_powerbutton_fps); + + final @FingerprintSensorProperties.SensorType int sensorType; + if (isUdfps) { + sensorType = FingerprintSensorProperties.TYPE_UDFPS_OPTICAL; + } else if (isPowerbuttonFps) { + sensorType = FingerprintSensorProperties.TYPE_POWER_BUTTON; + } else { + sensorType = FingerprintSensorProperties.TYPE_REAR; + } + + // IBiometricsFingerprint@2.1 does not manage timeout below the HAL, so the Gatekeeper HAT + // cannot be checked. + final boolean resetLockoutRequiresHardwareAuthToken = false; + final int maxEnrollmentsPerUser = getContext().getResources().getInteger( + R.integer.config_fingerprintMaxTemplatesPerUser); + + final List componentInfo = new ArrayList<>(); + if (isUdfps && udfpsProps.length == 3) { + return new FingerprintSensorPropertiesInternal(sensorId, + Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, + componentInfo, sensorType, resetLockoutRequiresHardwareAuthToken, udfpsProps[0], + udfpsProps[1], udfpsProps[2]); + } else { + return new FingerprintSensorPropertiesInternal(sensorId, + Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, + componentInfo, sensorType, resetLockoutRequiresHardwareAuthToken); + } + } + + private FaceSensorPropertiesInternal getHidlFaceSensorProps(int sensorId, + @BiometricManager.Authenticators.Types int strength) { + final boolean supportsSelfIllumination = getContext().getResources().getBoolean( + R.bool.config_faceAuthSupportsSelfIllumination); + final int maxTemplatesAllowed = getContext().getResources().getInteger( + R.integer.config_faceMaxTemplatesPerUser); + final List componentInfo = new ArrayList<>(); + final boolean supportsFaceDetect = false; + final boolean resetLockoutRequiresChallenge = true; + return new FaceSensorPropertiesInternal(sensorId, + Utils.authenticatorStrengthToPropertyStrength(strength), maxTemplatesAllowed, + componentInfo, FaceSensorProperties.TYPE_UNKNOWN, supportsFaceDetect, + supportsSelfIllumination, resetLockoutRequiresChallenge); + } + + private SensorPropertiesInternal getHidlIrisSensorProps(int sensorId, + @BiometricManager.Authenticators.Types int strength) { + final int maxEnrollmentsPerUser = 1; + final List componentInfo = new ArrayList<>(); + final boolean resetLockoutRequiresHardwareAuthToken = false; + final boolean resetLockoutRequiresChallenge = false; + return new SensorPropertiesInternal(sensorId, + Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, + componentInfo, resetLockoutRequiresHardwareAuthToken, + resetLockoutRequiresChallenge); + } } diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceCallback.java b/services/core/java/com/android/server/biometrics/sensors/BiometricServiceCallback.java deleted file mode 100644 index 2ae6ccd73e3da..0000000000000 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricServiceCallback.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2020 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; - -/** - * System_server services that require BiometricService to load before finishing initialization - * should implement this interface. - */ -public interface BiometricServiceCallback { - /** - * Notifies the service that BiometricService is initialized. - */ - void onBiometricServiceReady(); -} diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java index 0002ad249376d..0bc4f1b54d592 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java @@ -36,7 +36,7 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub { private final IFaceService mFaceService; private final int mSensorId; - public FaceAuthenticator(IFaceService faceService, int sensorId) throws RemoteException { + public FaceAuthenticator(IFaceService faceService, int sensorId) { mFaceService = faceService; mSensorId = sensorId; } 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 ada84769b9ef2..94d47aa029a26 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 @@ -57,7 +57,6 @@ 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.sensors.BiometricServiceCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; @@ -76,7 +75,7 @@ import java.util.List; * The service is responsible for maintaining a list of clients and dispatching all * face-related events. */ -public class FaceService extends SystemService implements BiometricServiceCallback { +public class FaceService extends SystemService { protected static final String TAG = "FaceService"; @@ -618,12 +617,76 @@ public class FaceService extends SystemService implements BiometricServiceCallba new ClientMonitorCallbackConverter(receiver), opPackageName); } + private void addHidlProviders(@NonNull List hidlSensors) { + for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) { + mServiceProviders.add( + new Face10(getContext(), hidlSensor, mLockoutResetDispatcher)); + } + } + + private void addAidlProviders() { + final String[] instances = ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR); + if (instances == null || instances.length == 0) { + return; + } + for (String instance : instances) { + final String fqName = IFace.DESCRIPTOR + "/" + instance; + final IFace face = IFace.Stub.asInterface( + ServiceManager.waitForDeclaredService(fqName)); + if (face == null) { + Slog.e(TAG, "Unable to get declared service: " + fqName); + continue; + } + try { + final SensorProps[] props = face.getSensorProps(); + final FaceProvider provider = new FaceProvider(getContext(), props, instance, + mLockoutResetDispatcher); + mServiceProviders.add(provider); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); + } + } + } + @Override // Binder call - public void initializeConfiguration(int sensorId, - @BiometricManager.Authenticators.Types int strength) { + public void registerAuthenticators( + @NonNull List hidlSensors) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); - mServiceProviders.add( - new Face10(getContext(), sensorId, strength, 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 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); + } + } + } + }); } } @@ -635,57 +698,6 @@ public class FaceService extends SystemService implements BiometricServiceCallba mServiceProviders = new ArrayList<>(); } - @Override - public void onBiometricServiceReady() { - final IBiometricService biometricService = IBiometricService.Stub.asInterface( - ServiceManager.getService(Context.BIOMETRIC_SERVICE)); - - final String[] instances = ServiceManager.getDeclaredInstances(IFace.DESCRIPTOR); - if (instances == null || instances.length == 0) { - return; - } - - // If for some reason the HAL is not started before the system service, do not block - // the rest of system server. 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(() -> { - for (String instance : instances) { - final String fqName = IFace.DESCRIPTOR + "/" + instance; - final IFace face = IFace.Stub.asInterface( - ServiceManager.waitForDeclaredService(fqName)); - try { - final SensorProps[] props = face.getSensorProps(); - final FaceProvider provider = new FaceProvider(getContext(), props, instance, - mLockoutResetDispatcher); - mServiceProviders.add(provider); - - // Register each sensor individually with BiometricService - for (SensorProps prop : props) { - final int sensorId = prop.commonProps.sensorId; - @BiometricManager.Authenticators.Types int strength = - Utils.propertyStrengthToAuthenticatorStrength( - prop.commonProps.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); - } - } - } catch (RemoteException e) { - Slog.e(TAG, "Remote exception when initializing instance: " + fqName); - } - } - }); - } - @Override public void onStart() { publishBinderService(Context.FACE_SERVICE, mServiceWrapper); 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 a40155b2df7d6..5dfc5907060f5 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 @@ -25,15 +25,12 @@ import android.content.Context; import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricFaceConstants; -import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricsProtoEnums; -import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; import android.hardware.biometrics.face.V1_0.IBiometricsFace; import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback; import android.hardware.face.Face; -import android.hardware.face.FaceSensorProperties; import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.face.IFaceServiceReceiver; import android.os.Binder; @@ -51,7 +48,6 @@ import android.provider.Settings; import android.util.Slog; import android.util.proto.ProtoOutputStream; -import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FrameworkStatsLog; import com.android.server.biometrics.SensorServiceStateProto; @@ -66,7 +62,6 @@ import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.EnumerateConsumer; import com.android.server.biometrics.sensors.ErrorConsumer; import com.android.server.biometrics.sensors.HalClientMonitor; -import com.android.server.biometrics.sensors.Interruptable; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; import com.android.server.biometrics.sensors.PerformanceTracker; @@ -327,19 +322,13 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { } } - @VisibleForTesting - Face10(@NonNull Context context, int sensorId, - @BiometricManager.Authenticators.Types int strength, + @VisibleForTesting Face10(@NonNull Context context, + @NonNull FaceSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher, - boolean supportsSelfIllumination, int maxTemplatesAllowed, @NonNull BiometricScheduler scheduler) { - mSensorProperties = new FaceSensorPropertiesInternal(sensorId, - Utils.authenticatorStrengthToPropertyStrength(strength), - maxTemplatesAllowed, new ArrayList() /* componentInfo */, - FaceSensorProperties.TYPE_UNKNOWN, false /* supportsFaceDetect */, - supportsSelfIllumination, true /* resetLockoutRequiresChallenge */); + mSensorProperties = sensorProps; mContext = context; - mSensorId = sensorId; + mSensorId = sensorProps.sensorId; mScheduler = scheduler; mHandler = new Handler(Looper.getMainLooper()); mUsageStats = new UsageStats(context); @@ -347,8 +336,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { mLazyDaemon = Face10.this::getDaemon; mLockoutTracker = new LockoutHalImpl(); mLockoutResetDispatcher = lockoutResetDispatcher; - mHalResultController = new HalResultController(sensorId, context, mHandler, mScheduler, - mLockoutTracker, lockoutResetDispatcher); + mHalResultController = new HalResultController(sensorProps.sensorId, context, mHandler, + mScheduler, mLockoutTracker, lockoutResetDispatcher); mHalResultController.setCallback(() -> { mDaemon = null; mCurrentUserId = UserHandle.USER_NULL; @@ -361,12 +350,9 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { } } - public Face10(@NonNull Context context, int sensorId, - @BiometricManager.Authenticators.Types int strength, + public Face10(@NonNull Context context, @NonNull FaceSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher) { - this(context, sensorId, strength, lockoutResetDispatcher, - context.getResources().getBoolean(R.bool.config_faceAuthSupportsSelfIllumination), - context.getResources().getInteger(R.integer.config_faceMaxTemplatesPerUser), + this(context, sensorProps, lockoutResetDispatcher, new BiometricScheduler(TAG, null /* gestureAvailabilityTracker */)); } diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java index 81096802a78b6..1e5942930b018 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintAuthenticator.java @@ -36,8 +36,7 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub private final IFingerprintService mFingerprintService; private final int mSensorId; - public FingerprintAuthenticator(IFingerprintService fingerprintService, int sensorId) - throws RemoteException { + public FingerprintAuthenticator(IFingerprintService fingerprintService, int sensorId) { mFingerprintService = fingerprintService; mSensorId = sensorId; } 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 b780222da380c..2b0637fe335a0 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 @@ -76,7 +76,6 @@ 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.sensors.BiometricServiceCallback; import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; @@ -96,7 +95,7 @@ import java.util.concurrent.Executor; * The service is responsible for maintaining a list of clients and dispatching all * fingerprint-related events. */ -public class FingerprintService extends SystemService implements BiometricServiceCallback { +public class FingerprintService extends SystemService { protected static final String TAG = "FingerprintService"; @@ -775,24 +774,89 @@ public class FingerprintService extends SystemService implements BiometricServic mGestureAvailabilityDispatcher.removeCallback(callback); } + private void addHidlProviders(List hidlSensors) { + for (FingerprintSensorPropertiesInternal hidlSensor : hidlSensors) { + final Fingerprint21 fingerprint21; + if ((Build.IS_USERDEBUG || Build.IS_ENG) + && getContext().getResources().getBoolean(R.bool.allow_test_udfps) + && Settings.Secure.getIntForUser(getContext().getContentResolver(), + Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */, + UserHandle.USER_CURRENT) != 0) { + fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), hidlSensor, + mLockoutResetDispatcher, mGestureAvailabilityDispatcher); + } else { + fingerprint21 = Fingerprint21.newInstance(getContext(), hidlSensor, + mLockoutResetDispatcher, mGestureAvailabilityDispatcher); + } + mServiceProviders.add(fingerprint21); + } + } + + private void addAidlProviders() { + final String[] instances = ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR); + if (instances == null || instances.length == 0) { + return; + } + for (String instance : instances) { + final String fqName = IFingerprint.DESCRIPTOR + "/" + instance; + final IFingerprint fp = IFingerprint.Stub.asInterface( + ServiceManager.waitForDeclaredService(fqName)); + if (fp == null) { + Slog.e(TAG, "Unable to get declared service: " + fqName); + continue; + } + try { + final SensorProps[] props = fp.getSensorProps(); + final FingerprintProvider provider = + new FingerprintProvider(getContext(), props, instance, + mLockoutResetDispatcher, mGestureAvailabilityDispatcher); + mServiceProviders.add(provider); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception in getSensorProps: " + fqName); + } + } + } + @Override // Binder call - public void initializeConfiguration(int sensorId, - @BiometricManager.Authenticators.Types int strength) { + public void registerAuthenticators( + @NonNull List hidlSensors) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); - final Fingerprint21 fingerprint21; - if ((Build.IS_USERDEBUG || Build.IS_ENG) - && getContext().getResources().getBoolean(R.bool.allow_test_udfps) - && Settings.Secure.getIntForUser(getContext().getContentResolver(), - Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */, - UserHandle.USER_CURRENT) != 0) { - fingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), sensorId, - strength, mLockoutResetDispatcher, mGestureAvailabilityDispatcher); - } else { - fingerprint21 = Fingerprint21.newInstance(getContext(), sensorId, strength, - mLockoutResetDispatcher, mGestureAvailabilityDispatcher); - } - mServiceProviders.add(fingerprint21); + // 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 props = + provider.getSensorProperties(); + for (FingerprintSensorPropertiesInternal prop : props) { + final int sensorId = prop.sensorId; + final @BiometricManager.Authenticators.Types 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); + } + } + } + }); } @Override @@ -806,7 +870,6 @@ public class FingerprintService extends SystemService implements BiometricServic } provider.onPointerDown(sensorId, x, y, minor, major); } - @Override public void onPointerUp(int sensorId) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); @@ -845,58 +908,6 @@ public class FingerprintService extends SystemService implements BiometricServic mFingerprintStateCallback = new FingerprintStateCallback(); } - @Override - public void onBiometricServiceReady() { - final IBiometricService biometricService = IBiometricService.Stub.asInterface( - ServiceManager.getService(Context.BIOMETRIC_SERVICE)); - - final String[] instances = ServiceManager.getDeclaredInstances(IFingerprint.DESCRIPTOR); - if (instances == null || instances.length == 0) { - return; - } - - // If for some reason the HAL is not started before the system service, do not block - // the rest of system server. 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(() -> { - for (String instance : instances) { - final String fqName = IFingerprint.DESCRIPTOR + "/" + instance; - final IFingerprint fp = IFingerprint.Stub.asInterface( - ServiceManager.waitForDeclaredService(fqName)); - try { - final SensorProps[] props = fp.getSensorProps(); - final FingerprintProvider provider = - new FingerprintProvider(getContext(), props, instance, - mLockoutResetDispatcher, mGestureAvailabilityDispatcher); - mServiceProviders.add(provider); - - // Register each sensor individually with BiometricService - for (SensorProps prop : props) { - final int sensorId = prop.commonProps.sensorId; - @BiometricManager.Authenticators.Types int strength = - Utils.propertyStrengthToAuthenticatorStrength( - prop.commonProps.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); - } - } - } catch (RemoteException e) { - Slog.e(TAG, "Remote exception when initializing instance: " + fqName); - } - } - }); - } - @Override public void onStart() { publishBinderService(Context.FINGERPRINT_SERVICE, mServiceWrapper); 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 ebfd5347241d5..3528690e64599 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 @@ -26,9 +26,7 @@ import android.app.UserSwitchObserver; import android.content.Context; import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricConstants; -import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricsProtoEnums; -import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.IInvalidationCallback; import android.hardware.biometrics.ITestSession; import android.hardware.biometrics.ITestSessionCallback; @@ -50,9 +48,7 @@ import android.os.UserManager; import android.util.Slog; import android.util.proto.ProtoOutputStream; -import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.server.biometrics.SensorServiceStateProto; import com.android.server.biometrics.SensorStateProto; @@ -314,17 +310,22 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } } - Fingerprint21(@NonNull Context context, @NonNull BiometricScheduler scheduler, - @NonNull Handler handler, int sensorId, - @BiometricManager.Authenticators.Types int strength, + Fingerprint21(@NonNull Context context, + @NonNull FingerprintSensorPropertiesInternal sensorProps, + @NonNull BiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull HalResultController controller) { mContext = context; - mSensorId = sensorId; + + mSensorProperties = sensorProps; + mSensorId = sensorProps.sensorId; + mIsUdfps = sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL + || sensorProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC; + mIsPowerbuttonFps = sensorProps.sensorType == FingerprintSensorProperties.TYPE_POWER_BUTTON; + mScheduler = scheduler; mHandler = handler; mActivityTaskManager = ActivityTaskManager.getInstance(); - mTaskStackListener = new BiometricTaskStackListener(); mAuthenticatorIds = Collections.synchronizedMap(new HashMap<>()); mLazyDaemon = Fingerprint21.this::getDaemon; @@ -341,46 +342,20 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } catch (RemoteException e) { Slog.e(TAG, "Unable to register user switch observer"); } - - // TODO(b/179175438): Remove this code block after transition to AIDL. - // The existence of config_udfps_sensor_props indicates that the sensor is UDFPS. - mIsUdfps = !ArrayUtils.isEmpty( - mContext.getResources().getIntArray(R.array.config_udfps_sensor_props)); - - // config_is_powerbutton_fps indicates whether device has a power button fingerprint sensor. - mIsPowerbuttonFps = mContext.getResources().getBoolean(R.bool.config_is_powerbutton_fps); - - final @FingerprintSensorProperties.SensorType int sensorType; - if (mIsUdfps) { - sensorType = FingerprintSensorProperties.TYPE_UDFPS_OPTICAL; - } else if (mIsPowerbuttonFps) { - sensorType = FingerprintSensorProperties.TYPE_POWER_BUTTON; - } else { - sensorType = FingerprintSensorProperties.TYPE_REAR; - } - - // IBiometricsFingerprint@2.1 does not manage timeout below the HAL, so the Gatekeeper HAT - // cannot be checked - final boolean resetLockoutRequiresHardwareAuthToken = false; - final int maxEnrollmentsPerUser = mContext.getResources() - .getInteger(R.integer.config_fingerprintMaxTemplatesPerUser); - - mSensorProperties = new FingerprintSensorPropertiesInternal(context, sensorId, - Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser, - new ArrayList() /* componentInfo */, sensorType, - resetLockoutRequiresHardwareAuthToken); } - public static Fingerprint21 newInstance(@NonNull Context context, int sensorId, int strength, + public static Fingerprint21 newInstance(@NonNull Context context, + @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { final Handler handler = new Handler(Looper.getMainLooper()); final BiometricScheduler scheduler = new BiometricScheduler(TAG, gestureAvailabilityDispatcher); - final HalResultController controller = new HalResultController(sensorId, context, handler, + final HalResultController controller = new HalResultController(sensorProps.sensorId, + context, handler, scheduler); - return new Fingerprint21(context, scheduler, handler, sensorId, strength, - lockoutResetDispatcher, controller); + return new Fingerprint21(context, sensorProps, scheduler, handler, lockoutResetDispatcher, + controller); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java index 48419c35e28ec..d1020a6ff068c 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java @@ -21,8 +21,6 @@ import android.annotation.Nullable; import android.app.trust.TrustManager; import android.content.ContentResolver; import android.content.Context; -import android.hardware.biometrics.BiometricManager; -import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.fingerprint.FingerprintManager; import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; @@ -39,7 +37,6 @@ import android.util.Slog; import android.util.SparseBooleanArray; import com.android.internal.R; -import com.android.server.biometrics.Utils; import com.android.server.biometrics.sensors.AuthenticationConsumer; import com.android.server.biometrics.sensors.BaseClientMonitor; import com.android.server.biometrics.sensors.BiometricScheduler; @@ -271,8 +268,8 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } } - public static Fingerprint21UdfpsMock newInstance(@NonNull Context context, int sensorId, - @BiometricManager.Authenticators.Types int strength, + public static Fingerprint21UdfpsMock newInstance(@NonNull Context context, + @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { Slog.d(TAG, "Creating Fingerprint23Mock!"); @@ -281,8 +278,8 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage final TestableBiometricScheduler scheduler = new TestableBiometricScheduler(TAG, gestureAvailabilityDispatcher); final MockHalResultController controller = - new MockHalResultController(sensorId, context, handler, scheduler); - return new Fingerprint21UdfpsMock(context, scheduler, handler, sensorId, strength, + new MockHalResultController(sensorProps.sensorId, context, handler, scheduler); + return new Fingerprint21UdfpsMock(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller); } @@ -407,12 +404,12 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage } private Fingerprint21UdfpsMock(@NonNull Context context, + @NonNull FingerprintSensorPropertiesInternal sensorProps, @NonNull TestableBiometricScheduler scheduler, - @NonNull Handler handler, int sensorId, - @BiometricManager.Authenticators.Types int strength, + @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull MockHalResultController controller) { - super(context, scheduler, handler, sensorId, strength, lockoutResetDispatcher, controller); + super(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller); mScheduler = scheduler; mScheduler.init(this); mHandler = handler; @@ -420,11 +417,11 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage final boolean resetLockoutRequiresHardwareAuthToken = false; final int maxTemplatesAllowed = mContext.getResources() .getInteger(R.integer.config_fingerprintMaxTemplatesPerUser); - mSensorProperties = new FingerprintSensorPropertiesInternal(sensorId, - Utils.authenticatorStrengthToPropertyStrength(strength), maxTemplatesAllowed, - new ArrayList() /* componentInfo */, + mSensorProperties = new FingerprintSensorPropertiesInternal(sensorProps.sensorId, + sensorProps.sensorStrength, maxTemplatesAllowed, sensorProps.componentInfo, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL, - resetLockoutRequiresHardwareAuthToken); + resetLockoutRequiresHardwareAuthToken, sensorProps.sensorLocationX, + sensorProps.sensorLocationY, sensorProps.sensorRadius); mMockHalResultController = controller; mUserHasTrust = new SparseBooleanArray(); mTrustManager = context.getSystemService(TrustManager.class); diff --git a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java index 1003c26f966e8..491818520e3cc 100644 --- a/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java +++ b/services/core/java/com/android/server/biometrics/sensors/iris/IrisAuthenticator.java @@ -35,7 +35,7 @@ import com.android.server.biometrics.sensors.LockoutTracker; public final class IrisAuthenticator extends IBiometricAuthenticator.Stub { private final IIrisService mIrisService; - public IrisAuthenticator(IIrisService irisService, int sensorId) throws RemoteException { + public IrisAuthenticator(IIrisService irisService, int sensorId) { mIrisService = irisService; } diff --git a/services/core/java/com/android/server/biometrics/sensors/iris/IrisService.java b/services/core/java/com/android/server/biometrics/sensors/iris/IrisService.java index 08b24897581fd..d684bb8439674 100644 --- a/services/core/java/com/android/server/biometrics/sensors/iris/IrisService.java +++ b/services/core/java/com/android/server/biometrics/sensors/iris/IrisService.java @@ -17,14 +17,26 @@ package com.android.server.biometrics.sensors.iris; import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL; +import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS; import android.annotation.NonNull; import android.content.Context; +import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.IBiometricService; +import android.hardware.biometrics.SensorPropertiesInternal; import android.hardware.iris.IIrisService; +import android.os.Handler; +import android.os.Process; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.util.Slog; +import com.android.server.ServiceThread; import com.android.server.SystemService; import com.android.server.biometrics.Utils; +import java.util.List; + /** * A service to manage multiple clients that want to access the Iris HAL API. * The service is responsible for maintaining a list of clients and dispatching all @@ -37,22 +49,54 @@ public class IrisService extends SystemService { private static final String TAG = "IrisService"; + private final IrisServiceWrapper mServiceWrapper; + /** * Receives the incoming binder calls from IrisManager. */ private final class IrisServiceWrapper extends IIrisService.Stub { @Override // Binder call - public void initializeConfiguration(int sensorId, int strength) { + public void registerAuthenticators(@NonNull List hidlSensors) { Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL); + + // 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(() -> { + final IBiometricService biometricService = IBiometricService.Stub.asInterface( + ServiceManager.getService(Context.BIOMETRIC_SERVICE)); + + for (SensorPropertiesInternal hidlSensor : hidlSensors) { + final int sensorId = hidlSensor.sensorId; + final @BiometricManager.Authenticators.Types int strength = + Utils.propertyStrengthToAuthenticatorStrength( + hidlSensor.sensorStrength); + final IrisAuthenticator authenticator = new IrisAuthenticator(mServiceWrapper, + sensorId); + try { + biometricService.registerAuthenticator(sensorId, TYPE_IRIS, strength, + authenticator); + } catch (RemoteException e) { + Slog.e(TAG, "Remote exception when registering sensorId: " + sensorId); + } + } + }); } } public IrisService(@NonNull Context context) { super(context); + mServiceWrapper = new IrisServiceWrapper(); } @Override public void onStart() { - publishBinderService(Context.IRIS_SERVICE, new IrisServiceWrapper()); + publishBinderService(Context.IRIS_SERVICE, mServiceWrapper); } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 6dedca190e2b9..8dc501119af13 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -108,7 +108,6 @@ import com.android.server.attention.AttentionManagerService; import com.android.server.audio.AudioService; import com.android.server.biometrics.AuthService; import com.android.server.biometrics.BiometricService; -import com.android.server.biometrics.sensors.BiometricServiceCallback; import com.android.server.biometrics.sensors.face.FaceService; import com.android.server.biometrics.sensors.fingerprint.FingerprintService; import com.android.server.biometrics.sensors.iris.IrisService; @@ -214,11 +213,9 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.LinkedList; -import java.util.List; import java.util.Locale; import java.util.Timer; import java.util.TreeSet; @@ -2334,12 +2331,10 @@ public final class SystemServer implements Dumpable { final boolean hasFeatureFingerprint = mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT); - final List biometricServiceCallback = new ArrayList<>(); if (hasFeatureFace) { t.traceBegin("StartFaceSensor"); final FaceService faceService = mSystemServiceManager.startService(FaceService.class); - biometricServiceCallback.add(faceService); t.traceEnd(); } @@ -2353,18 +2348,12 @@ public final class SystemServer implements Dumpable { t.traceBegin("StartFingerprintSensor"); final FingerprintService fingerprintService = mSystemServiceManager.startService(FingerprintService.class); - biometricServiceCallback.add(fingerprintService); t.traceEnd(); } // Start this service after all biometric sensor services are started. t.traceBegin("StartBiometricService"); mSystemServiceManager.startService(BiometricService.class); - for (BiometricServiceCallback service : biometricServiceCallback) { - Slog.d(TAG, "Notifying onBiometricServiceReady for: " - + service.getClass().getSimpleName()); - service.onBiometricServiceReady(); - } t.traceEnd(); t.traceBegin("StartAuthService"); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java index 10a7a50003174..6f0c8e1004c4d 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java @@ -31,11 +31,14 @@ import static org.mockito.Mockito.when; import android.app.AppOpsManager; import android.content.Context; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; import android.hardware.biometrics.IBiometricService; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.PromptInfo; +import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.face.IFaceService; +import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.hardware.fingerprint.IFingerprintService; import android.hardware.iris.IIrisService; import android.os.Binder; @@ -45,11 +48,17 @@ import android.platform.test.annotations.Presubmit; import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; +import com.android.internal.R; + import org.junit.Before; import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.List; + @Presubmit @SmallTest public class AuthServiceTest { @@ -62,6 +71,8 @@ public class AuthServiceTest { @Mock private Context mContext; @Mock + private Resources mResources; + @Mock private PackageManager mPackageManager; @Mock IBiometricServiceReceiver mReceiver; @@ -77,6 +88,10 @@ public class AuthServiceTest { IFaceService mFaceService; @Mock AppOpsManager mAppOpsManager; + @Captor + private ArgumentCaptor> mFingerprintPropsCaptor; + @Captor + private ArgumentCaptor> mFacePropsCaptor; @Before public void setUp() { @@ -89,7 +104,16 @@ public class AuthServiceTest { "2:8:15", // ID2:Face:Strong }; + when(mResources.getIntArray(eq(R.array.config_udfps_sensor_props))).thenReturn(new int[0]); + when(mResources.getBoolean(eq(R.bool.config_is_powerbutton_fps))).thenReturn(false); + when(mResources.getInteger(eq(R.integer.config_fingerprintMaxTemplatesPerUser))).thenReturn( + 1); + when(mResources.getBoolean(eq(R.bool.config_faceAuthSupportsSelfIllumination))).thenReturn( + false); + when(mResources.getInteger(eq(R.integer.config_faceMaxTemplatesPerUser))).thenReturn(1); + when(mContext.getPackageManager()).thenReturn(mPackageManager); + when(mContext.getResources()).thenReturn(mResources); when(mInjector.getBiometricService()).thenReturn(mBiometricService); when(mInjector.getConfiguration(any())).thenReturn(config); when(mInjector.getFingerprintService()).thenReturn(mFingerprintService); @@ -119,11 +143,18 @@ public class AuthServiceTest { } @Test - public void testRegisterAuthenticator_initializesConfiguration() throws Exception { + public void testRegisterAuthenticator_registerAuthenticators() throws Exception { + final int fingerprintId = 0; + final int fingerprintStrength = 15; + + final int faceId = 1; + final int faceStrength = 4095; final String[] config = { - "0:2:15", // ID0:Fingerprint:Strong - "1:8:4095", // ID2:Face:Convenience + // ID0:Fingerprint:Strong + String.format("%d:2:%d", fingerprintId, fingerprintStrength), + // ID2:Face:Convenience + String.format("%d:8:%d", faceId, faceStrength) }; when(mInjector.getConfiguration(any())).thenReturn(config); @@ -131,15 +162,18 @@ public class AuthServiceTest { mAuthService = new AuthService(mContext, mInjector); mAuthService.onStart(); - final int fingerprintId = 0; - final int faceId = 1; + verify(mFingerprintService).registerAuthenticators(mFingerprintPropsCaptor.capture()); + final FingerprintSensorPropertiesInternal fingerprintProp = + mFingerprintPropsCaptor.getValue().get(0); + assertEquals(fingerprintProp.sensorId, fingerprintId); + assertEquals(fingerprintProp.sensorStrength, + Utils.authenticatorStrengthToPropertyStrength(fingerprintStrength)); - final int fingerprintStrength = 15; - final int faceStrength = 4095; - - verify(mFingerprintService).initializeConfiguration(eq(fingerprintId), - eq(fingerprintStrength)); - verify(mFaceService).initializeConfiguration(eq(faceId), eq(faceStrength)); + verify(mFaceService).registerAuthenticators(mFacePropsCaptor.capture()); + final FaceSensorPropertiesInternal faceProp = mFacePropsCaptor.getValue().get(0); + assertEquals(faceProp.sensorId, faceId); + assertEquals(faceProp.sensorStrength, + Utils.authenticatorStrengthToPropertyStrength(faceStrength)); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java index 392535e8eea1a..0b59be65b8879 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java @@ -22,7 +22,10 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.Context; -import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.ComponentInfoInternal; +import android.hardware.biometrics.SensorProperties; +import android.hardware.face.FaceSensorProperties; +import android.hardware.face.FaceSensorPropertiesInternal; import android.os.Binder; import android.os.IBinder; import android.os.UserManager; @@ -40,6 +43,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.List; @Presubmit @SmallTest @@ -71,9 +75,18 @@ public class Face10Test { when(mUserManager.getAliveUsers()).thenReturn(new ArrayList<>()); mLockoutResetDispatcher = new LockoutResetDispatcher(mContext); - mFace10 = new Face10(mContext, SENSOR_ID, BiometricManager.Authenticators.BIOMETRIC_STRONG, - mLockoutResetDispatcher, false /* supportsSelfIllumination */, - 1 /* maxTemplatesAllowed */, mScheduler); + + final int maxEnrollmentsPerUser = 1; + final List componentInfo = new ArrayList<>(); + final boolean supportsFaceDetection = false; + final boolean supportsSelfIllumination = false; + final boolean resetLockoutRequiresChallenge = false; + final FaceSensorPropertiesInternal sensorProps = new FaceSensorPropertiesInternal(SENSOR_ID, + SensorProperties.STRENGTH_STRONG, maxEnrollmentsPerUser, componentInfo, + FaceSensorProperties.TYPE_UNKNOWN, supportsFaceDetection, supportsSelfIllumination, + resetLockoutRequiresChallenge); + + mFace10 = new Face10(mContext, sensorProps, mLockoutResetDispatcher, mScheduler); mBinder = new Binder(); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java index 904ade82a51f9..0a0dcc97272b9 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21Test.java @@ -25,8 +25,10 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.content.res.Resources; -import android.hardware.biometrics.BiometricManager; +import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint; +import android.hardware.fingerprint.FingerprintSensorProperties; +import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Handler; import android.os.Looper; import android.os.UserManager; @@ -46,6 +48,7 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; import java.util.ArrayList; +import java.util.List; @Presubmit @SmallTest @@ -83,10 +86,18 @@ public class Fingerprint21Test { .thenReturn(5); mLockoutResetDispatcher = new LockoutResetDispatcher(mContext); - mFingerprint21 = new TestableFingerprint21(mContext, mScheduler, - new Handler(Looper.getMainLooper()), SENSOR_ID, - BiometricManager.Authenticators.BIOMETRIC_WEAK, mLockoutResetDispatcher, - mHalResultController); + + final int maxEnrollmentsPerUser = 1; + final List componentInfo = new ArrayList<>(); + final boolean resetLockoutRequiresHardwareAuthToken = false; + final FingerprintSensorPropertiesInternal sensorProps = + new FingerprintSensorPropertiesInternal(SENSOR_ID, + FingerprintSensorProperties.STRENGTH_WEAK, maxEnrollmentsPerUser, + componentInfo, FingerprintSensorProperties.TYPE_UNKNOWN, + resetLockoutRequiresHardwareAuthToken); + + mFingerprint21 = new TestableFingerprint21(mContext, sensorProps, mScheduler, + new Handler(Looper.getMainLooper()), mLockoutResetDispatcher, mHalResultController); } @Test @@ -107,12 +118,11 @@ public class Fingerprint21Test { private static class TestableFingerprint21 extends Fingerprint21 { TestableFingerprint21(@NonNull Context context, - @NonNull BiometricScheduler scheduler, - @NonNull Handler handler, int sensorId, int strength, + @NonNull FingerprintSensorPropertiesInternal sensorProps, + @NonNull BiometricScheduler scheduler, @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull HalResultController controller) { - super(context, scheduler, handler, sensorId, strength, lockoutResetDispatcher, - controller); + super(context, sensorProps, scheduler, handler, lockoutResetDispatcher, controller); } @Override