On strongAuthChanges, update fp & face states
Previously, we relied on other state to update which would trigger updateBiometricListeningState. Instead of relying on other triggers, directly update the biometric listening state if strong auth or non-strong auth allowed states change. Don't run face auth or detect if device is locked down by the user. However, if bypass is enabled and the other strongauth requirements are triggered (ie: idle timeout, timeout, encrypted, dpm lockdown, after boot), then run detectFace if its supported. Bug: 259908246 Bug: 258513069 Bug: 260682144 Test: atest KeyguardUpdateMonitorTest Change-Id: If03a1525832dfb8366c36757ebc84c0dead51b9f
This commit is contained in:
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
@@ -170,7 +171,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;
|
||||||
@@ -1401,6 +1401,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);
|
||||||
@@ -1432,7 +1435,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();
|
||||||
@@ -1440,6 +1444,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) {
|
||||||
@@ -1451,8 +1464,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();
|
||||||
@@ -1460,6 +1473,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) {
|
||||||
@@ -1805,16 +1828,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) {
|
||||||
@@ -1830,7 +1849,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
|
||||||
@@ -1838,7 +1857,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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1999,8 +2018,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;
|
||||||
@@ -2575,24 +2593,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;
|
||||||
|
|
||||||
@@ -2604,9 +2615,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));
|
||||||
@@ -2658,7 +2668,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 =
|
||||||
@@ -2720,14 +2731,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
|
||||||
@@ -2735,20 +2739,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);
|
||||||
@@ -2769,14 +2768,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(
|
||||||
@@ -2786,19 +2781,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,
|
||||||
@@ -2902,9 +2897,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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -27,6 +27,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;
|
||||||
@@ -101,6 +102,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
|
||||||
@@ -977,8 +994,6 @@ 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)))
|
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser)))
|
||||||
.thenReturn(fingerprintLockoutMode);
|
.thenReturn(fingerprintLockoutMode);
|
||||||
@@ -1321,7 +1336,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
|
||||||
@@ -1505,11 +1520,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();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1973,6 +1986,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);
|
||||||
@@ -2066,9 +2182,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() {
|
||||||
@@ -2109,6 +2232,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();
|
||||||
|
|||||||
Reference in New Issue
Block a user