Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3ab0be34 authored by Beverly's avatar Beverly Committed by Beverly Tai
Browse files

Only show auth ripple on keyguard

- Don't show the ripple on the biometric prompt
- Don't show the ripple on face auth if bypass is disabled
- Don't show the ripple if we're not authenticating (ie: brought to
bouncer for strong auth requirement)

- Never show the udfps icon if strong auth is required

Fixes: 185394442
Fixes: 188373007
Test: manual
Test: atest KeyguardUpdateMonitorTest
Test: atest AuthRippleControllerTest
Change-Id: If3141e4812528f635946fe1dd036b065a188d975
parent 11b48770
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -2143,7 +2143,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        final boolean shouldListenUdfpsState = !isUdfps
                || (!getUserCanSkipBouncer(getCurrentUser())
                    && !isEncryptedOrLockdown(getCurrentUser())
                    && mStrongAuthTracker.hasUserAuthenticatedSinceBoot()
                    && !userNeedsStrongAuth()
                    && userDoesNotHaveTrust);

        return shouldListenKeyguardState && shouldListenUserState && shouldListenBouncerState
+10 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import com.android.settingslib.Utils
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.Command
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.policy.ConfigurationController
import com.android.systemui.util.ViewController
@@ -45,6 +46,7 @@ class AuthRippleController @Inject constructor(
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val commandRegistry: CommandRegistry,
    private val notificationShadeWindowController: NotificationShadeWindowController,
    private val bypassController: KeyguardBypassController,
    rippleView: AuthRippleView?
) : ViewController<AuthRippleView>(rippleView) {
    private var fingerprintSensorLocation: PointF? = null
@@ -69,12 +71,20 @@ class AuthRippleController @Inject constructor(
    }

    private fun showRipple(biometricSourceType: BiometricSourceType?) {
        if (!keyguardUpdateMonitor.isKeyguardVisible ||
            keyguardUpdateMonitor.userNeedsStrongAuth()) {
            return
        }

        if (biometricSourceType == BiometricSourceType.FINGERPRINT &&
            fingerprintSensorLocation != null) {
            mView.setSensorLocation(fingerprintSensorLocation!!)
            showRipple()
        } else if (biometricSourceType == BiometricSourceType.FACE &&
            faceSensorLocation != null) {
            if (!bypassController.canBypass()) {
                return
            }
            mView.setSensorLocation(faceSensorLocation!!)
            showRipple()
        }
+7 −4
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.keyguard;
import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE;
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 org.mockito.ArgumentMatchers.any;
@@ -477,7 +479,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
    @Test
    public void testFingerprintDoesNotAuth_whenEncrypted() {
        testFingerprintWhenStrongAuth(
                KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT);
                STRONG_AUTH_REQUIRED_AFTER_BOOT);
    }

    @Test
@@ -576,7 +578,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
    @Test
    public void skipsAuthentication_whenEncryptedKeyguard() {
        when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
                KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT);
                STRONG_AUTH_REQUIRED_AFTER_BOOT);
        mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);

        mKeyguardUpdateMonitor.dispatchStartedWakingUp();
@@ -588,7 +590,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
    @Test
    public void requiresAuthentication_whenEncryptedKeyguard_andBypass() {
        testStrongAuthExceptOnBouncer(
                KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT);
                STRONG_AUTH_REQUIRED_AFTER_BOOT);
    }

    @Test
@@ -893,7 +895,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);

        // 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
        assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
+81 −4
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
import org.junit.Before
import org.junit.Test
@@ -49,6 +50,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
    @Mock private lateinit var authController: AuthController
    @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
    @Mock private lateinit var bypassController: KeyguardBypassController

    @Before
    fun setUp() {
@@ -60,45 +62,120 @@ class AuthRippleControllerTest : SysuiTestCase() {
            keyguardUpdateMonitor,
            commandRegistry,
            notificationShadeWindowController,
            bypassController,
            rippleView
        )
        controller.init()
    }

    @Test
    fun testFingerprintTriggerRipple() {
    fun testFingerprintTrigger_Ripple() {
        // GIVEN fp exists, keyguard is visible, user doesn't need strong auth
        val fpsLocation = PointF(5f, 5f)
        `when`(authController.udfpsSensorLocation).thenReturn(fpsLocation)
        controller.onViewAttached()
        `when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
        `when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)

        // WHEN fingerprint authenticated
        val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
        verify(keyguardUpdateMonitor).registerCallback(captor.capture())

        captor.value.onBiometricAuthenticated(
            0 /* userId */,
            BiometricSourceType.FINGERPRINT /* type */,
            false /* isStrongBiometric */)

        // THEN update sensor location and show ripple
        verify(rippleView).setSensorLocation(fpsLocation)
        verify(rippleView).startRipple(any())
    }

    @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)
        `when`(authController.faceAuthSensorLocation).thenReturn(faceLocation)
        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)
        verify(keyguardUpdateMonitor).registerCallback(captor.capture())

        captor.value.onBiometricAuthenticated(
            0 /* userId */,
            BiometricSourceType.FACE /* type */,
            false /* isStrongBiometric */)

        // THEN show ripple
        verify(rippleView).setSensorLocation(faceLocation)
        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
    fun testNullFaceSensorLocationDoesNothing() {
        `when`(authController.faceAuthSensorLocation).thenReturn(null)