diff options
| author | 2024-02-27 05:59:24 +0000 | |
|---|---|---|
| committer | 2024-02-27 05:59:24 +0000 | |
| commit | b9d0add75949a47c8d66842999a9cc975aa3b96a (patch) | |
| tree | 62f91bdf5841918fd88c7324314ace1a38d97673 | |
| parent | 9b2ce0e931c896649fab3cef5dbf6d2a08ce0bfb (diff) | |
| parent | 7552f13b50482a77a2834050e6e2c1cfc05d6a63 (diff) | |
Merge "Retrying face auth when the camera changed while face auth is running" into main
6 files changed, 114 insertions, 7 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt index ae1539ebaf89..59b59bf1e437 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt @@ -50,6 +50,7 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.withContext @@ -64,13 +65,16 @@ interface FacePropertyRepository { /** The current face sensor location in current device rotation */ val sensorLocation: StateFlow<Point?> + + /** The info of current available camera. */ + val cameraInfo: StateFlow<CameraInfo?> } /** Describes a biometric sensor */ data class FaceSensorInfo(val id: Int, val strength: SensorStrength) /** Data class for camera info */ -private data class CameraInfo( +data class CameraInfo( /** The logical id of the camera */ val cameraId: String, /** The physical id of the camera */ @@ -124,7 +128,7 @@ constructor( private val cameraInfoList: List<CameraInfo> = loadCameraInfoList() private var currentPhysicalCameraId: String? = null - private val defaultSensorLocation: StateFlow<Point?> = + override val cameraInfo: StateFlow<CameraInfo?> = ConflatedCallbackFlow.conflatedCallbackFlow { val callback = object : CameraManager.AvailabilityCallback() { @@ -142,7 +146,7 @@ constructor( physicalCameraId == it.cameraPhysicalId } trySendWithFailureLogging( - cameraInfo?.cameraLocation, + cameraInfo, TAG, "Update face sensor location to $cameraInfo." ) @@ -168,7 +172,7 @@ constructor( } currentPhysicalCameraId = cameraInfo?.cameraPhysicalId trySendWithFailureLogging( - cameraInfo?.cameraLocation, + cameraInfo, TAG, "Update face sensor location to $cameraInfo." ) @@ -181,8 +185,16 @@ constructor( .stateIn( applicationScope, started = SharingStarted.WhileSubscribed(), - initialValue = - if (cameraInfoList.isNotEmpty()) cameraInfoList[0].cameraLocation else null + initialValue = if (cameraInfoList.isNotEmpty()) cameraInfoList[0] else null + ) + + private val defaultSensorLocation: StateFlow<Point?> = + cameraInfo + .map { it?.cameraLocation } + .stateIn( + applicationScope, + started = SharingStarted.WhileSubscribed(), + initialValue = null ) override val sensorLocation: StateFlow<Point?> = diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt index cf91e147d1b3..0c9fbc27cc5d 100644 --- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/SystemUIDeviceEntryFaceAuthInteractor.kt @@ -189,6 +189,18 @@ constructor( } } .launchIn(applicationScope) + + facePropertyRepository.cameraInfo + .onEach { + if (it != null && isRunning()) { + repository.cancel() + runFaceAuth( + FaceAuthUiEvent.FACE_AUTH_CAMERA_AVAILABLE_CHANGED, + fallbackToDetect = true + ) + } + } + .launchIn(applicationScope) } private suspend fun resetLockedOutState(currentUserId: Int) { diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt index ee220d5fb713..08a6166fe557 100644 --- a/packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/shared/FaceAuthReason.kt @@ -31,6 +31,7 @@ import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.ALTERNATE import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.ASSISTANT_VISIBILITY_CHANGED import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.AUTH_REQUEST_DURING_CANCELLATION import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.BIOMETRIC_ENABLED +import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.CAMERA_AVAILABLE_CHANGED import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.CAMERA_LAUNCHED import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.DEVICE_WOKEN_UP_ON_REACH_GESTURE import com.android.systemui.deviceentry.shared.InternalFaceAuthReasons.DISPLAY_OFF @@ -130,6 +131,7 @@ private object InternalFaceAuthReasons { "Face auth stopped because non strong biometric allowed changed" const val POSTURE_CHANGED = "Face auth started/stopped due to device posture changed." const val DISPLAY_OFF = "Face auth stopped due to display state OFF." + const val CAMERA_AVAILABLE_CHANGED = "Face auth started due to the available camera changed" } /** @@ -221,7 +223,9 @@ constructor(private val id: Int, val reason: String, var extraInfo: Int = 0) : @UiEvent(doc = NON_STRONG_BIOMETRIC_ALLOWED_CHANGED) FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED(1256, NON_STRONG_BIOMETRIC_ALLOWED_CHANGED), @UiEvent(doc = ACCESSIBILITY_ACTION) FACE_AUTH_ACCESSIBILITY_ACTION(1454, ACCESSIBILITY_ACTION), - @UiEvent(doc = DISPLAY_OFF) FACE_AUTH_DISPLAY_OFF(1461, DISPLAY_OFF); + @UiEvent(doc = DISPLAY_OFF) FACE_AUTH_DISPLAY_OFF(1461, DISPLAY_OFF), + @UiEvent(doc = CAMERA_AVAILABLE_CHANGED) + FACE_AUTH_CAMERA_AVAILABLE_CHANGED(1623, CAMERA_AVAILABLE_CHANGED); override fun getId(): Int = this.id diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt index 9f24d5dfea79..f5e96c93271a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt @@ -237,6 +237,35 @@ class FacePropertyRepositoryImplTest : SysuiTestCase() { } } + @Test + fun providesTheCameraInfoOnCameraAvailableChange() { + testScope.runTest { + runCurrent() + collectLastValue(underTest.cameraInfo) + + verify(faceManager).addAuthenticatorsRegisteredCallback(callback.capture()) + callback.value.onAllAuthenticatorsRegistered( + listOf(createSensorProperties(1, SensorProperties.STRENGTH_STRONG)) + ) + runCurrent() + verify(cameraManager) + .registerAvailabilityCallback(any(Executor::class.java), cameraCallback.capture()) + + cameraCallback.value.onPhysicalCameraAvailable("0", PHYSICAL_CAMERA_ID_OUTER_FRONT) + runCurrent() + + val cameraInfo by collectLastValue(underTest.cameraInfo) + assertThat(cameraInfo) + .isEqualTo( + CameraInfo( + "0", + PHYSICAL_CAMERA_ID_OUTER_FRONT, + Point(OUTER_FRONT_SENSOR_LOCATION[0], OUTER_FRONT_SENSOR_LOCATION[1]) + ) + ) + } + } + private fun createSensorProperties(id: Int, strength: Int) = FaceSensorPropertiesInternal(id, strength, 0, emptyList(), 1, false, false, false) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt index e30dd35d74c1..e1e9fcb2d059 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryFaceAuthInteractorTest.kt @@ -25,6 +25,7 @@ import androidx.test.filters.SmallTest import com.android.keyguard.keyguardUpdateMonitor import com.android.keyguard.trustManager import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.data.repository.CameraInfo import com.android.systemui.biometrics.data.repository.FaceSensorInfo import com.android.systemui.biometrics.data.repository.facePropertyRepository import com.android.systemui.biometrics.shared.model.LockoutMode @@ -490,6 +491,47 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() { verify(trustManager).clearAllBiometricRecognized(eq(BiometricSourceType.FACE), anyInt()) } + @Test + fun faceAuthIsRequestedWhenAuthIsRunningWhileCameraInfoChanged() = + testScope.runTest { + facePropertyRepository.setCameraIno(null) + underTest.start() + + faceAuthRepository.requestAuthenticate( + FaceAuthUiEvent.FACE_AUTH_UPDATED_KEYGUARD_VISIBILITY_CHANGED, + true + ) + facePropertyRepository.setCameraIno(CameraInfo("0", "1", null)) + + runCurrent() + assertThat(faceAuthRepository.runningAuthRequest.value) + .isEqualTo(Pair(FaceAuthUiEvent.FACE_AUTH_CAMERA_AVAILABLE_CHANGED, true)) + } + + @Test + fun faceAuthIsNotRequestedWhenNoAuthRunningWhileCameraInfoChanged() = + testScope.runTest { + facePropertyRepository.setCameraIno(null) + underTest.start() + + facePropertyRepository.setCameraIno(CameraInfo("0", "1", null)) + + runCurrent() + assertThat(faceAuthRepository.runningAuthRequest.value).isNull() + } + + @Test + fun faceAuthIsNotRequestedWhenAuthIsRunningWhileCameraInfoIsNull() = + testScope.runTest { + facePropertyRepository.setCameraIno(null) + underTest.start() + + facePropertyRepository.setCameraIno(null) + + runCurrent() + assertThat(faceAuthRepository.runningAuthRequest.value).isNull() + } + companion object { private const val primaryUserId = 1 private val primaryUser = UserInfo(primaryUserId, "test user", UserInfo.FLAG_PRIMARY) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt index 77f501f550d7..68ef55573dc8 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt @@ -33,6 +33,10 @@ class FakeFacePropertyRepository : FacePropertyRepository { override val sensorLocation: StateFlow<Point?> get() = faceSensorLocation + private val currentCameraInfo = MutableStateFlow<CameraInfo?>(null) + override val cameraInfo: StateFlow<CameraInfo?> + get() = currentCameraInfo + fun setLockoutMode(userId: Int, mode: LockoutMode) { lockoutModesForUser[userId] = mode } @@ -47,4 +51,8 @@ class FakeFacePropertyRepository : FacePropertyRepository { fun setSensorLocation(value: Point?) { faceSensorLocation.value = value } + + fun setCameraIno(value: CameraInfo?) { + currentCameraInfo.value = value + } } |