diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryDayFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryDayFragmentTest.kt
index 147a5961f1456b673ea39bad904d3f79b9a2be7d..cc57ba6dbf4711c57544025f1a8d630feea1f9f1 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryDayFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/ContactDiaryDayFragmentTest.kt
@@ -112,10 +112,10 @@ class ContactDiaryDayFragmentTest : BaseUITest() {
             fragmentArgs = fragmentArgs,
             themeResId = R.style.AppTheme_Main
         )
-        takeScreenshot<ContactDiaryDayFragment>(suffix)
+        takeScreenshot<ContactDiaryDayFragment>("persons_$suffix")
         onView(withId(R.id.contact_diary_day_tab_layout))
             .perform(selectTabAtPosition(1))
-        takeScreenshot<ContactDiaryDayFragment>(suffix + "_2")
+        takeScreenshot<ContactDiaryDayFragment>("locations_$suffix")
     }
 
     private fun setupViewModels() {
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt
index c4a5e96b418d6347da251672d8374473cb7dbb76..6181fbc5e9f83af068a8b3f6c30e9613b5730186 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/contactdiary/DiaryData.kt
@@ -3,63 +3,50 @@ package de.rki.coronawarnapp.ui.contactdiary
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.contactdiary.model.ContactDiaryLocation
 import de.rki.coronawarnapp.contactdiary.model.ContactDiaryPerson
+import de.rki.coronawarnapp.contactdiary.model.ContactDiaryPersonEncounter
 import de.rki.coronawarnapp.contactdiary.model.DefaultContactDiaryLocation
 import de.rki.coronawarnapp.contactdiary.model.DefaultContactDiaryLocationVisit
 import de.rki.coronawarnapp.contactdiary.model.DefaultContactDiaryPerson
 import de.rki.coronawarnapp.contactdiary.model.DefaultContactDiaryPersonEncounter
 import de.rki.coronawarnapp.contactdiary.ui.day.tabs.location.DiaryLocationListItem
 import de.rki.coronawarnapp.contactdiary.ui.day.tabs.person.DiaryPersonListItem
-import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.ListItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem
 import org.joda.time.Duration
 import org.joda.time.LocalDate
 
 object DiaryData {
 
     val DATA_ITEMS = listOf(
-        ListItem.Data(
-            R.drawable.ic_contact_diary_person_item,
-            "Max Mustermann",
-            null,
-            listOf(
-                R.string.contact_diary_person_encounter_duration_below_15_min,
-                R.string.contact_diary_person_encounter_mask_with,
-                R.string.contact_diary_person_encounter_environment_inside
-            ),
-            "Notizen notizen",
-            ListItem.Type.PERSON
+        DayOverviewItem.Data(
+            R.drawable.ic_contact_diary_location_item,
+            "Rewe",
+            Duration.standardMinutes(30),
+            attributes = null,
+            circumstances = null,
+            DayOverviewItem.Type.LOCATION
         ),
-
-        ListItem.Data(
+        DayOverviewItem.Data(
             R.drawable.ic_contact_diary_person_item,
-            "Erika Mustermann",
+            "Andrea Steinhauer",
             null,
             listOf(
-                R.string.contact_diary_person_encounter_environment_inside
+                R.string.contact_diary_person_encounter_duration_below_15_min,
+                R.string.contact_diary_person_encounter_environment_outside
             ),
-            "Notizen notizen",
-            ListItem.Type.PERSON
-        ),
-
-        ListItem.Data(
-            R.drawable.ic_contact_diary_location,
-            "Fitnessstudio",
-            Duration.millis(1800000),
             null,
-            "Notizen notizen",
-            ListItem.Type.LOCATION
+            DayOverviewItem.Type.PERSON
         ),
-
-        ListItem.Data(
-            R.drawable.ic_contact_diary_location,
-            "Supermarket",
+        DayOverviewItem.Data(
+            R.drawable.ic_contact_diary_location_item,
+            "Büro",
             null,
             null,
             null,
-            ListItem.Type.LOCATION
+            DayOverviewItem.Type.LOCATION
         )
     )
 
-    val HIGH_RISK = ListItem.Risk(
+    val HIGH_RISK = DayOverviewItem.Risk(
         title = R.string.contact_diary_high_risk_title,
         body = R.string.contact_diary_risk_body,
         bodyExtended = R.string.contact_diary_risk_body_extended,
@@ -68,7 +55,7 @@ object DiaryData {
 
     val HIGH_RISK_DUE_LOW_RISK_ENCOUNTERS = HIGH_RISK.copy(body = R.string.contact_diary_risk_body_high_risk_due_to_low_risk_encounters)
 
-    val LOW_RISK = ListItem.Risk(
+    val LOW_RISK = DayOverviewItem.Risk(
         title = R.string.contact_diary_low_risk_title,
         body = R.string.contact_diary_risk_body,
         bodyExtended = R.string.contact_diary_risk_body_extended,
@@ -77,10 +64,11 @@ object DiaryData {
 
     val LOCATIONS: List<DiaryLocationListItem> = listOf(
         DiaryLocationListItem(
-            item = DefaultContactDiaryLocation(locationName = "Sport"),
+            item = DefaultContactDiaryLocation(locationName = "Physiotherapie"),
             visit = DefaultContactDiaryLocationVisit(
                 contactDiaryLocation = DefaultContactDiaryLocation(locationName = ""),
-                date = LocalDate.now()
+                date = LocalDate.now(),
+                duration = Duration.standardMinutes(90)
             ),
             onItemClick = {},
             onDurationChanged = { _, _ -> },
@@ -89,19 +77,7 @@ object DiaryData {
             onDurationDialog = { _, _ -> }
         ),
         DiaryLocationListItem(
-            item = DefaultContactDiaryLocation(locationName = "Büro"),
-            visit = DefaultContactDiaryLocationVisit(
-                contactDiaryLocation = DefaultContactDiaryLocation(locationName = ""),
-                date = LocalDate.now()
-            ),
-            onItemClick = {},
-            onDurationChanged = { _, _ -> },
-            onCircumstancesChanged = { _, _ -> },
-            onCircumStanceInfoClicked = {},
-            onDurationDialog = { _, _ -> }
-        ),
-        DiaryLocationListItem(
-            item = DefaultContactDiaryLocation(locationName = "Supermarkt"),
+            item = DefaultContactDiaryLocation(locationName = "Hausarzt"),
             visit = null,
             onItemClick = {},
             onDurationChanged = { _, _ -> },
@@ -113,10 +89,14 @@ object DiaryData {
 
     val PERSONS: List<DiaryPersonListItem> = listOf(
         DiaryPersonListItem(
-            item = DefaultContactDiaryPerson(fullName = "Erika Mustermann"),
+            item = DefaultContactDiaryPerson(fullName = "Andrea Steinhauer"),
             personEncounter = DefaultContactDiaryPersonEncounter(
                 contactDiaryPerson = DefaultContactDiaryPerson(fullName = ""),
-                date = LocalDate.now()
+                date = LocalDate.now(),
+                durationClassification = ContactDiaryPersonEncounter.DurationClassification.LESS_THAN_15_MINUTES,
+                withMask = false,
+                wasOutside = true,
+                circumstances = "saßen nah beieinander"
             ),
             onItemClick = {},
             onDurationChanged = { _, _ -> },
@@ -126,7 +106,7 @@ object DiaryData {
             onCircumstanceInfoClicked = {}
         ),
         DiaryPersonListItem(
-            item = DefaultContactDiaryPerson(fullName = "Max Mustermann"),
+            item = DefaultContactDiaryPerson(fullName = "Constantin Frenzel"),
             personEncounter = DefaultContactDiaryPersonEncounter(
                 contactDiaryPerson = DefaultContactDiaryPerson(fullName = ""),
                 date = LocalDate.now()
@@ -137,16 +117,6 @@ object DiaryData {
             onWithMaskChanged = { _, _ -> },
             onWasOutsideChanged = { _, _ -> },
             onCircumstanceInfoClicked = {}
-        ),
-        DiaryPersonListItem(
-            item = DefaultContactDiaryPerson(fullName = "John Doe"),
-            personEncounter = null,
-            onItemClick = {},
-            onDurationChanged = { _, _ -> },
-            onCircumstancesChanged = { _, _ -> },
-            onWithMaskChanged = { _, _ -> },
-            onWasOutsideChanged = { _, _ -> },
-            onCircumstanceInfoClicked = {}
         )
     )
 
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/MainActivityTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/MainActivityTest.kt
index 63e5c8a119760fe4f0dc3efde12ac9ce35a4aca7..33e8494ef2f7407181362bed1786160df35ce486 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/MainActivityTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/MainActivityTest.kt
@@ -17,7 +17,9 @@ import de.rki.coronawarnapp.contactdiary.ui.ContactDiarySettings
 import de.rki.coronawarnapp.contactdiary.ui.exporter.ContactDiaryExporter
 import de.rki.coronawarnapp.contactdiary.ui.overview.ContactDiaryOverviewFragment
 import de.rki.coronawarnapp.contactdiary.ui.overview.ContactDiaryOverviewViewModel
-import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.ListItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem
 import de.rki.coronawarnapp.datadonation.analytics.worker.DataDonationAnalyticsScheduler
 import de.rki.coronawarnapp.deadman.DeadmanNotificationScheduler
 import de.rki.coronawarnapp.environment.EnvironmentSetup
@@ -291,7 +293,7 @@ class MainActivityTest : BaseUITest() {
         takeScreenshot<ContactDiaryOverviewFragment>()
 
         onView(withId(R.id.contact_diary_overview_recyclerview))
-            .perform(recyclerScrollTo(1))
+            .perform(recyclerScrollTo(4))
         takeScreenshot<ContactDiaryOverviewFragment>("2")
     }
 
@@ -322,21 +324,35 @@ class MainActivityTest : BaseUITest() {
             }
         )
 
-    private fun contactDiaryOverviewItemLiveData(): LiveData<List<ListItem>> =
-        MutableLiveData(
-            (0 until ContactDiaryOverviewViewModel.DAY_COUNT)
-                .map { LocalDate.now().minusDays(it) }
-                .mapIndexed { index, localDate ->
-                    ListItem(localDate).apply {
-                        data.addAll(DiaryData.DATA_ITEMS)
-                        risk = when (index % 3) {
-                            0 -> DiaryData.HIGH_RISK
-                            1 -> DiaryData.HIGH_RISK_DUE_LOW_RISK_ENCOUNTERS
-                            else -> DiaryData.LOW_RISK
-                        }
+    private fun contactDiaryOverviewItemLiveData(): LiveData<List<DiaryOverviewItem>> {
+        val data = mutableListOf<DiaryOverviewItem>()
+        data.add(OverviewSubHeaderItem)
+        val dayData = (0 until ContactDiaryOverviewViewModel.DAY_COUNT)
+            .map { LocalDate.now().minusDays(it) }
+            .mapIndexed { index, localDate ->
+                val dayData = mutableListOf<DayOverviewItem.Data>().apply {
+                    if (index == 1) {
+                        add(DiaryData.DATA_ITEMS[0])
+                        add(DiaryData.DATA_ITEMS[1])
+                    } else if (index == 3) {
+                        add(DiaryData.DATA_ITEMS[2])
                     }
                 }
-        )
+                val risk = when (index % 5) {
+                    3 -> DiaryData.HIGH_RISK_DUE_LOW_RISK_ENCOUNTERS
+                    else -> null // DiaryData.LOW_RISK OR DiaryData.HIGH_RISK POSSIBLE
+                }
+                DayOverviewItem(
+                    date = localDate,
+                    data = dayData,
+                    risk = risk
+                ) {
+                    // onClick
+                }
+            }
+        data.addAll(dayData)
+        return MutableLiveData(data)
+    }
 
     // ViewModels creators
     private fun mainActivityViewModelSpy() = spyk(
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsFragmentTest.kt
index eaf88daf0bfa813ccc1a453083c58ef0feae1004..634908d8bedf93147d08614b1d69c075480182aa 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsFragmentTest.kt
@@ -13,6 +13,7 @@ import io.mockk.coEvery
 import io.mockk.every
 import io.mockk.impl.annotations.MockK
 import io.mockk.spyk
+import kotlinx.coroutines.GlobalScope
 import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.flowOf
 import org.junit.After
@@ -71,6 +72,7 @@ class OnboardingAnalyticsFragmentTest : BaseUITest() {
 
     private fun onboardingAnalyticsViewModelSpy() = spyk(
         OnboardingAnalyticsViewModel(
+            appScope = GlobalScope,
             settings = settings,
             districts = districts,
             dispatcherProvider = TestDispatcherProvider(),
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionConsentFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionConsentFragmentTest.kt
index 0fde6ecaf2d8d1ce3e3c09bcb967d9c070e7bf91..7748ab27cde652375f87387997882dea0eec59a9 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionConsentFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionConsentFragmentTest.kt
@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.ui.submission
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import dagger.Module
 import dagger.android.ContributesAndroidInjector
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.nearby.modules.tekhistory.TEKHistoryProvider
 import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository
 import de.rki.coronawarnapp.submission.SubmissionRepository
@@ -30,6 +31,7 @@ class SubmissionConsentFragmentTest : BaseUITest() {
     @MockK lateinit var submissionRepository: SubmissionRepository
     @MockK lateinit var interoperabilityRepository: InteroperabilityRepository
     @MockK lateinit var tekHistoryProvider: TEKHistoryProvider
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     @Rule
     @JvmField
@@ -49,7 +51,8 @@ class SubmissionConsentFragmentTest : BaseUITest() {
                 submissionRepository,
                 interoperabilityRepository,
                 TestDispatcherProvider(),
-                tekHistoryProvider
+                tekHistoryProvider,
+                analyticsKeySubmissionCollector
             )
         setupMockViewModel(
             object : SubmissionConsentViewModel.Factory {
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionSymptomCalendarFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionSymptomCalendarFragmentTest.kt
index 943df7ec90e9868c1f5914330b2fcde74e8131e9..aa15d484e3d19014de85adbf21aa08caf8ac0c7e 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionSymptomCalendarFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionSymptomCalendarFragmentTest.kt
@@ -8,6 +8,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
 import dagger.Module
 import dagger.android.ContributesAndroidInjector
 import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.Symptoms
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -36,6 +37,7 @@ class SubmissionSymptomCalendarFragmentTest : BaseUITest() {
 
     @MockK lateinit var submissionRepository: SubmissionRepository
     @MockK lateinit var autoSubmission: AutoSubmission
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     @Rule
     @JvmField
@@ -54,7 +56,8 @@ class SubmissionSymptomCalendarFragmentTest : BaseUITest() {
                 Symptoms.Indication.POSITIVE,
                 TestDispatcherProvider(),
                 submissionRepository,
-                autoSubmission
+                autoSubmission,
+                analyticsKeySubmissionCollector
             )
         )
         with(viewModel) {
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionSymptomIntroFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionSymptomIntroFragmentTest.kt
index 9e86f9de03d7bb207f3652ace363a8c32ea6a14d..b1bf713e0d6302806fa5a017014fbafbcc7e981e 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionSymptomIntroFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionSymptomIntroFragmentTest.kt
@@ -9,6 +9,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
 import dagger.Module
 import dagger.android.ContributesAndroidInjector
 import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.Symptoms
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -38,6 +39,7 @@ class SubmissionSymptomIntroFragmentTest : BaseUITest() {
 
     @MockK lateinit var submissionRepository: SubmissionRepository
     @MockK lateinit var autoSubmission: AutoSubmission
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     @Rule
     @JvmField
@@ -55,7 +57,8 @@ class SubmissionSymptomIntroFragmentTest : BaseUITest() {
             SubmissionSymptomIntroductionViewModel(
                 TestDispatcherProvider(),
                 submissionRepository,
-                autoSubmission
+                autoSubmission,
+                analyticsKeySubmissionCollector
             )
         )
         with(viewModel) {
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultAvailableFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultAvailableFragmentTest.kt
index 82b41af38b9680a2cb43a620c1e9c3ed1d57e120..33dc537e4cc00d5866850b2411f9bd2c90c86ad9 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultAvailableFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultAvailableFragmentTest.kt
@@ -4,6 +4,7 @@ import androidx.lifecycle.MutableLiveData
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import dagger.Module
 import dagger.android.ContributesAndroidInjector
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
 import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryUpdater_Factory_Impl
@@ -37,6 +38,7 @@ class SubmissionTestResultAvailableFragmentTest : BaseUITest() {
     @MockK lateinit var tekHistoryUpdaterFactory: TEKHistoryUpdater_Factory_Impl
     @MockK lateinit var autoSubmission: AutoSubmission
     @MockK lateinit var appShortcutsHelper: AppShortcutsHelper
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     @Rule
     @JvmField
@@ -58,7 +60,8 @@ class SubmissionTestResultAvailableFragmentTest : BaseUITest() {
                 TestDispatcherProvider(),
                 tekHistoryUpdaterFactory,
                 submissionRepository,
-                autoSubmission
+                autoSubmission,
+                analyticsKeySubmissionCollector
             )
         )
 
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultConsentGivenFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultConsentGivenFragmentTest.kt
index 2ddeb46116948b3086b0916d7f9ddee5acb65d2a..352a9a57e08923857aa906ed603bbea20aa37b17 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultConsentGivenFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultConsentGivenFragmentTest.kt
@@ -12,6 +12,7 @@ import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiT
 import dagger.Module
 import dagger.android.ContributesAndroidInjector
 import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -45,6 +46,7 @@ class SubmissionTestResultConsentGivenFragmentTest : BaseUITest() {
     @MockK lateinit var submissionRepository: SubmissionRepository
     @MockK lateinit var autoSubmission: AutoSubmission
     @MockK lateinit var testResultAvailableNotificationService: TestResultAvailableNotificationService
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     @Rule
     @JvmField
@@ -70,6 +72,7 @@ class SubmissionTestResultConsentGivenFragmentTest : BaseUITest() {
                     submissionRepository,
                     autoSubmission,
                     testResultAvailableNotificationService,
+                    analyticsKeySubmissionCollector,
                     TestDispatcherProvider()
                 )
             )
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultNoConsentGivenFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultNoConsentGivenFragmentTest.kt
index 1aaa59220916d29cf48878e26bda36b579f790cc..8c640d2568570c263e634009b2f896b8d8de3fde 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultNoConsentGivenFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultNoConsentGivenFragmentTest.kt
@@ -4,6 +4,7 @@ import androidx.lifecycle.MutableLiveData
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import dagger.Module
 import dagger.android.ContributesAndroidInjector
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.ui.submission.testresult.TestResultUIState
@@ -32,6 +33,7 @@ class SubmissionTestResultNoConsentGivenFragmentTest : BaseUITest() {
 
     @MockK lateinit var submissionRepository: SubmissionRepository
     @MockK lateinit var testResultAvailableNotificationService: TestResultAvailableNotificationService
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     @Rule
     @JvmField
@@ -46,7 +48,13 @@ class SubmissionTestResultNoConsentGivenFragmentTest : BaseUITest() {
     fun setup() {
         MockKAnnotations.init(this, relaxed = true)
         viewModel =
-            spyk(SubmissionTestResultNoConsentViewModel(submissionRepository, testResultAvailableNotificationService))
+            spyk(
+                SubmissionTestResultNoConsentViewModel(
+                    submissionRepository,
+                    testResultAvailableNotificationService,
+                    analyticsKeySubmissionCollector
+                )
+            )
         setupMockViewModel(
             object : SubmissionTestResultNoConsentViewModel.Factory {
                 override fun create(): SubmissionTestResultNoConsentViewModel = viewModel
diff --git a/Corona-Warn-App/src/androidTest/java/testhelpers/ScreenShotter.kt b/Corona-Warn-App/src/androidTest/java/testhelpers/ScreenShotter.kt
index 4d9f4cea6269d3119a667f9373c88bac80d0c3db..b189086d8e18ecd94f81b614b2bbe28d9f7ea922 100644
--- a/Corona-Warn-App/src/androidTest/java/testhelpers/ScreenShotter.kt
+++ b/Corona-Warn-App/src/androidTest/java/testhelpers/ScreenShotter.kt
@@ -9,6 +9,7 @@ import androidx.annotation.StyleRes
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentFactory
 import androidx.test.espresso.ViewAction
+import androidx.test.platform.app.InstrumentationRegistry
 import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
 import de.rki.coronawarnapp.R
 import tools.fastlane.screengrab.Screengrab
@@ -31,7 +32,8 @@ inline fun <reified T> takeScreenshot(suffix: String = "", delay: Long = SCREENS
 
     val contentResolver = getInstrumentation().targetContext.contentResolver
     val testLabSetting = Settings.System.getString(contentResolver, "firebase.test.lab")
-    if ("true" == testLabSetting) {
+    val androidStudioMode = InstrumentationRegistry.getArguments().getString("androidStudioMode")
+    if ("true" in listOf(testLabSetting, androidStudioMode)) {
         Screengrab.screenshot(
             name,
             UiAutomatorScreenshotStrategy(),
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt
index c7e21989fd781d408136627899c6b122adea96bc..31529a2382e582f02eba099eb398e189fccea157 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryLocationEntity.kt
@@ -5,6 +5,7 @@ import androidx.room.ColumnInfo
 import androidx.room.Entity
 import androidx.room.PrimaryKey
 import de.rki.coronawarnapp.contactdiary.model.ContactDiaryLocation
+import de.rki.coronawarnapp.util.trimToLength
 import kotlinx.parcelize.Parcelize
 
 @Parcelize
@@ -19,10 +20,13 @@ data class ContactDiaryLocationEntity(
         get() = locationId
 }
 
+private const val MAX_CHARACTERS = 250
+private fun String.trimMaxCharacters(): String = this.trimToLength(MAX_CHARACTERS)
+
 fun ContactDiaryLocation.toContactDiaryLocationEntity(): ContactDiaryLocationEntity =
     ContactDiaryLocationEntity(
         locationId = this.locationId,
-        locationName = this.locationName,
-        phoneNumber = this.phoneNumber,
-        emailAddress = this.emailAddress
+        locationName = this.locationName.trimMaxCharacters(),
+        phoneNumber = this.phoneNumber?.trimMaxCharacters(),
+        emailAddress = this.emailAddress?.trimMaxCharacters()
     )
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryPersonEntity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryPersonEntity.kt
index f9a10824c76675487d7466cfb996a0a3131b517b..df4c008029586a80d117d193c66860de31cc737e 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryPersonEntity.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/entity/ContactDiaryPersonEntity.kt
@@ -5,6 +5,7 @@ import androidx.room.ColumnInfo
 import androidx.room.Entity
 import androidx.room.PrimaryKey
 import de.rki.coronawarnapp.contactdiary.model.ContactDiaryPerson
+import de.rki.coronawarnapp.util.trimToLength
 import kotlinx.parcelize.Parcelize
 
 @Parcelize
@@ -19,10 +20,13 @@ data class ContactDiaryPersonEntity(
         get() = personId
 }
 
+private const val MAX_CHARACTERS = 250
+private fun String.trimMaxCharacters(): String = this.trimToLength(MAX_CHARACTERS)
+
 fun ContactDiaryPerson.toContactDiaryPersonEntity(): ContactDiaryPersonEntity =
     ContactDiaryPersonEntity(
         personId = this.personId,
-        fullName = this.fullName,
-        phoneNumber = this.phoneNumber,
-        emailAddress = this.emailAddress
+        fullName = this.fullName.trimMaxCharacters(),
+        phoneNumber = this.phoneNumber?.trimMaxCharacters(),
+        emailAddress = this.emailAddress?.trimMaxCharacters()
     )
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragment.kt
index a33bc0e11e588448dbf12ee41458b1839c7a7db7..5e14d2498e8c64bc8a44643e14a3b528f1dc0f4f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragment.kt
@@ -45,8 +45,8 @@ class ContactDiaryDurationPickerFragment : DialogFragment() {
             var duration = requireArguments().getString(DURATION_ARGUMENT_KEY)!!.split(":").toTypedArray()
             if (duration.size < 2) duration = arrayOf("00", "00")
 
-            hours.value = if (hoursArray.size > duration[0].toInt()) hoursArray.indexOf(duration[0]) else 0
-            minutes.value = if (minutesArray.size > duration[1].toInt()) minutesArray.indexOf(duration[1]) else 0
+            hours.value = hoursArray.indexOf(duration[0])
+            minutes.value = minutesArray.indexOf(duration[1])
 
             cancelButton.setOnClickListener { dismiss() }
             okButton.setOnClickListener {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationFragment.kt
index b7540115e47f5e7109b60d9a9369739b37112298..8e35cbf814b1e79ac44fac7171e58a29893f2f2d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationFragment.kt
@@ -52,8 +52,8 @@ class ContactDiaryAddLocationFragment : Fragment(R.layout.contact_diary_add_loca
                     it.hideKeyboard()
                     viewModel.updateLocation(
                         location,
-                        phoneNumber = binding.locationPhoneInput.text.toString().trim(),
-                        emailAddress = binding.locationEmailInput.text.toString().trim()
+                        phoneNumber = binding.locationPhoneInput.text.toString(),
+                        emailAddress = binding.locationEmailInput.text.toString()
                     )
                 }
             }
@@ -64,8 +64,8 @@ class ContactDiaryAddLocationFragment : Fragment(R.layout.contact_diary_add_loca
                 locationSaveButton.setOnClickListener {
                     it.hideKeyboard()
                     viewModel.addLocation(
-                        phoneNumber = binding.locationPhoneInput.text.toString().trim(),
-                        emailAddress = binding.locationEmailInput.text.toString().trim()
+                        phoneNumber = binding.locationPhoneInput.text.toString(),
+                        emailAddress = binding.locationEmailInput.text.toString()
                     )
                 }
             }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationViewModel.kt
index 3f0b7c7ab96dfecadf57e861e7a475b3ad9f09d9..ca648415609b7a88a35d40c3b53ad836e4a0a5b3 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/location/ContactDiaryAddLocationViewModel.kt
@@ -39,7 +39,7 @@ class ContactDiaryAddLocationViewModel @AssistedInject constructor(
         .asLiveData()
 
     fun locationChanged(value: String) {
-        locationName.value = value.trim()
+        locationName.value = value
     }
 
     fun addLocation(phoneNumber: String, emailAddress: String) = launch(coroutineExceptionHandler) {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt
index f305c29de6d8b2fc9fdc90397f6ac616b4d3d31b..db541a96cecd37aa2d5e3d26e6c7cab90065158d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt
@@ -7,12 +7,10 @@ import androidx.appcompat.widget.Toolbar
 import androidx.core.app.ShareCompat
 import androidx.fragment.app.Fragment
 import de.rki.coronawarnapp.R
-import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.ContactDiaryOverviewAdapter
-import de.rki.coronawarnapp.contactdiary.util.getLocale
-import de.rki.coronawarnapp.contactdiary.util.toFormattedDay
-import de.rki.coronawarnapp.contactdiary.util.toFormattedDayForAccessibility
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewAdapter
 import de.rki.coronawarnapp.databinding.ContactDiaryOverviewFragmentBinding
 import de.rki.coronawarnapp.util.di.AutoInject
+import de.rki.coronawarnapp.util.lists.diffutil.update
 import de.rki.coronawarnapp.util.ui.doNavigate
 import de.rki.coronawarnapp.util.ui.observe2
 import de.rki.coronawarnapp.util.ui.viewBindingLazy
@@ -29,24 +27,20 @@ class ContactDiaryOverviewFragment : Fragment(R.layout.contact_diary_overview_fr
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
-        val adapter = ContactDiaryOverviewAdapter(
-            { it.toFormattedDay(requireContext().getLocale()) },
-            { it.toFormattedDayForAccessibility(requireContext().getLocale()) },
-            { vm.onItemPress(it) }
-        )
 
-        setupMenu(binding.toolbar)
+        val adapter = DiaryOverviewAdapter()
 
         binding.apply {
             contactDiaryOverviewRecyclerview.adapter = adapter
 
+            setupMenu(toolbar)
             toolbar.setNavigationOnClickListener {
                 vm.onBackButtonPress()
             }
         }
 
         vm.listItems.observe2(this) {
-            adapter.setItems(it)
+            adapter.update(it)
         }
 
         vm.routeToScreen.observe2(this) {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt
index c90a2d9856a443a69502c578efb145df438f5123..497b3fbf113c473ef459bed221d068903be99921 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt
@@ -13,7 +13,9 @@ import de.rki.coronawarnapp.contactdiary.model.ContactDiaryPersonEncounter.Durat
 import de.rki.coronawarnapp.contactdiary.retention.ContactDiaryCleanTask
 import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository
 import de.rki.coronawarnapp.contactdiary.ui.exporter.ContactDiaryExporter
-import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.ListItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem
 import de.rki.coronawarnapp.risk.result.AggregatedRiskPerDateResult
 import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
 import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass
@@ -55,8 +57,11 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(
         locationVisitsFlow,
         personEncountersFlow,
         riskLevelPerDateFlow
-    ) { dateList, locationVisitList, personEncounterList, riskLevelPerDateList ->
-        createListItemList(dateList, locationVisitList, personEncounterList, riskLevelPerDateList)
+    ) { dateList, locationVisists, personEncounters, riskLevelPerDateList ->
+        mutableListOf<DiaryOverviewItem>().apply {
+            add(OverviewSubHeaderItem)
+            addAll(createListItemList(dateList, locationVisists, personEncounters, riskLevelPerDateList))
+        }.toList()
     }.asLiveData(dispatcherProvider.Default)
 
     init {
@@ -70,30 +75,27 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(
 
     private fun createListItemList(
         dateList: List<LocalDate>,
-        locationVisitList: List<ContactDiaryLocationVisit>,
-        personEncounterList: List<ContactDiaryPersonEncounter>,
+        visits: List<ContactDiaryLocationVisit>,
+        encounters: List<ContactDiaryPersonEncounter>,
         riskLevelPerDateList: List<AggregatedRiskPerDateResult>
-    ): List<ListItem> {
+    ): List<DiaryOverviewItem> {
         Timber.v(
-            "createListItemList(dateList=$dateList, " +
-                "locationVisitList=$locationVisitList, " +
-                "personEncounterList=$personEncounterList)" +
-                "riskLevelPerDateList=$riskLevelPerDateList"
+            "createListItemList(dateList=%s, visits=%s, encounters=%s, riskLevelPerDateList=%s",
+            dateList,
+            visits,
+            encounters,
+            riskLevelPerDateList
         )
-        return dateList
-            .map {
-                ListItem(it)
-                    .apply {
-                        data.addPersonEncountersForDate(personEncounterList, date)
-                        data.addLocationVisitsForDate(locationVisitList, date)
-                        risk = riskLevelPerDateList
-                            .firstOrNull { riskLevelPerDate -> riskLevelPerDate.day == it }
-                            ?.toRisk(data.isNotEmpty())
-                    }
-            }
+        return dateList.map { date ->
+            val dayData = getEncountersForDate(encounters, date) + getVisitsForDate(visits, date)
+            val risk = riskLevelPerDateList
+                .firstOrNull { riskLevelPerDate -> riskLevelPerDate.day == date }
+                ?.toRisk(dayData.isNotEmpty())
+            DayOverviewItem(date = date, data = dayData, risk = risk) { onItemPress(it) }
+        }
     }
 
-    private fun AggregatedRiskPerDateResult.toRisk(locationOrPerson: Boolean): ListItem.Risk {
+    private fun AggregatedRiskPerDateResult.toRisk(locationOrPerson: Boolean): DayOverviewItem.Risk {
         @StringRes val title: Int
         @StringRes var body: Int = R.string.contact_diary_risk_body
         @DrawableRes val drawableId: Int
@@ -114,50 +116,46 @@ class ContactDiaryOverviewViewModel @AssistedInject constructor(
             drawableId = R.drawable.ic_low_risk_alert
         }
 
-        return ListItem.Risk(title, body, bodyExtend, drawableId)
+        return DayOverviewItem.Risk(title, body, bodyExtend, drawableId)
     }
 
-    private fun MutableList<ListItem.Data>.addPersonEncountersForDate(
+    private fun getEncountersForDate(
         personEncounterList: List<ContactDiaryPersonEncounter>,
         date: LocalDate
-    ) {
-        this += personEncounterList
-            .filter { personEncounter -> personEncounter.date == date }
-            .map { personEncounter ->
-                ListItem.Data(
-                    R.drawable.ic_contact_diary_person_item,
-                    name = personEncounter.contactDiaryPerson.fullName,
-                    duration = null,
-                    attributes = getPersonAttributes(personEncounter),
-                    circumstances = personEncounter.circumstances,
-                    ListItem.Type.PERSON
-                )
-            }
-    }
+    ) = personEncounterList
+        .filter { personEncounter -> personEncounter.date == date }
+        .map { personEncounter ->
+            DayOverviewItem.Data(
+                R.drawable.ic_contact_diary_person_item,
+                name = personEncounter.contactDiaryPerson.fullName,
+                duration = null,
+                attributes = getPersonAttributes(personEncounter),
+                circumstances = personEncounter.circumstances,
+                DayOverviewItem.Type.PERSON
+            )
+        }
 
-    private fun MutableList<ListItem.Data>.addLocationVisitsForDate(
+    private fun getVisitsForDate(
         locationVisitList: List<ContactDiaryLocationVisit>,
         date: LocalDate
-    ) {
-        this += locationVisitList
-            .filter { locationVisit -> locationVisit.date == date }
-            .map { locationVisit ->
-                ListItem.Data(
-                    R.drawable.ic_contact_diary_location_item,
-                    locationVisit.contactDiaryLocation.locationName,
-                    duration = locationVisit.duration,
-                    attributes = null,
-                    circumstances = locationVisit.circumstances,
-                    ListItem.Type.LOCATION
-                )
-            }
-    }
+    ) = locationVisitList
+        .filter { locationVisit -> locationVisit.date == date }
+        .map { locationVisit ->
+            DayOverviewItem.Data(
+                R.drawable.ic_contact_diary_location_item,
+                locationVisit.contactDiaryLocation.locationName,
+                duration = locationVisit.duration,
+                attributes = null,
+                circumstances = locationVisit.circumstances,
+                DayOverviewItem.Type.LOCATION
+            )
+        }
 
     fun onBackButtonPress() {
         routeToScreen.postValue(ContactDiaryOverviewNavigationEvents.NavigateToMainActivity)
     }
 
-    fun onItemPress(listItem: ListItem) {
+    fun onItemPress(listItem: DayOverviewItem) {
         routeToScreen.postValue(ContactDiaryOverviewNavigationEvents.NavigateToContactDiaryDayFragment(listItem.date))
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt
deleted file mode 100644
index e58c708ef1b935e6a1a3e0f091cedec570a230cf..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-package de.rki.coronawarnapp.contactdiary.ui.overview.adapter
-
-import android.view.ViewGroup
-import androidx.core.view.isGone
-import de.rki.coronawarnapp.R
-import de.rki.coronawarnapp.contactdiary.util.clearAndAddAll
-import de.rki.coronawarnapp.databinding.ContactDiaryOverviewListItemBinding
-import de.rki.coronawarnapp.ui.lists.BaseAdapter
-import de.rki.coronawarnapp.util.lists.BindableVH
-import org.joda.time.LocalDate
-
-class ContactDiaryOverviewAdapter(
-    private val dateFormatter: (LocalDate) -> String,
-    private val dateFormatterForAccessibility: (LocalDate) -> String,
-    private val onItemSelectionListener: (ListItem) -> Unit
-) : BaseAdapter<ContactDiaryOverviewAdapter.OverviewElementHolder>() {
-
-    private val elements: MutableList<ListItem> = mutableListOf()
-
-    fun setItems(elements: List<ListItem>) {
-        this.elements.clearAndAddAll(elements)
-        notifyDataSetChanged()
-    }
-
-    override fun getItemCount() = elements.size
-
-    override fun onCreateBaseVH(parent: ViewGroup, viewType: Int): OverviewElementHolder = OverviewElementHolder(parent)
-
-    override fun onBindBaseVH(holder: OverviewElementHolder, position: Int, payloads: MutableList<Any>) =
-        holder.bind(elements[position], payloads)
-
-    inner class OverviewElementHolder(parent: ViewGroup) :
-        BaseAdapter.VH(R.layout.contact_diary_overview_list_item, parent),
-        BindableVH<ListItem, ContactDiaryOverviewListItemBinding> {
-
-        private val nestedItemAdapter by lazy { ContactDiaryOverviewNestedAdapter() }
-
-        override val viewBinding: Lazy<ContactDiaryOverviewListItemBinding> =
-            lazy { ContactDiaryOverviewListItemBinding.bind(itemView) }
-
-        override val onBindData: ContactDiaryOverviewListItemBinding.(item: ListItem, payloads: List<Any>) -> Unit =
-            { item, _ ->
-                contactDiaryOverviewNestedRecyclerView.adapter = nestedItemAdapter
-                contactDiaryOverviewNestedRecyclerView.suppressLayout(true)
-                contactDiaryOverviewElementBody.setOnClickListener { onItemSelectionListener(item) }
-
-                contactDiaryOverviewElementBody.contentDescription = dateFormatterForAccessibility(item.date)
-
-                contactDiaryOverviewElementName.apply {
-                    text = dateFormatter(item.date)
-                }
-
-                contactDiaryOverviewNestedElementGroup.isGone = item.data.isEmpty()
-                nestedItemAdapter.setItems(item.data)
-
-                contactDiaryOverviewNestedListItemRisk.apply {
-                    item.risk?.let {
-                        this.contactDiaryOverviewRiskItem.isGone = false
-                        this.contactDiaryOverviewItemRiskTitle.text = context.getString(it.title)
-                        this.contactDiaryOverviewRiskItemImage.setImageResource(it.drawableId)
-
-                        val sb = StringBuilder().append(context.getString(it.body))
-
-                        it.bodyExtended?.let { extend ->
-                            sb.appendLine().append(context.getString(extend))
-                        }
-
-                        this.contactDiaryOverviewItemRiskBody.text = sb
-                    } ?: run { this.contactDiaryOverviewRiskItem.isGone = true }
-                }
-            }
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/DiaryOverviewAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/DiaryOverviewAdapter.kt
new file mode 100644
index 0000000000000000000000000000000000000000..43d8d0a0aa5ee0d61c04ee5c4bce058f310af275
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/DiaryOverviewAdapter.kt
@@ -0,0 +1,41 @@
+package de.rki.coronawarnapp.contactdiary.ui.overview.adapter
+
+import android.view.ViewGroup
+import androidx.annotation.LayoutRes
+import androidx.viewbinding.ViewBinding
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewVH
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderVH
+import de.rki.coronawarnapp.util.lists.BindableVH
+import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffUtilAdapter
+import de.rki.coronawarnapp.util.lists.diffutil.AsyncDiffer
+import de.rki.coronawarnapp.util.lists.modular.ModularAdapter
+import de.rki.coronawarnapp.util.lists.modular.mods.DataBinderMod
+import de.rki.coronawarnapp.util.lists.modular.mods.StableIdMod
+import de.rki.coronawarnapp.util.lists.modular.mods.TypedVHCreatorMod
+
+class DiaryOverviewAdapter :
+    ModularAdapter<DiaryOverviewAdapter.ItemVH<DiaryOverviewItem, ViewBinding>>(),
+    AsyncDiffUtilAdapter<DiaryOverviewItem> {
+
+    override val asyncDiffer: AsyncDiffer<DiaryOverviewItem> = AsyncDiffer(adapter = this)
+
+    init {
+        modules.addAll(
+            listOf(
+                StableIdMod(data),
+                DataBinderMod<DiaryOverviewItem, ItemVH<DiaryOverviewItem, ViewBinding>>(data),
+                TypedVHCreatorMod({ data[it] is DayOverviewItem }) { DayOverviewVH(it) },
+                TypedVHCreatorMod({ data[it] is OverviewSubHeaderItem }) { OverviewSubHeaderVH(it) },
+            )
+        )
+    }
+
+    override fun getItemCount(): Int = data.size
+
+    abstract class ItemVH<Item : DiaryOverviewItem, VB : ViewBinding>(
+        @LayoutRes layoutRes: Int,
+        parent: ViewGroup
+    ) : ModularAdapter.VH(layoutRes, parent), BindableVH<Item, VB>
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/DiaryOverviewItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/DiaryOverviewItem.kt
new file mode 100644
index 0000000000000000000000000000000000000000..fdd230356340fe70d541d5d4b9d95acb86f53c52
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/DiaryOverviewItem.kt
@@ -0,0 +1,5 @@
+package de.rki.coronawarnapp.contactdiary.ui.overview.adapter
+
+import de.rki.coronawarnapp.util.lists.HasStableId
+
+interface DiaryOverviewItem : HasStableId
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt
similarity index 77%
rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt
rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt
index 0185b24a95bed3906b7f1764a0129f2fb0478c97..adeb5f4ab50a89894610b09b4fbf56f144456a6b 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt
@@ -1,4 +1,4 @@
-package de.rki.coronawarnapp.contactdiary.ui.overview.adapter
+package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day
 
 import android.view.View
 import android.view.ViewGroup
@@ -10,11 +10,11 @@ import de.rki.coronawarnapp.ui.lists.BaseAdapter
 import de.rki.coronawarnapp.util.lists.BindableVH
 import org.joda.time.Duration
 
-class ContactDiaryOverviewNestedAdapter : BaseAdapter<ContactDiaryOverviewNestedAdapter.NestedItemViewHolder>() {
+class DayDataNestedAdapter : BaseAdapter<DayDataNestedAdapter.NestedItemViewHolder>() {
 
-    private val dataList: MutableList<ListItem.Data> = mutableListOf()
+    private val dataList: MutableList<DayOverviewItem.Data> = mutableListOf()
 
-    fun setItems(dataList: List<ListItem.Data>) {
+    fun setItems(dataList: List<DayOverviewItem.Data>) {
         this.dataList.clearAndAddAll(dataList)
         notifyDataSetChanged()
     }
@@ -29,17 +29,19 @@ class ContactDiaryOverviewNestedAdapter : BaseAdapter<ContactDiaryOverviewNested
 
     inner class NestedItemViewHolder(parent: ViewGroup) :
         BaseAdapter.VH(R.layout.contact_diary_overview_nested_list_item, parent),
-        BindableVH<ListItem.Data, ContactDiaryOverviewNestedListItemBinding> {
+        BindableVH<DayOverviewItem.Data, ContactDiaryOverviewNestedListItemBinding> {
         override val viewBinding: Lazy<ContactDiaryOverviewNestedListItemBinding> =
             lazy { ContactDiaryOverviewNestedListItemBinding.bind(itemView) }
 
-        override val onBindData: ContactDiaryOverviewNestedListItemBinding.(item: ListItem.Data, payloads: List<Any>)
-        -> Unit = { key, _ ->
+        override val onBindData: ContactDiaryOverviewNestedListItemBinding.(
+            item: DayOverviewItem.Data,
+            payloads: List<Any>
+        ) -> Unit = { key, _ ->
             contactDiaryOverviewElementImage.setImageResource(key.drawableId)
             contactDiaryOverviewElementName.text = key.name
             contactDiaryOverviewElementName.contentDescription = when (key.type) {
-                ListItem.Type.LOCATION -> context.getString(R.string.accessibility_location, key.name)
-                ListItem.Type.PERSON -> context.getString(R.string.accessibility_person, key.name)
+                DayOverviewItem.Type.LOCATION -> context.getString(R.string.accessibility_location, key.name)
+                DayOverviewItem.Type.PERSON -> context.getString(R.string.accessibility_person, key.name)
             }
             val attributes = getAttributes(key.duration, key.attributes, key.circumstances)
             if (attributes.isNotEmpty()) {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ListItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt
similarity index 61%
rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ListItem.kt
rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt
index f155c87bccc2d84c968fdc4f45504ef4e4e3060c..983df3ff3294df13cabf7fb507b7f9c186752936 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ListItem.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewItem.kt
@@ -1,15 +1,19 @@
-package de.rki.coronawarnapp.contactdiary.ui.overview.adapter
+package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day
 
 import androidx.annotation.DrawableRes
 import androidx.annotation.StringRes
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewItem
 import org.joda.time.Duration
 import org.joda.time.LocalDate
 
-data class ListItem(
-    val date: LocalDate
-) {
-    val data: MutableList<Data> = mutableListOf()
-    var risk: Risk? = null
+data class DayOverviewItem(
+    val date: LocalDate,
+    val data: List<Data>,
+    val risk: Risk?,
+    val onItemSelectionListener: (DayOverviewItem) -> Unit
+) : DiaryOverviewItem {
+
+    override val stableId: Long = date.hashCode().toLong()
 
     data class Data(
         @DrawableRes val drawableId: Int,
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c52682b1c41d7b0830a63ca2bd77c147237b2bb1
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayOverviewVH.kt
@@ -0,0 +1,55 @@
+package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day
+
+import android.view.ViewGroup
+import androidx.core.view.isGone
+import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewAdapter
+import de.rki.coronawarnapp.contactdiary.util.getLocale
+import de.rki.coronawarnapp.contactdiary.util.toFormattedDay
+import de.rki.coronawarnapp.contactdiary.util.toFormattedDayForAccessibility
+import de.rki.coronawarnapp.databinding.ContactDiaryOverviewListItemBinding
+
+class DayOverviewVH(parent: ViewGroup) :
+    DiaryOverviewAdapter.ItemVH<DayOverviewItem, ContactDiaryOverviewListItemBinding>(
+        layoutRes = R.layout.contact_diary_overview_list_item,
+        parent = parent
+    ) {
+
+    private val nestedItemAdapter by lazy { DayDataNestedAdapter() }
+
+    override val viewBinding: Lazy<ContactDiaryOverviewListItemBinding> =
+        lazy { ContactDiaryOverviewListItemBinding.bind(itemView) }
+
+    override val onBindData: ContactDiaryOverviewListItemBinding.(item: DayOverviewItem, payloads: List<Any>) -> Unit =
+        { item, _ ->
+            contactDiaryOverviewNestedRecyclerView.adapter = nestedItemAdapter
+            contactDiaryOverviewNestedRecyclerView.suppressLayout(true)
+            contactDiaryOverviewElementBody.setOnClickListener { item.onItemSelectionListener(item) }
+
+            contactDiaryOverviewElementBody.contentDescription =
+                item.date.toFormattedDayForAccessibility(context.getLocale())
+
+            contactDiaryOverviewElementName.apply {
+                text = item.date.toFormattedDay(context.getLocale())
+            }
+
+            contactDiaryOverviewNestedElementGroup.isGone = item.data.isEmpty()
+            nestedItemAdapter.setItems(item.data)
+
+            contactDiaryOverviewNestedListItemRisk.apply {
+                item.risk?.let {
+                    this.contactDiaryOverviewRiskItem.isGone = false
+                    this.contactDiaryOverviewItemRiskTitle.text = context.getString(it.title)
+                    this.contactDiaryOverviewRiskItemImage.setImageResource(it.drawableId)
+
+                    val sb = StringBuilder().append(context.getString(it.body))
+
+                    it.bodyExtended?.let { extend ->
+                        sb.appendLine().append(context.getString(extend))
+                    }
+
+                    this.contactDiaryOverviewItemRiskBody.text = sb
+                } ?: run { this.contactDiaryOverviewRiskItem.isGone = true }
+            }
+        }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/subheader/OverviewSubHeaderItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/subheader/OverviewSubHeaderItem.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8609770446bc478ba912a9b5a4e8b40c5151e901
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/subheader/OverviewSubHeaderItem.kt
@@ -0,0 +1,8 @@
+package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader
+
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewItem
+
+object OverviewSubHeaderItem : DiaryOverviewItem {
+
+    override val stableId: Long = this.hashCode().toLong()
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/subheader/OverviewSubHeaderVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/subheader/OverviewSubHeaderVH.kt
new file mode 100644
index 0000000000000000000000000000000000000000..35923cdc632852cd3f1661060e24a3612da3a679
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/subheader/OverviewSubHeaderVH.kt
@@ -0,0 +1,23 @@
+package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader
+
+import android.view.ViewGroup
+import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.DiaryOverviewAdapter
+import de.rki.coronawarnapp.databinding.ContactDiaryOverviewListSubheaderBinding
+
+class OverviewSubHeaderVH(parent: ViewGroup) :
+    DiaryOverviewAdapter.ItemVH<OverviewSubHeaderItem, ContactDiaryOverviewListSubheaderBinding>(
+        layoutRes = R.layout.contact_diary_overview_list_subheader,
+        parent = parent
+    ) {
+
+    override val viewBinding: Lazy<ContactDiaryOverviewListSubheaderBinding> =
+        lazy { ContactDiaryOverviewListSubheaderBinding.bind(itemView) }
+
+    override val onBindData: ContactDiaryOverviewListSubheaderBinding.(
+        item: OverviewSubHeaderItem,
+        payloads: List<Any>
+    ) -> Unit = { _, _ ->
+        // NOOP
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonFragment.kt
index ae8716f9fd970d59bf157a4dce9b2813f602e256..e54cede4df8d31fdc7e82a5d309f34f7b4803c32 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonFragment.kt
@@ -54,8 +54,8 @@ class ContactDiaryAddPersonFragment :
                     it.hideKeyboard()
                     viewModel.updatePerson(
                         person,
-                        phoneNumber = binding.personPhoneNumberInput.text.toString().trim(),
-                        emailAddress = binding.personEmailInput.text.toString().trim()
+                        phoneNumber = binding.personPhoneNumberInput.text.toString(),
+                        emailAddress = binding.personEmailInput.text.toString()
                     )
                 }
             }
@@ -65,8 +65,8 @@ class ContactDiaryAddPersonFragment :
             binding.personSaveButton.setOnClickListener {
                 it.hideKeyboard()
                 viewModel.addPerson(
-                    phoneNumber = binding.personPhoneNumberInput.text.toString().trim(),
-                    emailAddress = binding.personEmailInput.text.toString().trim()
+                    phoneNumber = binding.personPhoneNumberInput.text.toString(),
+                    emailAddress = binding.personEmailInput.text.toString()
                 )
             }
         }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonViewModel.kt
index f00889cfb4be8cc61242db89f5a8bc90f1fb271a..34eb68336c02d2300dd75fda71a27ce5310af72d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/person/ContactDiaryAddPersonViewModel.kt
@@ -38,7 +38,7 @@ class ContactDiaryAddPersonViewModel @AssistedInject constructor(
         .asLiveData()
 
     fun nameChanged(value: String) {
-        name.value = value.trim()
+        name.value = value
     }
 
     fun addPerson(phoneNumber: String, emailAddress: String) = launch(coroutineExceptionHandler) {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/AnalyticsModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/AnalyticsModule.kt
index 52c57ad78da01d091532ca8f6e0c890e83f7d205..0fdf9704e2e08868c4d3d8ab2b95389cb4fdfeba 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/AnalyticsModule.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/AnalyticsModule.kt
@@ -7,6 +7,7 @@ import dagger.multibindings.IntoSet
 import de.rki.coronawarnapp.datadonation.analytics.modules.DonorModule
 import de.rki.coronawarnapp.datadonation.analytics.modules.clientmetadata.ClientMetadataDonor
 import de.rki.coronawarnapp.datadonation.analytics.modules.exposureriskmetadata.ExposureRiskMetadataDonor
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionDonor
 import de.rki.coronawarnapp.datadonation.analytics.modules.registeredtest.TestResultDonor
 import de.rki.coronawarnapp.datadonation.analytics.modules.exposurewindows.AnalyticsExposureWindowDonor
 import de.rki.coronawarnapp.datadonation.analytics.modules.usermetadata.UserMetadataDonor
@@ -45,9 +46,9 @@ class AnalyticsModule {
     @Provides
     fun newExposureWindows(module: AnalyticsExposureWindowDonor): DonorModule = module
 
-//    @IntoSet
-//    @Provides
-//    fun keySubmission(module: KeySubmissionStateDonor): DonorModule = module
+    @IntoSet
+    @Provides
+    fun keySubmission(module: AnalyticsKeySubmissionDonor): DonorModule = module
 
     @IntoSet
     @Provides
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/common/PpaDataExtensions.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/common/PpaDataExtensions.kt
index 5a24f909c2f226fb4088d51c13a5d1ce8f47a0fd..2a898e5a0a3d943d7321b3d111dbe5d86dfecaab 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/common/PpaDataExtensions.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/common/PpaDataExtensions.kt
@@ -2,6 +2,8 @@ package de.rki.coronawarnapp.datadonation.analytics.common
 
 import androidx.annotation.StringRes
 import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.risk.RiskLevelResult
+import de.rki.coronawarnapp.risk.RiskState
 import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData
 
 val PpaData.PPAAgeGroup.labelStringRes: Int
@@ -64,3 +66,9 @@ val PpaData.PPAFederalState.federalStateShortName: String
             "PpaData.PPAFederalState.UNRECOGNIZED has no short name"
         )
     }
+
+fun RiskLevelResult.toMetadataRiskLevel(): PpaData.PPARiskLevel =
+    when (riskState) {
+        RiskState.INCREASED_RISK -> PpaData.PPARiskLevel.RISK_LEVEL_HIGH
+        else -> PpaData.PPARiskLevel.RISK_LEVEL_LOW
+    }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionCollector.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionCollector.kt
new file mode 100644
index 0000000000000000000000000000000000000000..138e26fa4fd7b0076569ae63527f2ca5d0479487
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionCollector.kt
@@ -0,0 +1,110 @@
+package de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission
+
+import de.rki.coronawarnapp.datadonation.analytics.common.toMetadataRiskLevel
+import de.rki.coronawarnapp.datadonation.analytics.storage.AnalyticsSettings
+import de.rki.coronawarnapp.risk.RiskLevelSettings
+import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
+import de.rki.coronawarnapp.risk.tryLatestResultsWithDefaults
+import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData
+import de.rki.coronawarnapp.util.TimeStamper
+import kotlinx.coroutines.flow.first
+import org.joda.time.Duration
+import javax.inject.Inject
+
+class AnalyticsKeySubmissionCollector @Inject constructor(
+    private val timeStamper: TimeStamper,
+    private val analyticsSettings: AnalyticsSettings,
+    private val analyticsKeySubmissionStorage: AnalyticsKeySubmissionStorage,
+    private val riskLevelStorage: RiskLevelStorage,
+    private val riskLevelSettings: RiskLevelSettings
+) {
+
+    fun reset() {
+        analyticsKeySubmissionStorage.clear()
+    }
+
+    fun reportPositiveTestResultReceived() {
+        if (disabled) return
+        analyticsKeySubmissionStorage.testResultReceivedAt.update { timeStamper.nowUTC.millis }
+    }
+
+    suspend fun reportTestRegistered() {
+        if (disabled) return
+        val testRegisteredAt = timeStamper.nowUTC
+        analyticsKeySubmissionStorage.testRegisteredAt.update { testRegisteredAt.millis }
+
+        val lastRiskResult = riskLevelStorage
+            .latestAndLastSuccessful
+            .first()
+            .tryLatestResultsWithDefaults()
+            .lastCalculated
+        val riskLevelAtRegistration = lastRiskResult.toMetadataRiskLevel()
+        analyticsKeySubmissionStorage.riskLevelAtTestRegistration.update {
+            riskLevelAtRegistration.number
+        }
+
+        if (riskLevelAtRegistration == PpaData.PPARiskLevel.RISK_LEVEL_HIGH) {
+            riskLevelSettings.lastChangeToHighRiskLevelTimestamp?.let {
+                val hours = Duration(
+                    it,
+                    testRegisteredAt
+                ).standardHours.toInt()
+                analyticsKeySubmissionStorage.hoursSinceHighRiskWarningAtTestRegistration.update {
+                    hours
+                }
+            }
+        }
+    }
+
+    fun reportSubmitted() {
+        if (disabled) return
+        analyticsKeySubmissionStorage.submitted.update { true }
+        analyticsKeySubmissionStorage.submittedAt.update { timeStamper.nowUTC.millis }
+    }
+
+    fun reportSubmittedInBackground() {
+        if (disabled) return
+        analyticsKeySubmissionStorage.submittedInBackground.update { true }
+    }
+
+    fun reportSubmittedAfterCancel() {
+        if (disabled) return
+        analyticsKeySubmissionStorage.submittedAfterCancel.update { true }
+    }
+
+    fun reportSubmittedAfterSymptomFlow() {
+        if (disabled) return
+        analyticsKeySubmissionStorage.submittedAfterSymptomFlow.update { true }
+    }
+
+    fun reportLastSubmissionFlowScreen(screen: Screen) {
+        if (disabled) return
+        analyticsKeySubmissionStorage.lastSubmissionFlowScreen.update { screen.code }
+    }
+
+    fun reportAdvancedConsentGiven() {
+        if (disabled) return
+        analyticsKeySubmissionStorage.advancedConsentGiven.update { true }
+    }
+
+    fun reportConsentWithdrawn() {
+        if (disabled) return
+        analyticsKeySubmissionStorage.advancedConsentGiven.update { false }
+    }
+
+    fun reportRegisteredWithTeleTAN() {
+        if (disabled) return
+        analyticsKeySubmissionStorage.registeredWithTeleTAN.update { true }
+    }
+
+    private val disabled: Boolean
+        get() = !analyticsSettings.analyticsEnabled.value
+}
+
+enum class Screen(val code: Int) {
+    UNKNOWN(PpaData.PPALastSubmissionFlowScreen.SUBMISSION_FLOW_SCREEN_UNKNOWN_VALUE),
+    TEST_RESULT(PpaData.PPALastSubmissionFlowScreen.SUBMISSION_FLOW_SCREEN_TEST_RESULT_VALUE),
+    WARN_OTHERS(PpaData.PPALastSubmissionFlowScreen.SUBMISSION_FLOW_SCREEN_WARN_OTHERS_VALUE),
+    SYMPTOMS(PpaData.PPALastSubmissionFlowScreen.SUBMISSION_FLOW_SCREEN_SYMPTOMS_VALUE),
+    SYMPTOM_ONSET(PpaData.PPALastSubmissionFlowScreen.SUBMISSION_FLOW_SCREEN_SYMPTOM_ONSET_VALUE)
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionDonor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionDonor.kt
new file mode 100644
index 0000000000000000000000000000000000000000..43be380985e0258331d73625b7e037fe7dcc700b
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionDonor.kt
@@ -0,0 +1,81 @@
+package de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission
+
+import androidx.annotation.VisibleForTesting
+import de.rki.coronawarnapp.datadonation.analytics.modules.DonorModule
+import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData
+import de.rki.coronawarnapp.util.TimeStamper
+import org.joda.time.Duration
+import org.joda.time.Instant
+import javax.inject.Inject
+import javax.inject.Singleton
+
+@Singleton
+class AnalyticsKeySubmissionDonor @Inject constructor(
+    val repository: AnalyticsKeySubmissionRepository,
+    private val timeStamper: TimeStamper
+) : DonorModule {
+
+    override suspend fun beginDonation(request: DonorModule.Request): DonorModule.Contribution {
+
+        val hours = request.currentConfig.analytics.hoursSinceTestResultToSubmitKeySubmissionMetadata
+        val timeSinceTestResultToSubmit = Duration.standardHours(hours.toLong())
+
+        return if (shouldSubmitData(timeSinceTestResultToSubmit)) {
+            object : DonorModule.Contribution {
+                override suspend fun injectData(protobufContainer: PpaData.PPADataAndroid.Builder) {
+                    val data = createContribution()
+                    protobufContainer.addKeySubmissionMetadataSet(data)
+                }
+
+                override suspend fun finishDonation(successful: Boolean) {
+                    if (successful) repository.reset()
+                }
+            }
+        } else {
+            AnalyticsKeySubmissionNoContribution
+        }
+    }
+
+    private fun createContribution() =
+        PpaData.PPAKeySubmissionMetadata.newBuilder()
+            .setAdvancedConsentGiven(repository.advancedConsentGiven)
+            .setDaysSinceMostRecentDateAtRiskLevelAtTestRegistration(
+                repository.daysSinceMostRecentDateAtRiskLevelAtTestRegistration
+            )
+            .setHoursSinceHighRiskWarningAtTestRegistration(
+                repository.hoursSinceHighRiskWarningAtTestRegistration
+            )
+            .setHoursSinceTestResult(repository.hoursSinceTestResult)
+            .setHoursSinceTestRegistration(repository.hoursSinceTestRegistration)
+            .setLastSubmissionFlowScreenValue(repository.lastSubmissionFlowScreen)
+            .setSubmitted(repository.submitted)
+            .setSubmittedAfterSymptomFlow(repository.submittedAfterSymptomFlow)
+            .setSubmittedAfterCancel(repository.submittedAfterCancel)
+            .setSubmittedInBackground(repository.submittedInBackground)
+            .setSubmittedWithTeleTAN(repository.submittedWithTeleTAN)
+
+    private fun shouldSubmitData(timeSinceTestResultToSubmit: Duration): Boolean {
+        return positiveTestResultReceived && (
+            keysSubmitted || enoughTimeHasPassedSinceResult(timeSinceTestResultToSubmit)
+            )
+    }
+
+    private val positiveTestResultReceived: Boolean
+        get() = repository.testResultReceivedAt > 0
+
+    private val keysSubmitted: Boolean
+        get() = repository.submitted
+
+    private fun enoughTimeHasPassedSinceResult(timeSinceTestResultToSubmit: Duration): Boolean =
+        timeStamper.nowUTC.minus(timeSinceTestResultToSubmit) > Instant.ofEpochMilli(repository.testResultReceivedAt)
+
+    override suspend fun deleteData() {
+        repository.reset()
+    }
+}
+
+@VisibleForTesting
+object AnalyticsKeySubmissionNoContribution : DonorModule.Contribution {
+    override suspend fun injectData(protobufContainer: PpaData.PPADataAndroid.Builder) = Unit
+    override suspend fun finishDonation(successful: Boolean) = Unit
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionRepository.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8982f68c86e54aa6a91873ed41244e1446ac447c
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionRepository.kt
@@ -0,0 +1,59 @@
+package de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission
+
+import de.rki.coronawarnapp.risk.RiskLevelSettings
+import org.joda.time.Duration
+import org.joda.time.Instant
+import javax.inject.Inject
+import kotlin.math.max
+
+class AnalyticsKeySubmissionRepository @Inject constructor(
+    private val storage: AnalyticsKeySubmissionStorage,
+    private val riskLevelSettings: RiskLevelSettings
+) {
+    val testResultReceivedAt: Long
+        get() = storage.testResultReceivedAt.value
+
+    private val testRegisteredAt: Long
+        get() = storage.testRegisteredAt.value
+
+    val submitted: Boolean
+        get() = storage.submitted.value
+
+    private val submittedAt: Long
+        get() = storage.submittedAt.value
+
+    val submittedInBackground: Boolean
+        get() = submitted && storage.submittedInBackground.value
+
+    val submittedAfterCancel: Boolean
+        get() = submitted && storage.submittedAfterCancel.value
+
+    val submittedAfterSymptomFlow: Boolean
+        get() = submitted && storage.submittedAfterSymptomFlow.value
+
+    val submittedWithTeleTAN: Boolean
+        get() = submitted && storage.registeredWithTeleTAN.value
+
+    val lastSubmissionFlowScreen: Int
+        get() = storage.lastSubmissionFlowScreen.value
+
+    val advancedConsentGiven: Boolean
+        get() = storage.advancedConsentGiven.value
+
+    val hoursSinceTestResult: Int
+        get() = Duration.millis(max(submittedAt - testResultReceivedAt, 0)).toStandardHours().hours
+
+    val hoursSinceTestRegistration: Int
+        get() = Duration.millis(max(submittedAt - testRegisteredAt, 0L)).toStandardHours().hours
+
+    val daysSinceMostRecentDateAtRiskLevelAtTestRegistration: Int
+        get() = Duration(
+            riskLevelSettings.lastChangeCheckedRiskLevelTimestamp,
+            Instant.ofEpochMilli(testRegisteredAt)
+        ).standardDays.toInt()
+
+    val hoursSinceHighRiskWarningAtTestRegistration: Int
+        get() = storage.hoursSinceHighRiskWarningAtTestRegistration.value
+
+    fun reset() = storage.clear()
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionStorage.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionStorage.kt
new file mode 100644
index 0000000000000000000000000000000000000000..085c5fe727216fee0a3f963e2548ac568412cf70
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionStorage.kt
@@ -0,0 +1,79 @@
+package de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission
+
+import android.content.Context
+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
+
+class AnalyticsKeySubmissionStorage @Inject constructor(
+    @AppContext val context: Context
+) {
+    private val prefs by lazy {
+        context.getSharedPreferences("analytics_key_submission_localdata", Context.MODE_PRIVATE)
+    }
+
+    val testResultReceivedAt = prefs.createFlowPreference(
+        key = "analytics_key_submission_testResultReceivedAt",
+        defaultValue = -1L
+    )
+
+    val testRegisteredAt = prefs.createFlowPreference(
+        key = "analytics_key_submission_testRegisteredAt",
+        defaultValue = -1L
+    )
+
+    val submitted = prefs.createFlowPreference(
+        key = "analytics_key_submission_submitted",
+        defaultValue = false
+    )
+
+    val submittedAt = prefs.createFlowPreference(
+        key = "analytics_key_submission_submittedAt",
+        defaultValue = -1L
+    )
+
+    val submittedInBackground = prefs.createFlowPreference(
+        key = "analytics_key_submission_submittedInBackground",
+        defaultValue = false
+    )
+
+    val submittedAfterCancel = prefs.createFlowPreference(
+        key = "analytics_key_submission_submittedAfterCancel",
+        defaultValue = false
+    )
+
+    val submittedAfterSymptomFlow = prefs.createFlowPreference(
+        key = "analytics_key_submission_submittedAfterSymptomFlow",
+        defaultValue = false
+    )
+
+    val lastSubmissionFlowScreen = prefs.createFlowPreference(
+        key = "analytics_key_submission_lastSubmissionFlowScreen",
+        defaultValue = Screen.UNKNOWN.code
+    )
+
+    val advancedConsentGiven = prefs.createFlowPreference(
+        key = "analytics_key_submission_advancedConsentGiven",
+        defaultValue = false
+    )
+
+    val registeredWithTeleTAN = prefs.createFlowPreference(
+        key = "analytics_key_submission_registeredWithTeleTAN",
+        defaultValue = false
+    )
+
+    val riskLevelAtTestRegistration = prefs.createFlowPreference(
+        key = "analytics_key_submission_riskLevelAtTestRegistration",
+        defaultValue = -1
+    )
+
+    val hoursSinceHighRiskWarningAtTestRegistration = prefs.createFlowPreference(
+        key = "analytics_key_submission_hoursSinceHighRiskWarningAtTestRegistration",
+        defaultValue = -1
+    )
+
+    fun clear() {
+        prefs.clearAndNotify()
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/KeySubmissionStateDonor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/KeySubmissionStateDonor.kt
deleted file mode 100644
index 7b254464f587eb6eba7da463db17f63ec3358f26..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/KeySubmissionStateDonor.kt
+++ /dev/null
@@ -1,27 +0,0 @@
-package de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission
-
-import de.rki.coronawarnapp.datadonation.analytics.modules.DonorModule
-import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData
-import javax.inject.Inject
-import javax.inject.Singleton
-
-@Singleton
-class KeySubmissionStateDonor @Inject constructor() : DonorModule {
-
-    override suspend fun beginDonation(request: DonorModule.Request): DonorModule.Contribution {
-        // TODO
-        return object : DonorModule.Contribution {
-            override suspend fun injectData(protobufContainer: PpaData.PPADataAndroid.Builder) {
-                // TODO
-            }
-
-            override suspend fun finishDonation(successful: Boolean) {
-                // TODO
-            }
-        }
-    }
-
-    override suspend fun deleteData() {
-        // TODO
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/storage/AnalyticsSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/storage/AnalyticsSettings.kt
index 9c240c16e7269c78546b020de46897865fa7d329..d8cd04f462c68679ded5ef54d7b502db2c69b2d3 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/storage/AnalyticsSettings.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/storage/AnalyticsSettings.kt
@@ -90,6 +90,11 @@ class AnalyticsSettings @Inject constructor(
         defaultValue = false
     )
 
+    val lastOnboardingVersionCode = prefs.createFlowPreference(
+        key = PKEY_ONBOARDED_VERSION_CODE,
+        defaultValue = 0L
+    )
+
     fun clear() = prefs.clearAndNotify()
 
     companion object {
@@ -99,5 +104,6 @@ class AnalyticsSettings @Inject constructor(
         private const val PKEY_USERINFO_DISTRICT = "userinfo.district"
         private const val PKEY_LAST_SUBMITTED_TIMESTAMP = "analytics.submission.timestamp"
         private const val PKEY_ANALYTICS_ENABLED = "analytics.enabled"
+        private const val PKEY_ONBOARDED_VERSION_CODE = "analytics.onboarding.versionCode"
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/storage/TestResultDonorSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/storage/TestResultDonorSettings.kt
index 84f9345ae6220ae41a2eb9e4162698849608bfad..11b76710c64c003c3c22715ce996e2afaee6d2f3 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/storage/TestResultDonorSettings.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/datadonation/analytics/storage/TestResultDonorSettings.kt
@@ -1,8 +1,8 @@
 package de.rki.coronawarnapp.datadonation.analytics.storage
 
 import android.content.Context
+import de.rki.coronawarnapp.datadonation.analytics.common.toMetadataRiskLevel
 import de.rki.coronawarnapp.risk.RiskLevelResult
-import de.rki.coronawarnapp.risk.RiskState
 import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData
 import de.rki.coronawarnapp.util.di.AppContext
 import de.rki.coronawarnapp.util.formatter.TestResult
@@ -77,12 +77,6 @@ class TestResultDonorSettings @Inject constructor(
 
     fun clear() = prefs.clearAndNotify()
 
-    private fun RiskLevelResult.toMetadataRiskLevel(): PpaData.PPARiskLevel =
-        when (riskState) {
-            RiskState.INCREASED_RISK -> PpaData.PPARiskLevel.RISK_LEVEL_HIGH
-            else -> PpaData.PPARiskLevel.RISK_LEVEL_LOW
-        }
-
     companion object {
         private const val PREFS_KEY_TEST_SCANNED_AFTER_CONSENT = "testResultDonor.testScannedAfterConsent"
         private const val PREFS_KEY_TEST_RESULT_AT_REGISTRATION = "testResultDonor.testResultAtRegistration"
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoFragment.kt
index 55741441fd6f7001ce7351a8818b5f91a2236a1b..5e090ad1587a0af310a71330d55f70c8cdc643d9 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoFragment.kt
@@ -4,6 +4,7 @@ import android.os.Bundle
 import android.view.View
 import android.view.ViewGroup
 import android.view.accessibility.AccessibilityEvent
+import androidx.activity.OnBackPressedCallback
 import androidx.core.view.isGone
 import androidx.fragment.app.Fragment
 import androidx.navigation.fragment.navArgs
@@ -52,16 +53,21 @@ class NewReleaseInfoFragment : Fragment(R.layout.new_release_info_screen_fragmen
             recyclerView.adapter = ItemAdapter(getItems())
         }
 
+        // Override android back button to bypass the infinite loop
+        val backCallback = object : OnBackPressedCallback(true) {
+            override fun handleOnBackPressed() = vm.onNextButtonClick()
+        }
+        requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backCallback)
+
         vm.routeToScreen.observe2(this) {
-            if (it is NewReleaseInfoNavigationEvents.CloseScreen) {
-                if (args.comesFromInfoScreen) {
+            when (it) {
+                is NewReleaseInfoNavigationEvents.CloseScreen ->
                     popBackStack()
-                } else {
+                is NewReleaseInfoNavigationEvents.NavigateToOnboardingDeltaAnalyticsFragment ->
                     doNavigate(
                         NewReleaseInfoFragmentDirections
                             .actionNewReleaseInfoFragmentToOnboardingDeltaAnalyticsFragment()
                     )
-                }
             }
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoNavigationEvents.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoNavigationEvents.kt
index e485871c4a3ab9b3e9a8ffec4acc29b42bdf5877..d9fe60928f22b5b3fd49f3df5cf690a7c89dcd25 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoNavigationEvents.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoNavigationEvents.kt
@@ -2,4 +2,5 @@ package de.rki.coronawarnapp.release
 
 sealed class NewReleaseInfoNavigationEvents {
     object CloseScreen : NewReleaseInfoNavigationEvents()
+    object NavigateToOnboardingDeltaAnalyticsFragment : NewReleaseInfoNavigationEvents()
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoViewModel.kt
index 476bbd9bdf9b5c47276ac58fb1a8746d2d7c512e..6a872ed31b89446f265d33b3e10c6cdb4f75198d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/release/NewReleaseInfoViewModel.kt
@@ -4,6 +4,7 @@ import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import de.rki.coronawarnapp.BuildConfig
 import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.datadonation.analytics.storage.AnalyticsSettings
 import de.rki.coronawarnapp.environment.BuildConfigWrap
 import de.rki.coronawarnapp.main.CWASettings
 import de.rki.coronawarnapp.ui.SingleLiveEvent
@@ -15,7 +16,8 @@ import timber.log.Timber
 
 class NewReleaseInfoViewModel @AssistedInject constructor(
     dispatcherProvider: DispatcherProvider,
-    private val settings: CWASettings
+    private val appSettings: CWASettings,
+    private val analyticsSettings: AnalyticsSettings
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     val routeToScreen: SingleLiveEvent<NewReleaseInfoNavigationEvents> = SingleLiveEvent()
@@ -23,8 +25,12 @@ class NewReleaseInfoViewModel @AssistedInject constructor(
     val title = R.string.release_info_version_title.toResolvingString(BuildConfig.VERSION_NAME)
 
     fun onNextButtonClick() {
-        settings.lastChangelogVersion.update { BuildConfigWrap.VERSION_CODE }
-        routeToScreen.postValue(NewReleaseInfoNavigationEvents.CloseScreen)
+        appSettings.lastChangelogVersion.update { BuildConfigWrap.VERSION_CODE }
+        if (analyticsSettings.lastOnboardingVersionCode.value == 0L) {
+            routeToScreen.postValue(NewReleaseInfoNavigationEvents.NavigateToOnboardingDeltaAnalyticsFragment)
+        } else {
+            routeToScreen.postValue(NewReleaseInfoNavigationEvents.CloseScreen)
+        }
     }
 
     fun getItems(
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 b377e9942036e23f79b16100f3c8dd26d99f3bc7..a746ab02146edcda3bf436f4f485e7cd93b318ed 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
@@ -85,6 +85,10 @@ class RiskLevelChangeDetector @Inject constructor(
 
             surveys.resetSurvey(Surveys.Type.HIGH_RISK_ENCOUNTER)
         }
+
+        if (oldRiskState == RiskState.LOW_RISK && newRiskState == RiskState.INCREASED_RISK) {
+            riskLevelSettings.lastChangeToHighRiskLevelTimestamp = newResult.calculatedAt
+        }
     }
 
     companion object {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelSettings.kt
index 4e2eb9cf9883e8bf9d5e557df24e9dca5123a89f..652905a0d75ad32267f8c1e4c1bb19764a9087ca 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelSettings.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelSettings.kt
@@ -33,9 +33,19 @@ class RiskLevelSettings @Inject constructor(
             putLong(PKEY_LAST_CHANGE_CHECKED_RISKLEVEL_TIMESTAMP, value?.millis ?: 0L)
         }
 
+    var lastChangeToHighRiskLevelTimestamp: Instant?
+        get() = prefs.getLong(PKEY_LAST_CHANGE_TO_HIGH_RISKLEVEL_TIMESTAMP, 0L).let {
+            if (it != 0L) Instant.ofEpochMilli(it) else null
+        }
+        set(value) = prefs.edit {
+            putLong(PKEY_LAST_CHANGE_TO_HIGH_RISKLEVEL_TIMESTAMP, value?.millis ?: 0L)
+        }
+
     companion object {
         private const val NAME_SHARED_PREFS = "risklevel_localdata"
         private const val PKEY_RISKLEVEL_CALC_LAST_CONFIG_ID = "risklevel.config.identifier.last"
         private const val PKEY_LAST_CHANGE_CHECKED_RISKLEVEL_TIMESTAMP = "PKEY_RISKLEVEL_CALC_LAST_CONFIG_ID"
+        private const val PKEY_LAST_CHANGE_TO_HIGH_RISKLEVEL_TIMESTAMP =
+            "PKEY_RISKLEVEL_CALC_LAST_CHANGE_TO_HIGH_RISKLEVEL"
     }
 }
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 37dfa4e4733cfe44b327076495d62c4edfa62235..fc70b8d81502d4dba3bb15c703443778ce207dd2 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
@@ -1,6 +1,7 @@
 package de.rki.coronawarnapp.submission
 
 import androidx.annotation.VisibleForTesting
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.deadman.DeadmanNotificationScheduler
 import de.rki.coronawarnapp.exception.ExceptionCategory
 import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException
@@ -33,7 +34,8 @@ class SubmissionRepository @Inject constructor(
     @AppScope private val scope: CoroutineScope,
     private val timeStamper: TimeStamper,
     private val tekHistoryStorage: TEKHistoryStorage,
-    private val deadmanNotificationScheduler: DeadmanNotificationScheduler
+    private val deadmanNotificationScheduler: DeadmanNotificationScheduler,
+    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 ) {
     private val testResultReceivedDateFlowInternal = MutableStateFlow(Date())
     val testResultReceivedDateFlow: Flow<Date> = testResultReceivedDateFlowInternal
@@ -124,6 +126,8 @@ class SubmissionRepository @Inject constructor(
         updateTestResult(registrationData.testResult)
         LocalData.devicePairingSuccessfulTimestamp(timeStamper.nowUTC.millis)
         BackgroundNoise.getInstance().scheduleDummyPattern()
+        analyticsKeySubmissionCollector.reportTestRegistered()
+        analyticsKeySubmissionCollector.reportRegisteredWithTeleTAN()
     }
 
     suspend fun asyncRegisterDeviceViaGUID(guid: String): TestResult {
@@ -132,6 +136,7 @@ class SubmissionRepository @Inject constructor(
         updateTestResult(registrationData.testResult)
         LocalData.devicePairingSuccessfulTimestamp(timeStamper.nowUTC.millis)
         BackgroundNoise.getInstance().scheduleDummyPattern()
+        analyticsKeySubmissionCollector.reportTestRegistered()
         return registrationData.testResult
     }
 
@@ -147,6 +152,7 @@ class SubmissionRepository @Inject constructor(
 
         if (testResult == TestResult.POSITIVE) {
             LocalData.isAllowedToSubmitDiagnosisKeys(true)
+            analyticsKeySubmissionCollector.reportPositiveTestResultReceived()
             deadmanNotificationScheduler.cancelScheduledWork()
         }
 
@@ -175,6 +181,7 @@ class SubmissionRepository @Inject constructor(
     fun removeTestFromDevice() {
         submissionSettings.hasViewedTestResult.update { false }
         submissionSettings.hasGivenConsent.update { false }
+        analyticsKeySubmissionCollector.reset()
         revokeConsentToSubmission()
         LocalData.registrationToken(null)
         LocalData.devicePairingSuccessfulTimestamp(0L)
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 7e37f823d25bb2cc9ca30e03bafad9215db86e59..2bd1faa295558ef435ff124e78fc28ac8ea8c828 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
@@ -2,6 +2,7 @@ package de.rki.coronawarnapp.submission.task
 
 import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
 import de.rki.coronawarnapp.appconfig.AppConfigProvider
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException
 import de.rki.coronawarnapp.notification.ShareTestResultNotificationService
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
@@ -26,6 +27,7 @@ import timber.log.Timber
 import javax.inject.Inject
 import javax.inject.Provider
 
+@Suppress("LongParameterList")
 class SubmissionTask @Inject constructor(
     private val playbook: Playbook,
     private val appConfigProvider: AppConfigProvider,
@@ -35,7 +37,8 @@ class SubmissionTask @Inject constructor(
     private val autoSubmission: AutoSubmission,
     private val timeStamper: TimeStamper,
     private val shareTestResultNotificationService: ShareTestResultNotificationService,
-    private val testResultAvailableNotificationService: TestResultAvailableNotificationService
+    private val testResultAvailableNotificationService: TestResultAvailableNotificationService,
+    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 ) : Task<DefaultProgress, SubmissionTask.Result> {
 
     private val internalProgress = ConflatedBroadcastChannel<DefaultProgress>()
@@ -43,14 +46,20 @@ class SubmissionTask @Inject constructor(
 
     private var isCanceled = false
 
+    private var inBackground = false
+
     override suspend fun run(arguments: Task.Arguments): Result {
         try {
             Timber.tag(TAG).d("Running with arguments=%s", arguments)
             arguments as Arguments
 
-            if (arguments.checkUserActivity && hasRecentUserActivity()) {
-                Timber.tag(TAG).w("User has recently been active in submission, skipping submission.")
-                return Result(state = Result.State.SKIPPED)
+            if (arguments.checkUserActivity) {
+                if (hasRecentUserActivity()) {
+                    Timber.tag(TAG).w("User has recently been active in submission, skipping submission.")
+                    return Result(state = Result.State.SKIPPED)
+                } else {
+                    inBackground = true
+                }
             }
 
             if (!submissionSettings.hasGivenConsent.value) {
@@ -141,6 +150,9 @@ class SubmissionTask @Inject constructor(
         Timber.tag(TAG).d("Submitting %s", submissionData)
         playbook.submit(submissionData)
 
+        analyticsKeySubmissionCollector.reportSubmitted()
+        if (inBackground) analyticsKeySubmissionCollector.reportSubmittedInBackground()
+
         Timber.tag(TAG).d("Submission successful, deleting submission data.")
         tekHistoryStorage.clear()
         submissionSettings.symptoms.update { null }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsFragment.kt
index 8727896d40b0c3a0b5dc66dd67e45e14d2edcdee..cd2d2231d7a44bb90c1a2ec4a51690bcf5aecb73 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsFragment.kt
@@ -26,8 +26,8 @@ class OnboardingAnalyticsFragment : Fragment(R.layout.fragment_onboarding_ppa),
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
         binding.apply {
-            onboardingButtonNext.setOnClickListener { viewModel.onNextButtonClick() }
-            onboardingButtonDisable.setOnClickListener { viewModel.onDisableClick() }
+            onboardingButtonNext.setOnClickListener { viewModel.onProceed(true) }
+            onboardingButtonDisable.setOnClickListener { viewModel.onProceed(false) }
             onboardingButtonBack.buttonIcon.setOnClickListener { requireActivity().onBackPressed() }
 
             federalStateRow.setOnClickListener {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsViewModel.kt
index ea44c1ea5a76bd05879084de383d0439d6b91041..600c2405f51c51168d9355634cc2f233bdc43d4a 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsViewModel.kt
@@ -7,18 +7,23 @@ import dagger.assisted.AssistedInject
 import de.rki.coronawarnapp.datadonation.analytics.Analytics
 import de.rki.coronawarnapp.datadonation.analytics.common.Districts
 import de.rki.coronawarnapp.datadonation.analytics.storage.AnalyticsSettings
+import de.rki.coronawarnapp.environment.BuildConfigWrap
 import de.rki.coronawarnapp.ui.SingleLiveEvent
+import de.rki.coronawarnapp.util.coroutine.AppScope
 import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
 import de.rki.coronawarnapp.util.flow.combine
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
 import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
+import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.launch
 
 class OnboardingAnalyticsViewModel @AssistedInject constructor(
-    settings: AnalyticsSettings,
-    dispatcherProvider: DispatcherProvider,
+    private val settings: AnalyticsSettings,
+    private val dispatcherProvider: DispatcherProvider,
     private val analytics: Analytics,
-    val districts: Districts
+    val districts: Districts,
+    @AppScope private val appScope: CoroutineScope
 ) : CWAViewModel() {
 
     val completedOnboardingEvent = SingleLiveEvent<Unit>()
@@ -32,19 +37,11 @@ class OnboardingAnalyticsViewModel @AssistedInject constructor(
         districtsList.singleOrNull { it.districtId == id }
     }.asLiveData(dispatcherProvider.IO)
 
-    fun onNextButtonClick() {
-        launch {
-            analytics.setAnalyticsEnabled(enabled = true)
+    fun onProceed(enable: Boolean) {
+        appScope.launch(context = dispatcherProvider.IO) {
+            analytics.setAnalyticsEnabled(enabled = enable)
         }
-
-        completedOnboardingEvent.postValue(Unit)
-    }
-
-    fun onDisableClick() {
-        launch {
-            analytics.setAnalyticsEnabled(enabled = false)
-        }
-
+        settings.lastOnboardingVersionCode.update { BuildConfigWrap.VERSION_CODE }
         completedOnboardingEvent.postValue(Unit)
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingDeltaAnalyticsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingDeltaAnalyticsFragment.kt
index e6e9ba278c958b0c58fd8e89619de7a0f1d12751..8efd0a961f244f665593e68517fbe20438e21050 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingDeltaAnalyticsFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/onboarding/OnboardingDeltaAnalyticsFragment.kt
@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.ui.onboarding
 import android.os.Bundle
 import android.view.View
 import android.view.accessibility.AccessibilityEvent
+import androidx.activity.OnBackPressedCallback
 import androidx.fragment.app.Fragment
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentOnboardingDeltaPpaBinding
@@ -26,9 +27,15 @@ class OnboardingDeltaAnalyticsFragment : Fragment(R.layout.fragment_onboarding_d
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
+
+        val backCallback = object : OnBackPressedCallback(true) {
+            override fun handleOnBackPressed() = viewModel.onProceed(false)
+        }
+        requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backCallback)
+
         binding.apply {
-            onboardingButtonNext.setOnClickListener { viewModel.onNextButtonClick() }
-            onboardingButtonDisable.setOnClickListener { viewModel.onDisableClick() }
+            onboardingButtonNext.setOnClickListener { viewModel.onProceed(true) }
+            onboardingButtonDisable.setOnClickListener { viewModel.onProceed(false) }
             onboardingButtonBack.buttonIcon.setOnClickListener { requireActivity().onBackPressed() }
 
             federalStateRow.setOnClickListener {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetViewModel.kt
index 2ecbb6d1767484e24eb7c0bf5df2dee0ceef5617..e9128ec667395042f895de51c2d97e5fa0712b22 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetViewModel.kt
@@ -7,10 +7,10 @@ import de.rki.coronawarnapp.exception.ExceptionCategory
 import de.rki.coronawarnapp.exception.reporting.report
 import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient
 import de.rki.coronawarnapp.notification.ShareTestResultNotificationService
-import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.ui.SingleLiveEvent
 import de.rki.coronawarnapp.util.DataReset
 import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
+import de.rki.coronawarnapp.util.shortcuts.AppShortcutsHelper
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
 import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
 import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
@@ -19,7 +19,7 @@ class SettingsResetViewModel @AssistedInject constructor(
     dispatcherProvider: DispatcherProvider,
     private val dataReset: DataReset,
     private val shareTestResultNotificationService: ShareTestResultNotificationService,
-    private val submissionRepository: SubmissionRepository
+    private val shortcutsHelper: AppShortcutsHelper
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     val clickEvent: SingleLiveEvent<SettingsEvents> = SingleLiveEvent()
@@ -51,6 +51,7 @@ class SettingsResetViewModel @AssistedInject constructor(
             shareTestResultNotificationService.resetSharePositiveTestResultNotification()
 
             dataReset.clearAllLocalData()
+            shortcutsHelper.removeAppShortcut()
             clickEvent.postValue(SettingsEvents.GoToOnboarding)
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModel.kt
index f65e937154ccab0401ca5e1be6b7460652a4ced9..1428e0f4fc1d1a3862db37a91653c4a934ae0704 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModel.kt
@@ -4,6 +4,7 @@ import androidx.lifecycle.asLiveData
 import com.google.android.gms.common.api.ApiException
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.nearby.modules.tekhistory.TEKHistoryProvider
 import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository
 import de.rki.coronawarnapp.submission.SubmissionRepository
@@ -13,13 +14,13 @@ import de.rki.coronawarnapp.util.ui.SingleLiveEvent
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
 import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
 import timber.log.Timber
-import kotlin.Exception
 
 class SubmissionConsentViewModel @AssistedInject constructor(
     private val submissionRepository: SubmissionRepository,
     interoperabilityRepository: InteroperabilityRepository,
     dispatcherProvider: DispatcherProvider,
-    private val tekHistoryProvider: TEKHistoryProvider
+    private val tekHistoryProvider: TEKHistoryProvider,
+    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     val routeToScreen: SingleLiveEvent<SubmissionNavigationEvents> = SingleLiveEvent()
@@ -29,6 +30,7 @@ class SubmissionConsentViewModel @AssistedInject constructor(
 
     fun onConsentButtonClick() {
         submissionRepository.giveConsentToSubmission()
+        analyticsKeySubmissionCollector.reportAdvancedConsentGiven()
         launch {
             try {
                 val preAuthorized = tekHistoryProvider.preAuthorizeExposureKeyHistory()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableViewModel.kt
index a5f0aa610694698ce6a3edcc50589ac7fa9938a5..89e79f6b9d6cf2ddfcb3d1dd0e091b7bf008d8b7 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/resultavailable/SubmissionTestResultAvailableViewModel.kt
@@ -7,6 +7,7 @@ import androidx.navigation.NavDirections
 import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.exception.ExceptionCategory
 import de.rki.coronawarnapp.exception.reporting.report
 import de.rki.coronawarnapp.submission.SubmissionRepository
@@ -23,7 +24,8 @@ class SubmissionTestResultAvailableViewModel @AssistedInject constructor(
     dispatcherProvider: DispatcherProvider,
     tekHistoryUpdaterFactory: TEKHistoryUpdater.Factory,
     submissionRepository: SubmissionRepository,
-    private val autoSubmission: AutoSubmission
+    private val autoSubmission: AutoSubmission,
+    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     val routeToScreen = SingleLiveEvent<NavDirections>()
@@ -113,6 +115,7 @@ class SubmissionTestResultAvailableViewModel @AssistedInject constructor(
                 tekHistoryUpdater.updateTEKHistoryOrRequestPermission()
             } else {
                 Timber.d("routeToScreen:SubmissionTestResultNoConsentFragment")
+                analyticsKeySubmissionCollector.reportConsentWithdrawn()
                 showKeysRetrievalProgress.postValue(false)
                 routeToScreen.postValue(
                     SubmissionTestResultAvailableFragmentDirections
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/symptoms/calendar/SubmissionSymptomCalendarViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/symptoms/calendar/SubmissionSymptomCalendarViewModel.kt
index 85af09cf324159ace2456eb156beb62d47331314..249f7e24e09d257c549b102d63de380f2d2e014f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/symptoms/calendar/SubmissionSymptomCalendarViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/symptoms/calendar/SubmissionSymptomCalendarViewModel.kt
@@ -8,6 +8,8 @@ import dagger.assisted.Assisted
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import de.rki.coronawarnapp.bugreporting.reportProblem
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.Screen
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.Symptoms
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -23,7 +25,8 @@ class SubmissionSymptomCalendarViewModel @AssistedInject constructor(
     @Assisted val symptomIndication: Symptoms.Indication,
     dispatcherProvider: DispatcherProvider,
     private val submissionRepository: SubmissionRepository,
-    private val autoSubmission: AutoSubmission
+    private val autoSubmission: AutoSubmission,
+    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     private val symptomStartInternal = MutableStateFlow<Symptoms.StartOf?>(null)
@@ -84,18 +87,19 @@ class SubmissionSymptomCalendarViewModel @AssistedInject constructor(
                 startOfSymptoms = symptomStartInternal.value
             ).also { Timber.tag(TAG).v("Symptoms updated to %s", it) }
         }
-        performSubmission()
+        performSubmission { analyticsKeySubmissionCollector.reportSubmittedAfterSymptomFlow() }
     }
 
     fun onCancelConfirmed() {
         Timber.d("onCancelConfirmed() clicked on calendar screen.")
-        performSubmission()
+        performSubmission { analyticsKeySubmissionCollector.reportSubmittedAfterCancel() }
     }
 
-    private fun performSubmission() {
+    private fun performSubmission(onSubmitted: () -> Unit) {
         launch {
             try {
                 autoSubmission.runSubmissionNow()
+                onSubmitted()
             } catch (e: Exception) {
                 Timber.tag(TAG).e(e, "performSubmission() failed.")
             } finally {
@@ -110,6 +114,7 @@ class SubmissionSymptomCalendarViewModel @AssistedInject constructor(
 
     fun onNewUserActivity() {
         Timber.d("onNewUserActivity()")
+        analyticsKeySubmissionCollector.reportLastSubmissionFlowScreen(Screen.SYMPTOM_ONSET)
         autoSubmission.updateLastSubmissionUserActivity()
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/symptoms/introduction/SubmissionSymptomIntroductionViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/symptoms/introduction/SubmissionSymptomIntroductionViewModel.kt
index 9bed16e6f78f7ebe9a84c14d4e3bf5b1868cea74..5d422d14af934617dc1bc59bb78338e361f0678d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/symptoms/introduction/SubmissionSymptomIntroductionViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/symptoms/introduction/SubmissionSymptomIntroductionViewModel.kt
@@ -4,6 +4,8 @@ import androidx.lifecycle.asLiveData
 import androidx.navigation.NavDirections
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.Screen
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.Symptoms
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -17,7 +19,8 @@ import timber.log.Timber
 class SubmissionSymptomIntroductionViewModel @AssistedInject constructor(
     dispatcherProvider: DispatcherProvider,
     private val submissionRepository: SubmissionRepository,
-    private val autoSubmission: AutoSubmission
+    private val autoSubmission: AutoSubmission,
+    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     private val symptomIndicationInternal = MutableStateFlow<Symptoms.Indication?>(null)
@@ -105,6 +108,7 @@ class SubmissionSymptomIntroductionViewModel @AssistedInject constructor(
 
     fun onNewUserActivity() {
         Timber.d("onNewUserActivity()")
+        analyticsKeySubmissionCollector.reportLastSubmissionFlowScreen(Screen.SYMPTOMS)
         autoSubmission.updateLastSubmissionUserActivity()
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultConsentGivenViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultConsentGivenViewModel.kt
index 43592aca074da95e7fca9d478207f9508dd9875a..a1277d4c81ad3c6ffd3e2a4df94e520c82891496 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultConsentGivenViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultConsentGivenViewModel.kt
@@ -4,6 +4,8 @@ import androidx.lifecycle.LiveData
 import androidx.lifecycle.asLiveData
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.Screen
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -21,6 +23,7 @@ class SubmissionTestResultConsentGivenViewModel @AssistedInject constructor(
     private val submissionRepository: SubmissionRepository,
     private val autoSubmission: AutoSubmission,
     private val testResultAvailableNotificationService: TestResultAvailableNotificationService,
+    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector,
     dispatcherProvider: DispatcherProvider
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
@@ -69,6 +72,7 @@ class SubmissionTestResultConsentGivenViewModel @AssistedInject constructor(
 
     fun onNewUserActivity() {
         Timber.d("onNewUserActivity()")
+        analyticsKeySubmissionCollector.reportLastSubmissionFlowScreen(Screen.TEST_RESULT)
         autoSubmission.updateLastSubmissionUserActivity()
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt
index 46577e1306d66b5a93e1da1aebab986539d7f6c1..2b1fa0d5a3a26617ed28f3031f18c4e5ef0fb68a 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentFragment.kt
@@ -9,6 +9,7 @@ import androidx.fragment.app.Fragment
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentSubmissionTestResultPositiveNoConsentBinding
 import de.rki.coronawarnapp.util.di.AutoInject
+import de.rki.coronawarnapp.util.shortcuts.AppShortcutsHelper
 import de.rki.coronawarnapp.util.ui.doNavigate
 import de.rki.coronawarnapp.util.ui.observe2
 import de.rki.coronawarnapp.util.ui.viewBindingLazy
@@ -24,6 +25,7 @@ class SubmissionTestResultNoConsentFragment :
     Fragment(R.layout.fragment_submission_test_result_positive_no_consent),
     AutoInject {
 
+    @Inject lateinit var appShortcutsHelper: AppShortcutsHelper
     @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
     private val viewModel: SubmissionTestResultNoConsentViewModel by cwaViewModels { viewModelFactory }
     private val binding: FragmentSubmissionTestResultPositiveNoConsentBinding by viewBindingLazy()
@@ -31,8 +33,6 @@ class SubmissionTestResultNoConsentFragment :
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
         super.onViewCreated(view, savedInstanceState)
 
-        viewModel.onTestOpened()
-
         val backCallback = object : OnBackPressedCallback(true) {
             override fun handleOnBackPressed() {
                 showCancelDialog()
@@ -60,6 +60,8 @@ class SubmissionTestResultNoConsentFragment :
 
     override fun onResume() {
         super.onResume()
+        appShortcutsHelper.removeAppShortcut()
+        viewModel.onTestOpened()
         binding.submissionTestResultContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT)
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentViewModel.kt
index ae6984fb4adc10cb12eca293448f9afbffd43ad4..49b07dec8537509cf4040c211f5203004102b380 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/testresult/positive/SubmissionTestResultNoConsentViewModel.kt
@@ -4,6 +4,8 @@ import androidx.lifecycle.LiveData
 import androidx.lifecycle.asLiveData
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.Screen
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.ui.submission.testresult.TestResultUIState
@@ -14,7 +16,8 @@ import kotlinx.coroutines.Dispatchers
 
 class SubmissionTestResultNoConsentViewModel @AssistedInject constructor(
     private val submissionRepository: SubmissionRepository,
-    private val testResultAvailableNotificationService: TestResultAvailableNotificationService
+    private val testResultAvailableNotificationService: TestResultAvailableNotificationService,
+    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 ) : CWAViewModel() {
 
     val uiState: LiveData<TestResultUIState> = combine(
@@ -29,6 +32,7 @@ class SubmissionTestResultNoConsentViewModel @AssistedInject constructor(
     }.asLiveData(context = Dispatchers.Default)
 
     fun onTestOpened() {
+        analyticsKeySubmissionCollector.reportLastSubmissionFlowScreen(Screen.TEST_RESULT)
         submissionRepository.setViewedTestResult()
         testResultAvailableNotificationService.cancelTestResultAvailableNotification()
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentFragment.kt
index 0592f38a373238dd7eca3dda0d547bd46f76dc41..4d245b7f5bf0022d5156ccf891cc251e603cd840 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentFragment.kt
@@ -11,6 +11,7 @@ import de.rki.coronawarnapp.tracing.ui.TracingConsentDialog
 import de.rki.coronawarnapp.ui.submission.SubmissionBlockingDialog
 import de.rki.coronawarnapp.util.DialogHelper
 import de.rki.coronawarnapp.util.di.AutoInject
+import de.rki.coronawarnapp.util.shortcuts.AppShortcutsHelper
 import de.rki.coronawarnapp.util.ui.doNavigate
 import de.rki.coronawarnapp.util.ui.observe2
 import de.rki.coronawarnapp.util.ui.viewBindingLazy
@@ -25,6 +26,7 @@ import javax.inject.Inject
 class SubmissionResultPositiveOtherWarningNoConsentFragment :
     Fragment(R.layout.fragment_submission_no_consent_positive_other_warning), AutoInject {
 
+    @Inject lateinit var appShortcutsHelper: AppShortcutsHelper
     @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
     private val viewModel: SubmissionResultPositiveOtherWarningNoConsentViewModel by cwaViewModelsAssisted(
         factoryProducer = { viewModelFactory },
@@ -89,6 +91,8 @@ class SubmissionResultPositiveOtherWarningNoConsentFragment :
 
     override fun onResume() {
         super.onResume()
+        viewModel.onResume()
+        appShortcutsHelper.removeAppShortcut()
         binding.submissionPositiveOtherPrivacyContainer.sendAccessibilityEvent(AccessibilityEvent.TYPE_ANNOUNCEMENT)
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModel.kt
index 9a9befc9f5786f017f5e97c23cc22406497cb42d..c02bbe34e37c171ee8e060def68fd83f9e4362d9 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModel.kt
@@ -7,6 +7,8 @@ import androidx.navigation.NavDirections
 import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.Screen
 import de.rki.coronawarnapp.exception.ExceptionCategory
 import de.rki.coronawarnapp.exception.reporting.report
 import de.rki.coronawarnapp.nearby.ENFClient
@@ -27,7 +29,8 @@ class SubmissionResultPositiveOtherWarningNoConsentViewModel @AssistedInject con
     private val autoSubmission: AutoSubmission,
     tekHistoryUpdaterFactory: TEKHistoryUpdater.Factory,
     interoperabilityRepository: InteroperabilityRepository,
-    private val submissionRepository: SubmissionRepository
+    private val submissionRepository: SubmissionRepository,
+    private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
     val routeToScreen = SingleLiveEvent<NavDirections>()
@@ -115,6 +118,10 @@ class SubmissionResultPositiveOtherWarningNoConsentViewModel @AssistedInject con
         tekHistoryUpdater.handleActivityResult(requestCode, resultCode, data)
     }
 
+    fun onResume() {
+        analyticsKeySubmissionCollector.reportLastSubmissionFlowScreen(Screen.WARN_OTHERS)
+    }
+
     @AssistedFactory
     interface Factory : CWAViewModelFactory<SubmissionResultPositiveOtherWarningNoConsentViewModel> {
         fun create(): SubmissionResultPositiveOtherWarningNoConsentViewModel
diff --git a/Corona-Warn-App/src/main/res/drawable/contact_diary_duration_background_selected.xml b/Corona-Warn-App/src/main/res/drawable/contact_diary_duration_background_selected.xml
index b230c96594d3925ca38a19c3802cfaeb1fd3ebc9..9a9dca8a8dd80db9dd568aa67c778b4d9e81f7b1 100644
--- a/Corona-Warn-App/src/main/res/drawable/contact_diary_duration_background_selected.xml
+++ b/Corona-Warn-App/src/main/res/drawable/contact_diary_duration_background_selected.xml
@@ -4,4 +4,4 @@
     <corners android:radius="@dimen/radius_card" />
     <solid android:color="@color/colorSurface1" />
     <stroke android:width="2dip" android:color="@color/colorAccent" />
-</shape>
\ No newline at end of file
+</shape>
diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_add_location_fragment.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_add_location_fragment.xml
index 1e1ec8dbe6c01241da337b636491fd0a4209fc6a..b2b7e568adcf48b11c6cf027b5eeb4d1e2966ca6 100644
--- a/Corona-Warn-App/src/main/res/layout/contact_diary_add_location_fragment.xml
+++ b/Corona-Warn-App/src/main/res/layout/contact_diary_add_location_fragment.xml
@@ -63,6 +63,7 @@
                 android:id="@+id/location_name_input_edit"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:maxLength="250"
                 android:imeOptions="actionNext"
                 android:inputType="textCapWords" />
 
@@ -85,6 +86,7 @@
                 android:id="@+id/location_phone_input"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:maxLength="250"
                 android:imeOptions="actionNext"
                 android:inputType="phone" />
 
@@ -107,6 +109,7 @@
                 android:id="@+id/location_email_input"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:maxLength="250"
                 android:imeOptions="actionDone"
                 android:inputType="textEmailAddress" />
 
diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_add_person_fragment.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_add_person_fragment.xml
index 2163a98fb554e92ad433c7b14c37fcca9376e0bd..b77f760528b0e1d2d540246c7e0d9de019734410 100644
--- a/Corona-Warn-App/src/main/res/layout/contact_diary_add_person_fragment.xml
+++ b/Corona-Warn-App/src/main/res/layout/contact_diary_add_person_fragment.xml
@@ -62,6 +62,7 @@
                 android:id="@+id/person_name_input"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:maxLength="250"
                 android:imeOptions="actionNext"
                 android:inputType="textCapWords" />
 
@@ -84,6 +85,7 @@
                 android:id="@+id/person_phone_number_input"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:maxLength="250"
                 android:imeOptions="actionNext"
                 android:inputType="phone" />
 
@@ -107,6 +109,7 @@
                 android:id="@+id/person_email_input"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
+                android:maxLength="250"
                 android:imeOptions="actionDone"
                 android:inputType="textEmailAddress" />
 
diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_duration_picker_dialog_fragment.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_duration_picker_dialog_fragment.xml
index b222b3df117080fe443a2c65fe306bc5ca791ba2..882b3e971552b8a976f45642f1cc8cda17d39a67 100644
--- a/Corona-Warn-App/src/main/res/layout/contact_diary_duration_picker_dialog_fragment.xml
+++ b/Corona-Warn-App/src/main/res/layout/contact_diary_duration_picker_dialog_fragment.xml
@@ -59,31 +59,28 @@
         app:layout_constraintStart_toEndOf="@+id/divider"
         app:layout_constraintTop_toBottomOf="@+id/title" />
 
-    <Button
+    <com.google.android.material.button.MaterialButton
         android:id="@+id/cancel_button"
-        style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog"
+        style="@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flush"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginTop="29dp"
-        android:layout_marginBottom="@dimen/spacing_small"
-        android:letterSpacing="0.08"
+        android:layout_marginEnd="8dp"
         android:text="@string/duration_dialog_cancel_button"
-        android:textColor="@color/colorTextTint"
-        app:layout_constraintBottom_toBottomOf="parent"
+        android:textColor="@color/colorAccent"
+        app:layout_constraintBottom_toBottomOf="@+id/ok_button"
         app:layout_constraintEnd_toStartOf="@id/ok_button"
-        app:layout_constraintTop_toBottomOf="@+id/minutes" />
+        app:layout_constraintTop_toTopOf="@+id/ok_button" />
 
-    <Button
+    <com.google.android.material.button.MaterialButton
         android:id="@+id/ok_button"
-        style="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog"
+        style="@style/Widget.MaterialComponents.Button.TextButton.Dialog.Flush"
         android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginTop="29dp"
-        android:layout_marginEnd="26dp"
-        android:layout_marginBottom="@dimen/spacing_small"
-        android:letterSpacing="0.08"
+        android:layout_marginTop="24dp"
+        android:layout_marginEnd="8dp"
+        android:layout_marginBottom="8dp"
         android:text="@string/duration_dialog_ok_button"
-        android:textColor="@color/colorTextTint"
+        android:textColor="@color/colorAccent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:layout_constraintTop_toBottomOf="@+id/minutes" />
diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_fragment.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_fragment.xml
index f3fcf6ff7ae6c678d7ab130f34a86075b8638b16..140a4c3982e094a187e809252263df3147963cd3 100644
--- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_fragment.xml
+++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_fragment.xml
@@ -1,65 +1,27 @@
 <?xml version="1.0" encoding="utf-8"?>
-<layout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools">
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/content_container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:contentDescription="@string/contact_diary_overview_title"
+    android:orientation="vertical">
 
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/content_container"
+    <androidx.appcompat.widget.Toolbar
+        android:id="@+id/toolbar"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:contentDescription="@string/contact_diary_overview_title">
+        android:layout_height="wrap_content"
+        android:background="@color/colorBackground"
+        app:popupTheme="@style/CWAToolbar.Menu"
+        app:title="@string/contact_diary_overview_title" />
 
-        <androidx.appcompat.widget.Toolbar
-            android:id="@+id/toolbar"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:background="@color/colorBackground"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toTopOf="parent"
-            app:popupTheme="@style/CWAToolbar.Menu"
-            app:title="@string/contact_diary_overview_title" />
-
-        <TextView
-            android:id="@+id/contact_diary_overview_subtitle"
-            style="@style/subtitleMedium"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/spacing_small"
-            android:focusable="true"
-            android:text="@string/contact_diary_overview_subtitle"
-            app:layout_constraintEnd_toEndOf="@id/guideline_end"
-            app:layout_constraintStart_toStartOf="@id/guideline_start"
-            app:layout_constraintTop_toBottomOf="@id/toolbar"
-            tools:text="Tragen Sie ein, mit wem Sie sich getroffen haben und wo Sie gewesen sind." />
-
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/contact_diary_overview_recyclerview"
-            android:layout_width="0dp"
-            android:layout_height="0dp"
-            android:layout_marginTop="@dimen/spacing_small"
-            android:layout_marginBottom="@dimen/spacing_mega_tiny"
-            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintEnd_toEndOf="@id/guideline_end"
-            app:layout_constraintHorizontal_bias="0.0"
-            app:layout_constraintStart_toStartOf="@+id/guideline_start"
-            app:layout_constraintTop_toBottomOf="@+id/contact_diary_overview_subtitle"
-            tools:listitem="@layout/contact_diary_overview_list_item" />
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/guideline_start"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            app:layout_constraintGuide_begin="@dimen/guideline_start" />
-
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/guideline_end"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            app:layout_constraintGuide_end="@dimen/guideline_end" />
-
-    </androidx.constraintlayout.widget.ConstraintLayout>
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/contact_diary_overview_recyclerview"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1"
+        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+        tools:listitem="@layout/contact_diary_overview_list_item" />
 
-</layout>
+</LinearLayout>
diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml
index ee6ea381df3b131608f7b6ad74af1fd75c765b77..6082e367f537a3a4bacfa1a5aae22919e5d5f5d4 100644
--- a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml
+++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_item.xml
@@ -1,94 +1,92 @@
 <?xml version="1.0" encoding="utf-8"?>
-<layout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools">
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/contact_diary_overview_element_body"
+    style="@style/contactDiaryCardRipple"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginStart="24dp"
+    android:layout_marginEnd="24dp"
+    android:layout_marginBottom="@dimen/spacing_tiny"
+    android:focusable="true">
 
-    <androidx.constraintlayout.widget.ConstraintLayout
-        android:id="@+id/contact_diary_overview_element_body"
-        style="@style/contactDiaryCardRipple"
-        android:layout_width="match_parent"
+    <TextView
+        android:id="@+id/contact_diary_overview_element_name"
+        style="@style/contactDiaryListItem"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/spacing_tiny"
-        android:focusable="true">
-
-        <TextView
-            android:id="@+id/contact_diary_overview_element_name"
-            style="@style/contactDiaryListItem"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="@dimen/spacing_small"
-            android:focusable="false"
-            app:layout_constraintBottom_toTopOf="@id/contact_diary_overview_element_guideline"
-            app:layout_constraintEnd_toStartOf="@+id/contact_diary_overview_element_right_arrow"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toTopOf="parent"
-            tools:text="Donnerstag, 01.12.2020" />
-
-        <ImageView
-            android:id="@+id/contact_diary_overview_element_right_arrow"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_marginVertical="@dimen/spacing_tiny"
-            android:layout_marginEnd="@dimen/spacing_small"
-            android:importantForAccessibility="no"
-            android:scaleType="centerInside"
-            android:src="@drawable/ic_contact_diary_right_arrow"
-            app:layout_constraintBottom_toTopOf="@id/contact_diary_overview_element_guideline"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintTop_toTopOf="parent" />
+        android:layout_marginStart="@dimen/spacing_small"
+        android:focusable="false"
+        app:layout_constraintBottom_toTopOf="@id/contact_diary_overview_element_guideline"
+        app:layout_constraintEnd_toStartOf="@+id/contact_diary_overview_element_right_arrow"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="Donnerstag, 01.12.2020" />
 
-        <androidx.constraintlayout.widget.Guideline
-            android:id="@+id/contact_diary_overview_element_guideline"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            app:layout_constraintGuide_begin="@dimen/contact_diary_list_item" />
+    <ImageView
+        android:id="@+id/contact_diary_overview_element_right_arrow"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginVertical="@dimen/spacing_tiny"
+        android:layout_marginEnd="@dimen/spacing_small"
+        android:importantForAccessibility="no"
+        android:scaleType="centerInside"
+        android:src="@drawable/ic_contact_diary_right_arrow"
+        app:layout_constraintBottom_toTopOf="@id/contact_diary_overview_element_guideline"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
 
-        <include
-            android:id="@+id/contact_diary_overview_nested_list_item_risk"
-            layout="@layout/contact_diary_overview_nested_list_item_risk"
-            android:layout_width="match_parent"
-            android:focusable="false"
-            android:layout_height="wrap_content"
-            app:layout_constraintTop_toBottomOf="@id/contact_diary_overview_element_guideline"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toEndOf="parent" />
+    <androidx.constraintlayout.widget.Guideline
+        android:id="@+id/contact_diary_overview_element_guideline"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        app:layout_constraintGuide_begin="@dimen/contact_diary_list_item" />
 
-        <androidx.constraintlayout.widget.Barrier
-            android:id="@+id/contact_diary_overview_barrier"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            app:barrierDirection="bottom"
-            app:barrierAllowsGoneWidgets="false"
-            app:constraint_referenced_ids="contact_diary_overview_element_guideline, contact_diary_overview_nested_list_item_risk"/>
+    <include
+        android:id="@+id/contact_diary_overview_nested_list_item_risk"
+        layout="@layout/contact_diary_overview_nested_list_item_risk"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:focusable="false"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/contact_diary_overview_element_guideline" />
 
-        <View
-            android:id="@+id/contact_diary_overview_element_divider"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/card_divider"
-            android:background="?android:attr/listDivider"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintTop_toBottomOf="@id/contact_diary_overview_barrier"/>
+    <androidx.constraintlayout.widget.Barrier
+        android:id="@+id/contact_diary_overview_barrier"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:barrierAllowsGoneWidgets="false"
+        app:barrierDirection="bottom"
+        app:constraint_referenced_ids="contact_diary_overview_element_guideline, contact_diary_overview_nested_list_item_risk" />
 
-        <androidx.recyclerview.widget.RecyclerView
-            android:id="@+id/contact_diary_overview_nested_recycler_view"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:nestedScrollingEnabled="false"
-            android:paddingVertical="@dimen/spacing_tiny"
-            app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
-            app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"
-            app:layout_constraintBottom_toBottomOf="parent"
-            app:layout_constraintTop_toBottomOf="@id/contact_diary_overview_element_divider" />
+    <View
+        android:id="@+id/contact_diary_overview_element_divider"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/card_divider"
+        android:background="?android:attr/listDivider"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/contact_diary_overview_barrier" />
 
-        <androidx.constraintlayout.widget.Group
-            android:id="@+id/contact_diary_overview_nested_element_group"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            app:constraint_referenced_ids="contact_diary_overview_element_divider,contact_diary_overview_nested_recycler_view"/>
+    <androidx.recyclerview.widget.RecyclerView
+        android:id="@+id/contact_diary_overview_nested_recycler_view"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:nestedScrollingEnabled="false"
+        android:paddingVertical="@dimen/spacing_tiny"
+        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toBottomOf="@id/contact_diary_overview_element_divider" />
 
-    </androidx.constraintlayout.widget.ConstraintLayout>
+    <androidx.constraintlayout.widget.Group
+        android:id="@+id/contact_diary_overview_nested_element_group"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:constraint_referenced_ids="contact_diary_overview_element_divider,contact_diary_overview_nested_recycler_view" />
 
-</layout>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_subheader.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_subheader.xml
new file mode 100644
index 0000000000000000000000000000000000000000..50ff8857dc420ebdc3684d2c25dc76ce27043b72
--- /dev/null
+++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_list_subheader.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    xmlns:tools="http://schemas.android.com/tools">
+
+
+    <TextView
+        android:id="@+id/contact_diary_overview_subtitle"
+        style="@style/subtitleMedium"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:layout_marginStart="24dp"
+        android:layout_marginTop="16dp"
+        android:layout_marginEnd="24dp"
+        android:layout_marginBottom="16dp"
+        android:focusable="true"
+        android:text="@string/contact_diary_overview_subtitle"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="Tragen Sie ein, mit wem Sie sich getroffen haben und wo Sie gewesen sind." />
+
+</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/navigation/nav_graph_onboarding.xml b/Corona-Warn-App/src/main/res/navigation/nav_graph_onboarding.xml
index 3c128a61f3a3f9b98e3b3efcd31e7167af410cf7..e4bcb9b60551fbc18d62f7ac4e364b71fc604136 100644
--- a/Corona-Warn-App/src/main/res/navigation/nav_graph_onboarding.xml
+++ b/Corona-Warn-App/src/main/res/navigation/nav_graph_onboarding.xml
@@ -135,4 +135,4 @@
         android:name="de.rki.coronawarnapp.ui.information.InformationTermsFragment"
         android:label="@layout/fragment_information_terms"
         tools:layout="@layout/fragment_information_terms" />
-</navigation>
\ No newline at end of file
+</navigation>
diff --git a/Corona-Warn-App/src/main/res/values-bg/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values-bg/contact_diary_strings.xml
index 7b9a7397daa1aebab0d499105fe5c82e02457ee4..07fcab5029d5c3969a433ff62e10985f97908bea 100644
--- a/Corona-Warn-App/src/main/res/values-bg/contact_diary_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-bg/contact_diary_strings.xml
@@ -11,7 +11,9 @@
     <string name="contact_diary_person_list_no_items_title">"Все още няма въведени лица"</string>
     <string name="contact_diary_person_list_no_items_subtitle">"Създайте лице и го добавете към Вашия дневник на контактите."</string>
     <string name="contact_diary_add_person_title">"Лице"</string>
-    <string name="contact_diary_add_person_text_input_name_hint">"Име"</string>
+    <string name="contact_diary_add_person_text_input_name_hint">"Име, фамилия"</string>
+    <string name="contact_diary_add_text_input_phone_hint">"Телефон"</string>
+    <string name="contact_diary_add_text_input_email_hint">"Имейл"</string>
     <string name="contact_diary_add_person_save_button">"Запазване"</string>
     <string name="contact_diary_add_location_title">"Място"</string>
     <string name="contact_diary_add_location_text_input_hint">"Описание"</string>
@@ -70,8 +72,10 @@
     <string name="contact_diary_low_risk_title">"Нисък риск"</string>
     <!-- XTXT: Body for contact diary overview screen risk information -->
     <string name="contact_diary_risk_body">"въз основа на оценените от приложението контакти."</string>
+    <!-- XTXT: Body for contact diary overview screen risk information when high risk due to low risk encounters-->
+    <string name="contact_diary_risk_body_high_risk_due_to_low_risk_encounters">"въз основа на повече от едно излагане на нисък риск."</string>
     <!-- XTXT: Extended Body for contact diary overview screen risk information -->
-    <string name="contact_diary_risk_body_extended">"въз основа на оценените от приложението контакти. Не е задължително те да са свързани с отбелязаните от Вас хора и места."</string>
+    <string name="contact_diary_risk_body_extended">"Не е задължително те да са свързани с отбелязаните от Вас хора и места."</string>
 
 
     <!-- XTXT: content description of contact journal image on home screen -->
@@ -111,6 +115,13 @@
     <!-- XHED: Title for the contact diary dialog to delete delete a single person -->
     <string name="contact_diary_delete_person_title">"Наистина ли искате да изтриете това лице?"</string>
 
+    <!-- XHED: Title for the contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_title">"Бележка"</string>
+    <!-- XTXT: Description for contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_description">"Тук можете да въведете бележки, които ще ви помогнат да оцените по-добре своя риск от заразяване."</string>
+    <!-- XTXT: Body for contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_body">"Опишете обстоятелствата, които биха могли да доведат до повишаване на вашето ниво на риск, например в каква близост сте били до други хора и каква дейност с потенциално влияние върху качеството на въздуха сте извършвали (напр. „седяхме близо един до друг“, „спортувахме“, „пространството беше малко“ или „пяхме“).\n\nАко се заразите, тази информация може да помогне на службата за обществено здравеопазване да проследи потенциалните вериги на заразяване."</string>
+
     <!-- XTXT: location (description for screen readers) -->
     <string name="accessibility_location">"Място %s"</string>
     <!-- XTXT: person (description for screen readers) -->
@@ -133,4 +144,29 @@
     <!-- XTXT: Edit (description for screen readers) -->
     <string name="accessibility_edit">"Редактиране"</string>
 
+    <!-- XACT: Add Person Button (description for screen readers) -->
+    <string name="accessibility_day_add_person">"Добавяне на лице"</string>
+    <!-- XACT: Add Location Button (description for screen readers) -->
+    <string name="accessibility_day_add_location">"Добавяне на място"</string>
+
+    <!-- XBUT: Option - person encounter - below 15 Min -->
+    <string name="contact_diary_person_encounter_duration_below_15_min">"По-малко от 15 мин"</string>
+    <!-- XBUT: Option - person encounter - above 15 Min -->
+    <string name="contact_diary_person_encounter_duration_above_15_min">"Повече от 15 мин"</string>
+    <!-- XBUT: Option - person encounter - with mask -->
+    <string name="contact_diary_person_encounter_mask_with">"С маска"</string>
+    <!-- XBUT: Option - person encounter - without mask -->
+    <string name="contact_diary_person_encounter_mask_without">"Без маска"</string>
+    <!-- XBUT: Option - person encounter - outside -->
+    <string name="contact_diary_person_encounter_environment_outside">"На открито"</string>
+    <!-- XBUT: Option - person encounter - inside-->
+    <string name="contact_diary_person_encounter_environment_inside">"На закрито"</string>
+    <!-- XTXT: Option - person encounter - circumstances hint-->
+    <string name="contact_diary_person_encounter_circumstances_hint">"Забележка (напр. близко разстояние)"</string>
+
+
+    <!-- XBUT: Option - person encounter - inside-->
+    <string name="contact_diary_location_visit_duration_label">"Продължителност"</string>
+    <!-- XTXT: Option - person encounter - circumstances hint-->
+    <string name="contact_diary_location_visit_circumstances_hint">"Забележка (напр. препълнено)"</string>
 </resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values-bg/release_info_strings.xml b/Corona-Warn-App/src/main/res/values-bg/release_info_strings.xml
index 22bc2a703de4e25aa7f6b5b9da3e47385ea552b3..ad038d586b9f7aea1e7a6d21cf2406c00009ffb2 100644
--- a/Corona-Warn-App/src/main/res/values-bg/release_info_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-bg/release_info_strings.xml
@@ -1,6 +1,6 @@
 <?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">
     <!-- ####################################
-                 Release Info Screen 1.12
+                 Release Info Screen 1.14
      ###################################### -->
 
     <!-- XHED: Title for the release info screen -->
@@ -16,42 +16,34 @@
 
     <!-- XHED: Titles for the release info screen bullet points -->
     <string-array name="new_release_title">
-        <item>"Връзка към анкетата на института “Роберт Кох”"</item>
-        <item>"Съгласие за споделяне на данни (незадължително)"</item>
-        <item>"Промени в плочките за риск"</item>
-        <item>"Продължаване на регистрирането на излагания на риск след споделянето на Вашите случайно генерирани ИД кодове"</item>
-        <item>"Внедряване на табове"</item>
-        <item>"Допълнителна информация относно процедурата за тестване"</item>
+        <item>"Допълнителни функции в дневника на контактите"</item>
+        <item>"Директен достъп до дневника на контактите"</item>
+        <item>"Повече подробности относно вашето ниво на риск"</item>
+        <item>"Екранни снимки на приложението Corona-Warn-App"</item>
     </string-array>
 
     <!-- XTXT: Text bodies for the release info screen bullet points -->
     <string-array name="new_release_body">
-        <item>"Ако Вашето ниво на риск от заразяване е повишено, можете да отворите и попълните анкетата на института “Роберт Кох” от самото приложение."</item>
-        <item>"Вече имате възможност да споделяте своите данни за използването на приложението. Това ще ни помогне да го подобрим."</item>
-        <item>"Малки промени в текстовете на плочките за риск."</item>
-        <item>"След като споделите Вашите случайно генерирани ИД кодове, можете да решите дали и кога бихте желали да включите пак регистрирането на излаганията на риск."</item>
-        <item>"Вече има отделен таб за Вашия дневник на контактите. Така имате бърз достъп до дневника и можете лесно да преминавате от него към началния екран на приложението."</item>
-        <item>"В приложението вече има по-подробна информация относно процедурата за тестване."</item>
+        <item>"Вече можете да въвеждате специфични обстоятелства за всеки контакт. Можете да избирате от предварително зададени опции (напр. продължителност на контакта, използвана ли е маска, или не), както и да въвеждате кратка бележка, в която да отбележите други обстоятелства, които биха могли да доведат да повишен риск. Ако се заразите, тази информация може да помогне на службата за обществено здравеопазване да проследи потенциалните вериги на заразяване."</item>
+        <item>"Вече можете да добавите запис в дневника на контактите си, без да е необходимо първо да отваряте приложението. За да направите това, докоснете и задръжте иконата на приложението Corona-Warn-App в продължение на 2 секунди, докато се появи меню, и след това изберете „Добавяне на запис с днешна дата в дневника“."</item>
+        <item>"Ако приложението указва, че вашият риск от заразяване е повишен, вече можете да видите дали това се дължи на едно или повече излагания с повишен риск, или на такива с нисък риск."</item>
+        <item>"Всички екранни снимки на приложението вече са достъпни в уебсайта https://www.coronawarn.app. Така ще можете да научавате например какви нови функции се планират."</item>
     </string-array>
 
     <!-- XTXT: Text labels that will be converted to Links -->
     <string-array name="new_release_linkified_labels">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app"</item>
     </string-array>
 
     <!-- XTXT: URL destinations for the lables in new_release_linkified_labels -->
     <string-array name="new_release_target_urls">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app/en/screenshots"</item>
     </string-array>
 
 </resources>
\ No newline at end of file
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 fbdda0b02b459d441f2450af2e29f76ea66c72ca..658893e14fd24cd4e11d9b2f9a559d01d22910e6 100644
--- a/Corona-Warn-App/src/main/res/values-bg/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-bg/strings.xml
@@ -322,7 +322,7 @@
     <string name="risk_details_behavior_body_stay_away">"Спазвайте дистанция от поне 1,5 м от околните."</string>
 
     <!-- XMSG: risk details - link to faq, something like a bullet point -->
-    <string name="risk_details_increased_risk_faq_link_text">"Ако се тествате, ще получите допълнителна информация относно процедурата за тестване в ЧЗВ."</string>
+    <string name="risk_details_increased_risk_faq_link_text">"Ако се тествате, вижте Процедура за тестване в ЧЗВ, за да получите допълнителна информация."</string>
     <!-- XTXT: Explanation screen increased risk level link label - HAS TO MATCH the link text above -->
     <string name="risk_details_increased_risk_faq_link_label">"ЧЗВ"</string>
     <!-- XTXT: Explains user about increased risk level: URL, has to be "translated" into english (relevant for all languages except german) - https://www.coronawarn.app/en/faq/#further_details -->
@@ -537,11 +537,11 @@
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - regional evaluation text -->
     <string name="onboarding_ppa_regional_evaluation_text">"Ако посочите федерална провинция и регион, ще можем да правим и регионални анализи."</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - age title -->
-    <string name="onboarding_ppa_age_title">"Вашата възраст (незадължително)"</string>
+    <string name="onboarding_ppa_age_title">"Вашата възрастова група (незадължително)"</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - consent title -->
     <string name="onboarding_ppa_more_info_title">"Подробна информация относно обработката на тези данни и рисковете относно защитата на данните в САЩ и други държави."</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - donate button -->
-    <string name="onboarding_ppa_consent_donate_button">"Споделяне на данни"</string>
+    <string name="onboarding_ppa_consent_donate_button">"Приемам"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - dont donate button -->
     <string name="onboarding_ppa_consent_not_donate_button">"Без споделяне на данни"</string>
 
@@ -1754,6 +1754,9 @@
     <!-- XBUT: Abort button for test result positive no consent screen -->
     <string name="submission_test_result_positive_no_consent_button_abort">"Отказ"</string>
 
+    <!-- XHED: Title of contact diary app shortcut -->
+    <string name="app_shortcut_contact_diary_title">"Добавяне на запис"</string>
+
     <!-- XTXT: Statistics information (Accessibilty) -->
     <string name="statistics_info_button">"Още информация"</string>
     <!-- XHED: Title for statistics reproduction card -->
@@ -1830,7 +1833,7 @@
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_UNSPECIFIED -->
     <string name="analytics_userinput_agegroup_unspecified">"Без отговор"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_0_TO_29 -->
-    <string name="analytics_userinput_agegroup_0_to_29">"0-29 години"</string>
+    <string name="analytics_userinput_agegroup_0_to_29">"До 29 години"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_30_TO_59 -->
     <string name="analytics_userinput_agegroup_30_to_59">"30-59 години"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_FROM_60 -->
@@ -1877,4 +1880,17 @@
     <string name="analytics_userinput_district_title">"В кой окръг се намирате"</string>
     <!-- XTXT: Analytics voluntary user input, district: UNSPECIFIED -->
     <string name="analytics_userinput_district_unspecified">"Без отговор"</string>
-</resources>
+
+    <!-- ####################################
+       Duration dialog
+   ###################################### -->
+
+    <!-- XHED: Duration dialog title -->
+    <string name="duration_dialog_title">"Продължителност"</string>
+    <!-- XBUT: Duration dialog cancel button -->
+    <string name="duration_dialog_cancel_button">"Отказ"</string>
+    <!-- XBUT: Duration dialog ok button -->
+    <string name="duration_dialog_ok_button">"OK"</string>
+    <!-- NOTR -->
+    <string name="duration_dialog_default_value">"00:00"</string>
+</resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values-en/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values-en/contact_diary_strings.xml
index 4590f73acfddedd5dcddbf5dbe74a2b8e330aa8f..67d81f0efc1f1469fdb4bfba79a26f3cd3a55d34 100644
--- a/Corona-Warn-App/src/main/res/values-en/contact_diary_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-en/contact_diary_strings.xml
@@ -11,7 +11,9 @@
     <string name="contact_diary_person_list_no_items_title">"No people defined yet"</string>
     <string name="contact_diary_person_list_no_items_subtitle">"Create a person and add them to your contact journal."</string>
     <string name="contact_diary_add_person_title">"Person"</string>
-    <string name="contact_diary_add_person_text_input_name_hint">"Name"</string>
+    <string name="contact_diary_add_person_text_input_name_hint">"First name, last name"</string>
+    <string name="contact_diary_add_text_input_phone_hint">"Phone"</string>
+    <string name="contact_diary_add_text_input_email_hint">"e-mail"</string>
     <string name="contact_diary_add_person_save_button">"Save"</string>
     <string name="contact_diary_add_location_title">"Place"</string>
     <string name="contact_diary_add_location_text_input_hint">"Description"</string>
@@ -70,8 +72,10 @@
     <string name="contact_diary_low_risk_title">"Low Risk"</string>
     <!-- XTXT: Body for contact diary overview screen risk information -->
     <string name="contact_diary_risk_body">"based on the encounters evaluated by the app."</string>
+    <!-- XTXT: Body for contact diary overview screen risk information when high risk due to low risk encounters-->
+    <string name="contact_diary_risk_body_high_risk_due_to_low_risk_encounters">"based on multiple exposures with low risk."</string>
     <!-- XTXT: Extended Body for contact diary overview screen risk information -->
-    <string name="contact_diary_risk_body_extended">"based on the encounters evaluated by the app. They are not necessarily related to the people and places you have recorded."</string>
+    <string name="contact_diary_risk_body_extended">"They are not necessarily related to the people and places you have recorded."</string>
 
 
     <!-- XTXT: content description of contact journal image on home screen -->
@@ -111,6 +115,13 @@
     <!-- XHED: Title for the contact diary dialog to delete delete a single person -->
     <string name="contact_diary_delete_person_title">"Do you really want to remove this person?"</string>
 
+    <!-- XHED: Title for the contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_title">"Note"</string>
+    <!-- XTXT: Description for contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_description">"You can enter notes here that will help you to better estimate your risk of infection."</string>
+    <!-- XTXT: Body for contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_body">"Write down the circumstances that could result in an increased risk, for example, how close you were to other people or things you did that could affect the air quality (examples: “sat close together”, “played sports”, “little space”, “we sang”).\n\nIf you become infected, this information can also help the public health authority trace potential chains of infection."</string>
+
     <!-- XTXT: location (description for screen readers) -->
     <string name="accessibility_location">"Place %s"</string>
     <!-- XTXT: person (description for screen readers) -->
@@ -133,4 +144,29 @@
     <!-- XTXT: Edit (description for screen readers) -->
     <string name="accessibility_edit">"Edit"</string>
 
+    <!-- XACT: Add Person Button (description for screen readers) -->
+    <string name="accessibility_day_add_person">"Add Person"</string>
+    <!-- XACT: Add Location Button (description for screen readers) -->
+    <string name="accessibility_day_add_location">"Add Place"</string>
+
+    <!-- XBUT: Option - person encounter - below 15 Min -->
+    <string name="contact_diary_person_encounter_duration_below_15_min">"Less than 15 min"</string>
+    <!-- XBUT: Option - person encounter - above 15 Min -->
+    <string name="contact_diary_person_encounter_duration_above_15_min">"More than 15 min"</string>
+    <!-- XBUT: Option - person encounter - with mask -->
+    <string name="contact_diary_person_encounter_mask_with">"With mask"</string>
+    <!-- XBUT: Option - person encounter - without mask -->
+    <string name="contact_diary_person_encounter_mask_without">"Without mask"</string>
+    <!-- XBUT: Option - person encounter - outside -->
+    <string name="contact_diary_person_encounter_environment_outside">"Outdoors"</string>
+    <!-- XBUT: Option - person encounter - inside-->
+    <string name="contact_diary_person_encounter_environment_inside">"Indoors"</string>
+    <!-- XTXT: Option - person encounter - circumstances hint-->
+    <string name="contact_diary_person_encounter_circumstances_hint">"Note (e.g. close distance)"</string>
+
+
+    <!-- XBUT: Option - person encounter - inside-->
+    <string name="contact_diary_location_visit_duration_label">"Duration"</string>
+    <!-- XTXT: Option - person encounter - circumstances hint-->
+    <string name="contact_diary_location_visit_circumstances_hint">"Note (e.g. very full)"</string>
 </resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values-en/release_info_strings.xml b/Corona-Warn-App/src/main/res/values-en/release_info_strings.xml
index 16bcc281c37b95b523da1f13f0944c8bd5f65fc9..97db0a2ff3c673927a356ef88cb27e6801fab66b 100644
--- a/Corona-Warn-App/src/main/res/values-en/release_info_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-en/release_info_strings.xml
@@ -1,6 +1,6 @@
 <?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">
     <!-- ####################################
-                 Release Info Screen 1.12
+                 Release Info Screen 1.14
      ###################################### -->
 
     <!-- XHED: Title for the release info screen -->
@@ -16,42 +16,34 @@
 
     <!-- XHED: Titles for the release info screen bullet points -->
     <string-array name="new_release_title">
-        <item>"Link to RKI survey"</item>
-        <item>"Consent to Share Data (optional)"</item>
-        <item>"Changes to the Risk Tiles"</item>
-        <item>"Continuation of Exposure Logging after Sharing Your Random IDs"</item>
-        <item>"Implementation of Tabs"</item>
-        <item>"More Information about the Testing Procedure"</item>
+        <item>"Additional Features in the Contact Journal"</item>
+        <item>"Direct Access to Contact Journal"</item>
+        <item>"More Details about Your Risk Status"</item>
+        <item>"Screenshots for the Corona-Warn-App"</item>
     </string-array>
 
     <!-- XTXT: Text bodies for the release info screen bullet points -->
     <string-array name="new_release_body">
-        <item>"If you have an increased risk, you can start and take a survey conducted by the Robert Koch Institute from within the app."</item>
-        <item>"You now have the option of sharing your usage data, which will help us to improve the app."</item>
-        <item>"Minor changes to the texts on the risk tiles."</item>
-        <item>"After you have shared your encrypted random IDs, you can decide whether and when you want to switch exposure logging back on."</item>
-        <item>"There is now a separate tab page for your contact journal. This lets you access your journal and switch from the contact journal back to the home screen of the app more quickly."</item>
-        <item>"The app now contains more detailed information about the testing procedure."</item>
+        <item>"You can now enter the specific circumstances of each encounter. You can select from the predefined options (such as duration of the encounter, with or without mask) and also enter a brief note to record other circumstances that might result in an increased risk. If you become infected, this information can help the public health authority trace potential chains of infection."</item>
+        <item>"You can now add an entry to your contact journal directly, without having to open the app first. To do so, tap and hold the icon for the Corona-Warn-App for approximately 2 seconds, until a menu appears, and then tap “Add Journal Entry for Today”."</item>
+        <item>"If the app indicates that you have an increased risk, you can now see whether the risk status is displayed based on one or more exposures with an increased risk or one or more exposures with a low risk."</item>
+        <item>"The website https://www.coronawarn.app now contains all the screenshots for the app, so you can find out about planned features, for example."</item>
     </string-array>
 
     <!-- XTXT: Text labels that will be converted to Links -->
     <string-array name="new_release_linkified_labels">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app"</item>
     </string-array>
 
     <!-- XTXT: URL destinations for the lables in new_release_linkified_labels -->
     <string-array name="new_release_target_urls">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app/en/screenshots"</item>
     </string-array>
 
 </resources>
\ No newline at end of file
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 0330f3c7b7f0bab25bccdc3ad621f791477b9178..d8c0ec6c58b8f6db20d394c7eb2a9318fe9bb08a 100644
--- a/Corona-Warn-App/src/main/res/values-en/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-en/strings.xml
@@ -537,11 +537,11 @@
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - regional evaluation text -->
     <string name="onboarding_ppa_regional_evaluation_text">"If you also specify your federal state and region, we can conduct regional analyses."</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - age title -->
-    <string name="onboarding_ppa_age_title">"Your age (optional)"</string>
+    <string name="onboarding_ppa_age_title">"Your age group (optional)"</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - consent title -->
     <string name="onboarding_ppa_more_info_title">"Detailed Information about This Data Processing and Data Protection Risks in the U.S. and Other Third Countries"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - donate button -->
-    <string name="onboarding_ppa_consent_donate_button">"Share Data"</string>
+    <string name="onboarding_ppa_consent_donate_button">"Accept"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - dont donate button -->
     <string name="onboarding_ppa_consent_not_donate_button">"Do Not Share"</string>
 
@@ -1754,6 +1754,9 @@
     <!-- XBUT: Abort button for test result positive no consent screen -->
     <string name="submission_test_result_positive_no_consent_button_abort">"Cancel"</string>
 
+    <!-- XHED: Title of contact diary app shortcut -->
+    <string name="app_shortcut_contact_diary_title">"Add Entry"</string>
+
     <!-- XTXT: Statistics information (Accessibilty) -->
     <string name="statistics_info_button">"Further information"</string>
     <!-- XHED: Title for statistics reproduction card -->
@@ -1830,7 +1833,7 @@
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_UNSPECIFIED -->
     <string name="analytics_userinput_agegroup_unspecified">"No answer"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_0_TO_29 -->
-    <string name="analytics_userinput_agegroup_0_to_29">"0-29 years old"</string>
+    <string name="analytics_userinput_agegroup_0_to_29">"Up to 29"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_30_TO_59 -->
     <string name="analytics_userinput_agegroup_30_to_59">"30-59 years old"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_FROM_60 -->
@@ -1877,4 +1880,17 @@
     <string name="analytics_userinput_district_title">"Your District (County)"</string>
     <!-- XTXT: Analytics voluntary user input, district: UNSPECIFIED -->
     <string name="analytics_userinput_district_unspecified">"No answer"</string>
+
+    <!-- ####################################
+       Duration dialog
+   ###################################### -->
+
+    <!-- XHED: Duration dialog title -->
+    <string name="duration_dialog_title">"Duration"</string>
+    <!-- XBUT: Duration dialog cancel button -->
+    <string name="duration_dialog_cancel_button">"Cancel"</string>
+    <!-- XBUT: Duration dialog ok button -->
+    <string name="duration_dialog_ok_button">"OK"</string>
+    <!-- NOTR -->
+    <string name="duration_dialog_default_value">"00:00"</string>
 </resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values-pl/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values-pl/contact_diary_strings.xml
index 38df500cf588e0f9c76fc2d46671d4d9ac3affb0..def8dbd37cbf58ecb39050b2a2c6ed1f712005d3 100644
--- a/Corona-Warn-App/src/main/res/values-pl/contact_diary_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-pl/contact_diary_strings.xml
@@ -11,7 +11,9 @@
     <string name="contact_diary_person_list_no_items_title">"Nie zdefiniowano jeszcze żadnych osób"</string>
     <string name="contact_diary_person_list_no_items_subtitle">"Utwórz osobę i dodaj ją do dziennika kontaktów."</string>
     <string name="contact_diary_add_person_title">"Osoba"</string>
-    <string name="contact_diary_add_person_text_input_name_hint">"ImiÄ™ i nazwisko"</string>
+    <string name="contact_diary_add_person_text_input_name_hint">"ImiÄ™, nazwisko"</string>
+    <string name="contact_diary_add_text_input_phone_hint">"Telefon"</string>
+    <string name="contact_diary_add_text_input_email_hint">"E-mail"</string>
     <string name="contact_diary_add_person_save_button">"Zapisz"</string>
     <string name="contact_diary_add_location_title">"Miejsce"</string>
     <string name="contact_diary_add_location_text_input_hint">"Opis"</string>
@@ -70,8 +72,10 @@
     <string name="contact_diary_low_risk_title">"Niskie ryzyko"</string>
     <!-- XTXT: Body for contact diary overview screen risk information -->
     <string name="contact_diary_risk_body">"na podstawie kontaktów ocenionych przez aplikację."</string>
+    <!-- XTXT: Body for contact diary overview screen risk information when high risk due to low risk encounters-->
+    <string name="contact_diary_risk_body_high_risk_due_to_low_risk_encounters">"na podstawie wielu narażeń o niskim ryzyku."</string>
     <!-- XTXT: Extended Body for contact diary overview screen risk information -->
-    <string name="contact_diary_risk_body_extended">"na podstawie kontaktów ocenionych przez aplikację. Niekoniecznie są one związane z zarejestrowanymi przez Ciebie osobami i miejscami."</string>
+    <string name="contact_diary_risk_body_extended">"Niekoniecznie sÄ… one zwiÄ…zane z zarejestrowanymi przez Ciebie osobami i miejscami."</string>
 
 
     <!-- XTXT: content description of contact journal image on home screen -->
@@ -111,6 +115,13 @@
     <!-- XHED: Title for the contact diary dialog to delete delete a single person -->
     <string name="contact_diary_delete_person_title">"Czy na pewno chcesz usunąć tę osobę?"</string>
 
+    <!-- XHED: Title for the contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_title">"Uwaga"</string>
+    <!-- XTXT: Description for contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_description">"Możesz tu wpisać uwagi, które pomogą Ci lepiej oszacować ryzyko zakażenia."</string>
+    <!-- XTXT: Body for contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_body">"Zapisz okoliczności, które mogły zwiększyć ryzyko, np. odległość od innych osób lub wykonywane czynności, które mogły mieć wpływ na jakość powietrza (przykłady: „siedzieliśmy blisko siebie”, „uprawialiśmy sport”, „mało miejsca”, „śpiewaliśmy”).\n\nW przypadku Twojego zakażenia informacje te będą mogły zostać wykorzystane przez organy ds. zdrowia publicznego do prześledzenia potencjalnych łańcuchów zakażenia."</string>
+
     <!-- XTXT: location (description for screen readers) -->
     <string name="accessibility_location">"Miejsce %s"</string>
     <!-- XTXT: person (description for screen readers) -->
@@ -133,4 +144,29 @@
     <!-- XTXT: Edit (description for screen readers) -->
     <string name="accessibility_edit">"Edytuj"</string>
 
+    <!-- XACT: Add Person Button (description for screen readers) -->
+    <string name="accessibility_day_add_person">"Dodaj osobÄ™"</string>
+    <!-- XACT: Add Location Button (description for screen readers) -->
+    <string name="accessibility_day_add_location">"Dodaj miejsce"</string>
+
+    <!-- XBUT: Option - person encounter - below 15 Min -->
+    <string name="contact_diary_person_encounter_duration_below_15_min">"Mniej niż 15 min"</string>
+    <!-- XBUT: Option - person encounter - above 15 Min -->
+    <string name="contact_diary_person_encounter_duration_above_15_min">"Więcej niż 15 min"</string>
+    <!-- XBUT: Option - person encounter - with mask -->
+    <string name="contact_diary_person_encounter_mask_with">"Z maseczkÄ…"</string>
+    <!-- XBUT: Option - person encounter - without mask -->
+    <string name="contact_diary_person_encounter_mask_without">"Bez maseczki"</string>
+    <!-- XBUT: Option - person encounter - outside -->
+    <string name="contact_diary_person_encounter_environment_outside">"Na zewnÄ…trz"</string>
+    <!-- XBUT: Option - person encounter - inside-->
+    <string name="contact_diary_person_encounter_environment_inside">"W pomieszczeniu"</string>
+    <!-- XTXT: Option - person encounter - circumstances hint-->
+    <string name="contact_diary_person_encounter_circumstances_hint">"Uwaga (np. bliska odległość)"</string>
+
+
+    <!-- XBUT: Option - person encounter - inside-->
+    <string name="contact_diary_location_visit_duration_label">"Czas trwania"</string>
+    <!-- XTXT: Option - person encounter - circumstances hint-->
+    <string name="contact_diary_location_visit_circumstances_hint">"Uwaga (np. bardzo pełny)"</string>
 </resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values-pl/release_info_strings.xml b/Corona-Warn-App/src/main/res/values-pl/release_info_strings.xml
index 1c663f6e74a37130ee3b1b89307408beeec10b4a..f04a4e4705434e19155807dc01b3b52898a4fc11 100644
--- a/Corona-Warn-App/src/main/res/values-pl/release_info_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-pl/release_info_strings.xml
@@ -1,6 +1,6 @@
 <?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">
     <!-- ####################################
-                 Release Info Screen 1.12
+                 Release Info Screen 1.14
      ###################################### -->
 
     <!-- XHED: Title for the release info screen -->
@@ -16,42 +16,34 @@
 
     <!-- XHED: Titles for the release info screen bullet points -->
     <string-array name="new_release_title">
-        <item>"Link do ankiety RKI"</item>
-        <item>"Zgoda na udostępnianie danych (opcjonalnie)"</item>
-        <item>"Zmiany w kafelkach ryzyka"</item>
-        <item>"Kontynuacja rejestrowania narażenia po udostępnieniu losowych identyfikatorów"</item>
-        <item>"Implementacja kart"</item>
-        <item>"Więcej informacji o procedurze testowania"</item>
+        <item>"Dodatkowe funkcje w dzienniku kontaktów"</item>
+        <item>"Bezpośredni dostęp do dziennika kontaktów"</item>
+        <item>"Więcej szczegółów na temat Twojego statusu ryzyka"</item>
+        <item>"Zrzuty ekranu dla Corona-Warn-App"</item>
     </string-array>
 
     <!-- XTXT: Text bodies for the release info screen bullet points -->
     <string-array name="new_release_body">
-        <item>"Jeśli masz podwyższone ryzyko, możesz rozpocząć i wypełnić ankietę przeprowadzaną przez Instytut Roberta Kocha z poziomu aplikacji."</item>
-        <item>"Masz teraz możliwość udostępnienia swoich danych na temat użytkowania, co pomoże nam ulepszyć aplikację."</item>
-        <item>"Niewielkie zmiany w tekstach na kafelkach ryzyka."</item>
-        <item>"Po udostępnieniu zaszyfrowanych losowych identyfikatorów możesz zdecydować, czy i kiedy chcesz ponownie włączyć rejestrowanie narażenia."</item>
-        <item>"Dostępna jest teraz oddzielna karta dla Twojego dziennika kontaktów. Dzięki niej uzyskasz dostęp do swojego dziennika i szybciej przełączysz się z dziennika kontaktów z powrotem na ekran główny aplikacji."</item>
-        <item>"Aplikacja zawiera teraz bardziej szczegółowe informacje na temat procedury testowania."</item>
+        <item>"Teraz możesz wprowadzić szczegółowe okoliczności każdego kontaktu. Możesz dokonać wyboru spośród predefiniowanych opcji (takich jak czas trwania kontaktu, z maseczką lub bez), a także wprowadzić krótką notatkę w celu zapisania innych okoliczności, które mogą zwiększać ryzyko. W przypadku Twojego zakażenia informacje te będą mogły zostać wykorzystane przez organy ds. zdrowia publicznego do prześledzenia potencjalnych łańcuchów zakażenia."</item>
+        <item>"Możesz teraz bezpośrednio dodać wpis do dziennika kontaktów bez konieczności otwierania aplikacji. Aby to zrobić, dotknij i przytrzymaj ikonę aplikacji Corona-Warn-App przez około 2 sekundy, aż pojawi się menu, a następnie dotknij opcji „Dodaj wpis do dziennika na dziś\"."</item>
+        <item>"Jeśli aplikacja wskaże podwyższone ryzyko, możesz sprawdzić, czy status ryzyka jest wyświetlany na podstawie jednego lub większej liczby narażeń o podwyższonym ryzyku czy jednego lub większej liczby o niskim ryzyku."</item>
+        <item>"Witryna https://www.coronawarn.app zawiera teraz wszystkie zrzuty ekranu aplikacji, dzięki czemu możesz uzyskać informacji na przykład o planowanych funkcjach."</item>
     </string-array>
 
     <!-- XTXT: Text labels that will be converted to Links -->
     <string-array name="new_release_linkified_labels">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app"</item>
     </string-array>
 
     <!-- XTXT: URL destinations for the lables in new_release_linkified_labels -->
     <string-array name="new_release_target_urls">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app/en/screenshots"</item>
     </string-array>
 
 </resources>
\ No newline at end of file
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 51bc65f9f9367f7eb5203b610216feb3ef871ec3..eaa9f8c595946d738be2cbd181342b4cd91328fb 100644
--- a/Corona-Warn-App/src/main/res/values-pl/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-pl/strings.xml
@@ -537,11 +537,11 @@
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - regional evaluation text -->
     <string name="onboarding_ppa_regional_evaluation_text">"Jeśli podasz również swój kraj związkowy i region, będziemy mogli przeprowadzić analizy regionalne."</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - age title -->
-    <string name="onboarding_ppa_age_title">"Twój wiek (opcjonalnie)"</string>
+    <string name="onboarding_ppa_age_title">"Twoja grupa wiekowa (opcjonalnie)"</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - consent title -->
     <string name="onboarding_ppa_more_info_title">"Szczegółowe informacje o ryzyku związanym z przetwarzaniem i ochroną danych w USA i innych krajach trzecich"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - donate button -->
-    <string name="onboarding_ppa_consent_donate_button">"Udostępnij dane"</string>
+    <string name="onboarding_ppa_consent_donate_button">"Akceptuj"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - dont donate button -->
     <string name="onboarding_ppa_consent_not_donate_button">"Nie udostępniaj"</string>
 
@@ -1754,6 +1754,9 @@
     <!-- XBUT: Abort button for test result positive no consent screen -->
     <string name="submission_test_result_positive_no_consent_button_abort">"Anuluj"</string>
 
+    <!-- XHED: Title of contact diary app shortcut -->
+    <string name="app_shortcut_contact_diary_title">"Dodaj wpis"</string>
+
     <!-- XTXT: Statistics information (Accessibilty) -->
     <string name="statistics_info_button">"Więcej informacji"</string>
     <!-- XHED: Title for statistics reproduction card -->
@@ -1830,7 +1833,7 @@
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_UNSPECIFIED -->
     <string name="analytics_userinput_agegroup_unspecified">"Brak odpowiedzi"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_0_TO_29 -->
-    <string name="analytics_userinput_agegroup_0_to_29">"0-29 lat"</string>
+    <string name="analytics_userinput_agegroup_0_to_29">"Do 29 lat"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_30_TO_59 -->
     <string name="analytics_userinput_agegroup_30_to_59">"30-59 lat"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_FROM_60 -->
@@ -1877,4 +1880,17 @@
     <string name="analytics_userinput_district_title">"Twój okręg (powiat)"</string>
     <!-- XTXT: Analytics voluntary user input, district: UNSPECIFIED -->
     <string name="analytics_userinput_district_unspecified">"Brak odpowiedzi"</string>
+
+    <!-- ####################################
+       Duration dialog
+   ###################################### -->
+
+    <!-- XHED: Duration dialog title -->
+    <string name="duration_dialog_title">"Czas trwania"</string>
+    <!-- XBUT: Duration dialog cancel button -->
+    <string name="duration_dialog_cancel_button">"Anuluj"</string>
+    <!-- XBUT: Duration dialog ok button -->
+    <string name="duration_dialog_ok_button">"OK"</string>
+    <!-- NOTR -->
+    <string name="duration_dialog_default_value">"00:00"</string>
 </resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values-ro/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values-ro/contact_diary_strings.xml
index 90539612e53b315e2e8674688e51d65ae34521da..322b6dc22bc51d3c16219331c408eb3c83820acd 100644
--- a/Corona-Warn-App/src/main/res/values-ro/contact_diary_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-ro/contact_diary_strings.xml
@@ -11,7 +11,9 @@
     <string name="contact_diary_person_list_no_items_title">"Nicio persoană definită deocamdată"</string>
     <string name="contact_diary_person_list_no_items_subtitle">"Creați o persoană și adăugați-o la jurnalul dvs. de contacte."</string>
     <string name="contact_diary_add_person_title">"Persoană"</string>
-    <string name="contact_diary_add_person_text_input_name_hint">"Nume"</string>
+    <string name="contact_diary_add_person_text_input_name_hint">"Prenume, nume"</string>
+    <string name="contact_diary_add_text_input_phone_hint">"Telefon"</string>
+    <string name="contact_diary_add_text_input_email_hint">"e-mail"</string>
     <string name="contact_diary_add_person_save_button">"Salvare"</string>
     <string name="contact_diary_add_location_title">"Loc"</string>
     <string name="contact_diary_add_location_text_input_hint">"Descriere"</string>
@@ -70,8 +72,10 @@
     <string name="contact_diary_low_risk_title">"Risc redus"</string>
     <!-- XTXT: Body for contact diary overview screen risk information -->
     <string name="contact_diary_risk_body">"pe baza întâlnirilor evaluate de aplicație."</string>
+    <!-- XTXT: Body for contact diary overview screen risk information when high risk due to low risk encounters-->
+    <string name="contact_diary_risk_body_high_risk_due_to_low_risk_encounters">"pe baza mai multor expuneri cu risc redus."</string>
     <!-- XTXT: Extended Body for contact diary overview screen risk information -->
-    <string name="contact_diary_risk_body_extended">"pe baza întâlnirilor evaluate de aplicație. Acestea nu sunt legate neapărat de persoanele și locurile pe care le-ați înregistrat."</string>
+    <string name="contact_diary_risk_body_extended">"Acestea nu sunt legate neapărat de persoanele și locurile pe care le-ați înregistrat."</string>
 
 
     <!-- XTXT: content description of contact journal image on home screen -->
@@ -111,6 +115,13 @@
     <!-- XHED: Title for the contact diary dialog to delete delete a single person -->
     <string name="contact_diary_delete_person_title">"Sigur doriți să eliminați această persoană?"</string>
 
+    <!-- XHED: Title for the contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_title">"Notă"</string>
+    <!-- XTXT: Description for contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_description">"Acum puteți introduce aici note care vă vor ajuta să estimați mai bine riscul dvs. de infectare."</string>
+    <!-- XTXT: Body for contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_body">"Notați circumstanțele care ar putea avea drept efect un risc crescut, de exemplu, cât de aproape vă aflați față de alte persoane și ce făceați (exemple: „am stat aproape unul de altul”, „am făcut sport”, „spațiu puțin”, „am cântat”).\n\nDacă vă infectați, aceste informații pot ajuta autoritatea de sănătate publică să urmărească posibilele lanțuri de infectare."</string>
+
     <!-- XTXT: location (description for screen readers) -->
     <string name="accessibility_location">"Locul %s"</string>
     <!-- XTXT: person (description for screen readers) -->
@@ -133,4 +144,29 @@
     <!-- XTXT: Edit (description for screen readers) -->
     <string name="accessibility_edit">"Editare"</string>
 
+    <!-- XACT: Add Person Button (description for screen readers) -->
+    <string name="accessibility_day_add_person">"Adăugare persoană"</string>
+    <!-- XACT: Add Location Button (description for screen readers) -->
+    <string name="accessibility_day_add_location">"Adăugare loc"</string>
+
+    <!-- XBUT: Option - person encounter - below 15 Min -->
+    <string name="contact_diary_person_encounter_duration_below_15_min">"Mai puțin de 15 min."</string>
+    <!-- XBUT: Option - person encounter - above 15 Min -->
+    <string name="contact_diary_person_encounter_duration_above_15_min">"Mai mult de 15 min."</string>
+    <!-- XBUT: Option - person encounter - with mask -->
+    <string name="contact_diary_person_encounter_mask_with">"Cu mască"</string>
+    <!-- XBUT: Option - person encounter - without mask -->
+    <string name="contact_diary_person_encounter_mask_without">"Fără mască"</string>
+    <!-- XBUT: Option - person encounter - outside -->
+    <string name="contact_diary_person_encounter_environment_outside">"ÃŽn exterior"</string>
+    <!-- XBUT: Option - person encounter - inside-->
+    <string name="contact_diary_person_encounter_environment_inside">"ÃŽn interior"</string>
+    <!-- XTXT: Option - person encounter - circumstances hint-->
+    <string name="contact_diary_person_encounter_circumstances_hint">"Notă (de ex., distanță mică)"</string>
+
+
+    <!-- XBUT: Option - person encounter - inside-->
+    <string name="contact_diary_location_visit_duration_label">"Durată"</string>
+    <!-- XTXT: Option - person encounter - circumstances hint-->
+    <string name="contact_diary_location_visit_circumstances_hint">"Notă (de ex., foarte plin)"</string>
 </resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values-ro/release_info_strings.xml b/Corona-Warn-App/src/main/res/values-ro/release_info_strings.xml
index ab72df625c9f8d4eddcd4860a9a8944b1735ee0a..7015d94907b8d2201d60cd8c67aba2414efc3737 100644
--- a/Corona-Warn-App/src/main/res/values-ro/release_info_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-ro/release_info_strings.xml
@@ -1,6 +1,6 @@
 <?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">
     <!-- ####################################
-                 Release Info Screen 1.12
+                 Release Info Screen 1.14
      ###################################### -->
 
     <!-- XHED: Title for the release info screen -->
@@ -16,42 +16,34 @@
 
     <!-- XHED: Titles for the release info screen bullet points -->
     <string-array name="new_release_title">
-        <item>"Legătură la chestionarul RKI"</item>
-        <item>"Consimțământ pentru partajarea datelor (opțional)"</item>
-        <item>"Modificări la mozaicurile riscului"</item>
-        <item>"Continuarea înregistrării în jurnal a expunerilor după partajarea ID-urilor dvs. aleatorii"</item>
-        <item>"Implementarea taburilor"</item>
-        <item>"Mai multe informații despre procedura de testare"</item>
+        <item>"Caracteristici suplimentare în jurnalul de contacte"</item>
+        <item>"Acces direct la jurnalul de contacte"</item>
+        <item>"Mai multe detalii despre starea riscului dvs."</item>
+        <item>"Capturi de ecran ale aplicației Corona-Warn"</item>
     </string-array>
 
     <!-- XTXT: Text bodies for the release info screen bullet points -->
     <string-array name="new_release_body">
-        <item>"Dacă aveți risc crescut, puteți începe cu participarea la un chestionar desfășurat de Institutul Robert Koch în aplicație."</item>
-        <item>"Acum aveți opțiunea de partajare a datelor de utilizare, ceea ce ne va ajuta să îmbunătățim aplicația."</item>
-        <item>"Modificări minore ale textelor de pe mozaicurile riscului."</item>
-        <item>"După ce ați partajat ID-urile dvs. aleatorii criptate, puteți decide dacă și când doriți să activați din nou înregistrarea în jurnal a expunerilor."</item>
-        <item>"Acum există o pagină de tab separată pentru jurnalul dvs. de contacte. Acesta vă permite să accesați jurnalul dvs. și să comutați de la jurnalul de contacte înapoi la ecranul inițial al aplicației mai rapid."</item>
-        <item>"Aplicația conține acum informații mai detaliate despre procedura de testare."</item>
+        <item>"Acum puteți introduce circumstanțele specifice ale fiecărei întâlniri. Puteți selecta din opțiunile predefinite (precum durata întâlnirii, cu mască sau fără mască) și puteți, de asemenea, introduce o notă scurtă pentru a înregistra alte circumstanțe care pot duce la un risc crescut. Dacă vă infectați, aceste informații pot ajuta autoritatea de sănătate publică să urmărească posibilele lanțuri de infectare."</item>
+        <item>"Acum puteți adăuga o intrare direct la jurnalul dvs. de contacte, fără a mai fi nevoie să deschideți mai întâi aplicația. Pentru aceasta, atingeți și mențineți apăsată pictograma pentru aplicația Corona-Warn timp de aproximativ 2 secunde, până apare un meniu, apoi apăsați pe „Adăugare intrare în jurnal pentru astăzi”."</item>
+        <item>"Dacă aplicația indică un risc crescut pentru dvs., acum puteți vedea dacă starea riscului este afișată pe baza uneia sau mai multor expuneri cu un risc crescut sau pe baza mai multor expuneri cu risc redus."</item>
+        <item>"Site-ul web https://www.coronawarn.app conține acum toate capturile de ecran ale aplicației, pentru a găsi, de exemplu, caracteristicile planificate."</item>
     </string-array>
 
     <!-- XTXT: Text labels that will be converted to Links -->
     <string-array name="new_release_linkified_labels">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app"</item>
     </string-array>
 
     <!-- XTXT: URL destinations for the lables in new_release_linkified_labels -->
     <string-array name="new_release_target_urls">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app/en/screenshots"</item>
     </string-array>
 
 </resources>
\ No newline at end of file
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 e29be8d41f483ea294dcf04f97dcbd3e28617c81..9e673a7e8cc46fbe9cfa00d71a655f6d0819e36b 100644
--- a/Corona-Warn-App/src/main/res/values-ro/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-ro/strings.xml
@@ -537,11 +537,11 @@
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - regional evaluation text -->
     <string name="onboarding_ppa_regional_evaluation_text">"Dacă specificați, de asemenea, statul federal și regiunea dvs., putem efectua analize regionale."</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - age title -->
-    <string name="onboarding_ppa_age_title">"Vârsta dvs. (opțional)"</string>
+    <string name="onboarding_ppa_age_title">"Grupul dvs. de vârstă (opțional)"</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - consent title -->
     <string name="onboarding_ppa_more_info_title">"Informații detaliate despre prelucrarea acestor date și riscurile privind prelucrarea datelor din SUA și din alte țări terțe"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - donate button -->
-    <string name="onboarding_ppa_consent_donate_button">"Partajare date"</string>
+    <string name="onboarding_ppa_consent_donate_button">"Accept"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - dont donate button -->
     <string name="onboarding_ppa_consent_not_donate_button">"Fără partajare"</string>
 
@@ -1754,6 +1754,9 @@
     <!-- XBUT: Abort button for test result positive no consent screen -->
     <string name="submission_test_result_positive_no_consent_button_abort">"Anulare"</string>
 
+    <!-- XHED: Title of contact diary app shortcut -->
+    <string name="app_shortcut_contact_diary_title">"Adăugare intrare"</string>
+
     <!-- XTXT: Statistics information (Accessibilty) -->
     <string name="statistics_info_button">"Informații suplimentare"</string>
     <!-- XHED: Title for statistics reproduction card -->
@@ -1830,7 +1833,7 @@
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_UNSPECIFIED -->
     <string name="analytics_userinput_agegroup_unspecified">"Nu răspund"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_0_TO_29 -->
-    <string name="analytics_userinput_agegroup_0_to_29">"0-29 de ani"</string>
+    <string name="analytics_userinput_agegroup_0_to_29">"Sub 29 de ani"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_30_TO_59 -->
     <string name="analytics_userinput_agegroup_30_to_59">"30-59 de ani"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_FROM_60 -->
@@ -1877,4 +1880,17 @@
     <string name="analytics_userinput_district_title">"Districtul (județul) dvs."</string>
     <!-- XTXT: Analytics voluntary user input, district: UNSPECIFIED -->
     <string name="analytics_userinput_district_unspecified">"Nu răspund"</string>
+
+    <!-- ####################################
+       Duration dialog
+   ###################################### -->
+
+    <!-- XHED: Duration dialog title -->
+    <string name="duration_dialog_title">"Durată"</string>
+    <!-- XBUT: Duration dialog cancel button -->
+    <string name="duration_dialog_cancel_button">"Anulare"</string>
+    <!-- XBUT: Duration dialog ok button -->
+    <string name="duration_dialog_ok_button">"OK"</string>
+    <!-- NOTR -->
+    <string name="duration_dialog_default_value">"00:00"</string>
 </resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values-tr/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values-tr/contact_diary_strings.xml
index c8b833111fc2d158b4b355975f9dde90202d6968..eb4308ad5f45b4efc85cf53be6b9132b5bd60fb5 100644
--- a/Corona-Warn-App/src/main/res/values-tr/contact_diary_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-tr/contact_diary_strings.xml
@@ -11,7 +11,9 @@
     <string name="contact_diary_person_list_no_items_title">"Henüz hiçbir kişi tanımlanmadı"</string>
     <string name="contact_diary_person_list_no_items_subtitle">"Bir kişi oluşturun ve temas güncenize ekleyin."</string>
     <string name="contact_diary_add_person_title">"KiÅŸi"</string>
-    <string name="contact_diary_add_person_text_input_name_hint">"Ad"</string>
+    <string name="contact_diary_add_person_text_input_name_hint">"Ad, soyadı"</string>
+    <string name="contact_diary_add_text_input_phone_hint">"Telefon"</string>
+    <string name="contact_diary_add_text_input_email_hint">"e-posta"</string>
     <string name="contact_diary_add_person_save_button">"Kaydet"</string>
     <string name="contact_diary_add_location_title">"Yer"</string>
     <string name="contact_diary_add_location_text_input_hint">"Tanım"</string>
@@ -70,8 +72,10 @@
     <string name="contact_diary_low_risk_title">"Düşük Risk"</string>
     <!-- XTXT: Body for contact diary overview screen risk information -->
     <string name="contact_diary_risk_body">"uygulama tarafından değerlendirilen karşılaşmalar temel alınır."</string>
+    <!-- XTXT: Body for contact diary overview screen risk information when high risk due to low risk encounters-->
+    <string name="contact_diary_risk_body_high_risk_due_to_low_risk_encounters">"(düşük riskli birden fazla maruz kalmaya göre)."</string>
     <!-- XTXT: Extended Body for contact diary overview screen risk information -->
-    <string name="contact_diary_risk_body_extended">"uygulama tarafından değerlendirilen karşılaşmalar temel alınır. Kaydettiğiniz kişilerle ve yerlerle ilgili olmaları şart değildir."</string>
+    <string name="contact_diary_risk_body_extended">"Kaydettiğiniz kişilerle ve yerlerle ilgili olmaları şart değildir."</string>
 
 
     <!-- XTXT: content description of contact journal image on home screen -->
@@ -111,6 +115,13 @@
     <!-- XHED: Title for the contact diary dialog to delete delete a single person -->
     <string name="contact_diary_delete_person_title">"Bu kişiyi gerçekten kaldırmak istiyor musunuz?"</string>
 
+    <!-- XHED: Title for the contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_title">"Not"</string>
+    <!-- XTXT: Description for contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_description">"Enfeksiyon riskinizi daha iyi tahmin etmenize yardımcı olacak notları bu bölüme girebilirsiniz."</string>
+    <!-- XTXT: Body for contact diary comment info screen -->
+    <string name="contact_diary_comment_info_screen_body">"Başka insanlara ne kadar yakın olduğunuz ya da yaptığınız şeyler gibi hava kalitesini etkileyebilecek ve riskin artmasına neden olabilecek koşulları yazın (örnekler: “yakın bir şekilde birlikte oturduk”, “spor yaptık”, “az alan vardı”, “şarkı söyledik”).\n\nEnfekte olmanız halinde bu bilgiler, kamu sağlığı yetkilisinin potansiyel enfeksiyon zincirlerini takip etmesine de yardımcı olabilir."</string>
+
     <!-- XTXT: location (description for screen readers) -->
     <string name="accessibility_location">"Yer %s"</string>
     <!-- XTXT: person (description for screen readers) -->
@@ -133,4 +144,29 @@
     <!-- XTXT: Edit (description for screen readers) -->
     <string name="accessibility_edit">"Düzenle"</string>
 
+    <!-- XACT: Add Person Button (description for screen readers) -->
+    <string name="accessibility_day_add_person">"KiÅŸi Ekle"</string>
+    <!-- XACT: Add Location Button (description for screen readers) -->
+    <string name="accessibility_day_add_location">"Yer Ekle"</string>
+
+    <!-- XBUT: Option - person encounter - below 15 Min -->
+    <string name="contact_diary_person_encounter_duration_below_15_min">"15 dakikadan az"</string>
+    <!-- XBUT: Option - person encounter - above 15 Min -->
+    <string name="contact_diary_person_encounter_duration_above_15_min">"15 dakikadan fazla"</string>
+    <!-- XBUT: Option - person encounter - with mask -->
+    <string name="contact_diary_person_encounter_mask_with">"Maskeli"</string>
+    <!-- XBUT: Option - person encounter - without mask -->
+    <string name="contact_diary_person_encounter_mask_without">"Maskesiz"</string>
+    <!-- XBUT: Option - person encounter - outside -->
+    <string name="contact_diary_person_encounter_environment_outside">"Açık hava"</string>
+    <!-- XBUT: Option - person encounter - inside-->
+    <string name="contact_diary_person_encounter_environment_inside">"Kapalı ortam"</string>
+    <!-- XTXT: Option - person encounter - circumstances hint-->
+    <string name="contact_diary_person_encounter_circumstances_hint">"Not (ör. yakın mesafe)"</string>
+
+
+    <!-- XBUT: Option - person encounter - inside-->
+    <string name="contact_diary_location_visit_duration_label">"Süre"</string>
+    <!-- XTXT: Option - person encounter - circumstances hint-->
+    <string name="contact_diary_location_visit_circumstances_hint">"Not (ör. çok dolu)"</string>
 </resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values-tr/release_info_strings.xml b/Corona-Warn-App/src/main/res/values-tr/release_info_strings.xml
index 11084f58b7e4126e7ab7ffb8abef6168d3ffd899..c29b757bb969656b1dc0b0e1663ac93110bd1386 100644
--- a/Corona-Warn-App/src/main/res/values-tr/release_info_strings.xml
+++ b/Corona-Warn-App/src/main/res/values-tr/release_info_strings.xml
@@ -1,6 +1,6 @@
 <?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">
     <!-- ####################################
-                 Release Info Screen 1.12
+                 Release Info Screen 1.14
      ###################################### -->
 
     <!-- XHED: Title for the release info screen -->
@@ -16,42 +16,34 @@
 
     <!-- XHED: Titles for the release info screen bullet points -->
     <string-array name="new_release_title">
-        <item>"RKI anketi bağlantısı"</item>
-        <item>"Veri Paylaşma İzni (isteğe bağlı)"</item>
-        <item>"Risk Kutucuklarındaki Değişiklikler"</item>
-        <item>"Rastgele Kimliklerinizi Paylaştıktan Sonra Maruz Kalma Günlüğüne Devam Etme"</item>
-        <item>"Sekmelerin Uygulanması"</item>
-        <item>"Test Prosedürü Hakkında Daha Fazla Bilgi"</item>
+        <item>"Temas Güncesindeki Ek Özellikler"</item>
+        <item>"Temas Güncesine Doğrudan Erişim"</item>
+        <item>"Risk Durumunuz Hakkında Daha Ayrıntılı Bilgi"</item>
+        <item>"Corona-Warn-App Ekran Görüntüleri"</item>
     </string-array>
 
     <!-- XTXT: Text bodies for the release info screen bullet points -->
     <string-array name="new_release_body">
-        <item>"Yüksek risk altındaysanız Robert Koch Institute tarafından sunulan bir anketi uygulamadan yanıtlayabilirsiniz."</item>
-        <item>"Kullanım verilerinizi paylaşarak uygulamayı iyileştirmemize yardımcı olma seçeneğine sahipsiniz."</item>
-        <item>"Risk kutucuklarındaki metinler üzerinde ufak değişiklikler."</item>
-        <item>"Şifrelenmiş rastgele kimliklerinizi paylaştıktan sonra maruz kalma günlüğünü yeniden açmak isteyip istemediğinize ve ne zaman yeniden açacağınıza karar verebilirsiniz."</item>
-        <item>"Temas günceniz için ayrı bir sekme sayfası eklenmiştir. Bu sayede, daha hızlı bir şekilde güncenize erişebilir ve temas güncenizden uygulamanızın ana ekranına geri dönebilirsiniz."</item>
-        <item>"Uygulama artık test prosedürü hakkında daha ayrıntılı bilgiler içermektedir."</item>
+        <item>"Artık her bir karşılaşma için belirli koşullar girebilirsiniz. Önceden tanımlanmış seçenekler (örneğin karşılaşmanın süresi, maske takılı olup olmadığı) arasından seçim yapabilir ve yüksek riske neden olabilecek diğer koşulları kaydetmek için kısa bir not da ekleyebilirsiniz. Enfekte olmanız halinde bu bilgiler kamu sağlığı yetkilisinin potansiyel enfeksiyon zincirlerini takip etmesine yardımcı olabilir."</item>
+        <item>"Artık önce uygulamayı açmanız gerekmeden doğrudan temas güncenize giriş ekleyebilirsiniz. Bunun için, bir menü görüntülenene dek yaklaşık 2 saniye süreyle Corona-Warn-App simgesine basılı tutun ve ardından “Bugün için Günce Girişi Ekle” seçeneğine dokunun."</item>
+        <item>"Uygulama, yüksek risk altında olduğunuzu belirtiyorsa artık risk durumunun, yüksek riskli bir veya daha fazla maruz kalmaya göre mi yoksa düşük riskli bir veya daha fazla maruz kalmaya göre mi görüntülendiğini görebilirsiniz."</item>
+        <item>"https://www.coronawarn.app adresindeki web sitesinde uygulamanın tüm ekran görüntüleri sunulmaktadır. Bu sayede, planlanan özellikler gibi çeşitli bilgileri edinebilirsiniz."</item>
     </string-array>
 
     <!-- XTXT: Text labels that will be converted to Links -->
     <string-array name="new_release_linkified_labels">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app"</item>
     </string-array>
 
     <!-- XTXT: URL destinations for the lables in new_release_linkified_labels -->
     <string-array name="new_release_target_urls">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
-        <item></item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app/en/screenshots"</item>
     </string-array>
 
 </resources>
\ No newline at end of file
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 dbb190211959b7022cf7bb1981658c5c2c0bca48..771a2ed84e25fd8f224652461450881497960131 100644
--- a/Corona-Warn-App/src/main/res/values-tr/strings.xml
+++ b/Corona-Warn-App/src/main/res/values-tr/strings.xml
@@ -323,8 +323,8 @@
 
     <!-- XMSG: risk details - link to faq, something like a bullet point -->
     <string name="risk_details_increased_risk_faq_link_text">"Test yaptırırsanız SSS bölümünde test prosedürü hakkında ek bilgi bulabilirsiniz."</string>
-    <!-- XTXT: Explanation screen increased risk level link label -->
-    <string name="risk_details_increased_risk_faq_link_label">"SSS: Test Prosedürü"</string>
+    <!-- XTXT: Explanation screen increased risk level link label - HAS TO MATCH the link text above -->
+    <string name="risk_details_increased_risk_faq_link_label">"SSS"</string>
     <!-- XTXT: Explains user about increased risk level: URL, has to be "translated" into english (relevant for all languages except german) - https://www.coronawarn.app/en/faq/#further_details -->
     <string name="risk_details_increased_risk_faq_url">"https://www.coronawarn.app/en/faq/#red_card_how_to_test"</string>
 
@@ -537,11 +537,11 @@
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - regional evaluation text -->
     <string name="onboarding_ppa_regional_evaluation_text">"Federal eyalet ve bölge bilgilerinizi de paylaşırsanız bölgesel analizler yapabiliriz."</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - age title -->
-    <string name="onboarding_ppa_age_title">"Yaşınız (isteğe bağlı)"</string>
+    <string name="onboarding_ppa_age_title">"Yaş grubunuz (isteğe bağlı)"</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - consent title -->
     <string name="onboarding_ppa_more_info_title">"ABD’de ve Diğer Üçüncü Ülkelerde Veri İşleme ve Veri Koruma Riskleri Hakkında Ayrıntılı Bilgiler"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - donate button -->
-    <string name="onboarding_ppa_consent_donate_button">"Verileri PaylaÅŸ"</string>
+    <string name="onboarding_ppa_consent_donate_button">"Kabul Et"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - dont donate button -->
     <string name="onboarding_ppa_consent_not_donate_button">"PaylaÅŸma"</string>
 
@@ -1754,6 +1754,9 @@
     <!-- XBUT: Abort button for test result positive no consent screen -->
     <string name="submission_test_result_positive_no_consent_button_abort">"Ä°ptal"</string>
 
+    <!-- XHED: Title of contact diary app shortcut -->
+    <string name="app_shortcut_contact_diary_title">"GiriÅŸ Ekle"</string>
+
     <!-- XTXT: Statistics information (Accessibilty) -->
     <string name="statistics_info_button">"Daha fazla bilgi"</string>
     <!-- XHED: Title for statistics reproduction card -->
@@ -1830,7 +1833,7 @@
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_UNSPECIFIED -->
     <string name="analytics_userinput_agegroup_unspecified">"Bilgi yok"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_0_TO_29 -->
-    <string name="analytics_userinput_agegroup_0_to_29">"0-29 yaÅŸ"</string>
+    <string name="analytics_userinput_agegroup_0_to_29">"29 yaÅŸa kadar"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_30_TO_59 -->
     <string name="analytics_userinput_agegroup_30_to_59">"30-59 yaÅŸ"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_FROM_60 -->
@@ -1877,4 +1880,17 @@
     <string name="analytics_userinput_district_title">"Bölgeniz (İlçe)"</string>
     <!-- XTXT: Analytics voluntary user input, district: UNSPECIFIED -->
     <string name="analytics_userinput_district_unspecified">"Bilgi yok"</string>
+
+    <!-- ####################################
+       Duration dialog
+   ###################################### -->
+
+    <!-- XHED: Duration dialog title -->
+    <string name="duration_dialog_title">"Süre"</string>
+    <!-- XBUT: Duration dialog cancel button -->
+    <string name="duration_dialog_cancel_button">"Ä°ptal Et"</string>
+    <!-- XBUT: Duration dialog ok button -->
+    <string name="duration_dialog_ok_button">"Tamam"</string>
+    <!-- NOTR -->
+    <string name="duration_dialog_default_value">"00:00"</string>
 </resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml
index b7276c4c7e70bbcdae399d81b0bc44473134dfad..5a610c20973298353c67e836344802a78111b1b0 100644
--- a/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml
+++ b/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml
@@ -12,9 +12,9 @@
     <string name="contact_diary_person_list_no_items_title">"No people defined yet"</string>
     <string name="contact_diary_person_list_no_items_subtitle">"Create a person and add them to your contact journal."</string>
     <string name="contact_diary_add_person_title">"Person"</string>
-    <string name="contact_diary_add_person_text_input_name_hint">"Name"</string>
-    <string name="contact_diary_add_text_input_phone_hint" />
-    <string name="contact_diary_add_text_input_email_hint"/>
+    <string name="contact_diary_add_person_text_input_name_hint">"First name, last name"</string>
+    <string name="contact_diary_add_text_input_phone_hint">"Phone"</string>
+    <string name="contact_diary_add_text_input_email_hint">"e-mail"</string>
     <string name="contact_diary_add_person_save_button">"Save"</string>
     <string name="contact_diary_add_location_title">"Place"</string>
     <string name="contact_diary_add_location_text_input_hint">"Description"</string>
@@ -74,7 +74,7 @@
     <!-- XTXT: Body for contact diary overview screen risk information -->
     <string name="contact_diary_risk_body">"based on the encounters evaluated by the app."</string>
     <!-- XTXT: Body for contact diary overview screen risk information when high risk due to low risk encounters-->
-    <string name="contact_diary_risk_body_high_risk_due_to_low_risk_encounters">"based on several encounters with low risk."</string>
+    <string name="contact_diary_risk_body_high_risk_due_to_low_risk_encounters">"based on multiple exposures with low risk."</string>
     <!-- XTXT: Extended Body for contact diary overview screen risk information -->
     <string name="contact_diary_risk_body_extended">"They are not necessarily related to the people and places you have recorded."</string>
 
@@ -146,11 +146,11 @@
     <string name="contact_diary_overview_location_duration_suffix" translatable="false">"Std."</string>
 
     <!-- XHED: Title for the contact diary comment info screen -->
-    <string name="contact_diary_comment_info_screen_title">"Notiz"</string>
+    <string name="contact_diary_comment_info_screen_title">"Note"</string>
     <!-- XTXT: Description for contact diary comment info screen -->
-    <string name="contact_diary_comment_info_screen_description">"Hier können Sie Notizen machen, die Ihnen helfen, das Risiko einer Infektion besser einzuschätzen."</string>
+    <string name="contact_diary_comment_info_screen_description">"You can enter notes here that will help you to better estimate your risk of infection."</string>
     <!-- XTXT: Body for contact diary comment info screen -->
-    <string name="contact_diary_comment_info_screen_body">"Notieren Sie Umstände, die zu einem erhöhten Risiko führen könnten, z.B. räumliche Nähe zu anderen Personen oder die Ausübung einer Tätigkeit, die sich auf die Luftqualität auswirkt (Beispiele: „saßen nah beieinander“, „es wurde Sport getrieben“, „wir haben gesungen“).\n\nSollten Sie sich tatsächlich anstecken, können diese Notizen auch dem Gesundheitsamt bei der Nachverfolgung möglicher Infektionsketten helfen."</string>
+    <string name="contact_diary_comment_info_screen_body">"Write down the circumstances that could result in an increased risk, for example, how close you were to other people or things you did that could affect the air quality (examples: “sat close together”, “played sports”, “little space”, “we sang”).\n\nIf you become infected, this information can also help the public health authority trace potential chains of infection."</string>
 
     <!-- XTXT: location (description for screen readers) -->
     <string name="accessibility_location">"Place %s"</string>
@@ -175,28 +175,28 @@
     <string name="accessibility_edit">"Edit"</string>
 
     <!-- XACT: Add Person Button (description for screen readers) -->
-    <string name="accessibility_day_add_person">""</string>
+    <string name="accessibility_day_add_person">"Add Person"</string>
     <!-- XACT: Add Location Button (description for screen readers) -->
-    <string name="accessibility_day_add_location">""</string>
+    <string name="accessibility_day_add_location">"Add Place"</string>
 
     <!-- XBUT: Option - person encounter - below 15 Min -->
-    <string name="contact_diary_person_encounter_duration_below_15_min">unter 15 Min</string>
+    <string name="contact_diary_person_encounter_duration_below_15_min">"Less than 15 min"</string>
     <!-- XBUT: Option - person encounter - above 15 Min -->
-    <string name="contact_diary_person_encounter_duration_above_15_min">über 15 Min</string>
+    <string name="contact_diary_person_encounter_duration_above_15_min">"More than 15 min"</string>
     <!-- XBUT: Option - person encounter - with mask -->
-    <string name="contact_diary_person_encounter_mask_with">mit Maske</string>
+    <string name="contact_diary_person_encounter_mask_with">"With mask"</string>
     <!-- XBUT: Option - person encounter - without mask -->
-    <string name="contact_diary_person_encounter_mask_without">ohne Maske</string>
+    <string name="contact_diary_person_encounter_mask_without">"Without mask"</string>
     <!-- XBUT: Option - person encounter - outside -->
-    <string name="contact_diary_person_encounter_environment_outside">im Freien</string>
+    <string name="contact_diary_person_encounter_environment_outside">"Outdoors"</string>
     <!-- XBUT: Option - person encounter - inside-->
-    <string name="contact_diary_person_encounter_environment_inside">drinnen</string>
+    <string name="contact_diary_person_encounter_environment_inside">"Indoors"</string>
     <!-- XTXT: Option - person encounter - circumstances hint-->
-    <string name="contact_diary_person_encounter_circumstances_hint">Notiz (z.B. geringer Abstand)</string>
+    <string name="contact_diary_person_encounter_circumstances_hint">"Note (e.g. close distance)"</string>
 
 
     <!-- XBUT: Option - person encounter - inside-->
-    <string name="contact_diary_location_visit_duration_label">Dauer</string>
+    <string name="contact_diary_location_visit_duration_label">"Duration"</string>
     <!-- XTXT: Option - person encounter - circumstances hint-->
-    <string name="contact_diary_location_visit_circumstances_hint">Notiz (z.B. sehr voll)</string>
+    <string name="contact_diary_location_visit_circumstances_hint">"Note (e.g. very full)"</string>
 </resources>
diff --git a/Corona-Warn-App/src/main/res/values/release_info_strings.xml b/Corona-Warn-App/src/main/res/values/release_info_strings.xml
index 16d097b510a3ae8c0cf7f16b6c28ef2fc5cbc221..b8c27c66cf82e2b01ffe02bc9f8c4ac4ee88356d 100644
--- a/Corona-Warn-App/src/main/res/values/release_info_strings.xml
+++ b/Corona-Warn-App/src/main/res/values/release_info_strings.xml
@@ -1,7 +1,7 @@
 <?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">
     <!-- ####################################
-                 Release Info Screen 1.12
+                 Release Info Screen 1.14
      ###################################### -->
 
     <!-- XHED: Title for the release info screen -->
@@ -9,7 +9,7 @@
     <!-- XHED: Version title for the release info screen -->
     <string name="release_info_version_title">Release %1$s</string>
     <!-- XTXT: Description for the release info screen -->
-    <string name="release_info_version_body" />
+    <string name="release_info_version_body">"Along with bug fixes, this update also includes new and enhanced features."</string>
     <!-- XBUT: Continue button for the release info screen -->
     <string name="release_info_continue_button">"Next"</string>
     <!-- XTXT: New release info footer -->
@@ -17,34 +17,34 @@
 
     <!-- XHED: Titles for the release info screen bullet points -->
     <string-array name="new_release_title">
-        <item>EN: Zusatzfunktionen im Kontakt-Tagebuch</item>
-        <item>Direkter Zugriff auf Kontakt-Tagebuch</item>
-        <item>Mehr Details zum Risikostatus</item>
-        <item>Screenshots zur Corona-Warn-App</item>
+        <item>"Additional Features in the Contact Journal"</item>
+        <item>"Direct Access to Contact Journal"</item>
+        <item>"More Details about Your Risk Status"</item>
+        <item>"Screenshots for the Corona-Warn-App"</item>
     </string-array>
 
     <!-- XTXT: Text bodies for the release info screen bullet points -->
     <string-array name="new_release_body">
-        <item>EN: Sie können zu jedem Eintrag angeben, unter welchen Umständen die Begegnung stattfand. Sie können aus vorgegebenen Optionen auswählen (z.B. Dauer der Begegnung, mit oder ohne Maske) sowie zusätzlich in einer kurzen Notiz weitere Umstände erfassen, die zu einem erhöhten Risiko führen könnten. Sollten Sie sich tatsächlich anstecken, können diese Angaben dem Gesundheitsamt bei der Nachverfolgung möglicher Infektionsketten helfen.</item>
-        <item>Sie können nun direkt einen Eintrag im Kontakt-Tagebuch hinzufügen, ohne erst die App öffnen zu müssen. Tippen Sie dazu etwa 2 Sekunden lang auf das Icon der Corona-Warn-App bis ein Menü erscheint und tippen Sie dann auf "Tagebuch-Eintrag für heute hinzufügen“.</item>
-        <item>Wenn Ihnen in der App ein erhöhtes Risiko angezeigt wird, können Sie nun sehen, ob der Risikostatus aufgrund einer bzw. mehrerer Begegnungen mit erhöhtem Risiko angezeigt wird, oder aufgrund von mehreren Begegnungen mit niedrigem Risiko.</item>
-        <item>Auf https://www.coronawarn.app stehen nun alle Screenshots der App zu Verfügung. So können Sie sich nun auch über geplante Funktionen der App informieren.</item>
+        <item>"You can now enter the specific circumstances of each encounter. You can select from the predefined options (such as duration of the encounter, with or without mask) and also enter a brief note to record other circumstances that might result in an increased risk. If you become infected, this information can help the public health authority trace potential chains of infection."</item>
+        <item>"You can now add an entry to your contact journal directly, without having to open the app first. To do so, tap and hold the icon for the Corona-Warn-App for approximately 2 seconds, until a menu appears, and then tap “Add Journal Entry for Today”."</item>
+        <item>"If the app indicates that you have an increased risk, you can now see whether the risk status is displayed based on one or more exposures with an increased risk or one or more exposures with a low risk."</item>
+        <item>"The website https://www.coronawarn.app now contains all the screenshots for the app, so you can find out about planned features, for example."</item>
     </string-array>
 
     <!-- XTXT: Text labels that will be converted to Links -->
     <string-array name="new_release_linkified_labels">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item>https://www.coronawarn.app</item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app"</item>
     </string-array>
 
     <!-- XTXT: URL destinations for the lables in new_release_linkified_labels -->
     <string-array name="new_release_target_urls">
-        <item></item>
-        <item></item>
-        <item></item>
-        <item>https://www.coronawarn.app/en/screenshots</item>
+        <item/>
+        <item/>
+        <item/>
+        <item>"https://www.coronawarn.app/en/screenshots"</item>
     </string-array>
 
 </resources>
diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml
index de77c976edb37749ce346df5532e89ab9d307def..0ad1b02f4a76ef9b9514663baddd37633f5dad15 100644
--- a/Corona-Warn-App/src/main/res/values/strings.xml
+++ b/Corona-Warn-App/src/main/res/values/strings.xml
@@ -549,11 +549,11 @@
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - regional evaluation text -->
     <string name="onboarding_ppa_regional_evaluation_text">"If you also specify your federal state and region, we can conduct regional analyses."</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - age title -->
-    <string name="onboarding_ppa_age_title">"Your age (optional)"</string>
+    <string name="onboarding_ppa_age_title">"Your age group (optional)"</string>
     <!-- XTXT: onboarding privacy preserving analytics (ppa) - consent title -->
     <string name="onboarding_ppa_more_info_title">"Detailed Information about This Data Processing and Data Protection Risks in the U.S. and Other Third Countries"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - donate button -->
-    <string name="onboarding_ppa_consent_donate_button">"Share Data"</string>
+    <string name="onboarding_ppa_consent_donate_button">"Accept"</string>
     <!-- XBUT: onboarding privacy preserving analytics (ppa) - dont donate button -->
     <string name="onboarding_ppa_consent_not_donate_button">"Do Not Share"</string>
 
@@ -1771,7 +1771,7 @@
     <string name="submission_test_result_positive_no_consent_button_abort">"Cancel"</string>
 
     <!-- XHED: Title of contact diary app shortcut -->
-    <string name="app_shortcut_contact_diary_title">"Eintrag hinzufügen"</string>
+    <string name="app_shortcut_contact_diary_title">"Add Entry"</string>
 
     <!-- XTXT: Statistics information (Accessibilty) -->
     <string name="statistics_info_button">"Further information"</string>
@@ -1849,7 +1849,7 @@
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_UNSPECIFIED -->
     <string name="analytics_userinput_agegroup_unspecified">"No answer"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_0_TO_29 -->
-    <string name="analytics_userinput_agegroup_0_to_29">"0-29 years old"</string>
+    <string name="analytics_userinput_agegroup_0_to_29">"Up to 29"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_30_TO_59 -->
     <string name="analytics_userinput_agegroup_30_to_59">"30-59 years old"</string>
     <!-- XTXT: Analytics voluntary user input, age group: AGE_GROUP_FROM_60 -->
@@ -1902,11 +1902,11 @@
    ###################################### -->
 
     <!-- XHED: Duration dialog title -->
-    <string name="duration_dialog_title">Dauer</string>
+    <string name="duration_dialog_title">"Duration"</string>
     <!-- XBUT: Duration dialog cancel button -->
-    <string name="duration_dialog_cancel_button">Cancel</string>
+    <string name="duration_dialog_cancel_button">"Cancel"</string>
     <!-- XBUT: Duration dialog ok button -->
-    <string name="duration_dialog_ok_button">OK</string>
+    <string name="duration_dialog_ok_button">"OK"</string>
     <!-- NOTR -->
-    <string name="duration_dialog_default_value">00:00</string>
+    <string name="duration_dialog_default_value">"00:00"</string>
 </resources>
diff --git a/Corona-Warn-App/src/main/res/values/styles.xml b/Corona-Warn-App/src/main/res/values/styles.xml
index 246bcd8c0ff714441dc65d8b46af7f69909a1f5e..d1fc93e477682fd469efb0b74369d1b656953e38 100644
--- a/Corona-Warn-App/src/main/res/values/styles.xml
+++ b/Corona-Warn-App/src/main/res/values/styles.xml
@@ -477,8 +477,6 @@
         <item name="boxCornerRadiusTopStart">@dimen/spacing_mega_tiny</item>
         <item name="boxStrokeWidth">0dp</item>
         <item name="boxStrokeWidthFocused">0dp</item>
-        <item name="counterTextAppearance">@color/colorTransparent</item>
-        <item name="android:maxLength">5</item>
     </style>
 
     <style name="DefaultNumberPickerTheme" parent="AppTheme">
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/DurationExtensionKtTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/DurationExtensionKtTest.kt
index 4bfa961ca21dcfff47bb170e56e8c2441ee99680..84d647ea27cf50a0499fb23ca5d15a87d889d365 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/DurationExtensionKtTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/DurationExtensionKtTest.kt
@@ -54,4 +54,4 @@ internal class DurationExtensionKtTest {
         val suffix: String?,
         val expectedReadableDuration: String
     )
-}
\ No newline at end of file
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt
index a751d47446c7bd0fc5101c48c542e06ec0a65e6f..a9cab888e37c5c3870194c9da386a7dcbbcf3da4 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModelTest.kt
@@ -8,7 +8,8 @@ import de.rki.coronawarnapp.contactdiary.model.DefaultContactDiaryPerson
 import de.rki.coronawarnapp.contactdiary.model.DefaultContactDiaryPersonEncounter
 import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository
 import de.rki.coronawarnapp.contactdiary.ui.exporter.ContactDiaryExporter
-import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.ListItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day.DayOverviewItem
+import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.subheader.OverviewSubHeaderItem
 import de.rki.coronawarnapp.contactdiary.util.ContactDiaryData
 import de.rki.coronawarnapp.contactdiary.util.mockStringsForContactDiaryExporterTests
 import de.rki.coronawarnapp.risk.result.AggregatedRiskPerDateResult
@@ -109,9 +110,14 @@ open class ContactDiaryOverviewViewModelTest {
         verify(exactly = 1) { taskController.submit(any()) }
     }
 
+    @Test
+    fun `first item is subheader`() {
+        createInstance().listItems.getOrAwaitValue().first() is OverviewSubHeaderItem
+    }
+
     @Test
     fun `overview list lists all days as expected`() {
-        with(createInstance().listItems.getOrAwaitValue()) {
+        with(createInstance().listItems.getOrAwaitValue().filterIsInstance<DayOverviewItem>()) {
             size shouldBe ContactDiaryOverviewViewModel.DAY_COUNT
 
             var days = 0
@@ -129,7 +135,11 @@ open class ContactDiaryOverviewViewModelTest {
 
     @Test
     fun `navigate to day fragment with correct day`() {
-        val listItem = ListItem(date)
+        val listItem = DayOverviewItem(
+            date = date,
+            data = emptyList(),
+            risk = null
+        ) {}
 
         with(createInstance()) {
             onItemPress(listItem)
@@ -148,7 +158,11 @@ open class ContactDiaryOverviewViewModelTest {
         every { contactDiaryRepository.locationVisits } returns flowOf(listOf(locationVisit))
         every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf(listOf(aggregatedRiskPerDateResultLowRisk))
 
-        with(createInstance().listItems.getOrAwaitValue().first { it.date == date }) {
+        val item = createInstance().listItems.getOrAwaitValue().first {
+            it is DayOverviewItem && it.date == date
+        } as DayOverviewItem
+
+        with(item) {
             data.validate(
                 hasPerson = true,
                 hasLocation = true
@@ -166,7 +180,11 @@ open class ContactDiaryOverviewViewModelTest {
     fun `low risk without person or location`() {
         every { riskLevelStorage.aggregatedRiskPerDateResults } returns flowOf(listOf(aggregatedRiskPerDateResultLowRisk))
 
-        with(createInstance().listItems.getOrAwaitValue().first { it.date == date }) {
+        val item = createInstance().listItems.getOrAwaitValue().first {
+            it is DayOverviewItem && it.date == date
+        } as DayOverviewItem
+
+        with(item) {
             data.validate(
                 hasPerson = false,
                 hasLocation = false
@@ -190,7 +208,11 @@ open class ContactDiaryOverviewViewModelTest {
             )
         )
 
-        with(createInstance().listItems.getOrAwaitValue().first { it.date == date }) {
+        val item = createInstance().listItems.getOrAwaitValue().first {
+            it is DayOverviewItem && it.date == date
+        } as DayOverviewItem
+
+        with(item) {
             data.validate(
                 hasPerson = true,
                 hasLocation = true
@@ -212,7 +234,11 @@ open class ContactDiaryOverviewViewModelTest {
             )
         )
 
-        with(createInstance().listItems.getOrAwaitValue().first { it.date == date }) {
+        val item = createInstance().listItems.getOrAwaitValue().first {
+            it is DayOverviewItem && it.date == date
+        } as DayOverviewItem
+
+        with(item) {
             data.validate(
                 hasPerson = false,
                 hasLocation = false
@@ -236,7 +262,11 @@ open class ContactDiaryOverviewViewModelTest {
             )
         )
 
-        with(createInstance().listItems.getOrAwaitValue().first { it.date == date }) {
+        val item = createInstance().listItems.getOrAwaitValue().first {
+            it is DayOverviewItem && it.date == date
+        } as DayOverviewItem
+
+        with(item) {
             data.validate(
                 hasPerson = true,
                 hasLocation = true
@@ -258,7 +288,11 @@ open class ContactDiaryOverviewViewModelTest {
             )
         )
 
-        with(createInstance().listItems.getOrAwaitValue().first { it.date == date }) {
+        val item = createInstance().listItems.getOrAwaitValue().first {
+            it is DayOverviewItem && it.date == date
+        } as DayOverviewItem
+
+        with(item) {
             data.validate(
                 hasPerson = false,
                 hasLocation = false
@@ -298,7 +332,7 @@ open class ContactDiaryOverviewViewModelTest {
         }
     }
 
-    private fun List<ListItem.Data>.validate(hasPerson: Boolean, hasLocation: Boolean) {
+    private fun List<DayOverviewItem.Data>.validate(hasPerson: Boolean, hasLocation: Boolean) {
         var count = 0
         if (hasPerson) count++
         if (hasLocation) count++
@@ -306,17 +340,21 @@ open class ContactDiaryOverviewViewModelTest {
         size shouldBe count
         forEach {
             when (it.type) {
-                ListItem.Type.PERSON -> {
+                DayOverviewItem.Type.PERSON -> {
                     it.drawableId shouldBe R.drawable.ic_contact_diary_person_item
                 }
-                ListItem.Type.LOCATION -> {
+                DayOverviewItem.Type.LOCATION -> {
                     it.drawableId shouldBe R.drawable.ic_contact_diary_location_item
                 }
             }
         }
     }
 
-    private fun ListItem.Risk.validate(highRisk: Boolean, dueToLowEncounters: Boolean, hasPersonOrLocation: Boolean) {
+    private fun DayOverviewItem.Risk.validate(
+        highRisk: Boolean,
+        dueToLowEncounters: Boolean,
+        hasPersonOrLocation: Boolean
+    ) {
         when (highRisk) {
             true -> {
                 title shouldBe R.string.contact_diary_high_risk_title
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionCollectorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionCollectorTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ac0144363e0d88499e81d547406dfd63295e2f59
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionCollectorTest.kt
@@ -0,0 +1,3 @@
+package de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission
+
+class AnalyticsKeySubmissionCollectorTest
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionDonorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionDonorTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..252fa5d3b015fc6d749f9c1188bfe66fce6d568b
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/datadonation/analytics/modules/keysubmission/AnalyticsKeySubmissionDonorTest.kt
@@ -0,0 +1,3 @@
+package de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission
+
+class AnalyticsKeySubmissionDonorTest
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/release/NewReleaseInfoFragmentTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/release/NewReleaseInfoFragmentTest.kt
index 4e8a58260c50bdb7856b437d526c9aa1feefbaf0..a010e57352bade4d619e8f758aac8388a88196e9 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/release/NewReleaseInfoFragmentTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/release/NewReleaseInfoFragmentTest.kt
@@ -53,6 +53,10 @@ class NewReleaseInfoFragmentTest : BaseTest() {
     @Test
     fun `ensure TURKISH new release info arrays are of equal length`() = loadAndCompareStringArrayResources()
 
+    @Config(qualifiers = "bg")
+    @Test
+    fun `ensure BULGARIAN new release info arrays are of equal length`() = loadAndCompareStringArrayResources()
+
     @Config(qualifiers = "fr")
     @Test
     fun `ensure DEFAULT aka FRENCH new release info arrays are of equal length`() = loadAndCompareStringArrayResources()
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/release/NewReleaseInfoViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/release/NewReleaseInfoViewModelTest.kt
index f9ae8c5c3879e6d6417e0ee3c51ecd8fa41c555f..04d9af9abf9d1e52c2f65fa2a6388a23d5a48704 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/release/NewReleaseInfoViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/release/NewReleaseInfoViewModelTest.kt
@@ -1,6 +1,8 @@
 package de.rki.coronawarnapp.release
 
+import de.rki.coronawarnapp.datadonation.analytics.storage.AnalyticsSettings
 import de.rki.coronawarnapp.main.CWASettings
+import de.rki.coronawarnapp.util.preferences.FlowPreference
 import io.kotest.matchers.shouldBe
 import io.mockk.MockKAnnotations
 import io.mockk.Runs
@@ -10,29 +12,49 @@ import io.mockk.just
 import org.junit.jupiter.api.BeforeEach
 import org.junit.jupiter.api.Test
 import org.junit.jupiter.api.extension.ExtendWith
+import testhelpers.BaseTest
 import testhelpers.TestDispatcherProvider
 import testhelpers.extensions.InstantExecutorExtension
+import testhelpers.preferences.mockFlowPreference
 
 @ExtendWith(InstantExecutorExtension::class)
-class NewReleaseInfoViewModelTest {
+class NewReleaseInfoViewModelTest : BaseTest() {
 
-    @MockK lateinit var settings: CWASettings
+    @MockK lateinit var appSettings: CWASettings
+    @MockK lateinit var analyticsSettings: AnalyticsSettings
+    private lateinit var lastOnboardingVersionCode: FlowPreference<Long>
     lateinit var viewModel: NewReleaseInfoViewModel
 
     @BeforeEach
     fun setUp() {
         MockKAnnotations.init(this)
-        every { settings.lastChangelogVersion.update(any()) } just Runs
+        lastOnboardingVersionCode = mockFlowPreference(0L)
+        every { analyticsSettings.lastOnboardingVersionCode } returns lastOnboardingVersionCode
+
+        every { appSettings.lastChangelogVersion.update(any()) } just Runs
         viewModel = NewReleaseInfoViewModel(
             TestDispatcherProvider(),
-            settings
+            appSettings,
+            analyticsSettings
         )
     }
 
     @Test
-    fun testOnNextButtonClick() {
+    fun `if analytics onboarding has not yet been done, navigate to it`() {
+        lastOnboardingVersionCode.value shouldBe 0L
+
+        viewModel.onNextButtonClick()
+        viewModel.routeToScreen.value shouldBe NewReleaseInfoNavigationEvents.NavigateToOnboardingDeltaAnalyticsFragment
+    }
+
+    @Test
+    fun `if analytics onboarding is done, just close the release screen`() {
+        lastOnboardingVersionCode.update { 1130000L }
+
         viewModel.onNextButtonClick()
         viewModel.routeToScreen.value shouldBe NewReleaseInfoNavigationEvents.CloseScreen
+
+        lastOnboardingVersionCode.value shouldBe 1130000L
     }
 
     @Test
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 cd1f01845abb25bdb5a2c12a4e7a07d27731a23d..e78e650721b97d777d8d9409d12eca30d09271ea 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
@@ -1,5 +1,6 @@
 package de.rki.coronawarnapp.storage
 
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.deadman.DeadmanNotificationScheduler
 import de.rki.coronawarnapp.playbook.BackgroundNoise
 import de.rki.coronawarnapp.service.submission.SubmissionService
@@ -51,6 +52,7 @@ class SubmissionRepositoryTest : BaseTest() {
     @MockK lateinit var encryptedPreferencesFactory: EncryptedPreferencesFactory
     @MockK lateinit var encryptionErrorResetTool: EncryptionErrorResetTool
     @MockK lateinit var deadmanNotificationScheduler: DeadmanNotificationScheduler
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     private val guid = "123456-12345678-1234-4DA7-B166-B86D85475064"
     private val tan = "123456-12345678-1234-4DA7-B166-B86D85475064"
@@ -94,7 +96,8 @@ class SubmissionRepositoryTest : BaseTest() {
         submissionService = submissionService,
         timeStamper = timeStamper,
         tekHistoryStorage = tekHistoryStorage,
-        deadmanNotificationScheduler = deadmanNotificationScheduler
+        deadmanNotificationScheduler = deadmanNotificationScheduler,
+        analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
     )
 
     @Test
@@ -106,6 +109,7 @@ class SubmissionRepositoryTest : BaseTest() {
         every { LocalData.isAllowedToSubmitDiagnosisKeys(any()) } just Runs
         every { LocalData.isTestResultAvailableNotificationSent(any()) } just Runs
         every { LocalData.numberOfSuccessfulSubmissions(any()) } just Runs
+        every { analyticsKeySubmissionCollector.reset() } just Runs
 
         submissionRepository.removeTestFromDevice()
 
@@ -123,6 +127,7 @@ class SubmissionRepositoryTest : BaseTest() {
     @Test
     fun registrationWithGUIDSucceeds() = runBlockingTest {
         coEvery { submissionService.asyncRegisterDeviceViaGUID(guid) } returns registrationData
+        coEvery { analyticsKeySubmissionCollector.reportTestRegistered() } just Runs
 
         val submissionRepository = createInstance(scope = this)
 
@@ -139,6 +144,8 @@ class SubmissionRepositoryTest : BaseTest() {
     @Test
     fun registrationWithTeleTANSucceeds() = runBlockingTest {
         coEvery { submissionService.asyncRegisterDeviceViaTAN(tan) } returns registrationData
+        coEvery { analyticsKeySubmissionCollector.reportTestRegistered() } just Runs
+        every { analyticsKeySubmissionCollector.reportRegisteredWithTeleTAN() } just Runs
 
         val submissionRepository = createInstance(scope = this)
 
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 fdcb70d740fe07a8e7996a7d984c498a3980e6a9..f5e67e1b5f43d10e8739f91da62534ef7b022aaa 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
@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.submission.task
 import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
 import de.rki.coronawarnapp.appconfig.AppConfigProvider
 import de.rki.coronawarnapp.appconfig.ConfigData
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException
 import de.rki.coronawarnapp.notification.ShareTestResultNotificationService
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
@@ -56,10 +57,9 @@ class SubmissionTaskTest : BaseTest() {
     @MockK lateinit var tek: TemporaryExposureKey
     @MockK lateinit var userSymptoms: Symptoms
     @MockK lateinit var transformedKey: TemporaryExposureKeyExportOuterClass.TemporaryExposureKey
-
     @MockK lateinit var appConfigData: ConfigData
-
     @MockK lateinit var timeStamper: TimeStamper
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     private lateinit var settingSymptomsPreference: FlowPreference<Symptoms?>
 
@@ -101,6 +101,9 @@ class SubmissionTaskTest : BaseTest() {
 
         coEvery { playbook.submit(any()) } just Runs
 
+        every { analyticsKeySubmissionCollector.reportSubmitted() } just Runs
+        every { analyticsKeySubmissionCollector.reportSubmittedInBackground() } just Runs
+
         every { shareTestResultNotificationService.cancelSharePositiveTestResultNotification() } just Runs
         every { testResultAvailableNotificationService.cancelTestResultAvailableNotification() } just Runs
 
@@ -118,7 +121,8 @@ class SubmissionTaskTest : BaseTest() {
         shareTestResultNotificationService = shareTestResultNotificationService,
         timeStamper = timeStamper,
         autoSubmission = autoSubmission,
-        testResultAvailableNotificationService = testResultAvailableNotificationService
+        testResultAvailableNotificationService = testResultAvailableNotificationService,
+        analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
     )
 
     @Test
@@ -148,6 +152,9 @@ class SubmissionTaskTest : BaseTest() {
                 )
             )
 
+            analyticsKeySubmissionCollector.reportSubmitted()
+            analyticsKeySubmissionCollector.reportSubmittedInBackground()
+
             tekHistoryStorage.clear()
             settingSymptomsPreference.update(match { it.invoke(mockk()) == null })
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsViewModelTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7c07b541dc8e7355c3eb832482cc7099623cf2d1
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/onboarding/OnboardingAnalyticsViewModelTest.kt
@@ -0,0 +1,84 @@
+package de.rki.coronawarnapp.ui.onboarding
+
+import de.rki.coronawarnapp.datadonation.analytics.Analytics
+import de.rki.coronawarnapp.datadonation.analytics.common.Districts
+import de.rki.coronawarnapp.datadonation.analytics.storage.AnalyticsSettings
+import de.rki.coronawarnapp.environment.BuildConfigWrap
+import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData.PPAAgeGroup
+import de.rki.coronawarnapp.server.protocols.internal.ppdd.PpaData.PPAFederalState
+import de.rki.coronawarnapp.util.preferences.FlowPreference
+import io.kotest.matchers.shouldBe
+import io.mockk.MockKAnnotations
+import io.mockk.Runs
+import io.mockk.coEvery
+import io.mockk.coVerify
+import io.mockk.every
+import io.mockk.impl.annotations.MockK
+import io.mockk.just
+import io.mockk.mockkObject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.test.runBlockingTest
+import org.junit.jupiter.api.BeforeEach
+import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+import testhelpers.BaseTest
+import testhelpers.TestDispatcherProvider
+import testhelpers.extensions.InstantExecutorExtension
+import testhelpers.preferences.mockFlowPreference
+
+@ExtendWith(InstantExecutorExtension::class)
+class OnboardingAnalyticsViewModelTest : BaseTest() {
+
+    @MockK lateinit var settings: AnalyticsSettings
+    @MockK lateinit var analytics: Analytics
+    @MockK lateinit var districts: Districts
+    private lateinit var lastOnboardingVersionCode: FlowPreference<Long>
+
+    @BeforeEach
+    fun setUp() {
+        MockKAnnotations.init(this)
+        lastOnboardingVersionCode = mockFlowPreference(0L)
+
+        every { settings.lastOnboardingVersionCode } returns lastOnboardingVersionCode
+        every { settings.userInfoAgeGroup } returns mockFlowPreference(PPAAgeGroup.AGE_GROUP_UNSPECIFIED)
+        every { settings.userInfoDistrict } returns mockFlowPreference(0)
+        every { settings.userInfoFederalState } returns mockFlowPreference(PPAFederalState.FEDERAL_STATE_UNSPECIFIED)
+
+        coEvery { analytics.setAnalyticsEnabled(any()) } just Runs
+
+        mockkObject(BuildConfigWrap)
+        every { BuildConfigWrap.VERSION_CODE } returns 1234567890L
+    }
+
+    private fun createInstance(scope: CoroutineScope) = OnboardingAnalyticsViewModel(
+        appScope = scope,
+        dispatcherProvider = TestDispatcherProvider(),
+        analytics = analytics,
+        districts = districts,
+        settings = settings
+    )
+
+    @Test
+    fun `accepting ppa updates versioncode and state `() {
+        lastOnboardingVersionCode.value shouldBe 0L
+
+        runBlockingTest {
+            createInstance(scope = this).onProceed(true)
+        }
+
+        coVerify { analytics.setAnalyticsEnabled(true) }
+        lastOnboardingVersionCode.value shouldBe 1234567890L
+    }
+
+    @Test
+    fun `declining ppa updates versioncode and state`() {
+        lastOnboardingVersionCode.value shouldBe 0L
+
+        runBlockingTest {
+            createInstance(scope = this).onProceed(false)
+        }
+
+        coVerify { analytics.setAnalyticsEnabled(false) }
+        lastOnboardingVersionCode.value shouldBe 1234567890L
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt
index 2467d7099a012f4b09496e9165e2e8f9dc39415c..5e1f894d73b3e3296a5664e021376872cef265b7 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/qrcode/consent/SubmissionConsentViewModelTest.kt
@@ -1,6 +1,7 @@
 package de.rki.coronawarnapp.ui.submission.qrcode.consent
 
 import com.google.android.gms.common.api.ApiException
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.nearby.modules.tekhistory.TEKHistoryProvider
 import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository
 import de.rki.coronawarnapp.submission.SubmissionRepository
@@ -30,6 +31,7 @@ class SubmissionConsentViewModelTest {
     @MockK lateinit var submissionRepository: SubmissionRepository
     @MockK lateinit var interoperabilityRepository: InteroperabilityRepository
     @MockK lateinit var tekHistoryProvider: TEKHistoryProvider
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     lateinit var viewModel: SubmissionConsentViewModel
 
@@ -40,11 +42,13 @@ class SubmissionConsentViewModelTest {
         MockKAnnotations.init(this)
         every { interoperabilityRepository.countryList } returns MutableStateFlow(countryList)
         every { submissionRepository.giveConsentToSubmission() } just Runs
+        every { analyticsKeySubmissionCollector.reportAdvancedConsentGiven() } just Runs
         viewModel = SubmissionConsentViewModel(
             submissionRepository,
             interoperabilityRepository,
             dispatcherProvider = TestDispatcherProvider(),
-            tekHistoryProvider
+            tekHistoryProvider,
+            analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
         )
     }
 
@@ -74,6 +78,7 @@ class SubmissionConsentViewModelTest {
 
     @Test
     fun `giveGoogleConsentResult when user Allows routes to QR Code scan`() {
+        every { analyticsKeySubmissionCollector.reportAdvancedConsentGiven() } just Runs
         viewModel.giveGoogleConsentResult(true)
         viewModel.routeToScreen.value shouldBe SubmissionNavigationEvents.NavigateToQRCodeScan
     }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/symptoms/calendar/SubmissionSymptomCalendarViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/symptoms/calendar/SubmissionSymptomCalendarViewModelTest.kt
index 05498c26cd671904a1907733501eb9f9c218d45d..835ce668dbbfcd9ec40525b1576bbdb0f722fd56 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/symptoms/calendar/SubmissionSymptomCalendarViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/symptoms/calendar/SubmissionSymptomCalendarViewModelTest.kt
@@ -1,5 +1,6 @@
 package de.rki.coronawarnapp.ui.submission.symptoms.calendar
 
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.Symptoms
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -29,6 +30,7 @@ class SubmissionSymptomCalendarViewModelTest : BaseTest() {
 
     @MockK lateinit var submissionRepository: SubmissionRepository
     @MockK lateinit var autoSubmission: AutoSubmission
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
     private lateinit var currentSymptoms: FlowPreference<Symptoms?>
 
     @BeforeEach
@@ -48,7 +50,8 @@ class SubmissionSymptomCalendarViewModelTest : BaseTest() {
             symptomIndication = indication,
             dispatcherProvider = TestDispatcherProvider(),
             submissionRepository = submissionRepository,
-            autoSubmission = autoSubmission
+            autoSubmission = autoSubmission,
+            analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
         )
 
     @Test
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/symptoms/introduction/SubmissionSymptomIntroductionViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/symptoms/introduction/SubmissionSymptomIntroductionViewModelTest.kt
index f067783b3477bc21e9bf2bfad233924ee2f3016f..250cb3f5c117bd403c560b54938e46396fd053fa 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/symptoms/introduction/SubmissionSymptomIntroductionViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/symptoms/introduction/SubmissionSymptomIntroductionViewModelTest.kt
@@ -1,5 +1,6 @@
 package de.rki.coronawarnapp.ui.submission.symptoms.introduction
 
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.Symptoms
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -28,6 +29,7 @@ class SubmissionSymptomIntroductionViewModelTest : BaseTest() {
 
     @MockK lateinit var submissionRepository: SubmissionRepository
     @MockK lateinit var autoSubmission: AutoSubmission
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
     private val currentSymptoms = mockFlowPreference<Symptoms?>(null)
 
     @BeforeEach
@@ -42,7 +44,8 @@ class SubmissionSymptomIntroductionViewModelTest : BaseTest() {
     private fun createViewModel() = SubmissionSymptomIntroductionViewModel(
         dispatcherProvider = TestDispatcherProvider(),
         submissionRepository = submissionRepository,
-        autoSubmission = autoSubmission
+        autoSubmission = autoSubmission,
+        analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
     )
 
     @Test
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testavailable/SubmissionTestResultAvailableViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testavailable/SubmissionTestResultAvailableViewModelTest.kt
index d6e16b3112e83ec35603db00d2ab694844e3ba21..f06833355235b74b2ecc8746f09cd475bf9fa929 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testavailable/SubmissionTestResultAvailableViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testavailable/SubmissionTestResultAvailableViewModelTest.kt
@@ -1,5 +1,6 @@
 package de.rki.coronawarnapp.ui.submission.testavailable
 
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
 import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryUpdater
@@ -29,6 +30,7 @@ class SubmissionTestResultAvailableViewModelTest : BaseTest() {
     @MockK lateinit var autoSubmission: AutoSubmission
     @MockK lateinit var tekHistoryUpdater: TEKHistoryUpdater
     @MockK lateinit var tekHistoryUpdaterFactory: TEKHistoryUpdater.Factory
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     @BeforeEach
     fun setUp() {
@@ -46,7 +48,8 @@ class SubmissionTestResultAvailableViewModelTest : BaseTest() {
         submissionRepository = submissionRepository,
         dispatcherProvider = TestDispatcherProvider(),
         tekHistoryUpdaterFactory = tekHistoryUpdaterFactory,
-        autoSubmission = autoSubmission
+        autoSubmission = autoSubmission,
+        analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
     )
 
     @Test
@@ -94,6 +97,7 @@ class SubmissionTestResultAvailableViewModelTest : BaseTest() {
     @Test
     fun `go to test result without updating TEK history if NO consent is given`() {
         every { submissionRepository.hasGivenConsentToSubmission } returns flowOf(false)
+        every { analyticsKeySubmissionCollector.reportConsentWithdrawn() } just Runs
         val viewModel = createViewModel()
 
         viewModel.proceed()
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultConsentGivenViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultConsentGivenViewModelTest.kt
index c84ea408def3e5f45cba933fdcde2aaf483b497c..757497cea3cf68b9202ee6aa258789c4940c54ad 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultConsentGivenViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/testresult/SubmissionTestResultConsentGivenViewModelTest.kt
@@ -1,5 +1,6 @@
 package de.rki.coronawarnapp.ui.submission.testresult
 
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
 import de.rki.coronawarnapp.submission.SubmissionRepository
 import de.rki.coronawarnapp.submission.auto.AutoSubmission
@@ -20,6 +21,7 @@ class SubmissionTestResultConsentGivenViewModelTest : BaseTest() {
     @MockK lateinit var submissionRepository: SubmissionRepository
     @MockK lateinit var autoSubmission: AutoSubmission
     @MockK lateinit var testResultAvailableNotificationService: TestResultAvailableNotificationService
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
     lateinit var viewModel: SubmissionTestResultConsentGivenViewModel
 
     @BeforeEach
@@ -31,7 +33,8 @@ class SubmissionTestResultConsentGivenViewModelTest : BaseTest() {
         submissionRepository = submissionRepository,
         dispatcherProvider = TestDispatcherProvider(),
         autoSubmission = autoSubmission,
-        testResultAvailableNotificationService = testResultAvailableNotificationService
+        testResultAvailableNotificationService = testResultAvailableNotificationService,
+        analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
     )
 
     @Test
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModelTest.kt
index eb91b4fafd41603c8c62dd43b8f3d65fdb411589..6b3e2fdc42a2b7829f254c762b2bf1e682637b0d 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/submission/warnothers/SubmissionResultPositiveOtherWarningNoConsentViewModelTest.kt
@@ -1,5 +1,6 @@
 package de.rki.coronawarnapp.ui.submission.warnothers
 
+import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
 import de.rki.coronawarnapp.nearby.ENFClient
 import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository
 import de.rki.coronawarnapp.submission.SubmissionRepository
@@ -31,6 +32,7 @@ class SubmissionResultPositiveOtherWarningNoConsentViewModelTest : BaseTest() {
     @MockK lateinit var tekHistoryUpdaterFactory: TEKHistoryUpdater.Factory
     @MockK lateinit var interoperabilityRepository: InteroperabilityRepository
     @MockK lateinit var enfClient: ENFClient
+    @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 
     @BeforeEach
     fun setUp() {
@@ -50,7 +52,8 @@ class SubmissionResultPositiveOtherWarningNoConsentViewModelTest : BaseTest() {
         autoSubmission = autoSubmission,
         enfClient = enfClient,
         interoperabilityRepository = interoperabilityRepository,
-        submissionRepository = submissionRepository
+        submissionRepository = submissionRepository,
+        analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
     )
 
     @Test
diff --git a/gradle.properties b/gradle.properties
index 9b0279b18b450e889f22c4827e04be18cfda289b..dd26c8008b0a8c7eee720e9465a64cb40e3df128 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -20,4 +20,4 @@ org.gradle.dependency.verification.console=verbose
 VERSION_MAJOR=1
 VERSION_MINOR=15
 VERSION_PATCH=0
-VERSION_BUILD=2
+VERSION_BUILD=4