mirror of
https://codeberg.org/timelimit/timelimit-android.git
synced 2025-10-03 17:59:51 +02:00
Add more checks to InstanceIdForegroundAppHelper
This commit is contained in:
parent
1a19b9fcc3
commit
8b71b0f369
1 changed files with 46 additions and 4 deletions
|
@ -16,6 +16,7 @@
|
||||||
package io.timelimit.android.integration.platform.android.foregroundapp
|
package io.timelimit.android.integration.platform.android.foregroundapp
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
|
import android.app.usage.UsageEvents
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
|
@ -34,13 +35,14 @@ class InstanceIdForegroundAppHelper(context: Context): UsageStatsForegroundAppHe
|
||||||
private var lastQueryTime = 0L
|
private var lastQueryTime = 0L
|
||||||
private var lastEventTimestamp = 0L
|
private var lastEventTimestamp = 0L
|
||||||
private val apps = SparseArray<ForegroundApp>()
|
private val apps = SparseArray<ForegroundApp>()
|
||||||
|
private val nativeEvent = UsageEvents.Event()
|
||||||
|
|
||||||
override suspend fun getForegroundApps(
|
override suspend fun getForegroundApps(
|
||||||
queryInterval: Long,
|
queryInterval: Long,
|
||||||
experimentalFlags: Long
|
experimentalFlags: Long
|
||||||
): Set<ForegroundApp> {
|
): Set<ForegroundApp> {
|
||||||
if (Build.VERSION.SDK_INT > 32) {
|
if (Build.VERSION.SDK_INT > 32) {
|
||||||
throw UntestedSystemVersionException()
|
throw InstanceIdException.UntestedSystemVersionException()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getPermissionStatus() != RuntimePermissionStatus.Granted) {
|
if (getPermissionStatus() != RuntimePermissionStatus.Granted) {
|
||||||
|
@ -73,10 +75,42 @@ class InstanceIdForegroundAppHelper(context: Context): UsageStatsForegroundAppHe
|
||||||
|
|
||||||
usageStatsManager.queryEvents(queryStartTime, queryEndTime)?.let { nativeEvents ->
|
usageStatsManager.queryEvents(queryStartTime, queryEndTime)?.let { nativeEvents ->
|
||||||
val events = TlUsageEvents.fromUsageEvents(nativeEvents)
|
val events = TlUsageEvents.fromUsageEvents(nativeEvents)
|
||||||
|
var isFirstEvent = true
|
||||||
|
|
||||||
while (events.readNextItem()) {
|
while (true) {
|
||||||
lastEventTimestamp = events.timestamp
|
// loop condition with additional checks
|
||||||
|
val didReadEvent = kotlin.run {
|
||||||
|
val didReadNativeEvent = nativeEvents.getNextEvent(nativeEvent)
|
||||||
|
val didReadTlEvent = events.readNextItem()
|
||||||
|
|
||||||
|
if (didReadNativeEvent != didReadTlEvent) {
|
||||||
|
throw InstanceIdException.NotMatchingData(
|
||||||
|
if (didReadTlEvent) "events got next event but nativeEvents not"
|
||||||
|
else "nativeEvents got next event but events not"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
didReadTlEvent // == didReadNativeEvent
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!didReadEvent) break
|
||||||
|
|
||||||
|
// check the consistency
|
||||||
|
kotlin.run {
|
||||||
|
if (events.eventType != nativeEvent.eventType) {
|
||||||
|
throw InstanceIdException.NotMatchingData("got different eventTypes: ${events.eventType} vs ${nativeEvent.eventType}")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events.timestamp != nativeEvent.timeStamp) {
|
||||||
|
throw InstanceIdException.NotMatchingData("got different timestamps: ${events.timestamp} vs ${nativeEvent.timeStamp}")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events.timestamp < lastEventTimestamp && !isFirstEvent) {
|
||||||
|
throw InstanceIdException.EventsNotSortedByTimestamp()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// process the event
|
||||||
if (events.eventType == TlUsageEvents.DEVICE_STARTUP) {
|
if (events.eventType == TlUsageEvents.DEVICE_STARTUP) {
|
||||||
apps.clear()
|
apps.clear()
|
||||||
} else if (events.eventType == TlUsageEvents.MOVE_TO_FOREGROUND) {
|
} else if (events.eventType == TlUsageEvents.MOVE_TO_FOREGROUND) {
|
||||||
|
@ -89,6 +123,10 @@ class InstanceIdForegroundAppHelper(context: Context): UsageStatsForegroundAppHe
|
||||||
) {
|
) {
|
||||||
apps.remove(events.instanceId)
|
apps.remove(events.instanceId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// save values for the next iteration and the next query
|
||||||
|
isFirstEvent = false
|
||||||
|
lastEventTimestamp = events.timestamp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,5 +144,9 @@ class InstanceIdForegroundAppHelper(context: Context): UsageStatsForegroundAppHe
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
class UntestedSystemVersionException: RuntimeException()
|
sealed class InstanceIdException(message: String): RuntimeException(message) {
|
||||||
|
class UntestedSystemVersionException: InstanceIdException("untested system version")
|
||||||
|
class NotMatchingData(detail: String): InstanceIdException("not matching data: $detail")
|
||||||
|
class EventsNotSortedByTimestamp: InstanceIdException("events not sorted by timestamp")
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue