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
This commit is contained in:
@@ -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<ComponentInfoInternal> componentInfo,
|
||||
boolean resetLockoutRequiresHardwareAuthToken, boolean resetLockoutRequiresChallenge) {
|
||||
this.sensorId = sensorId;
|
||||
|
||||
@@ -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<FaceSensorPropertiesInternal> hidlSensors);
|
||||
}
|
||||
|
||||
@@ -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<ComponentInfoInternal> 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();
|
||||
|
||||
@@ -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<FingerprintSensorPropertiesInternal> hidlSensors);
|
||||
|
||||
// Notifies about a finger touching the sensor area.
|
||||
void onPointerDown(int sensorId, int x, int y, float minor, float major);
|
||||
|
||||
@@ -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<SensorPropertiesInternal> hidlSensors);
|
||||
}
|
||||
|
||||
@@ -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<FingerprintSensorPropertiesInternal> hidlFingerprintSensors = new ArrayList<>();
|
||||
List<FaceSensorPropertiesInternal> hidlFaceSensors = new ArrayList<>();
|
||||
// Iris doesn't have IrisSensorPropertiesInternal, using SensorPropertiesInternal instead.
|
||||
List<SensorPropertiesInternal> 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<ComponentInfoInternal> 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<ComponentInfoInternal> 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<ComponentInfoInternal> componentInfo = new ArrayList<>();
|
||||
final boolean resetLockoutRequiresHardwareAuthToken = false;
|
||||
final boolean resetLockoutRequiresChallenge = false;
|
||||
return new SensorPropertiesInternal(sensorId,
|
||||
Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser,
|
||||
componentInfo, resetLockoutRequiresHardwareAuthToken,
|
||||
resetLockoutRequiresChallenge);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<FaceSensorPropertiesInternal> 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<FaceSensorPropertiesInternal> 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<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);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<ComponentInfoInternal>() /* 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 */));
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<FingerprintSensorPropertiesInternal> 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<FingerprintSensorPropertiesInternal> 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<FingerprintSensorPropertiesInternal> 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);
|
||||
|
||||
@@ -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<ComponentInfoInternal>() /* 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
|
||||
|
||||
@@ -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<ComponentInfoInternal>() /* 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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<SensorPropertiesInternal> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> 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");
|
||||
|
||||
@@ -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<List<FingerprintSensorPropertiesInternal>> mFingerprintPropsCaptor;
|
||||
@Captor
|
||||
private ArgumentCaptor<List<FaceSensorPropertiesInternal>> 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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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<ComponentInfoInternal> 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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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<ComponentInfoInternal> 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
|
||||
|
||||
Reference in New Issue
Block a user