summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chandru S <chandruis@google.com> 2023-03-28 15:51:44 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-03-28 15:51:44 +0000
commit8b8848020de152d2a88298ff7b195e70fde8c6b3 (patch)
tree1728a1c9705263d9a0549fceb1afbb095e607d7f
parent2835276515a0b9cc53a6b0435d91f6fb35e4bed5 (diff)
parente6462e402f5b9dead837304c34d8236ab3b6045e (diff)
Merge "Add FP running state and FP sensor type information to DeviceEntryFPAuthRepository" into udc-dev
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt46
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt72
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt10
6 files changed, 158 insertions, 17 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 1de3ddd7c1dd..30321f75dd73 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -2476,8 +2476,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
* not enrolled udfps. This may be false if called before onAllAuthenticatorsRegistered.
*/
public boolean isUdfpsSupported() {
- return mAuthController.getUdfpsProps() != null
- && !mAuthController.getUdfpsProps().isEmpty();
+ return mAuthController.isUdfpsSupported();
}
/**
@@ -2492,8 +2491,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
* not enrolled sfps. This may be false if called before onAllAuthenticatorsRegistered.
*/
public boolean isSfpsSupported() {
- return mAuthController.getSfpsProps() != null
- && !mAuthController.getSfpsProps().isEmpty();
+ return mAuthController.isSfpsSupported();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index 705fc8c1a8fd..92344dbbfe15 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -984,6 +984,36 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
return mSidefpsProps;
}
+ /**
+ * @return true if udfps HW is supported on this device. Can return true even if the user has
+ * not enrolled udfps. This may be false if called before onAllAuthenticatorsRegistered.
+ */
+ public boolean isUdfpsSupported() {
+ return getUdfpsProps() != null && !getUdfpsProps().isEmpty();
+ }
+
+ /**
+ * @return true if sfps HW is supported on this device. Can return true even if the user has
+ * not enrolled sfps. This may be false if called before onAllAuthenticatorsRegistered.
+ */
+ public boolean isSfpsSupported() {
+ return getSfpsProps() != null && !getSfpsProps().isEmpty();
+ }
+
+ /**
+ * @return true if rear fps HW is supported on this device. Can return true even if the user has
+ * not enrolled sfps. This may be false if called before onAllAuthenticatorsRegistered.
+ */
+ public boolean isRearFpsSupported() {
+ for (FingerprintSensorPropertiesInternal prop: mFpProps) {
+ if (prop.sensorType == TYPE_REAR) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
private String getErrorString(@Modality int modality, int error, int vendorCode) {
switch (modality) {
case TYPE_FACE:
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
index 7c466845a923..4fa56ee8e4d2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepository.kt
@@ -20,6 +20,7 @@ import android.hardware.biometrics.BiometricSourceType
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.Dumpable
+import com.android.systemui.biometrics.AuthController
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import com.android.systemui.dagger.SysUISingleton
@@ -29,6 +30,7 @@ import java.io.PrintWriter
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.stateIn
@@ -37,6 +39,17 @@ import kotlinx.coroutines.flow.stateIn
interface DeviceEntryFingerprintAuthRepository {
/** Whether the device entry fingerprint auth is locked out. */
val isLockedOut: StateFlow<Boolean>
+
+ /**
+ * Whether the fingerprint sensor is currently listening, this doesn't mean that the user is
+ * actively authenticating.
+ */
+ val isRunning: Flow<Boolean>
+
+ /**
+ * Fingerprint sensor type present on the device, null if fingerprint sensor is not available.
+ */
+ val availableFpSensorType: BiometricType?
}
/**
@@ -50,6 +63,7 @@ interface DeviceEntryFingerprintAuthRepository {
class DeviceEntryFingerprintAuthRepositoryImpl
@Inject
constructor(
+ val authController: AuthController,
val keyguardUpdateMonitor: KeyguardUpdateMonitor,
@Application scope: CoroutineScope,
dumpManager: DumpManager,
@@ -63,6 +77,12 @@ constructor(
pw.println("isLockedOut=${isLockedOut.value}")
}
+ override val availableFpSensorType: BiometricType?
+ get() =
+ if (authController.isUdfpsSupported) BiometricType.UNDER_DISPLAY_FINGERPRINT
+ else if (authController.isSfpsSupported) BiometricType.SIDE_FINGERPRINT
+ else if (authController.isRearFpsSupported) BiometricType.REAR_FINGERPRINT else null
+
override val isLockedOut: StateFlow<Boolean> =
conflatedCallbackFlow {
val sendLockoutUpdate =
@@ -89,6 +109,32 @@ constructor(
}
.stateIn(scope, started = SharingStarted.Eagerly, initialValue = false)
+ override val isRunning: Flow<Boolean>
+ get() = conflatedCallbackFlow {
+ val callback =
+ object : KeyguardUpdateMonitorCallback() {
+ override fun onBiometricRunningStateChanged(
+ running: Boolean,
+ biometricSourceType: BiometricSourceType?
+ ) {
+ if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
+ trySendWithFailureLogging(
+ running,
+ TAG,
+ "Fingerprint running state changed"
+ )
+ }
+ }
+ }
+ keyguardUpdateMonitor.registerCallback(callback)
+ trySendWithFailureLogging(
+ keyguardUpdateMonitor.isFingerprintDetectionRunning,
+ TAG,
+ "Initial fingerprint running state"
+ )
+ awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
+ }
+
companion object {
const val TAG = "DeviceEntryFingerprintAuthRepositoryImpl"
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index a8b42544fd87..4ed4e20e7e1a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -1360,9 +1360,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
public void startsListeningForSfps_whenKeyguardIsVisible_ifRequireInteractiveToAuthEnabled()
throws RemoteException {
// SFPS supported and enrolled
- final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
- props.add(newFingerprintSensorPropertiesInternal(TYPE_POWER_BUTTON));
- when(mAuthController.getSfpsProps()).thenReturn(props);
+ when(mAuthController.isSfpsSupported()).thenReturn(true);
when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
// WHEN require interactive to auth is disabled, and keyguard is not awake
@@ -1401,9 +1399,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
public void notListeningForSfps_whenGoingToSleep_ifRequireInteractiveToAuthEnabled()
throws RemoteException {
// GIVEN SFPS supported and enrolled
- final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
- props.add(newFingerprintSensorPropertiesInternal(TYPE_POWER_BUTTON));
- when(mAuthController.getSfpsProps()).thenReturn(props);
+ when(mAuthController.isSfpsSupported()).thenReturn(true);
when(mAuthController.isSfpsEnrolled(anyInt())).thenReturn(true);
// GIVEN Preconditions for sfps auth to run
@@ -2843,8 +2839,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
private void givenUdfpsSupported() {
- Assert.assertFalse(mFingerprintSensorProperties.isEmpty());
- when(mAuthController.getUdfpsProps()).thenReturn(mFingerprintSensorProperties);
+ when(mAuthController.isUdfpsSupported()).thenReturn(true);
Assert.assertTrue(mKeyguardUpdateMonitor.isUdfpsSupported());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
index 0519a44d55ba..70f766f719e9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFingerprintAuthRepositoryTest.kt
@@ -21,6 +21,7 @@ import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.AuthController
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.dump.DumpManager
import com.android.systemui.util.mockito.whenever
@@ -37,6 +38,7 @@ import org.junit.runners.JUnit4
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
+import org.mockito.Mockito.atLeastOnce
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -46,7 +48,9 @@ import org.mockito.MockitoAnnotations
class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var dumpManager: DumpManager
- @Captor private lateinit var callbackCaptor: ArgumentCaptor<KeyguardUpdateMonitorCallback>
+ @Mock private lateinit var authController: AuthController
+ @Captor
+ private lateinit var updateMonitorCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
private lateinit var testScope: TestScope
@@ -59,6 +63,7 @@ class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
underTest =
DeviceEntryFingerprintAuthRepositoryImpl(
+ authController,
keyguardUpdateMonitor,
testScope.backgroundScope,
dumpManager,
@@ -67,7 +72,7 @@ class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
@After
fun tearDown() {
- verify(keyguardUpdateMonitor).removeCallback(callbackCaptor.value)
+ // verify(keyguardUpdateMonitor).removeCallback(updateMonitorCallback.value)
}
@Test
@@ -76,8 +81,8 @@ class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
val isLockedOutValue = collectLastValue(underTest.isLockedOut)
runCurrent()
- verify(keyguardUpdateMonitor).registerCallback(callbackCaptor.capture())
- val callback = callbackCaptor.value
+ verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallback.capture())
+ val callback = updateMonitorCallback.value
whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(true)
callback.onLockedOutStateChanged(BiometricSourceType.FACE)
@@ -90,4 +95,63 @@ class DeviceEntryFingerprintAuthRepositoryTest : SysuiTestCase() {
callback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT)
assertThat(isLockedOutValue()).isFalse()
}
+
+ @Test
+ fun fpRunningStateIsPropagated() =
+ testScope.runTest {
+ val isRunning = collectLastValue(underTest.isRunning)
+ whenever(keyguardUpdateMonitor.isFingerprintDetectionRunning).thenReturn(true)
+
+ // Initial value is available
+ assertThat(isRunning()).isTrue()
+
+ verify(keyguardUpdateMonitor, atLeastOnce())
+ .registerCallback(updateMonitorCallback.capture())
+ invokeOnCallback {
+ it.onBiometricRunningStateChanged(false, BiometricSourceType.FINGERPRINT)
+ }
+
+ assertThat(isRunning()).isFalse()
+
+ invokeOnCallback { it.onBiometricRunningStateChanged(true, BiometricSourceType.FACE) }
+
+ assertThat(isRunning()).isFalse()
+
+ updateMonitorCallback.value.onBiometricRunningStateChanged(
+ true,
+ BiometricSourceType.FINGERPRINT
+ )
+ assertThat(isRunning()).isTrue()
+ }
+
+ private fun invokeOnCallback(action: (KeyguardUpdateMonitorCallback) -> Unit) {
+ updateMonitorCallback.allValues.forEach { action(it) }
+ }
+
+ @Test
+ fun enabledFingerprintTypeProvidesTheCorrectOutput() =
+ testScope.runTest {
+ whenever(authController.isSfpsSupported).thenReturn(true)
+ whenever(authController.isUdfpsSupported).thenReturn(false)
+ whenever(authController.isRearFpsSupported).thenReturn(false)
+
+ assertThat(underTest.availableFpSensorType).isEqualTo(BiometricType.SIDE_FINGERPRINT)
+
+ whenever(authController.isSfpsSupported).thenReturn(false)
+ whenever(authController.isUdfpsSupported).thenReturn(true)
+ whenever(authController.isRearFpsSupported).thenReturn(false)
+
+ assertThat(underTest.availableFpSensorType)
+ .isEqualTo(BiometricType.UNDER_DISPLAY_FINGERPRINT)
+
+ whenever(authController.isSfpsSupported).thenReturn(false)
+ whenever(authController.isUdfpsSupported).thenReturn(false)
+ whenever(authController.isRearFpsSupported).thenReturn(true)
+
+ assertThat(underTest.availableFpSensorType).isEqualTo(BiometricType.REAR_FINGERPRINT)
+
+ whenever(authController.isRearFpsSupported).thenReturn(false)
+
+ assertThat(underTest.availableFpSensorType).isNull()
+ }
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt
index 5641832b6ae2..00b1a401ac79 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeDeviceEntryFingerprintAuthRepository.kt
@@ -17,14 +17,22 @@
package com.android.systemui.keyguard.data.repository
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class FakeDeviceEntryFingerprintAuthRepository : DeviceEntryFingerprintAuthRepository {
- private val _isLockedOut = MutableStateFlow<Boolean>(false)
+ private val _isLockedOut = MutableStateFlow(false)
override val isLockedOut: StateFlow<Boolean> = _isLockedOut.asStateFlow()
+ private val _isRunning = MutableStateFlow(false)
+ override val isRunning: Flow<Boolean>
+ get() = _isRunning
+
+ override val availableFpSensorType: BiometricType?
+ get() = null
+
fun setLockedOut(lockedOut: Boolean) {
_isLockedOut.value = lockedOut
}