Add a bouncer string for adaptive auth
Flag: ACONFIG android.adaptiveauth.enable_adaptive_auth DEVELOPMENT
Bug: 285053096
Test: 1. Trigger 5 failed biometric attempts and/or primary auth
attempts from BiometricPrompt or Settings (not on Keyguard),
which will lock the device out
2. See bouncer message
Test: atest KeyguardViewMediatorTest
Change-Id: Ie6140a866bd77020734f7c868d0b2a470a904683
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e401c71..57c4230 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1416,6 +1416,9 @@
<!-- Indication on the keyguard that appears when a trust agents unlocks the device. [CHAR LIMIT=40] -->
<string name="keyguard_indication_trust_unlocked">Kept unlocked by TrustAgent</string>
+ <!-- Message asking the user to authenticate with primary authentication methods (PIN/pattern/password) or biometrics after the device is locked by adaptive auth. [CHAR LIMIT=60] -->
+ <string name="kg_prompt_after_adaptive_auth_lock">Theft protection\nDevice locked, too many unlock attempts</string>
+
<!-- Accessibility string for current zen mode and selected exit condition. A template that simply concatenates existing mode string and the current condition description. [CHAR LIMIT=20] -->
<string name="zen_mode_and_condition"><xliff:g id="zen_mode" example="Priority interruptions only">%1$s</xliff:g>. <xliff:g id="exit_condition" example="For one hour">%2$s</xliff:g></string>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 3585feb..84c8ea7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -19,6 +19,7 @@
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.view.WindowInsets.Type.ime;
+import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_ADAPTIVE_AUTH_REQUEST;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
@@ -126,6 +127,8 @@
return R.string.kg_prompt_reason_timeout_password;
case PROMPT_REASON_TRUSTAGENT_EXPIRED:
return R.string.kg_prompt_reason_timeout_password;
+ case PROMPT_REASON_ADAPTIVE_AUTH_REQUEST:
+ return R.string.kg_prompt_after_adaptive_auth_lock;
case PROMPT_REASON_NONE:
return 0;
default:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
index db7ff88..bf8900d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java
@@ -331,6 +331,9 @@
case PROMPT_REASON_TRUSTAGENT_EXPIRED:
resId = R.string.kg_prompt_reason_timeout_pattern;
break;
+ case PROMPT_REASON_ADAPTIVE_AUTH_REQUEST:
+ resId = R.string.kg_prompt_after_adaptive_auth_lock;
+ break;
case PROMPT_REASON_NONE:
break;
default:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
index fcff0db..bcab6f0 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinBasedInputView.java
@@ -16,6 +16,7 @@
package com.android.keyguard;
+import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_ADAPTIVE_AUTH_REQUEST;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NONE;
import static com.android.keyguard.KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
@@ -138,6 +139,8 @@
return R.string.kg_prompt_reason_timeout_pin;
case PROMPT_REASON_TRUSTAGENT_EXPIRED:
return R.string.kg_prompt_reason_timeout_pin;
+ case PROMPT_REASON_ADAPTIVE_AUTH_REQUEST:
+ return R.string.kg_prompt_after_adaptive_auth_lock;
case PROMPT_REASON_NONE:
return 0;
default:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 83b1a2c..3e87c1b6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -67,6 +67,11 @@
int PROMPT_REASON_TRUSTAGENT_EXPIRED = 8;
/**
+ * Some auth is required because adaptive auth has determined risk
+ */
+ int PROMPT_REASON_ADAPTIVE_AUTH_REQUEST = 9;
+
+ /**
* Strong auth is required because the device has just booted because of an automatic
* mainline update.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
index 8197145..c25e748 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerMessageInteractor.kt
@@ -50,6 +50,7 @@
import com.android.systemui.res.R.string.kg_primary_auth_locked_out_password
import com.android.systemui.res.R.string.kg_primary_auth_locked_out_pattern
import com.android.systemui.res.R.string.kg_primary_auth_locked_out_pin
+import com.android.systemui.res.R.string.kg_prompt_after_adaptive_auth_lock
import com.android.systemui.res.R.string.kg_prompt_after_dpm_lock
import com.android.systemui.res.R.string.kg_prompt_after_update_password
import com.android.systemui.res.R.string.kg_prompt_after_update_pattern
@@ -208,6 +209,11 @@
} else {
faceLockedOut(currentSecurityMode, isFingerprintAuthCurrentlyAllowed.value)
}
+ } else if (flags.isSomeAuthRequiredAfterAdaptiveAuthRequest) {
+ authRequiredAfterAdaptiveAuthRequest(
+ currentSecurityMode,
+ isFingerprintAuthCurrentlyAllowed.value
+ )
} else if (
trustOrBiometricsAvailable &&
flags.strongerAuthRequiredAfterNonStrongBiometricsTimeout
@@ -464,6 +470,34 @@
}.toMessage()
}
+private fun authRequiredAfterAdaptiveAuthRequest(
+ securityMode: SecurityMode,
+ fpAuthIsAllowed: Boolean
+): BouncerMessageModel {
+ return if (fpAuthIsAllowed) authRequiredAfterAdaptiveAuthRequestFingerprintAllowed(securityMode)
+ else
+ return when (securityMode) {
+ SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_adaptive_auth_lock)
+ SecurityMode.Password ->
+ Pair(keyguard_enter_password, kg_prompt_after_adaptive_auth_lock)
+ SecurityMode.PIN -> Pair(keyguard_enter_pin, kg_prompt_after_adaptive_auth_lock)
+ else -> Pair(0, 0)
+ }.toMessage()
+}
+
+private fun authRequiredAfterAdaptiveAuthRequestFingerprintAllowed(
+ securityMode: SecurityMode
+): BouncerMessageModel {
+ return when (securityMode) {
+ SecurityMode.Pattern ->
+ Pair(kg_unlock_with_pattern_or_fp, kg_prompt_after_adaptive_auth_lock)
+ SecurityMode.Password ->
+ Pair(kg_unlock_with_password_or_fp, kg_prompt_after_adaptive_auth_lock)
+ SecurityMode.PIN -> Pair(kg_unlock_with_pin_or_fp, kg_prompt_after_adaptive_auth_lock)
+ else -> Pair(0, 0)
+ }.toMessage()
+}
+
private fun authRequiredAfterUserLockdown(securityMode: SecurityMode): BouncerMessageModel {
return when (securityMode) {
SecurityMode.Pattern -> Pair(keyguard_enter_pattern, kg_prompt_after_user_lockdown_pattern)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index b5ca79e7..1b6d6a9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -30,6 +30,7 @@
import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_OCCLUSION;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_TRANSITION_FROM_AOD;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_UNLOCK_ANIMATION;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED;
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_DPM_LOCK_NOW;
@@ -921,15 +922,17 @@
return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
} else if ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) != 0) {
return KeyguardSecurityView.PROMPT_REASON_DEVICE_ADMIN;
+ } else if (any && ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0
+ || mUpdateMonitor.isFingerprintLockedOut())) {
+ return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
+ } else if ((strongAuth & SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST) != 0) {
+ return KeyguardSecurityView.PROMPT_REASON_ADAPTIVE_AUTH_REQUEST;
} else if (trustAgentsEnabled
&& (strongAuth & SOME_AUTH_REQUIRED_AFTER_USER_REQUEST) != 0) {
return KeyguardSecurityView.PROMPT_REASON_USER_REQUEST;
} else if (trustAgentsEnabled
&& (strongAuth & SOME_AUTH_REQUIRED_AFTER_TRUSTAGENT_EXPIRED) != 0) {
return KeyguardSecurityView.PROMPT_REASON_TRUSTAGENT_EXPIRED;
- } else if (any && ((strongAuth & STRONG_AUTH_REQUIRED_AFTER_LOCKOUT) != 0
- || mUpdateMonitor.isFingerprintLockedOut())) {
- return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
} else if (any && (strongAuth & STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) != 0) {
return KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
} else if (any && (strongAuth
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AuthenticationFlags.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AuthenticationFlags.kt
index cf5b88f..08904b6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AuthenticationFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/AuthenticationFlags.kt
@@ -60,6 +60,12 @@
LockPatternUtils.StrongAuthTracker
.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT
)
+
+ val isSomeAuthRequiredAfterAdaptiveAuthRequest =
+ containsFlag(
+ flag,
+ LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST
+ )
}
private fun containsFlag(haystack: Int, needle: Int): Boolean {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 2732047..0957748 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -21,6 +21,7 @@
import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_TIMEOUT;
import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;
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 com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
@@ -650,6 +651,25 @@
}
@Test
+ public void testBouncerPrompt_deviceLockedByAdaptiveAuth() {
+ // GIVEN no trust agents enabled and biometrics aren't enrolled
+ when(mUpdateMonitor.isTrustUsuallyManaged(anyInt())).thenReturn(false);
+ when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(false);
+
+ // WHEN the strong auth reason is SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST
+ KeyguardUpdateMonitor.StrongAuthTracker strongAuthTracker =
+ mock(KeyguardUpdateMonitor.StrongAuthTracker.class);
+ when(mUpdateMonitor.getStrongAuthTracker()).thenReturn(strongAuthTracker);
+ when(strongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
+ when(strongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
+ SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST);
+
+ // THEN the bouncer prompt reason should return PROMPT_REASON_ADAPTIVE_AUTH_REQUEST
+ assertEquals(KeyguardSecurityView.PROMPT_REASON_ADAPTIVE_AUTH_REQUEST,
+ mViewMediator.mViewMediatorCallback.getBouncerPromptReason());
+ }
+
+ @Test
public void testBouncerPrompt_deviceRestartedDueToMainlineUpdate() {
// GIVEN biometrics enrolled
when(mUpdateMonitor.isUnlockingWithBiometricsPossible(anyInt())).thenReturn(true);