diff --git a/app/src/main/kotlin/com/wire/android/di/AppModule.kt b/app/src/main/kotlin/com/wire/android/di/AppModule.kt index 3fdc3230101..6395f4ca06f 100644 --- a/app/src/main/kotlin/com/wire/android/di/AppModule.kt +++ b/app/src/main/kotlin/com/wire/android/di/AppModule.kt @@ -27,6 +27,7 @@ import android.media.MediaPlayer import androidx.core.app.NotificationManagerCompat import com.wire.android.BuildConfig import com.wire.android.mapper.MessageResourceProvider +import com.wire.android.ui.home.appLock.CurrentTimestampProvider import com.wire.android.util.dispatchers.DefaultDispatcherProvider import com.wire.android.util.dispatchers.DispatcherProvider import dagger.Module @@ -79,4 +80,8 @@ object AppModule { ) } } + + @Singleton + @Provides + fun provideCurrentTimestampProvider(): CurrentTimestampProvider = { System.currentTimeMillis() } } diff --git a/app/src/main/kotlin/com/wire/android/ui/home/appLock/LockCodeTimeManager.kt b/app/src/main/kotlin/com/wire/android/ui/home/appLock/LockCodeTimeManager.kt index dcd702ff654..d10ac19158b 100644 --- a/app/src/main/kotlin/com/wire/android/ui/home/appLock/LockCodeTimeManager.kt +++ b/app/src/main/kotlin/com/wire/android/ui/home/appLock/LockCodeTimeManager.kt @@ -55,9 +55,11 @@ class LockCodeTimeManager @Inject constructor( currentScreenManager: CurrentScreenManager, observeAppLockConfigUseCase: ObserveAppLockConfigUseCase, globalDataStore: GlobalDataStore, + currentTimestamp: CurrentTimestampProvider, ) { - private lateinit var isLockedFlow: MutableStateFlow + private var isLockedFlow: MutableStateFlow + private var lockTimeoutStarted: Long? = null init { runBlocking { @@ -77,13 +79,26 @@ class LockCodeTimeManager @Inject constructor( when { appLockConfig is AppLockConfig.Disabled -> flowOf(false) - !isInForeground && !isLockedFlow.value -> flow { + !isInForeground && !isLockedFlow.value && appLockConfig is AppLockConfig.Enabled -> flow { appLogger.i("$TAG lock is enabled and app in the background, lock count started") + if (lockTimeoutStarted == null) { + lockTimeoutStarted = currentTimestamp() + } delay(appLockConfig.timeout.inWholeMilliseconds) - appLogger.i("$TAG lock count ended, app state should be locked if passcode is set") + appLogger.i("$TAG lock count ended while app in the background, app state should be locked") + emit(true) + } - if (appLockConfig is AppLockConfig.Enabled) { + isInForeground && !isLockedFlow.value && appLockConfig is AppLockConfig.Enabled -> flow { + if (lockTimeoutStarted != null + && (lockTimeoutStarted!! + appLockConfig.timeout.inWholeMilliseconds) < currentTimestamp() + ) { + appLogger.i("$TAG app put into foreground and lock count ended, app state should be locked") emit(true) + } else { + appLogger.i("$TAG app put into foreground but lock count hasn't ended, app state should not be changed") + emit(false) + lockTimeoutStarted = null } } @@ -101,6 +116,7 @@ class LockCodeTimeManager @Inject constructor( fun appUnlocked() { appLogger.i("$TAG app unlocked") isLockedFlow.value = false + lockTimeoutStarted = null } fun isAppLocked(): Boolean = isLockedFlow.value @@ -111,3 +127,5 @@ class LockCodeTimeManager @Inject constructor( private const val TAG = "LockCodeTimeManager" } } + +typealias CurrentTimestampProvider = () -> Long diff --git a/app/src/test/kotlin/com/wire/android/ui/home/appLock/LockCodeTimeManagerTest.kt b/app/src/test/kotlin/com/wire/android/ui/home/appLock/LockCodeTimeManagerTest.kt index a5fbe32b9d4..da45eb2ab96 100644 --- a/app/src/test/kotlin/com/wire/android/ui/home/appLock/LockCodeTimeManagerTest.kt +++ b/app/src/test/kotlin/com/wire/android/ui/home/appLock/LockCodeTimeManagerTest.kt @@ -175,6 +175,7 @@ class LockCodeTimeManagerTest { arrangement.withIsAppVisible(false) advanceTimeBy(startDelay) arrangement.withIsAppVisible(true) + advanceUntilIdle() // then assertEquals(expected, manager.observeAppLock().first()) } @@ -297,7 +298,8 @@ class LockCodeTimeManagerTest { CoroutineScope(dispatcher), currentScreenManager, observeAppLockConfigUseCase, - globalDataStore + globalDataStore, + dispatcher.scheduler::currentTime ) }