Support face unlock for PS if class2 biometric and above
With this change it is checked if face unlock is supported as a class2 or class3 biometrics on the device. If face is convenience biometrics then face unlock for private space controller is not added. Bug: 329044103 Test: atest UtilsTest and verified Face unlock is not added if face is convenience Change-Id: I6e1a6557774be1173ad3ee7ff7b14d51f9fe1716
This commit is contained in:
@@ -54,8 +54,10 @@ import android.graphics.drawable.AdaptiveIconDrawable;
|
|||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.VectorDrawable;
|
import android.graphics.drawable.VectorDrawable;
|
||||||
|
import android.hardware.biometrics.SensorProperties;
|
||||||
import android.hardware.face.Face;
|
import android.hardware.face.Face;
|
||||||
import android.hardware.face.FaceManager;
|
import android.hardware.face.FaceManager;
|
||||||
|
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||||
import android.hardware.fingerprint.Fingerprint;
|
import android.hardware.fingerprint.Fingerprint;
|
||||||
import android.hardware.fingerprint.FingerprintManager;
|
import android.hardware.fingerprint.FingerprintManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
@@ -927,6 +929,23 @@ public final class Utils extends com.android.settingslib.Utils {
|
|||||||
return hasFingerprintHardware(context) && hasFaceHardware(context);
|
return hasFingerprintHardware(context) && hasFaceHardware(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if face is supported as Class 2 biometrics and above on the device, false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
public static boolean isFaceNotConvenienceBiometric(@NonNull Context context) {
|
||||||
|
FaceManager faceManager = getFaceManagerOrNull(context);
|
||||||
|
if (faceManager != null) {
|
||||||
|
final List<FaceSensorPropertiesInternal> faceProperties =
|
||||||
|
faceManager.getSensorPropertiesInternal();
|
||||||
|
if (!faceProperties.isEmpty()) {
|
||||||
|
final FaceSensorPropertiesInternal props = faceProperties.get(0);
|
||||||
|
return props.sensorStrength != SensorProperties.STRENGTH_CONVENIENCE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Launches an intent which may optionally have a user id defined.
|
* Launches an intent which may optionally have a user id defined.
|
||||||
* @param fragment Fragment to use to launch the activity.
|
* @param fragment Fragment to use to launch the activity.
|
||||||
|
@@ -87,7 +87,8 @@ public class PrivateSpaceFacePreferenceController extends BiometricFaceStatusPre
|
|||||||
public void displayPreference(@NonNull PreferenceScreen screen) {
|
public void displayPreference(@NonNull PreferenceScreen screen) {
|
||||||
super.displayPreference(screen);
|
super.displayPreference(screen);
|
||||||
Preference preference = screen.findPreference(getPreferenceKey());
|
Preference preference = screen.findPreference(getPreferenceKey());
|
||||||
if (!Utils.isMultipleBiometricsSupported(mContext)) {
|
if (!Utils.isMultipleBiometricsSupported(mContext)
|
||||||
|
&& Utils.isFaceNotConvenienceBiometric(mContext)) {
|
||||||
preference.setTitle(R.string.private_space_face_title);
|
preference.setTitle(R.string.private_space_face_title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -89,7 +89,8 @@ public class PrivateSpaceFingerprintPreferenceController
|
|||||||
public void displayPreference(@NonNull PreferenceScreen screen) {
|
public void displayPreference(@NonNull PreferenceScreen screen) {
|
||||||
super.displayPreference(screen);
|
super.displayPreference(screen);
|
||||||
Preference preference = screen.findPreference(getPreferenceKey());
|
Preference preference = screen.findPreference(getPreferenceKey());
|
||||||
if (!Utils.isMultipleBiometricsSupported(mContext)) {
|
if (!Utils.isMultipleBiometricsSupported(mContext)
|
||||||
|
|| !Utils.isFaceNotConvenienceBiometric(mContext)) {
|
||||||
preference.setTitle(R.string.private_space_fingerprint_title);
|
preference.setTitle(R.string.private_space_fingerprint_title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -73,13 +73,14 @@ public class UseOneLockSettingsFragment extends DashboardFragment {
|
|||||||
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
final List<AbstractPreferenceController> controllers = new ArrayList<>();
|
||||||
controllers.add(new UseOneLockControllerSwitch(context, this));
|
controllers.add(new UseOneLockControllerSwitch(context, this));
|
||||||
controllers.add(new PrivateSpaceLockController(context, this));
|
controllers.add(new PrivateSpaceLockController(context, this));
|
||||||
if (Utils.isMultipleBiometricsSupported(context)) {
|
boolean isFaceAuthAllowed = Utils.isFaceNotConvenienceBiometric(context);
|
||||||
|
if (Utils.isMultipleBiometricsSupported(context) && isFaceAuthAllowed) {
|
||||||
controllers.add(new FaceFingerprintUnlockController(context, getSettingsLifecycle()));
|
controllers.add(new FaceFingerprintUnlockController(context, getSettingsLifecycle()));
|
||||||
} else if (Utils.hasFingerprintHardware(context)) {
|
} else if (Utils.hasFingerprintHardware(context)) {
|
||||||
controllers.add(
|
controllers.add(
|
||||||
new PrivateSpaceFingerprintPreferenceController(
|
new PrivateSpaceFingerprintPreferenceController(
|
||||||
context, "private_space_biometrics", getSettingsLifecycle()));
|
context, "private_space_biometrics", getSettingsLifecycle()));
|
||||||
} else if (Utils.hasFaceHardware(context)) {
|
} else if (Utils.hasFaceHardware(context) && isFaceAuthAllowed) {
|
||||||
controllers.add(
|
controllers.add(
|
||||||
new PrivateSpaceFacePreferenceController(
|
new PrivateSpaceFacePreferenceController(
|
||||||
context, "private_space_biometrics", getSettingsLifecycle()));
|
context, "private_space_biometrics", getSettingsLifecycle()));
|
||||||
|
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package com.android.settings;
|
package com.android.settings;
|
||||||
|
|
||||||
|
import static android.hardware.biometrics.SensorProperties.STRENGTH_CONVENIENCE;
|
||||||
|
import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
|
||||||
|
import static android.hardware.biometrics.SensorProperties.STRENGTH_WEAK;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
@@ -43,6 +47,9 @@ import android.graphics.Color;
|
|||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.VectorDrawable;
|
import android.graphics.drawable.VectorDrawable;
|
||||||
|
import android.hardware.face.FaceManager;
|
||||||
|
import android.hardware.face.FaceSensorProperties;
|
||||||
|
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
@@ -433,6 +440,69 @@ public class UtilsTest {
|
|||||||
assertNull(confirmCredentialString);
|
assertNull(confirmCredentialString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isFaceNotConvenienceBiometric_faceStrengthStrong_shouldReturnTrue() {
|
||||||
|
FaceManager mockFaceManager = mock(FaceManager.class);
|
||||||
|
when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mockFaceManager);
|
||||||
|
doReturn(true).when(mPackageManager).hasSystemFeature(anyString());
|
||||||
|
List<FaceSensorPropertiesInternal> props = List.of(new FaceSensorPropertiesInternal(
|
||||||
|
0 /* id */,
|
||||||
|
STRENGTH_STRONG,
|
||||||
|
1 /* maxTemplatesAllowed */,
|
||||||
|
new ArrayList<>() /* componentInfo */,
|
||||||
|
FaceSensorProperties.TYPE_UNKNOWN,
|
||||||
|
true /* supportsFaceDetection */,
|
||||||
|
true /* supportsSelfIllumination */,
|
||||||
|
false /* resetLockoutRequiresChallenge */));
|
||||||
|
doReturn(props).when(mockFaceManager).getSensorPropertiesInternal();
|
||||||
|
|
||||||
|
assertThat(Utils.isFaceNotConvenienceBiometric(mContext)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isFaceNotConvenienceBiometric_faceStrengthWeak_shouldReturnTrue() {
|
||||||
|
FaceManager mockFaceManager = mock(FaceManager.class);
|
||||||
|
when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mockFaceManager);
|
||||||
|
doReturn(true).when(mPackageManager).hasSystemFeature(anyString());
|
||||||
|
List<FaceSensorPropertiesInternal> props = List.of(new FaceSensorPropertiesInternal(
|
||||||
|
0 /* id */,
|
||||||
|
STRENGTH_WEAK,
|
||||||
|
1 /* maxTemplatesAllowed */,
|
||||||
|
new ArrayList<>() /* componentInfo */,
|
||||||
|
FaceSensorProperties.TYPE_UNKNOWN,
|
||||||
|
true /* supportsFaceDetection */,
|
||||||
|
true /* supportsSelfIllumination */,
|
||||||
|
false /* resetLockoutRequiresChallenge */));
|
||||||
|
doReturn(props).when(mockFaceManager).getSensorPropertiesInternal();
|
||||||
|
|
||||||
|
assertThat(Utils.isFaceNotConvenienceBiometric(mContext)).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isFaceNotConvenienceBiometric_faceStrengthConvenience_shouldReturnFalse() {
|
||||||
|
FaceManager mockFaceManager = mock(FaceManager.class);
|
||||||
|
when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(mockFaceManager);
|
||||||
|
doReturn(true).when(mPackageManager).hasSystemFeature(anyString());
|
||||||
|
List<FaceSensorPropertiesInternal> props = List.of(new FaceSensorPropertiesInternal(
|
||||||
|
0 /* id */,
|
||||||
|
STRENGTH_CONVENIENCE,
|
||||||
|
1 /* maxTemplatesAllowed */,
|
||||||
|
new ArrayList<>() /* componentInfo */,
|
||||||
|
FaceSensorProperties.TYPE_UNKNOWN,
|
||||||
|
true /* supportsFaceDetection */,
|
||||||
|
true /* supportsSelfIllumination */,
|
||||||
|
false /* resetLockoutRequiresChallenge */));
|
||||||
|
doReturn(props).when(mockFaceManager).getSensorPropertiesInternal();
|
||||||
|
|
||||||
|
assertThat(Utils.isFaceNotConvenienceBiometric(mContext)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void isFaceNotConvenienceBiometric_faceManagerNull_shouldReturnFalse() {
|
||||||
|
when(mContext.getSystemService(Context.FACE_SERVICE)).thenReturn(null);
|
||||||
|
assertThat(Utils.isFaceNotConvenienceBiometric(mContext)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
private void setUpForConfirmCredentialString(boolean isEffectiveUserManagedProfile) {
|
private void setUpForConfirmCredentialString(boolean isEffectiveUserManagedProfile) {
|
||||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager);
|
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager);
|
||||||
when(mMockUserManager.getCredentialOwnerProfile(USER_ID)).thenReturn(USER_ID);
|
when(mMockUserManager.getCredentialOwnerProfile(USER_ID)).thenReturn(USER_ID);
|
||||||
|
Reference in New Issue
Block a user