diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/biometrics/BiometricsManager.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/biometrics/BiometricsManager.kt new file mode 100644 index 0000000000..6898c853e5 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/biometrics/BiometricsManager.kt @@ -0,0 +1,11 @@ +package com.x8bit.bitwarden.ui.platform.manager.biometrics + +/** + * Interface to manage biometrics within the app. + */ +interface BiometricsManager { + /** + * Returns `true` if the device supports string biometric authentication, `false` otherwise. + */ + val isBiometricsSupported: Boolean +} diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/biometrics/BiometricsManagerImpl.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/biometrics/BiometricsManagerImpl.kt new file mode 100644 index 0000000000..6ac18e7845 --- /dev/null +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/manager/biometrics/BiometricsManagerImpl.kt @@ -0,0 +1,30 @@ +package com.x8bit.bitwarden.ui.platform.manager.biometrics + +import android.app.Activity +import androidx.biometric.BiometricManager +import androidx.biometric.BiometricManager.Authenticators +import com.x8bit.bitwarden.data.platform.annotation.OmitFromCoverage + +/** + * Default implementation of the [BiometricsManager] to manage biometrics within the app. + */ +@OmitFromCoverage +class BiometricsManagerImpl( + private val activity: Activity, +) : BiometricsManager { + private val biometricManager: BiometricManager = BiometricManager.from(activity) + + override val isBiometricsSupported: Boolean + get() = when (biometricManager.canAuthenticate(Authenticators.BIOMETRIC_STRONG)) { + BiometricManager.BIOMETRIC_SUCCESS -> true + BiometricManager.BIOMETRIC_STATUS_UNKNOWN, + BiometricManager.BIOMETRIC_ERROR_UNSUPPORTED, + BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE, + BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED, + BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE, + BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED, + -> false + + else -> false + } +} diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/theme/BitwardenTheme.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/theme/BitwardenTheme.kt index 42062df0b0..bce8629604 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/theme/BitwardenTheme.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/theme/BitwardenTheme.kt @@ -23,6 +23,8 @@ import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppTheme +import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManager +import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManagerImpl import com.x8bit.bitwarden.ui.platform.manager.exit.ExitManager import com.x8bit.bitwarden.ui.platform.manager.exit.ExitManagerImpl import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager @@ -82,6 +84,7 @@ fun BitwardenTheme( LocalPermissionsManager provides PermissionsManagerImpl(activity), LocalIntentManager provides IntentManagerImpl(context), LocalExitManager provides ExitManagerImpl(activity), + LocalBiometricsManager provides BiometricsManagerImpl(activity), ) { // Set overall theme based on color scheme and typography settings MaterialTheme( @@ -170,6 +173,13 @@ private fun lightColorScheme(context: Context): ColorScheme = private fun Int.toColor(context: Context): Color = Color(context.getColor(this)) +/** + * Provides access to the biometrics manager throughout the app. + */ +val LocalBiometricsManager: ProvidableCompositionLocal = compositionLocalOf { + error("CompositionLocal BiometricsManager not present") +} + /** * Provides access to the exit manager throughout the app. */