Merge "Only show auth ripple on keyguard" into sc-dev

This commit is contained in:
Beverly Tai
2021-05-20 22:32:38 +00:00
committed by Android (Google) Code Review
4 changed files with 99 additions and 9 deletions

View File

@@ -2143,7 +2143,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final boolean shouldListenUdfpsState = !isUdfps final boolean shouldListenUdfpsState = !isUdfps
|| (!getUserCanSkipBouncer(getCurrentUser()) || (!getUserCanSkipBouncer(getCurrentUser())
&& !isEncryptedOrLockdown(getCurrentUser()) && !isEncryptedOrLockdown(getCurrentUser())
&& mStrongAuthTracker.hasUserAuthenticatedSinceBoot() && !userNeedsStrongAuth()
&& userDoesNotHaveTrust); && userDoesNotHaveTrust);
return shouldListenKeyguardState && shouldListenUserState && shouldListenBouncerState return shouldListenKeyguardState && shouldListenUserState && shouldListenBouncerState

View File

@@ -27,6 +27,7 @@ import com.android.settingslib.Utils
import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.Command import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope import com.android.systemui.statusbar.phone.dagger.StatusBarComponent.StatusBarScope
import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.ViewController import com.android.systemui.util.ViewController
@@ -45,6 +46,7 @@ class AuthRippleController @Inject constructor(
private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val commandRegistry: CommandRegistry, private val commandRegistry: CommandRegistry,
private val notificationShadeWindowController: NotificationShadeWindowController, private val notificationShadeWindowController: NotificationShadeWindowController,
private val bypassController: KeyguardBypassController,
rippleView: AuthRippleView? rippleView: AuthRippleView?
) : ViewController<AuthRippleView>(rippleView) { ) : ViewController<AuthRippleView>(rippleView) {
private var fingerprintSensorLocation: PointF? = null private var fingerprintSensorLocation: PointF? = null
@@ -69,12 +71,20 @@ class AuthRippleController @Inject constructor(
} }
private fun showRipple(biometricSourceType: BiometricSourceType?) { private fun showRipple(biometricSourceType: BiometricSourceType?) {
if (!keyguardUpdateMonitor.isKeyguardVisible ||
keyguardUpdateMonitor.userNeedsStrongAuth()) {
return
}
if (biometricSourceType == BiometricSourceType.FINGERPRINT && if (biometricSourceType == BiometricSourceType.FINGERPRINT &&
fingerprintSensorLocation != null) { fingerprintSensorLocation != null) {
mView.setSensorLocation(fingerprintSensorLocation!!) mView.setSensorLocation(fingerprintSensorLocation!!)
showRipple() showRipple()
} else if (biometricSourceType == BiometricSourceType.FACE && } else if (biometricSourceType == BiometricSourceType.FACE &&
faceSensorLocation != null) { faceSensorLocation != null) {
if (!bypassController.canBypass()) {
return
}
mView.setSensorLocation(faceSensorLocation!!) mView.setSensorLocation(faceSensorLocation!!)
showRipple() showRipple()
} }

View File

@@ -19,6 +19,8 @@ package com.android.keyguard;
import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE; import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID; import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@@ -477,7 +479,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test @Test
public void testFingerprintDoesNotAuth_whenEncrypted() { public void testFingerprintDoesNotAuth_whenEncrypted() {
testFingerprintWhenStrongAuth( testFingerprintWhenStrongAuth(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT); STRONG_AUTH_REQUIRED_AFTER_BOOT);
} }
@Test @Test
@@ -576,7 +578,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test @Test
public void skipsAuthentication_whenEncryptedKeyguard() { public void skipsAuthentication_whenEncryptedKeyguard() {
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn( when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT); STRONG_AUTH_REQUIRED_AFTER_BOOT);
mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController); mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
mKeyguardUpdateMonitor.dispatchStartedWakingUp(); mKeyguardUpdateMonitor.dispatchStartedWakingUp();
@@ -588,7 +590,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test @Test
public void requiresAuthentication_whenEncryptedKeyguard_andBypass() { public void requiresAuthentication_whenEncryptedKeyguard_andBypass() {
testStrongAuthExceptOnBouncer( testStrongAuthExceptOnBouncer(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT); STRONG_AUTH_REQUIRED_AFTER_BOOT);
} }
@Test @Test
@@ -893,7 +895,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD); mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
// WHEN user hasn't authenticated since last boot // WHEN user hasn't authenticated since last boot
when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(false); when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
.thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT);
// THEN we shouldn't listen for udfps // THEN we shouldn't listen for udfps
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false); assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);

View File

