mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-03 09:49:25 +02:00
Process network ids for the limit login categories
This commit is contained in:
parent
2f85752b97
commit
c1f79878fc
1 changed files with 109 additions and 20 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* TimeLimit Copyright <C> 2019 - 2020 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
|
||||||
|
@ -23,25 +23,51 @@ import io.timelimit.android.data.extensions.getCategoryWithParentCategories
|
||||||
import io.timelimit.android.data.model.ExperimentalFlags
|
import io.timelimit.android.data.model.ExperimentalFlags
|
||||||
import io.timelimit.android.data.model.derived.CompleteUserLoginRelatedData
|
import io.timelimit.android.data.model.derived.CompleteUserLoginRelatedData
|
||||||
import io.timelimit.android.integration.platform.BatteryStatus
|
import io.timelimit.android.integration.platform.BatteryStatus
|
||||||
|
import io.timelimit.android.integration.platform.NetworkId
|
||||||
|
import io.timelimit.android.livedata.ignoreUnchanged
|
||||||
|
import io.timelimit.android.livedata.liveDataFromFunction
|
||||||
import io.timelimit.android.logic.AppLogic
|
import io.timelimit.android.logic.AppLogic
|
||||||
import io.timelimit.android.logic.BlockingReason
|
import io.timelimit.android.logic.BlockingReason
|
||||||
import io.timelimit.android.logic.RealTime
|
import io.timelimit.android.logic.RealTime
|
||||||
import io.timelimit.android.logic.blockingreason.CategoryHandlingCache
|
import io.timelimit.android.logic.blockingreason.CategoryHandlingCache
|
||||||
|
import java.lang.IllegalStateException
|
||||||
import java.util.concurrent.CountDownLatch
|
import java.util.concurrent.CountDownLatch
|
||||||
|
|
||||||
sealed class AllowUserLoginStatus {
|
sealed class AllowUserLoginStatus {
|
||||||
data class Allow(val maxTime: Long): AllowUserLoginStatus()
|
open val dependsOnNetworkId = false
|
||||||
data class ForbidByCategory(val categoryTitle: String, val blockingReason: BlockingReason, val maxTime: Long): AllowUserLoginStatus()
|
|
||||||
|
data class Allow(
|
||||||
|
val maxTime: Long,
|
||||||
|
override val dependsOnNetworkId: Boolean
|
||||||
|
): AllowUserLoginStatus()
|
||||||
|
|
||||||
|
data class ForbidByCategory(
|
||||||
|
val categoryTitle: String,
|
||||||
|
val blockingReason: BlockingReason,
|
||||||
|
val maxTime: Long,
|
||||||
|
override val dependsOnNetworkId: Boolean
|
||||||
|
): AllowUserLoginStatus()
|
||||||
|
|
||||||
object ForbidByMissingSync: AllowUserLoginStatus()
|
object ForbidByMissingSync: AllowUserLoginStatus()
|
||||||
object ForbidUserNotFound: AllowUserLoginStatus()
|
object ForbidUserNotFound: AllowUserLoginStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
object AllowUserLoginStatusUtil {
|
object AllowUserLoginStatusUtil {
|
||||||
private fun calculate(data: CompleteUserLoginRelatedData, time: RealTime, cache: CategoryHandlingCache, batteryStatus: BatteryStatus, missingSyncForLimitLoginUser: Boolean): AllowUserLoginStatus = synchronized(cache) {
|
private fun calculate(
|
||||||
|
data: CompleteUserLoginRelatedData,
|
||||||
|
time: RealTime,
|
||||||
|
cache: CategoryHandlingCache,
|
||||||
|
batteryStatus: BatteryStatus,
|
||||||
|
missingSyncForLimitLoginUser: Boolean,
|
||||||
|
currentNetworkId: NetworkId?
|
||||||
|
): AllowUserLoginStatus = synchronized(cache) {
|
||||||
val hasPremium = data.deviceRelatedData.isConnectedAndHasPremium || data.deviceRelatedData.isLocalMode
|
val hasPremium = data.deviceRelatedData.isConnectedAndHasPremium || data.deviceRelatedData.isLocalMode
|
||||||
|
|
||||||
if (!hasPremium) {
|
if (!hasPremium) {
|
||||||
return AllowUserLoginStatus.Allow(maxTime = Long.MAX_VALUE)
|
return AllowUserLoginStatus.Allow(
|
||||||
|
maxTime = Long.MAX_VALUE,
|
||||||
|
dependsOnNetworkId = false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (data.limitLoginCategoryUserRelatedData != null && data.loginRelatedData.limitLoginCategory != null) {
|
return if (data.limitLoginCategoryUserRelatedData != null && data.loginRelatedData.limitLoginCategory != null) {
|
||||||
|
@ -52,6 +78,7 @@ object AllowUserLoginStatusUtil {
|
||||||
val preBlockDuration = data.loginRelatedData.limitLoginCategory.preBlockDuration
|
val preBlockDuration = data.loginRelatedData.limitLoginCategory.preBlockDuration
|
||||||
val maxCheckedTime = time.timeInMillis + preBlockDuration
|
val maxCheckedTime = time.timeInMillis + preBlockDuration
|
||||||
val categoryIds = data.limitLoginCategoryUserRelatedData.getCategoryWithParentCategories(data.loginRelatedData.limitLoginCategory.categoryId)
|
val categoryIds = data.limitLoginCategoryUserRelatedData.getCategoryWithParentCategories(data.loginRelatedData.limitLoginCategory.categoryId)
|
||||||
|
var dependsOnAnyNetworkId = false
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
cache.reportStatus(
|
cache.reportStatus(
|
||||||
|
@ -60,18 +87,21 @@ object AllowUserLoginStatusUtil {
|
||||||
timeInMillis = currentCheckedTime,
|
timeInMillis = currentCheckedTime,
|
||||||
shouldTrustTimeTemporarily = time.shouldTrustTimeTemporarily,
|
shouldTrustTimeTemporarily = time.shouldTrustTimeTemporarily,
|
||||||
batteryStatus = batteryStatus,
|
batteryStatus = batteryStatus,
|
||||||
currentNetworkId = null, // only checks shouldBlockAtSystemLevel which ignores the network id
|
currentNetworkId = currentNetworkId,
|
||||||
hasPremiumOrLocalMode = data.deviceRelatedData.isLocalMode || data.deviceRelatedData.isConnectedAndHasPremium
|
hasPremiumOrLocalMode = data.deviceRelatedData.isLocalMode || data.deviceRelatedData.isConnectedAndHasPremium
|
||||||
)
|
)
|
||||||
|
|
||||||
val handlings = categoryIds.map { cache.get(it) }
|
val handlings = categoryIds.map { cache.get(it) }
|
||||||
val remainingTimeToCheck = maxCheckedTime - currentCheckedTime
|
val remainingTimeToCheck = maxCheckedTime - currentCheckedTime
|
||||||
|
|
||||||
|
dependsOnAnyNetworkId = dependsOnAnyNetworkId or (handlings.find { it.dependsOnNetworkId } != null)
|
||||||
|
|
||||||
handlings.find { it.remainingSessionDuration != null && it.remainingSessionDuration < remainingTimeToCheck }?.let { blockingHandling ->
|
handlings.find { it.remainingSessionDuration != null && it.remainingSessionDuration < remainingTimeToCheck }?.let { blockingHandling ->
|
||||||
return AllowUserLoginStatus.ForbidByCategory(
|
return AllowUserLoginStatus.ForbidByCategory(
|
||||||
categoryTitle = blockingHandling.createdWithCategoryRelatedData.category.title,
|
categoryTitle = blockingHandling.createdWithCategoryRelatedData.category.title,
|
||||||
blockingReason = BlockingReason.SessionDurationLimit,
|
blockingReason = BlockingReason.SessionDurationLimit,
|
||||||
maxTime = blockingHandling.dependsOnMaxTime
|
maxTime = blockingHandling.dependsOnMaxTime,
|
||||||
|
dependsOnNetworkId = dependsOnAnyNetworkId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +109,8 @@ object AllowUserLoginStatusUtil {
|
||||||
return AllowUserLoginStatus.ForbidByCategory(
|
return AllowUserLoginStatus.ForbidByCategory(
|
||||||
categoryTitle = blockingHandling.createdWithCategoryRelatedData.category.title,
|
categoryTitle = blockingHandling.createdWithCategoryRelatedData.category.title,
|
||||||
blockingReason = BlockingReason.TimeOver,
|
blockingReason = BlockingReason.TimeOver,
|
||||||
maxTime = blockingHandling.dependsOnMaxTime
|
maxTime = blockingHandling.dependsOnMaxTime,
|
||||||
|
dependsOnNetworkId = dependsOnAnyNetworkId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +118,19 @@ object AllowUserLoginStatusUtil {
|
||||||
return AllowUserLoginStatus.ForbidByCategory(
|
return AllowUserLoginStatus.ForbidByCategory(
|
||||||
categoryTitle = blockingHandling.createdWithCategoryRelatedData.category.title,
|
categoryTitle = blockingHandling.createdWithCategoryRelatedData.category.title,
|
||||||
blockingReason = blockingHandling.systemLevelBlockingReason,
|
blockingReason = blockingHandling.systemLevelBlockingReason,
|
||||||
maxTime = blockingHandling.dependsOnMaxTime
|
maxTime = blockingHandling.dependsOnMaxTime,
|
||||||
|
dependsOnNetworkId = dependsOnAnyNetworkId
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
handlings.find { !it.okByNetworkId }?.let { blockingHandling ->
|
||||||
|
if (!dependsOnAnyNetworkId) throw IllegalStateException()
|
||||||
|
|
||||||
|
return AllowUserLoginStatus.ForbidByCategory(
|
||||||
|
categoryTitle = blockingHandling.createdWithCategoryRelatedData.category.title,
|
||||||
|
blockingReason = blockingHandling.activityBlockingReason,
|
||||||
|
maxTime = Long.MAX_VALUE,
|
||||||
|
dependsOnNetworkId = dependsOnAnyNetworkId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,12 +144,14 @@ object AllowUserLoginStatusUtil {
|
||||||
val maxTimeByCategories = categoryIds.map { cache.get(it) }.minByOrNull { it.dependsOnMaxTime }?.dependsOnMaxTime ?: Long.MAX_VALUE
|
val maxTimeByCategories = categoryIds.map { cache.get(it) }.minByOrNull { it.dependsOnMaxTime }?.dependsOnMaxTime ?: Long.MAX_VALUE
|
||||||
|
|
||||||
AllowUserLoginStatus.Allow(
|
AllowUserLoginStatus.Allow(
|
||||||
maxTime = (maxTimeByCategories - preBlockDuration).coerceAtLeast(time.timeInMillis + 1000)
|
maxTime = (maxTimeByCategories - preBlockDuration).coerceAtLeast(time.timeInMillis + 1000),
|
||||||
|
dependsOnNetworkId = dependsOnAnyNetworkId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AllowUserLoginStatus.Allow(
|
AllowUserLoginStatus.Allow(
|
||||||
maxTime = Long.MAX_VALUE
|
maxTime = Long.MAX_VALUE,
|
||||||
|
dependsOnNetworkId = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,27 +163,54 @@ object AllowUserLoginStatusUtil {
|
||||||
val userRelatedData = logic.database.derivedDataDao().getUserLoginRelatedDataSync(userId) ?: return AllowUserLoginStatus.ForbidUserNotFound
|
val userRelatedData = logic.database.derivedDataDao().getUserLoginRelatedDataSync(userId) ?: return AllowUserLoginStatus.ForbidUserNotFound
|
||||||
val realTime = RealTime.newInstance()
|
val realTime = RealTime.newInstance()
|
||||||
val batteryStatus = logic.platformIntegration.getBatteryStatus()
|
val batteryStatus = logic.platformIntegration.getBatteryStatus()
|
||||||
val latch = CountDownLatch(1)
|
|
||||||
|
|
||||||
Threads.mainThreadHandler.post {
|
CountDownLatch(1).let { latch ->
|
||||||
logic.realTimeLogic.getRealTime(realTime)
|
Threads.mainThreadHandler.post {
|
||||||
latch.countDown()
|
logic.realTimeLogic.getRealTime(realTime)
|
||||||
|
latch.countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
latch.await()
|
||||||
}
|
}
|
||||||
|
|
||||||
latch.await()
|
val attempt1 = calculate(
|
||||||
|
data = userRelatedData,
|
||||||
|
batteryStatus = batteryStatus,
|
||||||
|
time = realTime,
|
||||||
|
cache = CategoryHandlingCache(),
|
||||||
|
missingSyncForLimitLoginUser = requireSyncOnLimitLoginUser && !didSync,
|
||||||
|
currentNetworkId = null
|
||||||
|
)
|
||||||
|
|
||||||
return calculate(
|
return if (attempt1.dependsOnNetworkId) {
|
||||||
|
val currentNetworkId = CountDownLatch(1).let { latch ->
|
||||||
|
var currentNetworkId: NetworkId? = null
|
||||||
|
|
||||||
|
Threads.mainThreadHandler.post {
|
||||||
|
currentNetworkId = logic.platformIntegration.getCurrentNetworkId()
|
||||||
|
latch.countDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
latch.await()
|
||||||
|
|
||||||
|
currentNetworkId!!
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate(
|
||||||
data = userRelatedData,
|
data = userRelatedData,
|
||||||
batteryStatus = batteryStatus,
|
batteryStatus = batteryStatus,
|
||||||
time = realTime,
|
time = realTime,
|
||||||
cache = CategoryHandlingCache(),
|
cache = CategoryHandlingCache(),
|
||||||
missingSyncForLimitLoginUser = requireSyncOnLimitLoginUser && !didSync
|
missingSyncForLimitLoginUser = requireSyncOnLimitLoginUser && !didSync,
|
||||||
)
|
currentNetworkId = currentNetworkId
|
||||||
|
)
|
||||||
|
} else attempt1
|
||||||
}
|
}
|
||||||
|
|
||||||
fun calculateLive(logic: AppLogic, userId: String, didSyncLive: LiveData<Boolean>): LiveData<AllowUserLoginStatus> = object : MediatorLiveData<AllowUserLoginStatus>() {
|
fun calculateLive(logic: AppLogic, userId: String, didSyncLive: LiveData<Boolean>): LiveData<AllowUserLoginStatus> = object : MediatorLiveData<AllowUserLoginStatus>() {
|
||||||
val cache = CategoryHandlingCache()
|
val cache = CategoryHandlingCache()
|
||||||
val time = RealTime.newInstance()
|
val time = RealTime.newInstance()
|
||||||
|
val currentNetworkIdLive = liveDataFromFunction { logic.platformIntegration.getCurrentNetworkId() }.ignoreUnchanged()
|
||||||
var batteryStatus: BatteryStatus? = null
|
var batteryStatus: BatteryStatus? = null
|
||||||
var hasUserLoginRelatedData = false
|
var hasUserLoginRelatedData = false
|
||||||
var userLoginRelatedData: CompleteUserLoginRelatedData? = null
|
var userLoginRelatedData: CompleteUserLoginRelatedData? = null
|
||||||
|
@ -147,6 +219,8 @@ object AllowUserLoginStatusUtil {
|
||||||
var isConnectedMode = false
|
var isConnectedMode = false
|
||||||
var didLoadIsConnectedMode = false
|
var didLoadIsConnectedMode = false
|
||||||
var didSync = false
|
var didSync = false
|
||||||
|
var isObservingNetworkId = false
|
||||||
|
var currentNetworkId: NetworkId? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
addSource(logic.platformIntegration.getBatteryStatusLive(), androidx.lifecycle.Observer {
|
addSource(logic.platformIntegration.getBatteryStatusLive(), androidx.lifecycle.Observer {
|
||||||
|
@ -194,7 +268,8 @@ object AllowUserLoginStatusUtil {
|
||||||
batteryStatus = batteryStatus,
|
batteryStatus = batteryStatus,
|
||||||
cache = cache,
|
cache = cache,
|
||||||
time = time,
|
time = time,
|
||||||
missingSyncForLimitLoginUser = isConnectedMode && requireSyncForLimitLoginUsers && !didSync
|
missingSyncForLimitLoginUser = isConnectedMode && requireSyncForLimitLoginUsers && !didSync,
|
||||||
|
currentNetworkId = currentNetworkId
|
||||||
)
|
)
|
||||||
|
|
||||||
if (result != value) {
|
if (result != value) {
|
||||||
|
@ -212,6 +287,20 @@ object AllowUserLoginStatusUtil {
|
||||||
logic.timeApi.cancelScheduledAction(updateRunnable)
|
logic.timeApi.cancelScheduledAction(updateRunnable)
|
||||||
logic.timeApi.runDelayedByUptime(updateRunnable, scheduledTime - time.timeInMillis)
|
logic.timeApi.runDelayedByUptime(updateRunnable, scheduledTime - time.timeInMillis)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (result.dependsOnNetworkId != isObservingNetworkId) {
|
||||||
|
// important detail: the addSource can call update immediately
|
||||||
|
isObservingNetworkId = result.dependsOnNetworkId
|
||||||
|
|
||||||
|
if (result.dependsOnNetworkId) {
|
||||||
|
addSource(currentNetworkIdLive) {
|
||||||
|
currentNetworkId = it; update()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
removeSource(currentNetworkIdLive)
|
||||||
|
currentNetworkId = null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActive() {
|
override fun onActive() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue