summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/biometrics/BiometricConstants.java6
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java27
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricService.java13
-rw-r--r--services/core/java/com/android/server/biometrics/PreAuthInfo.java88
-rw-r--r--services/core/java/com/android/server/biometrics/Utils.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java62
8 files changed, 181 insertions, 25 deletions
diff --git a/core/java/android/hardware/biometrics/BiometricConstants.java b/core/java/android/hardware/biometrics/BiometricConstants.java
index 43ef33e1f420..28046c56b9f8 100644
--- a/core/java/android/hardware/biometrics/BiometricConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricConstants.java
@@ -151,6 +151,12 @@ public interface BiometricConstants {
int BIOMETRIC_ERROR_RE_ENROLL = 16;
/**
+ * The privacy setting has been enabled and will block use of the sensor.
+ * @hide
+ */
+ int BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED = 18;
+
+ /**
* This constant is only used by SystemUI. It notifies SystemUI that authentication was paused
* because the authentication attempt was unsuccessful.
* @hide
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 3c7f0267d943..166d6abd1809 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1666,6 +1666,8 @@
<string name="face_setup_notification_title">Set up Face Unlock</string>
<!-- Contents of a notification that directs the user to set up face unlock by enrolling their face. [CHAR LIMIT=NONE] -->
<string name="face_setup_notification_content">Unlock your phone by looking at it</string>
+ <!-- Error message indicating that the camera privacy sensor has been turned on [CHAR LIMIT=NONE] -->
+ <string name="face_sensor_privacy_enabled">To use Face Unlock, turn on <b>Camera access</b> in Settings > Privacy</string>
<!-- Title of a notification that directs the user to enroll a fingerprint. [CHAR LIMIT=NONE] -->
<string name="fingerprint_setup_notification_title">Set up more ways to unlock</string>
<!-- Contents of a notification that directs the user to enroll a fingerprint. [CHAR LIMIT=NONE] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index a23816e8174a..54282bef00f0 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2570,6 +2570,7 @@
<java-symbol type="string" name="face_recalibrate_notification_name" />
<java-symbol type="string" name="face_recalibrate_notification_title" />
<java-symbol type="string" name="face_recalibrate_notification_content" />
+ <java-symbol type="string" name="face_sensor_privacy_enabled" />
<java-symbol type="string" name="face_error_unable_to_process" />
<java-symbol type="string" name="face_error_hw_not_available" />
<java-symbol type="string" name="face_error_no_space" />
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 1226dca1f306..d8f6a01398d1 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -31,6 +31,7 @@ import android.content.IntentFilter;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PointF;
+import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
@@ -89,6 +90,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
private static final String TAG = "AuthController";
private static final boolean DEBUG = true;
+ private static final int SENSOR_PRIVACY_DELAY = 500;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final CommandQueue mCommandQueue;
@@ -122,6 +124,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
@Nullable private List<FingerprintSensorPropertiesInternal> mSidefpsProps;
@NonNull private final SparseBooleanArray mUdfpsEnrolledForUser;
+ private SensorPrivacyManager mSensorPrivacyManager;
private class BiometricTaskStackListener extends TaskStackListener {
@Override
@@ -492,6 +495,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.registerReceiver(mBroadcastReceiver, filter);
+ mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
}
private void updateFingerprintLocation() {
@@ -642,10 +646,16 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
final boolean isLockout = (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT)
|| (error == BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT);
+ boolean isCameraPrivacyEnabled = false;
+ if (error == BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE
+ && mSensorPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA,
+ mCurrentDialogArgs.argi1 /* userId */)) {
+ isCameraPrivacyEnabled = true;
+ }
// TODO(b/141025588): Create separate methods for handling hard and soft errors.
final boolean isSoftError = (error == BiometricConstants.BIOMETRIC_PAUSED_REJECTED
- || error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT);
-
+ || error == BiometricConstants.BIOMETRIC_ERROR_TIMEOUT
+ || isCameraPrivacyEnabled);
if (mCurrentDialog != null) {
if (mCurrentDialog.isAllowDeviceCredentials() && isLockout) {
if (DEBUG) Log.d(TAG, "onBiometricError, lockout");
@@ -655,12 +665,23 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
? mContext.getString(R.string.biometric_not_recognized)
: getErrorString(modality, error, vendorCode);
if (DEBUG) Log.d(TAG, "onBiometricError, soft error: " + errorMessage);
- mCurrentDialog.onAuthenticationFailed(modality, errorMessage);
+ // The camera privacy error can return before the prompt initializes its state,
+ // causing the prompt to appear to endlessly authenticate. Add a small delay
+ // to stop this.
+ if (isCameraPrivacyEnabled) {
+ mHandler.postDelayed(() -> {
+ mCurrentDialog.onAuthenticationFailed(modality,
+ mContext.getString(R.string.face_sensor_privacy_enabled));
+ }, SENSOR_PRIVACY_DELAY);
+ } else {
+ mCurrentDialog.onAuthenticationFailed(modality, errorMessage);
+ }
} else {
final String errorMessage = getErrorString(modality, error, vendorCode);
if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage);
mCurrentDialog.onError(modality, errorMessage);
}
+
} else {
Log.w(TAG, "onBiometricError callback but dialog is gone");
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index f42870b4b734..758cf7a7d430 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -1036,7 +1036,8 @@ public class BiometricService extends SystemService {
promptInfo.setAuthenticators(authenticators);
return PreAuthInfo.create(mTrustManager, mDevicePolicyManager, mSettingObserver, mSensors,
- userId, promptInfo, opPackageName, false /* checkDevicePolicyManager */);
+ userId, promptInfo, opPackageName, false /* checkDevicePolicyManager */,
+ getContext());
}
/**
@@ -1375,7 +1376,8 @@ public class BiometricService extends SystemService {
try {
final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager,
mDevicePolicyManager, mSettingObserver, mSensors, userId, promptInfo,
- opPackageName, promptInfo.isDisallowBiometricsIfPolicyExists());
+ opPackageName, promptInfo.isDisallowBiometricsIfPolicyExists(),
+ getContext());
final Pair<Integer, Integer> preAuthStatus = preAuthInfo.getPreAuthenticateStatus();
@@ -1383,8 +1385,11 @@ public class BiometricService extends SystemService {
+ "), status(" + preAuthStatus.second + "), preAuthInfo: " + preAuthInfo
+ " requestId: " + requestId + " promptInfo.isIgnoreEnrollmentState: "
+ promptInfo.isIgnoreEnrollmentState());
-
- if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS) {
+ // BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED is added so that BiometricPrompt can
+ // be shown for this case.
+ if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS
+ || preAuthStatus.second
+ == BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED) {
// If BIOMETRIC_WEAK or BIOMETRIC_STRONG are allowed, but not enrolled, but
// CREDENTIAL is requested and available, set the bundle to only request
// CREDENTIAL.
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index a5a3542f49c7..05c3f68f355b 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -26,6 +26,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustManager;
+import android.content.Context;
+import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.PromptInfo;
@@ -59,6 +61,7 @@ class PreAuthInfo {
static final int CREDENTIAL_NOT_ENROLLED = 9;
static final int BIOMETRIC_LOCKOUT_TIMED = 10;
static final int BIOMETRIC_LOCKOUT_PERMANENT = 11;
+ static final int BIOMETRIC_SENSOR_PRIVACY_ENABLED = 12;
@IntDef({AUTHENTICATOR_OK,
BIOMETRIC_NO_HARDWARE,
BIOMETRIC_DISABLED_BY_DEVICE_POLICY,
@@ -69,7 +72,8 @@ class PreAuthInfo {
BIOMETRIC_NOT_ENABLED_FOR_APPS,
CREDENTIAL_NOT_ENROLLED,
BIOMETRIC_LOCKOUT_TIMED,
- BIOMETRIC_LOCKOUT_PERMANENT})
+ BIOMETRIC_LOCKOUT_PERMANENT,
+ BIOMETRIC_SENSOR_PRIVACY_ENABLED})
@Retention(RetentionPolicy.SOURCE)
@interface AuthenticatorStatus {}
@@ -84,13 +88,15 @@ class PreAuthInfo {
final boolean credentialAvailable;
final boolean confirmationRequested;
final boolean ignoreEnrollmentState;
+ final int userId;
+ final Context context;
static PreAuthInfo create(ITrustManager trustManager,
DevicePolicyManager devicePolicyManager,
BiometricService.SettingObserver settingObserver,
List<BiometricSensor> sensors,
int userId, PromptInfo promptInfo, String opPackageName,
- boolean checkDevicePolicyManager)
+ boolean checkDevicePolicyManager, Context context)
throws RemoteException {
final boolean confirmationRequested = promptInfo.isConfirmationRequested();
@@ -116,14 +122,22 @@ class PreAuthInfo {
devicePolicyManager, settingObserver, sensor, userId, opPackageName,
checkDevicePolicyManager, requestedStrength,
promptInfo.getAllowedSensorIds(),
- promptInfo.isIgnoreEnrollmentState());
+ promptInfo.isIgnoreEnrollmentState(),
+ context);
Slog.d(TAG, "Package: " + opPackageName
+ " Sensor ID: " + sensor.id
+ " Modality: " + sensor.modality
+ " Status: " + status);
- if (status == AUTHENTICATOR_OK) {
+ // A sensor with privacy enabled will still be eligible to
+ // authenticate with biometric prompt. This is so the framework can display
+ // a sensor privacy error message to users after briefly showing the
+ // Biometric Prompt.
+ //
+ // Note: if only a certain sensor is required and the privacy is enabled,
+ // canAuthenticate() will return false.
+ if (status == AUTHENTICATOR_OK || status == BIOMETRIC_SENSOR_PRIVACY_ENABLED) {
eligibleSensors.add(sensor);
} else {
ineligibleSensors.add(new Pair<>(sensor, status));
@@ -133,7 +147,7 @@ class PreAuthInfo {
return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested,
eligibleSensors, ineligibleSensors, credentialAvailable, confirmationRequested,
- promptInfo.isIgnoreEnrollmentState());
+ promptInfo.isIgnoreEnrollmentState(), userId, context);
}
/**
@@ -149,7 +163,7 @@ class PreAuthInfo {
BiometricSensor sensor, int userId, String opPackageName,
boolean checkDevicePolicyManager, int requestedStrength,
@NonNull List<Integer> requestedSensorIds,
- boolean ignoreEnrollmentState) {
+ boolean ignoreEnrollmentState, Context context) {
if (!requestedSensorIds.isEmpty() && !requestedSensorIds.contains(sensor.id)) {
return BIOMETRIC_NO_HARDWARE;
@@ -175,6 +189,16 @@ class PreAuthInfo {
&& !ignoreEnrollmentState) {
return BIOMETRIC_NOT_ENROLLED;
}
+ final SensorPrivacyManager sensorPrivacyManager = context
+ .getSystemService(SensorPrivacyManager.class);
+
+ if (sensorPrivacyManager != null && sensor.modality == TYPE_FACE) {
+ if (sensorPrivacyManager
+ .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, userId)) {
+ return BIOMETRIC_SENSOR_PRIVACY_ENABLED;
+ }
+ }
+
final @LockoutTracker.LockoutMode int lockoutMode =
sensor.impl.getLockoutModeForUser(userId);
@@ -243,7 +267,8 @@ class PreAuthInfo {
private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested,
boolean credentialRequested, List<BiometricSensor> eligibleSensors,
List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable,
- boolean confirmationRequested, boolean ignoreEnrollmentState) {
+ boolean confirmationRequested, boolean ignoreEnrollmentState, int userId,
+ Context context) {
mBiometricRequested = biometricRequested;
mBiometricStrengthRequested = biometricStrengthRequested;
this.credentialRequested = credentialRequested;
@@ -253,6 +278,8 @@ class PreAuthInfo {
this.credentialAvailable = credentialAvailable;
this.confirmationRequested = confirmationRequested;
this.ignoreEnrollmentState = ignoreEnrollmentState;
+ this.userId = userId;
+ this.context = context;
}
private Pair<BiometricSensor, Integer> calculateErrorByPriority() {
@@ -280,15 +307,35 @@ class PreAuthInfo {
private Pair<Integer, Integer> getInternalStatus() {
@AuthenticatorStatus final int status;
@BiometricAuthenticator.Modality int modality = TYPE_NONE;
+
+ final SensorPrivacyManager sensorPrivacyManager = context
+ .getSystemService(SensorPrivacyManager.class);
+
+ boolean cameraPrivacyEnabled = false;
+ if (sensorPrivacyManager != null) {
+ cameraPrivacyEnabled = sensorPrivacyManager
+ .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, userId);
+ }
+
if (mBiometricRequested && credentialRequested) {
if (credentialAvailable || !eligibleSensors.isEmpty()) {
- status = AUTHENTICATOR_OK;
- if (credentialAvailable) {
- modality |= TYPE_CREDENTIAL;
- }
for (BiometricSensor sensor : eligibleSensors) {
modality |= sensor.modality;
}
+
+ if (credentialAvailable) {
+ modality |= TYPE_CREDENTIAL;
+ status = AUTHENTICATOR_OK;
+ } else if (modality == TYPE_FACE && cameraPrivacyEnabled) {
+ // If the only modality requested is face, credential is unavailable,
+ // and the face sensor privacy is enabled then return
+ // BIOMETRIC_SENSOR_PRIVACY_ENABLED.
+ //
+ // Note: This sensor will still be eligible for calls to authenticate.
+ status = BIOMETRIC_SENSOR_PRIVACY_ENABLED;
+ } else {
+ status = AUTHENTICATOR_OK;
+ }
} else {
// Pick the first sensor error if it exists
if (!ineligibleSensors.isEmpty()) {
@@ -302,10 +349,18 @@ class PreAuthInfo {
}
} else if (mBiometricRequested) {
if (!eligibleSensors.isEmpty()) {
- status = AUTHENTICATOR_OK;
- for (BiometricSensor sensor : eligibleSensors) {
- modality |= sensor.modality;
- }
+ for (BiometricSensor sensor : eligibleSensors) {
+ modality |= sensor.modality;
+ }
+ if (modality == TYPE_FACE && cameraPrivacyEnabled) {
+ // If the only modality requested is face and the privacy is enabled
+ // then return BIOMETRIC_SENSOR_PRIVACY_ENABLED.
+ //
+ // Note: This sensor will still be eligible for calls to authenticate.
+ status = BIOMETRIC_SENSOR_PRIVACY_ENABLED;
+ } else {
+ status = AUTHENTICATOR_OK;
+ }
} else {
// Pick the first sensor error if it exists
if (!ineligibleSensors.isEmpty()) {
@@ -326,9 +381,9 @@ class PreAuthInfo {
Slog.e(TAG, "No authenticators requested");
status = BIOMETRIC_NO_HARDWARE;
}
-
Slog.d(TAG, "getCanAuthenticateInternal Modality: " + modality
+ " AuthenticatorStatus: " + status);
+
return new Pair<>(modality, status);
}
@@ -362,6 +417,7 @@ class PreAuthInfo {
case CREDENTIAL_NOT_ENROLLED:
case BIOMETRIC_LOCKOUT_TIMED:
case BIOMETRIC_LOCKOUT_PERMANENT:
+ case BIOMETRIC_SENSOR_PRIVACY_ENABLED:
break;
case BIOMETRIC_DISABLED_BY_DEVICE_POLICY:
diff --git a/services/core/java/com/android/server/biometrics/Utils.java b/services/core/java/com/android/server/biometrics/Utils.java
index 4f7c6b012c23..0e2582c23b86 100644
--- a/services/core/java/com/android/server/biometrics/Utils.java
+++ b/services/core/java/com/android/server/biometrics/Utils.java
@@ -33,6 +33,7 @@ import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_LOCKOUT_TIMED;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENABLED_FOR_APPS;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENROLLED;
import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NO_HARDWARE;
+import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_SENSOR_PRIVACY_ENABLED;
import static com.android.server.biometrics.PreAuthInfo.CREDENTIAL_NOT_ENROLLED;
import android.annotation.NonNull;
@@ -278,6 +279,9 @@ public class Utils {
case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT:
biometricManagerCode = BiometricManager.BIOMETRIC_SUCCESS;
break;
+ case BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED:
+ biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
+ break;
default:
Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode);
biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE;
@@ -337,7 +341,8 @@ public class Utils {
case BIOMETRIC_LOCKOUT_PERMANENT:
return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT;
-
+ case BIOMETRIC_SENSOR_PRIVACY_ENABLED:
+ return BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED;
case BIOMETRIC_DISABLED_BY_DEVICE_POLICY:
case BIOMETRIC_HARDWARE_NOT_DETECTED:
case BIOMETRIC_NOT_ENABLED_FOR_APPS:
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
index b3f7587df612..b255a35c512e 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthSessionTest.java
@@ -302,6 +302,65 @@ public class AuthSessionTest {
testInvokesCancel(session -> session.onDialogDismissed(DISMISSED_REASON_NEGATIVE, null));
}
+ // TODO (b/208484275) : Enable these tests
+ // @Test
+ // public void testPreAuth_canAuthAndPrivacyDisabled() throws Exception {
+ // SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class);
+ // when(manager
+ // .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt()))
+ // .thenReturn(false);
+ // when(mContext.getSystemService(SensorPrivacyManager.class))
+ // .thenReturn(manager);
+ // setupFace(1 /* id */, false /* confirmationAlwaysRequired */,
+ // mock(IBiometricAuthenticator.class));
+ // final PromptInfo promptInfo = createPromptInfo(Authenticators.BIOMETRIC_STRONG);
+ // final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false);
+ // assertEquals(BiometricManager.BIOMETRIC_SUCCESS, preAuthInfo.getCanAuthenticateResult());
+ // for (BiometricSensor sensor : preAuthInfo.eligibleSensors) {
+ // assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState());
+ // }
+ // }
+
+ // @Test
+ // public void testPreAuth_cannotAuthAndPrivacyEnabled() throws Exception {
+ // SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class);
+ // when(manager
+ // .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt()))
+ // .thenReturn(true);
+ // when(mContext.getSystemService(SensorPrivacyManager.class))
+ // .thenReturn(manager);
+ // setupFace(1 /* id */, false /* confirmationAlwaysRequired */,
+ // mock(IBiometricAuthenticator.class));
+ // final PromptInfo promptInfo = createPromptInfo(Authenticators.BIOMETRIC_STRONG);
+ // final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false);
+ // assertEquals(BiometricManager.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED,
+ // preAuthInfo.getCanAuthenticateResult());
+ // // Even though canAuth returns privacy enabled, we should still be able to authenticate.
+ // for (BiometricSensor sensor : preAuthInfo.eligibleSensors) {
+ // assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState());
+ // }
+ // }
+
+ // @Test
+ // public void testPreAuth_canAuthAndPrivacyEnabledCredentialEnabled() throws Exception {
+ // SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class);
+ // when(manager
+ // .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt()))
+ // .thenReturn(true);
+ // when(mContext.getSystemService(SensorPrivacyManager.class))
+ // .thenReturn(manager);
+ // setupFace(1 /* id */, false /* confirmationAlwaysRequired */,
+ // mock(IBiometricAuthenticator.class));
+ // final PromptInfo promptInfo =
+ // createPromptInfo(Authenticators.BIOMETRIC_STRONG
+ // | Authenticators. DEVICE_CREDENTIAL);
+ // final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false);
+ // assertEquals(BiometricManager.BIOMETRIC_SUCCESS, preAuthInfo.getCanAuthenticateResult());
+ // for (BiometricSensor sensor : preAuthInfo.eligibleSensors) {
+ // assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState());
+ // }
+ // }
+
private void testInvokesCancel(Consumer<AuthSession> sessionConsumer) throws RemoteException {
final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
@@ -331,7 +390,8 @@ public class AuthSessionTest {
userId,
promptInfo,
TEST_PACKAGE,
- checkDevicePolicyManager);
+ checkDevicePolicyManager,
+ mContext);
}
private AuthSession createAuthSession(List<BiometricSensor> sensors,