From aa3c4d06e10cfa1e54ff3823c95b95d06d3af012 Mon Sep 17 00:00:00 2001 From: Jonas L Date: Mon, 11 Mar 2019 00:00:00 +0000 Subject: [PATCH] Add deleting old used time items --- .../timelimit/android/data/dao/UsedTimeDao.kt | 3 + .../android/logic/BackgroundTaskLogic.kt | 36 +++++++++-- .../android/logic/DayChangeTracker.kt | 60 +++++++++++++++++++ .../timelimit/android/logic/RealTimeLogic.kt | 12 +++- .../android/logic/UsedTimeDeleter.kt | 45 ++++++++++++++ 5 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/io/timelimit/android/logic/DayChangeTracker.kt create mode 100644 app/src/main/java/io/timelimit/android/logic/UsedTimeDeleter.kt diff --git a/app/src/main/java/io/timelimit/android/data/dao/UsedTimeDao.kt b/app/src/main/java/io/timelimit/android/data/dao/UsedTimeDao.kt index 86864a1..ff492b1 100644 --- a/app/src/main/java/io/timelimit/android/data/dao/UsedTimeDao.kt +++ b/app/src/main/java/io/timelimit/android/data/dao/UsedTimeDao.kt @@ -60,6 +60,9 @@ abstract class UsedTimeDao { @Query("DELETE FROM used_time WHERE category_id = :categoryId") abstract fun deleteUsedTimeItems(categoryId: String) + @Query("DELETE FROM used_time WHERE day_of_epoch < :lastDayToKeep") + abstract fun deleteOldUsedTimeItems(lastDayToKeep: Int) + @Query("SELECT * FROM used_time LIMIT :pageSize OFFSET :offset") abstract fun getUsedTimePageSync(offset: Int, pageSize: Int): List diff --git a/app/src/main/java/io/timelimit/android/logic/BackgroundTaskLogic.kt b/app/src/main/java/io/timelimit/android/logic/BackgroundTaskLogic.kt index 9629b43..9f242bd 100644 --- a/app/src/main/java/io/timelimit/android/logic/BackgroundTaskLogic.kt +++ b/app/src/main/java/io/timelimit/android/logic/BackgroundTaskLogic.kt @@ -128,6 +128,10 @@ class BackgroundTaskLogic(val appLogic: AppLogic) { private var usedTimeUpdateHelper: UsedTimeItemBatchUpdateHelper? = null private var previousMainLogicExecutionTime = 0 private var previousMainLoopEndTime = 0L + private val dayChangeTracker = DayChangeTracker( + timeApi = appLogic.timeApi, + longDuration = 1000 * 60 * 10 /* 10 minutes */ + ) private val appTitleCache = QueryAppTitleCache(appLogic.platformIntegration) @@ -184,6 +188,32 @@ class BackgroundTaskLogic(val appLogic: AppLogic) { // get the current time appLogic.realTimeLogic.getRealTime(realTime) + val nowTimestamp = realTime.timeInMillis + val nowTimezone = TimeZone.getTimeZone(deviceUserEntry.timeZone) + + val nowDate = DateInTimezone.newInstance(nowTimestamp, nowTimezone) + val minuteOfWeek = getMinuteOfWeek(nowTimestamp, nowTimezone) + + // eventually remove old used time data + if (realTime.shouldTrustTimePermanently) { + val dayChange = dayChangeTracker.reportDayChange(nowDate.dayOfEpoch) + + fun deleteOldUsedTimes() = UsedTimeDeleter.deleteOldUsedTimeItems( + database = appLogic.database, + date = nowDate + ) + + if (realTime.isNetworkTime) { + if (dayChange == DayChangeTracker.DayChange.Now) { + deleteOldUsedTimes() + } + } else { + if (dayChange == DayChangeTracker.DayChange.NowSinceLongerTime) { + deleteOldUsedTimes() + } + } + } + // get the categories val categories = childCategories.get(deviceUserEntry.id).waitForNonNullValue() val temporarilyAllowedApps = temporarilyAllowedApps.waitForNonNullValue() @@ -242,12 +272,6 @@ class BackgroundTaskLogic(val appLogic: AppLogic) { )) appLogic.platformIntegration.showAppLockScreen(foregroundAppPackageName) } else { - val nowTimestamp = realTime.timeInMillis - val nowTimezone = TimeZone.getTimeZone(deviceUserEntry.timeZone) - - val nowDate = DateInTimezone.newInstance(nowTimestamp, nowTimezone) - val minuteOfWeek = getMinuteOfWeek(nowTimestamp, nowTimezone) - // disable time limits temporarily feature if (realTime.shouldTrustTimeTemporarily && nowTimestamp < deviceUserEntry.disableLimitsUntil) { appLogic.platformIntegration.setAppStatusMessage(AppStatusMessage( diff --git a/app/src/main/java/io/timelimit/android/logic/DayChangeTracker.kt b/app/src/main/java/io/timelimit/android/logic/DayChangeTracker.kt new file mode 100644 index 0000000..6b90fa3 --- /dev/null +++ b/app/src/main/java/io/timelimit/android/logic/DayChangeTracker.kt @@ -0,0 +1,60 @@ +/* + * TimeLimit Copyright 2019 Jonas Lochmann + * + * 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 + * the Free Software Foundation version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.timelimit.android.logic + +import io.timelimit.android.integration.time.TimeApi + +class DayChangeTracker (private val timeApi: TimeApi, private val longDuration: Long) { + private var lastDayOfEpoch = -1 + private var lastDayOfEpochChange = -1L + private var lastReportedDayChangeDuration = -1L + + fun reportDayChange(newDay: Int): DayChange { + val uptime = timeApi.getCurrentUptimeInMillis() + + return if (lastDayOfEpoch != newDay) { + lastDayOfEpochChange = uptime + lastDayOfEpoch = newDay + lastReportedDayChangeDuration = 0 + + DayChange.Now + } else { + val newDayChangeDuration = uptime - lastDayOfEpochChange + + try { + if (newDayChangeDuration >= longDuration && lastReportedDayChangeDuration < longDuration) { + DayChange.NowSinceLongerTime + } else { + DayChange.No + } + } finally { + lastReportedDayChangeDuration = newDayChangeDuration + } + } + } + + enum class DayChange { + No, + Now, + NowSinceLongerTime + } + + fun reset() { + lastDayOfEpoch = -1 + lastDayOfEpochChange = -1 + lastReportedDayChangeDuration = -1 + } +} \ No newline at end of file diff --git a/app/src/main/java/io/timelimit/android/logic/RealTimeLogic.kt b/app/src/main/java/io/timelimit/android/logic/RealTimeLogic.kt index 107e6cd..ba754a8 100644 --- a/app/src/main/java/io/timelimit/android/logic/RealTimeLogic.kt +++ b/app/src/main/java/io/timelimit/android/logic/RealTimeLogic.kt @@ -142,34 +142,41 @@ class RealTimeLogic(private val appLogic: AppLogic) { time.timeInMillis = systemTime time.shouldTrustTimeTemporarily = true time.shouldTrustTimePermanently = false + time.isNetworkTime = false } else if (deviceConfig.networkTime == NetworkTime.Disabled) { time.timeInMillis = systemTime time.shouldTrustTimeTemporarily = true time.shouldTrustTimePermanently = true + time.isNetworkTime = false } else if (deviceConfig.networkTime == NetworkTime.IfPossible) { if (uptimeRealTimeOffset != null) { time.timeInMillis = systemUptime + uptimeRealTimeOffset time.shouldTrustTimeTemporarily = true time.shouldTrustTimePermanently = true + time.isNetworkTime = true } else { time.timeInMillis = systemTime time.shouldTrustTimeTemporarily = true time.shouldTrustTimePermanently = true + time.isNetworkTime = false } } else if (deviceConfig.networkTime == NetworkTime.Enabled) { if (uptimeRealTimeOffset != null) { time.timeInMillis = systemUptime + uptimeRealTimeOffset time.shouldTrustTimeTemporarily = true time.shouldTrustTimePermanently = true + time.isNetworkTime = true } else if (confirmedUptimeSystemTimeOffset != null) { time.timeInMillis = systemUptime + confirmedUptimeSystemTimeOffset time.shouldTrustTimeTemporarily = true time.shouldTrustTimePermanently = false + time.isNetworkTime = false } else { time.timeInMillis = systemTime // 5 seconds grace period time.shouldTrustTimeTemporarily = requireRemoteTimeUptime + 5000 > systemUptime time.shouldTrustTimePermanently = false + time.isNetworkTime = false } } else { throw IllegalStateException() @@ -199,9 +206,10 @@ class RealTimeLogic(private val appLogic: AppLogic) { data class RealTime( var timeInMillis: Long, var shouldTrustTimeTemporarily: Boolean, - var shouldTrustTimePermanently: Boolean + var shouldTrustTimePermanently: Boolean, + var isNetworkTime: Boolean ) { companion object { - fun newInstance() = RealTime(0, false, false) + fun newInstance() = RealTime(0, false, false, false) } } diff --git a/app/src/main/java/io/timelimit/android/logic/UsedTimeDeleter.kt b/app/src/main/java/io/timelimit/android/logic/UsedTimeDeleter.kt new file mode 100644 index 0000000..df737b0 --- /dev/null +++ b/app/src/main/java/io/timelimit/android/logic/UsedTimeDeleter.kt @@ -0,0 +1,45 @@ +/* + * TimeLimit Copyright 2019 Jonas Lochmann + * + * 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 + * the Free Software Foundation version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.timelimit.android.logic + +import io.timelimit.android.async.Threads +import io.timelimit.android.data.Database +import io.timelimit.android.data.transaction +import io.timelimit.android.date.DateInTimezone + +object UsedTimeDeleter { + fun deleteOldUsedTimeItems(database: Database, date: DateInTimezone) { + Threads.database.execute { + database.transaction().use { + if (database.config().getDeviceAuthTokenSync().isNotEmpty()) { + // using the connected mode + // => server does the deletion + return@execute + } + + if (database.config().getOwnDeviceIdSync() == null) { + // not configured + // => no need to delete anything + return@execute + } + + database.usedTimes().deleteOldUsedTimeItems(lastDayToKeep = date.dayOfEpoch - date.dayOfWeek) + + it.setSuccess() + } + } + } +} \ No newline at end of file