From 0def95397a547887c5655b50af2372489a49c698 Mon Sep 17 00:00:00 2001 From: nain <126972030+nain-F49FF806@users.noreply.github.com> Date: Sat, 7 Dec 2024 10:48:11 +0000 Subject: [PATCH] Implement configurable auto lock delay duration --- app/build.gradle.kts | 2 +- .../aer/config/ConfigurationActivity.kt | 13 ++++- .../AutoLockDelayMinutesTextListener.kt | 46 ++++++++++++++++ .../java/alt/nainapps/aer/lock/LockStore.kt | 29 ++++++++-- app/src/main/res/layout/configuration.xml | 54 +++++++------------ app/src/main/res/values/strings.xml | 5 +- 6 files changed, 106 insertions(+), 43 deletions(-) create mode 100644 app/src/main/java/alt/nainapps/aer/config/autolock/AutoLockDelayMinutesTextListener.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1b2b396..4e9f700 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -14,7 +14,7 @@ android { defaultConfig { minSdk = rootProject.extra["minSdkVersion"] as Int targetSdk = rootProject.extra["targetSdkVersion"] as Int - versionCode = 1733550000 + versionCode = 1733568000 versionName = "2024.12.07" applicationId = "alt.nainapps.aer" vectorDrawables { diff --git a/app/src/main/java/alt/nainapps/aer/config/ConfigurationActivity.kt b/app/src/main/java/alt/nainapps/aer/config/ConfigurationActivity.kt index 6d9df7c..e2a9326 100644 --- a/app/src/main/java/alt/nainapps/aer/config/ConfigurationActivity.kt +++ b/app/src/main/java/alt/nainapps/aer/config/ConfigurationActivity.kt @@ -1,10 +1,12 @@ /* * Copyright (c) 2022 2bllw8 + * Copyright (c) 2024 nain * SPDX-License-Identifier: GPL-3.0-only */ package alt.nainapps.aer.config import alt.nainapps.aer.R +import alt.nainapps.aer.config.autolock.buildValidatedAutoLockDelayListener import alt.nainapps.aer.config.password.ChangePasswordDialog import alt.nainapps.aer.config.password.SetPasswordDialog import alt.nainapps.aer.lock.LockStore @@ -13,8 +15,10 @@ import alt.nainapps.aer.shell.AnemoShell import android.app.Activity import android.content.Intent import android.os.Bundle +import android.text.Editable import android.view.View import android.widget.CompoundButton +import android.widget.EditText import android.widget.Switch import android.widget.TextView import java.util.function.Consumer @@ -68,6 +72,13 @@ class ConfigurationActivity : Activity() { lockStore.isAutoLockEnabled = isChecked } + val autoLockDelayMinutesEditable = findViewById(R.id.config_auto_lock_delay_minutes) + autoLockDelayMinutesEditable.text = Editable.Factory.getInstance().newEditable( + lockStore.autoLockDelayMinutes.toString() + ) + val autoLockDelayListener = buildValidatedAutoLockDelayListener(this.baseContext, lockStore, autoLockDelayMinutesEditable) + autoLockDelayMinutesEditable.addTextChangedListener(autoLockDelayListener) + biometricSwitch = findViewById(R.id.configuration_biometric_unlock) biometricSwitch!!.visibility = if (lockStore.canAuthenticateBiometric()) View.VISIBLE else View.GONE biometricSwitch!!.isChecked = lockStore.isBiometricUnlockEnabled @@ -120,4 +131,4 @@ class ConfigurationActivity : Activity() { }, ) } -} +} \ No newline at end of file diff --git a/app/src/main/java/alt/nainapps/aer/config/autolock/AutoLockDelayMinutesTextListener.kt b/app/src/main/java/alt/nainapps/aer/config/autolock/AutoLockDelayMinutesTextListener.kt new file mode 100644 index 0000000..9c81e0a --- /dev/null +++ b/app/src/main/java/alt/nainapps/aer/config/autolock/AutoLockDelayMinutesTextListener.kt @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 nain + * SPDX-License-Identifier: GPL-3.0-only + */ + +package alt.nainapps.aer.config.autolock + +import alt.nainapps.aer.R +import alt.nainapps.aer.lock.LockStore +import android.content.Context +import android.text.Editable +import android.text.TextWatcher +import android.widget.EditText + +fun interface AutoLockDelayMinutesTextListener : TextWatcher { + + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + } + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + } + override fun afterTextChanged(s: Editable) { + afterTextChanged(s.toString()) + } + // this will be provided as lambda + fun afterTextChanged(text: String) +} + +fun buildValidatedAutoLockDelayListener(context: Context, lockstore: LockStore, input: EditText): AutoLockDelayMinutesTextListener { + return AutoLockDelayMinutesTextListener { text -> + // validate text isNumber + try { + text.toLong() + } catch (error: NumberFormatException) { + input.setError("NaN: Not a Number", + context.getDrawable(R.drawable.ic_error)) + return@AutoLockDelayMinutesTextListener + } + val minutes: Long = text.toLong() + // validate not zero + if (minutes == 0L) { + input.setError("Auto lock delay can't be zero", + context.getDrawable(R.drawable.ic_error)) + } + lockstore.autoLockDelayMinutes = minutes + } +} \ No newline at end of file diff --git a/app/src/main/java/alt/nainapps/aer/lock/LockStore.kt b/app/src/main/java/alt/nainapps/aer/lock/LockStore.kt index 097e53c..2ee4293 100644 --- a/app/src/main/java/alt/nainapps/aer/lock/LockStore.kt +++ b/app/src/main/java/alt/nainapps/aer/lock/LockStore.kt @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 2bllw8 + * Copyright (c) 2024 nain * SPDX-License-Identifier: GPL-3.0-only */ package alt.nainapps.aer.lock @@ -114,6 +115,22 @@ class LockStore private constructor(context: Context) : OnSharedPreferenceChange } } + @get:Synchronized + @set:Synchronized + var autoLockDelayMinutes: Long + get() = preferences.getLong(KEY_AUTO_LOCK_DELAY_MINUTES, DEFAULT_AUTO_LOCK_DELAY_MINUTES) + set(delayMinutes) { + preferences.edit().putLong(KEY_AUTO_LOCK_DELAY_MINUTES, delayMinutes).apply() + + if (!isLocked) { + if (isAutoLockEnabled) { + // If auto-lock is enabled while the storage is unlocked, schedule new job + cancelAutoLock() + scheduleAutoLock() + } + } + } + fun canAuthenticateBiometric(): Boolean { return Build.VERSION.SDK_INT >= 29 && biometricManager != null && biometricManager.canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS } @@ -146,7 +163,7 @@ class LockStore private constructor(context: Context) : OnSharedPreferenceChange private fun scheduleAutoLock() { jobScheduler.schedule( JobInfo.Builder(AUTO_LOCK_JOB_ID, autoLockComponent) - .setMinimumLatency(AUTO_LOCK_DELAY) + .setMinimumLatency(millisFromMinutes(autoLockDelayMinutes)) .build() ) } @@ -166,6 +183,11 @@ class LockStore private constructor(context: Context) : OnSharedPreferenceChange } } + // convert minutes to milliseconds + private fun millisFromMinutes(minutes: Long): Long { + return minutes * 60L * 1000L + } + companion object { private const val TAG = "LockStore" @@ -173,17 +195,16 @@ class LockStore private constructor(context: Context) : OnSharedPreferenceChange private const val KEY_LOCK = "is_locked" private const val KEY_PASSWORD = "password_hash" private const val KEY_AUTO_LOCK = "auto_lock" + private const val KEY_AUTO_LOCK_DELAY_MINUTES = "auto_lock_delay_minutes" private const val KEY_BIOMETRIC_UNLOCK = "biometric_unlock" private const val DEFAULT_LOCK_VALUE = false private const val DEFAULT_AUTO_LOCK_VALUE = false + private const val DEFAULT_AUTO_LOCK_DELAY_MINUTES = 15L private const val HASH_ALGORITHM = "SHA-256" private const val AUTO_LOCK_JOB_ID = 64 - // 15 minutes in milliseconds - private const val AUTO_LOCK_DELAY = 1000L * 60L * 15L - @Volatile private var instance: LockStore? = null diff --git a/app/src/main/res/layout/configuration.xml b/app/src/main/res/layout/configuration.xml index 2747727..424bdac 100644 --- a/app/src/main/res/layout/configuration.xml +++ b/app/src/main/res/layout/configuration.xml @@ -1,5 +1,6 @@ - + android:layout_height="wrap_content" + android:foreground="?android:attr/selectableItemBackground" + android:minHeight="56dp" + android:paddingHorizontal="16dp" + android:text="@string/configuration_storage_unlock_biometric" + android:textSize="16sp" /> + tools:text="@string/configuration_auto_lock_delay_minutes_label" /> - + android:minHeight="56dp" + android:minEms="3" + android:maxEms="5" + android:inputType="number" /> - - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 47ac3b5..97e077f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -62,14 +62,13 @@ Lock storage access Unlock storage access Allow storage unlock with biometric access - Automatically lock access after _ minutes + Automatically lock access after delay StoragePrefActivity Storage Configuration Storage Config Storage Config (Disabled) Tap to select / Drag to reorder: Aer Storage Backend - Autolock delay (in minutes) - 15 + Auto lock delay (in minutes)