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

Commit ab3b6ef5 authored by Chandru S's avatar Chandru S Committed by Automerger Merge Worker
Browse files

Merge "Add onBiometricAuthenticated in BiometricUnlockController to control...

Merge "Add onBiometricAuthenticated in BiometricUnlockController to control when the auth ripple is shown" into udc-dev am: 9d5a85ae

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22461150



Change-Id: I40b10936ebd78d04ba1b7c7dbe6bbf2fd31ab8d9
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents c7d3c839 9d5a85ae
Loading
Loading
Loading
Loading
+24 −10
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.systemui.animation.Interpolators
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.CircleReveal
import com.android.systemui.statusbar.LiftReveal
@@ -43,7 +44,6 @@ import com.android.systemui.statusbar.commandline.Command
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -52,7 +52,7 @@ import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Provider

/***
/**
 * Controls two ripple effects:
 *   1. Unlocked ripple: shows when authentication is successful
 *   2. UDFPS dwell ripple: shows when the user has their finger down on the UDFPS area and reacts
@@ -71,14 +71,15 @@ class AuthRippleController @Inject constructor(
    private val wakefulnessLifecycle: WakefulnessLifecycle,
    private val commandRegistry: CommandRegistry,
    private val notificationShadeWindowController: NotificationShadeWindowController,
    private val bypassController: KeyguardBypassController,
    private val biometricUnlockController: BiometricUnlockController,
    private val udfpsControllerProvider: Provider<UdfpsController>,
    private val statusBarStateController: StatusBarStateController,
    private val featureFlags: FeatureFlags,
    private val logger: KeyguardLogger,
    private val biometricUnlockController: BiometricUnlockController,
    rippleView: AuthRippleView?
) : ViewController<AuthRippleView>(rippleView), KeyguardStateController.Callback,
) :
    ViewController<AuthRippleView>(rippleView),
    KeyguardStateController.Callback,
    WakefulnessLifecycle.Observer {

    @VisibleForTesting
@@ -102,6 +103,22 @@ class AuthRippleController @Inject constructor(
        keyguardStateController.addCallback(this)
        wakefulnessLifecycle.addObserver(this)
        commandRegistry.registerCommand("auth-ripple") { AuthRippleCommand() }
        biometricUnlockController.addListener(biometricModeListener)
    }

    private val biometricModeListener =
        object : BiometricUnlockController.BiometricUnlockEventsListener {
            override fun onBiometricUnlockedWithKeyguardDismissal(
                    biometricSourceType: BiometricSourceType?
            ) {
                if (biometricSourceType != null) {
                    showUnlockRipple(biometricSourceType)
                } else {
                    logger.log(TAG,
                            LogLevel.ERROR,
                            "Unexpected scenario where biometricSourceType is null")
                }
            }
        }

    @VisibleForTesting
@@ -113,6 +130,7 @@ class AuthRippleController @Inject constructor(
        keyguardStateController.removeCallback(this)
        wakefulnessLifecycle.removeObserver(this)
        commandRegistry.unregisterCommand("auth-ripple")
        biometricUnlockController.removeListener(biometricModeListener)

        notificationShadeWindowController.setForcePluginOpen(false, this)
    }
@@ -143,9 +161,6 @@ class AuthRippleController @Inject constructor(
                showUnlockedRipple()
            }
        } else if (biometricSourceType == BiometricSourceType.FACE) {
            if (!bypassController.canBypass() && !authController.isUdfpsFingerDown) {
                return
            }
            faceSensorLocation?.let {
                mView.setSensorLocation(it)
                circleReveal = CircleReveal(
@@ -267,7 +282,6 @@ class AuthRippleController @Inject constructor(
                if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
                    mView.fadeDwellRipple()
                }
                showUnlockRipple(biometricSourceType)
            }

        override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType) {
+3 −3
Original line number Diff line number Diff line
@@ -471,7 +471,7 @@ constructor(
        }

        val callback =
            object : BiometricUnlockController.BiometricModeListener {
            object : BiometricUnlockController.BiometricUnlockEventsListener {
                override fun onModeChanged(@WakeAndUnlockMode mode: Int) {
                    dispatchUpdate()
                }
@@ -481,10 +481,10 @@ constructor(
                }
            }

        biometricUnlockController.addBiometricModeListener(callback)
        biometricUnlockController.addListener(callback)
        dispatchUpdate()

        awaitClose { biometricUnlockController.removeBiometricModeListener(callback) }
        awaitClose { biometricUnlockController.removeListener(callback) }
    }

    override val wakefulness: Flow<WakefulnessModel> = conflatedCallbackFlow {
+31 −12
Original line number Diff line number Diff line
@@ -163,7 +163,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
    private PendingAuthenticated mPendingAuthenticated = null;
    private boolean mHasScreenTurnedOnSinceAuthenticating;
    private boolean mFadedAwayAfterWakeAndUnlock;
    private Set<BiometricModeListener> mBiometricModeListeners = new HashSet<>();
    private Set<BiometricUnlockEventsListener> mBiometricUnlockEventsListeners = new HashSet<>();

    private final MetricsLogger mMetricsLogger;
    private final AuthController mAuthController;
@@ -314,14 +314,14 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
        mKeyguardViewController = keyguardViewController;
    }

    /** Adds a {@link BiometricModeListener}. */
    public void addBiometricModeListener(BiometricModeListener listener) {
        mBiometricModeListeners.add(listener);
    /** Adds a {@link BiometricUnlockEventsListener}. */
    public void addListener(BiometricUnlockEventsListener listener) {
        mBiometricUnlockEventsListeners.add(listener);
    }

    /** Removes a {@link BiometricModeListener}. */
    public void removeBiometricModeListener(BiometricModeListener listener) {
        mBiometricModeListeners.remove(listener);
    /** Removes a {@link BiometricUnlockEventsListener}. */
    public void removeListener(BiometricUnlockEventsListener listener) {
        mBiometricUnlockEventsListeners.remove(listener);
    }

    private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() {
@@ -387,7 +387,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
    @Override
    public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
            boolean isStrongBiometric) {
        Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
        Trace.beginSection("BiometricUnlockController#onBiometricUnlocked");
        if (mUpdateMonitor.isGoingToSleep()) {
            mLogger.deferringAuthenticationDueToSleep(userId,
                    biometricSourceType,
@@ -411,10 +411,15 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
            mKeyguardViewMediator.userActivity();
            startWakeAndUnlock(biometricSourceType, isStrongBiometric);
        } else {
            mLogger.d("onBiometricAuthenticated aborted by bypass controller");
            mLogger.d("onBiometricUnlocked aborted by bypass controller");
        }
    }

    /**
     * Wake and unlock the device in response to successful authentication using biometrics.
     * @param biometricSourceType Biometric source that was used to authenticate.
     * @param isStrongBiometric
     */
    public void startWakeAndUnlock(BiometricSourceType biometricSourceType,
                                   boolean isStrongBiometric) {
        int mode = calculateMode(biometricSourceType, isStrongBiometric);
@@ -422,6 +427,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
                || mode == MODE_WAKE_AND_UNLOCK_PULSING || mode == MODE_UNLOCK_COLLAPSING
                || mode == MODE_WAKE_AND_UNLOCK_FROM_DREAM || mode == MODE_DISMISS_BOUNCER) {
            vibrateSuccess(biometricSourceType);
            onBiometricUnlockedWithKeyguardDismissal(biometricSourceType);
        }
        startWakeAndUnlock(mode);
    }
@@ -502,11 +508,17 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
    }

    private void onModeChanged(@WakeAndUnlockMode int mode) {
        for (BiometricModeListener listener : mBiometricModeListeners) {
        for (BiometricUnlockEventsListener listener : mBiometricUnlockEventsListeners) {
            listener.onModeChanged(mode);
        }
    }

    private void onBiometricUnlockedWithKeyguardDismissal(BiometricSourceType biometricSourceType) {
        for (BiometricUnlockEventsListener listener : mBiometricUnlockEventsListeners) {
            listener.onBiometricUnlockedWithKeyguardDismissal(biometricSourceType);
        }
    }

    public boolean hasPendingAuthentication() {
        return mPendingAuthenticated != null
                && mUpdateMonitor
@@ -777,7 +789,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
        mMode = MODE_NONE;
        mBiometricType = null;
        mNotificationShadeWindowController.setForceDozeBrightness(false);
        for (BiometricModeListener listener : mBiometricModeListeners) {
        for (BiometricUnlockEventsListener listener : mBiometricUnlockEventsListeners) {
            listener.onResetMode();
        }
        mNumConsecutiveFpFailures = 0;
@@ -895,10 +907,17 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
    }

    /** An interface to interact with the {@link BiometricUnlockController}. */
    public interface BiometricModeListener {
    public interface BiometricUnlockEventsListener {
        /** Called when {@code mMode} is reset to {@link #MODE_NONE}. */
        default void onResetMode() {}
        /** Called when {@code mMode} has changed in {@link #startWakeAndUnlock(int)}. */
        default void onModeChanged(@WakeAndUnlockMode int mode) {}

        /**
         * Called when the device is unlocked successfully using biometrics with the keyguard also
         * being dismissed.
         */
        default void onBiometricUnlockedWithKeyguardDismissal(
                BiometricSourceType biometricSourceType) { }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -1675,8 +1675,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
        mStatusBarStateController.addCallback(mStateListener,
                SysuiStatusBarStateController.RANK_STATUS_BAR);
        mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
        mBiometricUnlockController.addBiometricModeListener(
                new BiometricUnlockController.BiometricModeListener() {
        mBiometricUnlockController.addListener(
                new BiometricUnlockController.BiometricUnlockEventsListener() {
                    @Override
                    public void onResetMode() {
                        setWakeAndUnlocking(false);
+28 −65
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import com.android.systemui.statusbar.NotificationShadeWindowController
import com.android.systemui.statusbar.commandline.CommandRegistry
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.leak.RotationUtils
@@ -50,6 +49,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
import org.mockito.Mockito.never
@@ -73,16 +73,28 @@ class AuthRippleControllerTest : SysuiTestCase() {
    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
    @Mock private lateinit var authController: AuthController
    @Mock private lateinit var keyguardStateController: KeyguardStateController
    @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
    @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
    @Mock private lateinit var bypassController: KeyguardBypassController
    @Mock private lateinit var biometricUnlockController: BiometricUnlockController
    @Mock private lateinit var udfpsControllerProvider: Provider<UdfpsController>
    @Mock private lateinit var udfpsController: UdfpsController
    @Mock private lateinit var statusBarStateController: StatusBarStateController
    @Mock private lateinit var featureFlags: FeatureFlags
    @Mock private lateinit var lightRevealScrim: LightRevealScrim
    @Mock private lateinit var fpSensorProp: FingerprintSensorPropertiesInternal
    @Mock
    private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
    @Mock
    private lateinit var notificationShadeWindowController: NotificationShadeWindowController
    @Mock
    private lateinit var biometricUnlockController: BiometricUnlockController
    @Mock
    private lateinit var udfpsControllerProvider: Provider<UdfpsController>
    @Mock
    private lateinit var udfpsController: UdfpsController
    @Mock
    private lateinit var statusBarStateController: StatusBarStateController
    @Mock
    private lateinit var featureFlags: FeatureFlags
    @Mock
    private lateinit var lightRevealScrim: LightRevealScrim
    @Mock
    private lateinit var fpSensorProp: FingerprintSensorPropertiesInternal

    @Captor
    private lateinit var biometricUnlockListener:
            ArgumentCaptor<BiometricUnlockController.BiometricUnlockEventsListener>

    @Before
    fun setUp() {
@@ -106,13 +118,12 @@ class AuthRippleControllerTest : SysuiTestCase() {
            wakefulnessLifecycle,
            commandRegistry,
            notificationShadeWindowController,
            bypassController,
            biometricUnlockController,
            udfpsControllerProvider,
            statusBarStateController,
            featureFlags,
            KeyguardLogger(logcatLogBuffer(AuthRippleController.TAG)),
            rippleView
            biometricUnlockController,
            rippleView,
        )
        controller.init()
        `when`(mCentralSurfaces.lightRevealScrim).thenReturn(lightRevealScrim)
@@ -134,12 +145,9 @@ class AuthRippleControllerTest : SysuiTestCase() {
                eq(BiometricSourceType.FINGERPRINT))).thenReturn(true)

        // 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 */)
        verify(biometricUnlockController).addListener(biometricUnlockListener.capture())
        biometricUnlockListener.value
                .onBiometricUnlockedWithKeyguardDismissal(BiometricSourceType.FINGERPRINT)

        // THEN update sensor location and show ripple
        verify(rippleView).setFingerprintSensorLocation(fpsLocation, 0f)
@@ -190,51 +198,6 @@ class AuthRippleControllerTest : SysuiTestCase() {
        verify(rippleView, never()).startUnlockedRipple(any())
    }

    @Test
    fun testFaceTriggerBypassEnabled_Ripple() {
        // GIVEN face auth sensor exists, keyguard is showing & unlocking with face is allowed
        val faceLocation = Point(5, 5)
        `when`(authController.faceSensorLocation).thenReturn(faceLocation)
        controller.onViewAttached()

        `when`(keyguardStateController.isShowing).thenReturn(true)
        `when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
                BiometricSourceType.FACE)).thenReturn(true)

        // 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).startUnlockedRipple(any())
    }

    @Test
    fun testFaceTriggerNonBypass_NoRipple() {
        // GIVEN face auth sensor exists
        val faceLocation = Point(5, 5)
        `when`(authController.faceSensorLocation).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()).startUnlockedRipple(any())
    }

    @Test
    fun testNullFaceSensorLocationDoesNothing() {
        `when`(authController.faceSensorLocation).thenReturn(null)
Loading