From 0011ed15f3cfb631cc5e9290d41ca4b9d064bdd6 Mon Sep 17 00:00:00 2001 From: Beverly Date: Fri, 10 Feb 2023 20:18:02 +0000 Subject: [PATCH] RESTRICT AUTOMERGE Add activeUnlock config to force dismissKeyguard On some wakeup active unlock triggers Test: manual Test: atest KeyguardUpdateMonitorTest ActiveUnlockConfigTest Fixes: 267170467 Change-Id: Ib1aa68a7407f9e902d78f1d949471edddb26281a --- core/java/android/provider/Settings.java | 13 +++- .../settings/backup/SecureSettings.java | 1 + .../validators/SecureSettingsValidators.java | 2 + .../android/keyguard/ActiveUnlockConfig.kt | 45 ++++++++++- .../keyguard/FaceWakeUpTriggersConfig.kt | 2 +- .../keyguard/KeyguardUpdateMonitor.java | 19 ++++- .../keyguard/ActiveUnlockConfigTest.kt | 76 ++++++++++++++++--- .../keyguard/KeyguardUpdateMonitorTest.java | 50 ++++++++++++ 8 files changed, 192 insertions(+), 16 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index ce29c731221f4..10e1633b22d77 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9922,7 +9922,7 @@ public final class Settings { /** * If active unlock triggers on unlock intents, then also request active unlock on - * these wake-up reasons. See PowerManager.WakeReason for value mappings. + * these wake-up reasons. See {@link PowerManager.WakeReason} for value mappings. * WakeReasons should be separated by a pipe. For example: "0|3" or "0". If this * setting should be disabled, then this should be set to an empty string. A null value * will use the system default value (WAKE_REASON_UNFOLD_DEVICE). @@ -9931,6 +9931,17 @@ public final class Settings { public static final String ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS = "active_unlock_wakeups_considered_unlock_intents"; + /** + * If active unlock triggers and succeeds on these wakeups, force dismiss keyguard on + * these wake reasons. See {@link PowerManager#WakeReason} for value mappings. + * WakeReasons should be separated by a pipe. For example: "0|3" or "0". If this + * setting should be disabled, then this should be set to an empty string. A null value + * will use the system default value (WAKE_REASON_UNFOLD_DEVICE). + * @hide + */ + public static final String ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD = + "active_unlock_wakeups_to_force_dismiss_keyguard"; + /** * Whether the assist gesture should be enabled. * diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 2afcf71731710..b5eaa4b776b8b 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -131,6 +131,7 @@ public class SecureSettings { Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO, Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED, Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS, + Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, Settings.Secure.VR_DISPLAY_MODE, Settings.Secure.NOTIFICATION_BADGING, Settings.Secure.NOTIFICATION_DISMISS_RTL, diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 53ae9268f49ef..534e31ae42ee7 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -191,6 +191,8 @@ public class SecureSettingsValidators { ANY_STRING_VALIDATOR); VALIDATORS.put(Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS, ANY_STRING_VALIDATOR); + VALIDATORS.put(Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, + ANY_STRING_VALIDATOR); VALIDATORS.put(Secure.ASSIST_GESTURE_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ASSIST_GESTURE_SILENCE_ALERTS_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.ASSIST_GESTURE_WAKE_ENABLED, BOOLEAN_VALIDATOR); diff --git a/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt b/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt index ead1a100f75bb..c4f1ce8f5d3b1 100644 --- a/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt +++ b/packages/SystemUI/src/com/android/keyguard/ActiveUnlockConfig.kt @@ -29,8 +29,9 @@ import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ACQUIRE_INFO import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_FACE_ERRORS import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED -import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_WAKE +import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS +import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD import android.util.Log import com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser import com.android.systemui.Dumpable @@ -60,9 +61,27 @@ class ActiveUnlockConfig @Inject constructor( * Indicates the origin for an active unlock request. */ enum class ActiveUnlockRequestOrigin { + /** + * Trigger ActiveUnlock on wake ups that'd trigger FaceAuth, see [FaceWakeUpTriggersConfig] + */ WAKE, + + /** + * Trigger ActiveUnlock on unlock intents. This includes the bouncer showing or tapping on + * a notification. May also include wakeups: [wakeupsConsideredUnlockIntents]. + */ UNLOCK_INTENT, + + /** + * Trigger ActiveUnlock on biometric failures. This may include soft errors depending on + * the other settings. See: [faceErrorsToTriggerBiometricFailOn], + * [faceAcquireInfoToTriggerBiometricFailOn]. + */ BIOMETRIC_FAIL, + + /** + * Trigger ActiveUnlock when the assistant is triggered. + */ ASSISTANT, } @@ -85,6 +104,7 @@ class ActiveUnlockConfig @Inject constructor( private var faceAcquireInfoToTriggerBiometricFailOn = mutableSetOf() private var onUnlockIntentWhenBiometricEnrolled = mutableSetOf() private var wakeupsConsideredUnlockIntents = mutableSetOf() + private var wakeupsToForceDismissKeyguard = mutableSetOf() private val settingsObserver = object : ContentObserver(handler) { private val wakeUri = secureSettings.getUriFor(ACTIVE_UNLOCK_ON_WAKE) @@ -97,6 +117,8 @@ class ActiveUnlockConfig @Inject constructor( secureSettings.getUriFor(ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED) private val wakeupsConsideredUnlockIntentsUri = secureSettings.getUriFor(ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS) + private val wakeupsToForceDismissKeyguardUri = + secureSettings.getUriFor(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD) fun register() { registerUri( @@ -108,6 +130,7 @@ class ActiveUnlockConfig @Inject constructor( faceAcquireInfoUri, unlockIntentWhenBiometricEnrolledUri, wakeupsConsideredUnlockIntentsUri, + wakeupsToForceDismissKeyguardUri, ) ) @@ -182,6 +205,15 @@ class ActiveUnlockConfig @Inject constructor( wakeupsConsideredUnlockIntents, setOf(WAKE_REASON_UNFOLD_DEVICE)) } + + if (selfChange || uris.contains(wakeupsToForceDismissKeyguardUri)) { + processStringArray( + secureSettings.getStringForUser( + ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, + getCurrentUser()), + wakeupsToForceDismissKeyguard, + setOf(WAKE_REASON_UNFOLD_DEVICE)) + } } /** @@ -248,6 +280,14 @@ class ActiveUnlockConfig @Inject constructor( return wakeupsConsideredUnlockIntents.contains(pmWakeReason) } + /** + * Whether the PowerManager wake reason should force dismiss the keyguard if active + * unlock is successful. + */ + fun shouldWakeupForceDismissKeyguard(pmWakeReason: Int): Boolean { + return wakeupsToForceDismissKeyguard.contains(pmWakeReason) + } + /** * Whether to trigger active unlock based on where the request is coming from and * the current settings. @@ -321,6 +361,9 @@ class ActiveUnlockConfig @Inject constructor( pw.println(" activeUnlockWakeupsConsideredUnlockIntents=${ wakeupsConsideredUnlockIntents.map { PowerManager.wakeReasonToString(it) } }") + pw.println(" activeUnlockFromWakeupsToAlwaysDismissKeyguard=${ + wakeupsToForceDismissKeyguard.map { PowerManager.wakeReasonToString(it) } + }") pw.println("Current state:") keyguardUpdateMonitor?.let { diff --git a/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt b/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt index a0c43fba4bc1d..788a66dcf2817 100644 --- a/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt +++ b/packages/SystemUI/src/com/android/keyguard/FaceWakeUpTriggersConfig.kt @@ -29,7 +29,7 @@ import java.io.PrintWriter import java.util.stream.Collectors import javax.inject.Inject -/** Determines which device wake-ups should trigger face authentication. */ +/** Determines which device wake-ups should trigger passive authentication. */ @SysUISingleton class FaceWakeUpTriggersConfig @Inject diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index bb29a7e123d8d..145b32f0e5804 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1927,11 +1927,23 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab FACE_AUTH_UPDATED_STARTED_WAKING_UP.setExtraInfo(pmWakeReason); updateFaceListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_STARTED_WAKING_UP); - requestActiveUnlock( + + final ActiveUnlockConfig.ActiveUnlockRequestOrigin requestOrigin = mActiveUnlockConfig.isWakeupConsideredUnlockIntent(pmWakeReason) ? ActiveUnlockConfig.ActiveUnlockRequestOrigin.UNLOCK_INTENT - : ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE, - "wakingUp - " + PowerManager.wakeReasonToString(pmWakeReason)); + : ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE; + final String reason = "wakingUp - " + PowerManager.wakeReasonToString(pmWakeReason); + if (mActiveUnlockConfig.shouldWakeupForceDismissKeyguard(pmWakeReason)) { + requestActiveUnlockDismissKeyguard( + requestOrigin, + reason + ); + } else { + requestActiveUnlock( + requestOrigin, + reason + ); + } } else { mLogger.logSkipUpdateFaceListeningOnWakeup(pmWakeReason); } @@ -2590,6 +2602,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } + /** * Attempts to trigger active unlock from trust agent. * Only dismisses the keyguard under certain conditions. diff --git a/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt index badeb27e76967..e84a975d84e21 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/ActiveUnlockConfigTest.kt @@ -31,6 +31,7 @@ import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_UNLOCK_INTENT_WHEN_BIOMETRIC_ENROLLED import android.provider.Settings.Secure.ACTIVE_UNLOCK_ON_WAKE import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_CONSIDERED_UNLOCK_INTENTS +import android.provider.Settings.Secure.ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager @@ -51,6 +52,7 @@ import java.io.PrintWriter @SmallTest class ActiveUnlockConfigTest : SysuiTestCase() { + private lateinit var secureSettings: FakeSettings @Mock private lateinit var contentResolver: ContentResolver @@ -71,7 +73,6 @@ class ActiveUnlockConfigTest : SysuiTestCase() { @Before fun setUp() { MockitoAnnotations.initMocks(this) - currentUser = KeyguardUpdateMonitor.getCurrentUser() secureSettings = FakeSettings() activeUnlockConfig = ActiveUnlockConfig( @@ -313,10 +314,6 @@ class ActiveUnlockConfigTest : SysuiTestCase() { assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(wakeReason)) } } - assertTrue(activeUnlockConfig.isWakeupConsideredUnlockIntent(PowerManager.WAKE_REASON_LIFT)) - assertTrue(activeUnlockConfig.isWakeupConsideredUnlockIntent(PowerManager.WAKE_REASON_TAP)) - assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent( - PowerManager.WAKE_REASON_UNFOLD_DEVICE)) } @Test @@ -330,11 +327,70 @@ class ActiveUnlockConfigTest : SysuiTestCase() { for (wakeReason in 0..WAKE_REASON_BIOMETRIC) { assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(wakeReason)) } - assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent( - PowerManager.WAKE_REASON_LIFT)) - assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent(PowerManager.WAKE_REASON_TAP)) - assertFalse(activeUnlockConfig.isWakeupConsideredUnlockIntent( - PowerManager.WAKE_REASON_UNFOLD_DEVICE)) + } + + @Test + fun isWakeupForceDismissKeyguard_singleValue() { + verifyRegisterSettingObserver() + + // GIVEN lift is considered an unlock intent + secureSettings.putStringForUser(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, + PowerManager.WAKE_REASON_LIFT.toString(), currentUser) + updateSetting(secureSettings.getUriFor( + ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD + )) + + // THEN only WAKE_REASON_LIFT is considered an unlock intent + for (wakeReason in 0..WAKE_REASON_BIOMETRIC) { + if (wakeReason == PowerManager.WAKE_REASON_LIFT) { + assertTrue(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason)) + } else { + assertFalse(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason)) + } + } + } + + @Test + fun isWakeupForceDismissKeyguard_emptyValues() { + verifyRegisterSettingObserver() + + // GIVEN lift and tap are considered an unlock intent + secureSettings.putStringForUser(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, + " ", currentUser) + updateSetting(secureSettings.getUriFor( + ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD + )) + + // THEN no wake up gestures are considered an unlock intent + for (wakeReason in 0..WAKE_REASON_BIOMETRIC) { + assertFalse(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason)) + } + } + + @Test + fun isWakeupForceDismissKeyguard_multiValue() { + verifyRegisterSettingObserver() + + // GIVEN lift and tap are considered an unlock intent + secureSettings.putStringForUser(ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD, + PowerManager.WAKE_REASON_LIFT.toString() + + "|" + + PowerManager.WAKE_REASON_TAP.toString(), + currentUser + ) + updateSetting(secureSettings.getUriFor( + ACTIVE_UNLOCK_WAKEUPS_TO_FORCE_DISMISS_KEYGUARD + )) + + // THEN WAKE_REASON_LIFT and WAKE_REASON TAP are considered an unlock intent + for (wakeReason in 0..WAKE_REASON_BIOMETRIC) { + if (wakeReason == PowerManager.WAKE_REASON_LIFT || + wakeReason == PowerManager.WAKE_REASON_TAP) { + assertTrue(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason)) + } else { + assertFalse(activeUnlockConfig.shouldWakeupForceDismissKeyguard(wakeReason)) + } + } } @Test diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 853d8ed251c9d..06d5d8bffefed 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -2374,6 +2374,56 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); } + @Test + public void unfoldWakeup_requestActiveUnlock_forceDismissKeyguard() + throws RemoteException { + // GIVEN shouldTriggerActiveUnlock + keyguardIsVisible(); + when(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())).thenReturn(true); + + // GIVEN active unlock triggers on wakeup + when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin( + ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE)) + .thenReturn(true); + + // GIVEN an unfold should force dismiss the keyguard + when(mActiveUnlockConfig.shouldWakeupForceDismissKeyguard( + PowerManager.WAKE_REASON_UNFOLD_DEVICE)).thenReturn(true); + + // WHEN device wakes up from an unfold + mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNFOLD_DEVICE); + mTestableLooper.processAllMessages(); + + // THEN request unlock with a keyguard dismissal + verify(mTrustManager).reportUserRequestedUnlock(eq(KeyguardUpdateMonitor.getCurrentUser()), + eq(true)); + } + + @Test + public void unfoldWakeup_requestActiveUnlock_noDismissKeyguard() + throws RemoteException { + // GIVEN shouldTriggerActiveUnlock on wake from UNFOLD_DEVICE + keyguardIsVisible(); + when(mLockPatternUtils.isSecure(KeyguardUpdateMonitor.getCurrentUser())).thenReturn(true); + + // GIVEN active unlock triggers on wakeup + when(mActiveUnlockConfig.shouldAllowActiveUnlockFromOrigin( + ActiveUnlockConfig.ActiveUnlockRequestOrigin.WAKE)) + .thenReturn(true); + + // GIVEN an unfold should NOT force dismiss the keyguard + when(mActiveUnlockConfig.shouldWakeupForceDismissKeyguard( + PowerManager.WAKE_REASON_UNFOLD_DEVICE)).thenReturn(false); + + // WHEN device wakes up from an unfold + mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_UNFOLD_DEVICE); + mTestableLooper.processAllMessages(); + + // THEN request unlock WITHOUT a keyguard dismissal + verify(mTrustManager).reportUserRequestedUnlock(eq(KeyguardUpdateMonitor.getCurrentUser()), + eq(false)); + } + private void userDeviceLockDown() { when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false); when(mStrongAuthTracker.getStrongAuthForUser(mCurrentUserId))