Keep annoy unblock counter during reboot

This commit is contained in:
Jonas Lochmann 2022-03-07 01:00:00 +01:00
parent d72b6801dd
commit d4bfa37caf
No known key found for this signature in database
GPG key ID: 8B8C9AEE10FA5B36
6 changed files with 1323 additions and 6 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* /*
* TimeLimit Copyright <C> 2019 - 2021 Jonas Lochmann * TimeLimit Copyright <C> 2019 - 2022 Jonas Lochmann
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -274,4 +274,10 @@ object DatabaseMigrations {
database.execSQL("ALTER TABLE category ADD COLUMN block_notification_delay INTEGER NOT NULL DEFAULT 0") database.execSQL("ALTER TABLE category ADD COLUMN block_notification_delay INTEGER NOT NULL DEFAULT 0")
} }
} }
val MIGRATE_TO_V39 = object: Migration(38, 39) {
override fun migrate(database: SupportSQLiteDatabase) {
// nothing to do, there was just a new config item type added
}
}
} }

View file

@ -51,7 +51,7 @@ import java.util.concurrent.TimeUnit
UserLimitLoginCategory::class, UserLimitLoginCategory::class,
CategoryNetworkId::class, CategoryNetworkId::class,
ChildTask::class ChildTask::class
], version = 38) ], version = 39)
abstract class RoomDatabase: RoomDatabase(), io.timelimit.android.data.Database { abstract class RoomDatabase: RoomDatabase(), io.timelimit.android.data.Database {
companion object { companion object {
private val lock = Object() private val lock = Object()
@ -123,7 +123,8 @@ abstract class RoomDatabase: RoomDatabase(), io.timelimit.android.data.Database
DatabaseMigrations.MIGRATE_TO_V35, DatabaseMigrations.MIGRATE_TO_V35,
DatabaseMigrations.MIGRATE_TO_V36, DatabaseMigrations.MIGRATE_TO_V36,
DatabaseMigrations.MIGRATE_TO_V37, DatabaseMigrations.MIGRATE_TO_V37,
DatabaseMigrations.MIGRATE_TO_V38 DatabaseMigrations.MIGRATE_TO_V38,
DatabaseMigrations.MIGRATE_TO_V39
) )
.setQueryExecutor(Threads.database) .setQueryExecutor(Threads.database)
.addCallback(object: Callback() { .addCallback(object: Callback() {

View file

@ -327,4 +327,7 @@ abstract class ConfigDao {
fun getServerApiLevelSync() = getValueOfKeySync(ConfigurationItemType.ServerApiLevel).let { it?.toInt() ?: 0 } fun getServerApiLevelSync() = getValueOfKeySync(ConfigurationItemType.ServerApiLevel).let { it?.toInt() ?: 0 }
fun getServerApiLevelLive() = getValueOfKeyAsync(ConfigurationItemType.ServerApiLevel).map { it?.toInt() ?: 0 } fun getServerApiLevelLive() = getValueOfKeyAsync(ConfigurationItemType.ServerApiLevel).map { it?.toInt() ?: 0 }
fun setServerApiLevelSync(serverApiLevel: Int) { updateValueSync(ConfigurationItemType.ServerApiLevel, serverApiLevel.toString()) } fun setServerApiLevelSync(serverApiLevel: Int) { updateValueSync(ConfigurationItemType.ServerApiLevel, serverApiLevel.toString()) }
fun getAnnoyManualUnblockCounter() = getValueOfKeySync(ConfigurationItemType.AnnoyManualUnblockCounter).let { it?.toInt() ?: 0 }
fun setAnoyManualUnblockCounterSync(counter: Int) { updateValueSync(ConfigurationItemType.AnnoyManualUnblockCounter, counter.toString()) }
} }

View file

@ -99,7 +99,8 @@ enum class ConfigurationItemType {
EnableUpdates, EnableUpdates,
UpdateStatus, UpdateStatus,
CustomOrganizationName, CustomOrganizationName,
ServerApiLevel ServerApiLevel,
AnnoyManualUnblockCounter,
} }
object ConfigurationItemTypeUtil { object ConfigurationItemTypeUtil {
@ -126,6 +127,7 @@ object ConfigurationItemTypeUtil {
private const val UPDATE_STATUS = 22 private const val UPDATE_STATUS = 22
private const val CUSTOM_ORGANIZATION_NAME = 23 private const val CUSTOM_ORGANIZATION_NAME = 23
private const val SERVER_API_LEVEL = 24 private const val SERVER_API_LEVEL = 24
private const val ANNOY_MANUAL_UNBLOCK_COUNTER = 25
val TYPES = listOf( val TYPES = listOf(
ConfigurationItemType.OwnDeviceId, ConfigurationItemType.OwnDeviceId,
@ -150,7 +152,8 @@ object ConfigurationItemTypeUtil {
ConfigurationItemType.EnableUpdates, ConfigurationItemType.EnableUpdates,
ConfigurationItemType.UpdateStatus, ConfigurationItemType.UpdateStatus,
ConfigurationItemType.CustomOrganizationName, ConfigurationItemType.CustomOrganizationName,
ConfigurationItemType.ServerApiLevel ConfigurationItemType.ServerApiLevel,
ConfigurationItemType.AnnoyManualUnblockCounter
) )
fun serialize(value: ConfigurationItemType) = when(value) { fun serialize(value: ConfigurationItemType) = when(value) {
@ -177,6 +180,7 @@ object ConfigurationItemTypeUtil {
ConfigurationItemType.UpdateStatus -> UPDATE_STATUS ConfigurationItemType.UpdateStatus -> UPDATE_STATUS
ConfigurationItemType.CustomOrganizationName -> CUSTOM_ORGANIZATION_NAME ConfigurationItemType.CustomOrganizationName -> CUSTOM_ORGANIZATION_NAME
ConfigurationItemType.ServerApiLevel -> SERVER_API_LEVEL ConfigurationItemType.ServerApiLevel -> SERVER_API_LEVEL
ConfigurationItemType.AnnoyManualUnblockCounter -> ANNOY_MANUAL_UNBLOCK_COUNTER
} }
fun parse(value: Int) = when(value) { fun parse(value: Int) = when(value) {
@ -203,6 +207,7 @@ object ConfigurationItemTypeUtil {
UPDATE_STATUS -> ConfigurationItemType.UpdateStatus UPDATE_STATUS -> ConfigurationItemType.UpdateStatus
CUSTOM_ORGANIZATION_NAME -> ConfigurationItemType.CustomOrganizationName CUSTOM_ORGANIZATION_NAME -> ConfigurationItemType.CustomOrganizationName
SERVER_API_LEVEL -> ConfigurationItemType.ServerApiLevel SERVER_API_LEVEL -> ConfigurationItemType.ServerApiLevel
ANNOY_MANUAL_UNBLOCK_COUNTER -> ConfigurationItemType.AnnoyManualUnblockCounter
else -> throw IllegalArgumentException() else -> throw IllegalArgumentException()
} }
} }

View file

@ -15,11 +15,13 @@
*/ */
package io.timelimit.android.logic package io.timelimit.android.logic
import android.os.Build import android.util.Log
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
import io.timelimit.android.BuildConfig import io.timelimit.android.BuildConfig
import io.timelimit.android.async.Threads import io.timelimit.android.async.Threads
import io.timelimit.android.coroutines.executeAndWait
import io.timelimit.android.coroutines.runAsync
import io.timelimit.android.integration.platform.ProtectionLevel import io.timelimit.android.integration.platform.ProtectionLevel
import io.timelimit.android.livedata.* import io.timelimit.android.livedata.*
@ -27,6 +29,7 @@ class AnnoyLogic (val appLogic: AppLogic) {
// config // config
companion object { companion object {
private const val ENABLE = !BuildConfig.storeCompilant private const val ENABLE = !BuildConfig.storeCompilant
private const val LOG_TAG = "AnnoyLogic"
private const val TEMP_UNBLOCK_DURATION = 1000 * 45L private const val TEMP_UNBLOCK_DURATION = 1000 * 45L
private const val TEMP_UNBLOCK_PARENT_DURATION = 1000 * 60 * 10L private const val TEMP_UNBLOCK_PARENT_DURATION = 1000 * 60 * 10L
@ -87,6 +90,7 @@ class AnnoyLogic (val appLogic: AppLogic) {
nextManualUnblockTimestamp = now + manualUnblockDelay(manualUnblockCounter) nextManualUnblockTimestamp = now + manualUnblockDelay(manualUnblockCounter)
enableTempDisabled(TEMP_UNBLOCK_DURATION) enableTempDisabled(TEMP_UNBLOCK_DURATION)
saveManualUnblockCounterAsync()
} }
// input: trigger temp unblock by parents (event) // input: trigger temp unblock by parents (event)
@ -95,8 +99,10 @@ class AnnoyLogic (val appLogic: AppLogic) {
nextManualUnblockTimestamp = now() nextManualUnblockTimestamp = now()
enableTempDisabled(TEMP_UNBLOCK_PARENT_DURATION) enableTempDisabled(TEMP_UNBLOCK_PARENT_DURATION)
saveManualUnblockCounterAsync()
} }
// helper functions
private fun enableTempDisabled(duration: Long) { private fun enableTempDisabled(duration: Long) {
annoyTempDisabled.value = true annoyTempDisabled.value = true
@ -104,4 +110,75 @@ class AnnoyLogic (val appLogic: AppLogic) {
Threads.mainThreadHandler.postDelayed(annoyTempDisabledSetFalse, duration) Threads.mainThreadHandler.postDelayed(annoyTempDisabledSetFalse, duration)
isManipulated.observeForever(resetTempDisabledObserver) isManipulated.observeForever(resetTempDisabledObserver)
} }
// state saving and restoring
private fun saveManualUnblockCounterAsync() {
Threads.mainThreadHandler.removeCallbacks(saveZeroUnblockCounterRunnable)
Threads.database.execute {
try {
appLogic.database.config().setAnoyManualUnblockCounterSync(manualUnblockCounter)
} catch (ex: Exception) {
if (BuildConfig.DEBUG) {
Log.w(LOG_TAG, "could not save unblock counter value", ex)
}
}
}
eventuallyScheduleResetOfStoredCounter()
}
private fun eventuallyScheduleResetOfStoredCounter() {
if (manualUnblockCounter > 0) {
val now = now()
val resetTimestamp = nextManualUnblockTimestamp + manualUnblockDelay(manualUnblockCounter)
val resetDelay = resetTimestamp - now
if (resetDelay > 0) {
if (BuildConfig.DEBUG) {
Log.d(LOG_TAG, "scheduled counter reset in ${resetDelay/1000} seconds")
}
Threads.mainThreadHandler.postDelayed(saveZeroUnblockCounterRunnable, resetDelay)
}
}
}
private val saveZeroUnblockCounterRunnable = Runnable {
Threads.database.execute {
if (BuildConfig.DEBUG) {
Log.d(LOG_TAG, "reset counter now")
}
try {
appLogic.database.config().setAnoyManualUnblockCounterSync(0)
} catch (ex: Exception) {
if (BuildConfig.DEBUG) {
Log.w(LOG_TAG, "could not reset saved counter value", ex)
}
}
}
}
init {
runAsync {
try {
val counter = Threads.database.executeAndWait {
appLogic.database.config().getAnnoyManualUnblockCounter()
}
val now = now()
if (counter > 0) {
manualUnblockCounter = counter
nextManualUnblockTimestamp = now + manualUnblockDelay(manualUnblockCounter)
eventuallyScheduleResetOfStoredCounter()
}
} catch (ex: Exception) {
if (BuildConfig.DEBUG) {
Log.w(LOG_TAG, "could not load saved counter", ex)
}
}
}
}
} }