Merge "On strongAuthChanges, update fp & face states" into tm-qpr-dev

This commit is contained in:
TreeHugger Robot
2022-12-05 14:54:07 +00:00
committed by Android (Google) Code Review
5 changed files with 274 additions and 140 deletions

View File

@@ -48,11 +48,13 @@ import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_INIT
import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_OCCLUSION_CHANGED import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_OCCLUSION_CHANGED
import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_RESET import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_RESET
import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_VISIBILITY_CHANGED import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_VISIBILITY_CHANGED
import com.android.keyguard.InternalFaceAuthReasons.NON_STRONG_BIOMETRIC_ALLOWED_CHANGED
import com.android.keyguard.InternalFaceAuthReasons.OCCLUDING_APP_REQUESTED import com.android.keyguard.InternalFaceAuthReasons.OCCLUDING_APP_REQUESTED
import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN
import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN
import com.android.keyguard.InternalFaceAuthReasons.RETRY_AFTER_HW_UNAVAILABLE import com.android.keyguard.InternalFaceAuthReasons.RETRY_AFTER_HW_UNAVAILABLE
import com.android.keyguard.InternalFaceAuthReasons.STARTED_WAKING_UP import com.android.keyguard.InternalFaceAuthReasons.STARTED_WAKING_UP
import com.android.keyguard.InternalFaceAuthReasons.STRONG_AUTH_ALLOWED_CHANGED
import com.android.keyguard.InternalFaceAuthReasons.TRUST_DISABLED import com.android.keyguard.InternalFaceAuthReasons.TRUST_DISABLED
import com.android.keyguard.InternalFaceAuthReasons.TRUST_ENABLED import com.android.keyguard.InternalFaceAuthReasons.TRUST_ENABLED
import com.android.keyguard.InternalFaceAuthReasons.USER_SWITCHING import com.android.keyguard.InternalFaceAuthReasons.USER_SWITCHING
@@ -121,6 +123,9 @@ private object InternalFaceAuthReasons {
const val FACE_AUTHENTICATED = "Face auth started/stopped because face is authenticated" const val FACE_AUTHENTICATED = "Face auth started/stopped because face is authenticated"
const val BIOMETRIC_ENABLED = const val BIOMETRIC_ENABLED =
"Face auth started/stopped because biometric is enabled on keyguard" "Face auth started/stopped because biometric is enabled on keyguard"
const val STRONG_AUTH_ALLOWED_CHANGED = "Face auth stopped because strong auth allowed changed"
const val NON_STRONG_BIOMETRIC_ALLOWED_CHANGED =
"Face auth stopped because non strong biometric allowed changed"
} }
/** /**
@@ -204,7 +209,11 @@ constructor(private val id: Int, val reason: String, var extraInfo: Int = 0) :
@UiEvent(doc = FACE_AUTHENTICATED) @UiEvent(doc = FACE_AUTHENTICATED)
FACE_AUTH_UPDATED_ON_FACE_AUTHENTICATED(1187, FACE_AUTHENTICATED), FACE_AUTH_UPDATED_ON_FACE_AUTHENTICATED(1187, FACE_AUTHENTICATED),
@UiEvent(doc = BIOMETRIC_ENABLED) @UiEvent(doc = BIOMETRIC_ENABLED)
FACE_AUTH_UPDATED_BIOMETRIC_ENABLED_ON_KEYGUARD(1188, BIOMETRIC_ENABLED); FACE_AUTH_UPDATED_BIOMETRIC_ENABLED_ON_KEYGUARD(1188, BIOMETRIC_ENABLED),
@UiEvent(doc = STRONG_AUTH_ALLOWED_CHANGED)
FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED(1255, STRONG_AUTH_ALLOWED_CHANGED),
@UiEvent(doc = NON_STRONG_BIOMETRIC_ALLOWED_CHANGED)
FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED(1256, NON_STRONG_BIOMETRIC_ALLOWED_CHANGED);
override fun getId(): Int = this.id override fun getId(): Int = this.id

View File

@@ -53,17 +53,17 @@ data class KeyguardFaceListenModel(
val biometricSettingEnabledForUser: Boolean, val biometricSettingEnabledForUser: Boolean,
val bouncerFullyShown: Boolean, val bouncerFullyShown: Boolean,
val faceAndFpNotAuthenticated: Boolean, val faceAndFpNotAuthenticated: Boolean,
val faceAuthAllowed: Boolean,
val faceDisabled: Boolean, val faceDisabled: Boolean,
val faceLockedOut: Boolean, val faceLockedOut: Boolean,
val fpLockedOut: Boolean,
val goingToSleep: Boolean, val goingToSleep: Boolean,
val keyguardAwake: Boolean, val keyguardAwake: Boolean,
val keyguardGoingAway: Boolean, val keyguardGoingAway: Boolean,
val listeningForFaceAssistant: Boolean, val listeningForFaceAssistant: Boolean,
val occludingAppRequestingFaceAuth: Boolean, val occludingAppRequestingFaceAuth: Boolean,
val primaryUser: Boolean, val primaryUser: Boolean,
val scanningAllowedByStrongAuth: Boolean,
val secureCameraLaunched: Boolean, val secureCameraLaunched: Boolean,
val supportsDetect: Boolean,
val switchingUser: Boolean, val switchingUser: Boolean,
val udfpsBouncerShowing: Boolean, val udfpsBouncerShowing: Boolean,
val udfpsFingerDown: Boolean, val udfpsFingerDown: Boolean,
@@ -79,9 +79,8 @@ data class KeyguardActiveUnlockModel(
// keep sorted // keep sorted
val awakeKeyguard: Boolean, val awakeKeyguard: Boolean,
val authInterruptActive: Boolean, val authInterruptActive: Boolean,
val encryptedOrTimedOut: Boolean, val fpLockedOut: Boolean,
val fpLockout: Boolean, val primaryAuthRequired: Boolean,
val lockDown: Boolean,
val switchingUser: Boolean, val switchingUser: Boolean,
val triggerActiveUnlockForAssistant: Boolean, val triggerActiveUnlockForAssistant: Boolean,
val userCanDismissLockScreen: Boolean val userCanDismissLockScreen: Boolean

View File

@@ -34,9 +34,9 @@ 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;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.keyguard.FaceAuthReasonKt.apiRequestReasonToUiEvent; import static com.android.keyguard.FaceAuthReasonKt.apiRequestReasonToUiEvent;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_DREAM_STARTED; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_DREAM_STARTED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_FACE_CANCEL_NOT_RECEIVED; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_FACE_CANCEL_NOT_RECEIVED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_FINISHED_GOING_TO_SLEEP; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_FINISHED_GOING_TO_SLEEP;
@@ -65,6 +65,7 @@ import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_ON_FACE_AUT
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_ON_KEYGUARD_INIT; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_ON_KEYGUARD_INIT;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED;
import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING;
import static com.android.systemui.DejankUtils.whitelistIpcs; import static com.android.systemui.DejankUtils.whitelistIpcs;
@@ -171,7 +172,6 @@ import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.function.Consumer;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.inject.Inject; import javax.inject.Inject;
@@ -1421,6 +1421,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
} }
} }
/**
* Whether the user locked down the device. This doesn't include device policy manager lockdown.
*/
public boolean isUserInLockdown(int userId) { public boolean isUserInLockdown(int userId) {
return containsFlag(mStrongAuthTracker.getStrongAuthForUser(userId), return containsFlag(mStrongAuthTracker.getStrongAuthForUser(userId),
STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
@@ -1452,7 +1455,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return mStrongAuthTracker; return mStrongAuthTracker;
} }
private void notifyStrongAuthStateChanged(int userId) { @VisibleForTesting
void notifyStrongAuthAllowedChanged(int userId) {
Assert.isMainThread(); Assert.isMainThread();
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();
@@ -1460,6 +1464,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
cb.onStrongAuthStateChanged(userId); cb.onStrongAuthStateChanged(userId);
} }
} }
if (userId == getCurrentUser()) {
FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED.setExtraInfo(
mStrongAuthTracker.getStrongAuthForUser(getCurrentUser()));
// Strong auth is only reset when primary auth is used to enter the device,
// so we only check whether to stop biometric listening states here
updateBiometricListeningState(
BIOMETRIC_ACTION_STOP, FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED);
}
} }
private void notifyLockedOutStateChanged(BiometricSourceType type) { private void notifyLockedOutStateChanged(BiometricSourceType type) {
@@ -1471,8 +1484,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
} }
} }
} }
@VisibleForTesting
private void notifyNonStrongBiometricStateChanged(int userId) { void notifyNonStrongBiometricAllowedChanged(int userId) {
Assert.isMainThread(); Assert.isMainThread();
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();
@@ -1480,6 +1493,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
cb.onNonStrongBiometricAllowedChanged(userId); cb.onNonStrongBiometricAllowedChanged(userId);
} }
} }
if (userId == getCurrentUser()) {
FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED.setExtraInfo(
mStrongAuthTracker.isNonStrongBiometricAllowedAfterIdleTimeout(
getCurrentUser()) ? -1 : 1);
// This is only reset when primary auth is used to enter the device, so we only check
// whether to stop biometric listening states here
updateBiometricListeningState(BIOMETRIC_ACTION_STOP,
FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED);
}
} }
private void dispatchErrorMessage(CharSequence message) { private void dispatchErrorMessage(CharSequence message) {
@@ -1825,16 +1848,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
} }
} }
public static class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker { /**
private final Consumer<Integer> mStrongAuthRequiredChangedCallback; * Updates callbacks when strong auth requirements change.
private final Consumer<Integer> mNonStrongBiometricAllowedChanged; */
public class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
public StrongAuthTracker(Context context, public StrongAuthTracker(Context context) {
Consumer<Integer> strongAuthRequiredChangedCallback,
Consumer<Integer> nonStrongBiometricAllowedChanged) {
super(context); super(context);
mStrongAuthRequiredChangedCallback = strongAuthRequiredChangedCallback;
mNonStrongBiometricAllowedChanged = nonStrongBiometricAllowedChanged;
} }
public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) { public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
@@ -1850,7 +1869,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@Override @Override
public void onStrongAuthRequiredChanged(int userId) { public void onStrongAuthRequiredChanged(int userId) {
mStrongAuthRequiredChangedCallback.accept(userId); notifyStrongAuthAllowedChanged(userId);
} }
// TODO(b/247091681): Renaming the inappropriate onIsNonStrongBiometricAllowedChanged // TODO(b/247091681): Renaming the inappropriate onIsNonStrongBiometricAllowedChanged
@@ -1858,7 +1877,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// Strong-Auth // Strong-Auth
@Override @Override
public void onIsNonStrongBiometricAllowedChanged(int userId) { public void onIsNonStrongBiometricAllowedChanged(int userId) {
mNonStrongBiometricAllowedChanged.accept(userId); notifyNonStrongBiometricAllowedChanged(userId);
} }
} }
@@ -2019,8 +2038,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mUserTracker = userTracker; mUserTracker = userTracker;
mTelephonyListenerManager = telephonyListenerManager; mTelephonyListenerManager = telephonyListenerManager;
mDeviceProvisioned = isDeviceProvisionedInSettingsDb(); mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged, mStrongAuthTracker = new StrongAuthTracker(context);
this::notifyNonStrongBiometricStateChanged);
mBackgroundExecutor = backgroundExecutor; mBackgroundExecutor = backgroundExecutor;
mBroadcastDispatcher = broadcastDispatcher; mBroadcastDispatcher = broadcastDispatcher;
mInteractionJankMonitor = interactionJankMonitor; mInteractionJankMonitor = interactionJankMonitor;
@@ -2594,24 +2612,17 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|| !mLockPatternUtils.isSecure(user); || !mLockPatternUtils.isSecure(user);
// Don't trigger active unlock if fp is locked out // Don't trigger active unlock if fp is locked out
final boolean fpLockedout = mFingerprintLockedOut || mFingerprintLockedOutPermanent; final boolean fpLockedOut = mFingerprintLockedOut || mFingerprintLockedOutPermanent;
// Don't trigger active unlock if primary auth is required // Don't trigger active unlock if primary auth is required
final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user); final boolean primaryAuthRequired = !isUnlockingWithBiometricAllowed(true);
final boolean isLockDown =
containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
|| containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
final boolean isEncryptedOrTimedOut =
containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
|| containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
final boolean shouldTriggerActiveUnlock = final boolean shouldTriggerActiveUnlock =
(mAuthInterruptActive || triggerActiveUnlockForAssistant || awakeKeyguard) (mAuthInterruptActive || triggerActiveUnlockForAssistant || awakeKeyguard)
&& !mSwitchingUser && !mSwitchingUser
&& !userCanDismissLockScreen && !userCanDismissLockScreen
&& !fpLockedout && !fpLockedOut
&& !isLockDown && !primaryAuthRequired
&& !isEncryptedOrTimedOut
&& !mKeyguardGoingAway && !mKeyguardGoingAway
&& !mSecureCameraLaunched; && !mSecureCameraLaunched;
@@ -2623,9 +2634,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
shouldTriggerActiveUnlock, shouldTriggerActiveUnlock,
awakeKeyguard, awakeKeyguard,
mAuthInterruptActive, mAuthInterruptActive,
isEncryptedOrTimedOut, fpLockedOut,
fpLockedout, primaryAuthRequired,
isLockDown,
mSwitchingUser, mSwitchingUser,
triggerActiveUnlockForAssistant, triggerActiveUnlockForAssistant,
userCanDismissLockScreen)); userCanDismissLockScreen));
@@ -2677,7 +2687,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
&& !fingerprintDisabledForUser && !fingerprintDisabledForUser
&& (!mKeyguardGoingAway || !mDeviceInteractive) && (!mKeyguardGoingAway || !mDeviceInteractive)
&& mIsPrimaryUser && mIsPrimaryUser
&& biometricEnabledForUser; && biometricEnabledForUser
&& !isUserInLockdown(user);
final boolean strongerAuthRequired = !isUnlockingWithFingerprintAllowed(); final boolean strongerAuthRequired = !isUnlockingWithFingerprintAllowed();
final boolean isSideFps = isSfpsSupported() && isSfpsEnrolled(); final boolean isSideFps = isSfpsSupported() && isSfpsEnrolled();
final boolean shouldListenBouncerState = final boolean shouldListenBouncerState =
@@ -2739,14 +2750,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final boolean awakeKeyguard = isKeyguardVisible() && mDeviceInteractive final boolean awakeKeyguard = isKeyguardVisible() && mDeviceInteractive
&& !statusBarShadeLocked; && !statusBarShadeLocked;
final int user = getCurrentUser(); final int user = getCurrentUser();
final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user); final boolean faceAuthAllowed = isUnlockingWithBiometricAllowed(FACE);
final boolean isLockDown =
containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW)
|| containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
final boolean isEncryptedOrTimedOut =
containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
|| containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
final boolean fpLockedOut = isFingerprintLockedOut();
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
@@ -2754,20 +2758,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// the lock screen even when TrustAgents are keeping the device unlocked. // the lock screen even when TrustAgents are keeping the device unlocked.
final boolean userNotTrustedOrDetectionIsNeeded = !getUserHasTrust(user) || canBypass; final boolean userNotTrustedOrDetectionIsNeeded = !getUserHasTrust(user) || canBypass;
// Scan even when encrypted or timeout to show a preemptive bouncer when bypassing. // If the device supports face detection (without authentication), if bypass is enabled,
// Lock-down mode shouldn't scan, since it is more explicit. // allow face detection to happen even if stronger auth is required. When face is detected,
boolean strongAuthAllowsScanning = (!isEncryptedOrTimedOut || canBypass // we show the bouncer. However, if the user manually locked down the device themselves,
&& !mPrimaryBouncerFullyShown); // never attempt to detect face.
final boolean supportsDetect = !mFaceSensorProperties.isEmpty()
// If the device supports face detection (without authentication) and bypass is enabled, && mFaceSensorProperties.get(0).supportsFaceDetection
// allow face scanning to happen if the device is in lockdown mode. && canBypass && !mPrimaryBouncerIsOrWillBeShowing
// Otherwise, prevent scanning. && !isUserInLockdown(user);
final boolean supportsDetectOnly = !mFaceSensorProperties.isEmpty() final boolean faceAuthAllowedOrDetectionIsNeeded = faceAuthAllowed || supportsDetect;
&& canBypass
&& mFaceSensorProperties.get(0).supportsFaceDetection;
if (isLockDown && !supportsDetectOnly) {
strongAuthAllowsScanning = false;
}
// If the face or fp has recently been authenticated do not attempt to authenticate again. // If the face or fp has recently been authenticated do not attempt to authenticate again.
final boolean faceAndFpNotAuthenticated = !getUserUnlockedWithBiometric(user); final boolean faceAndFpNotAuthenticated = !getUserUnlockedWithBiometric(user);
@@ -2788,14 +2787,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|| mUdfpsBouncerShowing) || mUdfpsBouncerShowing)
&& !mSwitchingUser && !faceDisabledForUser && userNotTrustedOrDetectionIsNeeded && !mSwitchingUser && !faceDisabledForUser && userNotTrustedOrDetectionIsNeeded
&& !mKeyguardGoingAway && biometricEnabledForUser && !mKeyguardGoingAway && biometricEnabledForUser
&& strongAuthAllowsScanning && mIsPrimaryUser && faceAuthAllowedOrDetectionIsNeeded && mIsPrimaryUser
&& (!mSecureCameraLaunched || mOccludingAppRequestingFace) && (!mSecureCameraLaunched || mOccludingAppRequestingFace)
&& faceAndFpNotAuthenticated && faceAndFpNotAuthenticated
&& !mGoingToSleep && !mGoingToSleep;
// We only care about fp locked out state and not face because we still trigger
// face auth even when face is locked out to show the user a message that face
// unlock was supposed to run but didn't
&& !fpLockedOut;
// Aggregate relevant fields for debug logging. // Aggregate relevant fields for debug logging.
maybeLogListenerModelData( maybeLogListenerModelData(
@@ -2805,19 +2800,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
shouldListen, shouldListen,
mAuthInterruptActive, mAuthInterruptActive,
biometricEnabledForUser, biometricEnabledForUser,
mPrimaryBouncerFullyShown, mPrimaryBouncerFullyShown,
faceAndFpNotAuthenticated, faceAndFpNotAuthenticated,
faceAuthAllowed,
faceDisabledForUser, faceDisabledForUser,
isFaceLockedOut(), isFaceLockedOut(),
fpLockedOut,
mGoingToSleep, mGoingToSleep,
awakeKeyguard, awakeKeyguard,
mKeyguardGoingAway, mKeyguardGoingAway,
shouldListenForFaceAssistant, shouldListenForFaceAssistant,
mOccludingAppRequestingFace, mOccludingAppRequestingFace,
mIsPrimaryUser, mIsPrimaryUser,
strongAuthAllowsScanning,
mSecureCameraLaunched, mSecureCameraLaunched,
supportsDetect,
mSwitchingUser, mSwitchingUser,
mUdfpsBouncerShowing, mUdfpsBouncerShowing,
isUdfpsFingerDown, isUdfpsFingerDown,
@@ -2921,9 +2916,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// This would need to be updated for multi-sensor devices // This would need to be updated for multi-sensor devices
final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty() final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty()
&& mFaceSensorProperties.get(0).supportsFaceDetection; && mFaceSensorProperties.get(0).supportsFaceDetection;
if (isEncryptedOrLockdown(userId) && supportsFaceDetection) { if (!isUnlockingWithBiometricAllowed(FACE) && supportsFaceDetection) {
mLogger.v("startListeningForFace - detect");
mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId); mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
} else { } else {
mLogger.v("startListeningForFace - authenticate");
final boolean isBypassEnabled = mKeyguardBypassController != null final boolean isBypassEnabled = mKeyguardBypassController != null
&& mKeyguardBypassController.isBypassEnabled(); && mKeyguardBypassController.isBypassEnabled();
mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal, mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal,

View File

@@ -87,17 +87,17 @@ private fun faceModel(user: Int) = KeyguardFaceListenModel(
biometricSettingEnabledForUser = false, biometricSettingEnabledForUser = false,
bouncerFullyShown = false, bouncerFullyShown = false,
faceAndFpNotAuthenticated = false, faceAndFpNotAuthenticated = false,
faceAuthAllowed = true,
faceDisabled = false, faceDisabled = false,
faceLockedOut = false, faceLockedOut = false,
fpLockedOut = false,
goingToSleep = false, goingToSleep = false,
keyguardAwake = false, keyguardAwake = false,
keyguardGoingAway = false, keyguardGoingAway = false,
listeningForFaceAssistant = false, listeningForFaceAssistant = false,
occludingAppRequestingFaceAuth = false, occludingAppRequestingFaceAuth = false,
primaryUser = false, primaryUser = false,
scanningAllowedByStrongAuth = false,
secureCameraLaunched = false, secureCameraLaunched = false,
supportsDetect = true,
switchingUser = false, switchingUser = false,
udfpsBouncerShowing = false, udfpsBouncerShowing = false,
udfpsFingerDown = false, udfpsFingerDown = false,

View File

@@ -26,6 +26,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.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
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.BIOMETRIC_STATE_CANCELLING_RESTARTING;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT; import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
@@ -100,6 +101,8 @@ import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import androidx.annotation.NonNull;
import com.android.dx.mockito.inline.extended.ExtendedMockito; import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.jank.InteractionJankMonitor;
import com.android.internal.logging.InstanceId; import com.android.internal.logging.InstanceId;
@@ -267,21 +270,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// IBiometricsFace@1.0 does not support detection, only authentication. // IBiometricsFace@1.0 does not support detection, only authentication.
when(mFaceSensorProperties.isEmpty()).thenReturn(false); when(mFaceSensorProperties.isEmpty()).thenReturn(false);
when(mFaceSensorProperties.get(anyInt())).thenReturn(
createFaceSensorProperties(/* supportsFaceDetection = */ false));
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */,
"vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */,
"00000001" /* serialNumber */, "" /* softwareVersion */));
componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */,
"" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */,
"vendor/version/revision" /* softwareVersion */));
when(mFaceSensorProperties.get(anyInt())).thenReturn(new FaceSensorPropertiesInternal(
0 /* id */,
FaceSensorProperties.STRENGTH_STRONG, 1 /* maxTemplatesAllowed */,
componentInfo, FaceSensorProperties.TYPE_UNKNOWN,
false /* supportsFaceDetection */, true /* supportsSelfIllumination */,
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(
@@ -354,6 +345,28 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
when(mAuthController.areAllFingerprintAuthenticatorsRegistered()).thenReturn(true); when(mAuthController.areAllFingerprintAuthenticatorsRegistered()).thenReturn(true);
} }
@NonNull
private FaceSensorPropertiesInternal createFaceSensorProperties(boolean supportsFaceDetection) {
final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */,
"vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */,
"00000001" /* serialNumber */, "" /* softwareVersion */));
componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */,
"" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */,
"vendor/version/revision" /* softwareVersion */));
return new FaceSensorPropertiesInternal(
0 /* id */,
FaceSensorProperties.STRENGTH_STRONG,
1 /* maxTemplatesAllowed */,
componentInfo,
FaceSensorProperties.TYPE_UNKNOWN,
supportsFaceDetection /* supportsFaceDetection */,
true /* supportsSelfIllumination */,
false /* resetLockoutRequiresChallenge */);
}
@After @After
public void tearDown() { public void tearDown() {
if (mMockitoSession != null) { if (mMockitoSession != null) {
@@ -611,7 +624,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test @Test
public void testUnlockingWithFaceAllowed_strongAuthTrackerUnlockingWithBiometricAllowed() { public void testUnlockingWithFaceAllowed_strongAuthTrackerUnlockingWithBiometricAllowed() {
// GIVEN unlocking with biometric is allowed // GIVEN unlocking with biometric is allowed
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true); strongAuthNotRequired();
// THEN unlocking with face and fp is allowed // THEN unlocking with face and fp is allowed
Assert.assertTrue(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed( Assert.assertTrue(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
@@ -633,7 +646,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test @Test
public void testUnlockingWithFaceAllowed_fingerprintLockout() { public void testUnlockingWithFaceAllowed_fingerprintLockout() {
// GIVEN unlocking with biometric is allowed // GIVEN unlocking with biometric is allowed
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true); strongAuthNotRequired();
// WHEN fingerprint is locked out // WHEN fingerprint is locked out
fingerprintErrorLockedOut(); fingerprintErrorLockedOut();
@@ -656,7 +669,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test @Test
public void testUnlockingWithFpAllowed_fingerprintLockout() { public void testUnlockingWithFpAllowed_fingerprintLockout() {
// GIVEN unlocking with biometric is allowed // GIVEN unlocking with biometric is allowed
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true); strongAuthNotRequired();
// WHEN fingerprint is locked out // WHEN fingerprint is locked out
fingerprintErrorLockedOut(); fingerprintErrorLockedOut();
@@ -710,10 +723,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
} }
@Test @Test
public void skipsAuthentication_whenEncryptedKeyguard() { public void skipsAuthentication_whenStrongAuthRequired_nonBypass() {
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn( lockscreenBypassIsNotAllowed();
STRONG_AUTH_REQUIRED_AFTER_BOOT); when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON); mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages(); mTestableLooper.processAllMessages();
@@ -723,15 +735,48 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
} }
@Test @Test
public void requiresAuthentication_whenEncryptedKeyguard_andBypass() { public void faceDetect_whenStrongAuthRequiredAndBypass() {
testStrongAuthExceptOnBouncer( // GIVEN bypass is enabled, face detection is supported and strong auth is required
STRONG_AUTH_REQUIRED_AFTER_BOOT); lockscreenBypassIsAllowed();
supportsFaceDetection();
strongAuthRequiredEncrypted();
keyguardIsVisible();
// WHEN the device wakes up
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
// FACE detect is triggered, not authenticate
verify(mFaceManager).detectFace(any(), any(), anyInt());
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
// WHEN bouncer becomes visible
setKeyguardBouncerVisibility(true);
clearInvocations(mFaceManager);
// THEN face scanning is not run
mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
} }
@Test @Test
public void requiresAuthentication_whenTimeoutKeyguard_andBypass() { public void noFaceDetect_whenStrongAuthRequiredAndBypass_faceDetectionUnsupported() {
testStrongAuthExceptOnBouncer( // GIVEN bypass is enabled, face detection is NOT supported and strong auth is required
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT); lockscreenBypassIsAllowed();
strongAuthRequiredEncrypted();
keyguardIsVisible();
// WHEN the device wakes up
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
// FACE detect and authenticate are NOT triggered
verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
} }
@Test @Test
@@ -764,24 +809,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(didFaceAuthRun).isFalse(); assertThat(didFaceAuthRun).isFalse();
} }
private void testStrongAuthExceptOnBouncer(int strongAuth) {
when(mKeyguardBypassController.canBypass()).thenReturn(true);
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(strongAuth);
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
keyguardIsVisible();
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
// Stop scanning when bouncer becomes visible
setKeyguardBouncerVisibility(true);
clearInvocations(mFaceManager);
mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean());
}
@Test @Test
public void testTriesToAuthenticate_whenAssistant() { public void testTriesToAuthenticate_whenAssistant() {
mKeyguardUpdateMonitor.setKeyguardShowing(true, true); mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
@@ -792,10 +819,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test @Test
public void testTriesToAuthenticate_whenTrustOnAgentKeyguard_ifBypass() { public void testTriesToAuthenticate_whenTrustOnAgentKeyguard_ifBypass() {
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON); mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages(); mTestableLooper.processAllMessages();
when(mKeyguardBypassController.canBypass()).thenReturn(true); lockscreenBypassIsAllowed();
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */, mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */, KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */,
new ArrayList<>()); new ArrayList<>());
@@ -815,26 +841,17 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
} }
@Test @Test
public void testIgnoresAuth_whenLockdown() { public void testNoFaceAuth_whenLockDown() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON); when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
mTestableLooper.processAllMessages(); userDeviceLockDown();
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
keyguardIsVisible(); keyguardIsVisible();
mTestableLooper.processAllMessages();
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(), verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyBoolean()); anyBoolean());
} verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
@Test
public void testTriesToAuthenticate_whenLockout() {
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT);
keyguardIsVisible();
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
} }
@Test @Test
@@ -1329,7 +1346,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED); mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED);
setKeyguardBouncerVisibility(false /* isVisible */); setKeyguardBouncerVisibility(false /* isVisible */);
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON); mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
when(mKeyguardBypassController.canBypass()).thenReturn(true); lockscreenBypassIsAllowed();
keyguardIsVisible(); keyguardIsVisible();
// WHEN status bar state reports a change to the keyguard that would normally indicate to // WHEN status bar state reports a change to the keyguard that would normally indicate to
@@ -1513,11 +1530,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
userNotCurrentlySwitching(); userNotCurrentlySwitching();
// This disables face auth // This disables face auth
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser())) when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
.thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT);
mTestableLooper.processAllMessages(); mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
} }
@@ -1981,6 +1996,109 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
); );
} }
@Test
public void testStrongAuthChange_lockDown_stopsFpAndFaceListeningState() {
// GIVEN device is listening for face and fingerprint
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
keyguardIsVisible();
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
final CancellationSignal fpCancel = spy(mKeyguardUpdateMonitor.mFingerprintCancelSignal);
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
mKeyguardUpdateMonitor.mFingerprintCancelSignal = fpCancel;
KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
mKeyguardUpdateMonitor.registerCallback(callback);
// WHEN strong auth changes and device is in user lockdown
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
userDeviceLockDown();
mKeyguardUpdateMonitor.notifyStrongAuthAllowedChanged(getCurrentUser());
mTestableLooper.processAllMessages();
// THEN face and fingerprint listening are cancelled
verify(faceCancel).cancel();
verify(callback).onBiometricRunningStateChanged(
eq(false), eq(BiometricSourceType.FACE));
verify(fpCancel).cancel();
verify(callback).onBiometricRunningStateChanged(
eq(false), eq(BiometricSourceType.FINGERPRINT));
}
@Test
public void testNonStrongBiometricAllowedChanged_stopsFaceListeningState() {
// GIVEN device is listening for face and fingerprint
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
keyguardIsVisible();
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
KeyguardUpdateMonitorCallback callback = mock(KeyguardUpdateMonitorCallback.class);
mKeyguardUpdateMonitor.registerCallback(callback);
// WHEN non-strong biometric allowed changes
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
mKeyguardUpdateMonitor.notifyNonStrongBiometricAllowedChanged(getCurrentUser());
mTestableLooper.processAllMessages();
// THEN face and fingerprint listening are cancelled
verify(faceCancel).cancel();
verify(callback).onBiometricRunningStateChanged(
eq(false), eq(BiometricSourceType.FACE));
}
@Test
public void testShouldListenForFace_withLockedDown_returnsFalse()
throws RemoteException {
keyguardNotGoingAway();
bouncerFullyVisibleAndNotGoingToSleep();
currentUserIsPrimary();
currentUserDoesNotHaveTrust();
biometricsNotDisabledThroughDevicePolicyManager();
biometricsEnabledForCurrentUser();
userNotCurrentlySwitching();
supportsFaceDetection();
mTestableLooper.processAllMessages();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue();
userDeviceLockDown();
assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse();
}
private void userDeviceLockDown() {
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
when(mStrongAuthTracker.getStrongAuthForUser(mCurrentUserId))
.thenReturn(STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
}
private void supportsFaceDetection() {
when(mFaceSensorProperties.get(anyInt()))
.thenReturn(createFaceSensorProperties(
/* supportsFaceDetection = */ true));
}
private void lockscreenBypassIsAllowed() {
mockCanBypassLockscreen(true);
}
private void mockCanBypassLockscreen(boolean canBypass) {
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
when(mKeyguardBypassController.canBypass()).thenReturn(canBypass);
}
private void lockscreenBypassIsNotAllowed() {
mockCanBypassLockscreen(false);
}
private void cleanupKeyguardUpdateMonitor() { private void cleanupKeyguardUpdateMonitor() {
if (mKeyguardUpdateMonitor != null) { if (mKeyguardUpdateMonitor != null) {
mKeyguardUpdateMonitor.removeCallback(mTestCallback); mKeyguardUpdateMonitor.removeCallback(mTestCallback);
@@ -2074,9 +2192,16 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
); );
} }
private void strongAuthRequiredEncrypted() {
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
.thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT);
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
}
private void strongAuthNotRequired() { private void strongAuthNotRequired() {
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser())) when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
.thenReturn(0); .thenReturn(0);
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
} }
private void currentUserDoesNotHaveTrust() { private void currentUserDoesNotHaveTrust() {
@@ -2117,6 +2242,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
setKeyguardBouncerVisibility(true); setKeyguardBouncerVisibility(true);
} }
private void bouncerNotVisible() {
setKeyguardBouncerVisibility(false);
}
private void setKeyguardBouncerVisibility(boolean isVisible) { private void setKeyguardBouncerVisibility(boolean isVisible) {
mKeyguardUpdateMonitor.sendPrimaryBouncerChanged(isVisible, isVisible); mKeyguardUpdateMonitor.sendPrimaryBouncerChanged(isVisible, isVisible);
mTestableLooper.processAllMessages(); mTestableLooper.processAllMessages();