diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTask.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTask.kt index 870c80617d260aafb04eedc58c461b86ae003372..608b952e46cd31a5c78f0ceca22c5bb1cbceb363 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTask.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTask.kt @@ -15,13 +15,10 @@ import de.rki.coronawarnapp.task.TaskFactory import de.rki.coronawarnapp.task.TaskFactory.Config.CollisionBehavior import de.rki.coronawarnapp.util.TimeStamper import de.rki.coronawarnapp.util.ui.toLazyString -import de.rki.coronawarnapp.worker.BackgroundWorkHelper import kotlinx.coroutines.channels.ConflatedBroadcastChannel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.first -import org.joda.time.DateTime -import org.joda.time.DateTimeZone import org.joda.time.Duration import org.joda.time.Instant import timber.log.Timber @@ -50,10 +47,6 @@ class DownloadDiagnosisKeysTask @Inject constructor( Timber.d("Running with arguments=%s", arguments) arguments as Arguments - if (arguments.withConstraints) { - if (!noKeysFetchedToday()) return object : Task.Result {} - } - /** * Handles the case when the ENClient got disabled but the Task is still scheduled * in a background job. Also it acts as a failure catch in case the orchestration code did @@ -191,25 +184,6 @@ class DownloadDiagnosisKeysTask @Inject constructor( } } - private fun noKeysFetchedToday(): Boolean { - val currentDate = DateTime(timeStamper.nowUTC, DateTimeZone.UTC) - val lastFetch = DateTime( - LocalData.lastTimeDiagnosisKeysFromServerFetch(), - DateTimeZone.UTC - ) - return (LocalData.lastTimeDiagnosisKeysFromServerFetch() == null || - currentDate.withTimeAtStartOfDay() != lastFetch.withTimeAtStartOfDay()).also { - if (it) { - Timber.tag(TAG) - .d("No keys fetched today yet (last=%s, now=%s)", lastFetch, currentDate) - BackgroundWorkHelper.sendDebugNotification( - "Start Task", - "No keys fetched today yet \n${DateTime.now()}\nUTC: $currentDate" - ) - } - } - } - private fun rollback(rollbackItems: MutableList<RollbackItem>) { try { Timber.tag(TAG).d("Initiate Rollback") diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt index 0658b10604134435f471c5ef6f351372f18bdcb0..e45cbc98f179654ac80834bbf44931a2cc1e1608 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt @@ -15,18 +15,20 @@ import de.rki.coronawarnapp.task.submitBlocking import de.rki.coronawarnapp.timer.TimerHelper import de.rki.coronawarnapp.tracing.TracingProgress import de.rki.coronawarnapp.util.ConnectivityHelper +import de.rki.coronawarnapp.util.TimeStamper import de.rki.coronawarnapp.util.coroutine.AppScope import de.rki.coronawarnapp.util.di.AppContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch -import org.joda.time.DateTime -import org.joda.time.DateTimeZone -import org.joda.time.Instant +import org.joda.time.Duration import timber.log.Timber import java.util.Date +import java.util.NoSuchElementException import javax.inject.Inject import javax.inject.Singleton @@ -43,7 +45,8 @@ class TracingRepository @Inject constructor( @AppContext private val context: Context, @AppScope private val scope: CoroutineScope, private val taskController: TaskController, - enfClient: ENFClient + enfClient: ENFClient, + private val timeStamper: TimeStamper ) { private val internalLastTimeDiagnosisKeysFetched = MutableStateFlow<Date?>(null) @@ -62,11 +65,9 @@ class TracingRepository @Inject constructor( LocalData.lastTimeDiagnosisKeysFromServerFetch() } - private val retrievingDiagnosisKeys = MutableStateFlow(false) private val internalIsRefreshing = - retrievingDiagnosisKeys.combine(taskController.tasks) { retrievingDiagnosisKeys, tasks -> - retrievingDiagnosisKeys || tasks.isRiskLevelTaskRunning() - } + taskController.tasks.map { it.isDownloadDiagnosisKeysTaskRunning() || it.isRiskLevelTaskRunning() } + val tracingProgress: Flow<TracingProgress> = combine( internalIsRefreshing, enfClient.isPerformingExposureDetection() @@ -81,6 +82,9 @@ class TracingRepository @Inject constructor( private fun List<TaskInfo>.isRiskLevelTaskRunning() = any { it.taskState.isActive && it.taskState.request.type == RiskLevelTask::class } + private fun List<TaskInfo>.isDownloadDiagnosisKeysTaskRunning() = any { + it.taskState.isActive && it.taskState.request.type == DownloadDiagnosisKeysTask::class + } /** * Refresh the diagnosis keys. For that isRefreshing is set to true which is displayed in the ui. @@ -93,7 +97,6 @@ class TracingRepository @Inject constructor( */ fun refreshDiagnosisKeys() { scope.launch { - retrievingDiagnosisKeys.value = true taskController.submitBlocking( DefaultTaskRequest( DownloadDiagnosisKeysTask::class, @@ -102,7 +105,6 @@ class TracingRepository @Inject constructor( ) taskController.submit(DefaultTaskRequest(RiskLevelTask::class)) refreshLastTimeDiagnosisKeysFetchedDate() - retrievingDiagnosisKeys.value = false TimerHelper.startManualKeyRetrievalTimer() } } @@ -126,19 +128,6 @@ class TracingRepository @Inject constructor( */ // TODO temp place, this needs to go somewhere better fun refreshRiskLevel() { - - // get the current date and the date the diagnosis keys were fetched the last time - val currentDate = DateTime(Instant.now(), DateTimeZone.UTC) - val lastFetch = DateTime( - LocalData.lastTimeDiagnosisKeysFromServerFetch(), - DateTimeZone.UTC - ) - - // check if the keys were not already retrieved today - val keysWereNotRetrievedToday = - LocalData.lastTimeDiagnosisKeysFromServerFetch() == null || - currentDate.withTimeAtStartOfDay() != lastFetch.withTimeAtStartOfDay() - // check if the network is enabled to make the server fetch val isNetworkEnabled = ConnectivityHelper.isNetworkEnabled(context) @@ -146,32 +135,51 @@ class TracingRepository @Inject constructor( // model the keys are only fetched on button press of the user val isBackgroundJobEnabled = ConnectivityHelper.autoModeEnabled(context) - Timber.tag(TAG).v("Keys were not retrieved today $keysWereNotRetrievedToday") + val wasNotYetFetched = LocalData.lastTimeDiagnosisKeysFromServerFetch() == null + Timber.tag(TAG).v("Network is enabled $isNetworkEnabled") Timber.tag(TAG).v("Background jobs are enabled $isBackgroundJobEnabled") + Timber.tag(TAG).v("Was not yet fetched from server $wasNotYetFetched") - if (keysWereNotRetrievedToday && isNetworkEnabled && isBackgroundJobEnabled) { - // TODO shouldn't access this directly - retrievingDiagnosisKeys.value = true - - // start the fetching and submitting of the diagnosis keys + if (isNetworkEnabled && isBackgroundJobEnabled) { scope.launch { - taskController.submitBlocking( - DefaultTaskRequest( - DownloadDiagnosisKeysTask::class, - DownloadDiagnosisKeysTask.Arguments() + if (wasNotYetFetched || downloadDiagnosisKeysTaskDidNotRunRecently()) { + Timber.tag(TAG).v("Start the fetching and submitting of the diagnosis keys") + + taskController.submitBlocking( + DefaultTaskRequest( + DownloadDiagnosisKeysTask::class, + DownloadDiagnosisKeysTask.Arguments() + ) ) - ) - refreshLastTimeDiagnosisKeysFetchedDate() - TimerHelper.checkManualKeyRetrievalTimer() + refreshLastTimeDiagnosisKeysFetchedDate() + TimerHelper.checkManualKeyRetrievalTimer() - taskController.submit(DefaultTaskRequest(RiskLevelTask::class)) - // TODO shouldn't access this directly - retrievingDiagnosisKeys.value = false + taskController.submit(DefaultTaskRequest(RiskLevelTask::class)) + } } } } + private suspend fun downloadDiagnosisKeysTaskDidNotRunRecently(): Boolean { + val currentDate = timeStamper.nowUTC + val taskLastFinishedAt = try { + taskController.tasks.first() + .filter { it.taskState.type == DownloadDiagnosisKeysTask::class } + .mapNotNull { it.taskState.finishedAt } + .sortedDescending() + .first() + } catch (e: NoSuchElementException) { + Timber.tag(TAG).v("download did not run recently - no task with a finishedAt date found") + return true + } + + return currentDate.isAfter(taskLastFinishedAt.plus(Duration.standardHours(1))).also { + Timber.tag(TAG) + .v("download did not run recently: %s (last=%s, now=%s)", it, taskLastFinishedAt, currentDate) + } + } + /** * Exposure summary * Refresh the following variables in TracingRepository