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:
Ilya Matyukhin
2021-04-20 19:32:28 -07:00
parent c72ac760e1
commit e1b53af498
20 changed files with 504 additions and 372 deletions

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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();
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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 */));
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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");

View File

@@ -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));
}

View File

@@ -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();
}

View File

@@ -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