Add explaination strings to bouncer if biometrics timeout

Add/Handle non-strong Biometric callbacks when 4-hour idle timeout,
and show a explaination strings to bouncer.

Bug: 240875182

Test: locally modified timeout to manually test
Test: atest SystemUITests
Change-Id: Ib77480863ef0d584105499d36a9e4b14b078fa58
This commit is contained in:
Jason Chang
2022-08-24 20:47:10 +08:00
parent fb95d523ed
commit 17f81ed758
6 changed files with 64 additions and 5 deletions

View File

@@ -201,13 +201,13 @@
<string name="kg_prompt_reason_restart_password">Password required after device restarts</string>
<!-- An explanation text that the pattern needs to be solved since the user hasn't used strong authentication since quite some time. [CHAR LIMIT=80] -->
<string name="kg_prompt_reason_timeout_pattern">Pattern required for additional security</string>
<string name="kg_prompt_reason_timeout_pattern">For additional security, use pattern instead</string>
<!-- An explanation text that the pin needs to be entered since the user hasn't used strong authentication since quite some time. [CHAR LIMIT=80] -->
<string name="kg_prompt_reason_timeout_pin">PIN required for additional security</string>
<string name="kg_prompt_reason_timeout_pin">For additional security, use PIN instead</string>
<!-- An explanation text that the password needs to be entered since the user hasn't used strong authentication since quite some time. [CHAR LIMIT=80] -->
<string name="kg_prompt_reason_timeout_password">Password required for additional security</string>
<string name="kg_prompt_reason_timeout_password">For additional security, use password instead</string>
<!-- An explanation text that the credential needs to be entered because a device admin has
locked the device. [CHAR LIMIT=80] -->

View File

@@ -1406,6 +1406,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
private void notifyNonStrongBiometricStateChanged(int userId) {
Assert.isMainThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onNonStrongBiometricAllowedChanged(userId);
}
}
}
private void dispatchErrorMessage(CharSequence message) {
Assert.isMainThread();
for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1759,11 +1769,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
public static class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
private final Consumer<Integer> mStrongAuthRequiredChangedCallback;
private final Consumer<Integer> mNonStrongBiometricAllowedChanged;
public StrongAuthTracker(Context context,
Consumer<Integer> strongAuthRequiredChangedCallback) {
Consumer<Integer> strongAuthRequiredChangedCallback,
Consumer<Integer> nonStrongBiometricAllowedChanged) {
super(context);
mStrongAuthRequiredChangedCallback = strongAuthRequiredChangedCallback;
mNonStrongBiometricAllowedChanged = nonStrongBiometricAllowedChanged;
}
public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
@@ -1781,6 +1794,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
public void onStrongAuthRequiredChanged(int userId) {
mStrongAuthRequiredChangedCallback.accept(userId);
}
// TODO(b/247091681): Renaming the inappropriate onIsNonStrongBiometricAllowedChanged
// callback wording for Weak/Convenience idle timeout constraint that only allow
// Strong-Auth
@Override
public void onIsNonStrongBiometricAllowedChanged(int userId) {
mNonStrongBiometricAllowedChanged.accept(userId);
}
}
protected void handleStartedWakingUp() {
@@ -1918,7 +1939,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mSubscriptionManager = SubscriptionManager.from(context);
mTelephonyListenerManager = telephonyListenerManager;
mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged);
mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged,
this::notifyNonStrongBiometricStateChanged);
mBackgroundExecutor = backgroundExecutor;
mBroadcastDispatcher = broadcastDispatcher;
mInteractionJankMonitor = interactionJankMonitor;

View File

@@ -305,4 +305,9 @@ public class KeyguardUpdateMonitorCallback {
* Called when the notification shade is expanded or collapsed.
*/
public void onShadeExpandedChanged(boolean expanded) { }
/**
* Called when the non-strong biometric state changed.
*/
public void onNonStrongBiometricAllowedChanged(int userId) { }
}

View File

@@ -794,6 +794,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
mUpdateMonitor.getStrongAuthTracker();
int strongAuth = strongAuthTracker.getStrongAuthForUser(currentUser);
boolean allowedNonStrongAfterIdleTimeout =
strongAuthTracker.isNonStrongBiometricAllowedAfterIdleTimeout(currentUser);
if (any && !strongAuthTracker.hasUserAuthenticatedSinceBoot()) {
return KeyguardSecurityView.PROMPT_REASON_RESTART;
@@ -815,6 +817,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
} else if (any && (strongAuth
& STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT) != 0) {
return KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
} else if (any && !allowedNonStrongAfterIdleTimeout) {
return KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
}
return KeyguardSecurityView.PROMPT_REASON_NONE;
}

View File

@@ -91,6 +91,11 @@ public class KeyguardBouncer {
mBouncerPromptReason = mCallback.getBouncerPromptReason();
}
}
@Override
public void onNonStrongBiometricAllowedChanged(int userId) {
mBouncerPromptReason = mCallback.getBouncerPromptReason();
}
};
private final Runnable mRemoveViewRunnable = this::removeView;
private final KeyguardBypassController mKeyguardBypassController;

View File

@@ -19,6 +19,7 @@ package com.android.systemui.keyguard;
import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
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_NON_STRONG_BIOMETRICS_TIMEOUT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -228,6 +229,28 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mViewMediator.mViewMediatorCallback.getBouncerPromptReason());
}
@Test
public void testBouncerPrompt_nonStrongIdleTimeout() {
// GIVEN trust agents enabled and biometrics are enrolled
when(mUpdateMonitor.isTrustUsuallyManaged(anyInt())).thenReturn(true);
when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(true);
// WHEN the strong auth reason is STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT
KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
mock(KeyguardUpdateMonitor.StrongAuthTracker.class);
when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(strongAuthTracker);
when(strongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
when(strongAuthTracker.isNonStrongBiometricAllowedAfterIdleTimeout(
anyInt())).thenReturn(false);
when(strongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT);
// THEN the bouncer prompt reason should return
// STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT
assertEquals(KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT,
mViewMediator.mViewMediatorCallback.getBouncerPromptReason());
}
@Test
public void testHideSurfaceBehindKeyguardMarksKeyguardNotGoingAway() {
mViewMediator.hideSurfaceBehindKeyguard();