Merge "Match Framework and AIDL SensorProps"

This commit is contained in:
Kevin Chyn
2020-09-23 21:33:35 +00:00
committed by Android (Google) Code Review
17 changed files with 180 additions and 49 deletions

View File

@@ -103,6 +103,7 @@ public class BiometricManager {
@IntDef(flag = true, value = {
BIOMETRIC_STRONG,
BIOMETRIC_WEAK,
BIOMETRIC_CONVENIENCE,
DEVICE_CREDENTIAL,
})
@interface Types {}

View File

@@ -0,0 +1,82 @@
/*
* 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 android.hardware.biometrics;
import android.annotation.IntDef;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* The base class containing all sensor-agnostic information. This is a superset of the
* {@link android.hardware.biometrics.common.CommonProps}, and provides backwards-compatible
* behavior with the older generation of HIDL (non-AIDL) interfaces.
* @hide
*/
public class SensorProperties implements Parcelable {
public static final int STRENGTH_CONVENIENCE = 0;
public static final int STRENGTH_WEAK = 1;
public static final int STRENGTH_STRONG = 2;
@IntDef({STRENGTH_CONVENIENCE, STRENGTH_WEAK, STRENGTH_STRONG})
@Retention(RetentionPolicy.SOURCE)
public @interface Strength {}
public final int sensorId;
@Strength public final int sensorStrength;
public final int maxEnrollmentsPerUser;
protected SensorProperties(int sensorId, @Strength int sensorStrength,
int maxEnrollmentsPerUser) {
this.sensorId = sensorId;
this.sensorStrength = sensorStrength;
this.maxEnrollmentsPerUser = maxEnrollmentsPerUser;
}
protected SensorProperties(Parcel in) {
sensorId = in.readInt();
sensorStrength = in.readInt();
maxEnrollmentsPerUser = in.readInt();
}
public static final Creator<SensorProperties> CREATOR = new Creator<SensorProperties>() {
@Override
public SensorProperties createFromParcel(Parcel in) {
return new SensorProperties(in);
}
@Override
public SensorProperties[] newArray(int size) {
return new SensorProperties[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(sensorId);
dest.writeInt(sensorStrength);
dest.writeInt(maxEnrollmentsPerUser);
}
}

View File

@@ -110,5 +110,5 @@ interface IFaceService {
String opPackageName);
// Give FaceService its ID. See AuthService.java
void initializeConfiguration(int sensorId);
void initializeConfiguration(int sensorId, int strength);
}

View File

@@ -17,6 +17,7 @@
package android.hardware.fingerprint;
import android.annotation.IntDef;
import android.hardware.biometrics.SensorProperties;
import android.hardware.face.FaceSensorProperties;
import android.os.Parcel;
import android.os.Parcelable;
@@ -28,45 +29,44 @@ import java.lang.annotation.RetentionPolicy;
* Container for fingerprint sensor properties.
* @hide
*/
public class FingerprintSensorProperties implements Parcelable {
public class FingerprintSensorProperties extends SensorProperties {
public static final int TYPE_UNKNOWN = 0;
public static final int TYPE_REAR = 1;
public static final int TYPE_UDFPS = 2;
public static final int TYPE_POWER_BUTTON = 3;
public static final int TYPE_UDFPS_ULTRASONIC = 2;
public static final int TYPE_UDFPS_OPTICAL = 3;
public static final int TYPE_POWER_BUTTON = 4;
public static final int TYPE_HOME_BUTTON = 5;
@IntDef({
TYPE_UNKNOWN,
@IntDef({TYPE_UNKNOWN,
TYPE_REAR,
TYPE_UDFPS,
TYPE_POWER_BUTTON})
TYPE_UDFPS_ULTRASONIC,
TYPE_UDFPS_OPTICAL,
TYPE_POWER_BUTTON,
TYPE_HOME_BUTTON})
@Retention(RetentionPolicy.SOURCE)
public @interface SensorType {}
public final int sensorId;
public final @SensorType int sensorType;
// IBiometricsFingerprint@2.1 does not manage timeout below the HAL, so the Gatekeeper HAT
// cannot be checked
public final boolean resetLockoutRequiresHardwareAuthToken;
// Maximum number of enrollments a user/profile can have.
public final int maxTemplatesAllowed;
/**
* Initializes SensorProperties with specified values
*/
public FingerprintSensorProperties(int sensorId, @SensorType int sensorType,
boolean resetLockoutRequiresHardwareAuthToken, int maxTemplatesAllowed) {
this.sensorId = sensorId;
public FingerprintSensorProperties(int sensorId, @Strength int strength,
int maxEnrollmentsPerUser, @SensorType int sensorType,
boolean resetLockoutRequiresHardwareAuthToken) {
super(sensorId, strength, maxEnrollmentsPerUser);
this.sensorType = sensorType;
this.resetLockoutRequiresHardwareAuthToken = resetLockoutRequiresHardwareAuthToken;
this.maxTemplatesAllowed = maxTemplatesAllowed;
}
protected FingerprintSensorProperties(Parcel in) {
sensorId = in.readInt();
super(in);
sensorType = in.readInt();
resetLockoutRequiresHardwareAuthToken = in.readBoolean();
maxTemplatesAllowed = in.readInt();
}
public static final Creator<FingerprintSensorProperties> CREATOR =
@@ -89,9 +89,18 @@ public class FingerprintSensorProperties implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(sensorId);
super.writeToParcel(dest, flags);
dest.writeInt(sensorType);
dest.writeBoolean(resetLockoutRequiresHardwareAuthToken);
dest.writeInt(maxTemplatesAllowed);
}
public boolean isAnyUdfpsType() {
switch (sensorType) {
case TYPE_UDFPS_OPTICAL:
case TYPE_UDFPS_ULTRASONIC:
return true;
default:
return false;
}
}
}

View File

@@ -118,7 +118,7 @@ interface IFingerprintService {
void removeClientActiveCallback(IFingerprintClientActiveCallback callback);
// Give FingerprintService its ID. See AuthService.java
void initializeConfiguration(int sensorId);
void initializeConfiguration(int sensorId, int strength);
// Notifies about a finger touching the sensor area.
void onFingerDown(int x, int y, float minor, float major);

View File

@@ -309,7 +309,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
final List<FingerprintSensorProperties> fingerprintSensorProperties =
mFingerprintManager.getSensorProperties();
for (FingerprintSensorProperties props : fingerprintSensorProperties) {
if (props.sensorType == FingerprintSensorProperties.TYPE_UDFPS) {
if (props.isAnyUdfpsType()) {
mUdfpsController = mUdfpsControllerFactory.get();
break;
}

View File

@@ -45,6 +45,7 @@ import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.biometrics.SensorProperties;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
@@ -119,8 +120,11 @@ public class AuthControllerTest extends SysuiTestCase {
when(mDialog2.isAllowDeviceCredentials()).thenReturn(false);
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
FingerprintSensorProperties prop = new FingerprintSensorProperties(
1, FingerprintSensorProperties.TYPE_UDFPS, true, 1);
FingerprintSensorProperties prop = new FingerprintSensorProperties(1 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
1 /* maxEnrollmentsPerUser */,
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
true /* resetLockoutRequireHardwareAuthToken */);
List<FingerprintSensorProperties> props = new ArrayList<>();
props.add(prop);
when(mFingerprintManager.getSensorProperties()).thenReturn(props);

View File

@@ -16,13 +16,15 @@
package com.android.server.biometrics;
import android.hardware.biometrics.BiometricManager;
/**
* Parsed sensor config. See core/res/res/values/config.xml config_biometric_sensors
*/
public class SensorConfig {
public final int id;
final int modality;
final int strength;
@BiometricManager.Authenticators.Types public final int strength;
public SensorConfig(String config) {
String[] elems = config.split(":");

View File

@@ -48,6 +48,7 @@ import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.PromptInfo;
import android.hardware.biometrics.SensorProperties;
import android.os.Binder;
import android.os.Build;
import android.os.RemoteException;
@@ -444,4 +445,22 @@ public class Utils {
}
return false;
}
/**
* Converts from {@link BiometricManager.Authenticators} biometric strength to the internal
* {@link SensorProperties} strength.
*/
public static @SensorProperties.Strength int authenticatorStrengthToPropertyStrength(
@BiometricManager.Authenticators.Types int strength) {
switch (strength) {
case BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE:
return SensorProperties.STRENGTH_CONVENIENCE;
case BiometricManager.Authenticators.BIOMETRIC_WEAK:
return SensorProperties.STRENGTH_WEAK;
case BiometricManager.Authenticators.BIOMETRIC_STRONG:
return SensorProperties.STRENGTH_STRONG;
default:
throw new IllegalArgumentException("Unknown strength: " + strength);
}
}
}

View File

@@ -26,6 +26,7 @@ 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.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
@@ -279,6 +280,7 @@ class Face10 implements IHwBinder.DeathRecipient {
};
Face10(@NonNull Context context, int sensorId,
@BiometricManager.Authenticators.Types int strength,
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
final boolean supportsSelfIllumination = context.getResources()
.getBoolean(R.bool.config_faceAuthSupportsSelfIllumination);

View File

@@ -34,7 +34,7 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
public FaceAuthenticator(IFaceService faceService, SensorConfig config)
throws RemoteException {
mFaceService = faceService;
mFaceService.initializeConfiguration(config.id);
mFaceService.initializeConfiguration(config.id, config.strength);
}
@Override

View File

@@ -21,6 +21,7 @@ import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricSensorReceiver;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
@@ -308,9 +309,10 @@ public class FaceService extends SystemService {
}
@Override // Binder call
public void initializeConfiguration(int sensorId) {
public void initializeConfiguration(int sensorId,
@BiometricManager.Authenticators.Types int strength) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
mFace10 = new Face10(getContext(), sensorId, mLockoutResetDispatcher);
mFace10 = new Face10(getContext(), sensorId, strength, mLockoutResetDispatcher);
}
}

View File

@@ -27,6 +27,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.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.biometrics.fingerprint.V2_2.IBiometricsFingerprintClientCallback;
@@ -296,6 +297,7 @@ class Fingerprint21 implements IHwBinder.DeathRecipient {
Fingerprint21(@NonNull Context context, @NonNull BiometricScheduler scheduler,
@NonNull Handler handler, int sensorId,
@BiometricManager.Authenticators.Types int strength,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull HalResultController controller) {
mContext = context;
@@ -335,25 +337,27 @@ class Fingerprint21 implements IHwBinder.DeathRecipient {
}
final @FingerprintSensorProperties.SensorType int sensorType =
isUdfps ? FingerprintSensorProperties.TYPE_UDFPS
isUdfps ? FingerprintSensorProperties.TYPE_UDFPS_OPTICAL
: FingerprintSensorProperties.TYPE_REAR;
// resetLockout is controlled by the framework, so hardwareAuthToken is not required
final boolean resetLockoutRequiresHardwareAuthToken = false;
final int maxTemplatesAllowed = mContext.getResources()
final int maxEnrollmentsPerUser = mContext.getResources()
.getInteger(R.integer.config_fingerprintMaxTemplatesPerUser);
mSensorProperties = new FingerprintSensorProperties(sensorId, sensorType,
resetLockoutRequiresHardwareAuthToken, maxTemplatesAllowed);
mSensorProperties = new FingerprintSensorProperties(sensorId,
Utils.authenticatorStrengthToPropertyStrength(strength), maxEnrollmentsPerUser,
sensorType, resetLockoutRequiresHardwareAuthToken);
}
static Fingerprint21 newInstance(@NonNull Context context, int sensorId,
static Fingerprint21 newInstance(@NonNull Context context, int sensorId, int strength,
@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(context, handler, scheduler);
return new Fingerprint21(context, scheduler, handler, sensorId, lockoutResetDispatcher,
controller);
return new Fingerprint21(context, scheduler, handler, sensorId, strength,
lockoutResetDispatcher, controller);
}
@Override

View File

@@ -21,6 +21,7 @@ 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.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
@@ -36,6 +37,7 @@ 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.BiometricScheduler;
import com.android.server.biometrics.sensors.ClientMonitor;
@@ -266,6 +268,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
}
static Fingerprint21UdfpsMock newInstance(@NonNull Context context, int sensorId,
@BiometricManager.Authenticators.Types int strength,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) {
Slog.d(TAG, "Creating Fingerprint23Mock!");
@@ -275,7 +278,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
new TestableBiometricScheduler(TAG, gestureAvailabilityDispatcher);
final MockHalResultController controller =
new MockHalResultController(context, handler, scheduler);
return new Fingerprint21UdfpsMock(context, scheduler, handler, sensorId,
return new Fingerprint21UdfpsMock(context, scheduler, handler, sensorId, strength,
lockoutResetDispatcher, controller);
}
@@ -401,9 +404,10 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
private Fingerprint21UdfpsMock(@NonNull Context context,
@NonNull TestableBiometricScheduler scheduler,
@NonNull Handler handler, int sensorId,
@BiometricManager.Authenticators.Types int strength,
@NonNull LockoutResetDispatcher lockoutResetDispatcher,
@NonNull MockHalResultController controller) {
super(context, scheduler, handler, sensorId, lockoutResetDispatcher, controller);
super(context, scheduler, handler, sensorId, strength, lockoutResetDispatcher, controller);
mScheduler = scheduler;
mScheduler.init(this);
mHandler = handler;
@@ -412,8 +416,9 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage
final int maxTemplatesAllowed = mContext.getResources()
.getInteger(R.integer.config_fingerprintMaxTemplatesPerUser);
mSensorProperties = new FingerprintSensorProperties(sensorId,
FingerprintSensorProperties.TYPE_UDFPS, resetLockoutRequiresHardwareAuthToken,
maxTemplatesAllowed);
Utils.authenticatorStrengthToPropertyStrength(strength), maxTemplatesAllowed,
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
resetLockoutRequiresHardwareAuthToken);
mMockHalResultController = controller;
mUserHasTrust = new SparseBooleanArray();
mTrustManager = context.getSystemService(TrustManager.class);

View File

@@ -34,7 +34,7 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub
public FingerprintAuthenticator(IFingerprintService fingerprintService, SensorConfig config)
throws RemoteException {
mFingerprintService = fingerprintService;
mFingerprintService.initializeConfiguration(config.id);
mFingerprintService.initializeConfiguration(config.id, config.strength);
}
@Override

View File

@@ -384,7 +384,7 @@ public class FingerprintService extends SystemService {
}
@Override // Binder call
public void initializeConfiguration(int sensorId) {
public void initializeConfiguration(int sensorId, int strength) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
if ((Build.IS_USERDEBUG || Build.IS_ENG)
@@ -393,9 +393,9 @@ public class FingerprintService extends SystemService {
Fingerprint21UdfpsMock.CONFIG_ENABLE_TEST_UDFPS, 0 /* default */,
UserHandle.USER_CURRENT) != 0) {
mFingerprint21 = Fingerprint21UdfpsMock.newInstance(getContext(), sensorId,
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
strength, mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
} else {
mFingerprint21 = Fingerprint21.newInstance(getContext(), sensorId,
mFingerprint21 = Fingerprint21.newInstance(getContext(), sensorId, strength,
mLockoutResetDispatcher, mGestureAvailabilityDispatcher);
}
}

View File

@@ -123,8 +123,7 @@ public class AuthServiceTest {
final String[] config = {
"0:2:15", // ID0:Fingerprint:Strong
"1:4:255", // ID1:Iris:Weak
"2:8:4095", // ID2:Face:Convenience
"1:8:4095", // ID2:Face:Convenience
};
when(mInjector.getConfiguration(any())).thenReturn(config);
@@ -133,12 +132,14 @@ public class AuthServiceTest {
mAuthService.onStart();
final int fingerprintId = 0;
final int irisId = 1;
final int faceId = 2;
final int faceId = 1;
verify(mFingerprintService).initializeConfiguration(eq(fingerprintId));
verify(mIrisService).initializeConfiguration(eq(irisId));
verify(mFaceService).initializeConfiguration(eq(faceId));
final int fingerprintStrength = 15;
final int faceStrength = 4095;
verify(mFingerprintService).initializeConfiguration(eq(fingerprintId),
eq(fingerprintStrength));
verify(mFaceService).initializeConfiguration(eq(faceId), eq(faceStrength));
}