diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentTest.kt
index 292d1d2c64fa0004d0e3dc4e918cff094d7a617f..5f2f3a274e85e9c145fb7c1cab7cf55586869160 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentTest.kt
@@ -17,6 +17,7 @@ import de.rki.coronawarnapp.notification.ShareTestResultNotificationService
 import de.rki.coronawarnapp.statistics.source.StatisticsProvider
 import de.rki.coronawarnapp.statistics.ui.homecards.StatisticsHomeCard
 import de.rki.coronawarnapp.storage.TracingRepository
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.ui.homecards.SubmissionStateProvider
 import de.rki.coronawarnapp.submission.ui.homecards.TestPositiveCard
@@ -67,6 +68,7 @@ class HomeFragmentTest : BaseUITest() {
     @MockK lateinit var statisticsProvider: StatisticsProvider
     @MockK lateinit var deadmanNotificationScheduler: DeadmanNotificationScheduler
     @MockK lateinit var appShortcutsHelper: AppShortcutsHelper
+    @MockK lateinit var tracingSettings: TracingSettings
 
     private lateinit var homeFragmentViewModel: HomeFragmentViewModel
 
@@ -256,7 +258,8 @@ class HomeFragmentTest : BaseUITest() {
             cwaSettings = cwaSettings,
             statisticsProvider = statisticsProvider,
             deadmanNotificationScheduler = deadmanNotificationScheduler,
-            appShortcutsHelper = appShortcutsHelper
+            appShortcutsHelper = appShortcutsHelper,
+            tracingSettings = tracingSettings
         )
     )
 
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentTest.kt
index 7eeb02ee3d9649bea978adb941dacde0312778da..a0362781c44750b755b88ca6f51228a89fd8d598 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentTest.kt
@@ -4,6 +4,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
 import dagger.Module
 import dagger.android.ContributesAndroidInjector
 import de.rki.coronawarnapp.nearby.TracingPermissionHelper
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository
 import io.mockk.MockKAnnotations
 import io.mockk.Runs
@@ -31,6 +32,7 @@ class OnboardingTracingFragmentTest : BaseUITest() {
 
     @MockK lateinit var interopRepo: InteroperabilityRepository
     @MockK lateinit var factory: TracingPermissionHelper.Factory
+    @MockK lateinit var tracingSettings: TracingSettings
 
     @Rule
     @JvmField
@@ -47,7 +49,8 @@ class OnboardingTracingFragmentTest : BaseUITest() {
             OnboardingTracingFragmentViewModel(
                 interoperabilityRepository = interopRepo,
                 tracingPermissionHelperFactory = factory,
-                dispatcherProvider = TestDispatcherProvider()
+                dispatcherProvider = TestDispatcherProvider(),
+                tracingSettings = tracingSettings
             )
         )
 
diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaOnboardingFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaOnboardingFragmentViewModel.kt
index 6ca53f71453eed67437e683a2aa449027b609d08..49daaf6fa2da7d161058154d3607cca0196ca57c 100644
--- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaOnboardingFragmentViewModel.kt
+++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaOnboardingFragmentViewModel.kt
@@ -7,7 +7,6 @@ import dagger.assisted.AssistedInject
 import de.rki.coronawarnapp.contactdiary.ui.ContactDiarySettings
 import de.rki.coronawarnapp.environment.BuildConfigWrap
 import de.rki.coronawarnapp.main.CWASettings
-import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
 import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
@@ -42,10 +41,10 @@ class DeltaOnboardingFragmentViewModel @AssistedInject constructor(
             ContactDiarySettings.OnboardingStatus.NOT_ONBOARDED
     }
 
-    fun isDeltaOnboardingDone() = LocalData.isInteroperabilityShownAtLeastOnce
+    fun isDeltaOnboardingDone() = settings.wasInteroperabilityShownAtLeastOnce
 
     fun setDeltaOboardinDone(value: Boolean) {
-        LocalData.isInteroperabilityShownAtLeastOnce = value
+        settings.wasInteroperabilityShownAtLeastOnce = value
     }
 
     @AssistedFactory
diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentViewModel.kt
index 0212b6a3796ce9620ad366bddaf660bcc8427629..0218b306014d78f70d9cebd057cc2978cfbd7d66 100644
--- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentViewModel.kt
+++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentViewModel.kt
@@ -8,8 +8,7 @@ import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
 import com.google.gson.Gson
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
-import de.rki.coronawarnapp.storage.LocalData
-import de.rki.coronawarnapp.submission.SubmissionRepository
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryStorage
 import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryUpdater
 import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
@@ -17,7 +16,6 @@ import de.rki.coronawarnapp.util.serialization.BaseGson
 import de.rki.coronawarnapp.util.ui.SingleLiveEvent
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
 import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
-import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.map
 import timber.log.Timber
@@ -26,7 +24,7 @@ import java.util.UUID
 class SubmissionTestFragmentViewModel @AssistedInject constructor(
     dispatcherProvider: DispatcherProvider,
     private val tekHistoryStorage: TEKHistoryStorage,
-    private val submissionRepository: SubmissionRepository,
+    private val submissionSettings: SubmissionSettings,
     tekHistoryUpdaterFactory: TEKHistoryUpdater.Factory,
     @BaseGson baseGson: Gson
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
@@ -60,8 +58,7 @@ class SubmissionTestFragmentViewModel @AssistedInject constructor(
     )
 
     val errorEvents = SingleLiveEvent<Throwable>()
-    private val internalToken = MutableStateFlow(LocalData.registrationToken())
-    val currentTestId = internalToken.asLiveData()
+    val currentTestId = submissionSettings.registrationToken.flow.asLiveData()
 
     val shareTEKsEvent = SingleLiveEvent<TEKExport>()
 
@@ -85,13 +82,15 @@ class SubmissionTestFragmentViewModel @AssistedInject constructor(
         .asLiveData(context = dispatcherProvider.Default)
 
     fun scrambleRegistrationToken() {
-        LocalData.registrationToken(UUID.randomUUID().toString())
-        internalToken.value = LocalData.registrationToken()
+        submissionSettings.registrationToken.update {
+            UUID.randomUUID().toString()
+        }
     }
 
     fun deleteRegistrationToken() {
-        LocalData.registrationToken(null)
-        internalToken.value = LocalData.registrationToken()
+        submissionSettings.registrationToken.update {
+            null
+        }
     }
 
     fun updateStorage() {
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 f797cf5b89cd738c7f47d106b854ef1f2ec08064..d57407ef4e48d7f63255544a925d6fdae4e261a8 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
@@ -21,7 +21,9 @@ import de.rki.coronawarnapp.exception.reporting.ErrorReportReceiver
 import de.rki.coronawarnapp.exception.reporting.ReportingConstants.ERROR_REPORT_LOCAL_BROADCAST_CHANNEL
 import de.rki.coronawarnapp.notification.NotificationHelper
 import de.rki.coronawarnapp.risk.RiskLevelChangeDetector
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
+import de.rki.coronawarnapp.storage.OnboardingSettings
+import de.rki.coronawarnapp.storage.preferences.EncryptedPreferencesMigration
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
 import de.rki.coronawarnapp.task.TaskController
 import de.rki.coronawarnapp.util.CWADebug
@@ -29,6 +31,7 @@ import de.rki.coronawarnapp.util.WatchdogService
 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.worker.BackgroundWorkScheduler
 import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.flow.onEach
@@ -57,6 +60,9 @@ class CoronaWarnApplication : Application(), HasAndroidInjector {
     @Inject lateinit var notificationHelper: NotificationHelper
     @Inject lateinit var deviceTimeHandler: DeviceTimeHandler
     @Inject lateinit var autoSubmission: AutoSubmission
+    @Inject lateinit var submissionSettings: SubmissionSettings
+    @Inject lateinit var onboardingSettings: OnboardingSettings
+    @Inject lateinit var encryptedPreferencesMigration: EncryptedPreferencesMigration
 
     @LogHistoryTree @Inject lateinit var rollingLogHistory: Timber.Tree
 
@@ -70,6 +76,10 @@ class CoronaWarnApplication : Application(), HasAndroidInjector {
 
         CWADebug.initAfterInjection(component)
 
+        encryptedPreferencesMigration.doMigration()
+
+        BackgroundWorkScheduler.init(component)
+
         Timber.plant(rollingLogHistory)
 
         Timber.v("onCreate(): WorkManager setup done: $workManager")
@@ -87,8 +97,8 @@ class CoronaWarnApplication : Application(), HasAndroidInjector {
             .onEach { isAppInForeground = it }
             .launchIn(GlobalScope)
 
-        if (LocalData.onboardingCompletedTimestamp() != null) {
-            if (!LocalData.isAllowedToSubmitDiagnosisKeys()) {
+        if (onboardingSettings.isOnboarded) {
+            if (!submissionSettings.isAllowedToSubmitKeys) {
                 deadmanNotificationScheduler.schedulePeriodic()
             }
             contactDiaryWorkScheduler.schedulePeriodic()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/RegistrationTokenCensor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/RegistrationTokenCensor.kt
index 6d1d15f608315295e742272515b256d6320f2686..81f2bece36227c378fb5c212b3a27171c2598a64 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/RegistrationTokenCensor.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/bugreporting/censors/RegistrationTokenCensor.kt
@@ -3,14 +3,16 @@ package de.rki.coronawarnapp.bugreporting.censors
 import dagger.Reusable
 import de.rki.coronawarnapp.bugreporting.censors.BugCensor.Companion.toNewLogLineIfDifferent
 import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.CWADebug
 import javax.inject.Inject
 
 @Reusable
-class RegistrationTokenCensor @Inject constructor() : BugCensor {
+class RegistrationTokenCensor @Inject constructor(
+    private val submissionSettings: SubmissionSettings
+) : BugCensor {
     override suspend fun checkLog(entry: LogLine): LogLine? {
-        val token = LocalData.registrationToken() ?: return null
+        val token = submissionSettings.registrationToken.value ?: return null
         if (!entry.message.contains(token)) return null
 
         val newMessage = if (CWADebug.isDeviceForTestersBuild) {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/Analytics.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/Analytics.kt
index 97949918f02c3590afca4dd76ab5fb8b3ae11f88..4c273c3bf87907bf9a2779923cade024be725462 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/Analytics.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/Analytics.kt
@@ -13,7 +13,7 @@ import de.rki.coronawarnapp.datadonation.safetynet.DeviceAttestation
 import de.rki.coronawarnapp.datadonation.safetynet.SafetyNetException
 import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData
 import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaDataRequestAndroid
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.OnboardingSettings
 import de.rki.coronawarnapp.util.TimeStamper
 import kotlinx.coroutines.TimeoutCancellationException
 import kotlinx.coroutines.flow.Flow
@@ -21,7 +21,6 @@ import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
 import kotlinx.coroutines.withTimeout
 import org.joda.time.Hours
-import org.joda.time.Instant
 import timber.log.Timber
 import javax.inject.Inject
 import javax.inject.Singleton
@@ -36,7 +35,8 @@ class Analytics @Inject constructor(
     private val donorModules: Set<@JvmSuppressWildcards DonorModule>,
     private val settings: AnalyticsSettings,
     private val logger: LastAnalyticsSubmissionLogger,
-    private val timeStamper: TimeStamper
+    private val timeStamper: TimeStamper,
+    private val onboardingSettings: OnboardingSettings
 ) {
     private val submissionLockoutMutex = Mutex()
 
@@ -173,7 +173,7 @@ class Analytics @Inject constructor(
 
     @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
     fun stopDueToTimeSinceOnboarding(): Boolean {
-        val onboarding = LocalData.onboardingCompletedTimestamp()?.let { Instant.ofEpochMilli(it) } ?: return true
+        val onboarding = onboardingSettings.onboardingCompletedTimestamp ?: return true
         return onboarding.plus(Hours.hours(ONBOARDING_DELAY_HOURS).toStandardDuration()).isAfter(timeStamper.nowUTC)
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/registeredtest/TestResultDonor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/registeredtest/TestResultDonor.kt
index 4a2053feca5bf156a479f8fb6085c4f70e80faf2..34f8be0bb2a6df2029de72f0de6a2888206da592 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/registeredtest/TestResultDonor.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/registeredtest/TestResultDonor.kt
@@ -6,7 +6,7 @@ import de.rki.coronawarnapp.datadonation.analytics.storage.TestResultDonorSettin
 import de.rki.coronawarnapp.risk.RiskLevelSettings
 import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
 import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.TimeStamper
 import de.rki.coronawarnapp.util.formatter.TestResult
 import kotlinx.coroutines.flow.first
@@ -22,6 +22,7 @@ class TestResultDonor @Inject constructor(
     private val riskLevelSettings: RiskLevelSettings,
     private val riskLevelStorage: RiskLevelStorage,
     private val timeStamper: TimeStamper,
+    private val submissionSettings: SubmissionSettings
 ) : DonorModule {
 
     override suspend fun beginDonation(request: DonorModule.Request): DonorModule.Contribution {
@@ -31,7 +32,7 @@ class TestResultDonor @Inject constructor(
             return TestResultMetadataNoContribution
         }
 
-        val timestampAtRegistration = LocalData.initialTestResultReceivedTimestamp()
+        val timestampAtRegistration = submissionSettings.initialTestResultReceivedAt
 
         if (timestampAtRegistration == null) {
             Timber.d("Skipping TestResultMetadata donation timestampAtRegistration isn't found")
@@ -43,8 +44,7 @@ class TestResultDonor @Inject constructor(
             .analytics
             .hoursSinceTestRegistrationToSubmitTestResultMetadata
 
-        val registrationTime = Instant.ofEpochMilli(timestampAtRegistration)
-        val hoursSinceTestRegistrationTime = Duration(registrationTime, timeStamper.nowUTC).standardHours.toInt()
+        val hoursSinceTestRegistrationTime = Duration(timestampAtRegistration, timeStamper.nowUTC).standardHours.toInt()
         val isDiffHoursMoreThanConfigHoursForPendingTest = hoursSinceTestRegistrationTime >= configHours
 
         val testResultAtRegistration =
@@ -53,7 +53,7 @@ class TestResultDonor @Inject constructor(
         val daysSinceMostRecentDateAtRiskLevelAtTestRegistration =
             calculateDaysSinceMostRecentDateAtRiskLevelAtTestRegistration(
                 riskLevelSettings.lastChangeCheckedRiskLevelTimestamp,
-                registrationTime
+                timestampAtRegistration
             )
 
         val riskLevelAtRegistration = testResultDonorSettings.riskLevelAtTestRegistration.value
@@ -62,7 +62,7 @@ class TestResultDonor @Inject constructor(
             if (riskLevelAtRegistration == PpaData.PPARiskLevel.RISK_LEVEL_LOW) {
                 DEFAULT_HOURS_SINCE_HIGH_RISK_WARNING
             } else {
-                calculatedHoursSinceHighRiskWarning(registrationTime)
+                calculatedHoursSinceHighRiskWarning(timestampAtRegistration)
             }
 
         return when {
@@ -87,7 +87,7 @@ class TestResultDonor @Inject constructor(
              */
             testResultAtRegistration.isFinal ->
                 finalTestMetadataDonation(
-                    registrationTime,
+                    timestampAtRegistration,
                     testResultAtRegistration,
                     daysSinceMostRecentDateAtRiskLevelAtTestRegistration,
                     hoursSinceHighRiskWarningAtTestRegistration
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 b545c807ec7d29864850a5c770e6ffd08100da77..66ecae8a8c6a1d467ce314b3c71db8ab90ef3893 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
@@ -8,7 +8,7 @@ import de.rki.coronawarnapp.environment.EnvironmentSetup
 import de.rki.coronawarnapp.nearby.ENFClient
 import de.rki.coronawarnapp.nearby.modules.detectiontracker.TrackedExposureDetection
 import de.rki.coronawarnapp.risk.RollbackItem
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskCancellationException
 import de.rki.coronawarnapp.task.TaskFactory
@@ -33,7 +33,8 @@ class DownloadDiagnosisKeysTask @Inject constructor(
     private val appConfigProvider: AppConfigProvider,
     private val keyPackageSyncTool: KeyPackageSyncTool,
     private val timeStamper: TimeStamper,
-    private val settings: DownloadDiagnosisKeysSettings
+    private val settings: DownloadDiagnosisKeysSettings,
+    private val submissionSettings: SubmissionSettings
 ) : Task<DownloadDiagnosisKeysTask.Progress, Task.Result> {
 
     private val internalProgress = ConflatedBroadcastChannel<Progress>()
@@ -113,7 +114,7 @@ class DownloadDiagnosisKeysTask @Inject constructor(
             // remember version code of this execution for next time
             settings.updateLastVersionCodeToCurrent()
 
-            if (LocalData.isAllowedToSubmitDiagnosisKeys()) {
+            if (submissionSettings.isAllowedToSubmitKeys) {
                 Timber.tag(TAG).i("task aborted, positive test result")
                 return object : Task.Result {}
             }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/main/CWASettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/main/CWASettings.kt
index b571c7f7f8b45e1fc65f5649fd00afa618bf62b1..e335d18c8d841cfbacf6813521731ef5a3908e3f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/main/CWASettings.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/main/CWASettings.kt
@@ -12,8 +12,6 @@ import javax.inject.Inject
 /**
  * For general app related values,
  * e.g. "Has dialog been shown", as "OnBoarding been shown?"
- * In future refactoring it should contain all values
- * from **[de.rki.coronawarnapp.storage.LocalData]** that don't fit more specific classes.
  */
 class CWASettings @Inject constructor(
     @AppContext val context: Context
@@ -27,6 +25,10 @@ class CWASettings @Inject constructor(
         get() = prefs.getBoolean(PKEY_DEVICE_TIME_INCORRECT_ACK, false)
         set(value) = prefs.edit { putBoolean(PKEY_DEVICE_TIME_INCORRECT_ACK, value) }
 
+    var wasInteroperabilityShownAtLeastOnce: Boolean
+        get() = prefs.getBoolean(PKEY_INTEROPERABILITY_SHOWED_AT_LEAST_ONCE, false)
+        set(value) = prefs.edit { putBoolean(PKEY_INTEROPERABILITY_SHOWED_AT_LEAST_ONCE, value) }
+
     var firstReliableDeviceTime: Instant
         get() = Instant.ofEpochMilli(prefs.getLong(PKEY_DEVICE_TIME_FIRST_RELIABLE, 0L))
         set(value) = prefs.edit { putLong(PKEY_DEVICE_TIME_FIRST_RELIABLE, value.millis) }
@@ -42,6 +44,20 @@ class CWASettings @Inject constructor(
         ).let { raw -> ConfigData.DeviceTimeState.values().single { it.key == raw } }
         set(value) = prefs.edit { putString(PKEY_DEVICE_TIME_LAST_STATE_CHANGE_STATE, value.key) }
 
+    var numberOfRemainingSharePositiveTestResultReminders: Int
+        get() = prefs.getInt(PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT, Int.MIN_VALUE)
+        set(value) = prefs.edit { putInt(PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT, value) }
+
+    val isNotificationsRiskEnabled = prefs.createFlowPreference(
+        key = PKEY_NOTIFICATIONS_RISK_ENABLED,
+        defaultValue = false
+    )
+
+    val isNotificationsTestEnabled = prefs.createFlowPreference(
+        key = PKEY_NOTIFICATIONS_TEST_ENABLED,
+        defaultValue = false
+    )
+
     val lastChangelogVersion = prefs.createFlowPreference(
         key = LAST_CHANGELOG_VERSION,
         defaultValue = DEFAULT_APP_VERSION
@@ -53,9 +69,13 @@ class CWASettings @Inject constructor(
 
     companion object {
         private const val PKEY_DEVICE_TIME_INCORRECT_ACK = "devicetime.incorrect.acknowledged"
+        private const val PKEY_INTEROPERABILITY_SHOWED_AT_LEAST_ONCE = "interoperability.showed"
         private const val PKEY_DEVICE_TIME_FIRST_RELIABLE = "devicetime.correct.first"
         private const val PKEY_DEVICE_TIME_LAST_STATE_CHANGE_TIME = "devicetime.laststatechange.timestamp"
         private const val PKEY_DEVICE_TIME_LAST_STATE_CHANGE_STATE = "devicetime.laststatechange.state"
+        private const val PKEY_NOTIFICATIONS_RISK_ENABLED = "notifications.risk.enabled"
+        private const val PKEY_NOTIFICATIONS_TEST_ENABLED = "notifications.test.enabled"
+        private const val PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT = "testresults.count"
         private const val LAST_CHANGELOG_VERSION = "update.changelog.lastversion"
         private const val DEFAULT_APP_VERSION = 1L
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/TracingPermissionHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/TracingPermissionHelper.kt
index c726fe9f59792f8052772dc24dbf66c57a6bdeab..1c3ad7c8c64bb948aa51c69a4c3123f1922673a4 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/TracingPermissionHelper.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/TracingPermissionHelper.kt
@@ -6,7 +6,7 @@ import androidx.annotation.VisibleForTesting
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.util.coroutine.AppScope
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.first
@@ -16,6 +16,7 @@ import timber.log.Timber
 class TracingPermissionHelper @AssistedInject constructor(
     @Assisted private val callback: Callback,
     private val enfClient: ENFClient,
+    private val tracingSettings: TracingSettings,
     @AppScope private val scope: CoroutineScope
 ) {
 
@@ -73,11 +74,7 @@ class TracingPermissionHelper @AssistedInject constructor(
         return true
     }
 
-    private fun isConsentGiven(): Boolean {
-        val firstTracingActivationAt = LocalData.initialTracingActivationTimestamp()
-        Timber.tag(TAG).v("isConsentGiven(): First tracing activationat: %d", firstTracingActivationAt)
-        return firstTracingActivationAt != null
-    }
+    private fun isConsentGiven(): Boolean = tracingSettings.isConsentGiven
 
     interface Callback {
         fun onUpdateTracingStatus(isTracingEnabled: Boolean)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt
index 208465596fcc7d74c6eaf67970ed7232ac0c3197..e8c1e9f7d7ebfb442c6aa05bb584990db24ac6f6 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt
@@ -6,7 +6,7 @@ import com.google.android.gms.nearby.exposurenotification.ExposureNotificationCl
 import com.google.android.gms.nearby.exposurenotification.ExposureNotificationStatusCodes
 import de.rki.coronawarnapp.exception.ExceptionCategory
 import de.rki.coronawarnapp.exception.reporting.report
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.util.coroutine.AppScope
 import de.rki.coronawarnapp.util.flow.shareLatest
 import kotlinx.coroutines.CancellationException
@@ -30,6 +30,7 @@ import kotlin.coroutines.suspendCoroutine
 @Singleton
 class DefaultTracingStatus @Inject constructor(
     private val client: ExposureNotificationClient,
+    private val tracingSettings: TracingSettings,
     @AppScope val scope: CoroutineScope
 ) : TracingStatus {
 
@@ -72,14 +73,15 @@ class DefaultTracingStatus @Inject constructor(
         client.start()
             .addOnSuccessListener { cont.resume(it) }
             .addOnFailureListener { cont.resumeWithException(it) }
+            .also {
+                tracingSettings.isConsentGiven = true
+            }
     }
 
     private suspend fun asyncStop() = suspendCoroutine<Void> { cont ->
         client.stop()
             .addOnSuccessListener { cont.resume(it) }
             .addOnFailureListener { cont.resumeWithException(it) }
-    }.also {
-        LocalData.lastNonActiveTracingTimestamp(System.currentTimeMillis())
     }
 
     override val isTracingEnabled: Flow<Boolean> = flow {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/notification/ShareTestResultNotificationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/notification/ShareTestResultNotificationService.kt
index f18af548a82fda119acb5f6380691e98e73c6d72..ad5dac0ac493edcfc99e8d4ee4edf84f08ddad6b 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/notification/ShareTestResultNotificationService.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/notification/ShareTestResultNotificationService.kt
@@ -3,11 +3,11 @@ package de.rki.coronawarnapp.notification
 import android.content.Context
 import androidx.navigation.NavDeepLinkBuilder
 import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.notification.NotificationConstants.POSITIVE_RESULT_NOTIFICATION_ID
 import de.rki.coronawarnapp.notification.NotificationConstants.POSITIVE_RESULT_NOTIFICATION_INITIAL_OFFSET
 import de.rki.coronawarnapp.notification.NotificationConstants.POSITIVE_RESULT_NOTIFICATION_INTERVAL
 import de.rki.coronawarnapp.notification.NotificationConstants.POSITIVE_RESULT_NOTIFICATION_TOTAL_COUNT
-import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.ui.main.MainActivity
 import de.rki.coronawarnapp.util.TimeStamper
 import de.rki.coronawarnapp.util.di.AppContext
@@ -17,13 +17,14 @@ import javax.inject.Inject
 class ShareTestResultNotificationService @Inject constructor(
     @AppContext private val context: Context,
     private val timeStamper: TimeStamper,
-    private val notificationHelper: NotificationHelper
+    private val notificationHelper: NotificationHelper,
+    private val cwaSettings: CWASettings
 ) {
 
     fun scheduleSharePositiveTestResultReminder() {
-        if (LocalData.numberOfRemainingSharePositiveTestResultReminders < 0) {
+        if (cwaSettings.numberOfRemainingSharePositiveTestResultReminders < 0) {
             Timber.v("Schedule positive test result notification")
-            LocalData.numberOfRemainingSharePositiveTestResultReminders = POSITIVE_RESULT_NOTIFICATION_TOTAL_COUNT
+            cwaSettings.numberOfRemainingSharePositiveTestResultReminders = POSITIVE_RESULT_NOTIFICATION_TOTAL_COUNT
             notificationHelper.scheduleRepeatingNotification(
                 timeStamper.nowUTC.plus(POSITIVE_RESULT_NOTIFICATION_INITIAL_OFFSET),
                 POSITIVE_RESULT_NOTIFICATION_INTERVAL,
@@ -35,8 +36,8 @@ class ShareTestResultNotificationService @Inject constructor(
     }
 
     fun showSharePositiveTestResultNotification(notificationId: Int) {
-        if (LocalData.numberOfRemainingSharePositiveTestResultReminders > 0) {
-            LocalData.numberOfRemainingSharePositiveTestResultReminders -= 1
+        if (cwaSettings.numberOfRemainingSharePositiveTestResultReminders > 0) {
+            cwaSettings.numberOfRemainingSharePositiveTestResultReminders -= 1
             val pendingIntent = NavDeepLinkBuilder(context)
                 .setGraph(R.navigation.nav_graph)
                 .setComponentName(MainActivity::class.java)
@@ -61,7 +62,7 @@ class ShareTestResultNotificationService @Inject constructor(
 
     fun resetSharePositiveTestResultNotification() {
         cancelSharePositiveTestResultNotification()
-        LocalData.numberOfRemainingSharePositiveTestResultReminders = Int.MIN_VALUE
+        cwaSettings.numberOfRemainingSharePositiveTestResultReminders = Int.MIN_VALUE
         Timber.v("Positive test result notification counter has been reset")
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/notification/TestResultAvailableNotificationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/notification/TestResultAvailableNotificationService.kt
index 9a9c3412fce65d9c1f45ae41135afd5335e5a436..9b5995b38cb1e31beb0f151aec5de801d971c95f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/notification/TestResultAvailableNotificationService.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/notification/TestResultAvailableNotificationService.kt
@@ -3,7 +3,7 @@ package de.rki.coronawarnapp.notification
 import android.content.Context
 import androidx.navigation.NavDeepLinkBuilder
 import de.rki.coronawarnapp.R
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.ui.main.MainActivity
 import de.rki.coronawarnapp.util.device.ForegroundState
 import de.rki.coronawarnapp.util.di.AppContext
@@ -17,13 +17,14 @@ class TestResultAvailableNotificationService @Inject constructor(
     @AppContext private val context: Context,
     private val foregroundState: ForegroundState,
     private val navDeepLinkBuilderProvider: Provider<NavDeepLinkBuilder>,
-    private val notificationHelper: NotificationHelper
+    private val notificationHelper: NotificationHelper,
+    private val cwaSettings: CWASettings
 ) {
 
     suspend fun showTestResultAvailableNotification(testResult: TestResult) {
         if (foregroundState.isInForeground.first()) return
 
-        if (!LocalData.isNotificationsTestEnabled) {
+        if (!cwaSettings.isNotificationsTestEnabled.value) {
             Timber.i("Don't show test result available notification because user doesn't want to be informed")
             return
         }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/BackgroundNoise.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/BackgroundNoise.kt
index 608c329c993ddcb7a6a263aa2df4f8a81b0814ed..cce89d6506f7ccdb7fb2bc872f11f5a76aa5991e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/BackgroundNoise.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/BackgroundNoise.kt
@@ -1,35 +1,24 @@
 package de.rki.coronawarnapp.playbook
 
-import de.rki.coronawarnapp.storage.LocalData
-import de.rki.coronawarnapp.util.di.AppInjector
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.worker.BackgroundConstants
 import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
+import javax.inject.Inject
+import javax.inject.Singleton
 import kotlin.random.Random
 
-class BackgroundNoise {
-    companion object {
-        @Volatile
-        private var instance: BackgroundNoise? = null
-
-        fun getInstance(): BackgroundNoise {
-            return instance ?: synchronized(this) {
-                instance ?: BackgroundNoise().also {
-                    instance = it
-                }
-            }
-        }
-    }
-
+@Singleton
+class BackgroundNoise @Inject constructor(
+    private val submissionSettings: SubmissionSettings,
     private val playbook: Playbook
-        get() = AppInjector.component.playbook
-
+) {
     fun scheduleDummyPattern() {
         if (BackgroundConstants.NUMBER_OF_DAYS_TO_RUN_PLAYBOOK > 0)
             BackgroundWorkScheduler.scheduleBackgroundNoisePeriodicWork()
     }
 
     suspend fun foregroundScheduleCheck() {
-        if (LocalData.isAllowedToSubmitDiagnosisKeys()) {
+        if (submissionSettings.isAllowedToSubmitKeys) {
             val chance = Random.nextFloat() * 100
             if (chance < DefaultPlaybook.PROBABILITY_TO_EXECUTE_PLAYBOOK_ON_APP_OPEN) {
                 playbook.dummy()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelChangeDetector.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelChangeDetector.kt
index a746ab02146edcda3bf436f4f485e7cd93b318ed..8a6fe31799602ee50ff2aabe8522054b497c6d00 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelChangeDetector.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelChangeDetector.kt
@@ -8,7 +8,8 @@ import de.rki.coronawarnapp.datadonation.survey.Surveys
 import de.rki.coronawarnapp.notification.NotificationConstants.NEW_MESSAGE_RISK_LEVEL_SCORE_NOTIFICATION_ID
 import de.rki.coronawarnapp.notification.NotificationHelper
 import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.TracingSettings
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.coroutine.AppScope
 import de.rki.coronawarnapp.util.device.ForegroundState
 import de.rki.coronawarnapp.util.di.AppContext
@@ -22,6 +23,7 @@ import kotlinx.coroutines.flow.onEach
 import timber.log.Timber
 import javax.inject.Inject
 
+@Suppress("LongParameterList")
 class RiskLevelChangeDetector @Inject constructor(
     @AppContext private val context: Context,
     @AppScope private val appScope: CoroutineScope,
@@ -30,7 +32,9 @@ class RiskLevelChangeDetector @Inject constructor(
     private val notificationManagerCompat: NotificationManagerCompat,
     private val foregroundState: ForegroundState,
     private val notificationHelper: NotificationHelper,
-    private val surveys: Surveys
+    private val surveys: Surveys,
+    private val submissionSettings: SubmissionSettings,
+    private val tracingSettings: TracingSettings
 ) {
 
     fun launch() {
@@ -64,7 +68,7 @@ class RiskLevelChangeDetector @Inject constructor(
 
         Timber.d("Last state was $oldRiskState and current state is $newRiskState")
 
-        if (hasHighLowLevelChanged(oldRiskState, newRiskState) && !LocalData.submissionWasSuccessful()) {
+        if (hasHighLowLevelChanged(oldRiskState, newRiskState) && !submissionSettings.isSubmissionSuccessful) {
             Timber.d("Notification Permission = ${notificationManagerCompat.areNotificationsEnabled()}")
 
             if (!foregroundState.isInForeground.first()) {
@@ -80,7 +84,7 @@ class RiskLevelChangeDetector @Inject constructor(
         }
 
         if (oldRiskState == RiskState.INCREASED_RISK && newRiskState == RiskState.LOW_RISK) {
-            LocalData.isUserToBeNotifiedOfLoweredRiskLevel = true
+            tracingSettings.isUserToBeNotifiedOfLoweredRiskLevel.update { true }
             Timber.d("Risk level changed LocalData is updated. Current Risk level is $newRiskState")
 
             surveys.resetSurvey(Surveys.Type.HIGH_RISK_ENCOUNTER)
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 058d658c79fd84cf764a8176046b2baf158f8a8b..0bdfeb13edd4bfc6c51bd722fbc0ebd21d0cdaf5 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
@@ -15,7 +15,7 @@ import de.rki.coronawarnapp.nearby.modules.detectiontracker.TrackedExposureDetec
 import de.rki.coronawarnapp.risk.RiskLevelResult.FailureReason
 import de.rki.coronawarnapp.risk.result.AggregatedRiskResult
 import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskCancellationException
 import de.rki.coronawarnapp.task.TaskFactory
@@ -45,6 +45,7 @@ class RiskLevelTask @Inject constructor(
     private val appConfigProvider: AppConfigProvider,
     private val riskLevelStorage: RiskLevelStorage,
     private val keyCacheRepository: KeyCacheRepository,
+    private val submissionSettings: SubmissionSettings,
     private val analyticsExposureWindowCollector: AnalyticsExposureWindowCollector
 ) : Task<DefaultProgress, RiskLevelTaskResult> {
 
@@ -82,7 +83,7 @@ class RiskLevelTask @Inject constructor(
             Timber.d("The current time is %s", it)
         }
 
-        if (LocalData.isAllowedToSubmitDiagnosisKeys()) {
+        if (submissionSettings.isAllowedToSubmitKeys) {
             Timber.i("Positive test result, skip risk calculation")
             return RiskLevelTaskResult(
                 calculatedAt = nowUTC,
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/EncryptedPreferences.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/EncryptedPreferences.kt
deleted file mode 100644
index 63733ba49fa6471e67ab037f2835dbcf677a8381..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/EncryptedPreferences.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package de.rki.coronawarnapp.storage
-
-import javax.inject.Qualifier
-
-@Qualifier
-@MustBeDocumented
-@Retention(AnnotationRetention.RUNTIME)
-annotation class EncryptedPreferences
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt
deleted file mode 100644
index a5cb1011cb3155c2f2275c19f7a7b6addd8253e4..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt
+++ /dev/null
@@ -1,448 +0,0 @@
-package de.rki.coronawarnapp.storage
-
-import android.content.SharedPreferences
-import androidx.core.content.edit
-import de.rki.coronawarnapp.CoronaWarnApplication
-import de.rki.coronawarnapp.R
-import de.rki.coronawarnapp.util.security.SecurityHelper.globalEncryptedSharedPreferencesInstance
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
-import timber.log.Timber
-
-/**
- * LocalData is responsible for all access to the shared preferences. Each preference is accessible
- * by a string which is stored in strings.xml.
- *
- * @see SharedPreferences
- */
-object LocalData {
-
-    private const val PREFERENCE_INTEROPERABILITY_IS_USED_AT_LEAST_ONCE =
-        "preference_interoperability_is_used_at_least_once"
-
-    private const val PREFERENCE_HAS_RISK_STATUS_LOWERED =
-        "preference_has_risk_status_lowered"
-
-    /****************************************************
-     * ONBOARDING DATA
-     ****************************************************/
-
-    /**
-     * Gets the boolean if the user has completed the onboarding
-     * from the EncryptedSharedPrefs
-     *
-     * @return boolean if user is onboarded
-     */
-    fun isOnboarded(): Boolean = getSharedPreferenceInstance().getBoolean(
-        CoronaWarnApplication.getAppContext().getString(R.string.preference_onboarding_completed),
-        false
-    )
-
-    /**
-     * Sets the boolean if the user has completed the onboarding
-     * from the EncryptedSharedPrefs
-     *
-     * @param value boolean if onboarding was completed
-     */
-    fun isOnboarded(value: Boolean) = getSharedPreferenceInstance().edit(true) {
-        putBoolean(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_onboarding_completed),
-            value
-        )
-    }
-
-    /**
-     * Gets the time when the user has completed the onboarding
-     * from the EncryptedSharedPrefs
-     *
-     * @return
-     */
-    fun onboardingCompletedTimestamp(): Long? {
-        val timestamp = getSharedPreferenceInstance().getLong(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_onboarding_completed_timestamp),
-            0L
-        )
-
-        if (timestamp == 0L) return null
-        return timestamp
-    }
-
-    /**
-     * Sets the time when the user has completed the onboarding
-     * from the EncryptedSharedPrefs
-     * @param value
-     */
-    fun onboardingCompletedTimestamp(value: Long) = getSharedPreferenceInstance().edit(true) {
-        putLong(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_onboarding_completed_timestamp),
-            value
-        )
-    }
-
-    /**
-     * Gets the boolean if the user has received the background warning
-     * from the EncryptedSharedPrefs
-     *
-     * @return boolean if background warning was shown
-     */
-    fun isBackgroundCheckDone(): Boolean = getSharedPreferenceInstance().getBoolean(
-        CoronaWarnApplication.getAppContext().getString(R.string.preference_background_check_done),
-        false
-    )
-
-    /**
-     * Sets the boolean if the user has received the background warning
-     * from the EncryptedSharedPrefs
-     *
-     * @param value boolean if background warning was shown
-     */
-    fun isBackgroundCheckDone(value: Boolean) = getSharedPreferenceInstance().edit(true) {
-        putBoolean(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_background_check_done),
-            value
-        )
-    }
-    /****************************************************
-     * TRACING DATA
-     ****************************************************/
-
-    /**
-     * Gets the initial timestamp when tracing was activated for the first time in ms
-     *
-     * @return timestamp in ms
-     */
-    fun initialTracingActivationTimestamp(): Long? {
-        val timestamp = getSharedPreferenceInstance().getLong(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_initial_tracing_activation_time),
-            0L
-        )
-
-        if (timestamp == 0L) return null
-        return timestamp
-    }
-
-    /**
-     * Sets the initial timestamp when tracing was activated for the first time in ms
-     *
-     * @param value timestamp in ms
-     */
-    fun initialTracingActivationTimestamp(value: Long) =
-        getSharedPreferenceInstance().edit(true) {
-            putLong(
-                CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_initial_tracing_activation_time),
-                value
-            )
-        }
-
-    /**
-     * Gets the timestamp when the user stopped Exposure Notification tracing the last time
-     * from the EncryptedSharedPrefs
-     *
-     * @return timestamp in ms
-     */
-    fun lastNonActiveTracingTimestamp(): Long? {
-        val timestamp = getSharedPreferenceInstance().getLong(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_last_non_active_tracing_timestamp),
-            0L
-        )
-        if (timestamp == 0L) return null
-        return timestamp
-    }
-
-    /**
-     * Sets the timestamp when the user stopped Exposure Notification tracing the last time
-     * from the EncryptedSharedPrefs
-     *
-     * @param value timestamp in ms
-     */
-    fun lastNonActiveTracingTimestamp(value: Long?) = getSharedPreferenceInstance().edit(true) {
-        putLong(
-            CoronaWarnApplication.getAppContext().getString(
-                R.string.preference_last_non_active_tracing_timestamp
-            ),
-            value ?: 0L
-        )
-    }
-
-    /**
-     * Sets the total amount of time the tracing was not active
-     * from the EncryptedSharedPrefs
-     *
-     * @param value timestamp in ms
-     */
-    fun totalNonActiveTracing(value: Long?) {
-        getSharedPreferenceInstance().edit(true) {
-            putLong(
-                CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_total_non_active_tracing),
-                value ?: 0L
-            )
-        }
-    }
-
-    /**
-     * Gets the total amount of time the tracing was not active
-     * from the EncryptedSharedPrefs
-     *
-     * @return timestamp in ms
-     */
-    fun totalNonActiveTracing(): Long {
-        return getSharedPreferenceInstance().getLong(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_total_non_active_tracing),
-            0L
-        )
-    }
-
-    /**
-
-     * Gets the timestamp when the Background Polling Began initially
-     * from the EncryptedSharedPrefs
-     *
-     * @return timestamp in ms
-     */
-    fun initialPollingForTestResultTimeStamp(): Long {
-        return getSharedPreferenceInstance().getLong(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_polling_test_result_started),
-            0L
-        )
-    }
-
-    /**
-     * Sets the timestamp when the Background Polling Began initially
-     * from the EncryptedSharedPrefs
-     *
-     * @param value timestamp in ms
-     */
-    fun initialPollingForTestResultTimeStamp(value: Long) =
-        getSharedPreferenceInstance().edit(true) {
-            putLong(
-                CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_polling_test_result_started),
-                value
-            )
-        }
-
-    /**
-
-     * Gets the flag if notification is executed on Status Change
-     * from the EncryptedSharedPrefs
-     *
-     * @return boolean
-     */
-    fun isTestResultAvailableNotificationSent(): Boolean {
-        return getSharedPreferenceInstance().getBoolean(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_test_result_notification),
-            false
-        )
-    }
-
-    /**
-     * Sets the flag if notification is executed on Status Change
-     * from the EncryptedSharedPrefs
-     *
-     * @param value boolean
-     */
-    fun isTestResultAvailableNotificationSent(value: Boolean) =
-        getSharedPreferenceInstance().edit(true) {
-            putBoolean(
-                CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_test_result_notification),
-                value
-            )
-        }
-
-    /**
-     * Sets a boolean depending whether the risk level decreased or not.
-     */
-    private val isUserToBeNotifiedOfLoweredRiskLevelFlowInternal by lazy {
-        MutableStateFlow(isUserToBeNotifiedOfLoweredRiskLevel)
-    }
-    val isUserToBeNotifiedOfLoweredRiskLevelFlow: Flow<Boolean> by lazy {
-        isUserToBeNotifiedOfLoweredRiskLevelFlowInternal
-    }
-    var isUserToBeNotifiedOfLoweredRiskLevel: Boolean
-        get() = getSharedPreferenceInstance().getBoolean(
-            PREFERENCE_HAS_RISK_STATUS_LOWERED,
-            false
-        )
-        set(value) = getSharedPreferenceInstance()
-            .edit(commit = true) { putBoolean(PREFERENCE_HAS_RISK_STATUS_LOWERED, value) }
-            .also { isUserToBeNotifiedOfLoweredRiskLevelFlowInternal.value = value }
-
-    /****************************************************
-     * SETTINGS DATA
-     ****************************************************/
-
-    private const val PKEY_NOTIFICATIONS_RISK_ENABLED = "preference_notifications_risk_enabled"
-
-    private val isNotificationsRiskEnabledFlowInternal by lazy {
-        MutableStateFlow(isNotificationsRiskEnabled)
-    }
-    val isNotificationsRiskEnabledFlow: Flow<Boolean> by lazy {
-        isNotificationsRiskEnabledFlowInternal
-    }
-    var isNotificationsRiskEnabled: Boolean
-        get() = getSharedPreferenceInstance().getBoolean(PKEY_NOTIFICATIONS_RISK_ENABLED, true)
-        set(value) = getSharedPreferenceInstance().edit(true) {
-            putBoolean(PKEY_NOTIFICATIONS_RISK_ENABLED, value)
-            isNotificationsRiskEnabledFlowInternal.value = value
-        }
-
-    private const val PKEY_NOTIFICATIONS_TEST_ENABLED = "preference_notifications_test_enabled"
-    private val isNotificationsTestEnabledFlowInternal by lazy {
-        MutableStateFlow(isNotificationsTestEnabled)
-    }
-    val isNotificationsTestEnabledFlow: Flow<Boolean> by lazy {
-        isNotificationsTestEnabledFlowInternal
-    }
-    var isNotificationsTestEnabled: Boolean
-        get() = getSharedPreferenceInstance().getBoolean(PKEY_NOTIFICATIONS_TEST_ENABLED, true)
-        set(value) = getSharedPreferenceInstance().edit(true) {
-            putBoolean(PKEY_NOTIFICATIONS_TEST_ENABLED, value)
-            isNotificationsTestEnabledFlowInternal.value = value
-        }
-
-    private const val PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT = "preference_positive_test_result_reminder_count"
-    var numberOfRemainingSharePositiveTestResultReminders: Int
-        get() = getSharedPreferenceInstance().getInt(PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT, Int.MIN_VALUE)
-        set(value) = getSharedPreferenceInstance().edit(true) {
-            putInt(PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT, value)
-        }
-
-    /****************************************************
-     * SUBMISSION DATA
-     ****************************************************/
-
-    private const val PREFERENCE_REGISTRATION_TOKEN = "preference_registration_token"
-
-    /**
-     * Gets the registration token that is needed for the submission process
-     *
-     * @return the registration token
-     */
-    fun registrationToken(): String? = getSharedPreferenceInstance()
-        .getString(PREFERENCE_REGISTRATION_TOKEN, null)
-
-    /**
-     * Sets the registration token that is needed for the submission process
-     *
-     * @param value registration token as string
-     */
-    fun registrationToken(value: String?) {
-        getSharedPreferenceInstance().edit(true) {
-            putString(PREFERENCE_REGISTRATION_TOKEN, value)
-        }
-    }
-
-    fun initialTestResultReceivedTimestamp(value: Long) =
-        getSharedPreferenceInstance().edit(true) {
-            putLong(
-                CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_initial_result_received_time),
-                value
-            )
-        }
-
-    fun initialTestResultReceivedTimestamp(): Long? {
-        val timestamp = getSharedPreferenceInstance().getLong(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_initial_result_received_time),
-            0L
-        )
-
-        if (timestamp == 0L) return null
-        return timestamp
-    }
-
-    fun devicePairingSuccessfulTimestamp(value: Long) =
-        getSharedPreferenceInstance().edit(true) {
-            putLong(
-                CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_device_pairing_successful_time),
-                value
-            )
-        }
-
-    fun devicePairingSuccessfulTimestamp(): Long {
-        return getSharedPreferenceInstance().getLong(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_device_pairing_successful_time),
-            0L
-        )
-    }
-
-    fun numberOfSuccessfulSubmissions(value: Int) =
-        getSharedPreferenceInstance().edit(true) {
-            putInt(
-                CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_number_successful_submissions),
-                value
-            )
-        }
-
-    private fun numberOfSuccessfulSubmissions(): Int {
-        return getSharedPreferenceInstance().getInt(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_number_successful_submissions),
-            0
-        )
-    }
-
-    fun submissionWasSuccessful(): Boolean = numberOfSuccessfulSubmissions() >= 1
-
-    fun isAllowedToSubmitDiagnosisKeys(isAllowedToSubmitDiagnosisKeys: Boolean) {
-        getSharedPreferenceInstance().edit(true) {
-            putBoolean(
-                CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_is_allowed_to_submit_diagnosis_keys),
-                isAllowedToSubmitDiagnosisKeys
-            )
-        }
-    }
-
-    fun isAllowedToSubmitDiagnosisKeys(): Boolean {
-        return getSharedPreferenceInstance().getBoolean(
-            CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_is_allowed_to_submit_diagnosis_keys),
-            false
-        )
-    }
-
-    /****************************************************
-     * ENCRYPTED SHARED PREFERENCES HANDLING
-     ****************************************************/
-
-    private fun getSharedPreferenceInstance(): SharedPreferences = globalEncryptedSharedPreferencesInstance
-
-    /****************************************************
-     * INTEROPERABILITY
-     ****************************************************/
-
-    var isInteroperabilityShownAtLeastOnce: Boolean
-        get() {
-            return getSharedPreferenceInstance().getBoolean(
-                PREFERENCE_INTEROPERABILITY_IS_USED_AT_LEAST_ONCE,
-                false
-            )
-        }
-        set(value) {
-            getSharedPreferenceInstance().edit(true) {
-                putBoolean(PREFERENCE_INTEROPERABILITY_IS_USED_AT_LEAST_ONCE, value)
-            }
-        }
-
-    fun clear() {
-        // If you make use of a FlowPreference, you need to manually clear it here
-        Timber.w("LocalData.clear()")
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/OnboardingSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/OnboardingSettings.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1f22c31b71311e5ad2a7b7e08a053151da93f8ae
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/OnboardingSettings.kt
@@ -0,0 +1,40 @@
+package de.rki.coronawarnapp.storage
+
+import android.content.Context
+import androidx.core.content.edit
+import de.rki.coronawarnapp.util.di.AppContext
+import de.rki.coronawarnapp.util.preferences.clearAndNotify
+import org.joda.time.Instant
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class OnboardingSettings @Inject constructor(
+    @AppContext private val context: Context
+) {
+    private val prefs by lazy {
+        context.getSharedPreferences("onboarding_localdata", Context.MODE_PRIVATE)
+    }
+
+    var onboardingCompletedTimestamp: Instant?
+        get() = prefs.getLong(ONBOARDING_COMPLETED_TIMESTAMP, 0L).let {
+            if (it != 0L) {
+                Instant.ofEpochMilli(it)
+            } else null
+        }
+        set(value) = prefs.edit { putLong(ONBOARDING_COMPLETED_TIMESTAMP, value?.millis ?: 0L) }
+
+    val isOnboarded: Boolean
+        get() = onboardingCompletedTimestamp != null
+
+    var isBackgroundCheckDone: Boolean
+        get() = prefs.getBoolean(BACKGROUND_CHECK_DONE, false)
+        set(value) = prefs.edit { putBoolean(BACKGROUND_CHECK_DONE, value) }
+
+    fun clear() = prefs.clearAndNotify()
+
+    companion object {
+        private const val ONBOARDING_COMPLETED_TIMESTAMP = "onboarding.done.timestamp"
+        private const val BACKGROUND_CHECK_DONE = "onboarding.background.checked"
+    }
+}
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 197617c59e7036b4798387deadc399e128f48973..49488cc0e03fd3dd3dcb9f3add4fcc5edb6b154d 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
@@ -32,7 +32,6 @@ import javax.inject.Singleton
  * The Tracing Repository refreshes and triggers all tracing relevant data. Some functions get their
  * data directly from the Exposure Notification, others consume the shared preferences.
  *
- * @see LocalData
  * @see InternalExposureNotificationClient
  */
 @Singleton
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingSettings.kt
new file mode 100644
index 0000000000000000000000000000000000000000..63f4739e96fc9ebde92732f85661316e1d373638
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingSettings.kt
@@ -0,0 +1,49 @@
+package de.rki.coronawarnapp.storage
+
+import android.content.Context
+import androidx.core.content.edit
+import de.rki.coronawarnapp.util.di.AppContext
+import de.rki.coronawarnapp.util.preferences.clearAndNotify
+import de.rki.coronawarnapp.util.preferences.createFlowPreference
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class TracingSettings @Inject constructor(@AppContext private val context: Context) {
+
+    private val prefs by lazy {
+        context.getSharedPreferences("tracing_settings", Context.MODE_PRIVATE)
+    }
+
+    var isConsentGiven: Boolean
+        get() = prefs.getBoolean(TRACING_ACTIVATION_TIMESTAMP, false)
+        set(value) = prefs.edit(true) {
+            putBoolean(TRACING_ACTIVATION_TIMESTAMP, value)
+        }
+
+    var initialPollingForTestResultTimeStamp: Long
+        get() = prefs.getLong(TRACING_POOLING_TIMESTAMP, 0L)
+        set(value) = prefs.edit(true) {
+            putLong(TRACING_POOLING_TIMESTAMP, value)
+        }
+
+    var isTestResultAvailableNotificationSent: Boolean
+        get() = prefs.getBoolean(TEST_RESULT_NOTIFICATION_SENT, false)
+        set(value) = prefs.edit(true) {
+            putBoolean(TEST_RESULT_NOTIFICATION_SENT, value)
+        }
+
+    val isUserToBeNotifiedOfLoweredRiskLevel = prefs.createFlowPreference(
+        key = LOWERED_RISK_LEVEL,
+        defaultValue = false
+    )
+
+    fun clear() = prefs.clearAndNotify()
+
+    companion object {
+        const val TRACING_POOLING_TIMESTAMP = "tracing.pooling.timestamp"
+        const val TRACING_ACTIVATION_TIMESTAMP = "tracing.activation.timestamp"
+        const val TEST_RESULT_NOTIFICATION_SENT = "test.notification.sent"
+        const val LOWERED_RISK_LEVEL = "notification.risk.lowered"
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/interoperability/InteroperabilityRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/interoperability/InteroperabilityRepository.kt
index fb07dcbaef0e0ae6af55d59abc0e4393b00b9f8c..b17572eb8e5af1ab8d57d912c1de09249705b49e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/interoperability/InteroperabilityRepository.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/interoperability/InteroperabilityRepository.kt
@@ -1,7 +1,7 @@
 package de.rki.coronawarnapp.storage.interoperability
 
 import de.rki.coronawarnapp.appconfig.AppConfigProvider
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.ui.Country
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.onEach
@@ -12,7 +12,8 @@ import javax.inject.Singleton
 
 @Singleton
 class InteroperabilityRepository @Inject constructor(
-    private val appConfigProvider: AppConfigProvider
+    private val appConfigProvider: AppConfigProvider,
+    private val settings: CWASettings
 ) {
 
     val countryList = appConfigProvider.currentConfig
@@ -39,6 +40,6 @@ class InteroperabilityRepository @Inject constructor(
     }
 
     fun saveInteroperabilityUsed() {
-        LocalData.isInteroperabilityShownAtLeastOnce = true
+        settings.wasInteroperabilityShownAtLeastOnce = true
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/preferences/EncryptedPreferencesHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/preferences/EncryptedPreferencesHelper.kt
new file mode 100644
index 0000000000000000000000000000000000000000..45b15c4d4b07e2cfc3fe60a6c82221d300dfbca1
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/preferences/EncryptedPreferencesHelper.kt
@@ -0,0 +1,51 @@
+package de.rki.coronawarnapp.storage.preferences
+
+import android.content.SharedPreferences
+import android.content.pm.ApplicationInfo
+import androidx.core.content.edit
+import de.rki.coronawarnapp.exception.CwaSecurityException
+import de.rki.coronawarnapp.util.security.EncryptedPreferencesFactory
+import de.rki.coronawarnapp.util.security.EncryptionErrorResetTool
+import de.rki.coronawarnapp.util.security.SecurityConstants
+import java.io.File
+import javax.inject.Inject
+
+class EncryptedPreferencesHelper @Inject constructor(
+    private val applicationInfo: ApplicationInfo,
+    factory: EncryptedPreferencesFactory,
+    encryptionErrorResetTool: EncryptionErrorResetTool
+) {
+
+    private val encryptedPreferencesFile by lazy {
+        File(applicationInfo.dataDir)
+            .resolve("shared_prefs/${SecurityConstants.ENCRYPTED_SHARED_PREFERENCES_FILE}.xml")
+    }
+
+    val encryptedSharedPreferencesInstance: SharedPreferences? by lazy {
+        withSecurityCatch {
+            try {
+                if (encryptedPreferencesFile.exists()) {
+                    factory.create(SecurityConstants.ENCRYPTED_SHARED_PREFERENCES_FILE)
+                } else {
+                    null
+                }
+            } catch (e: Exception) {
+                encryptionErrorResetTool.isResetNoticeToBeShown = true
+                null
+            }
+        }
+    }
+
+    fun clean() {
+        encryptedSharedPreferencesInstance?.edit(true) {
+            clear()
+        }
+        encryptedPreferencesFile.delete()
+    }
+
+    private fun <T> withSecurityCatch(doInCatch: () -> T) = try {
+        doInCatch.invoke()
+    } catch (e: Exception) {
+        throw CwaSecurityException(e)
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/preferences/EncryptedPreferencesMigration.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/preferences/EncryptedPreferencesMigration.kt
new file mode 100644
index 0000000000000000000000000000000000000000..cda45aade8aba1a42b5211b52bbfab33d807f92e
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/preferences/EncryptedPreferencesMigration.kt
@@ -0,0 +1,167 @@
+package de.rki.coronawarnapp.storage.preferences
+
+import android.content.Context
+import android.content.SharedPreferences
+import android.database.sqlite.SQLiteDatabase
+import de.rki.coronawarnapp.main.CWASettings
+import de.rki.coronawarnapp.storage.OnboardingSettings
+import de.rki.coronawarnapp.storage.TracingSettings
+import de.rki.coronawarnapp.submission.SubmissionSettings
+import de.rki.coronawarnapp.util.TimeAndDateExtensions.toInstantOrNull
+import de.rki.coronawarnapp.util.di.AppContext
+import org.joda.time.Instant
+import timber.log.Timber
+import javax.inject.Inject
+
+class EncryptedPreferencesMigration @Inject constructor(
+    @AppContext private val context: Context,
+    private val encryptedPreferencesHelper: EncryptedPreferencesHelper,
+    private val cwaSettings: CWASettings,
+    private val submissionSettings: SubmissionSettings,
+    private val tracingSettings: TracingSettings,
+    private val onboardingSettings: OnboardingSettings
+) {
+
+    fun doMigration() {
+        Timber.d("Migration start")
+        try {
+            copyData()
+            cleanData()
+        } catch (e: Exception) {
+            Timber.e(e, "Migration was not successful")
+        }
+        try {
+            dropDatabase()
+        } catch (e: Exception) {
+            Timber.e(e, "Database removing was not successful")
+        }
+        Timber.d("Migration finish")
+    }
+
+    private fun copyData() {
+        val encryptedSharedPreferences = encryptedPreferencesHelper.encryptedSharedPreferencesInstance ?: return
+        Timber.d("EncryptedPreferences are available")
+        SettingsLocalData(encryptedSharedPreferences).apply {
+            cwaSettings.wasInteroperabilityShownAtLeastOnce = wasInteroperabilityShown()
+            cwaSettings.isNotificationsRiskEnabled.update { isNotificationsRiskEnabled() }
+            cwaSettings.isNotificationsTestEnabled.update { isNotificationsTestEnabled() }
+            cwaSettings.numberOfRemainingSharePositiveTestResultReminders =
+                numberOfRemainingSharePositiveTestResultReminders()
+        }
+
+        OnboardingLocalData(encryptedSharedPreferences).apply {
+            onboardingSettings.onboardingCompletedTimestamp = onboardingCompletedTimestamp()?.let {
+                Instant.ofEpochMilli(it)
+            }
+            onboardingSettings.isBackgroundCheckDone = isBackgroundCheckDone()
+        }
+
+        TracingLocalData(encryptedSharedPreferences).apply {
+            tracingSettings.initialPollingForTestResultTimeStamp = initialPollingForTestResultTimeStamp()
+            tracingSettings.isTestResultAvailableNotificationSent = isTestResultAvailableNotificationSent()
+            tracingSettings.isUserToBeNotifiedOfLoweredRiskLevel.update { isUserToBeNotifiedOfLoweredRiskLevel() }
+            tracingSettings.isConsentGiven = initialTracingActivationTimestamp() != 0L
+        }
+
+        SubmissionLocalData(encryptedSharedPreferences).apply {
+            submissionSettings.registrationToken.update {
+                registrationToken()
+            }
+            submissionSettings.initialTestResultReceivedAt = initialTestResultReceivedTimestamp().toInstantOrNull()
+            submissionSettings.devicePairingSuccessfulAt = devicePairingSuccessfulTimestamp().toInstantOrNull()
+            submissionSettings.isSubmissionSuccessful = numberOfSuccessfulSubmissions() >= 1
+            submissionSettings.isAllowedToSubmitKeys = isAllowedToSubmitDiagnosisKeys()
+        }
+    }
+
+    private fun cleanData() {
+        encryptedPreferencesHelper.clean()
+    }
+
+    private fun dropDatabase() {
+        val file = context.getDatabasePath("coronawarnapp-db")
+        if (file.exists()) {
+            Timber.d("Removing database $file")
+            SQLiteDatabase.deleteDatabase(file)
+        }
+    }
+
+    private class SettingsLocalData(private val sharedPreferences: SharedPreferences) {
+
+        fun wasInteroperabilityShown() = sharedPreferences.getBoolean(PREFERENCE_INTEROPERABILITY_WAS_USED, false)
+
+        fun isNotificationsRiskEnabled(): Boolean = sharedPreferences.getBoolean(PKEY_NOTIFICATIONS_RISK_ENABLED, true)
+
+        fun isNotificationsTestEnabled(): Boolean = sharedPreferences.getBoolean(PKEY_NOTIFICATIONS_TEST_ENABLED, true)
+
+        fun numberOfRemainingSharePositiveTestResultReminders(): Int =
+            sharedPreferences.getInt(PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT, Int.MIN_VALUE)
+
+        companion object {
+            private const val PREFERENCE_INTEROPERABILITY_WAS_USED = "preference_interoperability_is_used_at_least_once"
+            private const val PKEY_NOTIFICATIONS_RISK_ENABLED = "preference_notifications_risk_enabled"
+            private const val PKEY_NOTIFICATIONS_TEST_ENABLED = "preference_notifications_test_enabled"
+            private const val PKEY_POSITIVE_TEST_RESULT_REMINDER_COUNT =
+                "preference_positive_test_result_reminder_count"
+        }
+    }
+
+    private class OnboardingLocalData(private val sharedPreferences: SharedPreferences) {
+        fun onboardingCompletedTimestamp(): Long? {
+            val timestamp = sharedPreferences.getLong(PKEY_ONBOARDING_COMPLETED_TIMESTAMP, 0L)
+
+            if (timestamp == 0L) return null
+            return timestamp
+        }
+
+        fun isBackgroundCheckDone(): Boolean = sharedPreferences.getBoolean(PKEY_BACKGROUND_CHECK_DONE, false)
+
+        companion object {
+            private const val PKEY_ONBOARDING_COMPLETED_TIMESTAMP = "preference_onboarding_completed_timestamp"
+            private const val PKEY_BACKGROUND_CHECK_DONE = "preference_background_check_done"
+        }
+    }
+
+    private class TracingLocalData(private val sharedPreferences: SharedPreferences) {
+
+        fun initialPollingForTestResultTimeStamp() = sharedPreferences.getLong(PKEY_POOLING_TEST_RESULT_STARTED, 0L)
+
+        fun isTestResultAvailableNotificationSent() = sharedPreferences.getBoolean(PKEY_TEST_RESULT_NOTIFICATION, false)
+
+        fun isUserToBeNotifiedOfLoweredRiskLevel() = sharedPreferences.getBoolean(PKEY_HAS_RISK_STATUS_LOWERED, false)
+
+        fun initialTracingActivationTimestamp(): Long = sharedPreferences.getLong(PKEY_TRACING_ACTIVATION_TIME, 0L)
+
+        companion object {
+            private const val PKEY_POOLING_TEST_RESULT_STARTED = "preference_polling_test_result_started"
+            private const val PKEY_TEST_RESULT_NOTIFICATION = "preference_test_result_notification"
+            private const val PKEY_HAS_RISK_STATUS_LOWERED = "preference_has_risk_status_lowered"
+            private const val PKEY_TRACING_ACTIVATION_TIME = "preference_initial_tracing_activation_time"
+        }
+    }
+
+    private class SubmissionLocalData(private val sharedPreferences: SharedPreferences) {
+        fun registrationToken(): String? = sharedPreferences.getString(PKEY_REGISTRATION_TOKEN, null)
+
+        fun initialTestResultReceivedTimestamp(): Long? {
+            val timestamp = sharedPreferences.getLong(PKEY_INITIAL_RESULT_RECEIVED_TIME, 0L)
+
+            if (timestamp == 0L) return null
+            return timestamp
+        }
+
+        fun devicePairingSuccessfulTimestamp(): Long = sharedPreferences.getLong(PKEY_DEVICE_PARING_SUCCESSFUL_TIME, 0L)
+
+        fun numberOfSuccessfulSubmissions(): Int = sharedPreferences.getInt(PKEY_NUMBER_SUCCESSFUL_SUBMISSIONS, 0)
+
+        fun isAllowedToSubmitDiagnosisKeys(): Boolean = sharedPreferences.getBoolean(PKEY_IS_ALLOWED_TO_SUBMIT, false)
+
+        companion object {
+            private const val PKEY_REGISTRATION_TOKEN = "preference_registration_token"
+            private const val PKEY_INITIAL_RESULT_RECEIVED_TIME = "preference_initial_result_received_time"
+            private const val PKEY_DEVICE_PARING_SUCCESSFUL_TIME = "preference_device_pairing_successful_time"
+            private const val PKEY_NUMBER_SUCCESSFUL_SUBMISSIONS = "preference_number_successful_submissions"
+            private const val PKEY_IS_ALLOWED_TO_SUBMIT = "preference_is_allowed_to_submit_diagnosis_keys"
+        }
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionRepository.kt
index 8f496e37159faa663aadcb93e23adf3709b988b2..392fcd548e782a4f8cbd0eef0e9ee28c12e931fb 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionRepository.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionRepository.kt
@@ -9,7 +9,7 @@ import de.rki.coronawarnapp.exception.http.CwaWebException
 import de.rki.coronawarnapp.exception.reporting.report
 import de.rki.coronawarnapp.playbook.BackgroundNoise
 import de.rki.coronawarnapp.service.submission.SubmissionService
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryStorage
 import de.rki.coronawarnapp.util.DeviceUIState
 import de.rki.coronawarnapp.util.NetworkRequestWrapper
@@ -35,10 +35,12 @@ class SubmissionRepository @Inject constructor(
     private val timeStamper: TimeStamper,
     private val tekHistoryStorage: TEKHistoryStorage,
     private val deadmanNotificationScheduler: DeadmanNotificationScheduler,
-    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
+    private val backgroundNoise: BackgroundNoise,
+    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector,
+    private val tracingSettings: TracingSettings
 ) {
     private val testResultReceivedDateFlowInternal =
-        MutableStateFlow(Date(LocalData.initialTestResultReceivedTimestamp() ?: System.currentTimeMillis()))
+        MutableStateFlow((submissionSettings.initialTestResultReceivedAt ?: timeStamper.nowUTC).toDate())
     val testResultReceivedDateFlow: Flow<Date> = testResultReceivedDateFlowInternal
 
     private val deviceUIStateFlowInternal =
@@ -77,18 +79,18 @@ class SubmissionRepository @Inject constructor(
     }
 
     fun refreshDeviceUIState(refreshTestResult: Boolean = true) {
-        if (LocalData.submissionWasSuccessful()) {
+        if (submissionSettings.isSubmissionSuccessful) {
             deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL)
             return
         }
 
-        val registrationToken = LocalData.registrationToken()
+        val registrationToken = submissionSettings.registrationToken.value
         if (registrationToken == null) {
             deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED)
             return
         }
 
-        if (LocalData.isAllowedToSubmitDiagnosisKeys()) {
+        if (submissionSettings.isAllowedToSubmitKeys) {
             deviceUIStateFlowInternal.value = NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE)
             return
         }
@@ -123,20 +125,24 @@ class SubmissionRepository @Inject constructor(
 
     suspend fun asyncRegisterDeviceViaTAN(tan: String) {
         val registrationData = submissionService.asyncRegisterDeviceViaTAN(tan)
-        LocalData.registrationToken(registrationData.registrationToken)
+        submissionSettings.registrationToken.update {
+            registrationData.registrationToken
+        }
         updateTestResult(registrationData.testResult)
-        LocalData.devicePairingSuccessfulTimestamp(timeStamper.nowUTC.millis)
-        BackgroundNoise.getInstance().scheduleDummyPattern()
+        submissionSettings.devicePairingSuccessfulAt = timeStamper.nowUTC
+        backgroundNoise.scheduleDummyPattern()
         analyticsKeySubmissionCollector.reportTestRegistered()
         analyticsKeySubmissionCollector.reportRegisteredWithTeleTAN()
     }
 
     suspend fun asyncRegisterDeviceViaGUID(guid: String): TestResult {
         val registrationData = submissionService.asyncRegisterDeviceViaGUID(guid)
-        LocalData.registrationToken(registrationData.registrationToken)
+        submissionSettings.registrationToken.update {
+            registrationData.registrationToken
+        }
         updateTestResult(registrationData.testResult)
-        LocalData.devicePairingSuccessfulTimestamp(timeStamper.nowUTC.millis)
-        BackgroundNoise.getInstance().scheduleDummyPattern()
+        submissionSettings.devicePairingSuccessfulAt = timeStamper.nowUTC
+        backgroundNoise.scheduleDummyPattern()
         analyticsKeySubmissionCollector.reportTestRegistered()
         return registrationData.testResult
     }
@@ -152,22 +158,22 @@ class SubmissionRepository @Inject constructor(
         testResultFlow.value = testResult
 
         if (testResult == TestResult.POSITIVE) {
-            LocalData.isAllowedToSubmitDiagnosisKeys(true)
+            submissionSettings.isAllowedToSubmitKeys = true
             analyticsKeySubmissionCollector.reportPositiveTestResultReceived()
             deadmanNotificationScheduler.cancelScheduledWork()
         }
 
-        val initialTestResultReceivedTimestamp = LocalData.initialTestResultReceivedTimestamp()
+        val initialTestResultReceivedTimestamp = submissionSettings.initialTestResultReceivedAt
 
         if (initialTestResultReceivedTimestamp == null) {
-            val currentTime = System.currentTimeMillis()
-            LocalData.initialTestResultReceivedTimestamp(currentTime)
-            testResultReceivedDateFlowInternal.value = Date(currentTime)
+            val currentTime = timeStamper.nowUTC
+            submissionSettings.initialTestResultReceivedAt = currentTime
+            testResultReceivedDateFlowInternal.value = currentTime.toDate()
             if (testResult == TestResult.PENDING) {
                 BackgroundWorkScheduler.startWorkScheduler()
             }
         } else {
-            testResultReceivedDateFlowInternal.value = Date(initialTestResultReceivedTimestamp)
+            testResultReceivedDateFlowInternal.value = initialTestResultReceivedTimestamp.toDate()
         }
     }
 
@@ -184,13 +190,13 @@ class SubmissionRepository @Inject constructor(
         submissionSettings.hasGivenConsent.update { false }
         analyticsKeySubmissionCollector.reset()
         revokeConsentToSubmission()
-        LocalData.registrationToken(null)
-        LocalData.devicePairingSuccessfulTimestamp(0L)
-        LocalData.initialPollingForTestResultTimeStamp(0L)
-        LocalData.initialTestResultReceivedTimestamp(0L)
-        LocalData.isAllowedToSubmitDiagnosisKeys(false)
-        LocalData.isTestResultAvailableNotificationSent(false)
-        LocalData.numberOfSuccessfulSubmissions(0)
+        submissionSettings.registrationToken.update { null }
+        submissionSettings.devicePairingSuccessfulAt = null
+        tracingSettings.initialPollingForTestResultTimeStamp = 0L
+        submissionSettings.initialTestResultReceivedAt = null
+        submissionSettings.isAllowedToSubmitKeys = false
+        tracingSettings.isTestResultAvailableNotificationSent = false
+        submissionSettings.isSubmissionSuccessful = false
     }
 
     private fun deriveUiState(testResult: TestResult?): DeviceUIState = when (testResult) {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionSettings.kt
index 486111f0e4c7cc6dc21e1cd88726451e93839cdd..1b362ef1a3eb843e762cba992a45ea33a5557c7f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionSettings.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/SubmissionSettings.kt
@@ -1,7 +1,9 @@
 package de.rki.coronawarnapp.submission
 
 import android.content.Context
+import androidx.core.content.edit
 import com.google.gson.Gson
+import de.rki.coronawarnapp.util.TimeAndDateExtensions.toInstantOrNull
 import de.rki.coronawarnapp.util.di.AppContext
 import de.rki.coronawarnapp.util.preferences.FlowPreference
 import de.rki.coronawarnapp.util.preferences.clearAndNotify
@@ -35,25 +37,46 @@ class SubmissionSettings @Inject constructor(
         context.getSharedPreferences("submission_localdata", Context.MODE_PRIVATE)
     }
 
+    val registrationToken = prefs.createFlowPreference<String?>(
+        key = TEST_REGISTRATION_TOKEN,
+        defaultValue = null
+    )
+
+    var initialTestResultReceivedAt: Instant?
+        get() = prefs.getLong(TEST_RESULT_RECEIVED_AT, 0L).toInstantOrNull()
+        set(value) = prefs.edit { putLong(TEST_RESULT_RECEIVED_AT, value?.millis ?: 0L) }
+
+    var devicePairingSuccessfulAt: Instant?
+        get() = prefs.getLong(TEST_PARING_SUCCESSFUL_AT, 0L).toInstantOrNull()
+        set(value) = prefs.edit { putLong(TEST_PARING_SUCCESSFUL_AT, value?.millis ?: 0L) }
+
+    var isSubmissionSuccessful: Boolean
+        get() = prefs.getBoolean(IS_KEY_SUBMISSION_SUCCESSFUL, false)
+        set(value) = prefs.edit { putBoolean(IS_KEY_SUBMISSION_SUCCESSFUL, value) }
+
+    var isAllowedToSubmitKeys: Boolean
+        get() = prefs.getBoolean(IS_KEY_SUBMISSION_ALLOWED, false)
+        set(value) = prefs.edit { putBoolean(IS_KEY_SUBMISSION_ALLOWED, value) }
+
     val hasGivenConsent = prefs.createFlowPreference(
-        key = "key_submission_consent",
+        key = SUBMISSION_CONSENT_GIVEN,
         defaultValue = false
     )
 
     val hasViewedTestResult = prefs.createFlowPreference(
-        key = "key_submission_result_viewed",
+        key = SUBMISSION_RESULT_VIEWED,
         defaultValue = false
     )
 
     val symptoms: FlowPreference<Symptoms?> = FlowPreference(
         prefs,
-        key = "submission.symptoms.latest",
+        key = SUBMISSION_SYMPTOMS_LATEST,
         reader = FlowPreference.gsonReader<Symptoms?>(gson, null),
         writer = FlowPreference.gsonWriter(gson)
     )
 
     val lastSubmissionUserActivityUTC = prefs.createFlowPreference(
-        key = "submission.user.activity.last",
+        key = AUTO_SUBMISSION_LAST_USER_ACTIVITY,
         reader = { key ->
             Instant.ofEpochMilli(getLong(key, 0L))
         },
@@ -63,17 +86,17 @@ class SubmissionSettings @Inject constructor(
     )
 
     val autoSubmissionEnabled = prefs.createFlowPreference(
-        key = "submission.auto.enabled",
+        key = AUTO_SUBMISSION_ENABLED,
         defaultValue = false
     )
 
     val autoSubmissionAttemptsCount = prefs.createFlowPreference(
-        key = "submission.auto.attempts.count",
+        key = AUTO_SUBMISSION_ATTEMPT_COUNT,
         defaultValue = 0
     )
 
     val autoSubmissionAttemptsLast = prefs.createFlowPreference(
-        key = "submission.auto.attempts.last",
+        key = AUTO_SUBMISSION_LAST_ATTEMPT,
         reader = { key ->
             Instant.ofEpochMilli(getLong(key, 0L))
         },
@@ -82,7 +105,20 @@ class SubmissionSettings @Inject constructor(
         }
     )
 
-    fun clear() {
-        prefs.clearAndNotify()
+    fun clear() = prefs.clearAndNotify()
+
+    companion object {
+        private const val TEST_REGISTRATION_TOKEN = "submission.test.token"
+        private const val TEST_RESULT_RECEIVED_AT = "submission.test.result.receivedAt"
+        private const val TEST_PARING_SUCCESSFUL_AT = "submission.test.pairedAt"
+        private const val IS_KEY_SUBMISSION_ALLOWED = "submission.allowed"
+        private const val IS_KEY_SUBMISSION_SUCCESSFUL = "submission.successful"
+        private const val SUBMISSION_CONSENT_GIVEN = "key_submission_consent"
+        private const val SUBMISSION_RESULT_VIEWED = "key_submission_result_viewed"
+        private const val SUBMISSION_SYMPTOMS_LATEST = "submission.symptoms.latest"
+        private const val AUTO_SUBMISSION_LAST_USER_ACTIVITY = "submission.user.activity.last"
+        private const val AUTO_SUBMISSION_ENABLED = "submission.auto.enabled"
+        private const val AUTO_SUBMISSION_ATTEMPT_COUNT = "submission.auto.attempts.count"
+        private const val AUTO_SUBMISSION_LAST_ATTEMPT = "submission.auto.attempts.last"
     }
 }
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 2bd1faa295558ef435ff124e78fc28ac8ea8c828..8232893d4888ca535c04abee92c7f978bfeb015c 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
@@ -7,7 +7,6 @@ import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException
 import de.rki.coronawarnapp.notification.ShareTestResultNotificationService
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
 import de.rki.coronawarnapp.playbook.Playbook
-import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.submission.Symptoms
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -119,7 +118,7 @@ class SubmissionTask @Inject constructor(
     }
 
     private suspend fun performSubmission(): Result {
-        val registrationToken = LocalData.registrationToken() ?: throw NoRegistrationTokenSetException()
+        val registrationToken = submissionSettings.registrationToken.value ?: throw NoRegistrationTokenSetException()
         Timber.tag(TAG).d("Using registrationToken=$registrationToken")
 
         val keys: List<TemporaryExposureKey> = try {
@@ -167,7 +166,7 @@ class SubmissionTask @Inject constructor(
     private fun setSubmissionFinished() {
         Timber.tag(TAG).d("setSubmissionFinished()")
         BackgroundWorkScheduler.stopWorkScheduler()
-        LocalData.numberOfSuccessfulSubmissions(1)
+        submissionSettings.isSubmissionSuccessful = true
         BackgroundWorkScheduler.startWorkScheduler()
 
         shareTestResultNotificationService.cancelSharePositiveTestResultNotification()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/SubmissionStateProvider.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/SubmissionStateProvider.kt
index add526c6fc104d3731060df0bcd13176a2222b29..d94e448b7c7e0789219c48b7f1344edf27a82801 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/SubmissionStateProvider.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/ui/homecards/SubmissionStateProvider.kt
@@ -2,8 +2,8 @@ package de.rki.coronawarnapp.submission.ui.homecards
 
 import dagger.Reusable
 import de.rki.coronawarnapp.exception.http.CwaServerError
-import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.submission.SubmissionRepository
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.CWADebug
 import de.rki.coronawarnapp.util.DeviceUIState
 import de.rki.coronawarnapp.util.NetworkRequestWrapper
@@ -18,18 +18,20 @@ import javax.inject.Inject
 
 @Reusable
 class SubmissionStateProvider @Inject constructor(
-    submissionRepository: SubmissionRepository
+    submissionRepository: SubmissionRepository,
+    submissionSettings: SubmissionSettings
 ) {
 
     val state: Flow<SubmissionState> = combine(
         submissionRepository.deviceUIStateFlow,
         submissionRepository.hasViewedTestResult,
-        submissionRepository.testResultReceivedDateFlow
-    ) { uiState, hasTestBeenSeen, testRegistrationDate ->
+        submissionRepository.testResultReceivedDateFlow,
+        submissionSettings.registrationToken.flow
+    ) { uiState, hasTestBeenSeen, testRegistrationDate, registrationToken ->
 
         val eval = Evaluation(
             deviceUiState = uiState,
-            isDeviceRegistered = LocalData.registrationToken() != null,
+            isDeviceRegistered = registrationToken != null,
             hasTestResultBeenSeen = hasTestBeenSeen
         )
         Timber.d("eval: %s", eval)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/launcher/LauncherActivityViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/launcher/LauncherActivityViewModel.kt
index acd7d63e6dc7763ab70d3da95733c8f1e61afded..5f83d8ea49767018da6f7c7a84879ec3296a7dde 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/launcher/LauncherActivityViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/launcher/LauncherActivityViewModel.kt
@@ -4,7 +4,7 @@ import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import de.rki.coronawarnapp.environment.BuildConfigWrap
 import de.rki.coronawarnapp.main.CWASettings
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.OnboardingSettings
 import de.rki.coronawarnapp.update.UpdateChecker
 import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
 import de.rki.coronawarnapp.util.ui.SingleLiveEvent
@@ -15,6 +15,7 @@ class LauncherActivityViewModel @AssistedInject constructor(
     private val updateChecker: UpdateChecker,
     dispatcherProvider: DispatcherProvider,
     private val cwaSettings: CWASettings,
+    private val onboardingSettings: OnboardingSettings
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     val events = SingleLiveEvent<LauncherEvent>()
@@ -31,7 +32,7 @@ class LauncherActivityViewModel @AssistedInject constructor(
     }
 
     private fun isJustInstalledOrUpdated() =
-        !LocalData.isOnboarded() || !LocalData.isInteroperabilityShownAtLeastOnce ||
+        !onboardingSettings.isOnboarded || !cwaSettings.wasInteroperabilityShownAtLeastOnce ||
             cwaSettings.lastChangelogVersion.value < BuildConfigWrap.VERSION_CODE
 
     @AssistedFactory
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt
index f6984c21e47c7cae1c08ef02749d3d15df21926b..545557ddd88760054a96560d618d8db498bc01f7 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt
@@ -22,7 +22,7 @@ import de.rki.coronawarnapp.contactdiary.ui.overview.ContactDiaryOverviewFragmen
 import de.rki.coronawarnapp.databinding.ActivityMainBinding
 import de.rki.coronawarnapp.datadonation.analytics.worker.DataDonationAnalyticsScheduler
 import de.rki.coronawarnapp.deadman.DeadmanNotificationScheduler
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.ui.base.startActivitySafely
 import de.rki.coronawarnapp.ui.setupWithNavController2
 import de.rki.coronawarnapp.util.AppShortcuts
@@ -84,6 +84,7 @@ class MainActivity : AppCompatActivity(), HasAndroidInjector {
     @Inject lateinit var deadmanScheduler: DeadmanNotificationScheduler
     @Inject lateinit var contactDiaryWorkScheduler: ContactDiaryWorkScheduler
     @Inject lateinit var dataDonationAnalyticsScheduler: DataDonationAnalyticsScheduler
+    @Inject lateinit var submissionSettings: SubmissionSettings
 
     override fun onCreate(savedInstanceState: Bundle?) {
         AppInjector.setup(this)
@@ -163,7 +164,7 @@ class MainActivity : AppCompatActivity(), HasAndroidInjector {
         vm.doBackgroundNoiseCheck()
         contactDiaryWorkScheduler.schedulePeriodic()
         dataDonationAnalyticsScheduler.schedulePeriodic()
-        if (!LocalData.isAllowedToSubmitDiagnosisKeys()) {
+        if (!submissionSettings.isAllowedToSubmitKeys) {
             deadmanScheduler.schedulePeriodic()
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityViewModel.kt
index 7db7bcbe8087531746be32bc27e7c5473de74daa..028197ca86763fa9b9bcfe559620172fc7f959e6 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityViewModel.kt
@@ -7,7 +7,7 @@ import dagger.assisted.AssistedInject
 import de.rki.coronawarnapp.contactdiary.ui.ContactDiarySettings
 import de.rki.coronawarnapp.environment.EnvironmentSetup
 import de.rki.coronawarnapp.playbook.BackgroundNoise
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.OnboardingSettings
 import de.rki.coronawarnapp.util.CWADebug
 import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
 import de.rki.coronawarnapp.util.device.BackgroundModeStatus
@@ -20,7 +20,9 @@ class MainActivityViewModel @AssistedInject constructor(
     dispatcherProvider: DispatcherProvider,
     private val environmentSetup: EnvironmentSetup,
     private val backgroundModeStatus: BackgroundModeStatus,
-    private val contactDiarySettings: ContactDiarySettings
+    private val contactDiarySettings: ContactDiarySettings,
+    private val backgroundNoise: BackgroundNoise,
+    private val onboardingSettings: OnboardingSettings
 ) : CWAViewModel(
     dispatcherProvider = dispatcherProvider
 ) {
@@ -43,8 +45,8 @@ class MainActivityViewModel @AssistedInject constructor(
         }
 
         launch {
-            if (!LocalData.isBackgroundCheckDone()) {
-                LocalData.isBackgroundCheckDone(true)
+            if (!onboardingSettings.isBackgroundCheckDone) {
+                onboardingSettings.isBackgroundCheckDone = true
                 if (backgroundModeStatus.isBackgroundRestricted.first()) {
                     showBackgroundJobDisabledNotification.postValue(Unit)
                 } else {
@@ -56,7 +58,7 @@ class MainActivityViewModel @AssistedInject constructor(
 
     fun doBackgroundNoiseCheck() {
         launch {
-            BackgroundNoise.getInstance().foregroundScheduleCheck()
+            backgroundNoise.foregroundScheduleCheck()
         }
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt
index f10170180f96824889fb921897e7607b463acf56..0c72da282baddaed96138f6756ab8620763cc3b6 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt
@@ -11,8 +11,8 @@ import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.notification.ShareTestResultNotificationService
 import de.rki.coronawarnapp.statistics.source.StatisticsProvider
 import de.rki.coronawarnapp.statistics.ui.homecards.StatisticsHomeCard
-import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.storage.TracingRepository
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.ui.homecards.FetchingResult
 import de.rki.coronawarnapp.submission.ui.homecards.NoTest
@@ -79,7 +79,8 @@ class HomeFragmentViewModel @AssistedInject constructor(
     appConfigProvider: AppConfigProvider,
     statisticsProvider: StatisticsProvider,
     private val deadmanNotificationScheduler: DeadmanNotificationScheduler,
-    private val appShortcutsHelper: AppShortcutsHelper
+    private val appShortcutsHelper: AppShortcutsHelper,
+    private val tracingSettings: TracingSettings,
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     private val tracingStateProvider by lazy { tracingStateProviderFactory.create(isDetailsMode = false) }
@@ -262,8 +263,9 @@ class HomeFragmentViewModel @AssistedInject constructor(
 
     // TODO only lazy to keep tests going which would break because of LocalData access
     val showLoweredRiskLevelDialog: LiveData<Boolean> by lazy {
-        LocalData
-            .isUserToBeNotifiedOfLoweredRiskLevelFlow
+        tracingSettings
+            .isUserToBeNotifiedOfLoweredRiskLevel
+            .flow
             .map { shouldBeNotified ->
                 val shouldBeShown = shouldBeNotified && !isLoweredRiskLevelDialogBeingShown
                 if (shouldBeShown) {
@@ -302,7 +304,7 @@ class HomeFragmentViewModel @AssistedInject constructor(
 
     fun userHasAcknowledgedTheLoweredRiskLevel() {
         isLoweredRiskLevelDialogBeingShown = false
-        LocalData.isUserToBeNotifiedOfLoweredRiskLevel = false
+        tracingSettings.isUserToBeNotifiedOfLoweredRiskLevel.update { false }
     }
 
     fun userHasAcknowledgedIncorrectDeviceTime() {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingActivity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingActivity.kt
index fe8a9252ff56112046101f42edf4e0a5c6ff8861..3888efc6398c11c741d3fc29bc6d796e1c36254e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingActivity.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingActivity.kt
@@ -13,16 +13,16 @@ import dagger.android.HasAndroidInjector
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.environment.BuildConfigWrap
 import de.rki.coronawarnapp.main.CWASettings
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.OnboardingSettings
 import de.rki.coronawarnapp.ui.main.MainActivity
 import de.rki.coronawarnapp.util.AppShortcuts
+import de.rki.coronawarnapp.util.TimeStamper
 import de.rki.coronawarnapp.util.di.AppInjector
 import javax.inject.Inject
 
 /**
  * This activity holds all the onboarding fragments and isn't used after a successful onboarding flow.
  *
- * @see LocalData
  */
 class OnboardingActivity : AppCompatActivity(), LifecycleObserver, HasAndroidInjector {
     companion object {
@@ -48,6 +48,8 @@ class OnboardingActivity : AppCompatActivity(), LifecycleObserver, HasAndroidInj
     override fun androidInjector(): AndroidInjector<Any> = dispatchingAndroidInjector
 
     @Inject lateinit var settings: CWASettings
+    @Inject lateinit var onboardingSettings: OnboardingSettings
+    @Inject lateinit var timeStamper: TimeStamper
 
     private val FragmentManager.currentNavigationFragment: Fragment?
         get() = primaryNavigationFragment?.childFragmentManager?.fragments?.first()
@@ -71,9 +73,12 @@ class OnboardingActivity : AppCompatActivity(), LifecycleObserver, HasAndroidInj
     }
 
     fun completeOnboarding() {
-        LocalData.isOnboarded(true)
-        LocalData.onboardingCompletedTimestamp(System.currentTimeMillis())
-        settings.lastChangelogVersion.update { BuildConfigWrap.VERSION_CODE }
+        onboardingSettings.onboardingCompletedTimestamp = timeStamper.nowUTC
+
+        settings.lastChangelogVersion.update {
+            BuildConfigWrap.VERSION_CODE
+        }
+
         MainActivity.start(this)
         finish()
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingLoadingViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingLoadingViewModel.kt
index 57dbcfc194b293b008651726c8c4dc7124f45fc5..487f4be42bc2c8068136fcb0b79a05f51b03586b 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingLoadingViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingLoadingViewModel.kt
@@ -4,21 +4,24 @@ import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import de.rki.coronawarnapp.environment.BuildConfigWrap
 import de.rki.coronawarnapp.main.CWASettings
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.OnboardingSettings
 import de.rki.coronawarnapp.util.ui.SingleLiveEvent
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
 import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
 
-class OnboardingLoadingViewModel @AssistedInject constructor(private val cwaSettings: CWASettings) : CWAViewModel() {
+class OnboardingLoadingViewModel @AssistedInject constructor(
+    private val cwaSettings: CWASettings,
+    private val onboardingSettings: OnboardingSettings
+) : CWAViewModel() {
 
     val navigationEvents = SingleLiveEvent<OnboardingFragmentEvents>()
 
     fun navigate() {
         when {
-            !LocalData.isOnboarded() -> {
+            !onboardingSettings.isOnboarded -> {
                 navigationEvents.postValue(OnboardingFragmentEvents.ShowOnboarding)
             }
-            !LocalData.isInteroperabilityShownAtLeastOnce -> {
+            !cwaSettings.wasInteroperabilityShownAtLeastOnce -> {
                 navigationEvents.postValue(OnboardingFragmentEvents.ShowInteropDeltaOnboarding)
             }
             cwaSettings.lastChangelogVersion.value < BuildConfigWrap.VERSION_CODE -> {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt
index 844e900278f2dd137c08cddb441dd38f1f96ff03..dca5b110f9d065b6af5a29728cbeb3ae83dfa58b 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingTracingFragmentViewModel.kt
@@ -9,7 +9,7 @@ import de.rki.coronawarnapp.exception.ExceptionCategory
 import de.rki.coronawarnapp.exception.reporting.report
 import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient
 import de.rki.coronawarnapp.nearby.TracingPermissionHelper
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository
 import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
 import de.rki.coronawarnapp.util.ui.SingleLiveEvent
@@ -20,7 +20,8 @@ import timber.log.Timber
 class OnboardingTracingFragmentViewModel @AssistedInject constructor(
     private val interoperabilityRepository: InteroperabilityRepository,
     tracingPermissionHelperFactory: TracingPermissionHelper.Factory,
-    dispatcherProvider: DispatcherProvider
+    dispatcherProvider: DispatcherProvider,
+    private val tracingSettings: TracingSettings,
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     val countryList = interoperabilityRepository.countryList
@@ -62,8 +63,7 @@ class OnboardingTracingFragmentViewModel @AssistedInject constructor(
             try {
                 if (InternalExposureNotificationClient.asyncIsEnabled()) {
                     InternalExposureNotificationClient.asyncStop()
-                    // Reset initial activation timestamp
-                    LocalData.initialTracingActivationTimestamp(0L)
+                    tracingSettings.isConsentGiven = false
                 }
             } catch (exception: Exception) {
                 exception.report(
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/notifications/NotificationSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/notifications/NotificationSettings.kt
index 3388bef869673426fcd8a42689d568f25fbfad09..6ecc209f9e0f46a21ee7645c350f5d6bef2248d3 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/notifications/NotificationSettings.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/notifications/NotificationSettings.kt
@@ -1,7 +1,7 @@
 package de.rki.coronawarnapp.ui.settings.notifications
 
 import androidx.core.app.NotificationManagerCompat
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.util.device.ForegroundState
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.map
@@ -11,6 +11,7 @@ import javax.inject.Singleton
 @Singleton
 class NotificationSettings @Inject constructor(
     foregroundState: ForegroundState,
+    private val cwaSettings: CWASettings,
     private val notificationManagerCompat: NotificationManagerCompat
 ) {
 
@@ -20,25 +21,23 @@ class NotificationSettings @Inject constructor(
         notificationManagerCompat.areNotificationsEnabled()
     }
 
-    val isNotificationsRiskEnabled: Flow<Boolean> = LocalData.isNotificationsRiskEnabledFlow
+    val isNotificationsRiskEnabled: Flow<Boolean> = cwaSettings.isNotificationsRiskEnabled.flow
 
     /**
      * Toggle notifications risk updates.
      *
-     * @see LocalData
      */
     fun toggleNotificationsRiskEnabled() {
-        LocalData.isNotificationsRiskEnabled = !LocalData.isNotificationsRiskEnabled
+        cwaSettings.isNotificationsRiskEnabled.update { !it }
     }
 
-    val isNotificationsTestEnabled: Flow<Boolean> = LocalData.isNotificationsTestEnabledFlow
+    val isNotificationsTestEnabled: Flow<Boolean> = cwaSettings.isNotificationsTestEnabled.flow
 
     /**
      * Toggle notifications for test updates in shared preferences and refresh it afterwards.
      *
-     * @see LocalData
      */
     fun toggleNotificationsTestEnabled() {
-        LocalData.isNotificationsTestEnabled = !LocalData.isNotificationsTestEnabled
+        cwaSettings.isNotificationsTestEnabled.update { !it }
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataReset.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataReset.kt
index d78661d2b7a2a4ac2d2152c02ade522a4c19440c..08eec626f20d6005b8aec183c6fa79f9a2fc0a7c 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataReset.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataReset.kt
@@ -15,10 +15,11 @@ import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.nearby.modules.detectiontracker.ExposureDetectionTracker
 import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
 import de.rki.coronawarnapp.statistics.source.StatisticsProvider
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.OnboardingSettings
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.submission.SubmissionRepository
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.di.AppContext
-import de.rki.coronawarnapp.util.security.SecurityHelper
 import kotlinx.coroutines.sync.Mutex
 import kotlinx.coroutines.sync.withLock
 import timber.log.Timber
@@ -45,7 +46,10 @@ class DataReset @Inject constructor(
     private val surveySettings: SurveySettings,
     private val analyticsSettings: AnalyticsSettings,
     private val analytics: Analytics,
-    private val bugReportingSettings: BugReportingSettings
+    private val bugReportingSettings: BugReportingSettings,
+    private val tracingSettings: TracingSettings,
+    private val onboardingSettings: OnboardingSettings,
+    private val submissionSettings: SubmissionSettings
 ) {
 
     private val mutex = Mutex()
@@ -57,11 +61,6 @@ class DataReset @Inject constructor(
     @SuppressLint("ApplySharedPref") // We need a commit here to ensure consistency
     suspend fun clearAllLocalData() = mutex.withLock {
         Timber.w("CWA LOCAL DATA DELETION INITIATED.")
-        // Because LocalData does not behave like a normal shared preference
-        LocalData.clear()
-        // Shared Preferences Reset
-        SecurityHelper.resetSharedPrefs()
-
         // Triggers deletion of all analytics contributed data
         analytics.setAnalyticsEnabled(false)
 
@@ -76,6 +75,9 @@ class DataReset @Inject constructor(
         cwaSettings.clear()
         surveySettings.clear()
         analyticsSettings.clear()
+        tracingSettings.clear()
+        onboardingSettings.clear()
+        submissionSettings.clear()
 
         // Clear contact diary database
         contactDiaryRepository.clear()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/RetryMechanism.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/RetryMechanism.kt
index ba2a372b51a99e49b2fdd04881f0d47d2b99f2c6..474bd237cdda0f3d3ae0a2ff9c284c6e3ef04780 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/RetryMechanism.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/RetryMechanism.kt
@@ -40,7 +40,7 @@ object RetryMechanism {
         }
     }
 
-    private const val DEFAULT_TOTAL_MAX_RETRY = 15 * 1000L // 15 seconds total delay
+    private const val DEFAULT_TOTAL_MAX_RETRY = 7 * 1000L // 7 seconds total delay
     private const val DEFAULT_MAX_DELAY = 3 * 1000L // 3 seconds max between retries
     private const val DEFAULT_MIN_DELAY = 25L // Almost immediate retry
     private const val DEFAULT_RETRY_MULTIPLIER = 1.5
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/TimeAndDateExtensions.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/TimeAndDateExtensions.kt
index 0a8833e9d86b937a49eab52c690c9e6a276cad6a..cfb9c9fca4ede8f16ae9bd4bf76ac2bfffde1c9c 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/TimeAndDateExtensions.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/TimeAndDateExtensions.kt
@@ -55,6 +55,14 @@ object TimeAndDateExtensions {
         }
     }
 
+    /**
+     * Converts a Long to Instant or null if the long is 0 or null
+     */
+    fun Long?.toInstantOrNull(): Instant? =
+        if (this != null && this != 0L) {
+            Instant.ofEpochMilli(this)
+        } else null
+
     /**
      * Converts milliseconds to human readable format hh:mm:ss
      *
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/WatchdogService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/WatchdogService.kt
index 3365de8462647f20759cd2856b946090ccac19e2..6ead4ba58ab9d791885e0f583891dcad02328f09 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/WatchdogService.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/WatchdogService.kt
@@ -6,7 +6,7 @@ import android.os.PowerManager
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
 import de.rki.coronawarnapp.diagnosiskeys.download.DownloadDiagnosisKeysTask
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.OnboardingSettings
 import de.rki.coronawarnapp.task.TaskController
 import de.rki.coronawarnapp.task.common.DefaultTaskRequest
 import de.rki.coronawarnapp.task.submitBlocking
@@ -27,7 +27,8 @@ class WatchdogService @Inject constructor(
     @AppContext private val context: Context,
     private val taskController: TaskController,
     private val backgroundModeStatus: BackgroundModeStatus,
-    @ProcessLifecycle private val processLifecycleOwner: LifecycleOwner
+    @ProcessLifecycle private val processLifecycleOwner: LifecycleOwner,
+    private val onboardingSettings: OnboardingSettings
 ) {
 
     private val powerManager by lazy {
@@ -73,7 +74,9 @@ class WatchdogService @Inject constructor(
 
         // if the user is onboarded we will schedule period background jobs
         // in case the app was force stopped and woken up again by the Google WakeUpService
-        if (LocalData.onboardingCompletedTimestamp() != null) BackgroundWorkScheduler.startWorkScheduler()
+        if (onboardingSettings.isOnboarded) {
+            BackgroundWorkScheduler.startWorkScheduler()
+        }
     }
 
     private fun createWakeLock(): PowerManager.WakeLock = powerManager
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/AndroidModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/AndroidModule.kt
index d548e33cdd1043f678b41558e4d97da5c38a2a43..813ad1b51f51fff8377f658371239fc01d278f6f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/AndroidModule.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/AndroidModule.kt
@@ -6,7 +6,7 @@ import android.app.NotificationManager
 import android.bluetooth.BluetoothAdapter
 import android.content.ContentResolver
 import android.content.Context
-import android.content.SharedPreferences
+import android.content.pm.ApplicationInfo
 import androidx.core.app.NotificationManagerCompat
 import androidx.core.content.getSystemService
 import androidx.lifecycle.LifecycleOwner
@@ -18,8 +18,6 @@ import com.google.android.gms.safetynet.SafetyNetClient
 import dagger.Module
 import dagger.Provides
 import de.rki.coronawarnapp.CoronaWarnApplication
-import de.rki.coronawarnapp.storage.EncryptedPreferences
-import de.rki.coronawarnapp.util.security.SecurityHelper
 import de.rki.coronawarnapp.util.worker.WorkManagerProvider
 import javax.inject.Singleton
 
@@ -57,11 +55,6 @@ class AndroidModule {
         workManagerProvider: WorkManagerProvider
     ): WorkManager = workManagerProvider.workManager
 
-    @EncryptedPreferences
-    @Provides
-    @Singleton
-    fun encryptedPreferences(): SharedPreferences = SecurityHelper.globalEncryptedSharedPreferencesInstance
-
     @Provides
     fun navDeepLinkBuilder(@AppContext context: Context): NavDeepLinkBuilder = NavDeepLinkBuilder(context)
 
@@ -80,4 +73,7 @@ class AndroidModule {
 
     @Provides
     fun contentResolver(@AppContext context: Context): ContentResolver = context.contentResolver
+
+    @Provides
+    fun applicationInfo(@AppContext context: Context): ApplicationInfo = context.applicationInfo
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt
index da4d4e081a5b64cb8664754d5b950c536c7513f6..35ee578c350d1feeaaaf43f1a4a3e9852c896171 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/di/ApplicationComponent.kt
@@ -41,6 +41,7 @@ import de.rki.coronawarnapp.util.security.SecurityModule
 import de.rki.coronawarnapp.util.serialization.SerializationModule
 import de.rki.coronawarnapp.util.worker.WorkerBinder
 import de.rki.coronawarnapp.verification.VerificationModule
+import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
 import javax.inject.Singleton
 
 @Singleton
@@ -84,6 +85,7 @@ interface ApplicationComponent : AndroidInjector<CoronaWarnApplication> {
     val enfClient: ENFClient
 
     val encryptedPreferencesFactory: EncryptedPreferencesFactory
+
     val errorResetTool: EncryptionErrorResetTool
 
     val playbook: Playbook
@@ -96,6 +98,8 @@ interface ApplicationComponent : AndroidInjector<CoronaWarnApplication> {
 
     fun inject(logger: DebugLogger)
 
+    fun inject(backgroundWorkScheduler: BackgroundWorkScheduler)
+
     @Component.Factory
     interface Factory {
         fun create(@BindsInstance app: CoronaWarnApplication): ApplicationComponent
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/EncryptionErrorResetTool.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/EncryptionErrorResetTool.kt
index ae4f6a47b04c194e57d4a36a28ed30a3995579e5..fd87b8a0ab525bacf7f0e9640088e7e87aedc36d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/EncryptionErrorResetTool.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/EncryptionErrorResetTool.kt
@@ -3,127 +3,25 @@ package de.rki.coronawarnapp.util.security
 import android.content.Context
 import android.content.SharedPreferences
 import androidx.core.content.edit
-import de.rki.coronawarnapp.util.TimeStamper
 import de.rki.coronawarnapp.util.di.AppContext
-import de.rki.coronawarnapp.util.errors.causes
-import org.joda.time.Instant
-import timber.log.Timber
-import java.io.File
-import java.security.GeneralSecurityException
 import javax.inject.Inject
 import javax.inject.Singleton
 
-/**
- * This tool determines the narrow scope for which we will recovery from an encryption error
- * by resetting our encrypted data.
- * This will allow users currently affected by it, that update the app, to keep using it without
- * requiring any manual actions from their side.
- *
- * https://github.com/corona-warn-app/cwa-app-android/issues/642
- */
 @Singleton
 class EncryptionErrorResetTool @Inject constructor(
-    @AppContext private val context: Context,
-    private val timeStamper: TimeStamper
+    @AppContext private val context: Context
 ) {
-    // https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/app/ContextImpl.java;drc=3b8e8d76315f6718a982d5e6a019b3aa4f634bcd;l=626
-    private val encryptedPreferencesFile by lazy {
-        val appbaseDir = context.filesDir.parentFile!!
-        val sharedPrefsDir = File(appbaseDir, "shared_prefs")
-        File(sharedPrefsDir, "${SecurityConstants.ENCRYPTED_SHARED_PREFERENCES_FILE}.xml")
-    }
     private val prefs: SharedPreferences by lazy {
         context.getSharedPreferences("encryption_error_reset_tool", Context.MODE_PRIVATE)
     }
 
-    private var isResetWindowConsumed: Boolean
-        get() = prefs.getBoolean(PKEY_EA1851_WAS_WINDOW_CONSUMED, false)
-        set(value) = prefs.edit {
-            putBoolean(PKEY_EA1851_WAS_WINDOW_CONSUMED, value)
-        }
-
-    private var resetPerformedAt: Instant?
-        get() = prefs.getLong(PKEY_EA1851_RESET_PERFORMED_AT, -1).let {
-            if (it == -1L) null else Instant.ofEpochMilli(it)
-        }
-        set(value) = prefs.edit {
-            if (value != null) {
-                putLong(PKEY_EA1851_RESET_PERFORMED_AT, value.millis)
-            } else {
-                remove(PKEY_EA1851_RESET_PERFORMED_AT)
-            }
-        }
-
     var isResetNoticeToBeShown: Boolean
         get() = prefs.getBoolean(PKEY_EA1851_SHOW_RESET_NOTICE, false)
         set(value) = prefs.edit {
             putBoolean(PKEY_EA1851_SHOW_RESET_NOTICE, value)
         }
 
-    fun tryResetIfNecessary(error: Throwable): Boolean {
-        Timber.w(error, "tryResetIfNecessary()")
-
-        // We only try to reset once, if the error reoccurs, on-going resets is not the solution.
-        if (isResetWindowConsumed) {
-            Timber.v("Reset window has been consumed -> no reset.")
-            return false
-        }
-        isResetWindowConsumed = true
-
-        val keyException = error.causes().lastOrNull()
-        if (keyException == null || keyException !is GeneralSecurityException) {
-            Timber.v("Error has no GeneralSecurityException as cause -> no reset.")
-            return false
-        }
-
-        // https://github.com/google/tink/blob/a8ec74d083068cd5e1ebed86fd8254630617b592/java_src/src/main/java/com/google/crypto/tink/aead/AeadWrapper.java#L83
-        if (keyException.message?.trim()?.equals("decryption failed") != true) {
-            Timber.v("Not the GeneralSecurityException we are looking for -> no reset.")
-            return false
-        }
-
-        if (!encryptedPreferencesFile.exists()) {
-            // The error we are looking for can only happen if there already is an encrypted preferences file
-            Timber.w(
-                "Error fits, but where is the existing preference file (%s)? -> no reset.",
-                encryptedPreferencesFile
-            )
-            return false
-        }
-
-        // So we have a GeneralSecurityException("decryption failed") and existing preferences
-        // And this is the first error we encountered after upgrading to 1.4.0, let's do this!
-
-        return try {
-            performReset()
-        } catch (e: Exception) {
-            // If anything goes wrong, we return false, so that our caller can rethrow the original error.
-            Timber.e(e, "Error while performing the reset.")
-            false
-        }
-    }
-
-    private fun performReset(): Boolean {
-        // Delete encrypted shared preferences file
-        if (!encryptedPreferencesFile.delete()) {
-            Timber.w("Couldn't delete %s", encryptedPreferencesFile)
-            // The encrypted preferences are a prerequisite for this error case
-            // If we can't delete that, we have to assume our reset approach failed.
-            return false
-        }
-
-        resetPerformedAt = timeStamper.nowUTC
-        isResetNoticeToBeShown = true
-
-        return true
-    }
-
     companion object {
-        private const val PKEY_EA1851_RESET_PERFORMED_AT = "ea1851.reset.performedAt"
-
-        @Suppress("unused")
-        private const val PKEY_EA1851_WAS_WINDOW_CONSUMED_OLD = "ea1851.reset.windowconsumed"
-        private const val PKEY_EA1851_WAS_WINDOW_CONSUMED = "ea1851.reset.windowconsumed.160"
         private const val PKEY_EA1851_SHOW_RESET_NOTICE = "ea1851.reset.shownotice"
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt
deleted file mode 100644
index cad222cb23d445517cd1760ef0762b155740f74a..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-package de.rki.coronawarnapp.util.security
-
-import android.annotation.SuppressLint
-import android.content.SharedPreferences
-import android.util.Base64
-import androidx.annotation.VisibleForTesting
-import de.rki.coronawarnapp.exception.CwaSecurityException
-import de.rki.coronawarnapp.util.di.AppInjector
-import de.rki.coronawarnapp.util.di.ApplicationComponent
-import de.rki.coronawarnapp.util.preferences.clearAndNotify
-import de.rki.coronawarnapp.util.security.SecurityConstants.ENCRYPTED_SHARED_PREFERENCES_FILE
-import timber.log.Timber
-
-/**
- * Key Store and Password Access
- */
-object SecurityHelper {
-
-    @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
-    internal val encryptedPreferencesProvider: (ApplicationComponent) -> SharedPreferences = {
-        val factory = it.encryptedPreferencesFactory
-        val encryptionErrorResetTool = it.errorResetTool
-        withSecurityCatch {
-            try {
-                factory.create(ENCRYPTED_SHARED_PREFERENCES_FILE)
-            } catch (e: Exception) {
-                if (encryptionErrorResetTool.tryResetIfNecessary(e)) {
-                    Timber.w("We could recovery from this error via reset. Now retrying.")
-                    factory.create(ENCRYPTED_SHARED_PREFERENCES_FILE)
-                } else {
-                    throw e
-                }
-            }
-        }
-    }
-
-    val globalEncryptedSharedPreferencesInstance: SharedPreferences by lazy {
-        encryptedPreferencesProvider(AppInjector.component)
-    }
-
-    private val String.toPreservedByteArray: ByteArray
-        get() = Base64.decode(this, Base64.NO_WRAP)
-
-    private val ByteArray.toPreservedString: String
-        get() = Base64.encodeToString(this, Base64.NO_WRAP)
-
-    @SuppressLint("ApplySharedPref")
-    fun resetSharedPrefs() {
-        globalEncryptedSharedPreferencesInstance.clearAndNotify()
-    }
-
-    fun <T> withSecurityCatch(doInCatch: () -> T) = try {
-        doInCatch.invoke()
-    } catch (e: Exception) {
-        throw CwaSecurityException(e)
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundNoisePeriodicWorker.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundNoisePeriodicWorker.kt
index f66cda4621d977c92e19d16da1c1fe0b5c8cf9cd..31922abf4120e6341508e056d82b84386aec82ab 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundNoisePeriodicWorker.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundNoisePeriodicWorker.kt
@@ -6,11 +6,12 @@ import androidx.work.WorkerParameters
 import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
+import de.rki.coronawarnapp.util.TimeStamper
 import de.rki.coronawarnapp.util.worker.InjectedWorkerFactory
 import de.rki.coronawarnapp.worker.BackgroundWorkScheduler.stop
-import org.joda.time.DateTime
-import org.joda.time.DateTimeZone
+import org.joda.time.Duration
+import org.joda.time.Instant
 import timber.log.Timber
 
 /**
@@ -20,7 +21,9 @@ import timber.log.Timber
  */
 class BackgroundNoisePeriodicWorker @AssistedInject constructor(
     @Assisted val context: Context,
-    @Assisted workerParams: WorkerParameters
+    @Assisted workerParams: WorkerParameters,
+    private val submissionSettings: SubmissionSettings,
+    private val timeStamper: TimeStamper
 ) : CoroutineWorker(context, workerParams) {
 
     /**
@@ -31,13 +34,13 @@ class BackgroundNoisePeriodicWorker @AssistedInject constructor(
 
         var result = Result.success()
         try {
-            val initialPairingDate = DateTime(
-                LocalData.devicePairingSuccessfulTimestamp(),
-                DateTimeZone.UTC
-            )
+            val initialPairingDate = submissionSettings.devicePairingSuccessfulAt ?: Instant.ofEpochMilli(0)
 
             // Check if the numberOfDaysToRunPlaybook are over
-            if (initialPairingDate.plusDays(BackgroundConstants.NUMBER_OF_DAYS_TO_RUN_PLAYBOOK).isBeforeNow) {
+            if (initialPairingDate
+                .plus(Duration.standardDays(NUMBER_OF_DAYS_TO_RUN_PLAYBOOK))
+                .isBefore(timeStamper.nowUTC)
+            ) {
                 stopWorker()
                 return result
             }
@@ -64,5 +67,6 @@ class BackgroundNoisePeriodicWorker @AssistedInject constructor(
 
     companion object {
         private val TAG = BackgroundNoisePeriodicWorker::class.java.simpleName
+        private const val NUMBER_OF_DAYS_TO_RUN_PLAYBOOK = BackgroundConstants.NUMBER_OF_DAYS_TO_RUN_PLAYBOOK.toLong()
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkScheduler.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkScheduler.kt
index 83804e32536b4875d0ae8917afbf951244699d5d..aaf6317d9be63bf12856a97c46cc9665512e65b7 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkScheduler.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkScheduler.kt
@@ -6,7 +6,7 @@ import androidx.work.Operation
 import androidx.work.WorkInfo
 import androidx.work.WorkManager
 import de.rki.coronawarnapp.CoronaWarnApplication
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.util.di.ApplicationComponent
 import timber.log.Timber
 import java.util.concurrent.ExecutionException
 
@@ -17,7 +17,11 @@ import java.util.concurrent.ExecutionException
  * @see BackgroundConstants
  * @see BackgroundWorkHelper
  */
-object BackgroundWorkScheduler {
+object BackgroundWorkScheduler : BackgroundWorkSchedulerBase() {
+
+    fun init(component: ApplicationComponent) {
+        component.inject(this)
+    }
 
     /**
      * Enum class for work tags
@@ -67,7 +71,7 @@ object BackgroundWorkScheduler {
      * Checks if periodic worker was already scheduled. If not - reschedule it again.
      * For [WorkTag.DIAGNOSIS_TEST_RESULT_RETRIEVAL_PERIODIC_WORKER] also checks if User is Registered
      *
-     * @see LocalData.registrationToken
+     * @see de.rki.coronawarnapp.submission.SubmissionSettings.registrationToken
      * @see isWorkActive
      */
     fun startWorkScheduler() {
@@ -82,12 +86,13 @@ object BackgroundWorkScheduler {
             WorkType.DIAGNOSIS_KEY_BACKGROUND_PERIODIC_WORK.start()
             notificationBody.append("[DIAGNOSIS_KEY_BACKGROUND_PERIODIC_WORK] ")
         }
-        if (!LocalData.submissionWasSuccessful()) {
+        if (!submissionSettings.isSubmissionSuccessful) {
             if (!isWorkActive(WorkTag.DIAGNOSIS_TEST_RESULT_RETRIEVAL_PERIODIC_WORKER.tag) &&
-                LocalData.registrationToken() != null && !LocalData.isTestResultAvailableNotificationSent()
+                submissionSettings.registrationToken.value != null &&
+                !tracingSettings.isTestResultAvailableNotificationSent
             ) {
                 WorkType.DIAGNOSIS_TEST_RESULT_PERIODIC_WORKER.start()
-                LocalData.initialPollingForTestResultTimeStamp(System.currentTimeMillis())
+                tracingSettings.initialPollingForTestResultTimeStamp = System.currentTimeMillis()
                 notificationBody.append("[DIAGNOSIS_TEST_RESULT_PERIODIC_WORKER]")
             }
         }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkSchedulerBase.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkSchedulerBase.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9085a1645570aa546c4f8294904096753b46b17c
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkSchedulerBase.kt
@@ -0,0 +1,11 @@
+package de.rki.coronawarnapp.worker
+
+import de.rki.coronawarnapp.storage.TracingSettings
+import de.rki.coronawarnapp.submission.SubmissionSettings
+import javax.inject.Inject
+
+@Suppress("UnnecessaryAbstractClass")
+abstract class BackgroundWorkSchedulerBase {
+    @Inject internal lateinit var submissionSettings: SubmissionSettings
+    @Inject internal lateinit var tracingSettings: TracingSettings
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisTestResultRetrievalPeriodicWorker.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisTestResultRetrievalPeriodicWorker.kt
index 1540f8aa6716b3fe2f59563403557f5b3f6bc0ea..dc01b596996a6a4ba9f9e2da9e9ee1d4f944bcfc 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisTestResultRetrievalPeriodicWorker.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisTestResultRetrievalPeriodicWorker.kt
@@ -11,7 +11,7 @@ import de.rki.coronawarnapp.notification.NotificationConstants
 import de.rki.coronawarnapp.notification.NotificationHelper
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
 import de.rki.coronawarnapp.service.submission.SubmissionService
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.TimeAndDateExtensions
 import de.rki.coronawarnapp.util.TimeStamper
@@ -32,7 +32,8 @@ class DiagnosisTestResultRetrievalPeriodicWorker @AssistedInject constructor(
     private val notificationHelper: NotificationHelper,
     private val submissionSettings: SubmissionSettings,
     private val submissionService: SubmissionService,
-    private val timeStamper: TimeStamper
+    private val timeStamper: TimeStamper,
+    private val tracingSettings: TracingSettings,
 ) : CoroutineWorker(context, workerParams) {
 
     override suspend fun doWork(): Result {
@@ -55,7 +56,8 @@ class DiagnosisTestResultRetrievalPeriodicWorker @AssistedInject constructor(
             } else {
                 Timber.tag(TAG).d(" $id Running worker.")
 
-                val registrationToken = LocalData.registrationToken() ?: throw NoRegistrationTokenSetException()
+                val registrationToken =
+                    submissionSettings.registrationToken.value ?: throw NoRegistrationTokenSetException()
                 val testResult = submissionService.asyncRequestTestResult(registrationToken)
                 Timber.tag(TAG).d("$id: Test Result retrieved is $testResult")
 
@@ -80,7 +82,7 @@ class DiagnosisTestResultRetrievalPeriodicWorker @AssistedInject constructor(
     }
 
     private fun abortConditionsMet(currentMillis: Long): Boolean {
-        if (LocalData.isTestResultAvailableNotificationSent()) {
+        if (tracingSettings.isTestResultAvailableNotificationSent) {
             Timber.tag(TAG).d("$id: Notification already sent.")
             return true
         }
@@ -90,7 +92,7 @@ class DiagnosisTestResultRetrievalPeriodicWorker @AssistedInject constructor(
         }
 
         val calculateDays = TimeAndDateExtensions.calculateDays(
-            LocalData.initialPollingForTestResultTimeStamp(),
+            tracingSettings.initialPollingForTestResultTimeStamp,
             currentMillis
         )
         if (calculateDays >= BackgroundConstants.POLLING_VALIDITY_MAX_DAYS) {
@@ -104,7 +106,7 @@ class DiagnosisTestResultRetrievalPeriodicWorker @AssistedInject constructor(
 
     private suspend fun sendTestResultAvailableNotification(testResult: TestResult) {
         testResultAvailableNotificationService.showTestResultAvailableNotification(testResult)
-        LocalData.isTestResultAvailableNotificationSent(true)
+        tracingSettings.isTestResultAvailableNotificationSent = true
     }
 
     private fun cancelRiskLevelScoreNotification() {
@@ -114,7 +116,7 @@ class DiagnosisTestResultRetrievalPeriodicWorker @AssistedInject constructor(
     }
 
     private fun stopWorker() {
-        LocalData.initialPollingForTestResultTimeStamp(0L)
+        tracingSettings.initialPollingForTestResultTimeStamp = 0L
         BackgroundWorkScheduler.WorkType.DIAGNOSIS_TEST_RESULT_PERIODIC_WORKER.stop()
         Timber.tag(TAG).d("$id: Background worker stopped")
     }
diff --git a/Corona-Warn-App/src/main/res/values-bg/strings.xml b/Corona-Warn-App/src/main/res/values-bg/strings.xml
index 66b184830757a23d3d7ac65d9cba3efe7d7ef5e7..498b4a70adc6927a2bfcbac7324d23829ba114a6 100644
--- a/Corona-Warn-App/src/main/res/values-bg/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-bg/strings.xml
@@ -1,47 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?><resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" tools:ignore="MissingTranslation">
-
-    <!-- ####################################
-               Preference Keys
-    ######################################
-    TODO: Check what is needed -->
-
-    <!-- NOTR -->
-    <string name="preference_name"><xliff:g id="preference">"shared_preferences_cwa"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed"><xliff:g id="preference">"preference_onboarding_completed"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed_timestamp"><xliff:g id="preference">"preference_onboarding_completed_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_background_check_done"><xliff:g id="preference">"preference_background_check_done"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_reset_app"><xliff:g id="preference">"preference_reset_app"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_only_wifi"><xliff:g id="preference">"preference_only_wifi"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_device_pairing_successful_time"><xliff:g id="preference">"preference_device_pairing_successful_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_tracing_activation_time"><xliff:g id="preference">"preference_initial_tracing_activation_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_result_received_time"><xliff:g id="preference">"preference_initial_result_received_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_is_allowed_to_submit_diagnosis_keys"><xliff:g id="preference">"preference_is_allowed_to_submit_diagnosis_keys"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_database_password"><xliff:g id="preference">"preference_database_password"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_total_non_active_tracing"><xliff:g id="preference">"preference_total_non_active_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_last_non_active_tracing_timestamp"><xliff:g id="preference">"preference_last_non_active_tracing_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_number_successful_submissions"><xliff:g id="preference">"preference_number_successful_submissions"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string>
-
     <!-- ####################################
                      Generics
     ###################################### -->
diff --git a/Corona-Warn-App/src/main/res/values-de/strings.xml b/Corona-Warn-App/src/main/res/values-de/strings.xml
index a53ffdb8b040030d0a39ce0d8bacbf424fa4674b..6e6d5106ce8aac361f155b78f0b1aa73f19296d9 100644
--- a/Corona-Warn-App/src/main/res/values-de/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-de/strings.xml
@@ -1,48 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" tools:ignore="MissingTranslation">
-
-    <!-- ####################################
-               Preference Keys
-    ######################################
-    TODO: Check what is needed -->
-
-    <!-- NOTR -->
-    <string name="preference_name"><xliff:g id="preference">"shared_preferences_cwa"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed"><xliff:g id="preference">"preference_onboarding_completed"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed_timestamp"><xliff:g id="preference">"preference_onboarding_completed_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_background_check_done"><xliff:g id="preference">"preference_background_check_done"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_reset_app"><xliff:g id="preference">"preference_reset_app"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_only_wifi"><xliff:g id="preference">"preference_only_wifi"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_device_pairing_successful_time"><xliff:g id="preference">"preference_device_pairing_successful_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_tracing_activation_time"><xliff:g id="preference">"preference_initial_tracing_activation_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_result_received_time"><xliff:g id="preference">"preference_initial_result_received_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_is_allowed_to_submit_diagnosis_keys"><xliff:g id="preference">"preference_is_allowed_to_submit_diagnosis_keys"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_database_password"><xliff:g id="preference">"preference_database_password"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_total_non_active_tracing"><xliff:g id="preference">"preference_total_non_active_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_last_non_active_tracing_timestamp"><xliff:g id="preference">"preference_last_non_active_tracing_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_number_successful_submissions"><xliff:g id="preference">"preference_number_successful_submissions"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string>
-
     <!-- ####################################
                      Generics
     ###################################### -->
diff --git a/Corona-Warn-App/src/main/res/values-en/strings.xml b/Corona-Warn-App/src/main/res/values-en/strings.xml
index 5c5ab53178ea2fc153b29af8d71ca2bbd6f09929..d21b9aeb089913ffc7d1e701b4293a6ab9c9c404 100644
--- a/Corona-Warn-App/src/main/res/values-en/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-en/strings.xml
@@ -1,47 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?><resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" tools:ignore="MissingTranslation">
-
-    <!-- ####################################
-               Preference Keys
-    ######################################
-    TODO: Check what is needed -->
-
-    <!-- NOTR -->
-    <string name="preference_name"><xliff:g id="preference">"shared_preferences_cwa"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed"><xliff:g id="preference">"preference_onboarding_completed"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed_timestamp"><xliff:g id="preference">"preference_onboarding_completed_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_background_check_done"><xliff:g id="preference">"preference_background_check_done"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_reset_app"><xliff:g id="preference">"preference_reset_app"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_only_wifi"><xliff:g id="preference">"preference_only_wifi"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_device_pairing_successful_time"><xliff:g id="preference">"preference_device_pairing_successful_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_tracing_activation_time"><xliff:g id="preference">"preference_initial_tracing_activation_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_result_received_time"><xliff:g id="preference">"preference_initial_result_received_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_is_allowed_to_submit_diagnosis_keys"><xliff:g id="preference">"preference_is_allowed_to_submit_diagnosis_keys"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_database_password"><xliff:g id="preference">"preference_database_password"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_total_non_active_tracing"><xliff:g id="preference">"preference_total_non_active_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_last_non_active_tracing_timestamp"><xliff:g id="preference">"preference_last_non_active_tracing_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_number_successful_submissions"><xliff:g id="preference">"preference_number_successful_submissions"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string>
-
     <!-- ####################################
                      Generics
     ###################################### -->
diff --git a/Corona-Warn-App/src/main/res/values-pl/strings.xml b/Corona-Warn-App/src/main/res/values-pl/strings.xml
index 60216c9b7fa6bd68251c7c47ba9fdeda7bc08dc3..37ffe028420b7ee05fc4b06555231732833cf717 100644
--- a/Corona-Warn-App/src/main/res/values-pl/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-pl/strings.xml
@@ -1,47 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?><resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" tools:ignore="MissingTranslation">
-
-    <!-- ####################################
-               Preference Keys
-    ######################################
-    TODO: Check what is needed -->
-
-    <!-- NOTR -->
-    <string name="preference_name"><xliff:g id="preference">"shared_preferences_cwa"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed"><xliff:g id="preference">"preference_onboarding_completed"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed_timestamp"><xliff:g id="preference">"preference_onboarding_completed_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_background_check_done"><xliff:g id="preference">"preference_background_check_done"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_reset_app"><xliff:g id="preference">"preference_reset_app"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_only_wifi"><xliff:g id="preference">"preference_only_wifi"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_device_pairing_successful_time"><xliff:g id="preference">"preference_device_pairing_successful_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_tracing_activation_time"><xliff:g id="preference">"preference_initial_tracing_activation_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_result_received_time"><xliff:g id="preference">"preference_initial_result_received_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_is_allowed_to_submit_diagnosis_keys"><xliff:g id="preference">"preference_is_allowed_to_submit_diagnosis_keys"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_database_password"><xliff:g id="preference">"preference_database_password"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_total_non_active_tracing"><xliff:g id="preference">"preference_total_non_active_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_last_non_active_tracing_timestamp"><xliff:g id="preference">"preference_last_non_active_tracing_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_number_successful_submissions"><xliff:g id="preference">"preference_number_successful_submissions"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string>
-
     <!-- ####################################
                      Generics
     ###################################### -->
diff --git a/Corona-Warn-App/src/main/res/values-ro/strings.xml b/Corona-Warn-App/src/main/res/values-ro/strings.xml
index e7339c1a902ed87a24aff5b842c5adc74fed36d3..ce6862eda5e9ecc090476dddc2648c28bec826a7 100644
--- a/Corona-Warn-App/src/main/res/values-ro/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-ro/strings.xml
@@ -1,47 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?><resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" tools:ignore="MissingTranslation">
-
-    <!-- ####################################
-               Preference Keys
-    ######################################
-    TODO: Check what is needed -->
-
-    <!-- NOTR -->
-    <string name="preference_name"><xliff:g id="preference">"shared_preferences_cwa"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed"><xliff:g id="preference">"preference_onboarding_completed"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed_timestamp"><xliff:g id="preference">"preference_onboarding_completed_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_background_check_done"><xliff:g id="preference">"preference_background_check_done"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_reset_app"><xliff:g id="preference">"preference_reset_app"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_only_wifi"><xliff:g id="preference">"preference_only_wifi"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_device_pairing_successful_time"><xliff:g id="preference">"preference_device_pairing_successful_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_tracing_activation_time"><xliff:g id="preference">"preference_initial_tracing_activation_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_result_received_time"><xliff:g id="preference">"preference_initial_result_received_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_is_allowed_to_submit_diagnosis_keys"><xliff:g id="preference">"preference_is_allowed_to_submit_diagnosis_keys"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_database_password"><xliff:g id="preference">"preference_database_password"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_total_non_active_tracing"><xliff:g id="preference">"preference_total_non_active_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_last_non_active_tracing_timestamp"><xliff:g id="preference">"preference_last_non_active_tracing_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_number_successful_submissions"><xliff:g id="preference">"preference_number_successful_submissions"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string>
-
     <!-- ####################################
                      Generics
     ###################################### -->
diff --git a/Corona-Warn-App/src/main/res/values-tr/strings.xml b/Corona-Warn-App/src/main/res/values-tr/strings.xml
index d91a7055c97cad5de09393dd915a22dcb1dca29a..f408e7698649008c23232c2964420735064486cf 100644
--- a/Corona-Warn-App/src/main/res/values-tr/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-tr/strings.xml
@@ -1,47 +1,4 @@
 <?xml version="1.0" encoding="UTF-8"?><resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" tools:ignore="MissingTranslation">
-
-    <!-- ####################################
-               Preference Keys
-    ######################################
-    TODO: Check what is needed -->
-
-    <!-- NOTR -->
-    <string name="preference_name"><xliff:g id="preference">"shared_preferences_cwa"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed"><xliff:g id="preference">"preference_onboarding_completed"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed_timestamp"><xliff:g id="preference">"preference_onboarding_completed_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_background_check_done"><xliff:g id="preference">"preference_background_check_done"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_reset_app"><xliff:g id="preference">"preference_reset_app"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_only_wifi"><xliff:g id="preference">"preference_only_wifi"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_device_pairing_successful_time"><xliff:g id="preference">"preference_device_pairing_successful_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_tracing_activation_time"><xliff:g id="preference">"preference_initial_tracing_activation_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_result_received_time"><xliff:g id="preference">"preference_initial_result_received_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_is_allowed_to_submit_diagnosis_keys"><xliff:g id="preference">"preference_is_allowed_to_submit_diagnosis_keys"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_database_password"><xliff:g id="preference">"preference_database_password"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_total_non_active_tracing"><xliff:g id="preference">"preference_total_non_active_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_last_non_active_tracing_timestamp"><xliff:g id="preference">"preference_last_non_active_tracing_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_number_successful_submissions"><xliff:g id="preference">"preference_number_successful_submissions"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string>
-
     <!-- ####################################
                      Generics
     ###################################### -->
diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml
index 9921b1dfa0ea944ef832477d8981fc90ea2d3df3..38eb2464b2fe251d64f1b1f0568a845cb2392325 100644
--- a/Corona-Warn-App/src/main/res/values/strings.xml
+++ b/Corona-Warn-App/src/main/res/values/strings.xml
@@ -1,54 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <resources xmlns:tools="http://schemas.android.com/tools" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" tools:ignore="MissingTranslation">
-
-    <!-- ####################################
-               Preference Keys
-    ######################################
-    TODO: Check what is needed -->
-
-    <!-- NOTR -->
-    <string name="preference_name"><xliff:g id="preference">"shared_preferences_cwa"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed"><xliff:g id="preference">"preference_onboarding_completed"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_onboarding_completed_timestamp"><xliff:g id="preference">"preference_onboarding_completed_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_background_check_done"><xliff:g id="preference">"preference_background_check_done"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_reset_app"><xliff:g id="preference">"preference_reset_app"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_only_wifi"><xliff:g id="preference">"preference_only_wifi"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_background_job_allowed"><xliff:g id="preference">"preference_background_job_enabled"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_mobile_data_allowed"><xliff:g id="preference">"preference_mobile_data_enabled"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_registration_token"><xliff:g id="preference">"preference_registration_token"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_device_pairing_successful_time"><xliff:g id="preference">"preference_device_pairing_successful_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_tracing_activation_time"><xliff:g id="preference">"preference_initial_tracing_activation_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_initial_result_received_time"><xliff:g id="preference">"preference_initial_result_received_time"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_is_allowed_to_submit_diagnosis_keys"><xliff:g id="preference">"preference_is_allowed_to_submit_diagnosis_keys"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_database_password"><xliff:g id="preference">"preference_database_password"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_total_non_active_tracing"><xliff:g id="preference">"preference_total_non_active_tracing"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_last_non_active_tracing_timestamp"><xliff:g id="preference">"preference_last_non_active_tracing_timestamp"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_number_successful_submissions"><xliff:g id="preference">"preference_number_successful_submissions"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string>
-    <!-- NOTR -->
-    <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string>
-
     <!-- ####################################
                      Generics
     ###################################### -->
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/CensorInjectionTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/CensorInjectionTest.kt
index 10c54df0a834451588d7daddb3610dd29a6cc673..90bcddb7723145acd4131e3d4e6ba14343778a09 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/CensorInjectionTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/CensorInjectionTest.kt
@@ -5,6 +5,7 @@ import dagger.Module
 import dagger.Provides
 import de.rki.coronawarnapp.bugreporting.BugReportingSharedModule
 import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import io.github.classgraph.ClassGraph
 import io.kotest.matchers.collections.shouldContainAll
 import io.kotest.matchers.shouldBe
@@ -63,4 +64,8 @@ class MockProvider {
     @Singleton
     @Provides
     fun diary(): ContactDiaryRepository = mockk()
+
+    @Singleton
+    @Provides
+    fun submissionSettings(): SubmissionSettings = mockk()
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryEncounterCensorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryEncounterCensorTest.kt
index 55c64ca412d57ba704a113d26d5c71dc02798785..a00968c428c93e723309761c38e08af1634ce905 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryEncounterCensorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryEncounterCensorTest.kt
@@ -53,21 +53,23 @@ class DiaryEncounterCensorTest : BaseTest() {
         val censorMe = LogLine(
             timestamp = 1,
             priority = 3,
-            message = """
+            message =
+                """
                 On A rainy day,
                 two persons Spilled coffee on each others laptops,
                 everyone disliked that.
-            """.trimIndent(),
+                """.trimIndent(),
             tag = "I'm a tag",
             throwable = null
         )
 
         instance.checkLog(censorMe) shouldBe censorMe.copy(
-            message = """
+            message =
+                """
                     On Encounter#2/Circumstances,
                     two persons Encounter#3/Circumstances,
                     everyone disliked that.
-            """.trimIndent()
+                """.trimIndent()
         )
     }
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryLocationCensorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryLocationCensorTest.kt
index 47c8eae21cb961cb31de04ce4620dccc8a1ec5a2..0c80fee73ed0eb5e43ee044c80a43214c73047d2 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryLocationCensorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryLocationCensorTest.kt
@@ -56,20 +56,22 @@ class DiaryLocationCensorTest : BaseTest() {
         val censorMe = LogLine(
             timestamp = 1,
             priority = 3,
-            message = """
+            message =
+                """
                 Bürgermeister of Munich (+49 089 3333) and Karl of Aachen [+49 0241 9999] called each other.
                 Both agreed that their emails (bürgermeister@münchen.de|karl@aachen.de) are awesome,
                 and that Bielefeld doesn't exist as it has neither phonenumber (null) nor email (null).
-            """.trimIndent(),
+                """.trimIndent(),
             tag = "I'm a tag",
             throwable = null
         )
         instance.checkLog(censorMe) shouldBe censorMe.copy(
-            message = """
+            message =
+                """
                 Bürgermeister of Location#1/Name (Location#1/PhoneNumber) and Karl of Location#3/Name [Location#3/PhoneNumber] called each other.
                 Both agreed that their emails (Location#1/EMail|Location#3/EMail) are awesome,
                 and that Location#2/Name doesn't exist as it has neither phonenumber (null) nor email (null).
-            """.trimIndent()
+                """.trimIndent()
         )
     }
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryPersonCensorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryPersonCensorTest.kt
index 163faca82d6a3f14e9d68e8387e363b458681b39..e4e5e38c294d6f3b384f6a8e7191f725a29ed441 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryPersonCensorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryPersonCensorTest.kt
@@ -57,20 +57,22 @@ class DiaryPersonCensorTest : BaseTest() {
         val censorMe = LogLine(
             timestamp = 1,
             priority = 3,
-            message = """
+            message =
+                """
                 Ralf requested more coffee from +49 1234 7777,
                 but Matthias thought he had enough has had enough for today.
                 A quick mail to luka@sap.com confirmed this.
-            """.trimIndent(),
+                """.trimIndent(),
             tag = "I'm a tag",
             throwable = null
         )
         instance.checkLog(censorMe) shouldBe censorMe.copy(
-            message = """
+            message =
+                """
                 Person#2/Name requested more coffee from Person#1/PhoneNumber,
                 but Person#3/Name thought he had enough has had enough for today.
                 A quick mail to Person#1/EMail confirmed this.
-            """.trimIndent()
+                """.trimIndent()
         )
     }
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryVisitCensorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryVisitCensorTest.kt
index 6af281b9a25a6c87b5091015d4bae770f652fa82..cb9405722fde29918cb4d4a03fff8413fd518bea 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryVisitCensorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/DiaryVisitCensorTest.kt
@@ -52,20 +52,22 @@ class DiaryVisitCensorTest : BaseTest() {
         val censorMe = LogLine(
             timestamp = 1,
             priority = 3,
-            message = """
+            message =
+                """
                 After having a Döner that was too spicy,
                 I got my beard shaved without mask,
                 only to find out the supermarket was out of toiletpaper.
-            """.trimIndent(),
+                """.trimIndent(),
             tag = "I'm a tag",
             throwable = null
         )
         instance.checkLog(censorMe) shouldBe censorMe.copy(
-            message = """
+            message =
+                """
                 After having a Visit#1/Circumstances,
                 I got my Visit#2/Circumstances,
                 only to find out the supermarket was Visit#3/Circumstances.
-            """.trimIndent()
+                """.trimIndent()
         )
     }
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/RegistrationTokenCensorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/RegistrationTokenCensorTest.kt
index a1266ba8016ff84188722fbe1eee9020392cb410..284f8398badbfc1427c82fbfdaebc1bd6b488bc7 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/RegistrationTokenCensorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/bugreporting/censors/RegistrationTokenCensorTest.kt
@@ -1,22 +1,27 @@
 package de.rki.coronawarnapp.bugreporting.censors
 
 import de.rki.coronawarnapp.bugreporting.debuglog.LogLine
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.CWADebug
 import io.kotest.matchers.shouldBe
 import io.mockk.MockKAnnotations
 import io.mockk.every
+import io.mockk.impl.annotations.MockK
 import io.mockk.mockkObject
 import io.mockk.verify
 import kotlinx.coroutines.test.runBlockingTest
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
+import testhelpers.preferences.mockFlowPreference
 
 class RegistrationTokenCensorTest : BaseTest() {
+    @MockK lateinit var submissionSettings: SubmissionSettings
 
     private val testToken = "63b4d3ff-e0de-4bd4-90c1-17c2bb683a2f"
 
+    private val regtokenPreference = mockFlowPreference<String?>(testToken)
+
     @BeforeEach
     fun setup() {
         MockKAnnotations.init(this)
@@ -24,11 +29,12 @@ class RegistrationTokenCensorTest : BaseTest() {
         mockkObject(CWADebug)
         every { CWADebug.isDeviceForTestersBuild } returns false
 
-        mockkObject(LocalData)
-        every { LocalData.registrationToken() } returns testToken
+        every { submissionSettings.registrationToken } returns regtokenPreference
     }
 
-    private fun createInstance() = RegistrationTokenCensor()
+    private fun createInstance() = RegistrationTokenCensor(
+        submissionSettings = submissionSettings
+    )
 
     @Test
     fun `censoring replaces the logline message`() = runBlockingTest {
@@ -49,12 +55,12 @@ class RegistrationTokenCensorTest : BaseTest() {
             message = "I'm a shy registration token: ########-e0de-4bd4-90c1-17c2bb683a2f"
         )
 
-        verify { LocalData.registrationToken() }
+        verify { regtokenPreference.value }
     }
 
     @Test
     fun `censoring returns null if there is no token`() = runBlockingTest {
-        every { LocalData.registrationToken() } returns null
+        every { submissionSettings.registrationToken } returns mockFlowPreference(null)
         val instance = createInstance()
         val filterMeNot = LogLine(
             timestamp = 1,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/AnalyticsTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/AnalyticsTest.kt
index a1b9812796d018fa5e09f415571e7fc4e87f6741..6cc0f482d8e03e279efd2d5565a51fc560f6477f 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/AnalyticsTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/AnalyticsTest.kt
@@ -16,7 +16,7 @@ import de.rki.coronawarnapp.datadonation.safetynet.SafetyNetException
 import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData
 import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaDataRequestAndroid
 import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpacAndroid
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.OnboardingSettings
 import de.rki.coronawarnapp.util.TimeStamper
 import io.kotest.matchers.shouldBe
 import io.mockk.MockKAnnotations
@@ -27,7 +27,6 @@ import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.just
 import io.mockk.mockk
-import io.mockk.mockkObject
 import io.mockk.slot
 import io.mockk.spyk
 import kotlinx.coroutines.delay
@@ -50,6 +49,7 @@ class AnalyticsTest : BaseTest() {
     @MockK lateinit var exposureRiskMetadataDonor: ExposureRiskMetadataDonor
     @MockK lateinit var lastAnalyticsSubmissionLogger: LastAnalyticsSubmissionLogger
     @MockK lateinit var timeStamper: TimeStamper
+    @MockK lateinit var onboardingSettings: OnboardingSettings
 
     private val baseTime: Instant = Instant.ofEpochMilli(0)
 
@@ -57,8 +57,6 @@ class AnalyticsTest : BaseTest() {
     fun setup() {
         MockKAnnotations.init(this)
 
-        mockkObject(LocalData)
-
         coEvery { appConfigProvider.getAppConfig() } returns configData
         every { configData.analytics } returns analyticsConfig
 
@@ -73,7 +71,7 @@ class AnalyticsTest : BaseTest() {
 
         val twoDaysAgo = baseTime.minus(Days.TWO.toStandardDuration())
         every { settings.lastSubmittedTimestamp } returns mockFlowPreference(twoDaysAgo)
-        every { LocalData.onboardingCompletedTimestamp() } returns twoDaysAgo.millis
+        every { onboardingSettings.onboardingCompletedTimestamp } returns twoDaysAgo
 
         every { analyticsConfig.safetyNetRequirements } returns SafetyNetRequirementsContainer()
 
@@ -88,7 +86,8 @@ class AnalyticsTest : BaseTest() {
             donorModules = modules,
             settings = settings,
             logger = lastAnalyticsSubmissionLogger,
-            timeStamper = timeStamper
+            timeStamper = timeStamper,
+            onboardingSettings = onboardingSettings
         )
     )
 
@@ -196,7 +195,7 @@ class AnalyticsTest : BaseTest() {
 
     @Test
     fun `abort due to time since onboarding`() {
-        every { LocalData.onboardingCompletedTimestamp() } returns baseTime.millis
+        every { onboardingSettings.onboardingCompletedTimestamp } returns baseTime
 
         val analytics = createInstance()
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionRepositoryTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionRepositoryTest.kt
index 136eaae38cf3cd1b3a7f1955e16bc2d6964e11f4..bbb25be9800a339a9614195855606218a98c33a5 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionRepositoryTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionRepositoryTest.kt
@@ -26,7 +26,8 @@ class AnalyticsKeySubmissionRepositoryTest : BaseTest() {
     }
 
     private fun createInstance() = AnalyticsKeySubmissionRepository(
-        storage, riskLevelSettings
+        storage,
+        riskLevelSettings
     )
 
     @Test
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/registeredtest/TestResultDonorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/registeredtest/TestResultDonorTest.kt
index 193b4bf5f13c24bcc41501e8bc059c19d28f484e..f128a602166778abbbcae049ec4a8e24a0fefd15 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/registeredtest/TestResultDonorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/registeredtest/TestResultDonorTest.kt
@@ -7,7 +7,7 @@ import de.rki.coronawarnapp.datadonation.analytics.storage.TestResultDonorSettin
 import de.rki.coronawarnapp.risk.RiskLevelSettings
 import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
 import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.TimeStamper
 import de.rki.coronawarnapp.util.formatter.TestResult
 import io.kotest.matchers.shouldBe
@@ -18,42 +18,43 @@ import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.just
 import io.mockk.mockk
-import io.mockk.mockkObject
 import io.mockk.unmockkAll
 import io.mockk.verify
 import kotlinx.coroutines.test.runBlockingTest
+import org.joda.time.Duration
 import org.joda.time.Instant
 import org.junit.jupiter.api.AfterEach
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
-
 import testhelpers.preferences.mockFlowPreference
-import java.util.concurrent.TimeUnit
 
 class TestResultDonorTest : BaseTest() {
     @MockK lateinit var testResultDonorSettings: TestResultDonorSettings
     @MockK lateinit var riskLevelSettings: RiskLevelSettings
     @MockK lateinit var riskLevelStorage: RiskLevelStorage
     @MockK lateinit var timeStamper: TimeStamper
+    @MockK lateinit var submissionSettings: SubmissionSettings
 
     private lateinit var testResultDonor: TestResultDonor
 
+    private val baseTime = Instant.ofEpochMilli(101010101)
+
     @BeforeEach
     fun setUp() {
         MockKAnnotations.init(this, true)
-        mockkObject(LocalData)
-        every { timeStamper.nowUTC } returns Instant.now()
-        every { riskLevelSettings.lastChangeCheckedRiskLevelTimestamp } returns Instant.now()
+        every { timeStamper.nowUTC } returns baseTime
+        every { riskLevelSettings.lastChangeCheckedRiskLevelTimestamp } returns baseTime
         every { testResultDonorSettings.riskLevelAtTestRegistration } returns
             mockFlowPreference(PpaData.PPARiskLevel.RISK_LEVEL_LOW)
-        every { LocalData.initialTestResultReceivedTimestamp() } returns System.currentTimeMillis()
+        every { submissionSettings.initialTestResultReceivedAt } returns baseTime
 
         testResultDonor = TestResultDonor(
             testResultDonorSettings,
             riskLevelSettings,
             riskLevelStorage,
             timeStamper,
+            submissionSettings
         )
     }
 
@@ -71,7 +72,7 @@ class TestResultDonorTest : BaseTest() {
     @Test
     fun `No donation when timestamp at registration is missing`() = runBlockingTest {
         every { testResultDonorSettings.testScannedAfterConsent } returns mockFlowPreference(true)
-        every { LocalData.initialTestResultReceivedTimestamp() } returns null
+        every { submissionSettings.initialTestResultReceivedAt } returns null
         testResultDonor.beginDonation(TestRequest) shouldBe TestResultDonor.TestResultMetadataNoContribution
     }
 
@@ -105,16 +106,16 @@ class TestResultDonorTest : BaseTest() {
             every { testResultDonorSettings.testScannedAfterConsent } returns mockFlowPreference(true)
             every { testResultDonorSettings.testResultAtRegistration } returns mockFlowPreference(TestResult.PENDING)
 
-            val timeDayBefore = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(1)
-            every { LocalData.initialTestResultReceivedTimestamp() } returns timeDayBefore
-            every { riskLevelSettings.lastChangeCheckedRiskLevelTimestamp } returns Instant.ofEpochMilli(timeDayBefore)
+            val timeDayBefore = baseTime.minus(Duration.standardDays(1))
+            every { submissionSettings.initialTestResultReceivedAt } returns timeDayBefore
+            every { riskLevelSettings.lastChangeCheckedRiskLevelTimestamp } returns timeDayBefore
 
             val donation = testResultDonor.beginDonation(TestRequest)
             donation.shouldBeInstanceOf<TestResultDonor.TestResultMetadataContribution>()
             with(donation.testResultMetadata) {
                 riskLevelAtTestRegistration shouldBe PpaData.PPARiskLevel.RISK_LEVEL_LOW
                 testResult shouldBe PpaData.PPATestResult.TEST_RESULT_PENDING
-                hoursSinceTestRegistration shouldBe 23
+                hoursSinceTestRegistration shouldBe 24
                 hoursSinceHighRiskWarningAtTestRegistration shouldBe -1
                 daysSinceMostRecentDateAtRiskLevelAtTestRegistration shouldBe 0
             }
@@ -126,7 +127,7 @@ class TestResultDonorTest : BaseTest() {
         runBlockingTest {
             every { testResultDonorSettings.testScannedAfterConsent } returns mockFlowPreference(true)
             every { testResultDonorSettings.testResultAtRegistration } returns mockFlowPreference(TestResult.POSITIVE)
-            every { testResultDonorSettings.finalTestResultReceivedAt } returns mockFlowPreference(Instant.now())
+            every { testResultDonorSettings.finalTestResultReceivedAt } returns mockFlowPreference(baseTime)
 
             val donation = testResultDonor.beginDonation(TestRequest)
             donation.shouldBeInstanceOf<TestResultDonor.TestResultMetadataContribution>()
@@ -145,7 +146,7 @@ class TestResultDonorTest : BaseTest() {
         runBlockingTest {
             every { testResultDonorSettings.testScannedAfterConsent } returns mockFlowPreference(true)
             every { testResultDonorSettings.testResultAtRegistration } returns mockFlowPreference(TestResult.NEGATIVE)
-            every { testResultDonorSettings.finalTestResultReceivedAt } returns mockFlowPreference(Instant.now())
+            every { testResultDonorSettings.finalTestResultReceivedAt } returns mockFlowPreference(baseTime)
 
             val donation = testResultDonor.beginDonation(TestRequest)
             donation.shouldBeInstanceOf<TestResultDonor.TestResultMetadataContribution>()
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTaskTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTaskTest.kt
index 6e4b58f4d948b2a8937bf192edfa96af3c03e410..3201a04a7c24b83bb2c573c35c9982a59ac3c585 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTaskTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTaskTest.kt
@@ -8,7 +8,7 @@ import de.rki.coronawarnapp.environment.BuildConfigWrap
 import de.rki.coronawarnapp.environment.EnvironmentSetup
 import de.rki.coronawarnapp.nearby.ENFClient
 import de.rki.coronawarnapp.nearby.modules.detectiontracker.TrackedExposureDetection
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.TimeStamper
 import io.mockk.MockKAnnotations
 import io.mockk.Runs
@@ -46,6 +46,7 @@ class DownloadDiagnosisKeysTaskTest : BaseTest() {
     @MockK lateinit var newKey1: CachedKey
 
     @MockK lateinit var latestTrackedDetection: TrackedExposureDetection
+    @MockK lateinit var submissionSettings: SubmissionSettings
 
     @BeforeEach
     fun setup() {
@@ -53,8 +54,7 @@ class DownloadDiagnosisKeysTaskTest : BaseTest() {
 
         mockkObject(BuildConfigWrap)
         every { BuildConfigWrap.VERSION_CODE } returns 1080005
-        mockkObject(LocalData)
-        every { LocalData.isAllowedToSubmitDiagnosisKeys() } returns false
+        every { submissionSettings.isAllowedToSubmitKeys } returns false
 
         availableKey1.apply {
             every { path } returns File("availableKey1")
@@ -101,7 +101,8 @@ class DownloadDiagnosisKeysTaskTest : BaseTest() {
         appConfigProvider = appConfigProvider,
         keyPackageSyncTool = keyPackageSyncTool,
         timeStamper = timeStamper,
-        settings = downloadSettings
+        settings = downloadSettings,
+        submissionSettings = submissionSettings
     )
 
     @Test
@@ -229,7 +230,7 @@ class DownloadDiagnosisKeysTaskTest : BaseTest() {
 
     @Test
     fun `we do not submit keys if user got positive test results`() = runBlockingTest {
-        every { LocalData.isAllowedToSubmitDiagnosisKeys() } returns true
+        every { submissionSettings.isAllowedToSubmitKeys } returns true
 
         createInstance().run(DownloadDiagnosisKeysTask.Arguments())
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/MainActivityViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/MainActivityViewModelTest.kt
index 1e15c104b00d5c4d273af764f67e0b857bc9e9f0..aa8bab6568f0480baf3d800c487bcc9eacae1beb 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/MainActivityViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/MainActivityViewModelTest.kt
@@ -2,7 +2,8 @@ package de.rki.coronawarnapp.main
 
 import de.rki.coronawarnapp.contactdiary.ui.ContactDiarySettings
 import de.rki.coronawarnapp.environment.EnvironmentSetup
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.playbook.BackgroundNoise
+import de.rki.coronawarnapp.storage.OnboardingSettings
 import de.rki.coronawarnapp.ui.main.MainActivityViewModel
 import de.rki.coronawarnapp.util.CWADebug
 import de.rki.coronawarnapp.util.device.BackgroundModeStatus
@@ -25,15 +26,16 @@ class MainActivityViewModelTest : BaseTest() {
     @MockK lateinit var environmentSetup: EnvironmentSetup
     @MockK lateinit var backgroundModeStatus: BackgroundModeStatus
     @MockK lateinit var diarySettings: ContactDiarySettings
+    @MockK lateinit var backgroundNoise: BackgroundNoise
+    @MockK lateinit var onboardingSettings: OnboardingSettings
 
     @BeforeEach
     fun setup() {
         MockKAnnotations.init(this)
 
-        mockkObject(LocalData)
         mockkObject(CWADebug)
 
-        every { LocalData.isBackgroundCheckDone() } returns true
+        every { onboardingSettings.isOnboarded } returns true
         every { environmentSetup.currentEnvironment } returns EnvironmentSetup.Type.WRU
     }
 
@@ -41,7 +43,9 @@ class MainActivityViewModelTest : BaseTest() {
         dispatcherProvider = TestDispatcherProvider(),
         environmentSetup = environmentSetup,
         backgroundModeStatus = backgroundModeStatus,
-        contactDiarySettings = diarySettings
+        contactDiarySettings = diarySettings,
+        backgroundNoise = backgroundNoise,
+        onboardingSettings = onboardingSettings
     )
 
     @Test
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt
index dbbcda67a7ea6f040e0f790cff68f8b5a95a138e..fe35faf99c0c09ab909c1ce2a86c2edbd7a928b6 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt
@@ -7,8 +7,8 @@ import de.rki.coronawarnapp.environment.BuildConfigWrap
 import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.notification.ShareTestResultNotificationService
 import de.rki.coronawarnapp.statistics.source.StatisticsProvider
-import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.storage.TracingRepository
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.ui.homecards.SubmissionDone
 import de.rki.coronawarnapp.submission.ui.homecards.SubmissionStateProvider
@@ -64,6 +64,7 @@ class HomeFragmentViewModelTest : BaseTest() {
     @MockK lateinit var statisticsProvider: StatisticsProvider
     @MockK lateinit var deadmanNotificationScheduler: DeadmanNotificationScheduler
     @MockK lateinit var appShortcutsHelper: AppShortcutsHelper
+    @MockK lateinit var tracingSettings: TracingSettings
 
     @BeforeEach
     fun setup() {
@@ -95,7 +96,8 @@ class HomeFragmentViewModelTest : BaseTest() {
         appConfigProvider = appConfigProvider,
         statisticsProvider = statisticsProvider,
         deadmanNotificationScheduler = deadmanNotificationScheduler,
-        appShortcutsHelper = appShortcutsHelper
+        appShortcutsHelper = appShortcutsHelper,
+        tracingSettings = tracingSettings
     )
 
     @Test
@@ -176,9 +178,7 @@ class HomeFragmentViewModelTest : BaseTest() {
 
     @Test
     fun `test correct order of displaying delta onboarding, release notes and popups`() {
-
-        mockkObject(LocalData)
-        every { LocalData.isInteroperabilityShownAtLeastOnce } returns false andThen true
+        every { cwaSettings.wasInteroperabilityShownAtLeastOnce } returns false andThen true
 
         mockkObject(BuildConfigWrap)
         every { BuildConfigWrap.VERSION_CODE } returns 1120004
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/TracingPermissionHelperTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/TracingPermissionHelperTest.kt
index de30f6d1da854d5d9ae23031569e496be0f4f31f..68c76f457bfbd3ea795cc687ba1ea51a02e31a62 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/TracingPermissionHelperTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/TracingPermissionHelperTest.kt
@@ -2,7 +2,7 @@ package de.rki.coronawarnapp.nearby
 
 import android.app.Activity
 import com.google.android.gms.common.api.Status
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.TracingSettings
 import io.kotest.matchers.shouldBe
 import io.mockk.Called
 import io.mockk.MockKAnnotations
@@ -13,7 +13,6 @@ import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.just
 import io.mockk.mockk
-import io.mockk.mockkObject
 import io.mockk.slot
 import io.mockk.verify
 import kotlinx.coroutines.CoroutineScope
@@ -25,6 +24,7 @@ import testhelpers.BaseTest
 
 class TracingPermissionHelperTest : BaseTest() {
     @MockK lateinit var enfClient: ENFClient
+    @MockK lateinit var tracingSettings: TracingSettings
 
     @BeforeEach
     fun setup() {
@@ -33,14 +33,14 @@ class TracingPermissionHelperTest : BaseTest() {
         coEvery { enfClient.isTracingEnabled } returns flowOf(false)
         coEvery { enfClient.setTracing(any(), any(), any(), any()) } just Runs
 
-        mockkObject(LocalData)
-        every { LocalData.initialTracingActivationTimestamp() } returns 123L
+        every { tracingSettings.isConsentGiven } returns true
     }
 
     fun createInstance(scope: CoroutineScope, callback: TracingPermissionHelper.Callback) = TracingPermissionHelper(
         callback = callback,
         scope = scope,
-        enfClient = enfClient
+        enfClient = enfClient,
+        tracingSettings = tracingSettings
     )
 
     @Test
@@ -61,7 +61,7 @@ class TracingPermissionHelperTest : BaseTest() {
 
     @Test
     fun `if consent is missing then we continue after it was given`() = runBlockingTest {
-        every { LocalData.initialTracingActivationTimestamp() } returns null
+        every { tracingSettings.isConsentGiven } returns false
 
         val callback = mockk<TracingPermissionHelper.Callback>(relaxUnitFun = true)
         val consentCallbackSlot = slot<(Boolean) -> Unit>()
@@ -85,7 +85,7 @@ class TracingPermissionHelperTest : BaseTest() {
 
     @Test
     fun `if consent was declined then we do nothing`() = runBlockingTest {
-        every { LocalData.initialTracingActivationTimestamp() } returns null
+        every { tracingSettings.isConsentGiven } returns false
 
         val callback = mockk<TracingPermissionHelper.Callback>(relaxUnitFun = true)
         val consentCallbackSlot = slot<(Boolean) -> Unit>()
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatusTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatusTest.kt
index a72581ca824c0513f308f8c3833727cb91d604b3..a9a402b39d5b9c41d76cc54c30b46daea87d7e18 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatusTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatusTest.kt
@@ -1,6 +1,7 @@
 package de.rki.coronawarnapp.nearby.modules.tracing
 
 import com.google.android.gms.nearby.exposurenotification.ExposureNotificationClient
+import de.rki.coronawarnapp.storage.TracingSettings
 import io.kotest.matchers.shouldBe
 import io.mockk.Called
 import io.mockk.MockKAnnotations
@@ -22,6 +23,7 @@ import testhelpers.gms.MockGMSTask
 class DefaultTracingStatusTest : BaseTest() {
 
     @MockK lateinit var client: ExposureNotificationClient
+    @MockK lateinit var tracingSettings: TracingSettings
 
     @BeforeEach
     fun setup() {
@@ -32,7 +34,8 @@ class DefaultTracingStatusTest : BaseTest() {
 
     private fun createInstance(scope: CoroutineScope): DefaultTracingStatus = DefaultTracingStatus(
         client = client,
-        scope = scope
+        scope = scope,
+        tracingSettings = tracingSettings
     )
 
     @Test
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/notification/TestResultAvailableNotificationServiceTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/notification/TestResultAvailableNotificationServiceTest.kt
index 2a50eb7dbe82515e9f01165e50d1a1314fb99dcb..d2fc8112210d32d98c6c86005037f29adff4b63d 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/notification/TestResultAvailableNotificationServiceTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/notification/TestResultAvailableNotificationServiceTest.kt
@@ -6,7 +6,7 @@ import android.content.Context
 import androidx.navigation.NavDeepLinkBuilder
 import de.rki.coronawarnapp.CoronaWarnApplication
 import de.rki.coronawarnapp.R
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.util.device.ForegroundState
 import de.rki.coronawarnapp.util.formatter.TestResult
 import io.kotest.matchers.shouldBe
@@ -35,26 +35,27 @@ class TestResultAvailableNotificationServiceTest : BaseTest() {
     @MockK lateinit var navDeepLinkBuilderProvider: Provider<NavDeepLinkBuilder>
     @MockK lateinit var notificationManager: NotificationManager
     @MockK lateinit var notificationHelper: NotificationHelper
+    @MockK lateinit var cwaSettings: CWASettings
 
     @BeforeEach
     fun setUp() {
         MockKAnnotations.init(this)
 
         mockkObject(CoronaWarnApplication)
-        mockkObject(LocalData)
 
         every { CoronaWarnApplication.getAppContext() } returns context
         every { context.getSystemService(Context.NOTIFICATION_SERVICE) } returns notificationManager
         every { navDeepLinkBuilderProvider.get() } returns navDeepLinkBuilder
         every { navDeepLinkBuilder.createPendingIntent() } returns pendingIntent
-        every { LocalData.isNotificationsTestEnabled } returns true
+        every { cwaSettings.isNotificationsTestEnabled.value } returns true
     }
 
     fun createInstance() = TestResultAvailableNotificationService(
         context = context,
         foregroundState = foregroundState,
         navDeepLinkBuilderProvider = navDeepLinkBuilderProvider,
-        notificationHelper = notificationHelper
+        notificationHelper = notificationHelper,
+        cwaSettings = cwaSettings
     )
 
     @Test
@@ -111,7 +112,7 @@ class TestResultAvailableNotificationServiceTest : BaseTest() {
     @Test
     fun `test notification in background disabled`() = runBlockingTest {
         coEvery { foregroundState.isInForeground } returns flow { emit(false) }
-        every { LocalData.isNotificationsTestEnabled } returns false
+        every { cwaSettings.isNotificationsTestEnabled.value } returns false
 
         createInstance().apply {
             showTestResultAvailableNotification(TestResult.POSITIVE)
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelChangeDetectorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelChangeDetectorTest.kt
index 9ec5698f0d5b0529d2aff62a4fea3b64333d9c6b..13fea4bb9f7b0a2bb24c3848256cfe2431e2ba14 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelChangeDetectorTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelChangeDetectorTest.kt
@@ -10,7 +10,8 @@ import de.rki.coronawarnapp.risk.RiskState.INCREASED_RISK
 import de.rki.coronawarnapp.risk.RiskState.LOW_RISK
 import de.rki.coronawarnapp.risk.result.AggregatedRiskResult
 import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.TracingSettings
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.TimeStamper
 import de.rki.coronawarnapp.util.device.ForegroundState
 import io.kotest.matchers.shouldBe
@@ -22,7 +23,6 @@ import io.mockk.coVerifySequence
 import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.just
-import io.mockk.mockkObject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.test.runBlockingTest
@@ -30,9 +30,9 @@ import org.joda.time.Instant
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
+import testhelpers.preferences.mockFlowPreference
 
 class RiskLevelChangeDetectorTest : BaseTest() {
-
     @MockK lateinit var context: Context
     @MockK lateinit var timeStamper: TimeStamper
     @MockK lateinit var riskLevelStorage: RiskLevelStorage
@@ -41,15 +41,15 @@ class RiskLevelChangeDetectorTest : BaseTest() {
     @MockK lateinit var riskLevelSettings: RiskLevelSettings
     @MockK lateinit var notificationHelper: NotificationHelper
     @MockK lateinit var surveys: Surveys
+    @MockK lateinit var submissionSettings: SubmissionSettings
+    @MockK lateinit var tracingSettings: TracingSettings
 
     @BeforeEach
     fun setup() {
         MockKAnnotations.init(this)
 
-        mockkObject(LocalData)
-
-        every { LocalData.isUserToBeNotifiedOfLoweredRiskLevel = any() } just Runs
-        every { LocalData.submissionWasSuccessful() } returns false
+        every { tracingSettings.isUserToBeNotifiedOfLoweredRiskLevel } returns mockFlowPreference(false)
+        every { submissionSettings.isSubmissionSuccessful } returns false
         every { foregroundState.isInForeground } returns flowOf(true)
         every { notificationManagerCompat.areNotificationsEnabled() } returns true
         every { riskLevelSettings.lastChangeCheckedRiskLevelTimestamp = any() } just Runs
@@ -78,7 +78,9 @@ class RiskLevelChangeDetectorTest : BaseTest() {
         foregroundState = foregroundState,
         riskLevelSettings = riskLevelSettings,
         notificationHelper = notificationHelper,
-        surveys = surveys
+        surveys = surveys,
+        submissionSettings = submissionSettings,
+        tracingSettings = tracingSettings
     )
 
     @Test
@@ -92,7 +94,6 @@ class RiskLevelChangeDetectorTest : BaseTest() {
             advanceUntilIdle()
 
             coVerifySequence {
-                LocalData wasNot Called
                 notificationManagerCompat wasNot Called
                 surveys wasNot Called
             }
@@ -115,7 +116,6 @@ class RiskLevelChangeDetectorTest : BaseTest() {
             advanceUntilIdle()
 
             coVerifySequence {
-                LocalData wasNot Called
                 notificationManagerCompat wasNot Called
                 surveys wasNot Called
             }
@@ -138,9 +138,8 @@ class RiskLevelChangeDetectorTest : BaseTest() {
             advanceUntilIdle()
 
             coVerifySequence {
-                LocalData.submissionWasSuccessful()
+                submissionSettings.isSubmissionSuccessful
                 foregroundState.isInForeground
-                LocalData.isUserToBeNotifiedOfLoweredRiskLevel = any()
                 surveys.resetSurvey(Surveys.Type.HIGH_RISK_ENCOUNTER)
             }
         }
@@ -162,7 +161,7 @@ class RiskLevelChangeDetectorTest : BaseTest() {
             advanceUntilIdle()
 
             coVerifySequence {
-                LocalData.submissionWasSuccessful()
+                submissionSettings.isSubmissionSuccessful
                 foregroundState.isInForeground
                 surveys wasNot Called
             }
@@ -186,7 +185,6 @@ class RiskLevelChangeDetectorTest : BaseTest() {
             advanceUntilIdle()
 
             coVerifySequence {
-                LocalData wasNot Called
                 notificationManagerCompat wasNot Called
                 surveys wasNot Called
             }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt
index 62a8305271e50cc3dd45c4c8014fd28180ec137f..28cf7f0f7f8327649644c8b907bebe7033c87694 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelTaskTest.kt
@@ -13,7 +13,7 @@ import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository
 import de.rki.coronawarnapp.nearby.ENFClient
 import de.rki.coronawarnapp.risk.result.AggregatedRiskResult
 import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.task.Task
 import de.rki.coronawarnapp.task.TaskCancellationException
 import de.rki.coronawarnapp.util.TimeStamper
@@ -39,7 +39,6 @@ import org.junit.jupiter.api.assertThrows
 import testhelpers.BaseTest
 
 class RiskLevelTaskTest : BaseTest() {
-
     @MockK lateinit var riskLevels: RiskLevels
     @MockK lateinit var context: Context
     @MockK lateinit var enfClient: ENFClient
@@ -50,6 +49,7 @@ class RiskLevelTaskTest : BaseTest() {
     @MockK lateinit var appConfigProvider: AppConfigProvider
     @MockK lateinit var riskLevelStorage: RiskLevelStorage
     @MockK lateinit var keyCacheRepository: KeyCacheRepository
+    @MockK lateinit var submissionSettings: SubmissionSettings
     @MockK lateinit var analyticsExposureWindowCollector: AnalyticsExposureWindowCollector
 
     private val arguments: Task.Arguments = object : Task.Arguments {}
@@ -59,9 +59,8 @@ class RiskLevelTaskTest : BaseTest() {
         MockKAnnotations.init(this)
 
         mockkObject(TimeVariables)
-        mockkObject(LocalData)
 
-        every { LocalData.isAllowedToSubmitDiagnosisKeys() } returns false
+        every { submissionSettings.isAllowedToSubmitKeys } returns false
         every { configData.isDeviceTimeCorrect } returns true
         every { backgroundModeStatus.isAutoModeEnabled } returns flowOf(true)
         coEvery { appConfigProvider.getAppConfig() } returns configData
@@ -95,6 +94,7 @@ class RiskLevelTaskTest : BaseTest() {
         appConfigProvider = appConfigProvider,
         riskLevelStorage = riskLevelStorage,
         keyCacheRepository = keyCacheRepository,
+        submissionSettings = submissionSettings,
         analyticsExposureWindowCollector = analyticsExposureWindowCollector
     )
 
@@ -215,7 +215,7 @@ class RiskLevelTaskTest : BaseTest() {
         coEvery { keyCacheRepository.getAllCachedKeys() } returns listOf(cachedKey)
         every { backgroundModeStatus.isAutoModeEnabled } returns flowOf(false)
         every { timeStamper.nowUTC } returns now
-        every { LocalData.isAllowedToSubmitDiagnosisKeys() } returns true
+        every { submissionSettings.isAllowedToSubmitKeys } returns true
 
         createTask().run(arguments) shouldBe RiskLevelTaskResult(
             calculatedAt = now,
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/SubmissionRepositoryTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/SubmissionRepositoryTest.kt
index 31d2aaa7c6d0775833f853d5d30f53f923de3dfe..31f62170a700594e6b68beb6e7f3039da3154d4f 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/SubmissionRepositoryTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/SubmissionRepositoryTest.kt
@@ -27,6 +27,7 @@ import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.just
 import io.mockk.mockkObject
+import io.mockk.slot
 import io.mockk.verify
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.emptyFlow
@@ -53,6 +54,7 @@ class SubmissionRepositoryTest : BaseTest() {
     @MockK lateinit var encryptionErrorResetTool: EncryptionErrorResetTool
     @MockK lateinit var deadmanNotificationScheduler: DeadmanNotificationScheduler
     @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
+    @MockK lateinit var tracingSettings: TracingSettings
 
     private val guid = "123456-12345678-1234-4DA7-B166-B86D85475064"
     private val tan = "123456-12345678-1234-4DA7-B166-B86D85475064"
@@ -60,6 +62,9 @@ class SubmissionRepositoryTest : BaseTest() {
     private val testResult = TestResult.PENDING
     private val registrationData = SubmissionService.RegistrationData(registrationToken, testResult)
 
+    private val registrationTokenPreference = mockFlowPreference<String?>(null)
+    private val resultReceivedTimeStamp = Instant.ofEpochMilli(101010101)
+
     @BeforeEach
     fun setUp() {
         MockKAnnotations.init(this)
@@ -69,14 +74,12 @@ class SubmissionRepositoryTest : BaseTest() {
         every { appComponent.encryptedPreferencesFactory } returns encryptedPreferencesFactory
         every { appComponent.errorResetTool } returns encryptionErrorResetTool
 
-        mockkObject(BackgroundNoise.Companion)
-        every { BackgroundNoise.getInstance() } returns backgroundNoise
         every { backgroundNoise.scheduleDummyPattern() } just Runs
 
-        mockkObject(LocalData)
-        every { LocalData.registrationToken(any()) } just Runs
-        every { LocalData.devicePairingSuccessfulTimestamp(any()) } just Runs
-        every { LocalData.initialTestResultReceivedTimestamp() } returns 1L
+        every { submissionSettings.registrationToken } returns registrationTokenPreference
+
+        every { submissionSettings.devicePairingSuccessfulAt = any() } just Runs
+        every { submissionSettings.initialTestResultReceivedAt } returns resultReceivedTimeStamp
 
         every { submissionSettings.hasGivenConsent } returns mockFlowPreference(false)
         every { submissionSettings.hasViewedTestResult } returns mockFlowPreference(false)
@@ -97,31 +100,41 @@ class SubmissionRepositoryTest : BaseTest() {
         timeStamper = timeStamper,
         tekHistoryStorage = tekHistoryStorage,
         deadmanNotificationScheduler = deadmanNotificationScheduler,
-        analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
+        backgroundNoise = backgroundNoise,
+        analyticsKeySubmissionCollector = analyticsKeySubmissionCollector,
+        tracingSettings = tracingSettings
     )
 
     @Test
     fun removeTestFromDeviceSucceeds() = runBlockingTest {
         val submissionRepository = createInstance(scope = this)
 
-        every { LocalData.initialPollingForTestResultTimeStamp(any()) } just Runs
-        every { LocalData.initialTestResultReceivedTimestamp(any()) } just Runs
-        every { LocalData.isAllowedToSubmitDiagnosisKeys(any()) } just Runs
-        every { LocalData.isTestResultAvailableNotificationSent(any()) } just Runs
-        every { LocalData.numberOfSuccessfulSubmissions(any()) } just Runs
+        val initialPollingForTestResultTimeStampSlot = slot<Long>()
+        val isTestResultAvailableNotificationSent = slot<Boolean>()
+        every {
+            tracingSettings.initialPollingForTestResultTimeStamp = capture(initialPollingForTestResultTimeStampSlot)
+        } answers {}
+        every {
+            tracingSettings.isTestResultAvailableNotificationSent = capture(isTestResultAvailableNotificationSent)
+        } answers {}
+
+        every { submissionSettings.initialTestResultReceivedAt = any() } just Runs
+        every { submissionSettings.isAllowedToSubmitKeys = any() } just Runs
+        every { submissionSettings.isSubmissionSuccessful = any() } just Runs
         every { analyticsKeySubmissionCollector.reset() } just Runs
 
         submissionRepository.removeTestFromDevice()
 
         verify(exactly = 1) {
-            LocalData.registrationToken(null)
-            LocalData.devicePairingSuccessfulTimestamp(0L)
-            LocalData.initialPollingForTestResultTimeStamp(0L)
-            LocalData.initialTestResultReceivedTimestamp(0L)
-            LocalData.isAllowedToSubmitDiagnosisKeys(false)
-            LocalData.isTestResultAvailableNotificationSent(false)
-            LocalData.numberOfSuccessfulSubmissions(0)
+            registrationTokenPreference.update(any())
+            submissionSettings.devicePairingSuccessfulAt = null
+            submissionSettings.initialTestResultReceivedAt = null
+            submissionSettings.isAllowedToSubmitKeys = false
+            submissionSettings.isSubmissionSuccessful = false
         }
+
+        initialPollingForTestResultTimeStampSlot.captured shouldBe 0L
+        isTestResultAvailableNotificationSent.captured shouldBe false
     }
 
     @Test
@@ -133,11 +146,13 @@ class SubmissionRepositoryTest : BaseTest() {
 
         submissionRepository.asyncRegisterDeviceViaGUID(guid)
 
-        verify {
-            LocalData.devicePairingSuccessfulTimestamp(any())
-            LocalData.registrationToken(registrationToken)
+        registrationTokenPreference.value shouldBe registrationToken
+        submissionRepository.testResultReceivedDateFlow.first() shouldBe resultReceivedTimeStamp.toDate()
+
+        verify(exactly = 1) {
+            registrationTokenPreference.update(any())
+            submissionSettings.devicePairingSuccessfulAt = any()
             backgroundNoise.scheduleDummyPattern()
-            submissionRepository.updateTestResult(testResult)
         }
     }
 
@@ -151,11 +166,13 @@ class SubmissionRepositoryTest : BaseTest() {
 
         submissionRepository.asyncRegisterDeviceViaTAN(tan)
 
-        coVerify {
-            LocalData.devicePairingSuccessfulTimestamp(any())
-            LocalData.registrationToken(registrationToken)
+        registrationTokenPreference.value shouldBe registrationToken
+        submissionRepository.testResultReceivedDateFlow.first() shouldBe resultReceivedTimeStamp.toDate()
+
+        verify(exactly = 1) {
+            registrationTokenPreference.update(any())
+            submissionSettings.devicePairingSuccessfulAt = any()
             backgroundNoise.scheduleDummyPattern()
-            submissionRepository.updateTestResult(testResult)
         }
     }
 
@@ -174,8 +191,10 @@ class SubmissionRepositoryTest : BaseTest() {
 
     @Test
     fun `ui state is SUBMITTED_FINAL when submission was done`() = runBlockingTest {
-        coEvery { LocalData.submissionWasSuccessful() } returns true
+        every { submissionSettings.isSubmissionSuccessful } returns true
+
         val submissionRepository = createInstance(scope = this)
+
         submissionRepository.refreshDeviceUIState()
         submissionRepository.deviceUIStateFlow.first() shouldBe
             NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL)
@@ -183,9 +202,11 @@ class SubmissionRepositoryTest : BaseTest() {
 
     @Test
     fun `ui state is UNPAIRED when no token is present`() = runBlockingTest {
-        coEvery { LocalData.submissionWasSuccessful() } returns false
-        coEvery { LocalData.registrationToken() } returns null
+        every { submissionSettings.isSubmissionSuccessful } returns false
+        every { submissionSettings.registrationToken } returns mockFlowPreference(null)
+
         val submissionRepository = createInstance(scope = this)
+
         submissionRepository.refreshDeviceUIState()
         submissionRepository.deviceUIStateFlow.first() shouldBe
             NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED)
@@ -193,10 +214,12 @@ class SubmissionRepositoryTest : BaseTest() {
 
     @Test
     fun `ui state is PAIRED_POSITIVE when allowed to submit`() = runBlockingTest {
-        coEvery { LocalData.submissionWasSuccessful() } returns false
-        coEvery { LocalData.registrationToken() } returns "token"
-        coEvery { LocalData.isAllowedToSubmitDiagnosisKeys() } returns true
+        every { submissionSettings.isSubmissionSuccessful } returns false
+        every { submissionSettings.registrationToken } returns mockFlowPreference("token")
+        coEvery { submissionSettings.isAllowedToSubmitKeys } returns true
+
         val submissionRepository = createInstance(scope = this)
+
         submissionRepository.refreshDeviceUIState()
         submissionRepository.deviceUIStateFlow.first() shouldBe
             NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_POSITIVE)
@@ -204,40 +227,53 @@ class SubmissionRepositoryTest : BaseTest() {
 
     @Test
     fun `refresh when state is PAIRED_NO_RESULT`() = runBlockingTest {
-        coEvery { LocalData.submissionWasSuccessful() } returns false
-        coEvery { LocalData.registrationToken() } returns "token"
-        coEvery { LocalData.isAllowedToSubmitDiagnosisKeys() } returns false
+        every { submissionSettings.isSubmissionSuccessful } returns false
+        every { submissionSettings.registrationToken } returns mockFlowPreference("token")
+        coEvery { submissionSettings.isAllowedToSubmitKeys } returns false
         coEvery { submissionService.asyncRequestTestResult(any()) } returns TestResult.PENDING
+
         val submissionRepository = createInstance(scope = this)
+
         submissionRepository.refreshDeviceUIState()
         submissionRepository.deviceUIStateFlow.first() shouldBe
             NetworkRequestWrapper.RequestSuccessful(DeviceUIState.PAIRED_NO_RESULT)
+
         coVerify(exactly = 1) { submissionService.asyncRequestTestResult(any()) }
     }
 
     @Test
     fun `refresh when state is UNPAIRED`() = runBlockingTest {
-        coEvery { LocalData.submissionWasSuccessful() } returns false
-        coEvery { LocalData.registrationToken() } returns null
-        coEvery { LocalData.isAllowedToSubmitDiagnosisKeys() } returns false
+        every { submissionSettings.isSubmissionSuccessful } returns false
+        every { submissionSettings.registrationToken } returns mockFlowPreference(null)
+        coEvery { submissionSettings.isAllowedToSubmitKeys } returns false
         coEvery { submissionService.asyncRequestTestResult(any()) } returns TestResult.PENDING
+
         val submissionRepository = createInstance(scope = this)
+
         submissionRepository.refreshDeviceUIState()
         submissionRepository.deviceUIStateFlow.first() shouldBe
             NetworkRequestWrapper.RequestSuccessful(DeviceUIState.UNPAIRED)
-        coEvery { LocalData.registrationToken() } returns "token"
+
+        every { submissionSettings.registrationToken } returns mockFlowPreference("token")
+
         submissionRepository.refreshDeviceUIState()
+
         coVerify(exactly = 1) { submissionService.asyncRequestTestResult(any()) }
     }
 
     @Test
     fun `no refresh when state is SUBMITTED_FINAL`() = runBlockingTest {
-        coEvery { LocalData.submissionWasSuccessful() } returns true
+        every { submissionSettings.isSubmissionSuccessful } returns true
+
         val submissionRepository = createInstance(scope = this)
+
         submissionRepository.refreshDeviceUIState()
+
         submissionRepository.deviceUIStateFlow.first() shouldBe
             NetworkRequestWrapper.RequestSuccessful(DeviceUIState.SUBMITTED_FINAL)
+
         submissionRepository.refreshDeviceUIState()
+
         coVerify(exactly = 0) { submissionService.asyncRequestTestResult(any()) }
     }
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/task/SubmissionTaskTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/task/SubmissionTaskTest.kt
index f5e67e1b5f43d10e8739f91da62534ef7b022aaa..f49adc5f87d8e25d5dacaf1dae27cd0ef3396290 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/task/SubmissionTaskTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/task/SubmissionTaskTest.kt
@@ -9,7 +9,6 @@ import de.rki.coronawarnapp.notification.ShareTestResultNotificationService
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
 import de.rki.coronawarnapp.playbook.Playbook
 import de.rki.coronawarnapp.server.protocols.external.exposurenotification.TemporaryExposureKeyExportOuterClass
-import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.submission.Symptoms
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -63,6 +62,7 @@ class SubmissionTaskTest : BaseTest() {
 
     private lateinit var settingSymptomsPreference: FlowPreference<Symptoms?>
 
+    private val registrationToken: FlowPreference<String?> = mockFlowPreference("regtoken")
     private val settingHasGivenConsent: FlowPreference<Boolean> = mockFlowPreference(true)
     private val settingAutoSubmissionAttemptsCount: FlowPreference<Int> = mockFlowPreference(0)
     private val settingAutoSubmissionAttemptsLast: FlowPreference<Instant> = mockFlowPreference(Instant.EPOCH)
@@ -73,9 +73,8 @@ class SubmissionTaskTest : BaseTest() {
     fun setup() {
         MockKAnnotations.init(this)
 
-        mockkObject(LocalData)
-        every { LocalData.registrationToken() } returns "regtoken"
-        every { LocalData.numberOfSuccessfulSubmissions(any()) } just Runs
+        every { submissionSettings.registrationToken } returns registrationToken
+        every { submissionSettings.isSubmissionSuccessful = any() } just Runs
 
         mockkObject(BackgroundWorkScheduler)
         every { BackgroundWorkScheduler.stopWorkScheduler() } just Runs
@@ -133,11 +132,20 @@ class SubmissionTaskTest : BaseTest() {
         )
 
         coVerifySequence {
+            submissionSettings.lastSubmissionUserActivityUTC
             settingLastUserActivityUTC.value
+            submissionSettings.hasGivenConsent
             settingHasGivenConsent.value
 
-            LocalData.registrationToken()
+            submissionSettings.autoSubmissionAttemptsCount
+            submissionSettings.autoSubmissionAttemptsLast
+            submissionSettings.autoSubmissionAttemptsCount
+            submissionSettings.autoSubmissionAttemptsLast
+            submissionSettings.registrationToken
+
+            registrationToken.value
             tekHistoryStorage.tekData
+            submissionSettings.symptoms
             settingSymptomsPreference.value
 
             tekHistoryCalculations.transformToKeyHistoryInExternalFormat(listOf(tek), userSymptoms)
@@ -156,12 +164,13 @@ class SubmissionTaskTest : BaseTest() {
             analyticsKeySubmissionCollector.reportSubmittedInBackground()
 
             tekHistoryStorage.clear()
+            submissionSettings.symptoms
             settingSymptomsPreference.update(match { it.invoke(mockk()) == null })
 
             autoSubmission.updateMode(AutoSubmission.Mode.DISABLED)
 
             BackgroundWorkScheduler.stopWorkScheduler()
-            LocalData.numberOfSuccessfulSubmissions(1)
+            submissionSettings.isSubmissionSuccessful = true
             BackgroundWorkScheduler.startWorkScheduler()
 
             shareTestResultNotificationService.cancelSharePositiveTestResultNotification()
@@ -195,7 +204,7 @@ class SubmissionTaskTest : BaseTest() {
         coVerifySequence {
             settingHasGivenConsent.value
 
-            LocalData.registrationToken()
+            registrationToken.value
             tekHistoryStorage.tekData
             settingSymptomsPreference.value
 
@@ -222,7 +231,7 @@ class SubmissionTaskTest : BaseTest() {
 
     @Test
     fun `task throws if no registration token is available`() = runBlockingTest {
-        every { LocalData.registrationToken() } returns null
+        every { submissionSettings.registrationToken } returns mockFlowPreference(null)
 
         val task = createTask()
         shouldThrow<NoRegistrationTokenSetException> {
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProviderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProviderTest.kt
index 4cc268ca6d272c0d96c80f8847883504572b549a..7ca361ae4bfbf43bfd339e3262fadbd93f3c097c 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProviderTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProviderTest.kt
@@ -18,7 +18,6 @@ import de.rki.coronawarnapp.tracing.ui.details.items.riskdetails.DetailsFailedCa
 import de.rki.coronawarnapp.tracing.ui.details.items.riskdetails.DetailsIncreasedRiskBox
 import de.rki.coronawarnapp.tracing.ui.details.items.riskdetails.DetailsLowRiskBox
 import de.rki.coronawarnapp.tracing.ui.details.items.survey.UserSurveyBox
-import de.rki.coronawarnapp.util.TimeAndDateExtensions.daysToMilliseconds
 import io.kotest.matchers.ints.shouldBeGreaterThan
 import io.kotest.matchers.shouldBe
 import io.mockk.MockKAnnotations
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/homecards/SubmissionStateProviderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/homecards/SubmissionStateProviderTest.kt
index 15decd484cd425591face7df7a9faf9995bed521..dee497b2ccdd3f88fa5a838b3480616fd2940ce5 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/homecards/SubmissionStateProviderTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/homecards/SubmissionStateProviderTest.kt
@@ -1,8 +1,8 @@
 package de.rki.coronawarnapp.tracing.ui.homecards
 
 import android.content.Context
-import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.submission.SubmissionRepository
+import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.submission.ui.homecards.NoTest
 import de.rki.coronawarnapp.submission.ui.homecards.SubmissionStateProvider
 import de.rki.coronawarnapp.util.DeviceUIState
@@ -11,7 +11,6 @@ import io.kotest.matchers.shouldBe
 import io.mockk.MockKAnnotations
 import io.mockk.every
 import io.mockk.impl.annotations.MockK
-import io.mockk.mockkObject
 import io.mockk.verifySequence
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.flow
@@ -22,6 +21,7 @@ import org.junit.jupiter.api.extension.ExtendWith
 import testhelpers.BaseTest
 import testhelpers.extensions.CoroutinesTestExtension
 import testhelpers.extensions.InstantExecutorExtension
+import testhelpers.preferences.mockFlowPreference
 import java.util.Date
 
 @ExtendWith(InstantExecutorExtension::class, CoroutinesTestExtension::class)
@@ -29,21 +29,24 @@ class SubmissionStateProviderTest : BaseTest() {
 
     @MockK lateinit var context: Context
     @MockK lateinit var submissionRepository: SubmissionRepository
+    @MockK lateinit var submissionSettings: SubmissionSettings
 
     @BeforeEach
     fun setup() {
         MockKAnnotations.init(this)
-        mockkObject(LocalData)
 
         every { submissionRepository.hasViewedTestResult } returns flow { emit(true) }
         every { submissionRepository.deviceUIStateFlow } returns flow {
             emit(NetworkRequestWrapper.RequestSuccessful<DeviceUIState, Throwable>(DeviceUIState.PAIRED_POSITIVE))
         }
         every { submissionRepository.testResultReceivedDateFlow } returns flow { emit(Date()) }
-        every { LocalData.registrationToken() } returns null
+        every { submissionSettings.registrationToken } returns mockFlowPreference(null)
     }
 
-    private fun createInstance() = SubmissionStateProvider(submissionRepository)
+    private fun createInstance() = SubmissionStateProvider(
+        submissionRepository = submissionRepository,
+        submissionSettings = submissionSettings
+    )
 
     @Test
     fun `state determination, unregistered test`() = runBlockingTest {
@@ -54,7 +57,7 @@ class SubmissionStateProviderTest : BaseTest() {
                 submissionRepository.deviceUIStateFlow
                 submissionRepository.hasViewedTestResult
                 submissionRepository.testResultReceivedDateFlow
-                LocalData.registrationToken()
+                submissionSettings.registrationToken
             }
         }
     }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/launcher/LauncherActivityViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/launcher/LauncherActivityViewModelTest.kt
index 14df18a27d310a3266724880134bfb279cee3f18..07a76044a01c0f3840389387debbd865b0bc9202 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/launcher/LauncherActivityViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/launcher/LauncherActivityViewModelTest.kt
@@ -2,7 +2,7 @@ package de.rki.coronawarnapp.ui.launcher
 
 import de.rki.coronawarnapp.environment.BuildConfigWrap
 import de.rki.coronawarnapp.main.CWASettings
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.OnboardingSettings
 import de.rki.coronawarnapp.update.UpdateChecker
 import io.kotest.matchers.shouldBe
 import io.kotest.matchers.types.instanceOf
@@ -26,13 +26,13 @@ class LauncherActivityViewModelTest : BaseTest() {
 
     @MockK lateinit var updateChecker: UpdateChecker
     @MockK lateinit var cwaSettings: CWASettings
+    @MockK lateinit var onboardingSettings: OnboardingSettings
 
     @BeforeEach
     fun setupFreshViewModel() {
         MockKAnnotations.init(this)
 
-        mockkObject(LocalData)
-        every { LocalData.isOnboarded() } returns false
+        every { onboardingSettings.isOnboarded } returns false
 
         mockkObject(BuildConfigWrap)
         every { BuildConfigWrap.VERSION_CODE } returns 10L
@@ -43,7 +43,8 @@ class LauncherActivityViewModelTest : BaseTest() {
     private fun createViewModel() = LauncherActivityViewModel(
         updateChecker = updateChecker,
         dispatcherProvider = TestDispatcherProvider(),
-        cwaSettings = cwaSettings
+        cwaSettings = cwaSettings,
+        onboardingSettings = onboardingSettings
     )
 
     @Test
@@ -67,8 +68,8 @@ class LauncherActivityViewModelTest : BaseTest() {
 
     @Test
     fun `onboarding finished`() {
-        every { LocalData.isOnboarded() } returns true
-        every { LocalData.isInteroperabilityShownAtLeastOnce } returns true
+        every { onboardingSettings.isOnboarded } returns true
+        every { cwaSettings.wasInteroperabilityShownAtLeastOnce } returns true
         every { cwaSettings.lastChangelogVersion } returns mockFlowPreference(10L)
 
         val vm = createViewModel()
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/settings/notification/NotificationsSettingsTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/settings/notification/NotificationsSettingsTest.kt
index 3bd5a7811a0ab9771756341527dd20c07f0f8b6f..7f0c43618e781d12ee792f90b6c2d6d6c5390b47 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/settings/notification/NotificationsSettingsTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/settings/notification/NotificationsSettingsTest.kt
@@ -1,18 +1,14 @@
 package de.rki.coronawarnapp.ui.settings.notification
 
 import androidx.core.app.NotificationManagerCompat
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.ui.settings.notifications.NotificationSettings
 import de.rki.coronawarnapp.util.device.ForegroundState
 import io.kotest.matchers.shouldBe
 import io.mockk.MockKAnnotations
-import io.mockk.Runs
 import io.mockk.coEvery
 import io.mockk.every
 import io.mockk.impl.annotations.MockK
-import io.mockk.just
-import io.mockk.mockkObject
-import io.mockk.verify
 import io.mockk.verifySequence
 import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.flow
@@ -20,32 +16,28 @@ import kotlinx.coroutines.test.runBlockingTest
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import testhelpers.BaseTest
+import testhelpers.preferences.mockFlowPreference
 
 class NotificationsSettingsTest : BaseTest() {
 
     @MockK lateinit var foregroundState: ForegroundState
     @MockK lateinit var notificationManagerCompat: NotificationManagerCompat
+    @MockK lateinit var cwaSettings: CWASettings
 
     @BeforeEach
     fun setup() {
         MockKAnnotations.init(this)
-        mockkObject(LocalData)
-
-        every { LocalData.isNotificationsRiskEnabledFlow } returns flow { emit(true) }
-        every { LocalData.isNotificationsRiskEnabled = any() } just Runs
-        every { LocalData.isNotificationsRiskEnabled } returns true
-
-        every { LocalData.isNotificationsTestEnabledFlow } returns flow { emit(true) }
-        every { LocalData.isNotificationsTestEnabled = any() } just Runs
-        every { LocalData.isNotificationsTestEnabled } returns true
 
+        every { cwaSettings.isNotificationsRiskEnabled } returns mockFlowPreference(true)
+        every { cwaSettings.isNotificationsTestEnabled } returns mockFlowPreference(true)
         every { notificationManagerCompat.areNotificationsEnabled() } returns true
         coEvery { foregroundState.isInForeground } returns flow { emit(true) }
     }
 
     private fun createInstance() = NotificationSettings(
         foregroundState = foregroundState,
-        notificationManagerCompat = notificationManagerCompat
+        notificationManagerCompat = notificationManagerCompat,
+        cwaSettings = cwaSettings
     )
 
     @Test
@@ -72,16 +64,4 @@ class NotificationsSettingsTest : BaseTest() {
             isNotificationsTestEnabled.first() shouldBe true
         }
     }
-
-    @Test
-    fun toggleNotificationsRiskEnabled() {
-        createInstance().toggleNotificationsRiskEnabled()
-        verify { LocalData.isNotificationsRiskEnabled = false }
-    }
-
-    @Test
-    fun toggleNotificationsTestEnabled() {
-        createInstance().toggleNotificationsTestEnabled()
-        verify { LocalData.isNotificationsTestEnabled = false }
-    }
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModelTest.kt
index b3d1b9bae194730731f92604c6d2a97b3d22bfc7..87265f9ce82758aecc07abf52db12f7563382062 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/scan/SubmissionQRCodeScanViewModelTest.kt
@@ -2,7 +2,6 @@ package de.rki.coronawarnapp.ui.submission.qrcode.scan
 
 import de.rki.coronawarnapp.bugreporting.censors.QRCodeCensor
 import de.rki.coronawarnapp.datadonation.analytics.modules.registeredtest.TestResultDataCollector
-import de.rki.coronawarnapp.playbook.BackgroundNoise
 import de.rki.coronawarnapp.service.submission.QRScanResult
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.ui.submission.ScanStatus
@@ -14,7 +13,6 @@ import io.mockk.coVerify
 import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.mockk
-import io.mockk.mockkObject
 import org.junit.Assert
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
@@ -25,16 +23,12 @@ import testhelpers.extensions.InstantExecutorExtension
 @ExtendWith(InstantExecutorExtension::class)
 class SubmissionQRCodeScanViewModelTest : BaseTest() {
 
-    @MockK lateinit var backgroundNoise: BackgroundNoise
     @MockK lateinit var submissionRepository: SubmissionRepository
     @MockK lateinit var testResultDataCollector: TestResultDataCollector
 
     @BeforeEach
     fun setUp() {
         MockKAnnotations.init(this)
-
-        mockkObject(BackgroundNoise.Companion)
-        every { BackgroundNoise.getInstance() } returns backgroundNoise
     }
 
     private fun createViewModel() = SubmissionQRCodeScanViewModel(
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/security/EncryptionResetToolTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/security/EncryptionResetToolTest.kt
deleted file mode 100644
index 574b1a009ce5b50486fd72da511a89e6488463fc..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/security/EncryptionResetToolTest.kt
+++ /dev/null
@@ -1,339 +0,0 @@
-package de.rki.coronawarnapp.util.security
-
-import android.content.Context
-import androidx.core.content.edit
-import de.rki.coronawarnapp.exception.CwaSecurityException
-import de.rki.coronawarnapp.util.TimeStamper
-import io.kotest.matchers.shouldBe
-import io.mockk.MockKAnnotations
-import io.mockk.every
-import io.mockk.impl.annotations.MockK
-import org.joda.time.Instant
-import org.junit.jupiter.api.AfterEach
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.Test
-import testhelpers.BaseIOTest
-import testhelpers.preferences.MockSharedPreferences
-import java.io.File
-import java.io.IOException
-import java.security.GeneralSecurityException
-import java.security.KeyException
-import java.security.KeyStoreException
-
-class EncryptionResetToolTest : BaseIOTest() {
-
-    @MockK lateinit var context: Context
-    @MockK lateinit var timeStamper: TimeStamper
-    private lateinit var mockPreferences: MockSharedPreferences
-
-    private val testDir = File(IO_TEST_BASEDIR, this::class.simpleName!!)
-    private val privateFilesDir = File(testDir, "files")
-    private val encryptedPrefsFile = File(testDir, "shared_prefs/shared_preferences_cwa.xml")
-
-    @BeforeEach
-    fun setup() {
-        MockKAnnotations.init(this)
-
-        every { context.filesDir } returns privateFilesDir
-
-        mockPreferences = MockSharedPreferences()
-        every {
-            context.getSharedPreferences(
-                "encryption_error_reset_tool",
-                Context.MODE_PRIVATE
-            )
-        } returns mockPreferences
-
-        every { timeStamper.nowUTC } returns Instant.ofEpochMilli(1234567890L)
-    }
-
-    @AfterEach
-    fun teardown() {
-        testDir.deleteRecursively()
-    }
-
-    private fun createInstance() = EncryptionErrorResetTool(
-        context = context,
-        timeStamper = timeStamper
-    )
-
-    private fun createMockFiles() {
-        encryptedPrefsFile.apply {
-            parentFile!!.mkdirs()
-            createNewFile()
-            exists() shouldBe true
-        }
-    }
-
-    @Test
-    fun `initialiation is sideeffect free`() {
-        createMockFiles()
-
-        createInstance()
-
-        encryptedPrefsFile.exists() shouldBe true
-        mockPreferences.dataMapPeek shouldBe emptyMap()
-    }
-
-    @Test
-    fun `reset dialog show flag is writable and persisted`() {
-        val instance = createInstance()
-        mockPreferences.dataMapPeek["ea1851.reset.shownotice"] shouldBe null
-        instance.isResetNoticeToBeShown shouldBe false
-
-        instance.isResetNoticeToBeShown = true
-        mockPreferences.dataMapPeek["ea1851.reset.shownotice"] shouldBe true
-        instance.isResetNoticeToBeShown shouldBe true
-
-        createInstance().isResetNoticeToBeShown shouldBe true
-
-        instance.isResetNoticeToBeShown = false
-        mockPreferences.dataMapPeek["ea1851.reset.shownotice"] shouldBe false
-        instance.isResetNoticeToBeShown shouldBe false
-    }
-
-    @Test
-    fun `reset is not warranted by default`() {
-        createMockFiles()
-
-        createInstance().tryResetIfNecessary(Exception())
-
-        encryptedPrefsFile.exists() shouldBe true
-    }
-
-    /**
-     Based on https://github.com/corona-warn-app/cwa-app-android/issues/642#issuecomment-650199424
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: java.lang.SecurityException: Could not decrypt value. decryption failed
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at androidx.security.crypto.EncryptedSharedPreferences.getDecryptedObject(EncryptedSharedPreferences.java:33)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at androidx.security.crypto.EncryptedSharedPreferences.getBoolean(EncryptedSharedPreferences.java:1)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at de.rki.coronawarnapp.update.UpdateChecker.checkForUpdate(UpdateChecker.kt:23)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at de.rki.coronawarnapp.update.UpdateChecker$checkForUpdate$1.invokeSuspend(Unknown Source:11)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:2)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:18)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at android.os.Handler.handleCallback(Handler.java:809)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at android.os.Handler.dispatchMessage(Handler.java:102)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at android.os.Looper.loop(Looper.java:166)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at android.app.ActivityThread.main(ActivityThread.java:7377)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at java.lang.reflect.Method.invoke(Native Method)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:469)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: Caused by: java.security.GeneralSecurityException: decryption failed
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at com.google.crypto.tink.aead.AeadWrapper$WrappedAead.decrypt(AeadWrapper.java:15)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	at androidx.security.crypto.EncryptedSharedPreferences.getDecryptedObject(EncryptedSharedPreferences.java:5)
-     06-23 21:52:51.681 10311 17331 17331 E AndroidRuntime: 	... 12 more
-     */
-    @Test
-    fun `reset is warranted if the first exception after upgrade was a GeneralSecurityException`() {
-        // We only perform the reset for users who encounter it the first time after the upgrade
-        createMockFiles()
-
-        createInstance().tryResetIfNecessary(
-            GeneralSecurityException("decryption failed")
-        ) shouldBe true
-
-        createInstance().tryResetIfNecessary(
-            GeneralSecurityException("decryption failed")
-        ) shouldBe false
-
-        encryptedPrefsFile.exists() shouldBe false
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe 1234567890L
-            this["ea1851.reset.windowconsumed.160"] shouldBe true
-            this["ea1851.reset.shownotice"] shouldBe true
-        }
-    }
-
-    @Test
-    fun `the previous reset attempt from 1_5_0 is ignored`() {
-        mockPreferences.edit { putBoolean("ea1851.reset.windowconsumed", true) }
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe null
-            this["ea1851.reset.windowconsumed"] shouldBe true
-            this["ea1851.reset.windowconsumed.160"] shouldBe null
-            this["ea1851.reset.shownotice"] shouldBe null
-        }
-
-        createMockFiles()
-
-        createInstance().tryResetIfNecessary(
-            GeneralSecurityException("decryption failed")
-        ) shouldBe true
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe 1234567890L
-            this["ea1851.reset.windowconsumed"] shouldBe true
-            this["ea1851.reset.windowconsumed.160"] shouldBe true
-            this["ea1851.reset.shownotice"] shouldBe true
-        }
-    }
-
-    @Test
-    fun `reset is also warranted if the exception has our desired exception as cause`() {
-        // We only perform the reset for users who encounter it the first time after the upgrade
-        createMockFiles()
-
-        createInstance().tryResetIfNecessary(
-            CwaSecurityException(RuntimeException(GeneralSecurityException("decryption failed")))
-        ) shouldBe true
-
-        encryptedPrefsFile.exists() shouldBe false
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe 1234567890L
-            this["ea1851.reset.windowconsumed.160"] shouldBe true
-            this["ea1851.reset.shownotice"] shouldBe true
-        }
-    }
-
-    @Test
-    fun `nested exception may have the same base exception type, ie GeneralSecurityException`() {
-        // https://github.com/corona-warn-app/cwa-app-android/issues/642#issuecomment-712188157
-        createMockFiles()
-
-        createInstance().tryResetIfNecessary(
-            KeyException( // subclass of GeneralSecurityException
-                "Permantly failed to instantiate encrypted preferences",
-                SecurityException(
-                    "Could not decrypt key. decryption failed",
-                    GeneralSecurityException("decryption failed")
-                )
-            )
-        ) shouldBe true
-
-        encryptedPrefsFile.exists() shouldBe false
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe 1234567890L
-            this["ea1851.reset.windowconsumed.160"] shouldBe true
-            this["ea1851.reset.shownotice"] shouldBe true
-        }
-    }
-
-    @Test
-    fun `exception check does not care about the first exception type`() {
-        createMockFiles()
-
-        createInstance().tryResetIfNecessary(
-            CwaSecurityException(
-                KeyException( // subclass of GeneralSecurityException
-                    "Permantly failed to instantiate encrypted preferences",
-                    SecurityException(
-                        "Could not decrypt key. decryption failed",
-                        GeneralSecurityException("decryption failed")
-                    )
-                )
-            )
-        ) shouldBe true
-
-        encryptedPrefsFile.exists() shouldBe false
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe 1234567890L
-            this["ea1851.reset.windowconsumed.160"] shouldBe true
-            this["ea1851.reset.shownotice"] shouldBe true
-        }
-    }
-
-    @Test
-    fun `exception check DOES care about the most nested exception`() {
-        createMockFiles()
-
-        createInstance().tryResetIfNecessary(
-            CwaSecurityException(
-                KeyException( // subclass of GeneralSecurityException
-                    "Permantly failed to instantiate encrypted preferences",
-                    SecurityException(
-                        "Could not decrypt key. decryption failed",
-                        GeneralSecurityException(
-                            "decryption failed",
-                            IOException("I am unexpeted")
-                        )
-                    )
-                )
-            )
-        ) shouldBe false
-
-        encryptedPrefsFile.exists() shouldBe true
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe null
-            this["ea1851.reset.windowconsumed.160"] shouldBe true
-            this["ea1851.reset.shownotice"] shouldBe null
-        }
-    }
-
-    @Test
-    fun `we want only a specific type of GeneralSecurityException`() {
-        createMockFiles()
-
-        createInstance().tryResetIfNecessary(
-            GeneralSecurityException("2020 failed")
-        ) shouldBe false
-
-        encryptedPrefsFile.exists() shouldBe true
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe null
-            this["ea1851.reset.windowconsumed.160"] shouldBe true
-            this["ea1851.reset.shownotice"] shouldBe null
-        }
-    }
-
-    @Test
-    fun `reset is not warranted for GeneralSecurityException that happened later`() {
-        createMockFiles()
-
-        createInstance().tryResetIfNecessary(KeyStoreException()) shouldBe false
-
-        createInstance().tryResetIfNecessary(
-            GeneralSecurityException("decryption failed")
-        ) shouldBe false
-
-        encryptedPrefsFile.exists() shouldBe true
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe null
-            this["ea1851.reset.windowconsumed.160"] shouldBe true
-            this["ea1851.reset.shownotice"] shouldBe null
-        }
-    }
-
-    @Test
-    fun `reset is not warranted if the error fits, but there is no existing preference file`() {
-        encryptedPrefsFile.exists() shouldBe false
-
-        createInstance().tryResetIfNecessary(
-            GeneralSecurityException("decryption failed")
-        ) shouldBe false
-
-        encryptedPrefsFile.exists() shouldBe false
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe null
-            this["ea1851.reset.windowconsumed.160"] shouldBe true
-            this["ea1851.reset.shownotice"] shouldBe null
-        }
-    }
-
-    @Test
-    fun `the reset is considered failed if the preferences can not be deleted`() {
-        createMockFiles()
-        encryptedPrefsFile.delete()
-        encryptedPrefsFile.mkdir() // Can't delete directories with children via `delete()`
-        File(encryptedPrefsFile, "prevent deletion").createNewFile()
-
-        createInstance().tryResetIfNecessary(
-            GeneralSecurityException("decryption failed")
-        ) shouldBe false
-
-        encryptedPrefsFile.exists() shouldBe true
-
-        mockPreferences.dataMapPeek.apply {
-            this["ea1851.reset.performedAt"] shouldBe null
-            this["ea1851.reset.windowconsumed.160"] shouldBe true
-            this["ea1851.reset.shownotice"] shouldBe null
-        }
-    }
-}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/security/SecurityHelperTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/security/SecurityHelperTest.kt
deleted file mode 100644
index cb3ce3fdd240f7fd67e74f109957c3b789355709..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/security/SecurityHelperTest.kt
+++ /dev/null
@@ -1,90 +0,0 @@
-package de.rki.coronawarnapp.util.security
-
-import android.content.SharedPreferences
-import de.rki.coronawarnapp.util.di.ApplicationComponent
-import io.kotest.assertions.throwables.shouldThrow
-import io.kotest.matchers.shouldBe
-import io.mockk.MockKAnnotations
-import io.mockk.every
-import io.mockk.impl.annotations.MockK
-import io.mockk.mockk
-import io.mockk.verify
-import io.mockk.verifySequence
-import org.junit.jupiter.api.BeforeEach
-import org.junit.jupiter.api.Test
-import testhelpers.BaseTest
-
-class SecurityHelperTest : BaseTest() {
-    @MockK
-    lateinit var appComponent: ApplicationComponent
-
-    @MockK
-    lateinit var errorResetTool: EncryptionErrorResetTool
-
-    @MockK
-    lateinit var preferenceFactory: EncryptedPreferencesFactory
-
-    @BeforeEach
-    fun setup() {
-        MockKAnnotations.init(this)
-
-        every { appComponent.errorResetTool } returns errorResetTool
-        every { appComponent.encryptedPreferencesFactory } returns preferenceFactory
-    }
-
-    @Test
-    fun `error free case is sideeffect free`() {
-        val sharedPreferences: SharedPreferences = mockk()
-        every { preferenceFactory.create("shared_preferences_cwa") } returns sharedPreferences
-
-        SecurityHelper.encryptedPreferencesProvider(appComponent) shouldBe sharedPreferences
-        verify(exactly = 0) { errorResetTool.tryResetIfNecessary(any()) }
-    }
-
-    @Test
-    fun `positive reset tool results cause a retry`() {
-        val ourPreferences: SharedPreferences = mockk()
-        var ourException: Exception? = null
-        every { preferenceFactory.create("shared_preferences_cwa") } answers {
-            if (ourException == null) {
-                ourException = Exception("99 bugs")
-                throw ourException!!
-            } else {
-                ourPreferences
-            }
-        }
-        every { errorResetTool.tryResetIfNecessary(any()) } returns true
-
-        SecurityHelper.encryptedPreferencesProvider(appComponent) shouldBe ourPreferences
-
-        verifySequence {
-            preferenceFactory.create(any())
-            errorResetTool.tryResetIfNecessary(ourException!!)
-            preferenceFactory.create(any())
-        }
-    }
-
-    @Test
-    fun `negative reset tool results rethrow the exception`() {
-        val ourPreferences: SharedPreferences = mockk()
-        var ourException: Exception? = null
-        every { preferenceFactory.create("shared_preferences_cwa") } answers {
-            if (ourException == null) {
-                ourException = Exception("99 bugs")
-                throw ourException!!
-            } else {
-                ourPreferences
-            }
-        }
-        every { errorResetTool.tryResetIfNecessary(any()) } returns false
-
-        shouldThrow<Exception> {
-            SecurityHelper.encryptedPreferencesProvider(appComponent) shouldBe ourPreferences
-        }.cause shouldBe ourException
-
-        verifySequence {
-            preferenceFactory.create(any())
-            errorResetTool.tryResetIfNecessary(ourException!!)
-        }
-    }
-}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/worker/DiagnosisTestResultRetrievalPeriodicWorkerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/worker/DiagnosisTestResultRetrievalPeriodicWorkerTest.kt
index 9de1965602d2351a0fc09046ce922b777f8d790a..2547fd7543ba824ef0c7cb14acfe1036a2ae4343 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/worker/DiagnosisTestResultRetrievalPeriodicWorkerTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/worker/DiagnosisTestResultRetrievalPeriodicWorkerTest.kt
@@ -9,7 +9,7 @@ import de.rki.coronawarnapp.notification.NotificationConstants
 import de.rki.coronawarnapp.notification.NotificationHelper
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
 import de.rki.coronawarnapp.service.submission.SubmissionService
-import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.storage.TracingSettings
 import de.rki.coronawarnapp.submission.SubmissionSettings
 import de.rki.coronawarnapp.util.TimeAndDateExtensions.daysToMilliseconds
 import de.rki.coronawarnapp.util.TimeStamper
@@ -29,12 +29,14 @@ import io.mockk.impl.annotations.MockK
 import io.mockk.impl.annotations.RelaxedMockK
 import io.mockk.just
 import io.mockk.mockkObject
+import io.mockk.slot
 import io.mockk.verify
 import kotlinx.coroutines.test.runBlockingTest
 import org.joda.time.Instant
 import org.junit.Before
 import org.junit.Test
 import testhelpers.BaseTest
+import testhelpers.preferences.mockFlowPreference
 
 class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
     @MockK lateinit var context: Context
@@ -48,6 +50,7 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
     @MockK lateinit var encryptionErrorResetTool: EncryptionErrorResetTool
     @MockK lateinit var operation: Operation
     @MockK lateinit var timeStamper: TimeStamper
+    @MockK lateinit var tracingSettings: TracingSettings
     @RelaxedMockK lateinit var workerParams: WorkerParameters
     private val currentInstant = Instant.ofEpochSecond(1611764225)
     private val registrationToken = "test token"
@@ -57,18 +60,17 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
         MockKAnnotations.init(this)
         every { submissionSettings.hasViewedTestResult.value } returns false
         every { timeStamper.nowUTC } returns currentInstant
+        every { tracingSettings.initialPollingForTestResultTimeStamp } returns currentInstant.millis
+        every { tracingSettings.isTestResultAvailableNotificationSent } returns false
+        every { tracingSettings.initialPollingForTestResultTimeStamp = capture(slot()) } answers {}
+        every { tracingSettings.isTestResultAvailableNotificationSent = capture(slot()) } answers {}
 
         mockkObject(AppInjector)
         every { AppInjector.component } returns appComponent
         every { appComponent.encryptedPreferencesFactory } returns encryptedPreferencesFactory
         every { appComponent.errorResetTool } returns encryptionErrorResetTool
 
-        mockkObject(LocalData)
-        every { LocalData.registrationToken() } returns registrationToken
-        every { LocalData.isTestResultAvailableNotificationSent() } returns false
-        every { LocalData.initialPollingForTestResultTimeStamp() } returns currentInstant.millis
-        every { LocalData.initialPollingForTestResultTimeStamp(any()) } just Runs
-        every { LocalData.isTestResultAvailableNotificationSent(any()) } just Runs
+        every { submissionSettings.registrationToken } returns mockFlowPreference(registrationToken)
 
         mockkObject(BackgroundWorkScheduler)
         every { BackgroundWorkScheduler.WorkType.DIAGNOSIS_TEST_RESULT_PERIODIC_WORKER.stop() } returns operation
@@ -82,19 +84,19 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
             val result = worker.doWork()
             coVerify(exactly = 0) { submissionService.asyncRequestTestResult(any()) }
             verify(exactly = 1) { BackgroundWorkScheduler.WorkType.DIAGNOSIS_TEST_RESULT_PERIODIC_WORKER.stop() }
-            assert(result is ListenableWorker.Result.Success)
+            result shouldBe ListenableWorker.Result.success()
         }
     }
 
     @Test
     fun testStopWorkerWhenNotificationSent() {
         runBlockingTest {
-            every { LocalData.isTestResultAvailableNotificationSent() } returns true
+            every { tracingSettings.isTestResultAvailableNotificationSent } returns true
             val worker = createWorker()
             val result = worker.doWork()
             coVerify(exactly = 0) { submissionService.asyncRequestTestResult(any()) }
             verify(exactly = 1) { BackgroundWorkScheduler.WorkType.DIAGNOSIS_TEST_RESULT_PERIODIC_WORKER.stop() }
-            assert(result is ListenableWorker.Result.Success)
+            result shouldBe ListenableWorker.Result.success()
         }
     }
 
@@ -103,7 +105,7 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
         runBlockingTest {
             val past =
                 currentInstant - (BackgroundConstants.POLLING_VALIDITY_MAX_DAYS.toLong() + 1).daysToMilliseconds()
-            every { LocalData.initialPollingForTestResultTimeStamp() } returns past.millis
+            every { tracingSettings.initialPollingForTestResultTimeStamp } returns past.millis
             val worker = createWorker()
             val result = worker.doWork()
             coVerify(exactly = 0) { submissionService.asyncRequestTestResult(any()) }
@@ -114,6 +116,11 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
 
     @Test
     fun testSendNotificationWhenPositive() {
+        val isTestResultAvailableNotificationSent = slot<Boolean>()
+        every {
+            tracingSettings.isTestResultAvailableNotificationSent = capture(isTestResultAvailableNotificationSent)
+        } answers {}
+
         runBlockingTest {
             val testResult = TestResult.POSITIVE
             coEvery { submissionService.asyncRequestTestResult(registrationToken) } returns testResult
@@ -126,19 +133,24 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
             val worker = createWorker()
             val result = worker.doWork()
             coVerify { submissionService.asyncRequestTestResult(registrationToken) }
-            coVerify { LocalData.isTestResultAvailableNotificationSent(true) }
             coVerify { testResultAvailableNotificationService.showTestResultAvailableNotification(testResult) }
             coVerify {
                 notificationHelper.cancelCurrentNotification(
                     NotificationConstants.NEW_MESSAGE_RISK_LEVEL_SCORE_NOTIFICATION_ID
                 )
             }
-            assert(result is ListenableWorker.Result.Success)
+            result shouldBe ListenableWorker.Result.success()
+            isTestResultAvailableNotificationSent.captured shouldBe true
         }
     }
 
     @Test
     fun testSendNotificationWhenNegative() {
+        val isTestResultAvailableNotificationSent = slot<Boolean>()
+        every {
+            tracingSettings.isTestResultAvailableNotificationSent = capture(isTestResultAvailableNotificationSent)
+        } answers {}
+
         runBlockingTest {
             val testResult = TestResult.NEGATIVE
             coEvery { submissionService.asyncRequestTestResult(registrationToken) } returns testResult
@@ -151,19 +163,24 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
             val worker = createWorker()
             val result = worker.doWork()
             coVerify { submissionService.asyncRequestTestResult(registrationToken) }
-            coVerify { LocalData.isTestResultAvailableNotificationSent(true) }
             coVerify { testResultAvailableNotificationService.showTestResultAvailableNotification(testResult) }
             coVerify {
                 notificationHelper.cancelCurrentNotification(
                     NotificationConstants.NEW_MESSAGE_RISK_LEVEL_SCORE_NOTIFICATION_ID
                 )
             }
-            assert(result is ListenableWorker.Result.Success)
+            result shouldBe ListenableWorker.Result.success()
+            isTestResultAvailableNotificationSent.captured shouldBe true
         }
     }
 
     @Test
     fun testSendNotificationWhenInvalid() {
+        val isTestResultAvailableNotificationSent = slot<Boolean>()
+        every {
+            tracingSettings.isTestResultAvailableNotificationSent = capture(isTestResultAvailableNotificationSent)
+        } answers {}
+
         runBlockingTest {
             val testResult = TestResult.INVALID
             coEvery { submissionService.asyncRequestTestResult(registrationToken) } returns testResult
@@ -176,14 +193,14 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
             val worker = createWorker()
             val result = worker.doWork()
             coVerify { submissionService.asyncRequestTestResult(registrationToken) }
-            coVerify { LocalData.isTestResultAvailableNotificationSent(true) }
             coVerify { testResultAvailableNotificationService.showTestResultAvailableNotification(testResult) }
             coVerify {
                 notificationHelper.cancelCurrentNotification(
                     NotificationConstants.NEW_MESSAGE_RISK_LEVEL_SCORE_NOTIFICATION_ID
                 )
             }
-            assert(result is ListenableWorker.Result.Success)
+            result shouldBe ListenableWorker.Result.success()
+            isTestResultAvailableNotificationSent.captured shouldBe true
         }
     }
 
@@ -201,7 +218,6 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
             val worker = createWorker()
             val result = worker.doWork()
             coVerify { submissionService.asyncRequestTestResult(registrationToken) }
-            coVerify(exactly = 0) { LocalData.isTestResultAvailableNotificationSent(true) }
             coVerify(exactly = 0) {
                 testResultAvailableNotificationService.showTestResultAvailableNotification(
                     testResult
@@ -213,7 +229,7 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
                 )
             }
             coVerify(exactly = 0) { BackgroundWorkScheduler.WorkType.DIAGNOSIS_TEST_RESULT_PERIODIC_WORKER.stop() }
-            assert(result is ListenableWorker.Result.Success)
+            result shouldBe ListenableWorker.Result.success()
         }
     }
 
@@ -236,6 +252,7 @@ class DiagnosisTestResultRetrievalPeriodicWorkerTest : BaseTest() {
         notificationHelper,
         submissionSettings,
         submissionService,
-        timeStamper
+        timeStamper,
+        tracingSettings
     )
 }
diff --git a/Corona-Warn-App/src/test/java/testhelpers/preferences/MockFlowPreference.kt b/Corona-Warn-App/src/testShared/java/testhelpers/preferences/MockFlowPreference.kt
similarity index 100%
rename from Corona-Warn-App/src/test/java/testhelpers/preferences/MockFlowPreference.kt
rename to Corona-Warn-App/src/testShared/java/testhelpers/preferences/MockFlowPreference.kt
diff --git a/Corona-Warn-App/src/test/java/testhelpers/preferences/MockSharedPreferences.kt b/Corona-Warn-App/src/testShared/java/testhelpers/preferences/MockSharedPreferences.kt
similarity index 100%
rename from Corona-Warn-App/src/test/java/testhelpers/preferences/MockSharedPreferences.kt
rename to Corona-Warn-App/src/testShared/java/testhelpers/preferences/MockSharedPreferences.kt