PIN Code Improvements. Add more settings (#1985)

- enable/disable biometrics
- enbale/disable grace period
This commit is contained in:
Benoit Marty 2020-09-23 12:00:04 +02:00 committed by Benoit Marty
parent b8cbafa75d
commit fdedfc954c
6 changed files with 58 additions and 8 deletions

View file

@ -12,6 +12,7 @@ Improvements 🙌:
- Use cache for user color - Use cache for user color
- Allow using an outdated homeserver, at user's risk (#1972) - Allow using an outdated homeserver, at user's risk (#1972)
- Restore small logo on login screens and fix scrolling issue on those screens - Restore small logo on login screens and fix scrolling issue on those screens
- PIN Code Improvements. Add more settings (#1985)
Bugfix 🐛: Bugfix 🐛:
- Long message cannot be sent/takes infinite time & blocks other messages #1397 - Long message cannot be sent/takes infinite time & blocks other messages #1397

View file

@ -32,6 +32,7 @@ import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.toast import im.vector.app.core.utils.toast
import im.vector.app.features.MainActivity import im.vector.app.features.MainActivity
import im.vector.app.features.MainActivityArgs import im.vector.app.features.MainActivityArgs
import im.vector.app.features.settings.VectorPreferences
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
@ -42,7 +43,8 @@ data class PinArgs(
) : Parcelable ) : Parcelable
class PinFragment @Inject constructor( class PinFragment @Inject constructor(
private val pinCodeStore: PinCodeStore private val pinCodeStore: PinCodeStore,
private val vectorPreferences: VectorPreferences
) : VectorBaseFragment() { ) : VectorBaseFragment() {
private val fragmentArgs: PinArgs by args() private val fragmentArgs: PinArgs by args()
@ -62,7 +64,7 @@ class PinFragment @Inject constructor(
val encodedPin = pinCodeStore.getEncodedPin() ?: return val encodedPin = pinCodeStore.getEncodedPin() ?: return
val authFragment = PFLockScreenFragment() val authFragment = PFLockScreenFragment()
val builder = PFFLockScreenConfiguration.Builder(requireContext()) val builder = PFFLockScreenConfiguration.Builder(requireContext())
.setUseBiometric(pinCodeStore.getRemainingBiometricsAttemptsNumber() > 0) .setUseBiometric(vectorPreferences.useBiometricsToUnlock() && pinCodeStore.getRemainingBiometricsAttemptsNumber() > 0)
.setTitle(getString(R.string.auth_pin_confirm_to_disable_title)) .setTitle(getString(R.string.auth_pin_confirm_to_disable_title))
.setClearCodeOnError(true) .setClearCodeOnError(true)
.setMode(PFFLockScreenConfiguration.MODE_AUTH) .setMode(PFFLockScreenConfiguration.MODE_AUTH)
@ -131,9 +133,8 @@ class PinFragment @Inject constructor(
val authFragment = PFLockScreenFragment() val authFragment = PFLockScreenFragment()
val canUseBiometrics = pinCodeStore.getRemainingBiometricsAttemptsNumber() > 0 val canUseBiometrics = pinCodeStore.getRemainingBiometricsAttemptsNumber() > 0
val builder = PFFLockScreenConfiguration.Builder(requireContext()) val builder = PFFLockScreenConfiguration.Builder(requireContext())
.setUseBiometric(true)
.setAutoShowBiometric(true) .setAutoShowBiometric(true)
.setUseBiometric(canUseBiometrics) .setUseBiometric(vectorPreferences.useBiometricsToUnlock() && canUseBiometrics)
.setAutoShowBiometric(canUseBiometrics) .setAutoShowBiometric(canUseBiometrics)
.setTitle(getString(R.string.auth_pin_title)) .setTitle(getString(R.string.auth_pin_title))
.setLeftButton(getString(R.string.auth_pin_forgot)) .setLeftButton(getString(R.string.auth_pin_forgot))

View file

@ -22,22 +22,29 @@ import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.OnLifecycleEvent import androidx.lifecycle.OnLifecycleEvent
import im.vector.app.features.settings.VectorPreferences
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
// 2 minutes, when enabled
private const val PERIOD_OF_GRACE_IN_MS = 2 * 60 * 1000L private const val PERIOD_OF_GRACE_IN_MS = 2 * 60 * 1000L
// 1 seconds, to avoid asking for PIN code when switching between Activities
private const val PERIOD_OF_GRACE_DISABLED_IN_MS = 1000L
/** /**
* This class is responsible for keeping the status of locking * This class is responsible for keeping the status of locking
* It automatically locks when entering background/foreground with a grace period. * It automatically locks when entering background/foreground with a grace period.
* You can force to unlock with unlock method, use it whenever the pin code has been validated. * You can force to unlock with unlock method, use it whenever the pin code has been validated.
*/ */
@Singleton @Singleton
class PinLocker @Inject constructor(private val pinCodeStore: PinCodeStore) : LifecycleObserver { class PinLocker @Inject constructor(
private val pinCodeStore: PinCodeStore,
private val vectorPreferences: VectorPreferences
) : LifecycleObserver {
enum class State { enum class State {
// App is locked, can be unlock // App is locked, can be unlock
@ -90,7 +97,7 @@ class PinLocker @Inject constructor(private val pinCodeStore: PinCodeStore) : Li
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME) @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
fun entersForeground() { fun entersForeground() {
val timeElapsedSinceBackground = SystemClock.elapsedRealtime() - entersBackgroundTs val timeElapsedSinceBackground = SystemClock.elapsedRealtime() - entersBackgroundTs
shouldBeLocked = shouldBeLocked || timeElapsedSinceBackground >= PERIOD_OF_GRACE_IN_MS shouldBeLocked = shouldBeLocked || timeElapsedSinceBackground >= getGracePeriod()
Timber.v("App enters foreground after $timeElapsedSinceBackground ms spent in background") Timber.v("App enters foreground after $timeElapsedSinceBackground ms spent in background")
computeState() computeState()
} }
@ -100,4 +107,12 @@ class PinLocker @Inject constructor(private val pinCodeStore: PinCodeStore) : Li
isBlocked = false isBlocked = false
entersBackgroundTs = SystemClock.elapsedRealtime() entersBackgroundTs = SystemClock.elapsedRealtime()
} }
private fun getGracePeriod(): Long {
return if (vectorPreferences.useGracePeriod()) {
PERIOD_OF_GRACE_IN_MS
} else {
PERIOD_OF_GRACE_DISABLED_IN_MS
}
}
} }

View file

@ -166,6 +166,8 @@ class VectorPreferences @Inject constructor(private val context: Context) {
// Security // Security
const val SETTINGS_SECURITY_USE_FLAG_SECURE = "SETTINGS_SECURITY_USE_FLAG_SECURE" const val SETTINGS_SECURITY_USE_FLAG_SECURE = "SETTINGS_SECURITY_USE_FLAG_SECURE"
const val SETTINGS_SECURITY_USE_PIN_CODE_FLAG = "SETTINGS_SECURITY_USE_PIN_CODE_FLAG" const val SETTINGS_SECURITY_USE_PIN_CODE_FLAG = "SETTINGS_SECURITY_USE_PIN_CODE_FLAG"
private const val SETTINGS_SECURITY_USE_BIOMETRICS_FLAG = "SETTINGS_SECURITY_USE_BIOMETRICS_FLAG"
private const val SETTINGS_SECURITY_USE_GRACE_PERIOD_FLAG = "SETTINGS_SECURITY_USE_GRACE_PERIOD_FLAG"
// other // other
const val SETTINGS_MEDIA_SAVING_PERIOD_KEY = "SETTINGS_MEDIA_SAVING_PERIOD_KEY" const val SETTINGS_MEDIA_SAVING_PERIOD_KEY = "SETTINGS_MEDIA_SAVING_PERIOD_KEY"
@ -839,12 +841,21 @@ class VectorPreferences @Inject constructor(private val context: Context) {
} }
/** /**
* The user enable protecting app access with pin code * The user enable protecting app access with pin code.
* Currently we use the pin code store to know if the pin is enabled, so this is not used
*/ */
fun useFlagPinCode(): Boolean { fun useFlagPinCode(): Boolean {
return defaultPrefs.getBoolean(SETTINGS_SECURITY_USE_PIN_CODE_FLAG, false) return defaultPrefs.getBoolean(SETTINGS_SECURITY_USE_PIN_CODE_FLAG, false)
} }
fun useBiometricsToUnlock(): Boolean {
return defaultPrefs.getBoolean(SETTINGS_SECURITY_USE_BIOMETRICS_FLAG, true)
}
fun useGracePeriod(): Boolean {
return defaultPrefs.getBoolean(SETTINGS_SECURITY_USE_GRACE_PERIOD_FLAG, true)
}
fun backgroundSyncTimeOut(): Int { fun backgroundSyncTimeOut(): Int {
return tryOrNull { return tryOrNull {
// The xml pref is saved as a string so use getString and parse // The xml pref is saved as a string so use getString and parse

View file

@ -2571,6 +2571,12 @@
<string name="settings_security_application_protection_screen_title">Configure protection</string> <string name="settings_security_application_protection_screen_title">Configure protection</string>
<string name="settings_security_pin_code_title">Enable PIN</string> <string name="settings_security_pin_code_title">Enable PIN</string>
<string name="settings_security_pin_code_summary">If you want to reset your PIN, tap Forgot PIN to logout and reset.</string> <string name="settings_security_pin_code_summary">If you want to reset your PIN, tap Forgot PIN to logout and reset.</string>
<string name="settings_security_pin_code_use_biometrics_title">Use biometrics</string>
<string name="settings_security_pin_code_use_biometrics_summary_on">Depending on your device, you will be able to unlock using fingerprints, face recognition, iris recognition, etc.</string>
<string name="settings_security_pin_code_use_biometrics_summary_off">PIN code is the only way to unlock the application.</string>
<string name="settings_security_pin_code_grace_period_title">Enable grace period</string>
<string name="settings_security_pin_code_grace_period_summary_on">PIN code will be asked after 2 minutes not using the application.</string>
<string name="settings_security_pin_code_grace_period_summary_off">PIN code will be requested every time you put the application to foreground.</string>
<string name="auth_pin_confirm_to_disable_title">Confirm PIN to disable PIN</string> <string name="auth_pin_confirm_to_disable_title">Confirm PIN to disable PIN</string>
<string name="error_opening_banned_room">Can\'t open a room where you are banned from.</string> <string name="error_opening_banned_room">Can\'t open a room where you are banned from.</string>
<string name="room_error_not_found">Can\'t find this room. Make sure it exists.</string> <string name="room_error_not_found">Can\'t find this room. Make sure it exists.</string>

View file

@ -7,4 +7,20 @@
android:summary="@string/settings_security_pin_code_summary" android:summary="@string/settings_security_pin_code_summary"
android:title="@string/settings_security_pin_code_title" /> android:title="@string/settings_security_pin_code_title" />
<im.vector.app.core.preference.VectorSwitchPreference
android:defaultValue="true"
android:dependency="SETTINGS_SECURITY_USE_PIN_CODE_FLAG"
android:key="SETTINGS_SECURITY_USE_BIOMETRICS_FLAG"
android:summaryOff="@string/settings_security_pin_code_use_biometrics_summary_off"
android:summaryOn="@string/settings_security_pin_code_use_biometrics_summary_on"
android:title="@string/settings_security_pin_code_use_biometrics_title" />
<im.vector.app.core.preference.VectorSwitchPreference
android:defaultValue="true"
android:dependency="SETTINGS_SECURITY_USE_PIN_CODE_FLAG"
android:key="SETTINGS_SECURITY_USE_GRACE_PERIOD_FLAG"
android:summaryOff="@string/settings_security_pin_code_grace_period_summary_off"
android:summaryOn="@string/settings_security_pin_code_grace_period_summary_on"
android:title="@string/settings_security_pin_code_grace_period_title" />
</androidx.preference.PreferenceScreen> </androidx.preference.PreferenceScreen>