mirror of
https://github.com/home-assistant/android
synced 2024-07-22 10:54:12 +00:00
Settings activity app lock (#2926)
* Extract app lock timout functionality from WebViewActivity * Add app lock authentication to SettingsActivity. Handle enabling app lock setting authentication in SettingsActivity to avoid callback clash. * Add blurview to SettingsActivity when app is locked * Increase blur radius: 5px seems small enough to have text still somewhat legible * Cleanup * Cache appLock state for use in touch listeners * Review rework * Add onWindowFocusChanged to settingsActivity to check for authentication * Cleanup SessionExpireMillis functions * Fix logging formats * Cleanup debug logging in onResume / onWindowFocusChanged handlers * Linter fix * Test SettingsActivity blurview without explicit background * Improve isAppLocked() debug logging * Increase applock grace period * Fix setLockAuthenticationResult return value * remove authentication from onResume. Perform only onWindowFocusChanged. * Prevent double authentication prompt when enabling app lock * Fix missing NotificationManagerCompat import
This commit is contained in:
parent
07845fb797
commit
1f226a71fe
|
@ -3,26 +3,46 @@ package io.homeassistant.companion.android.settings
|
|||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.biometric.BiometricManager
|
||||
import dagger.hilt.EntryPoint
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import dagger.hilt.android.EntryPointAccessors
|
||||
import dagger.hilt.android.components.ActivityComponent
|
||||
import eightbitlab.com.blurview.BlurView
|
||||
import eightbitlab.com.blurview.RenderScriptBlur
|
||||
import io.homeassistant.companion.android.BaseActivity
|
||||
import io.homeassistant.companion.android.R
|
||||
import io.homeassistant.companion.android.authenticator.Authenticator
|
||||
import io.homeassistant.companion.android.common.data.integration.IntegrationRepository
|
||||
import io.homeassistant.companion.android.settings.notification.NotificationHistoryFragment
|
||||
import io.homeassistant.companion.android.settings.qs.ManageTilesFragment
|
||||
import io.homeassistant.companion.android.settings.sensor.SensorDetailFragment
|
||||
import io.homeassistant.companion.android.settings.websocket.WebsocketSettingFragment
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import javax.inject.Inject
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
@AndroidEntryPoint
|
||||
class SettingsActivity : BaseActivity() {
|
||||
|
||||
@Inject
|
||||
lateinit var integrationUseCase: IntegrationRepository
|
||||
|
||||
private lateinit var authenticator: Authenticator
|
||||
private lateinit var blurView: BlurView
|
||||
|
||||
private var authenticating = false
|
||||
private var externalAuthCallback: ((Int) -> Boolean)? = null
|
||||
|
||||
companion object {
|
||||
private const val TAG = "SettingsActivity"
|
||||
|
||||
fun newInstance(context: Context): Intent {
|
||||
return Intent(context, SettingsActivity::class.java)
|
||||
}
|
||||
|
@ -49,6 +69,16 @@ class SettingsActivity : BaseActivity() {
|
|||
setSupportActionBar(findViewById(R.id.toolbar))
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
|
||||
blurView = findViewById(R.id.blurView)
|
||||
blurView.setupWith(window.decorView.rootView as ViewGroup)
|
||||
.setBlurAlgorithm(RenderScriptBlur(this))
|
||||
.setBlurAutoUpdate(true)
|
||||
.setBlurRadius(8f)
|
||||
.setHasFixedTransformationMatrix(false)
|
||||
.setBlurEnabled(false)
|
||||
|
||||
authenticator = Authenticator(this, this, ::settingsActivityAuthenticationResult)
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
val settingsNavigation = intent.getStringExtra("fragment")
|
||||
supportFragmentManager
|
||||
|
@ -74,6 +104,76 @@ class SettingsActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun onUserLeaveHint() {
|
||||
super.onUserLeaveHint()
|
||||
runBlocking {
|
||||
integrationUseCase.setAppActive(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
runBlocking {
|
||||
integrationUseCase.setAppActive(false)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
val appLocked = runBlocking {
|
||||
integrationUseCase.isAppLocked()
|
||||
}
|
||||
|
||||
blurView.setBlurEnabled(appLocked)
|
||||
}
|
||||
|
||||
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||
super.onWindowFocusChanged(hasFocus)
|
||||
if (hasFocus) {
|
||||
val appLocked = runBlocking {
|
||||
integrationUseCase.isAppLocked()
|
||||
}
|
||||
|
||||
if (appLocked) {
|
||||
authenticating = true
|
||||
authenticator.authenticate(getString(commonR.string.biometric_title))
|
||||
blurView.setBlurEnabled(true)
|
||||
} else {
|
||||
blurView.setBlurEnabled(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun settingsActivityAuthenticationResult(result: Int) {
|
||||
val isExtAuth = (externalAuthCallback != null)
|
||||
Log.d(TAG, "settingsActivityAuthenticationResult(): authenticating: $authenticating, externalAuth: $isExtAuth")
|
||||
|
||||
externalAuthCallback?.let {
|
||||
if (it(result) == true) {
|
||||
externalAuthCallback = null
|
||||
}
|
||||
}
|
||||
|
||||
if (authenticating) {
|
||||
authenticating = false
|
||||
when (result) {
|
||||
Authenticator.SUCCESS -> {
|
||||
Log.d(TAG, "Authentication successful, unlocking app")
|
||||
blurView.setBlurEnabled(false)
|
||||
runBlocking {
|
||||
integrationUseCase.setAppActive(true)
|
||||
}
|
||||
}
|
||||
Authenticator.CANCELED -> {
|
||||
Log.d(TAG, "Authentication canceled by user, closing activity")
|
||||
finishAffinity()
|
||||
}
|
||||
else -> Log.d(TAG, "Authentication failed, retry attempts allowed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
return when (item.itemId) {
|
||||
android.R.id.home -> {
|
||||
|
@ -88,6 +188,17 @@ class SettingsActivity : BaseActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
fun requestAuthentication(title: String, callback: (Int) -> Boolean): Boolean {
|
||||
return if (BiometricManager.from(this).canAuthenticate() != BiometricManager.BIOMETRIC_SUCCESS) {
|
||||
false
|
||||
} else {
|
||||
externalAuthCallback = callback
|
||||
authenticator.authenticate(title)
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
@EntryPoint
|
||||
@InstallIn(ActivityComponent::class)
|
||||
interface SettingsFragmentFactoryEntryPoint {
|
||||
|
|
|
@ -17,7 +17,6 @@ import android.util.Log
|
|||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.getSystemService
|
||||
|
@ -69,9 +68,6 @@ class SettingsFragment constructor(
|
|||
private const val BACKGROUND_LOCATION_REQUEST_CODE = 1
|
||||
}
|
||||
|
||||
private lateinit var authenticator: Authenticator
|
||||
private var setLock = false
|
||||
|
||||
private val requestBackgroundAccessResult = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
updateBackgroundAccessPref()
|
||||
}
|
||||
|
@ -83,8 +79,6 @@ class SettingsFragment constructor(
|
|||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
presenter.init(this)
|
||||
|
||||
authenticator = Authenticator(requireContext(), requireActivity(), ::authenticationResult)
|
||||
|
||||
preferenceManager.preferenceDataStore = presenter.getPreferenceDataStore()
|
||||
|
||||
setPreferencesFromResource(R.xml.preferences, rootKey)
|
||||
|
@ -102,18 +96,17 @@ class SettingsFragment constructor(
|
|||
}
|
||||
|
||||
findPreference<SwitchPreference>("app_lock")?.setOnPreferenceChangeListener { _, newValue ->
|
||||
var isValid: Boolean
|
||||
val isValid: Boolean
|
||||
if (newValue == false) {
|
||||
isValid = true
|
||||
findPreference<SwitchPreference>("app_lock_home_bypass")?.isVisible = false
|
||||
findPreference<EditTextPreference>("session_timeout")?.isVisible = false
|
||||
} else {
|
||||
isValid = true
|
||||
if (BiometricManager.from(requireActivity()).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS) {
|
||||
setLock = true
|
||||
authenticator.authenticate(getString(commonR.string.biometric_set_title))
|
||||
} else {
|
||||
isValid = false
|
||||
val settingsActivity = requireActivity() as SettingsActivity
|
||||
val canAuth = settingsActivity.requestAuthentication(getString(commonR.string.biometric_set_title), ::setLockAuthenticationResult)
|
||||
isValid = canAuth
|
||||
|
||||
if (!canAuth) {
|
||||
AlertDialog.Builder(requireActivity())
|
||||
.setTitle(commonR.string.set_lock_title)
|
||||
.setMessage(commonR.string.set_lock_message)
|
||||
|
@ -493,13 +486,17 @@ class SettingsFragment constructor(
|
|||
.commit()
|
||||
}
|
||||
|
||||
private fun authenticationResult(result: Int) {
|
||||
private fun setLockAuthenticationResult(result: Int): Boolean {
|
||||
val success = result == Authenticator.SUCCESS
|
||||
val switchLock = findPreference<SwitchPreference>("app_lock")
|
||||
switchLock?.isChecked = success
|
||||
|
||||
// Prevent requesting authentication after just enabling the app lock
|
||||
presenter.setAppActive(success)
|
||||
|
||||
findPreference<SwitchPreference>("app_lock_home_bypass")?.isVisible = success
|
||||
findPreference<EditTextPreference>("session_timeout")?.isVisible = success
|
||||
return (result == Authenticator.SUCCESS || result == Authenticator.CANCELED)
|
||||
}
|
||||
|
||||
private fun removeSystemFromThemesIfNeeded() {
|
||||
|
|
|
@ -11,12 +11,9 @@ interface SettingsPresenter {
|
|||
fun onFinish()
|
||||
fun updateExternalUrlStatus()
|
||||
fun updateInternalUrlStatus()
|
||||
fun isLockEnabled(): Boolean
|
||||
fun sessionTimeOut(): Int
|
||||
fun setAppActive(active: Boolean)
|
||||
suspend fun getNotificationRateLimits(): RateLimitResponse?
|
||||
|
||||
fun setSessionExpireMillis(value: Long)
|
||||
fun getSessionExpireMillis(): Long
|
||||
fun isSsidUsed(): Boolean
|
||||
fun clearSsids()
|
||||
fun showChangeLog(context: Context)
|
||||
|
|
|
@ -173,27 +173,9 @@ class SettingsPresenterImpl @Inject constructor(
|
|||
settingsView.updateSsids(ssids)
|
||||
}
|
||||
|
||||
override fun isLockEnabled(): Boolean {
|
||||
return runBlocking {
|
||||
authenticationUseCase.isLockEnabled()
|
||||
}
|
||||
}
|
||||
|
||||
override fun sessionTimeOut(): Int {
|
||||
return runBlocking {
|
||||
integrationUseCase.getSessionTimeOut()
|
||||
}
|
||||
}
|
||||
|
||||
override fun setSessionExpireMillis(value: Long) {
|
||||
mainScope.launch {
|
||||
integrationUseCase.setSessionExpireMillis(value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSessionExpireMillis(): Long {
|
||||
return runBlocking {
|
||||
integrationUseCase.getSessionExpireMillis()
|
||||
override fun setAppActive(active: Boolean) {
|
||||
runBlocking {
|
||||
integrationUseCase.setAppActive(active)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
private var videoHeight = 0
|
||||
private var firstAuthTime: Long = 0
|
||||
private var resourceURL: String = ""
|
||||
private var unlocked = false
|
||||
private var appLocked = true
|
||||
private var exoPlayer: SimpleExoPlayer? = null
|
||||
private var isExoFullScreen = false
|
||||
private var exoTop: Int = 0 // These margins are from the DOM and scaled to screen
|
||||
|
@ -225,7 +225,7 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
|
||||
binding.blurView.setupWith(binding.root)
|
||||
.setBlurAlgorithm(RenderScriptBlur(this))
|
||||
.setBlurRadius(5f)
|
||||
.setBlurRadius(8f)
|
||||
.setHasFixedTransformationMatrix(false)
|
||||
|
||||
exoPlayerView = binding.exoplayerView
|
||||
|
@ -238,10 +238,8 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
|
||||
playerBinding = ExoPlayerViewBinding.bind(exoPlayerView)
|
||||
|
||||
if (!presenter.isLockEnabled()) {
|
||||
binding.blurView.setBlurEnabled(false)
|
||||
unlocked = true
|
||||
}
|
||||
appLocked = presenter.isAppLocked()
|
||||
binding.blurView.setBlurEnabled(appLocked)
|
||||
|
||||
authenticator = Authenticator(this, this, ::authenticationResult)
|
||||
|
||||
|
@ -273,11 +271,11 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
) {
|
||||
dispatchKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_E))
|
||||
}
|
||||
return !unlocked
|
||||
return appLocked
|
||||
}
|
||||
|
||||
override fun onMotionEventHandled(v: View?, event: MotionEvent?): Boolean {
|
||||
return !unlocked
|
||||
return appLocked
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -698,12 +696,9 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
super.onResume()
|
||||
if ((currentLang != languagesManager.getCurrentLang()) || currentAutoplay != presenter.isAutoPlayVideoEnabled())
|
||||
recreate()
|
||||
if ((!unlocked && !presenter.isLockEnabled()) ||
|
||||
(!unlocked && presenter.isLockEnabled() && System.currentTimeMillis() < presenter.getSessionExpireMillis())
|
||||
) {
|
||||
unlocked = true
|
||||
binding.blurView.setBlurEnabled(false)
|
||||
}
|
||||
|
||||
appLocked = presenter.isAppLocked()
|
||||
binding.blurView.setBlurEnabled(appLocked)
|
||||
|
||||
enablePinchToZoom()
|
||||
|
||||
|
@ -723,6 +718,7 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
override fun onPause() {
|
||||
super.onPause()
|
||||
SensorWorker.start(this)
|
||||
presenter.setAppActive(false)
|
||||
}
|
||||
|
||||
private fun checkAndWarnForDisabledLocation() {
|
||||
|
@ -939,7 +935,8 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
when (result) {
|
||||
Authenticator.SUCCESS -> {
|
||||
Log.d(TAG, "Authentication successful, unlocking app")
|
||||
unlocked = true
|
||||
appLocked = false
|
||||
presenter.setAppActive(true)
|
||||
binding.blurView.setBlurEnabled(false)
|
||||
}
|
||||
Authenticator.CANCELED -> {
|
||||
|
@ -953,13 +950,13 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
override fun onWindowFocusChanged(hasFocus: Boolean) {
|
||||
super.onWindowFocusChanged(hasFocus)
|
||||
if (hasFocus) {
|
||||
if (presenter.isLockEnabled() && !unlocked)
|
||||
if ((System.currentTimeMillis() > presenter.getSessionExpireMillis())) {
|
||||
binding.blurView.setBlurEnabled(true)
|
||||
authenticator.authenticate(getString(commonR.string.biometric_title))
|
||||
} else {
|
||||
binding.blurView.setBlurEnabled(false)
|
||||
}
|
||||
appLocked = presenter.isAppLocked()
|
||||
if (appLocked) {
|
||||
binding.blurView.setBlurEnabled(true)
|
||||
authenticator.authenticate(getString(commonR.string.biometric_title))
|
||||
} else {
|
||||
binding.blurView.setBlurEnabled(false)
|
||||
}
|
||||
|
||||
val path = intent.getStringExtra(EXTRA_PATH)
|
||||
presenter.onViewReady(path)
|
||||
|
@ -1003,8 +1000,7 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
|
|||
|
||||
override fun onUserLeaveHint() {
|
||||
super.onUserLeaveHint()
|
||||
presenter.setSessionExpireMillis((System.currentTimeMillis() + (presenter.sessionTimeOut() * 1000)))
|
||||
unlocked = false
|
||||
presenter.setAppActive(false)
|
||||
videoHeight = decor.height
|
||||
val bounds = Rect(0, 0, 1920, 1080)
|
||||
if (isVideoFullScreen or isExoFullScreen) {
|
||||
|
|
|
@ -21,14 +21,14 @@ interface WebViewPresenter {
|
|||
fun isPinchToZoomEnabled(): Boolean
|
||||
fun isWebViewDebugEnabled(): Boolean
|
||||
|
||||
fun isAppLocked(): Boolean
|
||||
fun setAppActive(active: Boolean)
|
||||
|
||||
fun isLockEnabled(): Boolean
|
||||
fun isAutoPlayVideoEnabled(): Boolean
|
||||
|
||||
fun sessionTimeOut(): Int
|
||||
|
||||
fun setSessionExpireMillis(value: Long)
|
||||
fun getSessionExpireMillis(): Long
|
||||
|
||||
fun onFinish()
|
||||
|
||||
fun isSsidUsed(): Boolean
|
||||
|
|
|
@ -157,6 +157,18 @@ class WebViewPresenterImpl @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun isAppLocked(): Boolean {
|
||||
return runBlocking {
|
||||
integrationUseCase.isAppLocked()
|
||||
}
|
||||
}
|
||||
|
||||
override fun setAppActive(active: Boolean) {
|
||||
return runBlocking {
|
||||
integrationUseCase.setAppActive(active)
|
||||
}
|
||||
}
|
||||
|
||||
override fun isLockEnabled(): Boolean {
|
||||
return runBlocking {
|
||||
authenticationUseCase.isLockEnabled()
|
||||
|
@ -175,18 +187,6 @@ class WebViewPresenterImpl @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun setSessionExpireMillis(value: Long) {
|
||||
mainScope.launch {
|
||||
integrationUseCase.setSessionExpireMillis(value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSessionExpireMillis(): Long {
|
||||
return runBlocking {
|
||||
integrationUseCase.getSessionExpireMillis()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onFinish() {
|
||||
mainScope.cancel()
|
||||
}
|
||||
|
|
|
@ -1,19 +1,32 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:elevation="4dp"
|
||||
android:theme="@style/ThemeOverlay.HomeAssistant.ConfigActionBar" />
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/content"
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:elevation="4dp"
|
||||
android:theme="@style/ThemeOverlay.HomeAssistant.ConfigActionBar" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</LinearLayout>
|
||||
|
||||
<eightbitlab.com.blurview.BlurView
|
||||
android:id="@+id/blurView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</LinearLayout>
|
||||
android:layout_height="match_parent">
|
||||
</eightbitlab.com.blurview.BlurView>
|
||||
|
||||
</RelativeLayout>
|
|
@ -36,11 +36,13 @@ interface IntegrationRepository {
|
|||
suspend fun setWebViewDebugEnabled(enabled: Boolean)
|
||||
suspend fun isWebViewDebugEnabled(): Boolean
|
||||
|
||||
suspend fun isAppLocked(): Boolean
|
||||
suspend fun setAppActive(active: Boolean)
|
||||
|
||||
suspend fun sessionTimeOut(value: Int)
|
||||
suspend fun getSessionTimeOut(): Int
|
||||
|
||||
suspend fun setSessionExpireMillis(value: Long)
|
||||
suspend fun getSessionExpireMillis(): Long
|
||||
|
||||
suspend fun setControlsAuthRequired(setting: ControlsAuthRequiredSetting)
|
||||
suspend fun getControlsAuthRequired(): ControlsAuthRequiredSetting
|
||||
|
|
|
@ -80,8 +80,12 @@ class IntegrationRepositoryImpl @Inject constructor(
|
|||
private const val PREF_SEC_WARNING_NEXT = "sec_warning_last"
|
||||
private const val TAG = "IntegrationRepository"
|
||||
private const val RATE_LIMIT_URL = BuildConfig.RATE_LIMIT_URL
|
||||
|
||||
private const val APPLOCK_TIMEOUT_GRACE_MS = 1000
|
||||
}
|
||||
|
||||
private var appActive = false
|
||||
|
||||
override suspend fun registerDevice(deviceRegistration: DeviceRegistration) {
|
||||
val request = createUpdateRegistrationRequest(deviceRegistration)
|
||||
request.appId = APP_ID
|
||||
|
@ -373,6 +377,25 @@ class IntegrationRepositoryImpl @Inject constructor(
|
|||
localStorage.putBoolean(PREF_AUTOPLAY_VIDEO, enabled)
|
||||
}
|
||||
|
||||
override suspend fun isAppLocked(): Boolean {
|
||||
val lockEnabled = authenticationRepository.isLockEnabled()
|
||||
val sessionExpireMillis = getSessionExpireMillis()
|
||||
val currentMillis = System.currentTimeMillis()
|
||||
val sessionExpired = currentMillis > sessionExpireMillis
|
||||
val appLocked = lockEnabled && !appActive && sessionExpired
|
||||
|
||||
Log.d(TAG, "isAppLocked(): $appLocked. (LockEnabled: $lockEnabled, appActive: $appActive, expireMillis: $sessionExpireMillis, currentMillis: $currentMillis)")
|
||||
return appLocked
|
||||
}
|
||||
|
||||
override suspend fun setAppActive(active: Boolean) {
|
||||
if (!active) {
|
||||
setSessionExpireMillis(System.currentTimeMillis() + (getSessionTimeOut() * 1000) + APPLOCK_TIMEOUT_GRACE_MS)
|
||||
}
|
||||
Log.d(TAG, "setAppActive(): $active")
|
||||
appActive = active
|
||||
}
|
||||
|
||||
override suspend fun sessionTimeOut(value: Int) {
|
||||
localStorage.putInt(PREF_SESSION_TIMEOUT, value)
|
||||
}
|
||||
|
@ -382,10 +405,11 @@ class IntegrationRepositoryImpl @Inject constructor(
|
|||
}
|
||||
|
||||
override suspend fun setSessionExpireMillis(value: Long) {
|
||||
Log.d(TAG, "setSessionExpireMillis(): $value")
|
||||
localStorage.putLong(PREF_SESSION_EXPIRE, value)
|
||||
}
|
||||
|
||||
override suspend fun getSessionExpireMillis(): Long {
|
||||
private suspend fun getSessionExpireMillis(): Long {
|
||||
return localStorage.getLong(PREF_SESSION_EXPIRE) ?: 0
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue