diff --git a/Corona-Warn-App/build.gradle b/Corona-Warn-App/build.gradle
index 07b49cd3c4699cfce56cd2f44945d730183b6bb9..06191fd03f637ca09a0d6667492c8d6102cd781e 100644
--- a/Corona-Warn-App/build.gradle
+++ b/Corona-Warn-App/build.gradle
@@ -303,7 +303,7 @@ configurations.all {
 
 dependencies {
     // KOTLIN
-    def coroutineVersion = "1.4.2"
+    def coroutineVersion = "1.5.0"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutineVersion"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutineVersion"
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:$coroutineVersion"
diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/coronatest/ui/CoronaTestTestFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/coronatest/ui/CoronaTestTestFragment.kt
index 16d5cdc4527c205bcc11b49f7efb91ffa3d56e22..1209ca39b3c81070e61673188466c2ba08f30234 100644
--- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/coronatest/ui/CoronaTestTestFragment.kt
+++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/coronatest/ui/CoronaTestTestFragment.kt
@@ -66,7 +66,7 @@ class CoronaTestTestFragment : Fragment(R.layout.fragment_test_coronatest), Auto
         }
 
         vm.pcrtState.observe2(this) {
-            binding.pcrtData.text = it.getNiceTextForHumans(requireContext())
+            binding.pcrtData.text = it.getNiceTextForHumans()
         }
         binding.apply {
             pcrtDeleteAction.setOnClickListener { vm.deletePCRT() }
@@ -74,7 +74,7 @@ class CoronaTestTestFragment : Fragment(R.layout.fragment_test_coronatest), Auto
         }
 
         vm.ratState.observe2(this) {
-            binding.ratData.text = it.getNiceTextForHumans(requireContext())
+            binding.ratData.text = it.getNiceTextForHumans()
         }
         binding.apply {
             ratDeleteAction.setOnClickListener { vm.deleteRAT() }
diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/coronatest/ui/CoronaTestTestFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/coronatest/ui/CoronaTestTestFragmentViewModel.kt
index 1f5a05014104c4351e03b1e35f2bd50ebfe035a3..df524f3e15299e9f137bd1c73706e1fea68eca5d 100644
--- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/coronatest/ui/CoronaTestTestFragmentViewModel.kt
+++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/coronatest/ui/CoronaTestTestFragmentViewModel.kt
@@ -1,6 +1,5 @@
 package de.rki.coronawarnapp.test.coronatest.ui
 
-import android.content.Context
 import androidx.lifecycle.asLiveData
 import com.journeyapps.barcodescanner.BarcodeResult
 import dagger.assisted.AssistedFactory
@@ -100,7 +99,7 @@ class CoronaTestTestFragmentViewModel @AssistedInject constructor(
     data class PCRTState(
         val coronaTest: PCRCoronaTest?
     ) {
-        fun getNiceTextForHumans(context: Context): String {
+        fun getNiceTextForHumans(): String {
             return coronaTest
                 ?.toString()
                 ?.replace("PCRCoronaTest(", "")
@@ -113,7 +112,7 @@ class CoronaTestTestFragmentViewModel @AssistedInject constructor(
     data class RATState(
         val coronaTest: RACoronaTest?
     ) {
-        fun getNiceTextForHumans(context: Context): String {
+        fun getNiceTextForHumans(): String {
             return coronaTest
                 ?.toString()
                 ?.replace("RACoronaTest(", "")
diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/tasks/testtask/TestTask.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/tasks/testtask/TestTask.kt
index 45c6a1a39cb71af33faf15ee88baf8433099c4a4..7562774206b3f5a528bc1612ea7dc0fdb1407008 100644
--- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/tasks/testtask/TestTask.kt
+++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/tasks/testtask/TestTask.kt
@@ -3,11 +3,13 @@ package de.rki.coronawarnapp.test.tasks.testtask
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskCancellationException
 import de.rki.coronawarnapp.task.TaskFactory
+import de.rki.coronawarnapp.task.common.Finished
+import de.rki.coronawarnapp.task.common.ProgressResult
+import de.rki.coronawarnapp.task.common.Started
 import de.rki.coronawarnapp.task.common.DefaultProgress
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import org.joda.time.Duration
 import org.joda.time.Instant
 import timber.log.Timber
@@ -16,8 +18,8 @@ import javax.inject.Provider
 
 class TestTask @Inject constructor() : Task<DefaultProgress, TestTask.Result> {
 
-    private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
-    override val progress: Flow<DefaultProgress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<DefaultProgress>(Started)
+    override val progress: Flow<DefaultProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -28,13 +30,12 @@ class TestTask @Inject constructor() : Task<DefaultProgress, TestTask.Result> {
             if (isCanceled) throw TaskCancellationException()
         }
     } finally {
-        internalProgress.close()
+        internalProgress.value = Finished
     }
 
     private suspend fun runSafely(arguments: Arguments): Result {
         for (it in 1..10) {
-            internalProgress.send(DefaultProgress("${arguments.prefix}: ${Instant.now()}"))
-
+            internalProgress.value = ProgressResult("${arguments.prefix}: ${Instant.now()}")
             delay(1000)
 
             if (isCanceled) break
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt
index 0145584b0d9c32f272b62e77a1159ff96c643d17..3ed502671e04c4b8701db640498740185c7e9f5a 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt
@@ -36,12 +36,13 @@ import de.rki.coronawarnapp.task.TaskController
 import de.rki.coronawarnapp.util.BuildVersionWrap
 import de.rki.coronawarnapp.util.CWADebug
 import de.rki.coronawarnapp.util.WatchdogService
+import de.rki.coronawarnapp.util.coroutine.AppScope
 import de.rki.coronawarnapp.util.device.ForegroundState
 import de.rki.coronawarnapp.util.di.AppInjector
 import de.rki.coronawarnapp.util.di.ApplicationComponent
 import de.rki.coronawarnapp.util.hasAPILevel
 import de.rki.coronawarnapp.vaccination.core.execution.VaccinationUpdateScheduler
-import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
 import org.conscrypt.Conscrypt
@@ -81,6 +82,9 @@ class CoronaWarnApplication : Application(), HasAndroidInjector {
     @Inject lateinit var raTestResultAvailableNotificationService: RATTestResultAvailableNotificationService
     @Inject lateinit var vaccinationUpdateScheduler: VaccinationUpdateScheduler
 
+    @AppScope
+    @Inject lateinit var appScope: CoroutineScope
+
     @LogHistoryTree @Inject lateinit var rollingLogHistory: Timber.Tree
 
     override fun onCreate() {
@@ -113,7 +117,7 @@ class CoronaWarnApplication : Application(), HasAndroidInjector {
 
         foregroundState.isInForeground
             .onEach { isAppInForeground = it }
-            .launchIn(GlobalScope)
+            .launchIn(appScope)
 
         Timber.v("Setting up contact diary work scheduler")
         contactDiaryWorkScheduler.setup()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/retention/ContactDiaryCleanTask.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/retention/ContactDiaryCleanTask.kt
index 84a790910d2e197e902526256e1cd94f3ecdf5e6..b6a76a2471226424e34c35161eead806bbc26c02 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/retention/ContactDiaryCleanTask.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/retention/ContactDiaryCleanTask.kt
@@ -3,9 +3,10 @@ package de.rki.coronawarnapp.contactdiary.retention
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskFactory
 import de.rki.coronawarnapp.task.common.DefaultProgress
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
+import de.rki.coronawarnapp.task.common.Finished
+import de.rki.coronawarnapp.task.common.Started
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import org.joda.time.Duration
 import timber.log.Timber
 import javax.inject.Inject
@@ -15,8 +16,8 @@ class ContactDiaryCleanTask @Inject constructor(
     private val retentionCalculation: ContactDiaryRetentionCalculation
 ) : Task<DefaultProgress, Task.Result> {
 
-    private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
-    override val progress: Flow<DefaultProgress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<DefaultProgress>(Started)
+    override val progress: Flow<DefaultProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -38,7 +39,7 @@ class ContactDiaryCleanTask @Inject constructor(
         throw error
     } finally {
         Timber.i("Finished (isCanceled=$isCanceled).")
-        internalProgress.close()
+        internalProgress.value = Finished
     }
 
     override suspend fun cancel() {
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 ba1448d41337ec126c6f9de5dc27f234dba858b3..be7784d24b6031a82c5e2d3070c7dc2eeab9f593 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,9 +15,8 @@ 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 kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.first
 import org.joda.time.Duration
 import org.joda.time.Instant
@@ -37,8 +36,8 @@ class DownloadDiagnosisKeysTask @Inject constructor(
     private val coronaTestRepository: CoronaTestRepository,
 ) : Task<DownloadDiagnosisKeysTask.Progress, DownloadDiagnosisKeysTask.Result> {
 
-    private val internalProgress = ConflatedBroadcastChannel<Progress>()
-    override val progress: Flow<Progress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<Progress>(Progress.Started)
+    override val progress: Flow<Progress> = internalProgress
 
     private var isCanceled = false
 
@@ -67,8 +66,8 @@ class DownloadDiagnosisKeysTask @Inject constructor(
             // RETRIEVE RISK SCORE PARAMETERS
             val exposureConfig: ConfigData = appConfigProvider.getAppConfig()
 
-            internalProgress.send(Progress.ApiSubmissionStarted)
-            internalProgress.send(Progress.KeyFilesDownloadStarted)
+            internalProgress.value = Progress.ApiSubmissionStarted
+            internalProgress.value = Progress.KeyFilesDownloadStarted
 
             val requestedCountries = arguments.requestedCountries
             val keySyncResult = getAvailableKeyFiles(requestedCountries)
@@ -104,12 +103,7 @@ class DownloadDiagnosisKeysTask @Inject constructor(
             val availableKeyFiles = keySyncResult.availableKeys.map { it.path }
             val totalFileSize = availableKeyFiles.fold(0L, { acc, file -> file.length() + acc })
 
-            internalProgress.send(
-                Progress.KeyFilesDownloadFinished(
-                    availableKeyFiles.size,
-                    totalFileSize
-                )
-            )
+            internalProgress.value = Progress.KeyFilesDownloadFinished(availableKeyFiles.size, totalFileSize)
 
             // remember version code of this execution for next time
             settings.updateLastVersionCodeToCurrent()
@@ -127,7 +121,7 @@ class DownloadDiagnosisKeysTask @Inject constructor(
             )
             Timber.tag(TAG).d("Diagnosis Keys provided (success=%s)", isSubmissionSuccessful)
 
-            internalProgress.send(Progress.ApiSubmissionFinished)
+            internalProgress.value = Progress.ApiSubmissionFinished
 
             return Result()
         } catch (error: Exception) {
@@ -138,7 +132,7 @@ class DownloadDiagnosisKeysTask @Inject constructor(
             throw error
         } finally {
             Timber.i("Finished (isCanceled=$isCanceled).")
-            internalProgress.close()
+            internalProgress.value = Progress.Finished
         }
     }
 
@@ -218,6 +212,8 @@ class DownloadDiagnosisKeysTask @Inject constructor(
     class Result : Task.Result
 
     sealed class Progress : Task.Progress {
+        object Started : Progress()
+        object Finished : Progress()
         object ApiSubmissionStarted : Progress()
         object ApiSubmissionFinished : Progress()
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTask.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTask.kt
index ea7b2eece6db44ee9736e3c964240429d3775a14..a55f59dbd258a45c9ba9252411bed5b2173cbd84 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTask.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTask.kt
@@ -15,10 +15,9 @@ import de.rki.coronawarnapp.presencetracing.warning.storage.TraceWarningReposito
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskCancellationException
 import de.rki.coronawarnapp.task.TaskFactory
-import de.rki.coronawarnapp.util.TimeStamper
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
+import de.rki.coronawarnapp.task.common.Finished
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.firstOrNull
 import org.joda.time.Duration
@@ -27,7 +26,6 @@ import javax.inject.Inject
 import javax.inject.Provider
 
 class PresenceTracingWarningTask @Inject constructor(
-    private val timeStamper: TimeStamper,
     private val syncTool: TraceWarningPackageSyncTool,
     private val checkInWarningMatcher: CheckInWarningMatcher,
     private val presenceTracingRiskRepository: PresenceTracingRiskRepository,
@@ -38,8 +36,9 @@ class PresenceTracingWarningTask @Inject constructor(
     private val autoCheckOut: AutoCheckOut,
 ) : Task<PresenceTracingWarningTaskProgress, PresenceTracingWarningTask.Result> {
 
-    private val internalProgress = ConflatedBroadcastChannel<PresenceTracingWarningTaskProgress>()
-    override val progress: Flow<PresenceTracingWarningTaskProgress> = internalProgress.asFlow()
+    private val internalProgress =
+        MutableStateFlow<PresenceTracingWarningTaskProgress>(PresenceTracingWarningTaskProgress.Started)
+    override val progress: Flow<PresenceTracingWarningTaskProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -65,7 +64,7 @@ class PresenceTracingWarningTask @Inject constructor(
         throw error
     } finally {
         Timber.i("Finished (isCanceled=$isCanceled).")
-        internalProgress.close()
+        internalProgress.value = PresenceTracingWarningTaskProgress.Finished
     }
 
     private suspend fun doWork(): Result {
@@ -75,7 +74,7 @@ class PresenceTracingWarningTask @Inject constructor(
         presenceTracingRiskMapper.clearConfig()
 
         Timber.tag(TAG).d("Syncing packages.")
-        internalProgress.send(PresenceTracingWarningTaskProgress.Downloading())
+        internalProgress.value = PresenceTracingWarningTaskProgress.Downloading()
 
         val syncResult = syncTool.syncPackages()
 
@@ -119,7 +118,7 @@ class PresenceTracingWarningTask @Inject constructor(
         }
 
         Timber.tag(TAG).d("Running check-in matcher.")
-        internalProgress.send(PresenceTracingWarningTaskProgress.Calculating())
+        internalProgress.value = PresenceTracingWarningTaskProgress.Calculating()
 
         val matcherResult = checkInWarningMatcher.process(
             checkIns = checkIns,
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTaskProgress.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTaskProgress.kt
index a7c9869954c5a4435f65ffcb772b09648bd64a85..acd57eb491e0ffade32bba02e03d4c81094d7ee2 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTaskProgress.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTaskProgress.kt
@@ -6,6 +6,14 @@ import de.rki.coronawarnapp.util.ui.LazyString
 
 sealed class PresenceTracingWarningTaskProgress : Task.Progress {
 
+    object Started : PresenceTracingWarningTaskProgress() {
+        override val primaryMessage: LazyString = CachedString { "" }
+    }
+
+    object Finished : PresenceTracingWarningTaskProgress() {
+        override val primaryMessage: LazyString = CachedString { "" }
+    }
+
     data class Downloading(
         override val primaryMessage: LazyString = CachedString { "" }
     ) : PresenceTracingWarningTaskProgress()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt
index cab719c6c8faeeb36b4c8c43ed266f39f42c166f..29b46a9ce6a242921afb35ad2a8d338b0f0ff577 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelTask.kt
@@ -18,12 +18,13 @@ import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskCancellationException
 import de.rki.coronawarnapp.task.TaskFactory
+import de.rki.coronawarnapp.task.common.Finished
+import de.rki.coronawarnapp.task.common.Started
 import de.rki.coronawarnapp.task.common.DefaultProgress
 import de.rki.coronawarnapp.util.TimeStamper
 import de.rki.coronawarnapp.util.device.BackgroundModeStatus
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.first
 import org.joda.time.Duration
 import org.joda.time.Instant
@@ -45,8 +46,8 @@ class RiskLevelTask @Inject constructor(
     private val analyticsExposureWindowCollector: AnalyticsExposureWindowCollector,
 ) : Task<DefaultProgress, EwRiskLevelTaskResult> {
 
-    private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
-    override val progress: Flow<DefaultProgress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<DefaultProgress>(Started)
+    override val progress: Flow<DefaultProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -56,7 +57,7 @@ class RiskLevelTask @Inject constructor(
         val configData: ConfigData = appConfigProvider.getAppConfig()
 
         determineRiskLevelResult(configData).also {
-            Timber.i("Risklevel determined: %s", it)
+            Timber.i("Risk level determined: %s", it)
 
             checkCancel()
 
@@ -71,7 +72,7 @@ class RiskLevelTask @Inject constructor(
         throw error
     } finally {
         Timber.i("Finished (isCanceled=$isCanceled).")
-        internalProgress.close()
+        internalProgress.value = Finished
     }
 
     private suspend fun determineRiskLevelResult(configData: ConfigData): EwRiskLevelTaskResult {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/task/SubmissionTask.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/task/SubmissionTask.kt
index bf8c50d1dfadb1311526b939be3deaaede65c962..01ba0e6a4676c9c61050b2b5748c5341aab47abc 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/task/SubmissionTask.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/task/SubmissionTask.kt
@@ -20,11 +20,12 @@ import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryStorage
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskCancellationException
 import de.rki.coronawarnapp.task.TaskFactory
+import de.rki.coronawarnapp.task.common.Finished
+import de.rki.coronawarnapp.task.common.Started
 import de.rki.coronawarnapp.task.common.DefaultProgress
 import de.rki.coronawarnapp.util.TimeStamper
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.first
 import org.joda.time.Duration
 import timber.log.Timber
@@ -47,8 +48,8 @@ class SubmissionTask @Inject constructor(
     private val coronaTestRepository: CoronaTestRepository,
 ) : Task<DefaultProgress, SubmissionTask.Result> {
 
-    private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
-    override val progress: Flow<DefaultProgress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<DefaultProgress>(Started)
+    override val progress: Flow<DefaultProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -85,7 +86,7 @@ class SubmissionTask @Inject constructor(
             throw error
         } finally {
             Timber.i("Finished (isCanceled=$isCanceled).")
-            internalProgress.close()
+            internalProgress.value = Finished
         }
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/task/TaskController.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/task/TaskController.kt
index 1f2ed9d8415f5220febbf7d72c7d340438d66676..41f0ac32e908c32f0ba329c5c97656307c11854b 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/task/TaskController.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/task/TaskController.kt
@@ -63,7 +63,7 @@ class TaskController @Inject constructor(
     }
 
     /**
-     * Don't re-use taskrequests, create new requests for each submission.
+     * Don't re-use task requests, create new requests for each submission.
      * They contain unique IDs.
      */
     fun submit(request: TaskRequest) {
@@ -71,7 +71,7 @@ class TaskController @Inject constructor(
             throw MissingTaskFactoryException(request::class)
         }
         Timber.tag(TAG).i("Task submitted: %s", request)
-        taskQueue.offer(request)
+        taskQueue.trySend(request)
     }
 
     suspend fun cancel(requestId: UUID) = internalTaskData.updateSafely {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/task/common/DefaultProgress.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/task/common/DefaultProgress.kt
index 3d3912df9e6d6f65fe79df8ef0b11fa5552ece89..0f3dcf89befdf71a0c7d65334d91d747929d51e2 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/task/common/DefaultProgress.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/task/common/DefaultProgress.kt
@@ -2,13 +2,12 @@ package de.rki.coronawarnapp.task.common
 
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.util.ui.CachedString
-import de.rki.coronawarnapp.util.ui.LazyString
 
-data class DefaultProgress constructor(
-    override val primaryMessage: LazyString
-) : Task.Progress {
-
-    constructor(
-        primary: String
-    ) : this(CachedString { primary })
+sealed class DefaultProgress(progressMessage: String) : Task.Progress {
+    override val primaryMessage = CachedString { progressMessage }
 }
+
+object Started : DefaultProgress("Started")
+object Finished : DefaultProgress("Finished")
+
+data class ProgressResult(val progressMessage: String) : DefaultProgress(progressMessage)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/execution/VaccinationUpdateScheduler.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/execution/VaccinationUpdateScheduler.kt
index 5a1f61e59c1e8cb87611907a0f8ebbc38578260c..5393642f6da98b91c3e16e73b3260c7bedb1a8cc 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/execution/VaccinationUpdateScheduler.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/execution/VaccinationUpdateScheduler.kt
@@ -44,7 +44,7 @@ class VaccinationUpdateScheduler @Inject constructor(
         }
 
         vaccinationRepository.vaccinationInfos
-            .map { vaccinatedPersons ->
+            .map {
                 false // NOOP, but we want to keep the logic for now
             }
             .distinctUntilChanged()
@@ -59,11 +59,11 @@ class VaccinationUpdateScheduler @Inject constructor(
         // If there is a pending check or we have stale data, we refresh immediately when opening the app
         combine(
             // Pending checks?
-            vaccinationRepository.vaccinationInfos.map { persons ->
+            vaccinationRepository.vaccinationInfos.map {
                 false // NOOP, but we want to keep the logic for now
             }.distinctUntilChanged(),
             // Stale data?
-            vaccinationRepository.vaccinationInfos.map { persons ->
+            vaccinationRepository.vaccinationInfos.map {
                 false // NOOP, but we want to keep the logic for now
             }.distinctUntilChanged(),
             foregroundState.isInForeground
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/execution/task/VaccinationUpdateTask.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/execution/task/VaccinationUpdateTask.kt
index 3f02678f087144b55d3b1d2bc4de05d19223ee27..fdb14d5e90df4e916c192a18b504460112397c4e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/execution/task/VaccinationUpdateTask.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/vaccination/core/execution/task/VaccinationUpdateTask.kt
@@ -4,24 +4,23 @@ import de.rki.coronawarnapp.appconfig.AppConfigProvider
 import de.rki.coronawarnapp.bugreporting.reportProblem
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskFactory
+import de.rki.coronawarnapp.task.common.Finished
+import de.rki.coronawarnapp.task.common.Started
 import de.rki.coronawarnapp.task.common.DefaultProgress
-import de.rki.coronawarnapp.util.TimeStamper
 import de.rki.coronawarnapp.vaccination.core.repository.VaccinationRepository
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import org.joda.time.Duration
 import timber.log.Timber
 import javax.inject.Inject
 import javax.inject.Provider
 
 class VaccinationUpdateTask @Inject constructor(
-    private val timeStamper: TimeStamper,
     private val vaccinationRepository: VaccinationRepository,
 ) : Task<DefaultProgress, VaccinationUpdateTask.Result> {
 
-    private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
-    override val progress: Flow<DefaultProgress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<DefaultProgress>(Started)
+    override val progress: Flow<DefaultProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -35,7 +34,7 @@ class VaccinationUpdateTask @Inject constructor(
         throw error
     } finally {
         Timber.i("Finished (isCanceled=$isCanceled).")
-        internalProgress.close()
+        internalProgress.value = Finished
     }
 
     private suspend fun doWork(): Result {
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/CoronaWarnApplicationTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/CoronaWarnApplicationTest.kt
index 65ab5efe75b2ee24c625d50fde410893d31d355b..3ac27d32535f18a5afbff9c55e08b70eef31ecb6 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/CoronaWarnApplicationTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/CoronaWarnApplicationTest.kt
@@ -36,6 +36,7 @@ import io.mockk.mockk
 import io.mockk.mockkObject
 import io.mockk.mockkStatic
 import io.mockk.verifySequence
+import kotlinx.coroutines.test.TestCoroutineScope
 import org.conscrypt.Conscrypt
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
@@ -122,6 +123,7 @@ class CoronaWarnApplicationTest : BaseTest() {
                 app.pcrTestResultAvailableNotificationService = pcrTestResultAvailableNotificationService
                 app.raTestResultAvailableNotificationService = raTestResultAvailableNotificationService
                 app.vaccinationUpdateScheduler = vaccinationUpdateScheduler
+                app.appScope = TestCoroutineScope()
                 app.rollingLogHistory = object : Timber.Tree() {
                     override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
                         // NOOP
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTaskTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTaskTest.kt
index 98d7ace516554e1496faa5d6e0c784999f0db1c4..5fd04aacfcf35840aad5b9b69a704e07e4d16014 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTaskTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/presencetracing/risk/execution/PresenceTracingWarningTaskTest.kt
@@ -14,7 +14,6 @@ import de.rki.coronawarnapp.presencetracing.warning.download.TraceWarningPackage
 import de.rki.coronawarnapp.presencetracing.warning.storage.TraceWarningPackage
 import de.rki.coronawarnapp.presencetracing.warning.storage.TraceWarningRepository
 import de.rki.coronawarnapp.server.protocols.internal.pt.TraceWarning
-import de.rki.coronawarnapp.util.TimeStamper
 import io.kotest.assertions.throwables.shouldThrow
 import io.kotest.matchers.comparables.shouldBeLessThan
 import io.kotest.matchers.shouldNotBe
@@ -31,7 +30,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.test.runBlockingTest
 import org.joda.time.Duration
-import org.joda.time.Instant
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
@@ -39,7 +37,6 @@ import java.io.IOException
 
 class PresenceTracingWarningTaskTest : BaseTest() {
 
-    @MockK lateinit var timeStamper: TimeStamper
     @MockK lateinit var syncTool: TraceWarningPackageSyncTool
     @MockK lateinit var checkInWarningMatcher: CheckInWarningMatcher
     @MockK lateinit var presenceTracingRiskRepository: PresenceTracingRiskRepository
@@ -61,7 +58,6 @@ class PresenceTracingWarningTaskTest : BaseTest() {
 
         every { coronaTestRepository.coronaTests } returns coronaTests
 
-        every { timeStamper.nowUTC } returns Instant.ofEpochMilli(9000)
         coEvery { syncTool.syncPackages() } returns TraceWarningPackageSyncTool.SyncResult(successful = true)
         coEvery { checkInWarningMatcher.process(any(), any()) } answers {
             CheckInWarningMatcher.Result(
@@ -95,7 +91,6 @@ class PresenceTracingWarningTaskTest : BaseTest() {
     }
 
     private fun createInstance() = PresenceTracingWarningTask(
-        timeStamper = timeStamper,
         syncTool = syncTool,
         checkInWarningMatcher = checkInWarningMatcher,
         presenceTracingRiskRepository = presenceTracingRiskRepository,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/TaskControllerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/TaskControllerTest.kt
index 71370335eeb30b6f17ba1c479cb12a3d0c467da3..cdd01e22da45ec349d12ffc1b8d200eb63db0fd7 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/TaskControllerTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/TaskControllerTest.kt
@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.task
 import de.rki.coronawarnapp.bugreporting.reportProblem
 import de.rki.coronawarnapp.exception.reporting.report
 import de.rki.coronawarnapp.task.common.DefaultTaskRequest
+import de.rki.coronawarnapp.task.common.Finished
 import de.rki.coronawarnapp.task.testtasks.SkippingTask
 import de.rki.coronawarnapp.task.testtasks.alerterror.AlertErrorTask
 import de.rki.coronawarnapp.task.testtasks.precondition.PreconditionTask
@@ -41,30 +42,29 @@ import org.junit.jupiter.api.AfterEach
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import testhelpers.BaseIOTest
+import testhelpers.coroutines.runBlockingTest2
 import testhelpers.coroutines.test
 import testhelpers.extensions.isAfterOrEqual
 import java.io.File
 import java.io.FileNotFoundException
 import java.util.UUID
-import javax.inject.Provider
 
 class TaskControllerTest : BaseIOTest() {
 
     private val taskFactoryMap: MutableMap<
         Class<out Task<Task.Progress, Task.Result>>,
-        TaskFactory<out Task.Progress, out Task.Result>
-        > = mutableMapOf()
+        TaskFactory<out Task.Progress, out Task.Result>> = mutableMapOf()
     @MockK lateinit var timeStamper: TimeStamper
 
     private val testDir = File(IO_TEST_BASEDIR, this::class.java.simpleName)
 
-    private val timeoutFactory = spyk(TimeoutTask.Factory(Provider { TimeoutTask() }))
-    private val timeoutFactory2 = spyk(TimeoutTask2.Factory(Provider { TimeoutTask2() }))
-    private val queueingFactory = spyk(QueueingTask.Factory(Provider { QueueingTask() }))
-    private val skippingFactory = spyk(SkippingTask.Factory(Provider { SkippingTask() }))
-    private val preconditionFactory = spyk(PreconditionTask.Factory(Provider { PreconditionTask() }))
-    private val silentErrorFactory = spyk(SilentErrorTask.Factory(Provider { SilentErrorTask() }))
-    private val alertErrorFactory = spyk(AlertErrorTask.Factory(Provider { AlertErrorTask() }))
+    private val timeoutFactory = spyk(TimeoutTask.Factory { TimeoutTask() })
+    private val timeoutFactory2 = spyk(TimeoutTask2.Factory { TimeoutTask2() })
+    private val queueingFactory = spyk(QueueingTask.Factory { QueueingTask() })
+    private val skippingFactory = spyk(SkippingTask.Factory { SkippingTask() })
+    private val preconditionFactory = spyk(PreconditionTask.Factory { PreconditionTask() })
+    private val silentErrorFactory = spyk(SilentErrorTask.Factory { SilentErrorTask() })
+    private val alertErrorFactory = spyk(AlertErrorTask.Factory { AlertErrorTask() })
 
     @BeforeEach
     fun setup() {
@@ -96,7 +96,7 @@ class TaskControllerTest : BaseIOTest() {
     )
 
     @Test
-    fun `sideeffect free init`() = runBlockingTest {
+    fun `side effect free init`() = runBlockingTest {
         shouldNotThrowAny {
             val instance = createInstance(scope = this)
             instance.close()
@@ -130,7 +130,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `default task execution`() = runBlockingTest {
+    fun `default task execution`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val arguments = QueueingTask.Arguments(
@@ -166,12 +166,9 @@ class TaskControllerTest : BaseIOTest() {
 
         arguments.path.exists() shouldBe true
 
-        val lastProgressMessage = progressCollector.latestValue!!.primaryMessage.get(mockk())
-        lastProgressMessage shouldBe arguments.values.last()
+        progressCollector.latestValue shouldBe Finished
 
         infoFinished.apply {
-            // No more progress, task is finished
-//            progress.first() shouldBe ""
 
             taskState.isSuccessful shouldBe true
             taskState.resultOrThrow shouldNotBe null
@@ -195,7 +192,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `failed task yields exception`() = runBlockingTest {
+    fun `failed task yields exception`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val arguments = QueueingTask.Arguments(
@@ -234,7 +231,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `canceled task yields exception`() = runBlockingTest {
+    fun `canceled task yields exception`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val arguments = QueueingTask.Arguments(
@@ -258,7 +255,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `queued task execution`() = runBlockingTest {
+    fun `queued task execution`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val arguments = QueueingTask.Arguments(
@@ -309,7 +306,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `skippable tasks are skipped`() = runBlockingTest {
+    fun `skippable tasks are skipped`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val arguments = QueueingTask.Arguments(
@@ -354,7 +351,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `tasks with preconditions that are not met are skipped`() = runBlockingTest {
+    fun `tasks with preconditions that are not met are skipped`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val request = DefaultTaskRequest(type = PreconditionTask::class)
@@ -391,7 +388,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `collision behavior only affects task of same type`() = runBlockingTest {
+    fun `collision behavior only affects task of same type`() = runBlockingTest2(ignoreActive = true) {
         val arguments = QueueingTask.Arguments(path = File(testDir, UUID.randomUUID().toString()))
         arguments.path.exists() shouldBe false
 
@@ -440,7 +437,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `resubmitting a request has no effect`() = runBlockingTest {
+    fun `resubmitting a request has no effect`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val arguments = QueueingTask.Arguments(
@@ -472,7 +469,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `tasks are timed out according to their config`() = runBlockingTest {
+    fun `tasks are timed out according to their config`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val request = DefaultTaskRequest(
@@ -497,7 +494,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `timeout starts on execution, not while pending`() = runBlockingTest {
+    fun `timeout starts on execution, not while pending`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val taskWithTimeout = DefaultTaskRequest(
@@ -538,7 +535,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `parallel tasks can timeout`() = runBlockingTest {
+    fun `parallel tasks can timeout`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val task1WithTimeout = DefaultTaskRequest(
@@ -591,7 +588,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `old tasks are pruned from history`() = runBlockingTest {
+    fun `old tasks are pruned from history`() = runBlockingTest2(ignoreActive = true) {
         val instance = createInstance(scope = this)
 
         val expectedFiles = mutableListOf<File>()
@@ -631,7 +628,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `silent error handling`() = runBlockingTest {
+    fun `silent error handling`() = runBlockingTest2(ignoreActive = true) {
 
         val error: Throwable = spyk(Throwable())
 
@@ -643,7 +640,8 @@ class TaskControllerTest : BaseIOTest() {
 
         val instance = createInstance(scope = this)
 
-        val request = DefaultTaskRequest(type = SilentErrorTask::class, arguments = SilentErrorTask.Arguments(error = error))
+        val request =
+            DefaultTaskRequest(type = SilentErrorTask::class, arguments = SilentErrorTask.Arguments(error = error))
         instance.submit(request)
 
         val infoFinished = instance.tasks
@@ -660,7 +658,7 @@ class TaskControllerTest : BaseIOTest() {
     }
 
     @Test
-    fun `alert error handling`() = runBlockingTest {
+    fun `alert error handling`() = runBlockingTest2(ignoreActive = true) {
 
         val error: Throwable = spyk(Throwable())
 
@@ -672,7 +670,8 @@ class TaskControllerTest : BaseIOTest() {
 
         val instance = createInstance(scope = this)
 
-        val request = DefaultTaskRequest(type = AlertErrorTask::class, arguments = AlertErrorTask.Arguments(error = error))
+        val request =
+            DefaultTaskRequest(type = AlertErrorTask::class, arguments = AlertErrorTask.Arguments(error = error))
         instance.submit(request)
 
         val infoFinished = instance.tasks
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/alerterror/AlertErrorTask.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/alerterror/AlertErrorTask.kt
index 05572d15905f6830542c4e80a6c5f82eefc788d9..6d9a5517362982f2753c7a9a3165572f14e7ec00 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/alerterror/AlertErrorTask.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/alerterror/AlertErrorTask.kt
@@ -2,17 +2,18 @@ package de.rki.coronawarnapp.task.testtasks.alerterror
 
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskFactory
+import de.rki.coronawarnapp.task.common.Finished
+import de.rki.coronawarnapp.task.common.Started
 import de.rki.coronawarnapp.task.common.DefaultProgress
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import timber.log.Timber
 import javax.inject.Provider
 
 class AlertErrorTask : Task<DefaultProgress, AlertErrorTask.Result> {
 
-    private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
-    override val progress: Flow<DefaultProgress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<DefaultProgress>(Started)
+    override val progress: Flow<DefaultProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -22,7 +23,7 @@ class AlertErrorTask : Task<DefaultProgress, AlertErrorTask.Result> {
         throw arguments.error
     } finally {
         Timber.i("Finished (isCanceled=$isCanceled).")
-        internalProgress.close()
+        internalProgress.value = Finished
     }
 
     override suspend fun cancel() {
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/precondition/PreconditionTask.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/precondition/PreconditionTask.kt
index f85bb257879f3808498f3fb69b0eac35cbd7bd09..a8b8c5f4b52842539af52702d9d520bd7b6828ff 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/precondition/PreconditionTask.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/precondition/PreconditionTask.kt
@@ -2,18 +2,19 @@ package de.rki.coronawarnapp.task.testtasks.precondition
 
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskFactory
+import de.rki.coronawarnapp.task.common.Finished
+import de.rki.coronawarnapp.task.common.Started
 import de.rki.coronawarnapp.task.common.DefaultProgress
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import org.joda.time.Duration
 import timber.log.Timber
 import javax.inject.Provider
 
 class PreconditionTask : Task<DefaultProgress, PreconditionTask.Result> {
 
-    private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
-    override val progress: Flow<DefaultProgress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<DefaultProgress>(Started)
+    override val progress: Flow<DefaultProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -23,7 +24,7 @@ class PreconditionTask : Task<DefaultProgress, PreconditionTask.Result> {
         Result()
     } finally {
         Timber.i("Finished (isCanceled=$isCanceled).")
-        internalProgress.close()
+        internalProgress.value = Finished
     }
 
     override suspend fun cancel() {
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/queue/QueueingTask.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/queue/QueueingTask.kt
index 0c7d67d9dab2f9243f9043d362741b39614948c2..bb491a02ccf7fe6bb65fca7a2f6821d687583a43 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/queue/QueueingTask.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/queue/QueueingTask.kt
@@ -3,11 +3,13 @@ package de.rki.coronawarnapp.task.testtasks.queue
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskCancellationException
 import de.rki.coronawarnapp.task.TaskFactory
+import de.rki.coronawarnapp.task.common.Finished
+import de.rki.coronawarnapp.task.common.ProgressResult
+import de.rki.coronawarnapp.task.common.Started
 import de.rki.coronawarnapp.task.common.DefaultProgress
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import org.joda.time.Duration
 import timber.log.Timber
 import java.io.File
@@ -17,8 +19,8 @@ import javax.inject.Provider
 
 open class QueueingTask @Inject constructor() : Task<DefaultProgress, QueueingTask.Result> {
 
-    private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
-    override val progress: Flow<DefaultProgress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<DefaultProgress>(Started)
+    override val progress: Flow<DefaultProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -29,7 +31,7 @@ open class QueueingTask @Inject constructor() : Task<DefaultProgress, QueueingTa
         }
     } finally {
         Timber.i("Finished (isCanceled=$isCanceled).")
-        internalProgress.close()
+        internalProgress.value = Finished
     }
 
     private suspend fun runSafely(arguments: Arguments): Result {
@@ -40,7 +42,7 @@ open class QueueingTask @Inject constructor() : Task<DefaultProgress, QueueingTa
             arguments.path.appendText(it)
 
             Timber.v("Progress message: $it")
-            internalProgress.send(DefaultProgress(it))
+            internalProgress.value = ProgressResult(it)
             delay(arguments.delay)
         }
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/silenterror/SilentErrorTask.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/silenterror/SilentErrorTask.kt
index 81d6dfc42ee1f5d74ad11ad86d3c899d5530eed9..ca995ef75e8db528cbd8086d833b9509d596e584 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/silenterror/SilentErrorTask.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/silenterror/SilentErrorTask.kt
@@ -2,17 +2,18 @@ package de.rki.coronawarnapp.task.testtasks.silenterror
 
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskFactory
+import de.rki.coronawarnapp.task.common.Finished
+import de.rki.coronawarnapp.task.common.Started
 import de.rki.coronawarnapp.task.common.DefaultProgress
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import timber.log.Timber
 import javax.inject.Provider
 
 class SilentErrorTask : Task<DefaultProgress, SilentErrorTask.Result> {
 
-    private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
-    override val progress: Flow<DefaultProgress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<DefaultProgress>(Started)
+    override val progress: Flow<DefaultProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -22,7 +23,7 @@ class SilentErrorTask : Task<DefaultProgress, SilentErrorTask.Result> {
         throw arguments.error
     } finally {
         Timber.i("Finished (isCanceled=$isCanceled).")
-        internalProgress.close()
+        internalProgress.value = Finished
     }
 
     override suspend fun cancel() {
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/timeout/BaseTimeoutTask.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/timeout/BaseTimeoutTask.kt
index bafa28a2cb134a3c02fe723dd90eb2b9139b1e49..af06ee295d85f500fe3a7e27682df2369dbe5b4e 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/timeout/BaseTimeoutTask.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/task/testtasks/timeout/BaseTimeoutTask.kt
@@ -3,18 +3,19 @@ package de.rki.coronawarnapp.task.testtasks.timeout
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskCancellationException
 import de.rki.coronawarnapp.task.TaskFactory
+import de.rki.coronawarnapp.task.common.Finished
+import de.rki.coronawarnapp.task.common.Started
 import de.rki.coronawarnapp.task.common.DefaultProgress
-import kotlinx.coroutines.channels.ConflatedBroadcastChannel
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.asFlow
+import kotlinx.coroutines.flow.MutableStateFlow
 import timber.log.Timber
 import javax.inject.Provider
 
 abstract class BaseTimeoutTask : Task<DefaultProgress, TimeoutTaskResult> {
 
-    private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
-    override val progress: Flow<DefaultProgress> = internalProgress.asFlow()
+    private val internalProgress = MutableStateFlow<DefaultProgress>(Started)
+    override val progress: Flow<DefaultProgress> = internalProgress
 
     private var isCanceled = false
 
@@ -25,7 +26,7 @@ abstract class BaseTimeoutTask : Task<DefaultProgress, TimeoutTaskResult> {
         }
     } finally {
         Timber.i("Finished (isCanceled=$isCanceled).")
-        internalProgress.close()
+        internalProgress.value = Finished
     }
 
     private suspend fun runSafely(arguments: TimeoutTaskArguments): TimeoutTaskResult {
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/execution/task/VaccinationUpdateTaskTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/execution/task/VaccinationUpdateTaskTest.kt
index d1e7a0c15b92f14756e51e205f09478ba52bcb39..59c1af64093c344318739a48559cbbb27884342f 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/execution/task/VaccinationUpdateTaskTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/vaccination/core/execution/task/VaccinationUpdateTaskTest.kt
@@ -1,38 +1,29 @@
 package de.rki.coronawarnapp.vaccination.core.execution.task
 
-import de.rki.coronawarnapp.util.TimeStamper
 import de.rki.coronawarnapp.vaccination.core.repository.VaccinationRepository
 import io.mockk.MockKAnnotations
 import io.mockk.Runs
 import io.mockk.coEvery
 import io.mockk.coVerify
-import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.just
 import kotlinx.coroutines.test.runBlockingTest
-import org.joda.time.Instant
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
 
 class VaccinationUpdateTaskTest : BaseTest() {
 
-    @MockK lateinit var timeStamper: TimeStamper
     @MockK lateinit var vaccinationRepository: VaccinationRepository
 
-    private val currentInstant = Instant.ofEpochSecond(1611764225)
-
     @BeforeEach
     fun setUp() {
         MockKAnnotations.init(this)
 
-        every { timeStamper.nowUTC } returns currentInstant
-
         coEvery { vaccinationRepository.refresh(any()) } just Runs
     }
 
     private fun createInstance() = VaccinationUpdateTask(
-        timeStamper = timeStamper,
         vaccinationRepository = vaccinationRepository
     )