@@ -25,6 +25,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.NotificationShadeWindowController import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.CommandRegistry import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.ConfigurationController
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
@@ -49,6 +50,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var authController: AuthController @Mock private lateinit var authController: AuthController
@Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
@Mock private lateinit var bypassController: KeyguardBypassController
@Before @Before
fun setUp() { fun setUp() {
@@ -60,45 +62,120 @@ class AuthRippleControllerTest : SysuiTestCase() {
keyguardUpdateMonitor, keyguardUpdateMonitor,
commandRegistry, commandRegistry,
notificationShadeWindowController, notificationShadeWindowController,
bypassController,
rippleView rippleView
) )
controller.init() controller.init()
} }
@Test @Test
fun testFingerprintTriggerRipple() { fun testFingerprintTrigger_Ripple() {
// GIVEN fp exists, keyguard is visible, user doesn't need strong auth
val fpsLocation = PointF(5f, 5f) val fpsLocation = PointF(5f, 5f)
`when`(authController.udfpsSensorLocation).thenReturn(fpsLocation) `when`(authController.udfpsSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached() controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
// WHEN fingerprint authenticated
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java) val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(captor.capture()) verify(keyguardUpdateMonitor).registerCallback(captor.capture())
captor.value.onBiometricAuthenticated( captor.value.onBiometricAuthenticated(
0 /* userId */, 0 /* userId */,
BiometricSourceType.FINGERPRINT /* type */, BiometricSourceType.FINGERPRINT /* type */,
false /* isStrongBiometric */) false /* isStrongBiometric */)
// THEN update sensor location and show ripple
verify(rippleView).setSensorLocation(fpsLocation) verify(rippleView).setSensorLocation(fpsLocation)
verify(rippleView).startRipple(any()) verify(rippleView).startRipple(any())
} }
@Test @Test
fun testFaceTriggerRipple() { fun testFingerprintTrigger_KeyguardNotVisible_NoRipple() {
// GIVEN fp exists & user doesn't need strong auth
val fpsLocation = PointF(5f, 5f)
`when`(authController.udfpsSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
// WHEN keyguard is NOT visible & fingerprint authenticated
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(false)
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(captor.capture())
captor.value.onBiometricAuthenticated(
0 /* userId */,
BiometricSourceType.FINGERPRINT /* type */,
false /* isStrongBiometric */)
// THEN no ripple
verify(rippleView, never()).startRipple(any())
}
@Test
fun testFingerprintTrigger_StrongAuthRequired_NoRipple() {
// GIVEN fp exists & keyguard is visible
val fpsLocation = PointF(5f, 5f)
`when`(authController.udfpsSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
// WHEN user needs strong auth & fingerprint authenticated
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(true)
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(captor.capture())
captor.value.onBiometricAuthenticated(
0 /* userId */,
BiometricSourceType.FINGERPRINT /* type */,
false /* isStrongBiometric */)
// THEN no ripple
verify(rippleView, never()).startRipple(any())
}
@Test
fun testFaceTriggerBypassEnabled_Ripple() {
// GIVEN face auth sensor exists, keyguard is visible & strong auth isn't required
val faceLocation = PointF(5f, 5f) val faceLocation = PointF(5f, 5f)
`when`(authController.faceAuthSensorLocation).thenReturn(faceLocation) `when`(authController.faceAuthSensorLocation).thenReturn(faceLocation)
controller.onViewAttached() controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
// WHEN bypass is enabled & face authenticated
`when`(bypassController.canBypass()).thenReturn(true)
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java) val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(captor.capture()) verify(keyguardUpdateMonitor).registerCallback(captor.capture())
captor.value.onBiometricAuthenticated( captor.value.onBiometricAuthenticated(
0 /* userId */, 0 /* userId */,
BiometricSourceType.FACE /* type */, BiometricSourceType.FACE /* type */,
false /* isStrongBiometric */) false /* isStrongBiometric */)
// THEN show ripple
verify(rippleView).setSensorLocation(faceLocation) verify(rippleView).setSensorLocation(faceLocation)
verify(rippleView).startRipple(any()) verify(rippleView).startRipple(any())
} }
@Test
fun testFaceTriggerNonBypass_NoRipple() {
// GIVEN face auth sensor exists
val faceLocation = PointF(5f, 5f)
`when`(authController.faceAuthSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
// WHEN bypass isn't enabled & face authenticated
`when`(bypassController.canBypass()).thenReturn(false)
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(captor.capture())
captor.value.onBiometricAuthenticated(
0 /* userId */,
BiometricSourceType.FACE /* type */,
false /* isStrongBiometric */)
// THEN no ripple
verify(rippleView, never()).startRipple(any())
}
@Test @Test
fun testNullFaceSensorLocationDoesNothing() { fun testNullFaceSensorLocationDoesNothing() {
`when`(authController.faceAuthSensorLocation).thenReturn(null) `when`(authController.faceAuthSensorLocation).thenReturn(null)