Loading packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt +50 −50 Original line number Diff line number Diff line Loading @@ -16,13 +16,19 @@ package com.android.systemui.biometrics.data.repository import android.Manifest.permission.USE_BIOMETRIC_INTERNAL import android.annotation.RequiresPermission import android.hardware.biometrics.ComponentInfoInternal import android.hardware.biometrics.SensorLocationInternal import android.hardware.biometrics.SensorProperties import android.hardware.fingerprint.FingerprintManager import android.hardware.fingerprint.FingerprintSensorProperties import android.hardware.fingerprint.FingerprintSensorPropertiesInternal import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback import com.android.systemui.biometrics.shared.model.FingerprintSensorType import com.android.systemui.biometrics.shared.model.SensorStrength import com.android.systemui.biometrics.shared.model.toSensorStrength import com.android.systemui.biometrics.shared.model.toSensorType import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton Loading @@ -31,11 +37,10 @@ import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn /** * A repository for the global state of FingerprintProperty. Loading @@ -44,22 +49,17 @@ import kotlinx.coroutines.flow.shareIn */ interface FingerprintPropertyRepository { /** * If the repository is initialized or not. Other properties are defaults until this is true. */ val isInitialized: Flow<Boolean> /** The id of fingerprint sensor. */ val sensorId: StateFlow<Int> val sensorId: Flow<Int> /** The security strength of sensor (convenience, weak, strong). */ val strength: StateFlow<SensorStrength> val strength: Flow<SensorStrength> /** The types of fingerprint sensor (rear, ultrasonic, optical, etc.). */ val sensorType: StateFlow<FingerprintSensorType> val sensorType: Flow<FingerprintSensorType> /** The sensor location relative to each physical display. */ val sensorLocations: StateFlow<Map<String, SensorLocationInternal>> val sensorLocations: Flow<Map<String, SensorLocationInternal>> } @SysUISingleton Loading @@ -70,64 +70,64 @@ constructor( private val fingerprintManager: FingerprintManager?, ) : FingerprintPropertyRepository { override val isInitialized: Flow<Boolean> = @RequiresPermission(USE_BIOMETRIC_INTERNAL) private val props: StateFlow<FingerprintSensorPropertiesInternal> = conflatedCallbackFlow { val callback = object : IFingerprintAuthenticatorsRegisteredCallback.Stub() { override fun onAllAuthenticatorsRegistered( sensors: List<FingerprintSensorPropertiesInternal> ) { if (sensors.isNotEmpty()) { setProperties(sensors[0]) trySendWithFailureLogging(true, TAG, "initialize properties") if (sensors.isEmpty()) { trySendWithFailureLogging( DEFAULT_PROPS, TAG, "no registered sensors, use default props" ) } else { trySendWithFailureLogging( sensors[0], TAG, "update properties on authenticators registered" ) } } } fingerprintManager?.addAuthenticatorsRegisteredCallback(callback) trySendWithFailureLogging(false, TAG, "initial value defaulting to false") awaitClose {} } .shareIn(scope = applicationScope, started = SharingStarted.Eagerly, replay = 1) private val _sensorId: MutableStateFlow<Int> = MutableStateFlow(-1) override val sensorId: StateFlow<Int> = _sensorId.asStateFlow() .stateIn( applicationScope, started = SharingStarted.Eagerly, initialValue = DEFAULT_PROPS, ) private val _strength: MutableStateFlow<SensorStrength> = MutableStateFlow(SensorStrength.CONVENIENCE) override val strength = _strength.asStateFlow() override val sensorId: Flow<Int> = props.map { it.sensorId } private val _sensorType: MutableStateFlow<FingerprintSensorType> = MutableStateFlow(FingerprintSensorType.UNKNOWN) override val sensorType = _sensorType.asStateFlow() override val strength: Flow<SensorStrength> = props.map { it.sensorStrength.toSensorStrength() } private val _sensorLocations: MutableStateFlow<Map<String, SensorLocationInternal>> = MutableStateFlow(mapOf("" to SensorLocationInternal.DEFAULT)) override val sensorLocations: StateFlow<Map<String, SensorLocationInternal>> = _sensorLocations.asStateFlow() override val sensorType: Flow<FingerprintSensorType> = props.map { it.sensorType.toSensorType() } private fun setProperties(prop: FingerprintSensorPropertiesInternal) { _sensorId.value = prop.sensorId _strength.value = prop.sensorStrength.toSensorStrength() _sensorType.value = sensorTypeIntToObject(prop.sensorType) _sensorLocations.value = prop.allLocations.associateBy { sensorLocationInternal -> override val sensorLocations: Flow<Map<String, SensorLocationInternal>> = props.map { it.allLocations.associateBy { sensorLocationInternal -> sensorLocationInternal.displayId } } companion object { private const val TAG = "FingerprintPropertyRepositoryImpl" } } private fun sensorTypeIntToObject(value: Int): FingerprintSensorType { return when (value) { 0 -> FingerprintSensorType.UNKNOWN 1 -> FingerprintSensorType.REAR 2 -> FingerprintSensorType.UDFPS_ULTRASONIC 3 -> FingerprintSensorType.UDFPS_OPTICAL 4 -> FingerprintSensorType.POWER_BUTTON 5 -> FingerprintSensorType.HOME_BUTTON else -> throw IllegalArgumentException("Invalid SensorType value: $value") private val DEFAULT_PROPS = FingerprintSensorPropertiesInternal( -1 /* sensorId */, SensorProperties.STRENGTH_CONVENIENCE, 0 /* maxEnrollmentsPerUser */, listOf<ComponentInfoInternal>(), FingerprintSensorProperties.TYPE_UNKNOWN, false /* halControlsIllumination */, true /* resetLockoutRequiresHardwareAuthToken */, listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT) ) } } packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt +3 −5 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import com.android.systemui.biometrics.shared.model.PromptKind import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map Loading Loading @@ -69,7 +68,7 @@ interface PromptSelectorInteractor { val isConfirmationRequired: Flow<Boolean> /** Fingerprint sensor type */ val sensorType: StateFlow<FingerprintSensorType> val sensorType: Flow<FingerprintSensorType> /** Use biometrics for authentication. */ fun useBiometricsForAuthentication( Loading @@ -95,7 +94,7 @@ interface PromptSelectorInteractor { class PromptSelectorInteractorImpl @Inject constructor( private val fingerprintPropertyRepository: FingerprintPropertyRepository, fingerprintPropertyRepository: FingerprintPropertyRepository, private val promptRepository: PromptRepository, lockPatternUtils: LockPatternUtils, ) : PromptSelectorInteractor { Loading Loading @@ -147,8 +146,7 @@ constructor( } } override val sensorType: StateFlow<FingerprintSensorType> = fingerprintPropertyRepository.sensorType override val sensorType: Flow<FingerprintSensorType> = fingerprintPropertyRepository.sensorType override fun useBiometricsForAuthentication( promptInfo: PromptInfo, Loading packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractor.kt +22 −11 Original line number Diff line number Diff line Loading @@ -17,32 +17,43 @@ package com.android.systemui.biometrics.domain.interactor import android.hardware.biometrics.SensorLocationInternal import android.util.Log import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine /** Business logic for SideFps overlay offsets. */ interface SideFpsOverlayInteractor { /** Get the corresponding offsets based on different displayId. */ fun getOverlayOffsets(displayId: String): SensorLocationInternal /** The displayId of the current display. */ val displayId: Flow<String> /** Overlay offsets corresponding to given displayId. */ val overlayOffsets: Flow<SensorLocationInternal> /** Called on display changes, used to keep the display state in sync */ fun onDisplayChanged(displayId: String) } @SysUISingleton class SideFpsOverlayInteractorImpl @Inject constructor(private val fingerprintPropertyRepository: FingerprintPropertyRepository) : constructor(fingerprintPropertyRepository: FingerprintPropertyRepository) : SideFpsOverlayInteractor { override fun getOverlayOffsets(displayId: String): SensorLocationInternal { val offsets = fingerprintPropertyRepository.sensorLocations.value return if (offsets.containsKey(displayId)) { offsets[displayId]!! } else { Log.w(TAG, "No location specified for display: $displayId") offsets[""]!! private val _displayId: MutableStateFlow<String> = MutableStateFlow("") override val displayId: Flow<String> = _displayId.asStateFlow() override val overlayOffsets: Flow<SensorLocationInternal> = combine(displayId, fingerprintPropertyRepository.sensorLocations) { displayId, offsets -> offsets[displayId] ?: SensorLocationInternal.DEFAULT } override fun onDisplayChanged(displayId: String) { _displayId.value = displayId } companion object { Loading packages/SystemUI/src/com/android/systemui/biometrics/shared/model/FingerprintSensorType.kt +12 −0 Original line number Diff line number Diff line Loading @@ -27,3 +27,15 @@ enum class FingerprintSensorType { POWER_BUTTON, HOME_BUTTON, } /** Convert [this] to corresponding [FingerprintSensorType] */ fun Int.toSensorType(): FingerprintSensorType = when (this) { FingerprintSensorProperties.TYPE_UNKNOWN -> FingerprintSensorType.UNKNOWN FingerprintSensorProperties.TYPE_REAR -> FingerprintSensorType.REAR FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC -> FingerprintSensorType.UDFPS_ULTRASONIC FingerprintSensorProperties.TYPE_UDFPS_OPTICAL -> FingerprintSensorType.UDFPS_OPTICAL FingerprintSensorProperties.TYPE_POWER_BUTTON -> FingerprintSensorType.POWER_BUTTON FingerprintSensorProperties.TYPE_HOME_BUTTON -> FingerprintSensorType.HOME_BUTTON else -> throw IllegalArgumentException("Invalid SensorType value: $this") } packages/SystemUI/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt +3 −3 Original line number Diff line number Diff line Loading @@ -28,8 +28,8 @@ enum class SensorStrength { /** Convert [this] to corresponding [SensorStrength] */ fun Int.toSensorStrength(): SensorStrength = when (this) { 0 -> SensorStrength.CONVENIENCE 1 -> SensorStrength.WEAK 2 -> SensorStrength.STRONG SensorProperties.STRENGTH_CONVENIENCE -> SensorStrength.CONVENIENCE SensorProperties.STRENGTH_WEAK -> SensorStrength.WEAK SensorProperties.STRENGTH_STRONG -> SensorStrength.STRONG else -> throw IllegalArgumentException("Invalid SensorStrength value: $this") } Loading
packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FingerprintPropertyRepository.kt +50 −50 Original line number Diff line number Diff line Loading @@ -16,13 +16,19 @@ package com.android.systemui.biometrics.data.repository import android.Manifest.permission.USE_BIOMETRIC_INTERNAL import android.annotation.RequiresPermission import android.hardware.biometrics.ComponentInfoInternal import android.hardware.biometrics.SensorLocationInternal import android.hardware.biometrics.SensorProperties import android.hardware.fingerprint.FingerprintManager import android.hardware.fingerprint.FingerprintSensorProperties import android.hardware.fingerprint.FingerprintSensorPropertiesInternal import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback import com.android.systemui.biometrics.shared.model.FingerprintSensorType import com.android.systemui.biometrics.shared.model.SensorStrength import com.android.systemui.biometrics.shared.model.toSensorStrength import com.android.systemui.biometrics.shared.model.toSensorType import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.dagger.SysUISingleton Loading @@ -31,11 +37,10 @@ import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.shareIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn /** * A repository for the global state of FingerprintProperty. Loading @@ -44,22 +49,17 @@ import kotlinx.coroutines.flow.shareIn */ interface FingerprintPropertyRepository { /** * If the repository is initialized or not. Other properties are defaults until this is true. */ val isInitialized: Flow<Boolean> /** The id of fingerprint sensor. */ val sensorId: StateFlow<Int> val sensorId: Flow<Int> /** The security strength of sensor (convenience, weak, strong). */ val strength: StateFlow<SensorStrength> val strength: Flow<SensorStrength> /** The types of fingerprint sensor (rear, ultrasonic, optical, etc.). */ val sensorType: StateFlow<FingerprintSensorType> val sensorType: Flow<FingerprintSensorType> /** The sensor location relative to each physical display. */ val sensorLocations: StateFlow<Map<String, SensorLocationInternal>> val sensorLocations: Flow<Map<String, SensorLocationInternal>> } @SysUISingleton Loading @@ -70,64 +70,64 @@ constructor( private val fingerprintManager: FingerprintManager?, ) : FingerprintPropertyRepository { override val isInitialized: Flow<Boolean> = @RequiresPermission(USE_BIOMETRIC_INTERNAL) private val props: StateFlow<FingerprintSensorPropertiesInternal> = conflatedCallbackFlow { val callback = object : IFingerprintAuthenticatorsRegisteredCallback.Stub() { override fun onAllAuthenticatorsRegistered( sensors: List<FingerprintSensorPropertiesInternal> ) { if (sensors.isNotEmpty()) { setProperties(sensors[0]) trySendWithFailureLogging(true, TAG, "initialize properties") if (sensors.isEmpty()) { trySendWithFailureLogging( DEFAULT_PROPS, TAG, "no registered sensors, use default props" ) } else { trySendWithFailureLogging( sensors[0], TAG, "update properties on authenticators registered" ) } } } fingerprintManager?.addAuthenticatorsRegisteredCallback(callback) trySendWithFailureLogging(false, TAG, "initial value defaulting to false") awaitClose {} } .shareIn(scope = applicationScope, started = SharingStarted.Eagerly, replay = 1) private val _sensorId: MutableStateFlow<Int> = MutableStateFlow(-1) override val sensorId: StateFlow<Int> = _sensorId.asStateFlow() .stateIn( applicationScope, started = SharingStarted.Eagerly, initialValue = DEFAULT_PROPS, ) private val _strength: MutableStateFlow<SensorStrength> = MutableStateFlow(SensorStrength.CONVENIENCE) override val strength = _strength.asStateFlow() override val sensorId: Flow<Int> = props.map { it.sensorId } private val _sensorType: MutableStateFlow<FingerprintSensorType> = MutableStateFlow(FingerprintSensorType.UNKNOWN) override val sensorType = _sensorType.asStateFlow() override val strength: Flow<SensorStrength> = props.map { it.sensorStrength.toSensorStrength() } private val _sensorLocations: MutableStateFlow<Map<String, SensorLocationInternal>> = MutableStateFlow(mapOf("" to SensorLocationInternal.DEFAULT)) override val sensorLocations: StateFlow<Map<String, SensorLocationInternal>> = _sensorLocations.asStateFlow() override val sensorType: Flow<FingerprintSensorType> = props.map { it.sensorType.toSensorType() } private fun setProperties(prop: FingerprintSensorPropertiesInternal) { _sensorId.value = prop.sensorId _strength.value = prop.sensorStrength.toSensorStrength() _sensorType.value = sensorTypeIntToObject(prop.sensorType) _sensorLocations.value = prop.allLocations.associateBy { sensorLocationInternal -> override val sensorLocations: Flow<Map<String, SensorLocationInternal>> = props.map { it.allLocations.associateBy { sensorLocationInternal -> sensorLocationInternal.displayId } } companion object { private const val TAG = "FingerprintPropertyRepositoryImpl" } } private fun sensorTypeIntToObject(value: Int): FingerprintSensorType { return when (value) { 0 -> FingerprintSensorType.UNKNOWN 1 -> FingerprintSensorType.REAR 2 -> FingerprintSensorType.UDFPS_ULTRASONIC 3 -> FingerprintSensorType.UDFPS_OPTICAL 4 -> FingerprintSensorType.POWER_BUTTON 5 -> FingerprintSensorType.HOME_BUTTON else -> throw IllegalArgumentException("Invalid SensorType value: $value") private val DEFAULT_PROPS = FingerprintSensorPropertiesInternal( -1 /* sensorId */, SensorProperties.STRENGTH_CONVENIENCE, 0 /* maxEnrollmentsPerUser */, listOf<ComponentInfoInternal>(), FingerprintSensorProperties.TYPE_UNKNOWN, false /* halControlsIllumination */, true /* resetLockoutRequiresHardwareAuthToken */, listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT) ) } }
packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/PromptSelectorInteractor.kt +3 −5 Original line number Diff line number Diff line Loading @@ -32,7 +32,6 @@ import com.android.systemui.biometrics.shared.model.PromptKind import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map Loading Loading @@ -69,7 +68,7 @@ interface PromptSelectorInteractor { val isConfirmationRequired: Flow<Boolean> /** Fingerprint sensor type */ val sensorType: StateFlow<FingerprintSensorType> val sensorType: Flow<FingerprintSensorType> /** Use biometrics for authentication. */ fun useBiometricsForAuthentication( Loading @@ -95,7 +94,7 @@ interface PromptSelectorInteractor { class PromptSelectorInteractorImpl @Inject constructor( private val fingerprintPropertyRepository: FingerprintPropertyRepository, fingerprintPropertyRepository: FingerprintPropertyRepository, private val promptRepository: PromptRepository, lockPatternUtils: LockPatternUtils, ) : PromptSelectorInteractor { Loading Loading @@ -147,8 +146,7 @@ constructor( } } override val sensorType: StateFlow<FingerprintSensorType> = fingerprintPropertyRepository.sensorType override val sensorType: Flow<FingerprintSensorType> = fingerprintPropertyRepository.sensorType override fun useBiometricsForAuthentication( promptInfo: PromptInfo, Loading
packages/SystemUI/src/com/android/systemui/biometrics/domain/interactor/SideFpsOverlayInteractor.kt +22 −11 Original line number Diff line number Diff line Loading @@ -17,32 +17,43 @@ package com.android.systemui.biometrics.domain.interactor import android.hardware.biometrics.SensorLocationInternal import android.util.Log import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository import com.android.systemui.dagger.SysUISingleton import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.combine /** Business logic for SideFps overlay offsets. */ interface SideFpsOverlayInteractor { /** Get the corresponding offsets based on different displayId. */ fun getOverlayOffsets(displayId: String): SensorLocationInternal /** The displayId of the current display. */ val displayId: Flow<String> /** Overlay offsets corresponding to given displayId. */ val overlayOffsets: Flow<SensorLocationInternal> /** Called on display changes, used to keep the display state in sync */ fun onDisplayChanged(displayId: String) } @SysUISingleton class SideFpsOverlayInteractorImpl @Inject constructor(private val fingerprintPropertyRepository: FingerprintPropertyRepository) : constructor(fingerprintPropertyRepository: FingerprintPropertyRepository) : SideFpsOverlayInteractor { override fun getOverlayOffsets(displayId: String): SensorLocationInternal { val offsets = fingerprintPropertyRepository.sensorLocations.value return if (offsets.containsKey(displayId)) { offsets[displayId]!! } else { Log.w(TAG, "No location specified for display: $displayId") offsets[""]!! private val _displayId: MutableStateFlow<String> = MutableStateFlow("") override val displayId: Flow<String> = _displayId.asStateFlow() override val overlayOffsets: Flow<SensorLocationInternal> = combine(displayId, fingerprintPropertyRepository.sensorLocations) { displayId, offsets -> offsets[displayId] ?: SensorLocationInternal.DEFAULT } override fun onDisplayChanged(displayId: String) { _displayId.value = displayId } companion object { Loading
packages/SystemUI/src/com/android/systemui/biometrics/shared/model/FingerprintSensorType.kt +12 −0 Original line number Diff line number Diff line Loading @@ -27,3 +27,15 @@ enum class FingerprintSensorType { POWER_BUTTON, HOME_BUTTON, } /** Convert [this] to corresponding [FingerprintSensorType] */ fun Int.toSensorType(): FingerprintSensorType = when (this) { FingerprintSensorProperties.TYPE_UNKNOWN -> FingerprintSensorType.UNKNOWN FingerprintSensorProperties.TYPE_REAR -> FingerprintSensorType.REAR FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC -> FingerprintSensorType.UDFPS_ULTRASONIC FingerprintSensorProperties.TYPE_UDFPS_OPTICAL -> FingerprintSensorType.UDFPS_OPTICAL FingerprintSensorProperties.TYPE_POWER_BUTTON -> FingerprintSensorType.POWER_BUTTON FingerprintSensorProperties.TYPE_HOME_BUTTON -> FingerprintSensorType.HOME_BUTTON else -> throw IllegalArgumentException("Invalid SensorType value: $this") }
packages/SystemUI/src/com/android/systemui/biometrics/shared/model/SensorStrength.kt +3 −3 Original line number Diff line number Diff line Loading @@ -28,8 +28,8 @@ enum class SensorStrength { /** Convert [this] to corresponding [SensorStrength] */ fun Int.toSensorStrength(): SensorStrength = when (this) { 0 -> SensorStrength.CONVENIENCE 1 -> SensorStrength.WEAK 2 -> SensorStrength.STRONG SensorProperties.STRENGTH_CONVENIENCE -> SensorStrength.CONVENIENCE SensorProperties.STRENGTH_WEAK -> SensorStrength.WEAK SensorProperties.STRENGTH_STRONG -> SensorStrength.STRONG else -> throw IllegalArgumentException("Invalid SensorStrength value: $this") }