For non-udfps, detectFP if primaryAuth required
If the user attempts to FP auth, we will listen for FP
detection (as opposed to authentication or not at all). If the
user places their finger on the FP sensor, without running the
FP matcher, we can show the bouncer.
Additionally, update the logic when switching users. Immediately
after a user switch, cancel the FP listening state and then
restart based on the new state (because it may change to/from
detect or authenticate).
Repro steps:
1. Enable extra logging:
adb shell settings put global systemui/buffer/KeyguardUpdateMonitorLog v
2. Setup side fps
3. Fail side fps 5 times to lock out fp
4. See logs that SysUI is running detectFP ("startListeningForFingerprint - detect")
5. Attempt FP => bouncer appears
Test: atest KeyguardUpdateMonitorTest
Test: atest SystemUITests
Bug: 245778799
Change-Id: Ic1d4984c7514fc96b6552267128dee814730bb30
This commit is contained in:
@@ -26,7 +26,6 @@ data class KeyguardFingerprintListenModel(
|
|||||||
val credentialAttempted: Boolean,
|
val credentialAttempted: Boolean,
|
||||||
val deviceInteractive: Boolean,
|
val deviceInteractive: Boolean,
|
||||||
val dreaming: Boolean,
|
val dreaming: Boolean,
|
||||||
val encryptedOrLockdown: Boolean,
|
|
||||||
val fingerprintDisabled: Boolean,
|
val fingerprintDisabled: Boolean,
|
||||||
val fingerprintLockedOut: Boolean,
|
val fingerprintLockedOut: Boolean,
|
||||||
val goingToSleep: Boolean,
|
val goingToSleep: Boolean,
|
||||||
@@ -37,6 +36,7 @@ data class KeyguardFingerprintListenModel(
|
|||||||
val primaryUser: Boolean,
|
val primaryUser: Boolean,
|
||||||
val shouldListenSfpsState: Boolean,
|
val shouldListenSfpsState: Boolean,
|
||||||
val shouldListenForFingerprintAssistant: Boolean,
|
val shouldListenForFingerprintAssistant: Boolean,
|
||||||
|
val strongerAuthRequired: Boolean,
|
||||||
val switchingUser: Boolean,
|
val switchingUser: Boolean,
|
||||||
val udfps: Boolean,
|
val udfps: Boolean,
|
||||||
val userDoesNotHaveTrust: Boolean
|
val userDoesNotHaveTrust: Boolean
|
||||||
|
|||||||
@@ -363,16 +363,18 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
final boolean sfpsEnabled = getResources().getBoolean(
|
final boolean sfpsEnabled = getResources().getBoolean(
|
||||||
R.bool.config_show_sidefps_hint_on_bouncer);
|
R.bool.config_show_sidefps_hint_on_bouncer);
|
||||||
final boolean fpsDetectionRunning = mUpdateMonitor.isFingerprintDetectionRunning();
|
final boolean fpsDetectionRunning = mUpdateMonitor.isFingerprintDetectionRunning();
|
||||||
final boolean needsStrongAuth = mUpdateMonitor.userNeedsStrongAuth();
|
final boolean isUnlockingWithFpAllowed =
|
||||||
|
mUpdateMonitor.isUnlockingWithFingerprintAllowed();
|
||||||
|
|
||||||
boolean toShow = mBouncerVisible && sfpsEnabled && fpsDetectionRunning && !needsStrongAuth;
|
boolean toShow = mBouncerVisible && sfpsEnabled && fpsDetectionRunning
|
||||||
|
&& isUnlockingWithFpAllowed;
|
||||||
|
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Log.d(TAG, "sideFpsToShow=" + toShow + ", "
|
Log.d(TAG, "sideFpsToShow=" + toShow + ", "
|
||||||
+ "mBouncerVisible=" + mBouncerVisible + ", "
|
+ "mBouncerVisible=" + mBouncerVisible + ", "
|
||||||
+ "configEnabled=" + sfpsEnabled + ", "
|
+ "configEnabled=" + sfpsEnabled + ", "
|
||||||
+ "fpsDetectionRunning=" + fpsDetectionRunning + ", "
|
+ "fpsDetectionRunning=" + fpsDetectionRunning + ", "
|
||||||
+ "needsStrongAuth=" + needsStrongAuth);
|
+ "isUnlockingWithFpAllowed=" + isUnlockingWithFpAllowed);
|
||||||
}
|
}
|
||||||
if (toShow) {
|
if (toShow) {
|
||||||
mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER);
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_P
|
|||||||
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_TIMED;
|
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_TIMED;
|
||||||
import static android.hardware.biometrics.BiometricConstants.LockoutMode;
|
import static android.hardware.biometrics.BiometricConstants.LockoutMode;
|
||||||
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
|
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
|
||||||
|
import static android.hardware.biometrics.BiometricSourceType.FACE;
|
||||||
|
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
|
||||||
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
|
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
|
||||||
|
|
||||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
|
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
|
||||||
@@ -228,7 +230,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
* Biometric authentication: Cancelling and waiting for the relevant biometric service to
|
* Biometric authentication: Cancelling and waiting for the relevant biometric service to
|
||||||
* send us the confirmation that cancellation has happened.
|
* send us the confirmation that cancellation has happened.
|
||||||
*/
|
*/
|
||||||
private static final int BIOMETRIC_STATE_CANCELLING = 2;
|
@VisibleForTesting
|
||||||
|
protected static final int BIOMETRIC_STATE_CANCELLING = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Biometric state: During cancelling we got another request to start listening, so when we
|
||||||
|
* receive the cancellation done signal, we should start listening again.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
protected static final int BIOMETRIC_STATE_CANCELLING_RESTARTING = 3;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action indicating keyguard *can* start biometric authentiation.
|
* Action indicating keyguard *can* start biometric authentiation.
|
||||||
@@ -243,12 +253,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
*/
|
*/
|
||||||
private static final int BIOMETRIC_ACTION_UPDATE = 2;
|
private static final int BIOMETRIC_ACTION_UPDATE = 2;
|
||||||
|
|
||||||
/**
|
|
||||||
* Biometric state: During cancelling we got another request to start listening, so when we
|
|
||||||
* receive the cancellation done signal, we should start listening again.
|
|
||||||
*/
|
|
||||||
private static final int BIOMETRIC_STATE_CANCELLING_RESTARTING = 3;
|
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
|
public static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
|
||||||
public static final int BIOMETRIC_HELP_FACE_NOT_RECOGNIZED = -2;
|
public static final int BIOMETRIC_HELP_FACE_NOT_RECOGNIZED = -2;
|
||||||
@@ -356,7 +360,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
|
|
||||||
private KeyguardBypassController mKeyguardBypassController;
|
private KeyguardBypassController mKeyguardBypassController;
|
||||||
private List<SubscriptionInfo> mSubscriptionInfo;
|
private List<SubscriptionInfo> mSubscriptionInfo;
|
||||||
private int mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
|
@VisibleForTesting
|
||||||
|
protected int mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
|
||||||
private int mFaceRunningState = BIOMETRIC_STATE_STOPPED;
|
private int mFaceRunningState = BIOMETRIC_STATE_STOPPED;
|
||||||
private boolean mIsDreaming;
|
private boolean mIsDreaming;
|
||||||
private boolean mLogoutEnabled;
|
private boolean mLogoutEnabled;
|
||||||
@@ -790,7 +795,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
new BiometricAuthenticated(true, isStrongBiometric));
|
new BiometricAuthenticated(true, isStrongBiometric));
|
||||||
// Update/refresh trust state only if user can skip bouncer
|
// Update/refresh trust state only if user can skip bouncer
|
||||||
if (getUserCanSkipBouncer(userId)) {
|
if (getUserCanSkipBouncer(userId)) {
|
||||||
mTrustManager.unlockedByBiometricForUser(userId, BiometricSourceType.FINGERPRINT);
|
mTrustManager.unlockedByBiometricForUser(userId, FINGERPRINT);
|
||||||
}
|
}
|
||||||
// Don't send cancel if authentication succeeds
|
// Don't send cancel if authentication succeeds
|
||||||
mFingerprintCancelSignal = null;
|
mFingerprintCancelSignal = null;
|
||||||
@@ -800,7 +805,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricAuthenticated(userId, BiometricSourceType.FINGERPRINT,
|
cb.onBiometricAuthenticated(userId, FINGERPRINT,
|
||||||
isStrongBiometric);
|
isStrongBiometric);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -833,7 +838,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
|
cb.onBiometricAuthFailed(FINGERPRINT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (isUdfpsSupported()) {
|
if (isUdfpsSupported()) {
|
||||||
@@ -858,7 +863,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricAcquired(BiometricSourceType.FINGERPRINT, acquireInfo);
|
cb.onBiometricAcquired(FINGERPRINT, acquireInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -892,7 +897,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricHelp(msgId, helpString, BiometricSourceType.FINGERPRINT);
|
cb.onBiometricHelp(msgId, helpString, FINGERPRINT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -944,7 +949,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
|
if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
|
||||||
lockedOutStateChanged = !mFingerprintLockedOutPermanent;
|
lockedOutStateChanged = !mFingerprintLockedOutPermanent;
|
||||||
mFingerprintLockedOutPermanent = true;
|
mFingerprintLockedOutPermanent = true;
|
||||||
mLogger.d("Fingerprint locked out - requiring strong auth");
|
mLogger.d("Fingerprint permanently locked out - requiring stronger auth");
|
||||||
mLockPatternUtils.requireStrongAuth(
|
mLockPatternUtils.requireStrongAuth(
|
||||||
STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, getCurrentUser());
|
STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, getCurrentUser());
|
||||||
}
|
}
|
||||||
@@ -953,6 +958,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
|| msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
|
|| msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
|
||||||
lockedOutStateChanged |= !mFingerprintLockedOut;
|
lockedOutStateChanged |= !mFingerprintLockedOut;
|
||||||
mFingerprintLockedOut = true;
|
mFingerprintLockedOut = true;
|
||||||
|
mLogger.d("Fingerprint temporarily locked out - requiring stronger auth");
|
||||||
if (isUdfpsEnrolled()) {
|
if (isUdfpsEnrolled()) {
|
||||||
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
|
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
|
||||||
}
|
}
|
||||||
@@ -963,12 +969,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricError(msgId, errString, BiometricSourceType.FINGERPRINT);
|
cb.onBiometricError(msgId, errString, FINGERPRINT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lockedOutStateChanged) {
|
if (lockedOutStateChanged) {
|
||||||
notifyLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
|
notifyLockedOutStateChanged(FINGERPRINT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -996,7 +1002,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
notifyLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
|
notifyLockedOutStateChanged(FINGERPRINT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1019,7 +1025,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricRunningStateChanged(isFingerprintDetectionRunning(),
|
cb.onBiometricRunningStateChanged(isFingerprintDetectionRunning(),
|
||||||
BiometricSourceType.FINGERPRINT);
|
FINGERPRINT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1032,7 +1038,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
new BiometricAuthenticated(true, isStrongBiometric));
|
new BiometricAuthenticated(true, isStrongBiometric));
|
||||||
// Update/refresh trust state only if user can skip bouncer
|
// Update/refresh trust state only if user can skip bouncer
|
||||||
if (getUserCanSkipBouncer(userId)) {
|
if (getUserCanSkipBouncer(userId)) {
|
||||||
mTrustManager.unlockedByBiometricForUser(userId, BiometricSourceType.FACE);
|
mTrustManager.unlockedByBiometricForUser(userId, FACE);
|
||||||
}
|
}
|
||||||
// Don't send cancel if authentication succeeds
|
// Don't send cancel if authentication succeeds
|
||||||
mFaceCancelSignal = null;
|
mFaceCancelSignal = null;
|
||||||
@@ -1043,7 +1049,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricAuthenticated(userId,
|
cb.onBiometricAuthenticated(userId,
|
||||||
BiometricSourceType.FACE,
|
FACE,
|
||||||
isStrongBiometric);
|
isStrongBiometric);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1065,7 +1071,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricAuthFailed(BiometricSourceType.FACE);
|
cb.onBiometricAuthFailed(FACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
handleFaceHelp(BIOMETRIC_HELP_FACE_NOT_RECOGNIZED,
|
handleFaceHelp(BIOMETRIC_HELP_FACE_NOT_RECOGNIZED,
|
||||||
@@ -1078,7 +1084,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricAcquired(BiometricSourceType.FACE, acquireInfo);
|
cb.onBiometricAcquired(FACE, acquireInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1113,7 +1119,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricHelp(msgId, helpString, BiometricSourceType.FACE);
|
cb.onBiometricHelp(msgId, helpString, FACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1181,12 +1187,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricError(msgId, errString,
|
cb.onBiometricError(msgId, errString,
|
||||||
BiometricSourceType.FACE);
|
FACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lockedOutStateChanged) {
|
if (lockedOutStateChanged) {
|
||||||
notifyLockedOutStateChanged(BiometricSourceType.FACE);
|
notifyLockedOutStateChanged(FACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1200,7 +1206,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
FACE_AUTH_TRIGGERED_FACE_LOCKOUT_RESET), getBiometricLockoutDelay());
|
FACE_AUTH_TRIGGERED_FACE_LOCKOUT_RESET), getBiometricLockoutDelay());
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
notifyLockedOutStateChanged(BiometricSourceType.FACE);
|
notifyLockedOutStateChanged(FACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1223,7 +1229,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
|
||||||
if (cb != null) {
|
if (cb != null) {
|
||||||
cb.onBiometricRunningStateChanged(isFaceDetectionRunning(),
|
cb.onBiometricRunningStateChanged(isFaceDetectionRunning(),
|
||||||
BiometricSourceType.FACE);
|
FACE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1364,7 +1370,39 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
|
public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
|
||||||
return mStrongAuthTracker.isUnlockingWithBiometricAllowed(isStrongBiometric);
|
// StrongAuthTracker#isUnlockingWithBiometricAllowed includes
|
||||||
|
// STRONG_AUTH_REQUIRED_AFTER_LOCKOUT which is the same as mFingerprintLockedOutPermanent;
|
||||||
|
// however the strong auth tracker does not include the temporary lockout
|
||||||
|
// mFingerprintLockedOut.
|
||||||
|
return mStrongAuthTracker.isUnlockingWithBiometricAllowed(isStrongBiometric)
|
||||||
|
&& !mFingerprintLockedOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isUnlockingWithFaceAllowed() {
|
||||||
|
return mStrongAuthTracker.isUnlockingWithBiometricAllowed(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether fingerprint is allowed ot be used for unlocking based on the strongAuthTracker
|
||||||
|
* and temporary lockout state (tracked by FingerprintManager via error codes).
|
||||||
|
*/
|
||||||
|
public boolean isUnlockingWithFingerprintAllowed() {
|
||||||
|
return isUnlockingWithBiometricAllowed(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the given biometric is allowed based on strongAuth & lockout states.
|
||||||
|
*/
|
||||||
|
public boolean isUnlockingWithBiometricAllowed(
|
||||||
|
@NonNull BiometricSourceType biometricSourceType) {
|
||||||
|
switch (biometricSourceType) {
|
||||||
|
case FINGERPRINT:
|
||||||
|
return isUnlockingWithFingerprintAllowed();
|
||||||
|
case FACE:
|
||||||
|
return isUnlockingWithFaceAllowed();
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isUserInLockdown(int userId) {
|
public boolean isUserInLockdown(int userId) {
|
||||||
@@ -1386,11 +1424,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
return isEncrypted || isLockDown;
|
return isEncrypted || isLockDown;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean userNeedsStrongAuth() {
|
|
||||||
return mStrongAuthTracker.getStrongAuthForUser(getCurrentUser())
|
|
||||||
!= LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean containsFlag(int haystack, int needle) {
|
private boolean containsFlag(int haystack, int needle) {
|
||||||
return (haystack & needle) != 0;
|
return (haystack & needle) != 0;
|
||||||
}
|
}
|
||||||
@@ -1560,12 +1593,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private final FingerprintManager.FingerprintDetectionCallback mFingerprintDetectionCallback
|
|
||||||
= (sensorId, userId, isStrongBiometric) -> {
|
|
||||||
// Trigger the fingerprint success path so the bouncer can be shown
|
|
||||||
handleFingerprintAuthenticated(userId, isStrongBiometric);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Propagates a pointer down event to keyguard.
|
* Propagates a pointer down event to keyguard.
|
||||||
*/
|
*/
|
||||||
@@ -2636,27 +2663,25 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
&& (!mKeyguardGoingAway || !mDeviceInteractive)
|
&& (!mKeyguardGoingAway || !mDeviceInteractive)
|
||||||
&& mIsPrimaryUser
|
&& mIsPrimaryUser
|
||||||
&& biometricEnabledForUser;
|
&& biometricEnabledForUser;
|
||||||
|
final boolean strongerAuthRequired = !isUnlockingWithFingerprintAllowed();
|
||||||
final boolean shouldListenBouncerState = !(mFingerprintLockedOut
|
final boolean isSideFps = isSfpsSupported() && isSfpsEnrolled();
|
||||||
&& mPrimaryBouncerIsOrWillBeShowing && mCredentialAttempted);
|
final boolean shouldListenBouncerState =
|
||||||
|
!strongerAuthRequired || !mPrimaryBouncerIsOrWillBeShowing;
|
||||||
final boolean isEncryptedOrLockdownForUser = isEncryptedOrLockdown(user);
|
|
||||||
|
|
||||||
final boolean shouldListenUdfpsState = !isUdfps
|
final boolean shouldListenUdfpsState = !isUdfps
|
||||||
|| (!userCanSkipBouncer
|
|| (!userCanSkipBouncer
|
||||||
&& !isEncryptedOrLockdownForUser
|
&& !strongerAuthRequired
|
||||||
&& userDoesNotHaveTrust);
|
&& userDoesNotHaveTrust);
|
||||||
|
|
||||||
boolean shouldListenSideFpsState = true;
|
boolean shouldListenSideFpsState = true;
|
||||||
if (isSfpsSupported() && isSfpsEnrolled()) {
|
if (isSideFps) {
|
||||||
shouldListenSideFpsState =
|
shouldListenSideFpsState =
|
||||||
mSfpsRequireScreenOnToAuthPrefEnabled ? isDeviceInteractive() : true;
|
mSfpsRequireScreenOnToAuthPrefEnabled ? isDeviceInteractive() : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
|
boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
|
||||||
&& shouldListenBouncerState && shouldListenUdfpsState && !isFingerprintLockedOut()
|
&& shouldListenBouncerState && shouldListenUdfpsState
|
||||||
&& shouldListenSideFpsState;
|
&& shouldListenSideFpsState;
|
||||||
|
|
||||||
maybeLogListenerModelData(
|
maybeLogListenerModelData(
|
||||||
new KeyguardFingerprintListenModel(
|
new KeyguardFingerprintListenModel(
|
||||||
System.currentTimeMillis(),
|
System.currentTimeMillis(),
|
||||||
@@ -2668,7 +2693,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
mCredentialAttempted,
|
mCredentialAttempted,
|
||||||
mDeviceInteractive,
|
mDeviceInteractive,
|
||||||
mIsDreaming,
|
mIsDreaming,
|
||||||
isEncryptedOrLockdownForUser,
|
|
||||||
fingerprintDisabledForUser,
|
fingerprintDisabledForUser,
|
||||||
mFingerprintLockedOut,
|
mFingerprintLockedOut,
|
||||||
mGoingToSleep,
|
mGoingToSleep,
|
||||||
@@ -2679,6 +2703,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
mIsPrimaryUser,
|
mIsPrimaryUser,
|
||||||
shouldListenSideFpsState,
|
shouldListenSideFpsState,
|
||||||
shouldListenForFingerprintAssistant,
|
shouldListenForFingerprintAssistant,
|
||||||
|
strongerAuthRequired,
|
||||||
mSwitchingUser,
|
mSwitchingUser,
|
||||||
isUdfps,
|
isUdfps,
|
||||||
userDoesNotHaveTrust));
|
userDoesNotHaveTrust));
|
||||||
@@ -2706,10 +2731,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
final boolean isEncryptedOrTimedOut =
|
final boolean isEncryptedOrTimedOut =
|
||||||
containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
|
containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
|
||||||
|| containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
|
|| containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
|
||||||
|
final boolean fpLockedOut = isFingerprintLockedOut();
|
||||||
// TODO: always disallow when fp is already locked out?
|
|
||||||
final boolean fpLockedOut = mFingerprintLockedOut || mFingerprintLockedOutPermanent;
|
|
||||||
|
|
||||||
final boolean canBypass = mKeyguardBypassController != null
|
final boolean canBypass = mKeyguardBypassController != null
|
||||||
&& mKeyguardBypassController.canBypass();
|
&& mKeyguardBypassController.canBypass();
|
||||||
// There's no reason to ask the HAL for authentication when the user can dismiss the
|
// There's no reason to ask the HAL for authentication when the user can dismiss the
|
||||||
@@ -2831,15 +2853,22 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
// Waiting for restart via handleFingerprintError().
|
// Waiting for restart via handleFingerprintError().
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mLogger.v("startListeningForFingerprint()");
|
|
||||||
|
|
||||||
if (unlockPossible) {
|
if (unlockPossible) {
|
||||||
mFingerprintCancelSignal = new CancellationSignal();
|
mFingerprintCancelSignal = new CancellationSignal();
|
||||||
|
|
||||||
if (isEncryptedOrLockdown(userId)) {
|
if (!isUnlockingWithFingerprintAllowed()) {
|
||||||
mFpm.detectFingerprint(mFingerprintCancelSignal, mFingerprintDetectionCallback,
|
mLogger.v("startListeningForFingerprint - detect");
|
||||||
|
mFpm.detectFingerprint(
|
||||||
|
mFingerprintCancelSignal,
|
||||||
|
(sensorId, user, isStrongBiometric) -> {
|
||||||
|
mLogger.d("fingerprint detected");
|
||||||
|
// Trigger the fingerprint success path so the bouncer can be shown
|
||||||
|
handleFingerprintAuthenticated(user, isStrongBiometric);
|
||||||
|
},
|
||||||
userId);
|
userId);
|
||||||
} else {
|
} else {
|
||||||
|
mLogger.v("startListeningForFingerprint - authenticate");
|
||||||
mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal,
|
mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal,
|
||||||
mFingerprintAuthenticationCallback, null /* handler */,
|
mFingerprintAuthenticationCallback, null /* handler */,
|
||||||
FingerprintManager.SENSOR_ID_ANY, userId, 0 /* flags */);
|
FingerprintManager.SENSOR_ID_ANY, userId, 0 /* flags */);
|
||||||
@@ -3056,11 +3085,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Immediately stop previous biometric listening states.
|
||||||
|
// Resetting lockout states updates the biometric listening states.
|
||||||
if (mFaceManager != null && !mFaceSensorProperties.isEmpty()) {
|
if (mFaceManager != null && !mFaceSensorProperties.isEmpty()) {
|
||||||
|
stopListeningForFace(FACE_AUTH_UPDATED_USER_SWITCHING);
|
||||||
handleFaceLockoutReset(mFaceManager.getLockoutModeForUser(
|
handleFaceLockoutReset(mFaceManager.getLockoutModeForUser(
|
||||||
mFaceSensorProperties.get(0).sensorId, userId));
|
mFaceSensorProperties.get(0).sensorId, userId));
|
||||||
}
|
}
|
||||||
if (mFpm != null && !mFingerprintSensorProperties.isEmpty()) {
|
if (mFpm != null && !mFingerprintSensorProperties.isEmpty()) {
|
||||||
|
stopListeningForFingerprint();
|
||||||
handleFingerprintLockoutReset(mFpm.getLockoutModeForUser(
|
handleFingerprintLockoutReset(mFpm.getLockoutModeForUser(
|
||||||
mFingerprintSensorProperties.get(0).sensorId, userId));
|
mFingerprintSensorProperties.get(0).sensorId, userId));
|
||||||
}
|
}
|
||||||
@@ -3467,7 +3500,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
@AnyThread
|
@AnyThread
|
||||||
public void setSwitchingUser(boolean switching) {
|
public void setSwitchingUser(boolean switching) {
|
||||||
mSwitchingUser = switching;
|
mSwitchingUser = switching;
|
||||||
// Since this comes in on a binder thread, we need to post if first
|
// Since this comes in on a binder thread, we need to post it first
|
||||||
mHandler.post(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE,
|
mHandler.post(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE,
|
||||||
FACE_AUTH_UPDATED_USER_SWITCHING));
|
FACE_AUTH_UPDATED_USER_SWITCHING));
|
||||||
}
|
}
|
||||||
@@ -3559,8 +3592,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
|||||||
Assert.isMainThread();
|
Assert.isMainThread();
|
||||||
mUserFingerprintAuthenticated.clear();
|
mUserFingerprintAuthenticated.clear();
|
||||||
mUserFaceAuthenticated.clear();
|
mUserFaceAuthenticated.clear();
|
||||||
mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FINGERPRINT, unlockedUser);
|
mTrustManager.clearAllBiometricRecognized(FINGERPRINT, unlockedUser);
|
||||||
mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FACE, unlockedUser);
|
mTrustManager.clearAllBiometricRecognized(FACE, unlockedUser);
|
||||||
mLogger.d("clearBiometricRecognized");
|
mLogger.d("clearBiometricRecognized");
|
||||||
|
|
||||||
for (int i = 0; i < mCallbacks.size(); i++) {
|
for (int i = 0; i < mCallbacks.size(); i++) {
|
||||||
|
|||||||
@@ -116,9 +116,9 @@ class AuthRippleController @Inject constructor(
|
|||||||
notificationShadeWindowController.setForcePluginOpen(false, this)
|
notificationShadeWindowController.setForcePluginOpen(false, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showUnlockRipple(biometricSourceType: BiometricSourceType?) {
|
fun showUnlockRipple(biometricSourceType: BiometricSourceType) {
|
||||||
if (!keyguardStateController.isShowing ||
|
if (!keyguardStateController.isShowing ||
|
||||||
keyguardUpdateMonitor.userNeedsStrongAuth()) {
|
!keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(biometricSourceType)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -246,7 +246,7 @@ class AuthRippleController @Inject constructor(
|
|||||||
object : KeyguardUpdateMonitorCallback() {
|
object : KeyguardUpdateMonitorCallback() {
|
||||||
override fun onBiometricAuthenticated(
|
override fun onBiometricAuthenticated(
|
||||||
userId: Int,
|
userId: Int,
|
||||||
biometricSourceType: BiometricSourceType?,
|
biometricSourceType: BiometricSourceType,
|
||||||
isStrongBiometric: Boolean
|
isStrongBiometric: Boolean
|
||||||
) {
|
) {
|
||||||
if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
|
if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
|
||||||
@@ -255,14 +255,14 @@ class AuthRippleController @Inject constructor(
|
|||||||
showUnlockRipple(biometricSourceType)
|
showUnlockRipple(biometricSourceType)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType?) {
|
override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType) {
|
||||||
if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
|
if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
|
||||||
mView.retractDwellRipple()
|
mView.retractDwellRipple()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBiometricAcquired(
|
override fun onBiometricAcquired(
|
||||||
biometricSourceType: BiometricSourceType?,
|
biometricSourceType: BiometricSourceType,
|
||||||
acquireInfo: Int
|
acquireInfo: Int
|
||||||
) {
|
) {
|
||||||
if (biometricSourceType == BiometricSourceType.FINGERPRINT &&
|
if (biometricSourceType == BiometricSourceType.FINGERPRINT &&
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.systemui.keyguard.domain.interactor
|
package com.android.systemui.keyguard.domain.interactor
|
||||||
|
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
|
import android.hardware.biometrics.BiometricSourceType
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.os.Trace
|
import android.os.Trace
|
||||||
import android.os.UserHandle
|
import android.os.UserHandle
|
||||||
@@ -71,7 +72,7 @@ constructor(
|
|||||||
KeyguardUpdateMonitor.getCurrentUser()
|
KeyguardUpdateMonitor.getCurrentUser()
|
||||||
) &&
|
) &&
|
||||||
!needsFullscreenBouncer() &&
|
!needsFullscreenBouncer() &&
|
||||||
!keyguardUpdateMonitor.userNeedsStrongAuth() &&
|
keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE) &&
|
||||||
!keyguardBypassController.bypassEnabled
|
!keyguardBypassController.bypassEnabled
|
||||||
|
|
||||||
/** Runnable to show the primary bouncer. */
|
/** Runnable to show the primary bouncer. */
|
||||||
|
|||||||
@@ -240,8 +240,8 @@ public class KeyguardBouncer {
|
|||||||
&& !mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
|
&& !mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
|
||||||
KeyguardUpdateMonitor.getCurrentUser())
|
KeyguardUpdateMonitor.getCurrentUser())
|
||||||
&& !needsFullscreenBouncer()
|
&& !needsFullscreenBouncer()
|
||||||
&& !mKeyguardUpdateMonitor.isFaceLockedOut()
|
&& mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
|
||||||
&& !mKeyguardUpdateMonitor.userNeedsStrongAuth()
|
BiometricSourceType.FACE)
|
||||||
&& !mKeyguardBypassController.getBypassEnabled()) {
|
&& !mKeyguardBypassController.getBypassEnabled()) {
|
||||||
mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY);
|
mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ private fun fingerprintModel(user: Int) = KeyguardFingerprintListenModel(
|
|||||||
credentialAttempted = false,
|
credentialAttempted = false,
|
||||||
deviceInteractive = false,
|
deviceInteractive = false,
|
||||||
dreaming = false,
|
dreaming = false,
|
||||||
encryptedOrLockdown = false,
|
|
||||||
fingerprintDisabled = false,
|
fingerprintDisabled = false,
|
||||||
fingerprintLockedOut = false,
|
fingerprintLockedOut = false,
|
||||||
goingToSleep = false,
|
goingToSleep = false,
|
||||||
@@ -74,6 +73,7 @@ private fun fingerprintModel(user: Int) = KeyguardFingerprintListenModel(
|
|||||||
primaryUser = false,
|
primaryUser = false,
|
||||||
shouldListenSfpsState = false,
|
shouldListenSfpsState = false,
|
||||||
shouldListenForFingerprintAssistant = false,
|
shouldListenForFingerprintAssistant = false,
|
||||||
|
strongerAuthRequired = false,
|
||||||
switchingUser = false,
|
switchingUser = false,
|
||||||
udfps = false,
|
udfps = false,
|
||||||
userDoesNotHaveTrust = false
|
userDoesNotHaveTrust = false
|
||||||
|
|||||||
@@ -379,9 +379,9 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onBouncerVisibilityChanged_needsStrongAuth_sideFpsHintHidden() {
|
public void onBouncerVisibilityChanged_unlockingWithFingerprintNotAllowed_sideFpsHintHidden() {
|
||||||
setupConditionsToEnableSideFpsHint();
|
setupConditionsToEnableSideFpsHint();
|
||||||
setNeedsStrongAuth(true);
|
setUnlockingWithFingerprintAllowed(false);
|
||||||
reset(mSideFpsController);
|
reset(mSideFpsController);
|
||||||
|
|
||||||
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
|
||||||
@@ -574,7 +574,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
attachView();
|
attachView();
|
||||||
setSideFpsHintEnabledFromResources(true);
|
setSideFpsHintEnabledFromResources(true);
|
||||||
setFingerprintDetectionRunning(true);
|
setFingerprintDetectionRunning(true);
|
||||||
setNeedsStrongAuth(false);
|
setUnlockingWithFingerprintAllowed(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void attachView() {
|
private void attachView() {
|
||||||
@@ -593,9 +593,8 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
|||||||
enabled);
|
enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setNeedsStrongAuth(boolean needed) {
|
private void setUnlockingWithFingerprintAllowed(boolean allowed) {
|
||||||
when(mKeyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(needed);
|
when(mKeyguardUpdateMonitor.isUnlockingWithFingerprintAllowed()).thenReturn(allowed);
|
||||||
mKeyguardUpdateMonitorCallback.getValue().onStrongAuthStateChanged(/* userId= */ 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupGetSecurityView() {
|
private void setupGetSecurityView() {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
|
|||||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
|
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
|
||||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
|
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
|
||||||
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
|
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
|
||||||
|
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
|
||||||
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
|
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
|
||||||
import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
|
import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
|
||||||
|
|
||||||
@@ -281,7 +282,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
componentInfo, FaceSensorProperties.TYPE_UNKNOWN,
|
componentInfo, FaceSensorProperties.TYPE_UNKNOWN,
|
||||||
false /* supportsFaceDetection */, true /* supportsSelfIllumination */,
|
false /* supportsFaceDetection */, true /* supportsSelfIllumination */,
|
||||||
false /* resetLockoutRequiresChallenge */));
|
false /* resetLockoutRequiresChallenge */));
|
||||||
|
|
||||||
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
|
||||||
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
|
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
|
||||||
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(List.of(
|
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(List.of(
|
||||||
@@ -594,30 +594,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFingerprintDoesNotAuth_whenEncrypted() {
|
public void testOnlyDetectFingerprint_whenFingerprintUnlockNotAllowed() {
|
||||||
testFingerprintWhenStrongAuth(
|
|
||||||
STRONG_AUTH_REQUIRED_AFTER_BOOT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFingerprintDoesNotAuth_whenDpmLocked() {
|
|
||||||
testFingerprintWhenStrongAuth(
|
|
||||||
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testFingerprintDoesNotAuth_whenUserLockdown() {
|
|
||||||
testFingerprintWhenStrongAuth(
|
|
||||||
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void testFingerprintWhenStrongAuth(int strongAuth) {
|
|
||||||
// Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
|
// Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
|
||||||
// will trigger updateBiometricListeningState();
|
// will trigger updateBiometricListeningState();
|
||||||
clearInvocations(mFingerprintManager);
|
clearInvocations(mFingerprintManager);
|
||||||
mKeyguardUpdateMonitor.resetBiometricListeningState();
|
mKeyguardUpdateMonitor.resetBiometricListeningState();
|
||||||
|
|
||||||
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(strongAuth);
|
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
|
||||||
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
|
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
|
||||||
mTestableLooper.processAllMessages();
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
@@ -928,10 +911,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
faceLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
|
faceLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
|
||||||
final boolean fpLocked =
|
final boolean fpLocked =
|
||||||
fingerprintLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
|
fingerprintLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
|
||||||
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser)))
|
|
||||||
.thenReturn(fingerprintLockoutMode);
|
|
||||||
when(mFaceManager.getLockoutModeForUser(eq(FACE_SENSOR_ID), eq(newUser)))
|
|
||||||
.thenReturn(faceLockoutMode);
|
|
||||||
|
|
||||||
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
|
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
|
||||||
mTestableLooper.processAllMessages();
|
mTestableLooper.processAllMessages();
|
||||||
@@ -940,7 +919,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
|
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
|
||||||
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
|
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
|
||||||
anyInt());
|
anyInt());
|
||||||
|
// resetFaceManager();
|
||||||
|
// resetFingerprintManager();
|
||||||
|
|
||||||
|
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser)))
|
||||||
|
.thenReturn(fingerprintLockoutMode);
|
||||||
|
when(mFaceManager.getLockoutModeForUser(eq(FACE_SENSOR_ID), eq(newUser)))
|
||||||
|
.thenReturn(faceLockoutMode);
|
||||||
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
|
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
|
||||||
final CancellationSignal fpCancel = spy(mKeyguardUpdateMonitor.mFingerprintCancelSignal);
|
final CancellationSignal fpCancel = spy(mKeyguardUpdateMonitor.mFingerprintCancelSignal);
|
||||||
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
|
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
|
||||||
@@ -951,14 +936,22 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
mKeyguardUpdateMonitor.handleUserSwitchComplete(newUser);
|
mKeyguardUpdateMonitor.handleUserSwitchComplete(newUser);
|
||||||
mTestableLooper.processAllMessages();
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
verify(faceCancel, faceLocked ? times(1) : never()).cancel();
|
// THEN face and fingerprint listening are always cancelled immediately
|
||||||
verify(fpCancel, fpLocked ? times(1) : never()).cancel();
|
verify(faceCancel).cancel();
|
||||||
verify(callback, faceLocked ? times(1) : never()).onBiometricRunningStateChanged(
|
verify(callback).onBiometricRunningStateChanged(
|
||||||
eq(false), eq(BiometricSourceType.FACE));
|
eq(false), eq(BiometricSourceType.FACE));
|
||||||
verify(callback, fpLocked ? times(1) : never()).onBiometricRunningStateChanged(
|
verify(fpCancel).cancel();
|
||||||
|
verify(callback).onBiometricRunningStateChanged(
|
||||||
eq(false), eq(BiometricSourceType.FINGERPRINT));
|
eq(false), eq(BiometricSourceType.FINGERPRINT));
|
||||||
|
|
||||||
|
// THEN locked out states are updated
|
||||||
assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked);
|
assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked);
|
||||||
assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked);
|
assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked);
|
||||||
|
|
||||||
|
// Fingerprint should be restarted once its cancelled bc on lockout, the device
|
||||||
|
// can still detectFingerprint (and if it's not locked out, fingerprint can listen)
|
||||||
|
assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
|
||||||
|
.isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1144,9 +1137,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
// GIVEN status bar state is on the keyguard
|
// GIVEN status bar state is on the keyguard
|
||||||
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
|
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
|
||||||
|
|
||||||
// WHEN user hasn't authenticated since last boot
|
// WHEN user hasn't authenticated since last boot, cannot unlock with FP
|
||||||
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
|
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
|
||||||
.thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT);
|
|
||||||
|
|
||||||
// THEN we shouldn't listen for udfps
|
// THEN we shouldn't listen for udfps
|
||||||
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
|
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
|
||||||
@@ -1258,8 +1250,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
|||||||
when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
|
when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
|
||||||
|
|
||||||
// WHEN device in lock down
|
// WHEN device in lock down
|
||||||
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
|
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
|
||||||
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
|
|
||||||
|
|
||||||
// THEN we shouldn't listen for udfps
|
// THEN we shouldn't listen for udfps
|
||||||
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
|
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController
|
|||||||
import com.android.systemui.statusbar.policy.ConfigurationController
|
import com.android.systemui.statusbar.policy.ConfigurationController
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||||
import com.android.systemui.util.leak.RotationUtils
|
import com.android.systemui.util.leak.RotationUtils
|
||||||
import javax.inject.Provider
|
import com.android.systemui.util.mockito.any
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.assertFalse
|
import org.junit.Assert.assertFalse
|
||||||
import org.junit.Assert.assertTrue
|
import org.junit.Assert.assertTrue
|
||||||
@@ -46,15 +46,16 @@ import org.junit.Test
|
|||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.ArgumentCaptor
|
import org.mockito.ArgumentCaptor
|
||||||
import org.mockito.ArgumentMatchers
|
import org.mockito.ArgumentMatchers
|
||||||
|
import org.mockito.ArgumentMatchers.eq
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.any
|
import org.mockito.Mockito.`when`
|
||||||
import org.mockito.Mockito.never
|
import org.mockito.Mockito.never
|
||||||
import org.mockito.Mockito.reset
|
import org.mockito.Mockito.reset
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
import org.mockito.Mockito.`when`
|
|
||||||
import org.mockito.MockitoAnnotations
|
import org.mockito.MockitoAnnotations
|
||||||
import org.mockito.MockitoSession
|
import org.mockito.MockitoSession
|
||||||
import org.mockito.quality.Strictness
|
import org.mockito.quality.Strictness
|
||||||
|
import javax.inject.Provider
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@@ -118,12 +119,13 @@ class AuthRippleControllerTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFingerprintTrigger_KeyguardShowing_Ripple() {
|
fun testFingerprintTrigger_KeyguardShowing_Ripple() {
|
||||||
// GIVEN fp exists, keyguard is showing, user doesn't need strong auth
|
// GIVEN fp exists, keyguard is showing, unlocking with fp allowed
|
||||||
val fpsLocation = Point(5, 5)
|
val fpsLocation = Point(5, 5)
|
||||||
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
|
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
|
||||||
controller.onViewAttached()
|
controller.onViewAttached()
|
||||||
`when`(keyguardStateController.isShowing).thenReturn(true)
|
`when`(keyguardStateController.isShowing).thenReturn(true)
|
||||||
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
|
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
|
||||||
|
eq(BiometricSourceType.FINGERPRINT))).thenReturn(true)
|
||||||
|
|
||||||
// WHEN fingerprint authenticated
|
// WHEN fingerprint authenticated
|
||||||
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
|
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
|
||||||
@@ -140,11 +142,12 @@ class AuthRippleControllerTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFingerprintTrigger_KeyguardNotShowing_NoRipple() {
|
fun testFingerprintTrigger_KeyguardNotShowing_NoRipple() {
|
||||||
// GIVEN fp exists & user doesn't need strong auth
|
// GIVEN fp exists & unlocking with fp allowed
|
||||||
val fpsLocation = Point(5, 5)
|
val fpsLocation = Point(5, 5)
|
||||||
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
|
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
|
||||||
controller.onViewAttached()
|
controller.onViewAttached()
|
||||||
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
|
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
|
||||||
|
eq(BiometricSourceType.FINGERPRINT))).thenReturn(true)
|
||||||
|
|
||||||
// WHEN keyguard is NOT showing & fingerprint authenticated
|
// WHEN keyguard is NOT showing & fingerprint authenticated
|
||||||
`when`(keyguardStateController.isShowing).thenReturn(false)
|
`when`(keyguardStateController.isShowing).thenReturn(false)
|
||||||
@@ -160,15 +163,16 @@ class AuthRippleControllerTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFingerprintTrigger_StrongAuthRequired_NoRipple() {
|
fun testFingerprintTrigger_biometricUnlockNotAllowed_NoRipple() {
|
||||||
// GIVEN fp exists & keyguard is showing
|
// GIVEN fp exists & keyguard is showing
|
||||||
val fpsLocation = Point(5, 5)
|
val fpsLocation = Point(5, 5)
|
||||||
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
|
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
|
||||||
controller.onViewAttached()
|
controller.onViewAttached()
|
||||||
`when`(keyguardStateController.isShowing).thenReturn(true)
|
`when`(keyguardStateController.isShowing).thenReturn(true)
|
||||||
|
|
||||||
// WHEN user needs strong auth & fingerprint authenticated
|
// WHEN unlocking with fingerprint is NOT allowed & fingerprint authenticated
|
||||||
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(true)
|
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
|
||||||
|
eq(BiometricSourceType.FINGERPRINT))).thenReturn(false)
|
||||||
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
|
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
|
||||||
verify(keyguardUpdateMonitor).registerCallback(captor.capture())
|
verify(keyguardUpdateMonitor).registerCallback(captor.capture())
|
||||||
captor.value.onBiometricAuthenticated(
|
captor.value.onBiometricAuthenticated(
|
||||||
@@ -182,13 +186,14 @@ class AuthRippleControllerTest : SysuiTestCase() {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testFaceTriggerBypassEnabled_Ripple() {
|
fun testFaceTriggerBypassEnabled_Ripple() {
|
||||||
// GIVEN face auth sensor exists, keyguard is showing & strong auth isn't required
|
// GIVEN face auth sensor exists, keyguard is showing & unlocking with face is allowed
|
||||||
val faceLocation = Point(5, 5)
|
val faceLocation = Point(5, 5)
|
||||||
`when`(authController.faceSensorLocation).thenReturn(faceLocation)
|
`when`(authController.faceSensorLocation).thenReturn(faceLocation)
|
||||||
controller.onViewAttached()
|
controller.onViewAttached()
|
||||||
|
|
||||||
`when`(keyguardStateController.isShowing).thenReturn(true)
|
`when`(keyguardStateController.isShowing).thenReturn(true)
|
||||||
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
|
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
|
||||||
|
BiometricSourceType.FACE)).thenReturn(true)
|
||||||
|
|
||||||
// WHEN bypass is enabled & face authenticated
|
// WHEN bypass is enabled & face authenticated
|
||||||
`when`(bypassController.canBypass()).thenReturn(true)
|
`when`(bypassController.canBypass()).thenReturn(true)
|
||||||
@@ -275,6 +280,8 @@ class AuthRippleControllerTest : SysuiTestCase() {
|
|||||||
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
|
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
|
||||||
controller.onViewAttached()
|
controller.onViewAttached()
|
||||||
`when`(keyguardStateController.isShowing).thenReturn(true)
|
`when`(keyguardStateController.isShowing).thenReturn(true)
|
||||||
|
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
|
||||||
|
BiometricSourceType.FINGERPRINT)).thenReturn(true)
|
||||||
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
|
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
|
||||||
|
|
||||||
controller.showUnlockRipple(BiometricSourceType.FINGERPRINT)
|
controller.showUnlockRipple(BiometricSourceType.FINGERPRINT)
|
||||||
@@ -295,6 +302,8 @@ class AuthRippleControllerTest : SysuiTestCase() {
|
|||||||
`when`(keyguardStateController.isShowing).thenReturn(true)
|
`when`(keyguardStateController.isShowing).thenReturn(true)
|
||||||
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
|
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
|
||||||
`when`(authController.isUdfpsFingerDown).thenReturn(true)
|
`when`(authController.isUdfpsFingerDown).thenReturn(true)
|
||||||
|
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
|
||||||
|
eq(BiometricSourceType.FACE))).thenReturn(true)
|
||||||
|
|
||||||
controller.showUnlockRipple(BiometricSourceType.FACE)
|
controller.showUnlockRipple(BiometricSourceType.FACE)
|
||||||
assertTrue("reveal didn't start on keyguardFadingAway",
|
assertTrue("reveal didn't start on keyguardFadingAway",
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.content.res.ColorStateList;
|
import android.content.res.ColorStateList;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
|
import android.hardware.biometrics.BiometricSourceType;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
@@ -398,6 +399,8 @@ public class KeyguardBouncerTest extends SysuiTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testShow_delaysIfFaceAuthIsRunning() {
|
public void testShow_delaysIfFaceAuthIsRunning() {
|
||||||
|
when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE))
|
||||||
|
.thenReturn(true);
|
||||||
when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true);
|
when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true);
|
||||||
mBouncer.show(true /* reset */);
|
mBouncer.show(true /* reset */);
|
||||||
|
|
||||||
@@ -410,9 +413,10 @@ public class KeyguardBouncerTest extends SysuiTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testShow_doesNotDelaysIfFaceAuthIsLockedOut() {
|
public void testShow_doesNotDelaysIfFaceAuthIsNotAllowed() {
|
||||||
when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true);
|
when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true);
|
||||||
when(mKeyguardUpdateMonitor.isFaceLockedOut()).thenReturn(true);
|
when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE))
|
||||||
|
.thenReturn(false);
|
||||||
mBouncer.show(true /* reset */);
|
mBouncer.show(true /* reset */);
|
||||||
|
|
||||||
verify(mHandler, never()).postDelayed(any(), anyLong());
|
verify(mHandler, never()).postDelayed(any(), anyLong());
|
||||||
|
|||||||
Reference in New Issue
Block a user