diff --git a/.circleci/config.yml b/.circleci/config.yml
index 7d0ae9878ca1ee536fb639e7d081a61edfb8d011..da41853c01b3b421b31834a356171b8e748304aa 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -11,8 +11,8 @@ jobs:
     steps:
       - checkout
       - install-ndk:
-          ndk-sha: "50250fcba479de477b45801e2699cca47f7e1267"
-          ndk-version: "android-ndk-r21b"
+          ndk-sha: "c81a5bcb4672a18d3647bf6898cd4dbcb978d0e8"
+          ndk-version: "android-ndk-r21c"
       - restore-build-cache
       - restore_cache:
           key: jars-{{ checksum "build.gradle" }}-{{ checksum  "Corona-Warn-App/build.gradle" }}-{{ checksum  "Server-Protocol-Buffer/build.gradle" }}
@@ -36,4 +36,4 @@ workflows:
   version: 2
   workflow:
     jobs:
-      - quickBuildReleaseWithTestsAndChecks
\ No newline at end of file
+      - quickBuildReleaseWithTestsAndChecks
diff --git a/Corona-Warn-App/build.gradle b/Corona-Warn-App/build.gradle
index 42d442549310ad69e220027d210ea5411aade42c..ad0a14fdcb2ef010053ca246417671ffc15c69b1 100644
--- a/Corona-Warn-App/build.gradle
+++ b/Corona-Warn-App/build.gradle
@@ -25,7 +25,7 @@ apply plugin: "androidx.navigation.safeargs.kotlin"
 apply plugin: 'jacoco'
 
 android {
-    ndkVersion "21.1.6352462"
+    ndkVersion "21.2.6472646"
     compileSdkVersion 29
     buildToolsVersion "29.0.3"
 
@@ -33,8 +33,8 @@ android {
         applicationId 'de.rki.coronawarnapp'
         minSdkVersion 23
         targetSdkVersion 29
-        versionCode 8
-        versionName "0.8.1"
+        versionCode 9
+        versionName "0.8.2"
         testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
 
         buildConfigField "String", "DOWNLOAD_CDN_URL", "\"$DOWNLOAD_CDN_URL\""
@@ -142,12 +142,11 @@ task jacocoTestReport(type: JacocoReport, dependsOn: ['testDeviceReleaseUnitTest
 }
 
 dependencies {
-    api fileTree(dir: 'libs', include: ['play-services-nearby-18.0.2-eap.aar'])
-    implementation project(":Server-Protocol-Buffer")
-
-
+    // KOTLIN
     implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.7"
     implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+
+    // ANDROID STANDARD
     implementation 'androidx.appcompat:appcompat:1.1.0'
     implementation 'androidx.core:core-ktx:1.3.0'
     implementation 'com.google.android.material:material:1.1.0'
@@ -158,15 +157,13 @@ dependencies {
     implementation 'androidx.preference:preference:1.1.1'
     implementation 'androidx.work:work-runtime-ktx:2.3.4'
     implementation 'android.arch.lifecycle:extensions:1.1.1'
-    implementation 'com.android.volley:volley:1.1.1'
-    implementation 'com.squareup.okhttp3:okhttp:4.7.2'
-    implementation 'com.google.android.play:core:1.7.3'
-    implementation 'com.google.code.gson:gson:2.8.6'
-    implementation 'com.google.guava:guava:29.0-android'
+
+    // QR
     implementation('com.journeyapps:zxing-android-embedded:4.1.0') { transitive = false }
     // noinspection GradleDependency - needed for SDK 23 compatibility, in combination with com.journeyapps:zxing-android-embedded:4.1.0
     implementation 'com.google.zxing:core:3.3.0'
-    // implementation 'com.google.android.gms:play-services-nearby:18.0.2-eap'
+
+    // TESTING
     testImplementation 'junit:junit:4.13'
     testImplementation "org.mockito:mockito-core:3.3.3"
     testImplementation('org.robolectric:robolectric:4.3.1') {
@@ -181,23 +178,41 @@ dependencies {
     androidTestImplementation 'androidx.test.ext:truth:1.2.0'
     androidTestImplementation 'androidx.test.ext:junit:1.1.1'
 
-    implementation 'joda-time:joda-time:2.10.6'
 
+    // Play Services
+    implementation 'com.google.android.play:core:1.7.3'
     implementation 'com.google.android.gms:play-services-base:17.2.1'
     implementation 'com.google.android.gms:play-services-basement:17.2.1'
     implementation 'com.google.android.gms:play-services-safetynet:17.0.0'
     implementation 'com.google.android.gms:play-services-tasks:17.0.2'
+    api fileTree(dir: 'libs', include: ['play-services-nearby-18.0.2-eap.aar'])
 
-    def room_version = "2.2.5"
+    // HTTP
+    implementation 'com.squareup.retrofit2:retrofit:2.9.0'
+    implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
+    implementation ('com.squareup.retrofit2:converter-protobuf:2.9.0') {
+        exclude group: 'com.google.protobuf', module: 'protobuf-java'
+    }
+    implementation("com.squareup.okhttp3:logging-interceptor:4.7.2")
+    implementation 'com.squareup.okhttp3:okhttp:4.7.2'
 
+    // PERSISTENCE
+    def room_version = "2.2.5"
     implementation "androidx.room:room-runtime:$room_version"
     implementation "androidx.room:room-ktx:$room_version"
     implementation "androidx.room:room-guava:$room_version"
     kapt "androidx.room:room-compiler:$room_version"
+    implementation "androidx.sqlite:sqlite:2.0.1"
 
-    implementation "androidx.security:security-crypto:1.0.0-rc02"
+    // UTILS
+    implementation project(":Server-Protocol-Buffer")
+    implementation 'com.google.code.gson:gson:2.8.6'
+    implementation 'com.google.guava:guava:29.0-android'
+    implementation 'joda-time:joda-time:2.10.6'
 
+    // SECURITY
+    implementation "androidx.security:security-crypto:1.0.0-rc02"
     implementation 'net.zetetic:android-database-sqlcipher:4.4.0'
-    implementation "androidx.sqlite:sqlite:2.0.1"
+    implementation 'org.conscrypt:conscrypt-android:2.4.0'
 
 }
diff --git a/Corona-Warn-App/config/detekt.yml b/Corona-Warn-App/config/detekt.yml
index 6780100fbf1182df0877d17456ded6aed5f5d1a2..9cad3798d18540090f8b68a1d2ff5db08437dc99 100644
--- a/Corona-Warn-App/config/detekt.yml
+++ b/Corona-Warn-App/config/detekt.yml
@@ -410,7 +410,7 @@ performance:
     excludes: ['**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt']
   SpreadOperator:
     active: true
-    excludes: ['**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt']
+    excludes: ['**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt', '**/CertificatePinnerFactory.kt']
   UnnecessaryTemporaryInstantiation:
     active: true
 
diff --git a/Corona-Warn-App/proguard-rules.pro b/Corona-Warn-App/proguard-rules.pro
index d7f94bd58f371129aa8c14f41239dfdf970dfff7..98d843e33e802d99d96181ba29d639294f6343db 100644
--- a/Corona-Warn-App/proguard-rules.pro
+++ b/Corona-Warn-App/proguard-rules.pro
@@ -28,3 +28,33 @@
 # If you keep the line number information, uncomment this to
 # hide the original source file name.
 #-renamesourcefileattribute SourceFile
+
+# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
+# EnclosingMethod is required to use InnerClasses.
+-keepattributes Signature, InnerClasses, EnclosingMethod
+
+# Retrofit does reflection on method and parameter annotations.
+-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations
+
+# Retain service method parameters when optimizing.
+-keepclassmembers,allowshrinking,allowobfuscation interface * {
+    @retrofit2.http.* <methods>;
+}
+
+# Ignore annotation used for build tooling.
+-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
+
+# Ignore JSR 305 annotations for embedding nullability information.
+-dontwarn javax.annotation.**
+
+# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
+-dontwarn kotlin.Unit
+
+# Top-level functions that can only be used by Kotlin.
+-dontwarn retrofit2.KotlinExtensions
+-dontwarn retrofit2.KotlinExtensions$*
+
+# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
+# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
+-if interface * { @retrofit2.http.* <methods>; }
+-keep,allowobfuscation interface <1>
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/ExposureSummaryDaoTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/ExposureSummaryDaoTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1fd325556b1d9d09f0a0301e8fad91076864e555
--- /dev/null
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/ExposureSummaryDaoTest.kt
@@ -0,0 +1,75 @@
+package de.rki.coronawarnapp.storage
+
+import android.content.Context
+import androidx.room.Room
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * ExposureSummaryDao test.
+ */
+@RunWith(AndroidJUnit4::class)
+class ExposureSummaryDaoTest {
+    private lateinit var dao: ExposureSummaryDao
+    private lateinit var db: AppDatabase
+
+    @Before
+    fun setUp() {
+        val context = ApplicationProvider.getApplicationContext<Context>()
+        db = Room.inMemoryDatabaseBuilder(
+            context, AppDatabase::class.java).build()
+        dao = db.exposureSummaryDao()
+    }
+
+    /**
+     * Test Create / Read DB operations.
+     */
+    @Test
+    fun testCROperations() {
+        runBlocking {
+            val testEntity1 = ExposureSummaryEntity().apply {
+                this.daysSinceLastExposure = 1
+                this.matchedKeyCount = 1
+                this.maximumRiskScore = 1
+                this.summationRiskScore = 1
+            }
+
+            val testEntity2 = ExposureSummaryEntity().apply {
+                this.daysSinceLastExposure = 2
+                this.matchedKeyCount = 2
+                this.maximumRiskScore = 2
+                this.summationRiskScore = 2
+            }
+
+            assertThat(dao.getExposureSummaryEntities().isEmpty()).isTrue()
+
+            val id1 = dao.insertExposureSummaryEntity(testEntity1)
+            var selectAll = dao.getExposureSummaryEntities()
+            var selectLast = dao.getLatestExposureSummary()
+            assertThat(dao.getExposureSummaryEntities().isEmpty()).isFalse()
+            assertThat(selectAll.size).isEqualTo(1)
+            assertThat(selectAll[0].id).isEqualTo(id1)
+            assertThat(selectLast).isNotNull()
+            assertThat(selectLast?.id).isEqualTo(id1)
+
+            val id2 = dao.insertExposureSummaryEntity(testEntity2)
+            selectAll = dao.getExposureSummaryEntities()
+            selectLast = dao.getLatestExposureSummary()
+            assertThat(selectAll.isEmpty()).isFalse()
+            assertThat(selectAll.size).isEqualTo(2)
+            assertThat(selectLast).isNotNull()
+            assertThat(selectLast?.id).isEqualTo(id2)
+        }
+    }
+
+    @After
+    fun closeDb() {
+        db.close()
+    }
+}
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/keycache/KeyCacheDaoTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/keycache/KeyCacheDaoTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..d47bd985d1ef72dbe8c465e818576d32aa68418c
--- /dev/null
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/keycache/KeyCacheDaoTest.kt
@@ -0,0 +1,87 @@
+package de.rki.coronawarnapp.storage.keycache
+
+import android.content.Context
+import androidx.room.Room
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import de.rki.coronawarnapp.storage.AppDatabase
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * KeyCacheDao test.
+ */
+@RunWith(AndroidJUnit4::class)
+class KeyCacheDaoTest {
+    private lateinit var keyCacheDao: KeyCacheDao
+    private lateinit var db: AppDatabase
+
+    @Before
+    fun setUp() {
+        val context = ApplicationProvider.getApplicationContext<Context>()
+        db = Room.inMemoryDatabaseBuilder(
+            context, AppDatabase::class.java).build()
+        keyCacheDao = db.dateDao()
+    }
+
+    /**
+     * Test Create / Read / Delete DB operations.
+     */
+    @Test
+    fun testCRDOperations() {
+        runBlocking {
+            val dates = KeyCacheEntity().apply {
+                this.id = "0"
+                this.path = "0"
+                this.type = 0
+            }
+            val hours = KeyCacheEntity().apply {
+                this.id = "1"
+                this.path = "1"
+                this.type = 1
+            }
+
+            assertThat(keyCacheDao.getAllEntries().isEmpty()).isTrue()
+
+            keyCacheDao.insertEntry(dates)
+            keyCacheDao.insertEntry(hours)
+
+            var all = keyCacheDao.getAllEntries()
+
+            assertThat(all.size).isEqualTo(2)
+
+            val selectedDates = keyCacheDao.getDates()
+            assertThat(selectedDates.size).isEqualTo(1)
+            assertThat(selectedDates[0].type).isEqualTo(0)
+            assertThat(selectedDates[0].id).isEqualTo(dates.id)
+
+            val selectedHours = keyCacheDao.getHours()
+            assertThat(selectedHours.size).isEqualTo(1)
+            assertThat(selectedHours[0].type).isEqualTo(1)
+            assertThat(selectedHours[0].id).isEqualTo(hours.id)
+
+            keyCacheDao.clearHours()
+
+            all = keyCacheDao.getAllEntries()
+            assertThat(all.size).isEqualTo(1)
+            assertThat(all[0].type).isEqualTo(0)
+
+            keyCacheDao.insertEntry(hours)
+
+            assertThat(keyCacheDao.getAllEntries().size).isEqualTo(2)
+
+            keyCacheDao.clear()
+
+            assertThat(keyCacheDao.getAllEntries().isEmpty()).isTrue()
+        }
+    }
+
+    @After
+    fun closeDb() {
+        db.close()
+    }
+}
diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDaoTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDaoTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..797f5c58491b6f162aa7874e30941f930a0275cc
--- /dev/null
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDaoTest.kt
@@ -0,0 +1,73 @@
+package de.rki.coronawarnapp.storage.tracing
+
+import android.content.Context
+import androidx.room.Room
+import androidx.test.core.app.ApplicationProvider
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.google.common.truth.Truth.assertThat
+import de.rki.coronawarnapp.storage.AppDatabase
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import java.util.Date
+
+/**
+ * TracingIntervalDao test.
+ */
+@RunWith(AndroidJUnit4::class)
+class TracingIntervalDaoTest {
+    private lateinit var dao: TracingIntervalDao
+    private lateinit var db: AppDatabase
+
+    @Before
+    fun setUp() {
+        val context = ApplicationProvider.getApplicationContext<Context>()
+        db = Room.inMemoryDatabaseBuilder(
+            context, AppDatabase::class.java).build()
+        dao = db.tracingIntervalDao()
+    }
+
+    /**
+     * Test Create / Read / Delete DB operations.
+     */
+    @Test
+    fun testCRDOperations() {
+        runBlocking {
+            val oneDay = 24 * 60 * 60 * 1000
+            val today = Date().time
+            val testEntity = TracingIntervalEntity().apply {
+                // minus 1 day
+                this.from = today - oneDay
+                this.to = today
+            }
+
+            assertThat(dao.getAllIntervals().isEmpty()).isTrue()
+
+            dao.insertInterval(testEntity)
+
+            var select = dao.getAllIntervals()
+            assertThat(select.isEmpty()).isFalse()
+            assertThat(select.size).isEqualTo(1)
+            assertThat(select[0].from).isEqualTo(today - oneDay)
+            assertThat(select[0].to).isEqualTo(today)
+
+            dao.deleteOutdatedIntervals(today - 1)
+
+            select = dao.getAllIntervals()
+            assertThat(select.isEmpty()).isFalse()
+            assertThat(select.size).isEqualTo(1)
+
+            dao.deleteOutdatedIntervals(today + 1)
+            select = dao.getAllIntervals()
+            assertThat(select.isEmpty()).isTrue()
+        }
+    }
+
+    @After
+    fun closeDb() {
+        db.close()
+    }
+}
diff --git a/Corona-Warn-App/src/main/assets/pins.properties b/Corona-Warn-App/src/main/assets/pins.properties
new file mode 100644
index 0000000000000000000000000000000000000000..198e2e9bbfd58f9710527792369c0afe0fe7e132
--- /dev/null
+++ b/Corona-Warn-App/src/main/assets/pins.properties
@@ -0,0 +1,13 @@
+# TODO add certificate pinning
+#
+# Intermediates will be encoded like this:
+# openssl x509 -in CERTNAME -pubkey -noout | \
+# openssl pkey -pubin -outform der | \
+# openssl dgst -sha256 -binary | \
+# openssl enc -base64
+#
+# Format is sha256/BASE64ENCODED
+# Pins are delimited by ","
+SUBMISSION_PINS=
+DISTRIBUTION_PINS=
+VERIFICATION_PINS=
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt
index 3e151d6899fb6b99ea9b69bbea063ce0920ac544..c41efeec1fc396baeded15b70bc0895ba2aaceb4 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/CoronaWarnApplication.kt
@@ -13,6 +13,8 @@ import androidx.lifecycle.LifecycleObserver
 import androidx.lifecycle.OnLifecycleEvent
 import androidx.lifecycle.ProcessLifecycleOwner
 import de.rki.coronawarnapp.notification.NotificationHelper
+import org.conscrypt.Conscrypt
+import java.security.Security
 
 class CoronaWarnApplication : Application(), LifecycleObserver,
     Application.ActivityLifecycleCallbacks {
@@ -35,6 +37,8 @@ class CoronaWarnApplication : Application(), LifecycleObserver,
     override fun onCreate() {
         instance = this
         NotificationHelper.createNotificationChannel()
+        // Enable Conscrypt for TLS1.3 Support below API Level 29
+        Security.insertProviderAt(Conscrypt.newProvider(), 1)
         super.onCreate()
         ProcessLifecycleOwner.get().lifecycle.addObserver(this)
         registerActivityLifecycleCallbacks(this)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/TestForAPIFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/TestForAPIFragment.kt
index 907d9c8eea6ead66a765a1dad003caedaf24c853..e755d25ccb3434ad6177ccb4363950020b553eaa 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/TestForAPIFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/TestForAPIFragment.kt
@@ -32,6 +32,7 @@ import de.rki.coronawarnapp.nearby.InternalExposureNotificationPermissionHelper
 import de.rki.coronawarnapp.receiver.ExposureStateUpdateReceiver
 import de.rki.coronawarnapp.risk.TimeVariables
 import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange
+import de.rki.coronawarnapp.service.applicationconfiguration.ApplicationConfigurationService
 import de.rki.coronawarnapp.sharing.ExposureSharingService
 import de.rki.coronawarnapp.storage.AppDatabase
 import de.rki.coronawarnapp.storage.ExposureSummaryRepository
@@ -348,7 +349,7 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel
                     // only testing implementation: this is used to wait for the broadcastreceiver of the OS / EN API
                     InternalExposureNotificationClient.asyncProvideDiagnosisKeys(
                         googleFileList,
-                        getCustomConfig(),
+                        ApplicationConfigurationService.asyncRetrieveExposureConfiguration(),
                         token!!
                     )
                     showToast("Provided ${appleKeyList.size} keys to Google API with token $token")
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/TestRiskLevelCalculation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/TestRiskLevelCalculation.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b1f9739c044f88f797113232b76b5da0b37b7da1
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/TestRiskLevelCalculation.kt
@@ -0,0 +1,262 @@
+package de.rki.coronawarnapp
+
+import android.content.Intent
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Toast
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
+import androidx.lifecycle.Observer
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.viewModelScope
+import com.google.android.gms.nearby.exposurenotification.ExposureSummary
+import com.google.zxing.integration.android.IntentIntegrator
+import com.google.zxing.integration.android.IntentResult
+import de.rki.coronawarnapp.databinding.FragmentTestRiskLevelCalculationBinding
+import de.rki.coronawarnapp.exception.ExceptionCategory
+import de.rki.coronawarnapp.exception.TransactionException
+import de.rki.coronawarnapp.exception.report
+import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient
+import de.rki.coronawarnapp.risk.RiskLevel
+import de.rki.coronawarnapp.risk.TimeVariables
+import de.rki.coronawarnapp.server.protocols.AppleLegacyKeyExchange
+import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass
+import de.rki.coronawarnapp.service.applicationconfiguration.ApplicationConfigurationService
+import de.rki.coronawarnapp.sharing.ExposureSharingService
+import de.rki.coronawarnapp.storage.LocalData
+import de.rki.coronawarnapp.transaction.RetrieveDiagnosisKeysTransaction
+import de.rki.coronawarnapp.transaction.RiskLevelTransaction
+import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel
+import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel
+import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel
+import de.rki.coronawarnapp.util.KeyFileHelper
+import kotlinx.coroutines.launch
+import java.io.File
+import java.util.UUID
+import java.util.concurrent.TimeUnit
+
+@Suppress("MagicNumber")
+class TestRiskLevelCalculation : Fragment() {
+    companion object {
+        val TAG: String? = TestRiskLevelCalculation::class.simpleName
+    }
+
+    data class TransactionValues(
+        var appConfig: ApplicationConfigurationOuterClass.ApplicationConfiguration? = null,
+        var exposureSummary: ExposureSummary? = null,
+        var riskScore: Double? = null,
+        var riskLevel: RiskLevel? = null
+    )
+
+    private val tracingViewModel: TracingViewModel by activityViewModels()
+    private val settingsViewModel: SettingsViewModel by activityViewModels()
+    private val submissionViewModel: SubmissionViewModel by activityViewModels()
+    private lateinit var binding: FragmentTestRiskLevelCalculationBinding
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View? {
+        binding = FragmentTestRiskLevelCalculationBinding.inflate(inflater)
+        binding.tracingViewModel = tracingViewModel
+        binding.settingsViewModel = settingsViewModel
+        binding.submissionViewModel = submissionViewModel
+        binding.lifecycleOwner = this
+        return binding.root
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        binding.buttonRetrieveDiagnosisKeys.setOnClickListener {
+            tracingViewModel.viewModelScope.launch {
+                retrieveDiagnosisKeys()
+            }
+        }
+
+        binding.buttonProvideKeyViaQr.setOnClickListener {
+            scanLocalQRCodeAndProvide()
+        }
+
+        binding.buttonCalculateRiskLevel.setOnClickListener {
+            tracingViewModel.viewModelScope.launch {
+                calculateRiskLevel()
+            }
+        }
+
+        startObserving()
+    }
+
+    override fun onResume() {
+        super.onResume()
+        tracingViewModel.viewModelScope.launch {
+            RiskLevelTransaction.recordedTransactionValuesForTestingOnly = TransactionValues()
+            calculateRiskLevel()
+        }
+    }
+
+    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
+
+        val result: IntentResult? =
+            IntentIntegrator.parseActivityResult(requestCode, resultCode, data)
+        if (result != null) {
+            if (result.contents == null) {
+                Toast.makeText(requireContext(), "Cancelled", Toast.LENGTH_LONG).show()
+            } else {
+                ExposureSharingService.getOthersKeys(result.contents, onScannedKey)
+            }
+        } else {
+            super.onActivityResult(requestCode, resultCode, data)
+        }
+    }
+
+    private suspend fun retrieveDiagnosisKeys() {
+        try {
+            RetrieveDiagnosisKeysTransaction.start()
+        } catch (e: TransactionException) {
+            e.report(ExceptionCategory.INTERNAL)
+        }
+    }
+
+    private fun scanLocalQRCodeAndProvide() {
+        IntentIntegrator.forSupportFragment(this)
+            .setOrientationLocked(false)
+            .setBeepEnabled(false)
+            .initiateScan()
+    }
+
+    private val onScannedKey = { key: AppleLegacyKeyExchange.Key? ->
+        Log.i(TestForAPIFragment.TAG, "keys scanned..")
+        provideDiagnosisKey(key)
+    }
+
+    private fun provideDiagnosisKey(key: AppleLegacyKeyExchange.Key?) {
+        if (null == key) {
+            Toast.makeText(requireContext(), "No Key data found in QR code", Toast.LENGTH_SHORT)
+                .show()
+        } else {
+            val token = UUID.randomUUID().toString()
+            LocalData.googleApiToken(token)
+
+            val appleKeyList = mutableListOf<AppleLegacyKeyExchange.Key>()
+
+            appleKeyList.add(
+                AppleLegacyKeyExchange.Key.newBuilder()
+                    .setKeyData(key.keyData)
+                    .setRollingPeriod(144)
+                    .setRollingStartNumber(key.rollingStartNumber)
+                    .setTransmissionRiskLevel(1)
+                    .build()
+            )
+
+            val appleFiles = listOf(
+                AppleLegacyKeyExchange.File.newBuilder()
+                    .addAllKeys(appleKeyList)
+                    .build()
+            )
+
+            val dir =
+                File(File(requireContext().getExternalFilesDir(null), "key-export"), token)
+            dir.mkdirs()
+
+            var googleFileList: List<File>
+            lifecycleScope.launch {
+                googleFileList = KeyFileHelper.asyncCreateExportFiles(appleFiles, dir)
+
+                Log.i(
+                    TAG,
+                    "Provide ${googleFileList.count()} files with ${appleKeyList.size} keys with token $token"
+                )
+                try {
+                    // only testing implementation: this is used to wait for the broadcastreceiver of the OS / EN API
+                    InternalExposureNotificationClient.asyncProvideDiagnosisKeys(
+                        googleFileList,
+                        ApplicationConfigurationService.asyncRetrieveExposureConfiguration(),
+                        token
+                    )
+                    Toast.makeText(
+                        requireContext(),
+                        "Provided ${appleKeyList.size} keys to Google API with token $token",
+                        Toast.LENGTH_SHORT
+                    ).show()
+                } catch (e: Exception) {
+                    e.report(ExceptionCategory.EXPOSURENOTIFICATION)
+                }
+            }
+        }
+    }
+
+    private suspend fun calculateRiskLevel() {
+        try {
+            RiskLevelTransaction.start()
+        } catch (e: TransactionException) {
+            e.report(ExceptionCategory.INTERNAL)
+        }
+    }
+
+    private fun startObserving() {
+        RiskLevelTransaction.tempExposedTransactionValuesForTestingOnly.observe(
+            viewLifecycleOwner,
+            Observer {
+                tracingViewModel.viewModelScope.launch {
+                    val riskAsString = "Level: ${it.riskLevel}\n" +
+                            "Calc. Score: ${it.riskScore}\n" +
+                            "Tracing Duration: " +
+                            "${TimeUnit.MILLISECONDS.toDays(TimeVariables.getTimeActiveTracingDuration())} days \n" +
+                            "Tracing Duration in last 14 days: " +
+                            "${TimeVariables.getActiveTracingDaysInRetentionPeriod()} days"
+                    binding.labelRiskScore.text = riskAsString
+
+                    val lowClass =
+                        it.appConfig?.riskScoreClasses?.riskClassesList?.find { low -> low.label == "LOW" }
+                    val highClass =
+                        it.appConfig?.riskScoreClasses?.riskClassesList?.find { high -> high.label == "HIGH" }
+
+                    val configAsString =
+                        "Attenuation Weight Low: ${it.appConfig?.attenuationDuration?.weights?.low}\n" +
+                                "Attenuation Weight Mid: ${it.appConfig?.attenuationDuration?.weights?.mid}\n" +
+                                "Attenuation Weight High: ${it.appConfig?.attenuationDuration?.weights?.high}\n\n" +
+                                "Attenuation Offset: ${it.appConfig?.attenuationDuration?.defaultBucketOffset}\n" +
+                                "Attenuation Normalization: " +
+                                "${it.appConfig?.attenuationDuration?.riskScoreNormalizationDivisor}\n\n" +
+                                "Risk Score Low Class: ${lowClass?.min ?: 0} - ${lowClass?.max ?: 0}\n" +
+                                "Risk Score High Class: ${highClass?.min ?: 0} - ${highClass?.max ?: 0}"
+
+                    binding.labelBackendParameters.text = configAsString
+
+                    val summaryAsString =
+                        "Days Since Last Exposure: ${it.exposureSummary?.daysSinceLastExposure}\n" +
+                                "Matched Key Count: ${it.exposureSummary?.matchedKeyCount}\n" +
+                                "Maximum Risk Score: ${it.exposureSummary?.maximumRiskScore}\n" +
+                                "Attenuation Durations: [${it.exposureSummary?.attenuationDurationsInMinutes?.get(
+                                    0
+                                )}," +
+                                "${it.exposureSummary?.attenuationDurationsInMinutes?.get(1)}," +
+                                "${it.exposureSummary?.attenuationDurationsInMinutes?.get(2)}]\n" +
+                                "Summation Risk Score: ${it.exposureSummary?.summationRiskScore}"
+
+                    binding.labelExposureSummary.text = summaryAsString
+
+                    val maxRisk = it.exposureSummary?.maximumRiskScore
+                    val atWeights = it.appConfig?.attenuationDuration?.weights
+                    val attenuationDurationInMin =
+                        it.exposureSummary?.attenuationDurationsInMinutes
+                    val attenuationConfig = it.appConfig?.attenuationDuration
+                    val formulaString =
+                        "($maxRisk / ${attenuationConfig?.riskScoreNormalizationDivisor}) * " +
+                                "(${attenuationDurationInMin?.get(0)} * ${atWeights?.low} " +
+                                "+ ${attenuationDurationInMin?.get(1)} * ${atWeights?.mid} " +
+                                "+ ${attenuationDurationInMin?.get(2)} * ${atWeights?.high} " +
+                                "+ ${attenuationConfig?.defaultBucketOffset})"
+
+                    binding.labelFormula.text = formulaString
+
+                    binding.labelFullConfig.text = it.appConfig?.toString()
+                }
+            })
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/ErrorReportReceiver.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/ErrorReportReceiver.kt
new file mode 100644
index 0000000000000000000000000000000000000000..f9d52f4f917324183ef20a5c796355863f564ebc
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/ErrorReportReceiver.kt
@@ -0,0 +1,53 @@
+package de.rki.coronawarnapp.exception
+
+import android.app.Activity
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+import de.rki.coronawarnapp.CoronaWarnApplication
+import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.util.DialogHelper
+
+class ErrorReportReceiver(private val activity: Activity) : BroadcastReceiver() {
+    companion object {
+        private val TAG: String = ErrorReportReceiver::class.java.simpleName
+    }
+    override fun onReceive(context: Context, intent: Intent) {
+        val category = ExceptionCategory
+            .valueOf(intent.getStringExtra(ReportingConstants.ERROR_REPORT_CATEGORY_EXTRA) ?: "")
+        val prefix = intent.getStringExtra(ReportingConstants.ERROR_REPORT_PREFIX_EXTRA)
+        val suffix = intent.getStringExtra(ReportingConstants.ERROR_REPORT_SUFFIX_EXTRA)
+        val message = intent.getStringExtra(ReportingConstants.ERROR_REPORT_MESSAGE_EXTRA)
+            ?: context.resources.getString(R.string.errors_generic_text_unknown_error_cause)
+        val stack = intent.getStringExtra(ReportingConstants.ERROR_REPORT_STACK_EXTRA)
+        val title = context.resources.getString(R.string.errors_generic_headline)
+        val confirm = context.resources.getString(R.string.errors_generic_button_positive)
+        val details = context.resources.getString(R.string.errors_generic_button_negative)
+        val detailsTitle = context.resources.getString(R.string.errors_generic_details_headline)
+        if (CoronaWarnApplication.isAppInForeground) {
+            DialogHelper.showDialog(DialogHelper.DialogInstance(
+                activity,
+                title,
+                message,
+                confirm,
+                details,
+                null,
+                {},
+                {
+                    DialogHelper.showDialog(
+                        DialogHelper.DialogInstance(
+                            activity,
+                            title,
+                            "$detailsTitle:\n$stack",
+                            confirm
+                        )).run {}
+                }
+            ))
+        }
+        Log.e(
+            TAG,
+            "[$category]${(prefix ?: "")} $message${(suffix ?: "")}"
+        )
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/ExceptionReporter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/ExceptionReporter.kt
index 273b168eba828080659f3c00a34591d2af6256ab..65b1713f114f9d9b5029bab3340381d491404fea 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/ExceptionReporter.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/ExceptionReporter.kt
@@ -1,11 +1,10 @@
 package de.rki.coronawarnapp.exception
 
-import android.util.Log
-import android.widget.Toast
+import android.content.Intent
+import androidx.localbroadcastmanager.content.LocalBroadcastManager
 import de.rki.coronawarnapp.CoronaWarnApplication
-import kotlinx.coroutines.runBlocking
-
-private const val TAG: String = "ExceptionHandler"
+import java.io.PrintWriter
+import java.io.StringWriter
 
 fun Throwable.report(exceptionCategory: ExceptionCategory) =
     this.report(exceptionCategory, null, null)
@@ -15,16 +14,23 @@ fun Throwable.report(
     prefix: String?,
     suffix: String?
 ) {
-    runBlocking {
-        Toast.makeText(
-            CoronaWarnApplication.getAppContext(),
-            this@report.localizedMessage ?: "This should never happen.",
-            Toast.LENGTH_SHORT
-        ).show()
-    }
+    val intent = Intent(ReportingConstants.ERROR_REPORT_LOCAL_BROADCAST_CHANNEL)
+    intent.putExtra(ReportingConstants.ERROR_REPORT_CATEGORY_EXTRA, exceptionCategory.name)
+    intent.putExtra(ReportingConstants.ERROR_REPORT_PREFIX_EXTRA, prefix)
+    intent.putExtra(ReportingConstants.ERROR_REPORT_SUFFIX_EXTRA, suffix)
+    intent.putExtra(ReportingConstants.ERROR_REPORT_MESSAGE_EXTRA, this.message)
+    val sw = StringWriter()
+    this.printStackTrace()
+    this.printStackTrace(PrintWriter(sw))
+    intent.putExtra(ReportingConstants.ERROR_REPORT_STACK_EXTRA, sw.toString())
+    LocalBroadcastManager.getInstance(CoronaWarnApplication.getAppContext()).sendBroadcast(intent)
+}
 
-    Log.e(
-        TAG,
-        "[${exceptionCategory.name}]${(prefix ?: "")} ${(this.message ?: "Error Text Unavailable")}${(suffix ?: "")}"
-    )
+fun Throwable.reportGeneric(
+    stackString: String
+) {
+    val intent = Intent(ReportingConstants.ERROR_REPORT_LOCAL_BROADCAST_CHANNEL)
+    intent.putExtra("category", ExceptionCategory.INTERNAL.name)
+    intent.putExtra("stack", stackString)
+    LocalBroadcastManager.getInstance(CoronaWarnApplication.getAppContext()).sendBroadcast(intent)
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/NoTokenException.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/NoTokenException.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6140302afde799a1399e31c3f12db6730c861089
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/NoTokenException.kt
@@ -0,0 +1,8 @@
+package de.rki.coronawarnapp.exception
+
+class NoTokenException(
+    cause: Throwable
+) : Exception(
+    "An error occurred during BroadcastReceiver onReceive function. No token found",
+    cause
+)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/ReportingConstants.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/ReportingConstants.kt
new file mode 100644
index 0000000000000000000000000000000000000000..22f1c2393c84012e7d1731717d986a7b12938310
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/exception/ReportingConstants.kt
@@ -0,0 +1,10 @@
+package de.rki.coronawarnapp.exception
+
+object ReportingConstants {
+    const val ERROR_REPORT_LOCAL_BROADCAST_CHANNEL = "error-report"
+    const val ERROR_REPORT_CATEGORY_EXTRA = "category"
+    const val ERROR_REPORT_PREFIX_EXTRA = "prefix"
+    const val ERROR_REPORT_SUFFIX_EXTRA = "suffix"
+    const val ERROR_REPORT_MESSAGE_EXTRA = "message"
+    const val ERROR_REPORT_STACK_EXTRA = "stack"
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/CertificatePinnerFactory.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/CertificatePinnerFactory.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7a103bea08326d456c187f552de95bf760644f38
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/CertificatePinnerFactory.kt
@@ -0,0 +1,23 @@
+package de.rki.coronawarnapp.http
+
+import de.rki.coronawarnapp.util.PropertyLoader
+import okhttp3.CertificatePinner
+
+class CertificatePinnerFactory {
+    fun getCertificatePinner(): CertificatePinner = PropertyLoader().run {
+        CertificatePinner.Builder()
+            .add(
+                DynamicURLs.DOWNLOAD_CDN_URL.removePrefix(DynamicURLs.PATTERN_PREFIX_HTTPS),
+                *this.getDistributionPins()
+            )
+            .add(
+                DynamicURLs.SUBMISSION_CDN_URL.removePrefix(DynamicURLs.PATTERN_PREFIX_HTTPS),
+                *this.getSubmissionPins()
+            )
+            .add(
+                DynamicURLs.VERIFICATION_CDN_URL.removePrefix(DynamicURLs.PATTERN_PREFIX_HTTPS),
+                *this.getVerificationPins()
+            )
+            .build()
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/DynamicURLs.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/DynamicURLs.kt
index 6f83c12e8d72cea65b3f0674d316367ce3864695..20dd178142426076f75e04862dfe7603a4ad5cbc 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/DynamicURLs.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/DynamicURLs.kt
@@ -3,6 +3,7 @@ package de.rki.coronawarnapp.http
 import de.rki.coronawarnapp.BuildConfig
 
 object DynamicURLs {
+    const val PATTERN_PREFIX_HTTPS = "https://"
     /** CDN URLs for querying against the Server from the Build Config for downloading keys */
     var DOWNLOAD_CDN_URL = BuildConfig.DOWNLOAD_CDN_URL
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/OfflineCacheInterceptor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/OfflineCacheInterceptor.kt
new file mode 100644
index 0000000000000000000000000000000000000000..15bf62893e84da23d278a2be61571895d2ff4c07
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/OfflineCacheInterceptor.kt
@@ -0,0 +1,48 @@
+package de.rki.coronawarnapp.http
+
+import android.content.Context
+import de.rki.coronawarnapp.util.ConnectivityHelper.isNetworkEnabled
+import okhttp3.Interceptor
+import okhttp3.Response
+
+class OfflineCacheInterceptor(private val context: Context) : Interceptor {
+    companion object {
+        private const val MAX_AGE = 5
+        private const val MAX_STALE_DAYS = 1
+        private const val MAX_STALE = 60 * 60 * 24 * MAX_STALE_DAYS
+    }
+    override fun intercept(chain: Interceptor.Chain): Response {
+        // Get the request from the chain.
+        var request = chain.request()
+        /*
+        *  Leveraging the advantage of using Kotlin,
+        *  we initialize the request and change its header depending on whether
+        *  the device is connected to Internet or not.
+        */
+        request = if (isNetworkEnabled(context)) {
+            /*
+             *  If there is Internet, get the cache that was stored 5 seconds ago.
+             *  If the cache is older than 5 seconds, then discard it,
+             *  and indicate an error in fetching the response.
+             *  The 'max-age' attribute is responsible for this behavior.
+             */
+            request.newBuilder().header(
+                "Cache-Control",
+                "public, max-age=$MAX_AGE"
+            ).build()
+        } else {
+            /*
+            *  If there is no Internet, get the cache that was stored 1 days ago.
+            *  If the cache is older than 1 day, then discard it,
+            *  and indicate an error in fetching the response.
+            *  The 'max-stale' attribute is responsible for this behavior.
+            *  The 'only-if-cached' attribute indicates to not retrieve new data; fetch the cache only instead.
+            */
+            request.newBuilder().header(
+                "Cache-Control",
+                "public, only-if-cached, max-stale=$MAX_STALE"
+            ).build()
+        }
+        return chain.proceed(request)
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/OkHttp3Stack.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/OkHttp3Stack.kt
deleted file mode 100644
index 0e60fa00b1f51ed99ed0ea6cb8d5713b318d58f0..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/OkHttp3Stack.kt
+++ /dev/null
@@ -1,190 +0,0 @@
-package de.rki.coronawarnapp.http
-
-import android.content.Context
-import com.android.volley.Header
-import com.android.volley.Request
-import com.android.volley.toolbox.BaseHttpStack
-import com.android.volley.toolbox.HttpResponse
-import de.rki.coronawarnapp.risk.TimeVariables
-import okhttp3.Cache
-import okhttp3.ConnectionPool
-import okhttp3.ConnectionSpec
-import okhttp3.Headers
-import okhttp3.Interceptor
-import okhttp3.MediaType.Companion.toMediaType
-import okhttp3.OkHttpClient
-import okhttp3.RequestBody
-import okhttp3.RequestBody.Companion.toRequestBody
-import okhttp3.TlsVersion
-import java.io.File
-import java.util.concurrent.TimeUnit
-
-/**
- * Convenience Wrapper used for accessing the OkHTTP Transport layer with the Volley Interfaces.
- * Designed for:
- * - in-memory connection management
- * - disk based caching (10MB)
- * - extension based on volleys BaseHttpStack
- * - volley request queue
- * - synchronous calls executed by asynchronous thread-pool
- *
- * @param context
- * @param interceptors
- */
-class OkHttp3Stack(context: Context, interceptors: List<Interceptor>) : BaseHttpStack() {
-    constructor(context: Context) : this(context, emptyList())
-
-    /**
-     * List of interceptors, e.g. logging
-     */
-    private val mInterceptors: List<Interceptor> = interceptors
-
-    /**
-     * connection pool held in-memory, especially useful for key retrieval
-     */
-    private val conPool = ConnectionPool()
-
-    /**
-     * Basic disk cache backed by LRU
-     */
-    private val cache = Cache(
-        directory = File(context.cacheDir, HTTP_CACHE_NAME),
-        maxSize = HTTP_CACHE_SIZE
-    )
-
-    /**
-     * lazily initialized client instance of OkHTTP
-     */
-    private val client by lazy { buildClient() }
-
-    /**
-     * Convenience method to map headers from volley to OkHTTP style.
-     */
-    private fun mapHeaders(responseHeaders: Headers): List<Header> =
-        responseHeaders.map { Header(it.first, it.second) }
-
-    companion object {
-        /**
-         * 10 MiB
-         */
-        private const val HTTP_CACHE_SIZE = 50L * 1024L * 1024L
-
-        /**
-         * Cache file name
-         */
-        private const val HTTP_CACHE_NAME = "http_cache"
-
-        /**
-         * Convenience method used for building the correct request type.
-         */
-        private fun setConnectionParametersForRequest(
-            builder: okhttp3.Request.Builder,
-            request: Request<*>
-        ) {
-            when (request.method) {
-                Request.Method.DEPRECATED_GET_OR_POST -> { throw IllegalArgumentException("deprecated.") }
-                Request.Method.GET -> builder.get()
-                Request.Method.DELETE -> builder.delete(createRequestBody(request))
-                Request.Method.POST -> builder.post(createRequestBody(request)!!)
-                Request.Method.PUT -> builder.put(createRequestBody(request)!!)
-                Request.Method.HEAD -> builder.head()
-                Request.Method.OPTIONS -> builder.method("OPTIONS", null)
-                Request.Method.TRACE -> builder.method("TRACE", null)
-                Request.Method.PATCH -> builder.patch(createRequestBody(request)!!)
-                else -> throw IllegalStateException("Unknown method type.")
-            }
-        }
-
-        /**
-         * Convenience method to create a request body based on MediaType
-         *
-         * @param volleyRequest
-         */
-        private fun createRequestBody(volleyRequest: Request<*>): RequestBody? =
-            volleyRequest.body.toRequestBody(
-                volleyRequest.bodyContentType.toMediaType(),
-                0,
-                volleyRequest.body.size
-            )
-    }
-
-    override fun executeRequest(
-        request: Request<*>,
-        additionalHeaders: MutableMap<String, String>?
-    ): HttpResponse {
-        val okHttpRequest = buildRequest(request, additionalHeaders)
-
-        val okHttpCall = client.newCall(okHttpRequest)
-        val okHttpResponse = okHttpCall.execute()
-
-        val code = okHttpResponse.code
-        val body = okHttpResponse.body
-        val content = body?.byteStream()
-        val contentLength = body?.contentLength()?.toInt() ?: 0
-        val responseHeaders = mapHeaders(okHttpResponse.headers)
-        return HttpResponse(code, responseHeaders, contentLength, content)
-    }
-
-    /**
-     * Wrapper around the OkHTTP request builder used to set header fields, url and connection params.
-     *
-     * @param request
-     * @param additionalHeaders
-     */
-    private fun buildRequest(request: Request<*>, additionalHeaders: MutableMap<String, String>?):
-            okhttp3.Request {
-        val okHttpRequestBuilder = okhttp3.Request.Builder()
-        okHttpRequestBuilder.url(request.url)
-
-        val headers = request.headers
-        headers.forEach {
-            okHttpRequestBuilder.addHeader(it.key, it.value)
-        }
-        additionalHeaders?.forEach {
-            okHttpRequestBuilder.addHeader(it.key, it.value)
-        }
-
-        setConnectionParametersForRequest(okHttpRequestBuilder, request)
-
-        return okHttpRequestBuilder.build()
-    }
-
-    /**
-     * Helper method used to build the client with connection pool, timeout values, caching,
-     * connection specs, interceptors and other generic meta-info.
-     */
-    private fun buildClient(): OkHttpClient {
-        val clientBuilder = OkHttpClient.Builder()
-
-        val timeoutMs = TimeVariables.getTransactionTimeout()
-        clientBuilder.connectTimeout(timeoutMs, TimeUnit.MILLISECONDS)
-        clientBuilder.readTimeout(timeoutMs, TimeUnit.MILLISECONDS)
-        clientBuilder.writeTimeout(timeoutMs, TimeUnit.MILLISECONDS)
-        clientBuilder.callTimeout(timeoutMs, TimeUnit.MILLISECONDS)
-
-        clientBuilder.connectionPool(conPool)
-
-        cache.evictAll()
-        clientBuilder.cache(cache)
-
-        val spec: ConnectionSpec = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
-            .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_3)
-            .allEnabledCipherSuites() // TODO clarify more concrete Ciphers
-            .build()
-
-        clientBuilder.connectionSpecs(listOf(spec))
-
-        // TODO add certificate pinning
-//        val certificatePinner = CertificatePinner.Builder()
-//            .add(
-//                "x.de",
-//                "sha256/base64"
-//            )
-//            .build()
-//        clientBuilder.certificatePinner(certificatePinner)
-
-        mInterceptors.forEach { clientBuilder.addInterceptor(it) }
-
-        return clientBuilder.build()
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/RequestQueueHolder.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/RequestQueueHolder.kt
deleted file mode 100644
index 2c16c7709b93bfee4cab95efc80380914bf1b629..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/RequestQueueHolder.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package de.rki.coronawarnapp.http
-
-import com.android.volley.Request
-import com.android.volley.RequestQueue
-import de.rki.coronawarnapp.CoronaWarnApplication
-import de.rki.coronawarnapp.util.security.SecurityHelper
-
-/**
- * Request queue holder used to reference a singleton of a Volley request queue for simple web requests.
- * The Singleton is used here solely for Thread-Management, actual requests are executed by an OkHTTP
- * Transport Layer
- */
-object RequestQueueHolder {
-    /**
-     * lazily initialized singleton reference to a request queue.
-     */
-    private val requestQueue: RequestQueue by lazy {
-        // applicationContext is key, it keeps you from leaking the
-        // Activity or BroadcastReceiver if someone passes one in.
-        SecurityHelper.getPinnedWebStack(CoronaWarnApplication.getAppContext())
-    }
-
-    /**
-     * Adds a request to the queue.
-     *
-     * @param T return type of the request
-     * @param req a given request
-     */
-    fun <T> addToRequestQueue(req: Request<T>) {
-        requestQueue.add(req)
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/RetryInterceptor.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/RetryInterceptor.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c4bfa179b98416b7723cef0efa40abd32502c44d
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/RetryInterceptor.kt
@@ -0,0 +1,23 @@
+package de.rki.coronawarnapp.http
+
+import android.util.Log
+import okhttp3.Interceptor
+import okhttp3.Request
+import okhttp3.Response
+
+class RetryInterceptor : Interceptor {
+    companion object {
+        private const val MAX_RETRY_COUNT = 3
+    }
+    override fun intercept(chain: Interceptor.Chain): Response {
+        val request: Request = chain.request()
+        var response = chain.proceed(request)
+        var tryCount = 0
+        while (!response.isSuccessful && tryCount < MAX_RETRY_COUNT) {
+            Log.d(this.javaClass.simpleName, "Request is not successful - $tryCount")
+            tryCount++
+            response = chain.proceed(request)
+        }
+        return response
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b17803daad10bc54513d4fb4ef98273d60dccdac
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/ServiceFactory.kt
@@ -0,0 +1,122 @@
+package de.rki.coronawarnapp.http
+
+import de.rki.coronawarnapp.BuildConfig
+import de.rki.coronawarnapp.CoronaWarnApplication
+import de.rki.coronawarnapp.http.service.DistributionService
+import de.rki.coronawarnapp.http.service.SubmissionService
+import de.rki.coronawarnapp.http.service.VerificationService
+import de.rki.coronawarnapp.risk.TimeVariables
+import okhttp3.Cache
+import okhttp3.ConnectionPool
+import okhttp3.ConnectionSpec
+import okhttp3.Interceptor
+import okhttp3.OkHttpClient
+import okhttp3.logging.HttpLoggingInterceptor
+import retrofit2.Retrofit
+import retrofit2.converter.gson.GsonConverterFactory
+import retrofit2.converter.protobuf.ProtoConverterFactory
+import java.io.File
+import java.util.concurrent.TimeUnit
+
+class ServiceFactory {
+    companion object {
+        /**
+         * 10 MiB
+         */
+        private const val HTTP_CACHE_SIZE = 10L * 1024L * 1024L
+
+        /**
+         * Cache file name
+         */
+        private const val HTTP_CACHE_NAME = "http_cache"
+    }
+
+    /**
+     * List of interceptors, e.g. logging
+     */
+    private val mInterceptors: List<Interceptor> = listOf(
+        HttpLoggingInterceptor().also {
+            if (BuildConfig.DEBUG) it.setLevel(HttpLoggingInterceptor.Level.BODY)
+        },
+        OfflineCacheInterceptor(CoronaWarnApplication.getAppContext()),
+        RetryInterceptor()
+    )
+
+    /**
+     * connection pool held in-memory, especially useful for key retrieval
+     */
+    private val conPool = ConnectionPool()
+
+    /**
+     * Basic disk cache backed by LRU
+     */
+    private val cache = Cache(
+        directory = File(CoronaWarnApplication.getAppContext().cacheDir, HTTP_CACHE_NAME),
+        maxSize = HTTP_CACHE_SIZE
+    )
+
+    private val gsonConverterFactory = GsonConverterFactory.create()
+    private val protoConverterFactory = ProtoConverterFactory.create()
+
+    private val okHttpClient by lazy {
+        val clientBuilder = OkHttpClient.Builder()
+
+        val timeoutMs = TimeVariables.getTransactionTimeout()
+        clientBuilder.connectTimeout(timeoutMs, TimeUnit.MILLISECONDS)
+        clientBuilder.readTimeout(timeoutMs, TimeUnit.MILLISECONDS)
+        clientBuilder.writeTimeout(timeoutMs, TimeUnit.MILLISECONDS)
+        clientBuilder.callTimeout(timeoutMs, TimeUnit.MILLISECONDS)
+
+        clientBuilder.connectionPool(conPool)
+
+        cache.evictAll()
+        clientBuilder.cache(cache)
+
+        val spec: ConnectionSpec = ConnectionSpec.Builder(ConnectionSpec.RESTRICTED_TLS)
+            .allEnabledCipherSuites() // TODO clarify more concrete Ciphers
+            .build()
+
+        clientBuilder.connectionSpecs(listOf(spec))
+
+        CertificatePinnerFactory().getCertificatePinner().run {
+            if (this.pins.isNotEmpty()) {
+                clientBuilder.certificatePinner(this)
+            }
+        }
+
+        mInterceptors.forEach { clientBuilder.addInterceptor(it) }
+
+        clientBuilder.build()
+    }
+
+    fun distributionService(): DistributionService = distributionService
+    private val distributionService by lazy {
+        Retrofit.Builder()
+            .client(okHttpClient)
+            .baseUrl(DynamicURLs.DOWNLOAD_CDN_URL)
+            .addConverterFactory(gsonConverterFactory)
+            .build()
+            .create(DistributionService::class.java)
+    }
+
+    fun verificationService(): VerificationService = verificationService
+    private val verificationService by lazy {
+        Retrofit.Builder()
+            .client(okHttpClient)
+            .baseUrl(DynamicURLs.VERIFICATION_CDN_URL)
+            .addConverterFactory(gsonConverterFactory)
+            .build()
+            .create(VerificationService::class.java)
+    }
+
+    fun submissionService(): SubmissionService = submissionService
+    private val submissionService by lazy {
+        Retrofit.Builder()
+            .client(okHttpClient)
+            .baseUrl(DynamicURLs.SUBMISSION_CDN_URL)
+            .addConverterFactory(protoConverterFactory)
+            .addConverterFactory(gsonConverterFactory)
+            .build()
+            .create(SubmissionService::class.java)
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/WebRequestBuilder.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/WebRequestBuilder.kt
index 68167454aaf53ae488865e5a01af6afb894f7d27..a5e68d8526f74260805a524ed0415bf301682800 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/WebRequestBuilder.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/WebRequestBuilder.kt
@@ -21,245 +21,139 @@ package de.rki.coronawarnapp.http
 
 import KeyExportFormat
 import android.util.Log
-import com.android.volley.DefaultRetryPolicy
-import com.android.volley.Response
-import com.android.volley.VolleyError
-import com.android.volley.toolbox.JsonArrayRequest
-import com.android.volley.toolbox.StringRequest
-import de.rki.coronawarnapp.BuildConfig
-import de.rki.coronawarnapp.exception.WebRequestException
-import de.rki.coronawarnapp.exception.report
-import de.rki.coronawarnapp.http.request.ApplicationConfigurationRequest
-import de.rki.coronawarnapp.http.request.KeyFileRequest
-import de.rki.coronawarnapp.http.request.KeySubmissionRequest
-import de.rki.coronawarnapp.http.request.RegistrationTokenRequest
-import de.rki.coronawarnapp.http.request.TanRequest
-import de.rki.coronawarnapp.http.request.TestResultRequest
-import de.rki.coronawarnapp.risk.TimeVariables
+import de.rki.coronawarnapp.http.requests.RegistrationTokenRequest
+import de.rki.coronawarnapp.http.requests.ReqistrationRequest
+import de.rki.coronawarnapp.http.requests.TanRequestBody
 import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass.ApplicationConfiguration
-import de.rki.coronawarnapp.util.IndexHelper.convertToIndex
-import org.json.JSONArray
+import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyConstants
+import de.rki.coronawarnapp.service.submission.SubmissionConstants
+import de.rki.coronawarnapp.storage.FileStorageHelper
+import de.rki.coronawarnapp.util.TimeAndDateExtensions.toServerFormat
+import de.rki.coronawarnapp.util.ZipHelper.unzip
+import de.rki.coronawarnapp.util.security.SecurityHelper
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
 import java.io.File
-import java.util.ArrayList
+import java.util.Date
 import java.util.UUID
-import kotlin.coroutines.Continuation
-import kotlin.coroutines.resume
-import kotlin.coroutines.resumeWithException
-import kotlin.coroutines.suspendCoroutine
 
 object WebRequestBuilder {
     private val TAG: String? = WebRequestBuilder::class.simpleName
 
-    private const val MAX_RETRIES = 3
-    private const val BACKOFF_MULTIPLIER = 2F
+    private val serviceFactory = ServiceFactory()
 
-    private val standardRetryPolicy by lazy {
-        DefaultRetryPolicy(
-            TimeVariables.getTransactionTimeout().toInt(),
-            MAX_RETRIES,
-            BACKOFF_MULTIPLIER
-        )
-    }
+    private val distributionService = serviceFactory.distributionService()
+    private val verificationService = serviceFactory.verificationService()
+    private val submissionService = serviceFactory.submissionService()
 
-    suspend fun <T> asyncGetArrayListFromGenericRequest(
-        url: String,
-        parser: (JSONArray) -> ArrayList<T>
-    ) =
-        suspendCoroutine<ArrayList<T>> { cont ->
-            val requestID = UUID.randomUUID()
-            val getArrayListRequest = JsonArrayRequest(
-                url, Response.Listener { response ->
-                    Log.d(TAG, "$requestID: Response is $response")
-                    cont.resume(parser(response))
-                }, RequestErrorListener(requestID, cont)
-            )
-            RequestQueueHolder.addToRequestQueue(getArrayListRequest)
-            Log.d(TAG, "$requestID: Added $url to queue.")
-        }
+    suspend fun asyncGetDateIndex(): List<String> = withContext(Dispatchers.IO) {
+        return@withContext distributionService
+            .getDateIndex(DiagnosisKeyConstants.AVAILABLE_DATES_URL).toList()
+    }
 
-    suspend fun asyncGetIndexBasedQueryURLsFromServer(url: String) =
-        suspendCoroutine<Map<Long, String>> { cont ->
-            val requestID = UUID.randomUUID()
-            val getArrayListRequest = StringRequest(
-                url, Response.Listener { response ->
-                    if (BuildConfig.DEBUG) Log.d(TAG, "$requestID: Response is $response")
-                    cont.resume(response.convertToIndex())
-                }, RequestErrorListener(requestID, cont)
+    suspend fun asyncGetHourIndex(day: Date): List<String> = withContext(Dispatchers.IO) {
+        return@withContext distributionService
+            .getHourIndex(
+                DiagnosisKeyConstants.AVAILABLE_DATES_URL +
+                    "/${day.toServerFormat()}/${DiagnosisKeyConstants.HOUR}"
             )
-            RequestQueueHolder.addToRequestQueue(getArrayListRequest)
-            Log.d(TAG, "$requestID: Added $url to queue.")
-        }
+            .toList()
+    }
 
     /**
      * Retrieves Key Files from the Server based on a URL
      *
      * @param url the given URL
      */
-    suspend fun asyncGetKeyFilesFromServer(url: String) =
-        suspendCoroutine<File> { cont ->
-            val requestID = UUID.randomUUID()
-            val request = KeyFileRequest(
-                url,
-                requestID,
-                null,
-                Response.Listener { response ->
-                    Log.v(requestID.toString(), "key file request successful. (${response.length()}B)")
-                    cont.resume(response)
-                },
-                RequestErrorListener(requestID, cont)
-            ).also { keyFileRequest ->
-                keyFileRequest.retryPolicy = standardRetryPolicy
-                keyFileRequest.setShouldCache(false)
-                keyFileRequest.setShouldRetryServerErrors(true)
-            }
-            RequestQueueHolder.addToRequestQueue(request)
+    suspend fun asyncGetKeyFilesFromServer(
+        url: String
+    ): File = withContext(Dispatchers.IO) {
+        val requestID = UUID.randomUUID()
+        val fileName = "${UUID.nameUUIDFromBytes(url.toByteArray())}.zip"
+        val file = File(FileStorageHelper.keyExportDirectory, fileName)
+        file.outputStream().use {
             Log.v(requestID.toString(), "Added $url to queue.")
+            distributionService.getKeyFiles(url).byteStream().copyTo(it, DEFAULT_BUFFER_SIZE)
+            Log.v(requestID.toString(), "key file request successful.")
         }
+        return@withContext file
+    }
 
-    suspend fun asyncGetApplicationConfigurationFromServer(url: String) =
-        suspendCoroutine<ApplicationConfiguration> { cont ->
-            val requestID = UUID.randomUUID()
-            val getKeyBucketRequest =
-                ApplicationConfigurationRequest(
-                    url,
-                    requestID,
-                    null,
-                    Response.Listener { response -> cont.resume(response) },
-                    RequestErrorListener(requestID, cont)
-                )
-            RequestQueueHolder.addToRequestQueue(getKeyBucketRequest)
-            Log.d(TAG, "$requestID: Added $url to queue.")
+    suspend fun asyncGetApplicationConfigurationFromServer(): ApplicationConfiguration =
+        withContext(Dispatchers.IO) {
+            var applicationConfiguration: ApplicationConfiguration? = null
+            distributionService.getApplicationConfiguration(
+                DiagnosisKeyConstants.COUNTRY_APPCONFIG_DOWNLOAD_URL
+            ).byteStream().unzip { entry, entryContent ->
+                if (entry.name == "export.bin") {
+                    val appConfig = ApplicationConfiguration.parseFrom(entryContent)
+                    applicationConfiguration = appConfig
+                }
+                if (entry.name == "export.sig") {
+                    val signatures = KeyExportFormat.TEKSignatureList.parseFrom(entryContent)
+                    signatures.signaturesList.forEach {
+                        Log.d(TAG, it.signatureInfo.toString())
+                    }
+                }
+            }
+            if (applicationConfiguration == null) {
+                throw IllegalArgumentException("no file was found in the downloaded zip")
+            }
+            return@withContext applicationConfiguration!!
         }
 
     suspend fun asyncGetRegistrationToken(
-        url: String,
         key: String,
         keyType: String
-    ) =
-        suspendCoroutine<String> { cont ->
-            val requestID = UUID.randomUUID()
-            val getRegistrationTokenRequest =
-                RegistrationTokenRequest(
-                    url,
-                    requestID,
-                    keyType,
-                    key,
-                    false,
-                    standardRetryPolicy,
-                    Response.Listener { response ->
-                        Log.d(
-                            TAG,
-                            "$requestID: Registration Token Request successful"
-                        )
-                        cont.resume(response)
-                    },
-                    RequestErrorListener(requestID, cont)
-                )
-            RequestQueueHolder.addToRequestQueue(getRegistrationTokenRequest)
-            Log.d(TAG, "$requestID: Added $url to queue.")
+    ): String = withContext(Dispatchers.IO) {
+        val keyStr = if (keyType == SubmissionConstants.QR_CODE_KEY_TYPE) {
+            SecurityHelper.hash256(key)
+        } else {
+            key
         }
+        verificationService.getRegistrationToken(
+            SubmissionConstants.REGISTRATION_TOKEN_URL,
+            "0",
+            RegistrationTokenRequest(keyType, keyStr)
+        ).registrationToken
+    }
 
     suspend fun asyncGetTestResult(
-        url: String,
         registrationToken: String
-    ) =
-        suspendCoroutine<Int> { cont ->
-            val requestID = UUID.randomUUID()
-            val getTestResultRequest =
-                TestResultRequest(
-                    url,
-                    requestID,
-                    registrationToken,
-                    false,
-                    standardRetryPolicy,
-
-                    Response.Listener { response ->
-                        Log.d(
-                            TAG,
-                            "$requestID: Test Result Request successful"
-                        )
-                        cont.resume(response)
-                    },
-                    RequestErrorListener(requestID, cont)
-                )
-            RequestQueueHolder.addToRequestQueue(getTestResultRequest)
-            Log.d(TAG, "$requestID: Added $url to queue.")
-        }
+    ): Int = withContext(Dispatchers.IO) {
+        verificationService.getTestResult(
+            SubmissionConstants.TEST_RESULT_URL,
+            "0", ReqistrationRequest(registrationToken)
+        ).testResult
+    }
 
     suspend fun asyncGetTan(
-        url: String,
         registrationToken: String
-    ) =
-        suspendCoroutine<String> { cont ->
-            val requestID = UUID.randomUUID()
-            val getTANRequest =
-                TanRequest(
-                    url,
-                    requestID,
-                    registrationToken,
-                    false,
-                    standardRetryPolicy,
-
-                    Response.Listener { response ->
-                        Log.d(
-                            TAG,
-                            "$requestID: TAN Request successful"
-                        )
-                        cont.resume(response)
-                    },
-                    RequestErrorListener(requestID, cont)
-                )
-            RequestQueueHolder.addToRequestQueue(getTANRequest)
-            Log.d(TAG, "$requestID: Added $url to queue.")
-        }
+    ): String = withContext(Dispatchers.IO) {
+        verificationService.getTAN(SubmissionConstants.TAN_REQUEST_URL, "0",
+            TanRequestBody(
+                registrationToken
+            )
+        ).tan
+    }
 
     suspend fun asyncSubmitKeysToServer(
-        url: String,
         authCode: String,
         faked: Boolean,
         keyList: List<KeyExportFormat.TemporaryExposureKey>
-    ) =
-        suspendCoroutine<Int> { cont ->
-            val requestID = UUID.randomUUID()
-            Log.d(TAG, "Writing ${keyList.size} Keys to the Submission Payload.")
-            val submissionPayload = KeyExportFormat.SubmissionPayload.newBuilder()
-                .addAllKeys(keyList)
-                .build()
-                .toByteArray()
-            val submitKeysRequest =
-                KeySubmissionRequest(
-                    url,
-                    requestID,
-                    submissionPayload,
-                    authCode,
-                    faked,
-                    standardRetryPolicy,
-                    Response.Listener { response ->
-                        Log.d(
-                            TAG,
-                            "$requestID: Key Submission Request successful."
-                        )
-                        cont.resume(response)
-                    },
-                    RequestErrorListener(requestID, cont)
-                )
-            RequestQueueHolder.addToRequestQueue(submitKeysRequest)
-            Log.d(TAG, "$requestID: Added $url to queue.")
-        }
-
-    private class RequestErrorListener<T>(
-        private val requestID: UUID,
-        private val cont: Continuation<T>
-    ) :
-        Response.ErrorListener {
-        override fun onErrorResponse(error: VolleyError?) {
-            if (error != null) {
-                val webRequestException = WebRequestException("an error occurred during a webrequest", error)
-                webRequestException.report(de.rki.coronawarnapp.exception.ExceptionCategory.HTTP)
-                cont.resumeWithException(webRequestException)
-            } else {
-                cont.resumeWithException(NullPointerException("the provided exception from volley was null"))
-            }
-        }
+    ) = withContext(Dispatchers.IO) {
+        Log.d(TAG, "Writing ${keyList.size} Keys to the Submission Payload.")
+        val submissionPayload = KeyExportFormat.SubmissionPayload.newBuilder()
+            .addAllKeys(keyList)
+            .build()
+        var fakeHeader = "0"
+        if (faked) fakeHeader = Math.random().toInt().toString()
+        submissionService.submitKeys(
+            DiagnosisKeyConstants.DIAGNOSIS_KEYS_SUBMISSION_URL,
+            authCode,
+            fakeHeader,
+            submissionPayload
+        )
+        return@withContext
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/ApplicationConfigurationRequest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/ApplicationConfigurationRequest.kt
deleted file mode 100644
index a12c88fed40564ac1cb136fb0748d4511ed99fdd..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/ApplicationConfigurationRequest.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-package de.rki.coronawarnapp.http.request
-
-import KeyExportFormat
-import android.util.Log
-import com.android.volley.Cache.Entry
-import com.android.volley.NetworkResponse
-import com.android.volley.ParseError
-import com.android.volley.Request
-import com.android.volley.Response
-import com.android.volley.toolbox.HttpHeaderParser
-import de.rki.coronawarnapp.exception.ExceptionCategory.HTTP
-import de.rki.coronawarnapp.exception.report
-import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass.ApplicationConfiguration
-import de.rki.coronawarnapp.util.ZipHelper.unzip
-
-class ApplicationConfigurationRequest(
-    url: String,
-    private val requestTag: Any?,
-    private val headers: MutableMap<String, String>?,
-    private val listener: Response.Listener<ApplicationConfiguration>,
-    errorListener: Response.ErrorListener
-) : Request<ApplicationConfiguration>(Method.GET, url, errorListener) {
-
-    companion object {
-        private val TAG: String? = ApplicationConfigurationRequest::class.simpleName
-
-        private const val SOFT_TTL = 5 * 60 * 1000 // in 5 minutes cache will be hit, but also refreshed on background
-        private const val TTL = 1 * 60 * 60 * 1000 // in 1 hours this cache entry expires completely
-    }
-
-    override fun getTag(): Any = requestTag ?: super.getTag().also { this.addMarker("tag:$it") }
-    override fun deliverResponse(response: ApplicationConfiguration) = listener.onResponse(response)
-    override fun getHeaders(): MutableMap<String, String> = headers ?: super.getHeaders()
-
-    override fun parseNetworkResponse(response: NetworkResponse?): Response<ApplicationConfiguration> {
-        return try {
-            var cacheEntry = HttpHeaderParser.parseCacheHeaders(response)
-            if (cacheEntry == null && response != null) {
-                Log.v(TAG, "new cache entry.")
-                cacheEntry = Entry()
-                cacheEntry.data = response.data
-                cacheEntry.softTtl = SOFT_TTL.toLong()
-                cacheEntry.ttl = TTL.toLong()
-                cacheEntry.responseHeaders = response.headers
-            } else {
-                Log.v(TAG, "using cache entry")
-            }
-
-            var applicationConfiguration: ApplicationConfiguration? = null
-            response!!.data.inputStream().unzip { entry, entryContent ->
-                if (entry.name == "export.bin") {
-                    val appConfig = ApplicationConfiguration.parseFrom(entryContent)
-//                    Log.d(TAG, "app config from zip: $appConfig")
-                    applicationConfiguration = appConfig
-                }
-                if (entry.name == "export.sig") {
-                    val signatures = KeyExportFormat.TEKSignatureList.parseFrom(entryContent)
-                    signatures.signaturesList.forEach {
-                        Log.d(TAG, it.signatureInfo.toString())
-                    }
-                }
-            }
-            if (applicationConfiguration == null) {
-                throw IllegalArgumentException("no file was found in the downloaded zip")
-            }
-
-            Response.success(applicationConfiguration, cacheEntry)
-        } catch (e: Exception) {
-            e.report(
-                HTTP,
-                requestTag.toString(),
-                null
-            )
-            Response.error(ParseError(e))
-        }
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/KeyFileRequest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/KeyFileRequest.kt
deleted file mode 100644
index 00966a2fb57be8256e4d12ea209c995fdf45e569..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/KeyFileRequest.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-package de.rki.coronawarnapp.http.request
-
-import android.util.Log
-import com.android.volley.NetworkResponse
-import com.android.volley.Request
-import com.android.volley.Response
-import com.android.volley.toolbox.HttpHeaderParser
-import de.rki.coronawarnapp.storage.FileStorageHelper
-import java.io.File
-import java.util.UUID
-
-/**
- * Request Class used for querying ZIP files containing the key files
- *
- * @property requestTag a given request tag to add as tag
- * @property headers given header values
- * @property listener given listener to call on response
- *
- * @param url given request URL
- * @param errorListener given listener to call on error
- */
-class KeyFileRequest(
-    url: String,
-    private val requestTag: Any?,
-    private val headers: MutableMap<String, String>?,
-    private val listener: Response.Listener<File>,
-    errorListener: Response.ErrorListener
-) : Request<File>(Method.GET, url, errorListener) {
-
-    override fun getTag(): Any = requestTag ?: super.getTag().also { this.addMarker("tag:$it") }
-    override fun deliverResponse(response: File) = listener.onResponse(response)
-    override fun getHeaders(): MutableMap<String, String> = headers ?: super.getHeaders()
-
-    override fun parseNetworkResponse(response: NetworkResponse): Response<File> {
-        val fileName = "${UUID.nameUUIDFromBytes(url.toByteArray())}.zip"
-        Log.v(tag.toString(), "$url results in file name $fileName")
-        val file = File(FileStorageHelper.keyExportDirectory, fileName)
-        file.outputStream().use {
-            response.data.inputStream().copyTo(it, DEFAULT_BUFFER_SIZE)
-        }
-        return Response.success(file, HttpHeaderParser.parseCacheHeaders(response))
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/KeySubmissionRequest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/KeySubmissionRequest.kt
deleted file mode 100644
index e1fd16f017f1bedf771b7ccb322704008f53fccd..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/KeySubmissionRequest.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-package de.rki.coronawarnapp.http.request
-
-import android.util.Log
-import com.android.volley.DefaultRetryPolicy
-import com.android.volley.NetworkResponse
-import com.android.volley.ParseError
-import com.android.volley.Request
-import com.android.volley.Response
-import com.android.volley.RetryPolicy
-import com.android.volley.toolbox.HttpHeaderParser
-import com.google.protobuf.InvalidProtocolBufferException
-import de.rki.coronawarnapp.exception.ExceptionCategory.HTTP
-import de.rki.coronawarnapp.exception.report
-import java.io.UnsupportedEncodingException
-
-class KeySubmissionRequest(
-    url: String,
-    private val requestTag: Any?,
-    private val binaryBody: ByteArray,
-    private val authCode: String,
-    private val faked: Boolean,
-    private val retryPolicy: RetryPolicy?,
-    private val listener: Response.Listener<Int>,
-    errorListener: Response.ErrorListener
-) : Request<Int>(Method.POST, url, errorListener) {
-
-    companion object {
-        private val TAG: String? = KeySubmissionRequest::class.simpleName
-    }
-
-    override fun getTag(): Any = requestTag ?: super.getTag().also { this.addMarker("tag:$it") }
-
-    override fun getBodyContentType(): String =
-        "application/x-protobuf".also { this.addMarker("bodyContentType:$it") }
-
-    override fun getBody(): ByteArray = binaryBody
-
-    override fun deliverResponse(response: Int) = listener.onResponse(response)
-
-    override fun getRetryPolicy(): RetryPolicy =
-        retryPolicy ?: (super.getRetryPolicy() ?: DefaultRetryPolicy())
-
-    override fun getHeaders(): MutableMap<String, String> {
-        val headers = HashMap<String, String>(super.getHeaders())
-        if (faked) headers["cwa-fake"] = Math.random().toInt().toString()
-        else headers["cwa-fake"] = "0"
-        headers["cwa-authorization"] = authCode
-        this.addMarker("headers:$headers")
-        return headers
-    }
-
-    override fun parseNetworkResponse(response: NetworkResponse?): Response<Int> {
-        return try {
-            if (response == null) throw NullPointerException("response is null, this should never be the case")
-            return Response.success(
-                response.statusCode,
-                HttpHeaderParser.parseCacheHeaders(response)
-            )
-        } catch (e: UnsupportedEncodingException) {
-            e.report(HTTP)
-            Log.e(TAG, "invalid encoding found")
-            Response.error(ParseError(e))
-        } catch (e: InvalidProtocolBufferException) {
-            Log.e(TAG, "invalid protobuf message, probably the object parse failed")
-            e.report(HTTP)
-            Response.error(ParseError(e))
-        }
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/RegistrationTokenRequest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/RegistrationTokenRequest.kt
deleted file mode 100644
index 1a76aac8ca8c7199a4d58d70cc3e15b301b14bb1..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/RegistrationTokenRequest.kt
+++ /dev/null
@@ -1,92 +0,0 @@
-package de.rki.coronawarnapp.http.request
-
-import android.util.Log
-import com.android.volley.DefaultRetryPolicy
-import com.android.volley.NetworkResponse
-import com.android.volley.ParseError
-import com.android.volley.Request
-import com.android.volley.Response
-import com.android.volley.RetryPolicy
-import com.android.volley.toolbox.HttpHeaderParser
-import de.rki.coronawarnapp.exception.ExceptionCategory.HTTP
-import de.rki.coronawarnapp.exception.report
-import de.rki.coronawarnapp.service.submission.SubmissionConstants
-import org.json.JSONException
-import org.json.JSONObject
-import java.io.UnsupportedEncodingException
-import java.security.MessageDigest
-
-class RegistrationTokenRequest(
-    url: String,
-    private val requestTag: Any?,
-    private val keyType: String,
-    private val key: String,
-    private val faked: Boolean,
-    private val retryPolicy: RetryPolicy?,
-    private val listener: Response.Listener<String>,
-    errorListener: Response.ErrorListener
-) : Request<String>(Method.POST, url, errorListener) {
-
-    companion object {
-        private val TAG: String? = RegistrationTokenRequest::class.simpleName
-    }
-
-    override fun getTag(): Any = requestTag ?: super.getTag().also { this.addMarker("tag:$it") }
-
-    override fun getBodyContentType(): String =
-        "application/json".also { this.addMarker("bodyContentType:$it") }
-
-    override fun getBody(): ByteArray {
-        val body = JSONObject()
-
-        var keyStr = ""
-        if (keyType == SubmissionConstants.QR_CODE_KEY_TYPE) {
-            val md = MessageDigest.getInstance("SHA-256")
-            val keyDigest = md.digest(key.toByteArray())
-
-            for (b in keyDigest) {
-                keyStr += String.format("%02x", b)
-            }
-        } else {
-            keyStr = key
-        }
-
-        body.put("keyType", keyType)
-        body.put("key", keyStr)
-        return body.toString().toByteArray()
-    }
-
-    override fun deliverResponse(response: String) = listener.onResponse(response)
-
-    override fun getRetryPolicy(): RetryPolicy =
-        retryPolicy ?: (super.getRetryPolicy() ?: DefaultRetryPolicy())
-
-    override fun getHeaders(): MutableMap<String, String> {
-        val headers = HashMap<String, String>(super.getHeaders())
-        if (faked) headers["cwa-fake"] = Math.random().toInt().toString()
-        else headers["cwa-fake"] = "0"
-        this.addMarker("headers:$headers")
-        return headers
-    }
-
-    override fun parseNetworkResponse(response: NetworkResponse?): Response<String> {
-        return try {
-            if (response == null) throw NullPointerException("response is null, this should never be the case")
-            val strResp = String(response.data)
-            val jsonObj = JSONObject(strResp)
-            val registrationToken = jsonObj.getString("registrationToken")
-            return Response.success(
-                registrationToken,
-                HttpHeaderParser.parseCacheHeaders(response)
-            )
-        } catch (e: UnsupportedEncodingException) {
-            e.report(HTTP)
-            Log.e(TAG, "invalid encoding found")
-            Response.error(ParseError(e))
-        } catch (e: JSONException) {
-            Log.e(TAG, "invalid JSON message, probably the object parse failed")
-            e.report(HTTP)
-            Response.error(ParseError(e))
-        }
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/TanRequest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/TanRequest.kt
deleted file mode 100644
index 553fb3cae1070df85b316fe2138745b4f5b33e19..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/TanRequest.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-package de.rki.coronawarnapp.http.request
-
-import android.util.Log
-import com.android.volley.DefaultRetryPolicy
-import com.android.volley.NetworkResponse
-import com.android.volley.ParseError
-import com.android.volley.Request
-import com.android.volley.Response
-import com.android.volley.RetryPolicy
-import com.android.volley.toolbox.HttpHeaderParser
-import de.rki.coronawarnapp.exception.ExceptionCategory.HTTP
-import de.rki.coronawarnapp.exception.report
-import org.json.JSONException
-import org.json.JSONObject
-import java.io.UnsupportedEncodingException
-
-class TanRequest(
-    url: String,
-    private val requestTag: Any?,
-    private val registrationToken: String,
-    private val faked: Boolean,
-    private val retryPolicy: RetryPolicy?,
-    private val listener: Response.Listener<String>,
-    errorListener: Response.ErrorListener
-) : Request<String>(Method.POST, url, errorListener) {
-
-    companion object {
-        private val TAG: String? = TanRequest::class.simpleName
-    }
-
-    override fun getTag(): Any = requestTag ?: super.getTag().also { this.addMarker("tag:$it") }
-
-    override fun getBodyContentType(): String =
-        "application/json".also { this.addMarker("bodyContentType:$it") }
-
-    override fun getBody(): ByteArray {
-        val body = JSONObject()
-
-        body.put("registrationToken", registrationToken)
-        return body.toString().toByteArray()
-    }
-
-    override fun deliverResponse(response: String) = listener.onResponse(response)
-
-    override fun getRetryPolicy(): RetryPolicy =
-        retryPolicy ?: (super.getRetryPolicy() ?: DefaultRetryPolicy())
-
-    override fun getHeaders(): MutableMap<String, String> {
-        val headers = HashMap<String, String>(super.getHeaders())
-        if (faked) headers["cwa-fake"] = Math.random().toInt().toString()
-        else headers["cwa-fake"] = "0"
-        this.addMarker("headers:$headers")
-        return headers
-    }
-
-    override fun parseNetworkResponse(response: NetworkResponse?): Response<String> {
-        return try {
-            if (response == null) throw NullPointerException("response is null, this should never be the case")
-            val strResp = String(response.data)
-            val jsonObj = JSONObject(strResp)
-            val testResult = jsonObj.getString("tan")
-            return Response.success(
-                testResult,
-                HttpHeaderParser.parseCacheHeaders(response)
-            )
-        } catch (e: UnsupportedEncodingException) {
-            e.report(HTTP)
-            Log.e(TAG, "invalid encoding found")
-            Response.error(ParseError(e))
-        } catch (e: JSONException) {
-            Log.e(TAG, "invalid JSON message, probably the object parse failed")
-            e.report(HTTP)
-            Response.error(ParseError(e))
-        }
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/TestResultRequest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/TestResultRequest.kt
deleted file mode 100644
index 6634f8008e677cb8e668c1160398af9e3b15373a..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/request/TestResultRequest.kt
+++ /dev/null
@@ -1,76 +0,0 @@
-package de.rki.coronawarnapp.http.request
-
-import android.util.Log
-import com.android.volley.DefaultRetryPolicy
-import com.android.volley.NetworkResponse
-import com.android.volley.ParseError
-import com.android.volley.Request
-import com.android.volley.Response
-import com.android.volley.RetryPolicy
-import com.android.volley.toolbox.HttpHeaderParser
-import de.rki.coronawarnapp.exception.ExceptionCategory.HTTP
-import de.rki.coronawarnapp.exception.report
-import org.json.JSONException
-import org.json.JSONObject
-import java.io.UnsupportedEncodingException
-
-class TestResultRequest(
-    url: String,
-    private val requestTag: Any?,
-    private val registrationToken: String,
-    private val faked: Boolean,
-    private val retryPolicy: RetryPolicy?,
-    private val listener: Response.Listener<Int>,
-    errorListener: Response.ErrorListener
-) : Request<Int>(Method.POST, url, errorListener) {
-
-    companion object {
-        private val TAG: String? = TestResultRequest::class.simpleName
-    }
-
-    override fun getTag(): Any = requestTag ?: super.getTag().also { this.addMarker("tag:$it") }
-
-    override fun getBodyContentType(): String =
-        "application/json".also { this.addMarker("bodyContentType:$it") }
-
-    override fun getBody(): ByteArray {
-        val body = JSONObject()
-
-        body.put("registrationToken", registrationToken)
-        return body.toString().toByteArray()
-    }
-
-    override fun deliverResponse(response: Int) = listener.onResponse(response)
-
-    override fun getRetryPolicy(): RetryPolicy =
-        retryPolicy ?: (super.getRetryPolicy() ?: DefaultRetryPolicy())
-
-    override fun getHeaders(): MutableMap<String, String> {
-        val headers = HashMap<String, String>(super.getHeaders())
-        if (faked) headers["cwa-fake"] = Math.random().toInt().toString()
-        else headers["cwa-fake"] = "0"
-        this.addMarker("headers:$headers")
-        return headers
-    }
-
-    override fun parseNetworkResponse(response: NetworkResponse?): Response<Int> {
-        return try {
-            if (response == null) throw NullPointerException("response is null, this should never be the case")
-            val strResp = String(response.data)
-            val jsonObj = JSONObject(strResp)
-            val testResult = jsonObj.getInt("testResult")
-            return Response.success(
-                testResult,
-                HttpHeaderParser.parseCacheHeaders(response)
-            )
-        } catch (e: UnsupportedEncodingException) {
-            e.report(HTTP)
-            Log.e(TAG, "invalid encoding found")
-            Response.error(ParseError(e))
-        } catch (e: JSONException) {
-            Log.e(TAG, "invalid JSON message, probably the object parse failed")
-            e.report(HTTP)
-            Response.error(ParseError(e))
-        }
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/requests/RegistrationTokenRequest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/requests/RegistrationTokenRequest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..64b51092bc8b965b0df997c83af5bff45bfd9786
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/requests/RegistrationTokenRequest.kt
@@ -0,0 +1,10 @@
+package de.rki.coronawarnapp.http.requests
+
+import com.google.gson.annotations.SerializedName
+
+data class RegistrationTokenRequest(
+    @SerializedName("keyType")
+    val keyType: String,
+    @SerializedName("key")
+    val key: String
+)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/requests/ReqistrationRequest.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/requests/ReqistrationRequest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1c5dceb55042654a275cb6c6f5d3c49dc38fff82
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/requests/ReqistrationRequest.kt
@@ -0,0 +1,8 @@
+package de.rki.coronawarnapp.http.requests
+
+import com.google.gson.annotations.SerializedName
+
+data class ReqistrationRequest(
+    @SerializedName("registrationToken")
+    val registrationToken: String
+)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/requests/TanRequestBody.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/requests/TanRequestBody.kt
new file mode 100644
index 0000000000000000000000000000000000000000..a06f7aa9b56c5cac9f74bf0961b6a56eaecd597f
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/requests/TanRequestBody.kt
@@ -0,0 +1,8 @@
+package de.rki.coronawarnapp.http.requests
+
+import com.google.gson.annotations.SerializedName
+
+data class TanRequestBody(
+    @SerializedName("registrationToken")
+    val registrationToken: String
+)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/responses/RegistrationTokenResponse.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/responses/RegistrationTokenResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..4ec189715dc431a32c64e0a490815cc2abd4d90a
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/responses/RegistrationTokenResponse.kt
@@ -0,0 +1,8 @@
+package de.rki.coronawarnapp.http.responses
+
+import com.google.gson.annotations.SerializedName
+
+data class RegistrationTokenResponse(
+    @SerializedName("registrationToken")
+    val registrationToken: String
+)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/responses/TanResponse.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/responses/TanResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..91f1ea9b7c00ab4230b442127f84e61edd0e9796
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/responses/TanResponse.kt
@@ -0,0 +1,8 @@
+package de.rki.coronawarnapp.http.responses
+
+import com.google.gson.annotations.SerializedName
+
+data class TanResponse(
+    @SerializedName("tan")
+    val tan: String
+)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/responses/TestResultResponse.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/responses/TestResultResponse.kt
new file mode 100644
index 0000000000000000000000000000000000000000..065a2356f20f1ae6eaa09cd935f07f3bdbd7bfe3
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/responses/TestResultResponse.kt
@@ -0,0 +1,8 @@
+package de.rki.coronawarnapp.http.responses
+
+import com.google.gson.annotations.SerializedName
+
+data class TestResultResponse(
+    @SerializedName("testResult")
+    val testResult: Int
+)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/service/DistributionService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/service/DistributionService.kt
new file mode 100644
index 0000000000000000000000000000000000000000..9eef5b91ff6351e74d1b61e9c620b1856a181549
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/service/DistributionService.kt
@@ -0,0 +1,20 @@
+package de.rki.coronawarnapp.http.service
+
+import okhttp3.ResponseBody
+import retrofit2.http.GET
+import retrofit2.http.Url
+
+interface DistributionService {
+
+    @GET
+    suspend fun getDateIndex(@Url url: String): List<String>
+
+    @GET
+    suspend fun getHourIndex(@Url url: String): List<String>
+
+    @GET
+    suspend fun getKeyFiles(@Url url: String): ResponseBody
+
+    @GET
+    suspend fun getApplicationConfiguration(@Url url: String): ResponseBody
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/service/SubmissionService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/service/SubmissionService.kt
new file mode 100644
index 0000000000000000000000000000000000000000..e902a25b291a6bf9e89ceaac314a24487eaf05a0
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/service/SubmissionService.kt
@@ -0,0 +1,17 @@
+package de.rki.coronawarnapp.http.service
+
+import okhttp3.ResponseBody
+import retrofit2.http.Body
+import retrofit2.http.Header
+import retrofit2.http.POST
+import retrofit2.http.Url
+
+interface SubmissionService {
+    @POST
+    suspend fun submitKeys(
+        @Url url: String,
+        @Header("cwa-authorization") authCode: String,
+        @Header("cwa-fake") fake: String,
+        @Body requestBody: KeyExportFormat.SubmissionPayload
+    ): ResponseBody
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/service/VerificationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/service/VerificationService.kt
new file mode 100644
index 0000000000000000000000000000000000000000..688ceba4c53d8ae45c3d129760aa6b6caee98a61
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/http/service/VerificationService.kt
@@ -0,0 +1,36 @@
+package de.rki.coronawarnapp.http.service
+
+import de.rki.coronawarnapp.http.requests.RegistrationTokenRequest
+import de.rki.coronawarnapp.http.requests.ReqistrationRequest
+import de.rki.coronawarnapp.http.requests.TanRequestBody
+import de.rki.coronawarnapp.http.responses.RegistrationTokenResponse
+import de.rki.coronawarnapp.http.responses.TanResponse
+import de.rki.coronawarnapp.http.responses.TestResultResponse
+import retrofit2.http.Body
+import retrofit2.http.Header
+import retrofit2.http.POST
+import retrofit2.http.Url
+
+interface VerificationService {
+
+    @POST
+    suspend fun getRegistrationToken(
+        @Url url: String,
+        @Header("cwa-fake") fake: String,
+        @Body requestBody: RegistrationTokenRequest
+    ): RegistrationTokenResponse
+
+    @POST
+    suspend fun getTestResult(
+        @Url url: String,
+        @Header("cwa-fake") fake: String,
+        @Body request: ReqistrationRequest
+    ): TestResultResponse
+
+    @POST
+    suspend fun getTAN(
+        @Url url: String,
+        @Header("cwa-fake") fake: String,
+        @Body requestBody: TanRequestBody
+    ): TanResponse
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ExposureStateUpdateWorker.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ExposureStateUpdateWorker.kt
new file mode 100644
index 0000000000000000000000000000000000000000..bc97b2c7a0f981e49f7b7e1ea72bd565e5714aab
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/ExposureStateUpdateWorker.kt
@@ -0,0 +1,47 @@
+package de.rki.coronawarnapp.nearby
+
+import android.content.Context
+import android.util.Log
+import androidx.work.CoroutineWorker
+import androidx.work.WorkerParameters
+import com.google.android.gms.common.api.ApiException
+import com.google.android.gms.nearby.exposurenotification.ExposureNotificationClient
+import de.rki.coronawarnapp.exception.ExceptionCategory
+import de.rki.coronawarnapp.exception.NoTokenException
+import de.rki.coronawarnapp.exception.TransactionException
+import de.rki.coronawarnapp.exception.report
+import de.rki.coronawarnapp.storage.ExposureSummaryRepository
+import de.rki.coronawarnapp.transaction.RiskLevelTransaction
+
+class ExposureStateUpdateWorker(val context: Context, workerParams: WorkerParameters) :
+    CoroutineWorker(context, workerParams) {
+    companion object {
+        private val TAG = ExposureStateUpdateWorker::class.simpleName
+    }
+
+    override suspend fun doWork(): Result {
+        try {
+            Log.v(TAG, "worker to persist exposure summary started")
+            val token = inputData.getString(ExposureNotificationClient.EXTRA_TOKEN)
+                ?: throw NoTokenException(IllegalArgumentException("no token was found in the intent"))
+
+            Log.v(TAG, "valid token $token retrieved")
+
+            val exposureSummary = InternalExposureNotificationClient
+                .asyncGetExposureSummary(token)
+
+            ExposureSummaryRepository.getExposureSummaryRepository()
+                .insertExposureSummaryEntity(exposureSummary)
+            Log.v(TAG, "exposure summary state updated: $exposureSummary")
+
+            RiskLevelTransaction.start()
+            Log.v(TAG, "risk level calculation triggered")
+        } catch (e: ApiException) {
+            e.report(ExceptionCategory.EXPOSURENOTIFICATION)
+        } catch (e: TransactionException) {
+            e.report(ExceptionCategory.INTERNAL)
+        }
+
+        return Result.success()
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/receiver/ExposureStateUpdateReceiver.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/receiver/ExposureStateUpdateReceiver.kt
index e41d7b94ed186fe23d49704b177028c52bb20416..9a28ffa7b512be3d7d62fac0f05979e3f7325164 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/receiver/ExposureStateUpdateReceiver.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/receiver/ExposureStateUpdateReceiver.kt
@@ -3,22 +3,15 @@ package de.rki.coronawarnapp.receiver
 import android.content.BroadcastReceiver
 import android.content.Context
 import android.content.Intent
-import android.util.Log
-import com.google.android.gms.common.api.ApiException
+import androidx.work.Data
+import androidx.work.OneTimeWorkRequest
+import androidx.work.WorkManager
 import com.google.android.gms.nearby.exposurenotification.ExposureNotificationClient
-import de.rki.coronawarnapp.exception.ExceptionCategory.EXPOSURENOTIFICATION
 import de.rki.coronawarnapp.exception.ExceptionCategory.INTERNAL
-import de.rki.coronawarnapp.exception.TransactionException
+import de.rki.coronawarnapp.exception.NoTokenException
 import de.rki.coronawarnapp.exception.WrongReceiverException
 import de.rki.coronawarnapp.exception.report
-import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient
-import de.rki.coronawarnapp.storage.ExposureSummaryRepository
-import de.rki.coronawarnapp.storage.LocalData
-import de.rki.coronawarnapp.transaction.RiskLevelTransaction
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
-import java.util.UUID
+import de.rki.coronawarnapp.nearby.ExposureStateUpdateWorker
 
 /**
  * Receiver to listen to the Exposure Notification Exposure State Updated event. This event will be triggered from the
@@ -36,8 +29,6 @@ import java.util.UUID
 class ExposureStateUpdateReceiver : BroadcastReceiver() {
     companion object {
         private val TAG: String? = ExposureStateUpdateReceiver::class.simpleName
-        private const val EXPOSURE_STATE_UPDATE_PERMISSION =
-            "com.google.android.gms.nearby.exposurenotification.EXPOSURE_CALLBACK"
     }
 
     override fun onReceive(context: Context, intent: Intent) {
@@ -51,32 +42,27 @@ class ExposureStateUpdateReceiver : BroadcastReceiver() {
                     IllegalArgumentException("wrong action was received")
                 )
             }
-            val token = LocalData.googleApiToken()
 
-            val pendingRepository = goAsync()
+            val token =
+                intent.getStringExtra(ExposureNotificationClient.EXTRA_TOKEN)
+                    ?: throw NoTokenException(
+                        IllegalArgumentException("no token was found in the intent")
+                    )
 
-            GlobalScope.launch(Dispatchers.Default) {
-                try {
-                    val exposureSummary = InternalExposureNotificationClient
-                        .asyncGetExposureSummary(token ?: UUID.randomUUID().toString())
-
-                    ExposureSummaryRepository.getExposureSummaryRepository()
-                        .insertExposureSummaryEntity(exposureSummary)
-                    pendingRepository.finish()
-                    Log.v(TAG, "exposure summary state updated")
-                    try {
-                        RiskLevelTransaction.start()
-                    } catch (e: TransactionException) {
-                        e.report(INTERNAL)
-                    }
-                    Log.v(TAG, "exposure summary updated - trigger a new risk level calculation")
-                    Log.v(TAG, exposureSummary.toString())
-                } catch (e: ApiException) {
-                    e.report(EXPOSURENOTIFICATION)
-                }
-            }
+            val workManager = WorkManager.getInstance(context)
+            workManager.enqueue(
+                OneTimeWorkRequest.Builder(ExposureStateUpdateWorker::class.java)
+                    .setInputData(
+                        Data.Builder()
+                            .putString(ExposureNotificationClient.EXTRA_TOKEN, token)
+                            .build()
+                    )
+                    .build()
+            )
         } catch (e: WrongReceiverException) {
             e.report(INTERNAL)
+        } catch (e: NoTokenException) {
+            e.report(INTERNAL)
         }
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelCalculation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelCalculation.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0da900ecf9c83bc4969ff658ca331329616956a4
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/RiskLevelCalculation.kt
@@ -0,0 +1,65 @@
+package de.rki.coronawarnapp.risk
+
+import android.util.Log
+import com.google.android.gms.nearby.exposurenotification.ExposureSummary
+import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass
+import kotlin.math.round
+
+object RiskLevelCalculation {
+    private var TAG = RiskLevelCalculation::class.simpleName
+
+    private const val DECIMAL_MULTIPLIER = 100
+
+    fun calculateRiskScore(
+        attenuationParameters: ApplicationConfigurationOuterClass.AttenuationDuration,
+        exposureSummary: ExposureSummary
+    ): Double {
+
+        /** all attenuation values are capped to [TimeVariables.MAX_ATTENUATION_DURATION] */
+        val weightedAttenuationLow =
+            attenuationParameters.weights.low.capped()
+                .times(exposureSummary.attenuationDurationsInMinutes[0])
+        val weightedAttenuationMid =
+            attenuationParameters.weights.mid.capped()
+                .times(exposureSummary.attenuationDurationsInMinutes[1])
+        val weightedAttenuationHigh =
+            attenuationParameters.weights.high.capped()
+                .times(exposureSummary.attenuationDurationsInMinutes[2])
+
+        val maximumRiskScore = exposureSummary.maximumRiskScore.toDouble()
+
+        val defaultBucketOffset = attenuationParameters.defaultBucketOffset.toDouble()
+        val normalizationDivisor = attenuationParameters.riskScoreNormalizationDivisor.toDouble()
+
+        Log.v(
+            TAG,
+            "Weighted Attenuation: ($weightedAttenuationLow +" +
+                    " $weightedAttenuationMid +" +
+                    " $weightedAttenuationHigh +" +
+                    " $defaultBucketOffset)"
+        )
+
+        val weightedAttenuationDuration =
+            weightedAttenuationLow
+                .plus(weightedAttenuationMid)
+                .plus(weightedAttenuationHigh)
+                .plus(defaultBucketOffset)
+
+        Log.v(
+            TAG,
+            "Formula used: ($maximumRiskScore / $normalizationDivisor) * $weightedAttenuationDuration"
+        )
+
+        val riskScore = (maximumRiskScore / normalizationDivisor) * weightedAttenuationDuration
+
+        return round(riskScore.times(DECIMAL_MULTIPLIER)).div(DECIMAL_MULTIPLIER)
+    }
+
+    private fun Double.capped(): Double {
+        return if (this > TimeVariables.getMaxAttenuationDuration()) {
+            TimeVariables.getMaxAttenuationDuration()
+        } else {
+            this
+        }
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/TimeVariables.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/TimeVariables.kt
index 1e87eb70dfb0433e7c8ba1b1ee95da0388c58122..2e90edd67d3ae3aa8396d50c7f1258ada2b38e15 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/TimeVariables.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/TimeVariables.kt
@@ -115,6 +115,19 @@ object TimeVariables {
      */
     fun getManualKeyRetrievalDelay() = MANUAL_KEY_RETRIEVAL_DELAY
 
+    /**
+     * This is the maximum attenuation duration value for the risk level calculation
+     * in minutes
+     */
+    private const val MAX_ATTENUATION_DURATION = 30.0
+
+    /**
+     * Getter function for [MAX_ATTENUATION_DURATION]
+     *
+     * @return max attenuation duration in minutes
+     */
+    fun getMaxAttenuationDuration() = MAX_ATTENUATION_DURATION
+
     /****************************************************
      * STORED DATA
      ****************************************************/
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/applicationconfiguration/ApplicationConfigurationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/applicationconfiguration/ApplicationConfigurationService.kt
new file mode 100644
index 0000000000000000000000000000000000000000..596ba0925338015533e0c50a5fd8e82cd3e1365a
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/applicationconfiguration/ApplicationConfigurationService.kt
@@ -0,0 +1,68 @@
+package de.rki.coronawarnapp.service.applicationconfiguration
+
+import com.google.android.gms.nearby.exposurenotification.ExposureConfiguration
+import de.rki.coronawarnapp.http.WebRequestBuilder
+import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass
+
+object ApplicationConfigurationService {
+    suspend fun asyncRetrieveApplicationConfiguration(): ApplicationConfigurationOuterClass.ApplicationConfiguration {
+        return WebRequestBuilder
+            .asyncGetApplicationConfigurationFromServer()
+    }
+
+    suspend fun asyncRetrieveExposureConfiguration(): ExposureConfiguration =
+        asyncRetrieveApplicationConfiguration()
+            .mapRiskScoreToExposureConfiguration()
+
+    // todo double check that the weighted params are not used
+    private fun ApplicationConfigurationOuterClass.ApplicationConfiguration
+            .mapRiskScoreToExposureConfiguration(): ExposureConfiguration =
+        ExposureConfiguration
+            .ExposureConfigurationBuilder()
+            .setTransmissionRiskScores(
+                this.exposureConfig.transmission.appDefined1Value,
+                this.exposureConfig.transmission.appDefined2Value,
+                this.exposureConfig.transmission.appDefined3Value,
+                this.exposureConfig.transmission.appDefined4Value,
+                this.exposureConfig.transmission.appDefined5Value,
+                this.exposureConfig.transmission.appDefined6Value,
+                this.exposureConfig.transmission.appDefined7Value,
+                this.exposureConfig.transmission.appDefined8Value
+            )
+            .setDurationScores(
+                this.exposureConfig.duration.eq0MinValue,
+                this.exposureConfig.duration.gt0Le5MinValue,
+                this.exposureConfig.duration.gt5Le10MinValue,
+                this.exposureConfig.duration.gt10Le15MinValue,
+                this.exposureConfig.duration.gt15Le20MinValue,
+                this.exposureConfig.duration.gt20Le25MinValue,
+                this.exposureConfig.duration.gt25Le30MinValue,
+                this.exposureConfig.duration.gt30MinValue
+            )
+            .setDaysSinceLastExposureScores(
+                this.exposureConfig.daysSinceLastExposure.ge14DaysValue,
+                this.exposureConfig.daysSinceLastExposure.ge12Lt14DaysValue,
+                this.exposureConfig.daysSinceLastExposure.ge10Lt12DaysValue,
+                this.exposureConfig.daysSinceLastExposure.ge8Lt10DaysValue,
+                this.exposureConfig.daysSinceLastExposure.ge6Lt8DaysValue,
+                this.exposureConfig.daysSinceLastExposure.ge4Lt6DaysValue,
+                this.exposureConfig.daysSinceLastExposure.ge2Lt4DaysValue,
+                this.exposureConfig.daysSinceLastExposure.ge0Lt2DaysValue
+            )
+            .setAttenuationScores(
+                this.exposureConfig.attenuation.gt73DbmValue,
+                this.exposureConfig.attenuation.gt63Le73DbmValue,
+                this.exposureConfig.attenuation.gt51Le63DbmValue,
+                this.exposureConfig.attenuation.gt33Le51DbmValue,
+                this.exposureConfig.attenuation.gt27Le33DbmValue,
+                this.exposureConfig.attenuation.gt15Le27DbmValue,
+                this.exposureConfig.attenuation.gt10Le15DbmValue,
+                this.exposureConfig.attenuation.lt10DbmValue
+            )
+            .setMinimumRiskScore(this.minRiskScore)
+            .setDurationAtAttenuationThresholds(
+                this.attenuationDuration.thresholds.lower,
+                this.attenuationDuration.thresholds.upper
+            )
+            .build()
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyConstants.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyConstants.kt
index ce90f98ce95115d62142da3a38cdac497cede5b6..beef25125312cb51f5bde31a23a251ba8588ad63 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyConstants.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyConstants.kt
@@ -19,8 +19,6 @@
 
 package de.rki.coronawarnapp.service.diagnosiskey
 
-import de.rki.coronawarnapp.http.DynamicURLs
-
 /**
  * The Diagnosis Key constants are used inside the DiagnosisKeyService
  *
@@ -53,10 +51,10 @@ object DiagnosisKeyConstants {
     private var CURRENT_COUNTRY = "DE"
 
     /** Distribution URL built from CDN URL's and REST resources */
-    private var VERSIONED_DISTRIBUTION_CDN_URL = DynamicURLs.DOWNLOAD_CDN_URL + "/$VERSION/$CURRENT_VERSION"
+    private var VERSIONED_DISTRIBUTION_CDN_URL = "/$VERSION/$CURRENT_VERSION"
 
     /** Submission URL built from CDN URL's and REST resources */
-    private var VERSIONED_SUBMISSION_CDN_URL = DynamicURLs.SUBMISSION_CDN_URL + "/$VERSION/$CURRENT_VERSION"
+    private var VERSIONED_SUBMISSION_CDN_URL = "/$VERSION/$CURRENT_VERSION"
 
     /** Parameter Download URL built from CDN URL's and REST resources */
     private val PARAMETERS_DOWNLOAD_URL = "$VERSIONED_DISTRIBUTION_CDN_URL/$PARAMETERS"
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt
index 7169d014ed75b2b5e901870076f8c7c128a34585..24682d27e24334a78c12e7e8438a41656be37b80 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/diagnosiskey/DiagnosisKeyService.kt
@@ -24,7 +24,6 @@ import android.util.Log
 import de.rki.coronawarnapp.exception.DiagnosisKeyRetrievalException
 import de.rki.coronawarnapp.exception.DiagnosisKeySubmissionException
 import de.rki.coronawarnapp.http.WebRequestBuilder
-import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyConstants.DIAGNOSIS_KEYS_SUBMISSION_URL
 
 /**
  * The Diagnosis Key Service is used to interact with the Server to submit and retrieve keys through
@@ -51,7 +50,6 @@ object DiagnosisKeyService {
         try {
             Log.d(TAG, "Diagnosis Keys will be submitted.")
             WebRequestBuilder.asyncSubmitKeysToServer(
-                DIAGNOSIS_KEYS_SUBMISSION_URL,
                 authCode,
                 false,
                 keysToReport
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/riskscoreclassification/RiskScoreClassificationService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/riskscoreclassification/RiskScoreClassificationService.kt
deleted file mode 100644
index b29989b49c6a3f1439caeb4e62e8dbc38fb7ce48..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/riskscoreclassification/RiskScoreClassificationService.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package de.rki.coronawarnapp.service.riskscoreclassification
-
-import de.rki.coronawarnapp.http.WebRequestBuilder
-import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass.RiskScoreClassification
-import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyConstants
-
-object RiskScoreClassificationService {
-    suspend fun asyncRetrieveRiskScoreClassification(): RiskScoreClassification {
-        return WebRequestBuilder
-            .asyncGetApplicationConfigurationFromServer(DiagnosisKeyConstants.COUNTRY_APPCONFIG_DOWNLOAD_URL)
-            .riskScoreClasses
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/riskscoreparameter/RiskScoreParameterService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/riskscoreparameter/RiskScoreParameterService.kt
deleted file mode 100644
index 6df6ffded62244034daf9a1e4b9832b56f493ffa..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/riskscoreparameter/RiskScoreParameterService.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-package de.rki.coronawarnapp.service.riskscoreparameter
-
-import com.google.android.gms.nearby.exposurenotification.ExposureConfiguration
-import de.rki.coronawarnapp.http.WebRequestBuilder
-import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass.RiskScoreParameters
-import de.rki.coronawarnapp.service.diagnosiskey.DiagnosisKeyConstants
-
-object RiskScoreParameterService {
-    suspend fun asyncRetrieveRiskScoreParameters(): ExposureConfiguration =
-        WebRequestBuilder
-            .asyncGetApplicationConfigurationFromServer(DiagnosisKeyConstants.COUNTRY_APPCONFIG_DOWNLOAD_URL)
-            .exposureConfig
-            .mapRiskScoreToExposureConfiguration()
-
-    // TODO also add minimumRiskScore as soon as the backend will provide it in the correct proto
-    // right now it is available but only in the parent ApplicationConfiguration
-    private fun RiskScoreParameters.mapRiskScoreToExposureConfiguration(): ExposureConfiguration =
-        ExposureConfiguration
-            .ExposureConfigurationBuilder()
-            .setAttenuationWeight(this.attenuationWeight.toInt())
-            .setAttenuationScores(
-                this.attenuation.gt73DbmValue,
-                this.attenuation.gt63Le73DbmValue,
-                this.attenuation.gt51Le63DbmValue,
-                this.attenuation.gt33Le51DbmValue,
-                this.attenuation.gt27Le33DbmValue,
-                this.attenuation.gt15Le27DbmValue,
-                this.attenuation.gt10Le15DbmValue,
-                this.attenuation.lt10DbmValue
-            )
-            .setDaysSinceLastExposureWeight(this.daysWeight.toInt())
-            .setDaysSinceLastExposureScores(
-                this.daysSinceLastExposure.ge14DaysValue,
-                this.daysSinceLastExposure.ge12Lt14DaysValue,
-                this.daysSinceLastExposure.ge10Lt12DaysValue,
-                this.daysSinceLastExposure.ge8Lt10DaysValue,
-                this.daysSinceLastExposure.ge6Lt8DaysValue,
-                this.daysSinceLastExposure.ge4Lt6DaysValue,
-                this.daysSinceLastExposure.ge2Lt4DaysValue,
-                this.daysSinceLastExposure.ge0Lt2DaysValue
-            )
-            .setDurationWeight(this.durationWeight.toInt())
-            .setDurationScores(
-                this.duration.eq0MinValue,
-                this.duration.gt0Le5MinValue,
-                this.duration.gt5Le10MinValue,
-                this.duration.gt10Le15MinValue,
-                this.duration.gt15Le20MinValue,
-                this.duration.gt20Le25MinValue,
-                this.duration.gt25Le30MinValue,
-                this.duration.gt30MinValue
-            )
-            .setTransmissionRiskWeight(this.transmissionWeight.toInt())
-            .setTransmissionRiskScores(
-                this.transmission.appDefined1Value,
-                this.transmission.appDefined2Value,
-                this.transmission.appDefined3Value,
-                this.transmission.appDefined4Value,
-                this.transmission.appDefined5Value,
-                this.transmission.appDefined6Value,
-                this.transmission.appDefined7Value,
-                this.transmission.appDefined8Value
-            ).build()
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionConstants.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionConstants.kt
index 6edc4ce1bfc13a6d94b5924234ad29e1a46a0e0c..a99128c90139e6e25660ee52dcda1740142288d6 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionConstants.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionConstants.kt
@@ -1,7 +1,5 @@
 package de.rki.coronawarnapp.service.submission
 
-import de.rki.coronawarnapp.http.DynamicURLs
-
 object SubmissionConstants {
     private const val VERSION = "version"
     private const val REGISTRATION_TOKEN = "registrationToken"
@@ -10,8 +8,7 @@ object SubmissionConstants {
 
     private var CURRENT_VERSION = "v1"
 
-    private var VERIFICATION_CDN_URL = DynamicURLs.VERIFICATION_CDN_URL
-    private val VERSIONED_VERIFICATION_CDN_URL = "$VERIFICATION_CDN_URL/$VERSION/$CURRENT_VERSION"
+    private val VERSIONED_VERIFICATION_CDN_URL = "$VERSION/$CURRENT_VERSION"
 
     const val QR_CODE_KEY_TYPE = "GUID"
     const val TELE_TAN_KEY_TYPE = "TELETAN"
@@ -19,4 +16,8 @@ object SubmissionConstants {
     val REGISTRATION_TOKEN_URL = "$VERSIONED_VERIFICATION_CDN_URL/$REGISTRATION_TOKEN"
     val TEST_RESULT_URL = "$VERSIONED_VERIFICATION_CDN_URL/$TEST_RESULT"
     val TAN_REQUEST_URL = "$VERSIONED_VERIFICATION_CDN_URL/$TAN"
+
+    const val MAX_QR_CODE_LENGTH = 150
+    const val MAX_GUID_LENGTH = 80
+    const val GUID_SEPARATOR = '?'
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt
index ad23d8a0d3bcfdb5929ce91e24f9385117ab069b..c50399d451d64d9d6df4c21c22525e09ef3cf362 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/service/submission/SubmissionService.kt
@@ -4,11 +4,10 @@ import de.rki.coronawarnapp.exception.NoGUIDOrTANSetException
 import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException
 import de.rki.coronawarnapp.http.WebRequestBuilder
 import de.rki.coronawarnapp.service.submission.SubmissionConstants.QR_CODE_KEY_TYPE
-import de.rki.coronawarnapp.service.submission.SubmissionConstants.REGISTRATION_TOKEN_URL
-import de.rki.coronawarnapp.service.submission.SubmissionConstants.TAN_REQUEST_URL
 import de.rki.coronawarnapp.service.submission.SubmissionConstants.TELE_TAN_KEY_TYPE
 import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.transaction.SubmitDiagnosisKeysTransaction
+import de.rki.coronawarnapp.util.formatter.TestResult
 
 object SubmissionService {
     suspend fun asyncRegisterDevice() {
@@ -26,7 +25,6 @@ object SubmissionService {
     private suspend fun asyncRegisterDeviceViaGUID(guid: String) {
         val registrationToken =
             WebRequestBuilder.asyncGetRegistrationToken(
-                REGISTRATION_TOKEN_URL,
                 guid,
                 QR_CODE_KEY_TYPE
             )
@@ -38,7 +36,6 @@ object SubmissionService {
     private suspend fun asyncRegisterDeviceViaTAN(tan: String) {
         val registrationToken =
             WebRequestBuilder.asyncGetRegistrationToken(
-                REGISTRATION_TOKEN_URL,
                 tan,
                 TELE_TAN_KEY_TYPE
             )
@@ -47,11 +44,8 @@ object SubmissionService {
         deleteTeleTAN()
     }
 
-    suspend fun asyncRequestAuthCode(): String {
-        val registrationToken =
-            LocalData.registrationToken() ?: throw NoRegistrationTokenSetException()
-
-        val authCode = WebRequestBuilder.asyncGetTan(TAN_REQUEST_URL, registrationToken)
+    suspend fun asyncRequestAuthCode(registrationToken: String): String {
+        val authCode = WebRequestBuilder.asyncGetTan(registrationToken)
         return authCode
     }
 
@@ -61,17 +55,28 @@ object SubmissionService {
         SubmitDiagnosisKeysTransaction.start(registrationToken)
     }
 
-    /**
-     * extracts the GUID from [scanResult]. Returns null if it does not match the required pattern
-     */
-    fun extractGUID(scanResult: String): String? {
-        val potentialGUID = scanResult.substringAfterLast("?", "")
-        return if (potentialGUID.isEmpty())
-            null
-        else
-            potentialGUID
+    suspend fun asyncRequestTestResult(): TestResult {
+        val registrationToken =
+            LocalData.registrationToken() ?: throw NoRegistrationTokenSetException()
+        return TestResult.fromInt(
+            WebRequestBuilder.asyncGetTestResult(registrationToken)
+        )
+    }
+
+    fun containsValidGUID(scanResult: String): Boolean {
+        if (scanResult.length > SubmissionConstants.MAX_QR_CODE_LENGTH ||
+            scanResult.count { it == SubmissionConstants.GUID_SEPARATOR } != 1
+        )
+            return false
+
+        val potentialGUID = extractGUID(scanResult)
+
+        return !(potentialGUID.isEmpty() || potentialGUID.length > SubmissionConstants.MAX_GUID_LENGTH)
     }
 
+    fun extractGUID(scanResult: String): String =
+        scanResult.substringAfterLast(SubmissionConstants.GUID_SEPARATOR, "")
+
     fun storeTestGUID(guid: String) = LocalData.testGUID(guid)
 
     fun deleteTestGUID() {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt
index 1988d0d4d7ae593979fb45563ebb6b362ebdb7b6..734d06ac111bae16796557d58ef4304983b423bd 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt
@@ -160,7 +160,7 @@ object LocalData {
     fun lastTimeDiagnosisKeysFromServerFetch(): Date? {
         val time = getSharedPreferenceInstance().getLong(
             CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_m_timestamp_diagnosis_keys_fetch),
+                .getString(R.string.preference_timestamp_diagnosis_keys_fetch),
             0L
         )
         // TODO need this for nullable ref, shout not be goto for nullable storage
@@ -180,7 +180,7 @@ object LocalData {
         getSharedPreferenceInstance().edit(true) {
             putLong(
                 CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_m_timestamp_diagnosis_keys_fetch),
+                    .getString(R.string.preference_timestamp_diagnosis_keys_fetch),
                 value?.time ?: 0L
             )
         }
@@ -193,7 +193,7 @@ object LocalData {
      */
     fun lastTimeManualDiagnosisKeysRetrieved(): Long = getSharedPreferenceInstance().getLong(
         CoronaWarnApplication.getAppContext()
-            .getString(R.string.preference_m_timestamp_manual_diagnosis_keys_retrieval),
+            .getString(R.string.preference_timestamp_manual_diagnosis_keys_retrieval),
         0L
     )
 
@@ -204,7 +204,7 @@ object LocalData {
         getSharedPreferenceInstance().edit(true) {
             putLong(
                 CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_m_timestamp_manual_diagnosis_keys_retrieval),
+                    .getString(R.string.preference_timestamp_manual_diagnosis_keys_retrieval),
                 value
             )
         }
@@ -220,7 +220,7 @@ object LocalData {
      */
     fun googleApiToken(): String? = getSharedPreferenceInstance().getString(
         CoronaWarnApplication.getAppContext()
-            .getString(R.string.preference_m_string_google_api_token),
+            .getString(R.string.preference_string_google_api_token),
         null
     )
 
@@ -232,7 +232,7 @@ object LocalData {
     fun googleApiToken(value: String?) = getSharedPreferenceInstance().edit(true) {
         putString(
             CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_m_string_google_api_token),
+                .getString(R.string.preference_string_google_api_token),
             value
         )
     }
@@ -333,7 +333,7 @@ object LocalData {
      */
     fun registrationToken(): String? = getSharedPreferenceInstance().getString(
         CoronaWarnApplication.getAppContext()
-            .getString(R.string.preference_m_registration_token),
+            .getString(R.string.preference_registration_token),
         null
     )
 
@@ -346,7 +346,7 @@ object LocalData {
         getSharedPreferenceInstance().edit(true) {
             putString(
                 CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_m_registration_token),
+                    .getString(R.string.preference_registration_token),
                 value
             )
         }
@@ -410,7 +410,7 @@ object LocalData {
 
     fun testGUID(): String? = getSharedPreferenceInstance().getString(
         CoronaWarnApplication.getAppContext()
-            .getString(R.string.preference_m_test_guid),
+            .getString(R.string.preference_test_guid),
         null
     )
 
@@ -418,7 +418,7 @@ object LocalData {
         getSharedPreferenceInstance().edit(true) {
             putString(
                 CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_m_test_guid),
+                    .getString(R.string.preference_test_guid),
                 value
             )
         }
@@ -426,7 +426,7 @@ object LocalData {
 
     fun authCode(): String? = getSharedPreferenceInstance().getString(
         CoronaWarnApplication.getAppContext()
-            .getString(R.string.preference_m_auth_code),
+            .getString(R.string.preference_auth_code),
         null
     )
 
@@ -434,7 +434,7 @@ object LocalData {
         getSharedPreferenceInstance().edit(true) {
             putString(
                 CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_m_auth_code),
+                    .getString(R.string.preference_auth_code),
                 value
             )
         }
@@ -444,7 +444,7 @@ object LocalData {
         getSharedPreferenceInstance().edit(true) {
             putBoolean(
                 CoronaWarnApplication.getAppContext()
-                    .getString(R.string.preference_m_is_allowed_to_submit_diagnosis_keys),
+                    .getString(R.string.preference_is_allowed_to_submit_diagnosis_keys),
                 isAllowedToSubmitDiagnosisKeys
             )
         }
@@ -453,7 +453,7 @@ object LocalData {
     fun isAllowedToSubmitDiagnosisKeys(): Boolean? {
         return getSharedPreferenceInstance().getBoolean(
             CoronaWarnApplication.getAppContext()
-                .getString(R.string.preference_m_is_allowed_to_submit_diagnosis_keys),
+                .getString(R.string.preference_is_allowed_to_submit_diagnosis_keys),
             false
         )
     }
@@ -482,5 +482,5 @@ object LocalData {
 
     fun getLastFetchDatePreference() =
         CoronaWarnApplication.getAppContext()
-            .getString(R.string.preference_m_timestamp_diagnosis_keys_fetch)
+            .getString(R.string.preference_timestamp_diagnosis_keys_fetch)
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt
index 5d3546d60344dadc673df5f389c561195ce40388..f6ab3dad85f97a4aad5977020b87057c54410e80 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SubmissionRepository.kt
@@ -2,34 +2,61 @@ package de.rki.coronawarnapp.storage
 
 import androidx.lifecycle.MutableLiveData
 import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException
-import de.rki.coronawarnapp.http.WebRequestBuilder
-import de.rki.coronawarnapp.service.submission.SubmissionConstants.TEST_RESULT_URL
+import de.rki.coronawarnapp.service.submission.SubmissionService
+import de.rki.coronawarnapp.util.DeviceUIState
 import de.rki.coronawarnapp.util.formatter.TestResult
 import java.util.Date
 
 object SubmissionRepository {
     private val TAG: String? = SubmissionRepository::class.simpleName
 
-    val testResult = MutableLiveData(TestResult.INVALID)
     val testResultReceivedDate = MutableLiveData(Date())
+    val deviceUIState = MutableLiveData(DeviceUIState.UNPAIRED)
 
-    suspend fun refreshTestResult() {
-        val registrationToken =
-            LocalData.registrationToken() ?: throw NoRegistrationTokenSetException()
-        val testResultValue =
-            WebRequestBuilder.asyncGetTestResult(TEST_RESULT_URL, registrationToken)
-        testResult.value = TestResult.fromInt(testResultValue)
-        if (testResult == TestResult.POSITIVE) {
-            LocalData.isAllowedToSubmitDiagnosisKeys(true)
-        }
-        val initialTestResultReceivedTimestamp = LocalData.inititalTestResultReceivedTimestamp()
+    suspend fun refreshUIState() {
+        var uiState = DeviceUIState.UNPAIRED
 
-        if (initialTestResultReceivedTimestamp == null) {
-            val currentTime = System.currentTimeMillis()
-            LocalData.inititalTestResultReceivedTimestamp(currentTime)
-            testResultReceivedDate.value = Date(currentTime)
+        if (LocalData.numberOfSuccessfulSubmissions() == 1) {
+            uiState = DeviceUIState.SUBMITTED_FINAL
         } else {
-            testResultReceivedDate.value = Date(initialTestResultReceivedTimestamp)
+            if (LocalData.registrationToken() != null) {
+                uiState = when {
+                    LocalData.isAllowedToSubmitDiagnosisKeys() == true -> {
+                        DeviceUIState.PAIRED_POSITIVE
+                    }
+                    else -> fetchTestResult()
+                }
+            }
+        }
+        deviceUIState.value = uiState
+    }
+
+    private suspend fun fetchTestResult(): DeviceUIState {
+        try {
+            val testResult = SubmissionService.asyncRequestTestResult()
+
+            if (testResult == TestResult.POSITIVE) {
+                LocalData.isAllowedToSubmitDiagnosisKeys(true)
+            }
+
+            val initialTestResultReceivedTimestamp = LocalData.inititalTestResultReceivedTimestamp()
+
+            if (initialTestResultReceivedTimestamp == null) {
+                val currentTime = System.currentTimeMillis()
+                LocalData.inititalTestResultReceivedTimestamp(currentTime)
+                testResultReceivedDate.value = Date(currentTime)
+            } else {
+                testResultReceivedDate.value = Date(initialTestResultReceivedTimestamp)
+            }
+
+            return when (testResult) {
+                TestResult.NEGATIVE -> DeviceUIState.PAIRED_NEGATIVE
+                TestResult.POSITIVE -> DeviceUIState.PAIRED_POSITIVE
+                TestResult.PENDING -> DeviceUIState.PAIRED_NO_RESULT
+                TestResult.INVALID -> DeviceUIState.PAIRED_ERROR
+            }
+        } catch (err: NoRegistrationTokenSetException) {
+            return DeviceUIState.UNPAIRED
         }
     }
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/RetrieveDiagnosisKeysTransaction.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/RetrieveDiagnosisKeysTransaction.kt
index 9547187c67b0b5f58bcd31ff16742c289e820769..49e9ff6f798152a0df0974b11d37863209c72fe1 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/RetrieveDiagnosisKeysTransaction.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/RetrieveDiagnosisKeysTransaction.kt
@@ -23,7 +23,7 @@ import android.util.Log
 import com.google.android.gms.nearby.exposurenotification.ExposureConfiguration
 import de.rki.coronawarnapp.CoronaWarnApplication
 import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient
-import de.rki.coronawarnapp.service.riskscoreparameter.RiskScoreParameterService
+import de.rki.coronawarnapp.service.applicationconfiguration.ApplicationConfigurationService
 import de.rki.coronawarnapp.storage.FileStorageHelper
 import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.storage.keycache.KeyCacheRepository
@@ -215,7 +215,7 @@ object RetrieveDiagnosisKeysTransaction : Transaction() {
      */
     private suspend fun executeRetrieveRiskScoreParams() =
         executeState(RETRIEVE_RISK_SCORE_PARAMS) {
-            RiskScoreParameterService.asyncRetrieveRiskScoreParameters()
+            ApplicationConfigurationService.asyncRetrieveExposureConfiguration()
         }
 
     /**
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/RiskLevelTransaction.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/RiskLevelTransaction.kt
index 48c521cae4c8a7f57ff0f2cd38afd7a2501c5531..32e157f3771cbb6e23cb8a4fc9761b7b0b064267 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/RiskLevelTransaction.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/RiskLevelTransaction.kt
@@ -2,9 +2,11 @@ package de.rki.coronawarnapp.transaction
 
 import android.util.Log
 import androidx.core.app.NotificationCompat
+import androidx.lifecycle.MutableLiveData
 import com.google.android.gms.nearby.exposurenotification.ExposureSummary
 import de.rki.coronawarnapp.CoronaWarnApplication
 import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.TestRiskLevelCalculation
 import de.rki.coronawarnapp.exception.RiskLevelCalculationException
 import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient
 import de.rki.coronawarnapp.notification.NotificationHelper
@@ -15,9 +17,10 @@ import de.rki.coronawarnapp.risk.RiskLevel.NO_CALCULATION_POSSIBLE_TRACING_OFF
 import de.rki.coronawarnapp.risk.RiskLevel.UNDETERMINED
 import de.rki.coronawarnapp.risk.RiskLevel.UNKNOWN_RISK_INITIAL
 import de.rki.coronawarnapp.risk.RiskLevel.UNKNOWN_RISK_OUTDATED_RESULTS
+import de.rki.coronawarnapp.risk.RiskLevelCalculation
 import de.rki.coronawarnapp.risk.TimeVariables
-import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass.RiskScoreClassification
-import de.rki.coronawarnapp.service.riskscoreclassification.RiskScoreClassificationService
+import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass
+import de.rki.coronawarnapp.service.applicationconfiguration.ApplicationConfigurationService
 import de.rki.coronawarnapp.storage.ExposureSummaryRepository
 import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.storage.RiskLevelRepository
@@ -27,8 +30,8 @@ import de.rki.coronawarnapp.transaction.RiskLevelTransaction.RiskLevelTransactio
 import de.rki.coronawarnapp.transaction.RiskLevelTransaction.RiskLevelTransactionState.CHECK_UNKNOWN_RISK_INITIAL_TRACING_DURATION
 import de.rki.coronawarnapp.transaction.RiskLevelTransaction.RiskLevelTransactionState.CHECK_UNKNOWN_RISK_OUTDATED
 import de.rki.coronawarnapp.transaction.RiskLevelTransaction.RiskLevelTransactionState.CLOSE
+import de.rki.coronawarnapp.transaction.RiskLevelTransaction.RiskLevelTransactionState.RETRIEVE_APPLICATION_CONFIG
 import de.rki.coronawarnapp.transaction.RiskLevelTransaction.RiskLevelTransactionState.RETRIEVE_EXPOSURE_SUMMARY
-import de.rki.coronawarnapp.transaction.RiskLevelTransaction.RiskLevelTransactionState.RETRIEVE_RISK_THRESHOLD
 import de.rki.coronawarnapp.transaction.RiskLevelTransaction.RiskLevelTransactionState.UPDATE_RISK_LEVEL
 import de.rki.coronawarnapp.util.TimeAndDateExtensions.millisecondsToDays
 import de.rki.coronawarnapp.util.TimeAndDateExtensions.millisecondsToHours
@@ -101,7 +104,7 @@ import java.util.concurrent.atomic.AtomicReference
  * 1. [CHECK_TRACING]
  * 2. [CHECK_UNKNOWN_RISK_INITIAL_NO_KEYS]
  * 3. [CHECK_UNKNOWN_RISK_OUTDATED]
- * 4. [RETRIEVE_RISK_THRESHOLD]
+ * 4. [RETRIEVE_APPLICATION_CONFIG]
  * 5. [RETRIEVE_EXPOSURE_SUMMARY]
  * 6. [CHECK_INCREASED_RISK]
  * 7. [CHECK_UNKNOWN_RISK_INITIAL_TRACING_DURATION]
@@ -133,8 +136,9 @@ object RiskLevelTransaction : Transaction() {
         /** Check the conditions for the [UNKNOWN_RISK_OUTDATED_RESULTS] score */
         CHECK_UNKNOWN_RISK_OUTDATED,
 
-        /** Retrieve the RiskThreshold values to define the thresholds for [INCREASED_RISK] and [LOW_LEVEL_RISK] */
-        RETRIEVE_RISK_THRESHOLD,
+        /** Retrieve the Application Configuration values to calculate the Risk Score
+         * and determine the [INCREASED_RISK] and [LOW_LEVEL_RISK] */
+        RETRIEVE_APPLICATION_CONFIG,
 
         /** Retrieve the last persisted [ExposureSummary] (if available) from the Google Exposure Notification API for
          * further calculation of the Risk Level Score */
@@ -153,6 +157,17 @@ object RiskLevelTransaction : Transaction() {
         CLOSE
     }
 
+    /** TESTING ONLY
+     *
+     * TODO remove asap, only used to display the used values for risk level calculation
+     */
+
+    val tempExposedTransactionValuesForTestingOnly =
+        MutableLiveData<TestRiskLevelCalculation.TransactionValues>()
+
+    var recordedTransactionValuesForTestingOnly =
+        TestRiskLevelCalculation.TransactionValues()
+
     /** atomic reference for the rollback value for the last calculated risk level score */
     private val lastCalculatedRiskLevelScoreForRollback = AtomicReference<RiskLevel>()
 
@@ -178,9 +193,9 @@ object RiskLevelTransaction : Transaction() {
         if (isValidResult(result)) return@lockAndExecute
 
         /****************************************************
-         * RETRIEVE RISK THRESHOLD
+         * RETRIEVE APPLICATION CONFIGURATION
          ****************************************************/
-        val riskScoreClassification = executeRetrieveRiskThreshold()
+        val appConfiguration = executeRetrieveApplicationConfiguration()
 
         /****************************************************
          * RETRIEVE EXPOSURE SUMMARY
@@ -190,7 +205,7 @@ object RiskLevelTransaction : Transaction() {
         /****************************************************
          * CHECK [INCREASED_RISK] CONDITIONS
          ****************************************************/
-        result = executeCheckIncreasedRisk(riskScoreClassification, lastExposureSummary)
+        result = executeCheckIncreasedRisk(appConfiguration, lastExposureSummary)
         if (isValidResult(result)) return@lockAndExecute
 
         /****************************************************
@@ -204,7 +219,7 @@ object RiskLevelTransaction : Transaction() {
          * SET [LOW_LEVEL_RISK] LEVEL IF NONE ABOVE APPLIED
          ****************************************************/
         if (result == UNDETERMINED) {
-            lastCalculatedRiskLevelScoreForRollback.set(getLastCalculatedRiskLevelScore())
+            lastCalculatedRiskLevelScoreForRollback.set(RiskLevelRepository.getLastCalculatedScore())
             executeUpdateRiskLevelScore(LOW_LEVEL_RISK)
             executeClose()
             return@lockAndExecute
@@ -282,14 +297,19 @@ object RiskLevelTransaction : Transaction() {
         }
 
     /**
-     * Executes the [RETRIEVE_RISK_THRESHOLD] Transaction State
+     * Executes the [RETRIEVE_APPLICATION_CONFIG] Transaction State
+     *
+     * @return the values of the application configuration
      */
-    private suspend fun executeRetrieveRiskThreshold(): RiskScoreClassification =
-        executeState(RETRIEVE_RISK_THRESHOLD) {
-            // these are the threshold values defined by RKI
-            return@executeState getRiskThreshold().also {
-                Log.v(TAG, "$transactionId - retrieved risk threshold")
-            }
+    private suspend fun executeRetrieveApplicationConfiguration():
+            ApplicationConfigurationOuterClass.ApplicationConfiguration =
+        executeState(RETRIEVE_APPLICATION_CONFIG) {
+            return@executeState getApplicationConfiguration()
+                .also {
+                    // todo remove after testing sessions
+                    recordedTransactionValuesForTestingOnly.appConfig = it
+                    Log.v(TAG, "$transactionId - retrieved configuration from backend")
+                }
         }
 
     /**
@@ -299,6 +319,8 @@ object RiskLevelTransaction : Transaction() {
         val lastExposureSummary = getLastExposureSummary() ?: getNewExposureSummary()
 
         return@executeState lastExposureSummary.also {
+            // todo remove after testing sessions
+            recordedTransactionValuesForTestingOnly.exposureSummary = it
             Log.v(TAG, "$transactionId - get the exposure summary for further calculation")
         }
     }
@@ -307,23 +329,47 @@ object RiskLevelTransaction : Transaction() {
      * Executes the [CHECK_INCREASED_RISK] Transaction State
      */
     private suspend fun executeCheckIncreasedRisk(
-        riskScoreClassification: RiskScoreClassification,
+        appConfig: ApplicationConfigurationOuterClass.ApplicationConfiguration,
         exposureSummary: ExposureSummary
     ): RiskLevel =
         executeState(CHECK_INCREASED_RISK) {
 
-            val highRiskScoreClass = riskScoreClassification.riskClassesList.find { it.label == "HIGH" }
-                ?: throw RiskLevelCalculationException(IllegalStateException("no high risk score class found"))
+            // custom attenuation parameters to weight the attenuation
+            // values provided by the Google API
+            val attenuationParameters = appConfig.attenuationDuration
+
+            // calculate the risk score based on the values collected by the Google EN API and
+            // the backend configuration
+            val riskScore = RiskLevelCalculation.calculateRiskScore(
+                attenuationParameters,
+                exposureSummary
+            ).also {
+                // todo remove after testing sessions
+                recordedTransactionValuesForTestingOnly.riskScore = it
+                Log.v(TAG, "calculated risk with the given config: $it")
+            }
 
-            // if the risk score is above the defined level threshold we always return the high level risk score
-            if (exposureSummary.maximumRiskScore >= highRiskScoreClass.min) return@executeState INCREASED_RISK
-                .also {
-                    Log.v(
-                        TAG,
-                        "${exposureSummary.maximumRiskScore} is above the defined " +
-                                "min value ${highRiskScoreClass.min}"
-                    )
-                }
+            // these are the defined risk classes. They will divide the calculated
+            // risk score into the low and increased risk
+            val riskScoreClassification = appConfig.riskScoreClasses
+
+            // get the high risk score class
+            val highRiskScoreClass =
+                riskScoreClassification.riskClassesList.find { it.label == "HIGH" }
+                    ?: throw RiskLevelCalculationException(IllegalStateException("no high risk score class found"))
+
+            // if the calculated risk score is above the defined level threshold we return the high level risk score
+            if (riskScore >= highRiskScoreClass.min && riskScore <= highRiskScoreClass.max) {
+                Log.v(
+                    TAG, "$riskScore is above the defined " +
+                            "min value ${highRiskScoreClass.min}"
+                )
+                return@executeState INCREASED_RISK
+            } else if (riskScore > highRiskScoreClass.max) {
+                throw RiskLevelCalculationException(
+                    IllegalStateException("risk score is above the max threshold for score class")
+                )
+            }
 
             Log.v(TAG, "$transactionId - INCREASED_RISK not applicable")
             return@executeState UNDETERMINED
@@ -352,6 +398,13 @@ object RiskLevelTransaction : Transaction() {
         executeState(UPDATE_RISK_LEVEL) {
             Log.v(TAG, "$transactionId - update the risk level with $riskLevel")
             updateRiskLevelScore(riskLevel)
+                .also {
+                    // todo remove after testing sessions
+                    recordedTransactionValuesForTestingOnly.riskLevel = riskLevel
+                    tempExposedTransactionValuesForTestingOnly.postValue(
+                        recordedTransactionValuesForTestingOnly
+                    )
+                }
         }
 
     /**
@@ -381,7 +434,7 @@ object RiskLevelTransaction : Transaction() {
                 "$transactionId - $riskLevel was determined by the transaction. " +
                         "UPDATE and CLOSE will be called"
             )
-            lastCalculatedRiskLevelScoreForRollback.set(getLastCalculatedRiskLevelScore())
+            lastCalculatedRiskLevelScoreForRollback.set(RiskLevelRepository.getLastCalculatedScore())
             executeUpdateRiskLevelScore(riskLevel)
             executeClose()
             return true
@@ -404,14 +457,15 @@ object RiskLevelTransaction : Transaction() {
     }
 
     /**
-     * Make a call to the backend to retrieve the current risk threshold values from the RKI
+     * Make a call to the backend to retrieve the current application configuration values
      *
-     * @return the [RiskScoreClassification] from the backend
+     * @return the [ApplicationConfigurationOuterClass.ApplicationConfiguration] from the backend
      */
-    private suspend fun getRiskThreshold(): RiskScoreClassification = withContext(Dispatchers.Default) {
-        return@withContext RiskScoreClassificationService.asyncRetrieveRiskScoreClassification()
-            .also { Log.v(TAG, "risk score classes from backend: $it") }
-    }
+    private suspend fun getApplicationConfiguration(): ApplicationConfigurationOuterClass.ApplicationConfiguration =
+        withContext(Dispatchers.Default) {
+            return@withContext ApplicationConfigurationService.asyncRetrieveApplicationConfiguration()
+                .also { Log.v(TAG, "configuration from backend: $it") }
+        }
 
     /**
      * Returns a Boolean if the duration of the activated tracing time is above the
@@ -433,15 +487,6 @@ object RiskLevelTransaction : Transaction() {
         }
     }
 
-    /**
-     * Retrieves the last calculated Risk Level Score from the persisted storage
-     *
-     * @return
-     */
-    private fun getLastCalculatedRiskLevelScore(): RiskLevel {
-        return RiskLevelRepository.getLastCalculatedScore()
-    }
-
     /**
      * Updates the Risk Level Score in the repository with the calculated Risk Level
      *
@@ -468,7 +513,8 @@ object RiskLevelTransaction : Transaction() {
         val googleToken = LocalData.googleApiToken()
             ?: throw RiskLevelCalculationException(IllegalStateException("exposure summary is not persisted"))
 
-        val exposureSummary = InternalExposureNotificationClient.asyncGetExposureSummary(googleToken)
+        val exposureSummary =
+            InternalExposureNotificationClient.asyncGetExposureSummary(googleToken)
 
         ExposureSummaryRepository.getExposureSummaryRepository()
             .insertExposureSummaryEntity(exposureSummary)
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/SubmitDiagnosisKeysTransaction.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/SubmitDiagnosisKeysTransaction.kt
index f998b199a8d28d28264b16c9a69a049204512717..d7cc02559b5e019a75464d5fb7a2f6f791cbdbad 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/SubmitDiagnosisKeysTransaction.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/SubmitDiagnosisKeysTransaction.kt
@@ -52,7 +52,7 @@ object SubmitDiagnosisKeysTransaction : Transaction() {
          * RETRIEVE TAN
          ****************************************************/
         val authCode = executeState(RETRIEVE_TAN) {
-            SubmissionService.asyncRequestAuthCode()
+            SubmissionService.asyncRequestAuthCode(registrationToken)
         }
         /****************************************************
          * RETRIEVE TEMPORARY EXPOSURE KEY HISTORY
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/Transaction.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/Transaction.kt
index eccaf7ce3cdad600824de76c5348dd79de5f7dd0..f77781f0ad565f6df4e44e3d56e5ec59eda54f54 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/Transaction.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/transaction/Transaction.kt
@@ -21,10 +21,8 @@ package de.rki.coronawarnapp.transaction
 
 import android.util.Log
 import de.rki.coronawarnapp.BuildConfig
-import de.rki.coronawarnapp.exception.ExceptionCategory.INTERNAL
 import de.rki.coronawarnapp.exception.RollbackException
 import de.rki.coronawarnapp.exception.TransactionException
-import de.rki.coronawarnapp.exception.report
 import de.rki.coronawarnapp.risk.TimeVariables
 import de.rki.coronawarnapp.transaction.Transaction.InternalTransactionStates.INIT
 import kotlinx.coroutines.CoroutineScope
@@ -258,7 +256,6 @@ abstract class Transaction {
     protected open suspend fun handleTransactionError(error: Throwable?): Nothing {
         rollback()
         resetExecutedStateStack()
-        error?.report(INTERNAL)
         throw TransactionException(
             transactionId.get(),
             currentTransactionState.toString(),
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/UiConstants.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/UiConstants.kt
deleted file mode 100644
index 4179af0c1439f9f834cc837f7a0da2c3f6fb1918..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/UiConstants.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package de.rki.coronawarnapp.ui
-
-object UiConstants {
-    const val INFORMATION_URI = "https://www.bundesregierung.de/c19app-intern"
-
-    // todo move to strings if translatable is needed? if yes include regex in CallHelper to filter non-numerical chars excluding '+'
-    const val TECHNICAL_HOTLINE = "tel:+49 800 7540001"
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationAboutFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationAboutFragment.kt
index 09308fcbcfc01b5ea5a480f14ffafae3e66bede4..7107692858b881eac96b7472e3e88770ad19ddf5 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationAboutFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationAboutFragment.kt
@@ -32,7 +32,7 @@ class InformationAboutFragment : BaseFragment() {
     }
 
     private fun setButtonOnClickListener() {
-        binding.informationAboutHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.informationAboutHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationContactFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationContactFragment.kt
index e05286d770da4d0625b4d7a2ff50343b5d917eb2..3da4c84a61b69ccb942f73d09313873fcb1b1ac0 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationContactFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationContactFragment.kt
@@ -4,9 +4,9 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentInformationContactBinding
 import de.rki.coronawarnapp.ui.BaseFragment
-import de.rki.coronawarnapp.ui.UiConstants
 import de.rki.coronawarnapp.ui.main.MainActivity
 import de.rki.coronawarnapp.util.CallHelper
 
@@ -34,11 +34,16 @@ class InformationContactFragment : BaseFragment() {
     }
 
     private fun setButtonOnClickListener() {
-        binding.informationContactHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.informationContactHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
         binding.informationContactNavigationRowPhone.navigationRow.setOnClickListener {
-            CallHelper.call(this, UiConstants.TECHNICAL_HOTLINE)
+            CallHelper.call(
+                this,
+                requireContext().getString(
+                    R.string.information_contact_phone_call_number
+                )
+            )
         }
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationFragment.kt
index 34a1994eb917e2aad242bb8baf21482e088ffdf2..76866d570f16e5c64ccdaa1d81dc081050d0ccc5 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationFragment.kt
@@ -4,9 +4,9 @@ import android.os.Bundle
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
+import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.databinding.FragmentInformationBinding
 import de.rki.coronawarnapp.ui.BaseFragment
-import de.rki.coronawarnapp.ui.UiConstants
 import de.rki.coronawarnapp.ui.main.MainActivity
 import de.rki.coronawarnapp.util.OpenUrlHelper
 
@@ -55,7 +55,7 @@ class InformationFragment : BaseFragment() {
             )
         }
         binding.informationHelp.mainRow.setOnClickListener {
-            OpenUrlHelper.navigate(this, UiConstants.INFORMATION_URI)
+            OpenUrlHelper.navigate(this, requireContext().getString(R.string.main_about_link))
         }
         binding.informationLegal.mainRow.setOnClickListener {
             doNavigate(
@@ -67,7 +67,7 @@ class InformationFragment : BaseFragment() {
                 InformationFragmentDirections.actionInformationFragmentToInformationTechnicalFragment()
             )
         }
-        binding.informationHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationLegalFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationLegalFragment.kt
index c8e749ae390d193e28162c0c2863ba0c565bc52f..2d32a639d14c751fd4d015c5e2f2d8defbb8d013 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationLegalFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationLegalFragment.kt
@@ -32,7 +32,7 @@ class InformationLegalFragment : BaseFragment() {
     }
 
     private fun setButtonOnClickListener() {
-        binding.informationLegalHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.informationLegalHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationPrivacyFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationPrivacyFragment.kt
index 79fc00d186efffca3d3d5ead54391a437f6be09e..7b3cc61e44cfe8aafdd007c016e955f2a076dd4c 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationPrivacyFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationPrivacyFragment.kt
@@ -32,7 +32,7 @@ class InformationPrivacyFragment : BaseFragment() {
     }
 
     private fun setButtonOnClickListener() {
-        binding.informationPrivacyHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.informationPrivacyHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationTechnicalFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationTechnicalFragment.kt
index a240ada4f569179dab302911b99ca87b6bb529b4..a4e295f7e5e30c3525b164f08240e0bc8294be30 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationTechnicalFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationTechnicalFragment.kt
@@ -32,7 +32,7 @@ class InformationTechnicalFragment : BaseFragment() {
     }
 
     private fun setButtonOnClickListener() {
-        binding.informationTechnicalHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.informationTechnicalHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationTermsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationTermsFragment.kt
index 8581c18eab960411be337ba0267b0a34c2dee321..486172f2a36d982f5f641b006c01708bad2c6d47 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationTermsFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/information/InformationTermsFragment.kt
@@ -32,7 +32,7 @@ class InformationTermsFragment : BaseFragment() {
     }
 
     private fun setButtonOnClickListener() {
-        binding.informationTermsHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.informationTermsHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt
index 595f3580cbdb8c59b3d598dfcfe03f97addca98b..f6643d11320790a2fef07f2ebe681503c3ee3f76 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt
@@ -1,12 +1,15 @@
 package de.rki.coronawarnapp.ui.main
 
 import android.content.Intent
+import android.content.IntentFilter
 import android.os.Bundle
 import androidx.appcompat.app.AppCompatActivity
 import androidx.fragment.app.Fragment
 import androidx.fragment.app.FragmentManager
 import androidx.lifecycle.ViewModelProviders
+import androidx.localbroadcastmanager.content.LocalBroadcastManager
 import de.rki.coronawarnapp.R
+import de.rki.coronawarnapp.exception.ErrorReportReceiver
 import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel
 import de.rki.coronawarnapp.util.ConnectivityHelper
 import de.rki.coronawarnapp.worker.BackgroundWorkScheduler
@@ -29,6 +32,8 @@ class MainActivity : AppCompatActivity() {
 
     private lateinit var settingsViewModel: SettingsViewModel
 
+    private val errorReceiver = ErrorReportReceiver(this)
+
     /**
      * Register connection callback.
      */
@@ -69,6 +74,7 @@ class MainActivity : AppCompatActivity() {
      */
     override fun onResume() {
         super.onResume()
+        LocalBroadcastManager.getInstance(this).registerReceiver(errorReceiver, IntentFilter("error-report"))
         ConnectivityHelper.registerNetworkStatusCallback(this, callbackNetwork)
         ConnectivityHelper.registerBluetoothStatusCallback(this, callbackBluetooth)
     }
@@ -80,6 +86,8 @@ class MainActivity : AppCompatActivity() {
         super.onPause()
         ConnectivityHelper.unregisterNetworkStatusCallback(this, callbackNetwork)
         ConnectivityHelper.unregisterBluetoothStatusCallback(this, callbackBluetooth)
+        // Unregister since the activity is about to be closed.
+        LocalBroadcastManager.getInstance(this).unregisterReceiver(errorReceiver)
     }
 
     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainFragment.kt
index 5d2606f2096b17339a0cf5bc30d7111a8516bd20..6f9355b522059c605e357ffebdde14038a5bc98c 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainFragment.kt
@@ -14,7 +14,6 @@ import de.rki.coronawarnapp.databinding.FragmentMainBinding
 import de.rki.coronawarnapp.notification.NotificationHelper
 import de.rki.coronawarnapp.timer.TimerHelper
 import de.rki.coronawarnapp.ui.BaseFragment
-import de.rki.coronawarnapp.ui.UiConstants
 import de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel
 import de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel
 import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel
@@ -69,9 +68,7 @@ class MainFragment : BaseFragment() {
         tracingViewModel.refreshActiveTracingDaysInRetentionPeriod()
         settingsViewModel.refreshBackgroundJobEnabled()
         TimerHelper.checkManualKeyRetrievalTimer()
-        if (submissionViewModel.deviceRegistered) {
-            submissionViewModel.refreshTestResult()
-        }
+        submissionViewModel.refreshDeviceUIState()
     }
 
     private fun setButtonOnClickListener() {
@@ -110,7 +107,7 @@ class MainFragment : BaseFragment() {
             doNavigate(MainFragmentDirections.actionMainFragmentToSettingsTracingFragment())
         }
         binding.mainAbout.mainCard.setOnClickListener {
-            OpenUrlHelper.navigate(this, UiConstants.INFORMATION_URI)
+            OpenUrlHelper.navigate(this, requireContext().getString(R.string.main_about_link))
         }
         binding.mainHeaderShare.buttonIcon.setOnClickListener {
             doNavigate(MainFragmentDirections.actionMainFragmentToMainSharingFragment())
@@ -143,6 +140,11 @@ class MainFragment : BaseFragment() {
                     true
                 }
                 // todo remove only for testing
+                R.id.menu_test_risk_level -> {
+                    doNavigate(MainFragmentDirections.actionMainFragmentToTestRiskLevelCalculation())
+                    true
+                }
+                // todo remove only for testing
                 R.id.menu_notification_test -> {
                     Log.i(TAG, "calling notification")
                     Log.i(
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainOverviewFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainOverviewFragment.kt
index 5a007838f7bbd276978b91205c01850896fd98e6..03d4f39297202d74b84262ed53cc4f537dc1ef41 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainOverviewFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainOverviewFragment.kt
@@ -37,7 +37,7 @@ class MainOverviewFragment : BaseFragment() {
     }
 
     private fun setButtonOnClickListener() {
-        binding.mainOverviewHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.mainOverviewHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainShareFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainShareFragment.kt
index 9bff3a7ade91187967d67c1d86f56429e787f95d..e6b42e0eab63e620e68c122cf92df54947561464 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainShareFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainShareFragment.kt
@@ -45,7 +45,7 @@ class MainShareFragment : BaseFragment() {
         binding.mainShareButton.setOnClickListener {
             ShareHelper.shareText(this, getString(R.string.main_share_message), null)
         }
-        binding.mainShareHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.mainShareHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
     }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt
index 0e36914cd7aa90beba5380111d72626b0aff45b9..ed39f3716067f5f353c59e90740a59f9d5b2fcf1 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt
@@ -59,7 +59,7 @@ class SettingsFragment : BaseFragment() {
         val tracingRow = binding.settingsTracing.settingsRow
         val notificationRow = binding.settingsNotifications.settingsRow
         val resetRow = binding.settingsReset
-        val goBack = binding.settingsHeader.informationHeader.headerButtonBack.buttonIcon
+        val goBack = binding.settingsHeader.headerButtonBack.buttonIcon
         resetRow.setOnClickListener {
             doNavigate(
                 SettingsFragmentDirections.actionSettingsFragmentToSettingsResetFragment()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsNotificationFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsNotificationFragment.kt
index 7e335ef7c0ced13900475cf5e086f0af536d3188..695362b30c0d7ad3bd044cfe18308642eb4eb673 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsNotificationFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsNotificationFragment.kt
@@ -62,7 +62,7 @@ class SettingsNotificationFragment : Fragment() {
         // Settings
         val settingsRow = binding.settingsNavigationRowSystem.navigationRow
         val goBack =
-            binding.settingsDetailsHeaderNotifications.informationHeader.headerButtonBack.buttonIcon
+            binding.settingsNotificationsHeader.headerButtonBack.buttonIcon
         // Update Risk
         updateRiskNotificationSwitch.setOnCheckedChangeListener { _, _ ->
             // android calls this listener also on start, so it has to be verified if the user pressed the switch
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetFragment.kt
index 33ec04776d2ecadd6b1fcd9f3c8749e5a9284092..0606f781908a2808c4e184f3c9fcc9cbb348f0de 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsResetFragment.kt
@@ -6,7 +6,6 @@ import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
 import android.widget.Toast
-import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.lifecycleScope
 import com.google.android.gms.common.api.ApiException
 import de.rki.coronawarnapp.databinding.FragmentSettingsResetBinding
@@ -16,7 +15,6 @@ import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient
 import de.rki.coronawarnapp.ui.BaseFragment
 import de.rki.coronawarnapp.ui.main.MainActivity
 import de.rki.coronawarnapp.ui.onboarding.OnboardingActivity
-import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel
 import de.rki.coronawarnapp.util.DataRetentionHelper
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
@@ -25,7 +23,6 @@ import kotlinx.coroutines.withContext
 /**
  * The user is informed what a reset means and he can perform it.
  *
- * @see TracingViewModel
  */
 class SettingsResetFragment : BaseFragment() {
 
@@ -33,7 +30,6 @@ class SettingsResetFragment : BaseFragment() {
         private val TAG: String? = SettingsResetFragment::class.simpleName
     }
 
-    private val tracingViewModel: TracingViewModel by activityViewModels()
     private lateinit var binding: FragmentSettingsResetBinding
 
     override fun onCreateView(
@@ -42,8 +38,6 @@ class SettingsResetFragment : BaseFragment() {
         savedInstanceState: Bundle?
     ): View? {
         binding = FragmentSettingsResetBinding.inflate(inflater)
-        binding.tracingViewModel = tracingViewModel
-        binding.lifecycleOwner = this
         return binding.root
     }
 
@@ -55,7 +49,7 @@ class SettingsResetFragment : BaseFragment() {
         binding.settingsResetButtonCancel.setOnClickListener {
             (activity as MainActivity).goBack()
         }
-        binding.settingsDetailsHeaderReset.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.settingsResetHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
     }
@@ -90,7 +84,7 @@ class SettingsResetFragment : BaseFragment() {
         activity?.finish()
     }
 
-    private suspend fun deleteLocalAppContent() {
+    private fun deleteLocalAppContent() {
         DataRetentionHelper.clearAllLocalData(requireContext())
     }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt
index 89c4cdd24c74a0dbc744c83fd2f2d81e82b6db6f..219dfa2cd4b05121813785ba867b375750e543dd 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt
@@ -102,7 +102,7 @@ class SettingsTracingFragment : BaseFragment(),
                 }
             }
         }
-        binding.settingsTracingHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding.settingsTracingHeader.headerButtonBack.buttonIcon.setOnClickListener {
             (activity as MainActivity).goBack()
         }
         binding.settingsTracingStatusBluetooth.tracingStatusCardButton.setOnClickListener {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionDoneFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionDoneFragment.kt
index a3841c8f6d52b53b94fdbbcd6093dccdba7fc5b0..af9ab63b466a2b6159ab8371da8cbda72416d9bd 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionDoneFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionDoneFragment.kt
@@ -30,7 +30,12 @@ class SubmissionDoneFragment : BaseFragment() {
     }
 
     private fun setButtonOnClickListener() {
-        binding.submissionDoneHeader.informationHeader.headerButtonBack.buttonIcon.setOnClickListener {
+        binding
+            .submissionDoneInclude
+            .submissionDoneHeader
+            .informationHeader
+            .headerButtonBack.buttonIcon
+            .setOnClickListener {
             doNavigate(
                 SubmissionDoneFragmentDirections.actionSubmissionDoneFragmentToMainFragment()
             )
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt
index b94a5e620ba06fb3a6c0ebff639f0ed6095fb92f..527afa5328515903c9e9a994b2371f4de3c474fc 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionResultPositiveOtherWarningFragment.kt
@@ -29,7 +29,7 @@ class SubmissionResultPositiveOtherWarningFragment : BaseFragment(),
     private var submissionRequested = false
     private var submissionFailed = false
     private lateinit var internalExposureNotificationPermissionHelper:
-        InternalExposureNotificationPermissionHelper
+            InternalExposureNotificationPermissionHelper
 
     override fun onResume() {
         super.onResume()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt
index 22b63d2d9bb3d827f9d70225c4d0677354dbb239..c18d49a015360e7b4747526b6a323afe69dd88cc 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTanViewModel.kt
@@ -10,21 +10,13 @@ class SubmissionTanViewModel : ViewModel() {
 
     companion object {
         private val TAG: String? = SubmissionTanViewModel::class.simpleName
-
-        private const val TAN_LENGTH = 7
-        private val EXCLUDED_TAN_CHARS = listOf('0', 'O', 'I', '1')
-        private val VALID_TAN_CHARS =
-            ('a'..'z')
-                .plus('A'..'Z')
-                .plus('0'..'9')
-                .minus(EXCLUDED_TAN_CHARS)
     }
 
     val tan = MutableLiveData<String?>(null)
 
     val isValidTanFormat =
         Transformations.map(tan) {
-            it != null && it.length == TAN_LENGTH && it.all { c -> VALID_TAN_CHARS.contains(c) }
+            it != null && it.length == TanConstants.MAX_LENGTH
         }
 
     fun storeTeletan() {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt
index 9b04678d913c86174d4ecee970c35d1ee13ac6c2..cdb2f61ca13010f1d02736c3354a170463b13e33 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/SubmissionTestResultFragment.kt
@@ -45,13 +45,13 @@ class SubmissionTestResultFragment : BaseFragment() {
 
     override fun onResume() {
         super.onResume()
-        submissionViewModel.refreshTestResult()
+        submissionViewModel.refreshDeviceUIState()
         tracingViewModel.refreshIsTracingEnabled()
     }
 
     private fun setButtonOnClickListener() {
         binding.submissionTestResultButtonPendingRefresh.setOnClickListener {
-            submissionViewModel.refreshTestResult()
+            submissionViewModel.refreshDeviceUIState()
         }
 
         binding.submissionTestResultButtonPendingRemoveTest.setOnClickListener {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/TanConstants.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/TanConstants.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b6be13be81def6ec21f396f0b89f278cdeb9fd6a
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/TanConstants.kt
@@ -0,0 +1,6 @@
+package de.rki.coronawarnapp.ui.submission
+
+object TanConstants {
+    const val MAX_LENGTH = 7
+    val ALPHA_NUMERIC_CHARS = ('a'..'z').plus('A'..'Z').plus('0'..'9')
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/TanInput.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/TanInput.kt
index d1a251846533df73987b224954ebc59757d4869c..70cc48b6833364f5303cc7d9d7549f2962e58e7f 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/TanInput.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/TanInput.kt
@@ -2,6 +2,7 @@ package de.rki.coronawarnapp.ui.submission
 
 import android.content.Context
 import android.os.Handler
+import android.text.InputFilter
 import android.util.AttributeSet
 import android.view.inputmethod.InputMethodManager
 import android.widget.FrameLayout
@@ -22,6 +23,15 @@ class TanInput(context: Context, attrs: AttributeSet) : FrameLayout(context, att
         private const val KEYBOARD_TRIGGER_DELAY = 100L
     }
 
+    private val whitespaceFilter =
+        InputFilter { source, _, _, _, _, _ -> source.filter { !it.isWhitespace() } }
+    private val alphaNumericFilter = InputFilter { source, _, _, _, _, _ ->
+        source.filter {
+            TanConstants.ALPHA_NUMERIC_CHARS.contains(it)
+        }
+    }
+    private val lengthFilter = InputFilter.LengthFilter(TanConstants.MAX_LENGTH)
+
     var listener: ((String?) -> Unit)? = null
 
     private var tan: String? = null
@@ -29,6 +39,8 @@ class TanInput(context: Context, attrs: AttributeSet) : FrameLayout(context, att
     init {
         inflate(context, R.layout.view_tan_input, this)
 
+        tan_input_edittext.filters = arrayOf(whitespaceFilter, alphaNumericFilter, lengthFilter)
+
         // register listener
         tan_input_edittext.doOnTextChanged { text, _, _, _ -> updateTan(text) }
         setOnClickListener { showKeyboard() }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/CircleProgress.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/CircleProgress.kt
index dc4e6a9af5e40050ef288c74d3bd56813e0f7a55..bef8b354ff1f19b73fa79e234202a224cec75d54 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/CircleProgress.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/view/CircleProgress.kt
@@ -89,7 +89,8 @@ class CircleProgress @JvmOverloads constructor(
         val progressColor = styleAttrs.getColor(R.styleable.CircleProgress_progressColor,
             ContextCompat.getColor(context, R.color.colorPrimary))
         // attribute textColor; default = colorGrey
-        val textColor = styleAttrs.getColor(R.styleable.CircleProgress_textColor,
+        val textColor = styleAttrs.getColor(
+            R.styleable.CircleProgress_textColor,
             ContextCompat.getColor(context, R.color.textColorGrey)
         )
         // attribute disableText; default = true
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt
index 7baf40e1213ca6aeebd0fac8cb89879d12ed3dbe..de2bb9f5066be22b2fe90cd43af268fde93c8df7 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SubmissionViewModel.kt
@@ -11,28 +11,27 @@ import de.rki.coronawarnapp.storage.LocalData
 import de.rki.coronawarnapp.storage.SubmissionRepository
 import de.rki.coronawarnapp.ui.submission.ApiRequestState
 import de.rki.coronawarnapp.ui.submission.ScanStatus
-import de.rki.coronawarnapp.util.formatter.TestResult
+import de.rki.coronawarnapp.util.DeviceUIState
 import kotlinx.coroutines.launch
 import java.util.Date
 
 class SubmissionViewModel : ViewModel() {
     private val _scanStatus = MutableLiveData(ScanStatus.STARTED)
     private val _registrationState = MutableLiveData(ApiRequestState.IDLE)
-    private val _testResultState = MutableLiveData(ApiRequestState.IDLE)
-    private val _authCodeState = MutableLiveData(ApiRequestState.IDLE)
+    private val _uiStateState = MutableLiveData(ApiRequestState.IDLE)
     private val _submissionState = MutableLiveData(ApiRequestState.IDLE)
 
     val scanStatus: LiveData<ScanStatus> = _scanStatus
     val registrationState: LiveData<ApiRequestState> = _registrationState
-    val testResultState: LiveData<ApiRequestState> = _testResultState
-    val authCodeState: LiveData<ApiRequestState> = _authCodeState
+    val uiStateState: LiveData<ApiRequestState> = _uiStateState
     val submissionState: LiveData<ApiRequestState> = _submissionState
 
     val deviceRegistered get() = LocalData.registrationToken() != null
 
-    val testResult: LiveData<TestResult> =
-        SubmissionRepository.testResult
-    val testResultReceivedDate: LiveData<Date> = SubmissionRepository.testResultReceivedDate
+    val testResultReceivedDate: LiveData<Date> =
+        SubmissionRepository.testResultReceivedDate
+    val deviceUiState: LiveData<DeviceUIState> =
+        SubmissionRepository.deviceUIState
 
     fun submitDiagnosisKeys() =
         executeRequestWithState(SubmissionService::asyncSubmitExposureKeys, _submissionState)
@@ -40,12 +39,12 @@ class SubmissionViewModel : ViewModel() {
     fun doDeviceRegistration() =
         executeRequestWithState(SubmissionService::asyncRegisterDevice, _registrationState)
 
-    fun refreshTestResult() =
-        executeRequestWithState(SubmissionRepository::refreshTestResult, _testResultState)
+    fun refreshDeviceUIState() =
+        executeRequestWithState(SubmissionRepository::refreshUIState, _uiStateState)
 
     fun validateAndStoreTestGUID(scanResult: String) {
-        val guid = SubmissionService.extractGUID(scanResult)
-        if (guid != null) {
+        if (SubmissionService.containsValidGUID(scanResult)) {
+            val guid = SubmissionService.extractGUID(scanResult)
             SubmissionService.storeTestGUID(guid)
             _scanStatus.value = ScanStatus.SUCCESS
         } else {
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CachedKeyFileHolder.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CachedKeyFileHolder.kt
index 31257882044c2323e8cf6169321b82d137226390..c7ef6e95de1a86d70ad32e66e2f2a16e043d8df4 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CachedKeyFileHolder.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/CachedKeyFileHolder.kt
@@ -35,7 +35,6 @@ import kotlinx.coroutines.async
 import kotlinx.coroutines.awaitAll
 import kotlinx.coroutines.withContext
 import java.io.File
-import java.util.ArrayList
 import java.util.Date
 import java.util.UUID
 
@@ -193,27 +192,11 @@ object CachedKeyFileHolder {
      * Get all dates from server based as formatted dates
      */
     private suspend fun getDatesFromServer() =
-        WebRequestBuilder.asyncGetArrayListFromGenericRequest(
-            DiagnosisKeyConstants.AVAILABLE_DATES_URL
-        ) {
-            val result = ArrayList<String>()
-            for (i in 0 until it.length()) {
-                result.add(it.get(i).toString())
-            }
-            result
-        }
+        WebRequestBuilder.asyncGetDateIndex()
 
     /**
      * Get all hours from server based as formatted dates
      */
     private suspend fun getHoursFromServer(day: Date) =
-        WebRequestBuilder.asyncGetArrayListFromGenericRequest(
-            "${DiagnosisKeyConstants.AVAILABLE_DATES_URL}/${day.toServerFormat()}/${DiagnosisKeyConstants.HOUR}"
-        ) {
-            val result = ArrayList<String>()
-            for (i in 0 until it.length()) {
-                result.add(it.get(i).toString())
-            }
-            result
-        }
+        WebRequestBuilder.asyncGetHourIndex(day)
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt
index 6d2bbcf58a8ea38fb7518bdae67aa50d78590433..6118ea66109abe08a796a35d718f7c2cddbfc722 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt
@@ -136,6 +136,19 @@ object ConnectivityHelper {
         return bAdapter.isEnabled
     }
 
+    /**
+     * Get network enabled status.
+     *
+     * @return current network status
+     *
+     */
+    fun isNetworkEnabled(context: Context): Boolean {
+        val manager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+        val activeNetwork: Network? = manager.activeNetwork
+        val caps: NetworkCapabilities? = manager.getNetworkCapabilities(activeNetwork)
+        return caps?.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) ?: false
+    }
+
     /**
      * Abstract bluetooth state change callback.
      *
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt
index 5e8ba7e359e80f2d7df9b540a4c74e429e8d3e73..5c07fbd3315290a9e792a23e696fe4533a595747 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DialogHelper.kt
@@ -7,14 +7,34 @@ object DialogHelper {
 
     data class DialogInstance(
         val activity: Activity,
-        val title: Int,
-        val message: Int,
-        val positiveButton: Int,
-        val negativeButton: Int? = null,
-        val cancelable: Boolean = true,
+        val title: String,
+        val message: String?,
+        val positiveButton: String,
+        val negativeButton: String? = null,
+        val cancelable: Boolean? = true,
         val positiveButtonFunction: () -> Unit? = {},
         val negativeButtonFunction: () -> Unit? = {}
-    )
+    ) {
+        constructor(
+            activity: Activity,
+            title: Int,
+            message: Int,
+            positiveButton: Int,
+            negativeButton: Int? = null,
+            cancelable: Boolean? = true,
+            positiveButtonFunction: () -> Unit? = {},
+            negativeButtonFunction: () -> Unit? = {}
+        ) : this(
+            activity,
+            activity.resources.getString(title),
+            activity.resources.getString(message),
+            activity.resources.getString(positiveButton),
+            negativeButton?.let { activity.resources.getString(it) },
+            cancelable,
+            positiveButtonFunction,
+            negativeButtonFunction
+        )
+    }
 
     fun showDialog(
         dialogInstance: DialogInstance
@@ -24,7 +44,7 @@ object DialogHelper {
             builder.apply {
                 setTitle(dialogInstance.title)
                 setMessage(dialogInstance.message)
-                setCancelable(dialogInstance.cancelable)
+                setCancelable(dialogInstance.cancelable ?: true)
                 setPositiveButton(
                     dialogInstance.positiveButton
                 ) { _, _ ->
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/PropertyLoader.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/PropertyLoader.kt
new file mode 100644
index 0000000000000000000000000000000000000000..c162ac72f2968063000b03d4b7fef9b3bf923bea
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/PropertyLoader.kt
@@ -0,0 +1,28 @@
+package de.rki.coronawarnapp.util
+
+import android.util.Log
+import de.rki.coronawarnapp.CoronaWarnApplication
+import java.util.Properties
+
+class PropertyLoader {
+    companion object {
+        private const val PIN_PROPERTIES_FILE_NAME = "pins.properties"
+        private const val PIN_FILE_DELIMITER = ","
+        private const val DISTRIBUTION_PIN_PROPERTY_NAME = "DISTRIBUTION_PINS"
+        private const val SUBMISSION_PINS_PROPERTY_NAME = "SUBMISSION_PINS"
+        private const val VERIFICATION_PINS_PROPERTY_NAME = "VERIFICATION_PINS"
+    }
+
+    fun getDistributionPins() = getCertificatePins(DISTRIBUTION_PIN_PROPERTY_NAME)
+    fun getSubmissionPins() = getCertificatePins(SUBMISSION_PINS_PROPERTY_NAME)
+    fun getVerificationPins() = getCertificatePins(VERIFICATION_PINS_PROPERTY_NAME)
+
+    private fun getCertificatePins(key: String): Array<String> = Properties().run {
+        this.load(CoronaWarnApplication.getAppContext().assets.open(PIN_PROPERTIES_FILE_NAME))
+        this.getProperty(key)
+            .split(PIN_FILE_DELIMITER)
+            .filter { it.isNotEmpty() }
+            .also { Log.v(key, it.toString()) }
+            .toTypedArray()
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ProtoFormatConverterExtensions.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ProtoFormatConverterExtensions.kt
index 80325f9529aafad920dbe8a72e6c830c3f77e7ff..c81679e5d43ecefd71a6aff3a2f8f2187bda1b26 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ProtoFormatConverterExtensions.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ProtoFormatConverterExtensions.kt
@@ -9,19 +9,46 @@ object ProtoFormatConverterExtensions {
 
     private const val ROLLING_PERIOD = 144
     private const val DEFAULT_TRANSMISSION_RISK_LEVEL = 1
+    private const val TRANSMISSION_RISK_DAY_0 = 5
+    private const val TRANSMISSION_RISK_DAY_1 = 6
+    private const val TRANSMISSION_RISK_DAY_2 = 7
+    private const val TRANSMISSION_RISK_DAY_3 = 8
+    private const val TRANSMISSION_RISK_DAY_4 = 7
+    private const val TRANSMISSION_RISK_DAY_5 = 5
+    private const val TRANSMISSION_RISK_DAY_6 = 3
+    private const val TRANSMISSION_RISK_DAY_7 = 2
+    private val DEFAULT_TRANSMISSION_RISK_VECTOR = intArrayOf(
+        TRANSMISSION_RISK_DAY_0,
+        TRANSMISSION_RISK_DAY_1,
+        TRANSMISSION_RISK_DAY_2,
+        TRANSMISSION_RISK_DAY_3,
+        TRANSMISSION_RISK_DAY_4,
+        TRANSMISSION_RISK_DAY_5,
+        TRANSMISSION_RISK_DAY_6,
+        TRANSMISSION_RISK_DAY_7
+    )
     private const val MAXIMUM_KEYS = 14
 
     fun List<TemporaryExposureKey>.limitKeyCount() =
-        this.sortedWith(compareBy({ it.rollingStartIntervalNumber })).asReversed().take(MAXIMUM_KEYS)
+        this.sortedWith(compareBy { it.rollingStartIntervalNumber }).asReversed().take(MAXIMUM_KEYS)
 
-    fun List<TemporaryExposureKey>.transformKeyHistoryToExternalFormat() = this.map {
-        KeyExportFormat.TemporaryExposureKey.newBuilder()
-            .setKeyData(ByteString.readFrom(it.keyData.inputStream()))
-            .setRollingStartIntervalNumber(it.rollingStartIntervalNumber)
-            .setRollingPeriod(ROLLING_PERIOD)
-            .setTransmissionRiskLevel(DEFAULT_TRANSMISSION_RISK_LEVEL)
-            .build()
-    }
+    fun List<TemporaryExposureKey>.transformKeyHistoryToExternalFormat() =
+        this.sortedWith(compareBy { it.rollingStartIntervalNumber })
+            .mapIndexed { index, it ->
+                // The earliest key we receive is from yesterday (i.e. 1 day ago),
+                // thus we need use index+1
+                val riskValue =
+                    if (index + 1 <= DEFAULT_TRANSMISSION_RISK_VECTOR.lastIndex)
+                        DEFAULT_TRANSMISSION_RISK_VECTOR[index + 1]
+                    else
+                        DEFAULT_TRANSMISSION_RISK_LEVEL
+                KeyExportFormat.TemporaryExposureKey.newBuilder()
+                    .setKeyData(ByteString.readFrom(it.keyData.inputStream()))
+                    .setRollingStartIntervalNumber(it.rollingStartIntervalNumber)
+                    .setRollingPeriod(ROLLING_PERIOD)
+                    .setTransmissionRiskLevel(riskValue)
+                    .build()
+            }
 
     fun AppleLegacyKeyExchange.Key.convertToGoogleKey(): KeyExportFormat.TemporaryExposureKey =
         KeyExportFormat.TemporaryExposureKey.newBuilder()
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/UiStateHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/UiStateHelper.kt
deleted file mode 100644
index 3a3a5e0c412d7fb6eb53b435a6ef03f23977f8a5..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/UiStateHelper.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package de.rki.coronawarnapp.util
-
-import de.rki.coronawarnapp.storage.LocalData
-import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_NO_RESULT
-import de.rki.coronawarnapp.util.DeviceUIState.PAIRED_POSITIVE
-import de.rki.coronawarnapp.util.DeviceUIState.SUBMITTED_FINAL
-import de.rki.coronawarnapp.util.DeviceUIState.UNPAIRED
-
-object UiStateHelper {
-    private fun uiState(): DeviceUIState {
-        var uiState = UNPAIRED
-        if (LocalData.registrationToken() != "") {
-            if (LocalData.inititalTestResultReceivedTimestamp() == null) {
-                uiState = PAIRED_NO_RESULT
-            } else if (LocalData.isAllowedToSubmitDiagnosisKeys() == true) {
-                uiState = PAIRED_POSITIVE
-            }
-        } else if (LocalData.numberOfSuccessfulSubmissions() == 1) {
-            uiState = SUBMITTED_FINAL
-        }
-
-        return uiState
-    }
-}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterRiskHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterRiskHelper.kt
index 9ecbe2a7b59d905118e353ab8b554cd3e415408a..29adcd8d9e2e4ed8db1cb1a0dfaff924928f30a4 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterRiskHelper.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterRiskHelper.kt
@@ -113,15 +113,19 @@ fun formatRiskSavedRisk(riskLevelScore: Int?, savedRiskLevelScore: Int?): String
  */
 fun formatRiskContact(riskLevelScore: Int?, matchedKeysCount: Int?): String {
     val appContext = CoronaWarnApplication.getAppContext()
-    val keysArg = matchedKeysCount?.toString()
+    val resources = appContext.resources
+    val contacts = matchedKeysCount ?: 0
     return when (riskLevelScore) {
         RiskLevelConstants.INCREASED_RISK,
         RiskLevelConstants.LOW_LEVEL_RISK -> {
-            if (matchedKeysCount != null && matchedKeysCount != 0) {
-                appContext.getString(R.string.risk_card_body_contact_value)
-                    .format(keysArg)
-            } else {
+            if (matchedKeysCount == 0) {
                 appContext.getString(R.string.risk_card_body_contact)
+            } else {
+                resources.getQuantityString(
+                    R.plurals.risk_card_body_contact_value,
+                    contacts,
+                    contacts
+                )
             }
         }
         else -> ""
@@ -139,16 +143,14 @@ fun formatRiskContact(riskLevelScore: Int?, matchedKeysCount: Int?): String {
  */
 fun formatRiskContactLast(riskLevelScore: Int?, daysSinceLastExposure: Int?): String {
     val appContext = CoronaWarnApplication.getAppContext()
-    val daysArg = daysSinceLastExposure.toString()
-
+    val resources = appContext.resources
+    val days = daysSinceLastExposure ?: 0
     return if (riskLevelScore == RiskLevelConstants.INCREASED_RISK) {
-        if (daysSinceLastExposure != null && daysArg != "") {
-            appContext.getString(R.string.risk_card_increased_risk_body_contact_last)
-                .format(daysArg)
-        } else {
-            appContext.getString(R.string.risk_card_increased_risk_body_contact_last)
-                .format("0")
-        }
+        resources.getQuantityString(
+            R.plurals.risk_card_increased_risk_body_contact_last,
+            days,
+            days
+        )
     } else {
         ""
     }
@@ -297,13 +299,15 @@ fun formatRiskDetailsRiskLevelSubtitle(riskLevelScore: Int?): String {
  */
 fun formatRiskDetailsRiskLevelBody(riskLevelScore: Int?, daysSinceLastExposure: Int?): String {
     val appContext = CoronaWarnApplication.getAppContext()
-    val daysArg = daysSinceLastExposure.toString()
-
+    val resources = appContext.resources
+    val days = daysSinceLastExposure ?: 0
     return when (riskLevelScore) {
-        RiskLevelConstants.INCREASED_RISK -> {
-            appContext.getString(R.string.risk_details_information_body_increased_risk)
-                .format(daysArg)
-        }
+        RiskLevelConstants.INCREASED_RISK ->
+            resources.getQuantityString(
+                R.plurals.risk_details_information_body_increased_risk,
+                days,
+                days
+            )
         RiskLevelConstants.UNKNOWN_RISK_OUTDATED_RESULTS ->
             appContext.getString(R.string.risk_details_information_body_outdated_risk)
         RiskLevelConstants.LOW_LEVEL_RISK ->
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSettingsHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSettingsHelper.kt
index 41def653e3cd64fac11be87f556e81b26fa69baf..aff12f2ac96e0024cf041cc3f1a2c79bed24ad60 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSettingsHelper.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSettingsHelper.kt
@@ -109,16 +109,12 @@ fun formatNotificationsDescription(notifications: Boolean): String = formatText(
  * @param activeTracingDaysInRetentionPeriod
  * @return String
  */
-fun formatTracingStatusBody(tracing: Boolean, activeTracingDaysInRetentionPeriod: Long): String {
+// TODO add generic plural formatter helper
+fun formatTracingStatusBody(activeTracingDaysInRetentionPeriod: Long): String {
     val appContext = CoronaWarnApplication.getAppContext()
-    val daysArg = activeTracingDaysInRetentionPeriod.toString()
-    return if (tracing) {
-        appContext.getString(R.string.settings_tracing_status_body_active)
-            .format(daysArg)
-    } else {
-        appContext.getString(R.string.settings_tracing_status_body_inactive)
-            .format(daysArg)
-    }
+    val resources = appContext.resources
+    val days = activeTracingDaysInRetentionPeriod.toInt()
+    return resources.getQuantityString(R.plurals.settings_tracing_status_body_active, days, days)
 }
 
 /*Styler*/
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt
index 5d19352eef02c8ce867623592b399638e453dbfc..590f0cee20da901247071653289a563f0361feeb 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterSubmissionHelper.kt
@@ -7,145 +7,160 @@ import android.view.View
 import de.rki.coronawarnapp.CoronaWarnApplication
 import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.ui.submission.ApiRequestState
-import de.rki.coronawarnapp.util.formatter.TestResult.INVALID
-import de.rki.coronawarnapp.util.formatter.TestResult.NEGATIVE
-import de.rki.coronawarnapp.util.formatter.TestResult.PENDING
-import de.rki.coronawarnapp.util.formatter.TestResult.POSITIVE
+import de.rki.coronawarnapp.util.DeviceUIState
 import java.util.Date
 
-fun formatTestResultSpinnerVisible(testResultStatus: ApiRequestState?): Int =
-    formatVisibility(testResultStatus != ApiRequestState.SUCCESS)
+fun formatTestResultSpinnerVisible(uiStateState: ApiRequestState?): Int =
+    formatVisibility(uiStateState != ApiRequestState.SUCCESS)
 
-fun formatTestResultVisible(testResultStatus: ApiRequestState?): Int =
-    formatVisibility(testResultStatus == ApiRequestState.SUCCESS)
+fun formatTestResultVisible(uiStateState: ApiRequestState?): Int =
+    formatVisibility(uiStateState == ApiRequestState.SUCCESS)
 
-fun formatTestResultVirusNameTextVisible(testResult: TestResult?): Int {
-    return when (testResult) {
-        POSITIVE, NEGATIVE -> View.VISIBLE
+fun formatTestResultVirusNameTextVisible(uiState: DeviceUIState?): Int {
+    return when (uiState) {
+        DeviceUIState.PAIRED_POSITIVE,
+        DeviceUIState.PAIRED_POSITIVE_TELETAN,
+        DeviceUIState.PAIRED_NEGATIVE -> View.VISIBLE
         else -> View.GONE
     }
 }
 
-fun formatTestResultStatusTextVisible(testResult: TestResult?): Int {
-    return when (testResult) {
-        POSITIVE, NEGATIVE -> View.VISIBLE
+fun formatTestResultStatusTextVisible(uiState: DeviceUIState?): Int {
+    return when (uiState) {
+        DeviceUIState.PAIRED_POSITIVE,
+        DeviceUIState.PAIRED_POSITIVE_TELETAN,
+        DeviceUIState.PAIRED_NEGATIVE -> View.VISIBLE
         else -> View.GONE
     }
 }
 
-fun formatTestResultStatusText(testResult: TestResult?): String {
+fun formatTestResultStatusText(uiState: DeviceUIState?): String {
     val appContext = CoronaWarnApplication.getAppContext()
-    return when (testResult) {
-        NEGATIVE -> appContext.getString(R.string.test_result_card_status_negative)
-        POSITIVE -> appContext.getString(R.string.test_result_card_status_positive)
+    return when (uiState) {
+        DeviceUIState.PAIRED_NEGATIVE -> appContext.getString(R.string.test_result_card_status_negative)
+        DeviceUIState.PAIRED_POSITIVE,
+        DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getString(R.string.test_result_card_status_positive)
         else -> appContext.getString(R.string.test_result_card_status_invalid)
     }
 }
 
-fun formatTestResultStatusColor(testResult: TestResult?): Int {
+fun formatTestResultStatusColor(uiState: DeviceUIState?): Int {
     val appContext = CoronaWarnApplication.getAppContext()
-    return when (testResult) {
-        NEGATIVE -> appContext.getColor(R.color.colorGreen)
-        POSITIVE -> appContext.getColor(R.color.colorRed)
+    return when (uiState) {
+        DeviceUIState.PAIRED_NEGATIVE -> appContext.getColor(R.color.colorGreen)
+        DeviceUIState.PAIRED_POSITIVE,
+        DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getColor(R.color.colorRed)
         else -> appContext.getColor(R.color.colorRed)
     }
 }
 
-fun formatTestStatusIcon(testResult: TestResult?): Drawable? {
+fun formatTestStatusIcon(uiState: DeviceUIState?): Drawable? {
     val appContext = CoronaWarnApplication.getAppContext()
     // TODO Replace with real drawables when design is finished
-    return when (testResult) {
-        PENDING -> appContext.getDrawable(R.drawable.ic_test_result_illustration_pending)
-        POSITIVE -> appContext.getDrawable(R.drawable.ic_test_result_illustration_positive)
-        NEGATIVE -> appContext.getDrawable(R.drawable.ic_main_illustration_negative)
-        INVALID -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid)
+    return when (uiState) {
+        DeviceUIState.PAIRED_NO_RESULT -> appContext.getDrawable(R.drawable.ic_test_result_illustration_pending)
+        DeviceUIState.PAIRED_POSITIVE_TELETAN,
+        DeviceUIState.PAIRED_POSITIVE -> appContext.getDrawable(R.drawable.ic_test_result_illustration_positive)
+        DeviceUIState.PAIRED_NEGATIVE -> appContext.getDrawable(R.drawable.ic_main_illustration_negative)
+        DeviceUIState.PAIRED_ERROR -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid)
         else -> appContext.getDrawable(R.drawable.ic_test_result_illustration_invalid)
     }
 }
 
-fun formatTestResultInvalidStatusTextVisible(testResult: TestResult?): Int =
-    formatVisibility(testResult == INVALID)
+fun formatTestResultInvalidStatusTextVisible(uiState: DeviceUIState?): Int =
+    formatVisibility(uiState == DeviceUIState.PAIRED_ERROR)
 
-fun formatTestResultPendingStatusTextVisible(testResult: TestResult?): Int =
-    formatVisibility(testResult == PENDING)
+fun formatTestResultPendingStatusTextVisible(uiState: DeviceUIState?): Int =
+    formatVisibility(uiState == DeviceUIState.PAIRED_NO_RESULT)
 
 fun formatTestResultRegisteredAtText(registeredAt: Date?): String {
     val appContext = CoronaWarnApplication.getAppContext()
     return appContext.getString(R.string.test_result_card_registered_at_text).format(registeredAt)
 }
 
-fun formatTestResultPendingStepsVisible(testResult: TestResult?): Int =
-    formatVisibility(testResult == PENDING)
+fun formatTestResultPendingStepsVisible(uiState: DeviceUIState?): Int =
+    formatVisibility(uiState == DeviceUIState.PAIRED_NO_RESULT)
 
-fun formatTestResultNegativeStepsVisible(testResult: TestResult?): Int =
-    formatVisibility(testResult == NEGATIVE)
+fun formatTestResultNegativeStepsVisible(uiState: DeviceUIState?): Int =
+    formatVisibility(uiState == DeviceUIState.PAIRED_NEGATIVE)
 
-fun formatTestResultPositiveStepsVisible(testResult: TestResult?): Int =
-    formatVisibility(testResult == POSITIVE)
+fun formatTestResultPositiveStepsVisible(uiState: DeviceUIState?): Int =
+    formatVisibility(uiState == DeviceUIState.PAIRED_POSITIVE || uiState == DeviceUIState.PAIRED_POSITIVE_TELETAN)
 
-fun formatTestResultInvalidStepsVisible(testResult: TestResult?): Int =
-    formatVisibility(testResult == INVALID)
+fun formatTestResultInvalidStepsVisible(uiState: DeviceUIState?): Int =
+    formatVisibility(uiState == DeviceUIState.PAIRED_ERROR)
 
-fun formatSubmissionStatusCardContentTitleText(testResult: TestResult?): String {
+fun formatSubmissionStatusCardContentTitleText(uiState: DeviceUIState?): String {
     val appContext = CoronaWarnApplication.getAppContext()
-    return when (testResult) {
-        INVALID, NEGATIVE, POSITIVE -> appContext.getString(R.string.submission_status_card_title_available)
-        PENDING -> appContext.getString(R.string.submission_status_card_title_pending)
+    return when (uiState) {
+        DeviceUIState.PAIRED_ERROR,
+        DeviceUIState.PAIRED_NEGATIVE,
+        DeviceUIState.PAIRED_POSITIVE_TELETAN,
+        DeviceUIState.PAIRED_POSITIVE -> appContext.getString(R.string.submission_status_card_title_available)
+        DeviceUIState.PAIRED_NO_RESULT -> appContext.getString(R.string.submission_status_card_title_pending)
         else -> appContext.getString(R.string.submission_status_card_title_pending)
     }
 }
 
-fun formatSubmissionStatusCardContentBodyText(testResult: TestResult?): String {
+fun formatSubmissionStatusCardContentBodyText(uiState: DeviceUIState?): String {
     val appContext = CoronaWarnApplication.getAppContext()
-    return when (testResult) {
-        INVALID -> appContext.getString(R.string.submission_status_card_body_invalid)
-        NEGATIVE -> appContext.getString(R.string.submission_status_card_body_negative)
-        POSITIVE -> appContext.getString(R.string.submission_status_card_body_positive)
-        PENDING -> appContext.getString(R.string.submission_status_card_body_pending)
+    return when (uiState) {
+        DeviceUIState.PAIRED_ERROR -> appContext.getString(R.string.submission_status_card_body_invalid)
+        DeviceUIState.PAIRED_NEGATIVE -> appContext.getString(R.string.submission_status_card_body_negative)
+        DeviceUIState.PAIRED_POSITIVE,
+        DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getString(R.string.submission_status_card_body_positive)
+        DeviceUIState.PAIRED_NO_RESULT -> appContext.getString(R.string.submission_status_card_body_pending)
         else -> appContext.getString(R.string.submission_status_card_body_pending)
     }
 }
 
-fun formatSubmissionStatusCardContentButtonText(testResult: TestResult?): String {
+fun formatSubmissionStatusCardContentButtonText(uiState: DeviceUIState?): String {
     val appContext = CoronaWarnApplication.getAppContext()
-    return when (testResult) {
-        INVALID, NEGATIVE, POSITIVE -> appContext.getString(R.string.submission_status_card_button_show_results)
+    return when (uiState) {
+        DeviceUIState.PAIRED_ERROR,
+        DeviceUIState.PAIRED_NEGATIVE,
+        DeviceUIState.PAIRED_POSITIVE_TELETAN,
+        DeviceUIState.PAIRED_POSITIVE -> appContext.getString(R.string.submission_status_card_button_show_results)
         else -> appContext.getString(R.string.submission_status_card_button_show_details)
     }
 }
 
-fun formatSubmissionStatusCardContentStatusTextVisible(testResult: TestResult?): Int {
-    return when (testResult) {
-        POSITIVE, NEGATIVE, INVALID -> View.VISIBLE
+fun formatSubmissionStatusCardContentStatusTextVisible(uiState: DeviceUIState?): Int {
+    return when (uiState) {
+        DeviceUIState.PAIRED_POSITIVE,
+        DeviceUIState.PAIRED_POSITIVE_TELETAN,
+        DeviceUIState.PAIRED_NEGATIVE,
+        DeviceUIState.PAIRED_ERROR -> View.VISIBLE
         else -> View.GONE
     }
 }
 
-fun formatSubmissionStatusCardContentIcon(testResult: TestResult?): Drawable? {
+fun formatSubmissionStatusCardContentIcon(uiState: DeviceUIState?): Drawable? {
     val appContext = CoronaWarnApplication.getAppContext()
     // TODO Replace with real drawables when design is finished
-    return when (testResult) {
-        PENDING -> appContext.getDrawable(R.drawable.ic_main_illustration_pending)
-        POSITIVE -> appContext.getDrawable(R.drawable.ic_main_illustration_pending)
-        NEGATIVE -> appContext.getDrawable(R.drawable.ic_main_illustration_negative)
-        INVALID -> appContext.getDrawable(R.drawable.ic_main_illustration_invalid)
+    return when (uiState) {
+        DeviceUIState.PAIRED_NO_RESULT -> appContext.getDrawable(R.drawable.ic_main_illustration_pending)
+        DeviceUIState.PAIRED_POSITIVE,
+        DeviceUIState.PAIRED_POSITIVE_TELETAN -> appContext.getDrawable(R.drawable.ic_main_illustration_pending)
+        DeviceUIState.PAIRED_NEGATIVE -> appContext.getDrawable(R.drawable.ic_main_illustration_negative)
+        DeviceUIState.PAIRED_ERROR -> appContext.getDrawable(R.drawable.ic_main_illustration_invalid)
         else -> appContext.getDrawable(R.drawable.ic_main_illustration_invalid)
     }
 }
 
 fun formatSubmissionStatusCardFetchingVisible(
     deviceRegistered: Boolean?,
-    testResultState: ApiRequestState?
+    uiStateState: ApiRequestState?
 ): Int = formatVisibility(
     deviceRegistered == true && (
-            testResultState == ApiRequestState.STARTED ||
-                    testResultState == ApiRequestState.FAILED)
+            uiStateState == ApiRequestState.STARTED ||
+                    uiStateState == ApiRequestState.FAILED)
 )
 
 fun formatSubmissionStatusCardContentVisible(
     deviceRegistered: Boolean?,
-    testResultState: ApiRequestState?
-): Int = formatVisibility(deviceRegistered == true && testResultState == ApiRequestState.SUCCESS)
+    uiStateState: ApiRequestState?
+): Int = formatVisibility(deviceRegistered == true && uiStateState == ApiRequestState.SUCCESS)
 
 fun formatSubmissionTanButtonTint(isValidTanFormat: Boolean) = formatColor(
     isValidTanFormat,
@@ -159,11 +174,25 @@ fun formatSubmissionTanButtonTextColor(isValidTanFormat: Boolean) = formatColor(
     R.color.colorGreyDisabled
 )
 
-fun formatShowSubmissionStatusCard(testResult: TestResult?): Int =
-    formatVisibility(testResult != POSITIVE)
-
-fun formatShowSubmissionStatusPositiveCard(testResult: TestResult?): Int =
-    formatVisibility(testResult == POSITIVE)
-
-fun formatShowRiskStatusCard(testResult: TestResult?): Int =
-    formatVisibility(testResult != POSITIVE)
+fun formatShowSubmissionStatusCard(deviceUiState: DeviceUIState?): Int =
+    formatVisibility(
+        deviceUiState != DeviceUIState.PAIRED_POSITIVE &&
+                deviceUiState != DeviceUIState.PAIRED_POSITIVE_TELETAN &&
+                deviceUiState != DeviceUIState.SUBMITTED_FINAL
+    )
+
+fun formatShowSubmissionStatusPositiveCard(deviceUiState: DeviceUIState?): Int =
+    formatVisibility(
+        deviceUiState == DeviceUIState.PAIRED_POSITIVE ||
+                deviceUiState == DeviceUIState.PAIRED_POSITIVE_TELETAN
+    )
+
+fun formatShowSubmissionDoneCard(deviceUiState: DeviceUIState?): Int =
+    formatVisibility(deviceUiState == DeviceUIState.SUBMITTED_FINAL)
+
+fun formatShowRiskStatusCard(deviceUiState: DeviceUIState?): Int =
+    formatVisibility(
+        deviceUiState != DeviceUIState.PAIRED_POSITIVE &&
+                deviceUiState != DeviceUIState.PAIRED_POSITIVE_TELETAN &&
+                deviceUiState != DeviceUIState.SUBMITTED_FINAL
+    )
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt
index 9a8868b34f12a2596b683ca41886a7c5859f0801..799a18636a062aabee7551e7b00914c41cebd948 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt
@@ -23,11 +23,9 @@ import android.content.Context
 import android.content.SharedPreferences
 import androidx.security.crypto.EncryptedSharedPreferences
 import androidx.security.crypto.MasterKeys
-import com.android.volley.RequestQueue
-import com.android.volley.toolbox.Volley
 import de.rki.coronawarnapp.CoronaWarnApplication
-import de.rki.coronawarnapp.http.OkHttp3Stack
 import java.security.KeyStore
+import java.security.MessageDigest
 
 /**
  * Key Store and Password Access
@@ -38,7 +36,7 @@ object SecurityHelper {
     private val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
     private const val AndroidKeyStore = "AndroidKeyStore"
 
-    val keyStore: KeyStore by lazy {
+    private val keyStore: KeyStore by lazy {
         KeyStore.getInstance(AndroidKeyStore).also {
             it.load(null)
         }
@@ -68,7 +66,8 @@ object SecurityHelper {
         .toString()
         .toCharArray()
 
-    fun getPinnedWebStack(appContext: Context): RequestQueue {
-        return Volley.newRequestQueue(appContext, OkHttp3Stack(appContext))
-    }
+    fun hash256(input: String): String = MessageDigest
+        .getInstance("SHA-256")
+        .digest(input.toByteArray())
+        .fold("", { str, it -> str + "%02x".format(it) })
 }
diff --git a/Corona-Warn-App/src/main/res/drawable/ic_main_overview_circle.xml b/Corona-Warn-App/src/main/res/drawable/ic_main_overview_circle.xml
index 84d7b6297596dec33b85b84297c9d2d762abdadd..1aa46b8b1095229728d5265135b51957b75f8a37 100644
--- a/Corona-Warn-App/src/main/res/drawable/ic_main_overview_circle.xml
+++ b/Corona-Warn-App/src/main/res/drawable/ic_main_overview_circle.xml
@@ -3,10 +3,10 @@
     android:height="42dp"
     android:viewportWidth="40"
     android:viewportHeight="42">
-  <path
-      android:pathData="M20,21m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
-      android:strokeWidth="1"
-      android:fillColor="#5D6E80"
-      android:fillType="evenOdd"
-      android:strokeColor="#00000000"/>
+    <path
+        android:fillColor="#5D6E80"
+        android:fillType="evenOdd"
+        android:pathData="M20,21m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000" />
 </vector>
diff --git a/Corona-Warn-App/src/main/res/drawable/ic_settings_reset_circle.xml b/Corona-Warn-App/src/main/res/drawable/ic_settings_reset_circle.xml
index ded4098d2127aa78090e0c4b72c29a59da4af4fd..b9f5b384bcc063b20c4113eab431cc658c593699 100644
--- a/Corona-Warn-App/src/main/res/drawable/ic_settings_reset_circle.xml
+++ b/Corona-Warn-App/src/main/res/drawable/ic_settings_reset_circle.xml
@@ -3,26 +3,26 @@
     android:height="24dp"
     android:viewportWidth="24"
     android:viewportHeight="24">
-  <path
-      android:pathData="M3.6247,3.6245L8.5508,8.5516C7.6686,9.4342 7.1229,10.6533 7.1229,11.9998C7.1229,13.3114 7.6421,14.5391 8.5512,15.4483L8.5522,15.4493L3.6245,20.3755C1.5605,18.3107 0.2549,15.4886 0.161,12.3619L0.1555,11.9998C0.1555,8.729 1.4813,5.7679 3.6247,3.6245ZM20.3753,3.6245C22.5187,5.7679 23.8445,8.729 23.8445,11.9998C23.8445,15.2705 22.5187,18.2317 20.3753,20.3751L15.4481,15.4489C16.331,14.5663 16.8771,13.3468 16.8771,11.9998C16.8771,10.6533 16.3314,9.4342 15.4492,8.5516Z"
-      android:strokeAlpha="0.14092727"
-      android:strokeWidth="1"
-      android:fillColor="#95B9CB"
-      android:fillType="evenOdd"
-      android:strokeColor="#00000000"
-      android:fillAlpha="0.14092727"/>
-  <path
-      android:pathData="M5.5954,5.5952L8.5508,8.5517C7.6686,9.4343 7.1229,10.6533 7.1229,11.9999C7.1229,13.3115 7.6421,14.5392 8.5512,15.4484C8.5515,15.4487 8.5519,15.449 8.5522,15.4493L5.5955,18.4042C4.0274,16.8364 3.0318,14.6966 2.9482,12.3247L2.9425,11.9999C2.9425,9.4987 3.9563,7.2343 5.5954,5.5952ZM18.4046,5.5952C20.0437,7.2343 21.0575,9.4987 21.0575,11.9999C21.0575,14.501 20.0437,16.7654 18.4046,18.4045L15.4481,15.449C16.331,14.5664 16.8771,13.3469 16.8771,11.9999C16.8771,10.6533 16.3314,9.4343 15.4492,8.5517Z"
-      android:strokeAlpha="0.36"
-      android:strokeWidth="1"
-      android:fillColor="#95B9CB"
-      android:fillType="evenOdd"
-      android:strokeColor="#00000000"
-      android:fillAlpha="0.36"/>
-  <path
-      android:pathData="M12,5.7293C8.5368,5.7293 5.7294,8.5367 5.7294,11.9999C5.7294,13.6849 6.398,15.2657 7.5658,16.4336C8.7338,17.6017 10.3148,18.2704 12,18.2704C15.4632,18.2704 18.2706,15.463 18.2706,11.9999C18.2706,8.5367 15.4632,5.7293 12,5.7293ZM12,7.1227C14.6936,7.1227 16.8771,9.3063 16.8771,11.9999C16.8771,14.6934 14.6936,16.877 12,16.877C10.6882,16.877 9.4604,16.3576 8.5512,15.4484C7.6421,14.5392 7.1229,13.3115 7.1229,11.9999C7.1229,9.3063 9.3064,7.1227 12,7.1227Z"
-      android:strokeWidth="1"
-      android:fillColor="#007FAD"
-      android:fillType="nonZero"
-      android:strokeColor="#00000000"/>
+    <path
+        android:fillAlpha="0.14092727"
+        android:fillColor="#95B9CB"
+        android:fillType="evenOdd"
+        android:pathData="M3.6247,3.6245L8.5508,8.5516C7.6686,9.4342 7.1229,10.6533 7.1229,11.9998C7.1229,13.3114 7.6421,14.5391 8.5512,15.4483L8.5522,15.4493L3.6245,20.3755C1.5605,18.3107 0.2549,15.4886 0.161,12.3619L0.1555,11.9998C0.1555,8.729 1.4813,5.7679 3.6247,3.6245ZM20.3753,3.6245C22.5187,5.7679 23.8445,8.729 23.8445,11.9998C23.8445,15.2705 22.5187,18.2317 20.3753,20.3751L15.4481,15.4489C16.331,14.5663 16.8771,13.3468 16.8771,11.9998C16.8771,10.6533 16.3314,9.4342 15.4492,8.5516Z"
+        android:strokeWidth="1"
+        android:strokeAlpha="0.14092727"
+        android:strokeColor="#00000000" />
+    <path
+        android:fillAlpha="0.36"
+        android:fillColor="#95B9CB"
+        android:fillType="evenOdd"
+        android:pathData="M5.5954,5.5952L8.5508,8.5517C7.6686,9.4343 7.1229,10.6533 7.1229,11.9999C7.1229,13.3115 7.6421,14.5392 8.5512,15.4484C8.5515,15.4487 8.5519,15.449 8.5522,15.4493L5.5955,18.4042C4.0274,16.8364 3.0318,14.6966 2.9482,12.3247L2.9425,11.9999C2.9425,9.4987 3.9563,7.2343 5.5954,5.5952ZM18.4046,5.5952C20.0437,7.2343 21.0575,9.4987 21.0575,11.9999C21.0575,14.501 20.0437,16.7654 18.4046,18.4045L15.4481,15.449C16.331,14.5664 16.8771,13.3469 16.8771,11.9999C16.8771,10.6533 16.3314,9.4343 15.4492,8.5517Z"
+        android:strokeWidth="1"
+        android:strokeAlpha="0.36"
+        android:strokeColor="#00000000" />
+    <path
+        android:fillColor="#007FAD"
+        android:fillType="nonZero"
+        android:pathData="M12,5.7293C8.5368,5.7293 5.7294,8.5367 5.7294,11.9999C5.7294,13.6849 6.398,15.2657 7.5658,16.4336C8.7338,17.6017 10.3148,18.2704 12,18.2704C15.4632,18.2704 18.2706,15.463 18.2706,11.9999C18.2706,8.5367 15.4632,5.7293 12,5.7293ZM12,7.1227C14.6936,7.1227 16.8771,9.3063 16.8771,11.9999C16.8771,14.6934 14.6936,16.877 12,16.877C10.6882,16.877 9.4604,16.3576 8.5512,15.4484C7.6421,14.5392 7.1229,13.3115 7.1229,11.9999C7.1229,9.3063 9.3064,7.1227 12,7.1227Z"
+        android:strokeWidth="1"
+        android:strokeColor="#00000000" />
 </vector>
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_information.xml b/Corona-Warn-App/src/main/res/layout/fragment_information.xml
index 42f5e3ab808b2b549bc4688bcecbad1c408dea6e..5c8d871ef9284aae09b3ec5d5b39c57426848484 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_information.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_information.xml
@@ -8,130 +8,129 @@
 
     </data>
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true">
-
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <!-- todo details header layout can be merged with settings if designs stay as they are -->
-            <include
-                android:id="@+id/information_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:icon="@{@drawable/ic_close}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/information_title}" />
-
-            <include
-                android:id="@+id/information_about"
-                layout="@layout/include_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/information_header"
-                app:title="@{@string/information_about_title}" />
-
-            <include
-                android:id="@+id/information_privacy"
-                layout="@layout/include_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/information_about"
-                app:title="@{@string/information_privacy_title}" />
-
-            <include
-                android:id="@+id/information_terms"
-                layout="@layout/include_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/information_privacy"
-                app:title="@{@string/information_terms_title}" />
-
-            <include
-                android:id="@+id/information_contact"
-                layout="@layout/include_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/information_terms"
-                app:title="@{@string/information_contact_title}" />
-
-            <include
-                android:id="@+id/information_help"
-                layout="@layout/include_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/information_contact"
-                app:title="@{@string/information_help_title}" />
-
-            <include
-                android:id="@+id/information_technical"
-                layout="@layout/include_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/information_help"
-                app:title="@{@string/information_technical_title}" />
-
-            <include
-                android:id="@+id/information_legal"
-                layout="@layout/include_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/information_technical"
-                app:title="@{@string/information_legal_title}" />
-
-            <TextView
-                android:id="@+id/information_version"
-                style="@style/textMultiline"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_small"
-                android:text="@{FormatterInformationHelper.formatVersion()}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/information_legal" />
-
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
-
-            <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>
-
-    </ScrollView>
+        android:layout_height="match_parent">
+
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/information_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_close}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/information_title}" />
+
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/information_header">
+
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <include
+                    android:id="@+id/information_about"
+                    layout="@layout/include_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent"
+                    app:title="@{@string/information_about_title}" />
+
+                <include
+                    android:id="@+id/information_help"
+                    layout="@layout/include_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/information_about"
+                    app:title="@{@string/information_help_title}" />
+
+                <include
+                    android:id="@+id/information_terms"
+                    layout="@layout/include_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/information_help"
+                    app:title="@{@string/information_terms_title}" />
+
+                <include
+                    android:id="@+id/information_privacy"
+                    layout="@layout/include_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/information_terms"
+                    app:title="@{@string/information_privacy_title}" />
+
+                <include
+                    android:id="@+id/information_technical"
+                    layout="@layout/include_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/information_privacy"
+                    app:title="@{@string/information_technical_title}" />
+
+                <include
+                    android:id="@+id/information_contact"
+                    layout="@layout/include_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/information_technical"
+                    app:title="@{@string/information_contact_title}" />
+
+                <include
+                    android:id="@+id/information_legal"
+                    layout="@layout/include_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/information_contact"
+                    app:title="@{@string/information_legal_title}" />
+
+                <TextView
+                    android:id="@+id/information_version"
+                    style="@style/textMultiline"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_small"
+                    android:text="@{FormatterInformationHelper.formatVersion()}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/information_legal" />
+
+            </androidx.constraintlayout.widget.ConstraintLayout>
+
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_information_about.xml b/Corona-Warn-App/src/main/res/layout/fragment_information_about.xml
index e222be48e288780a838123e5aa56309a8cf2085f..155009e579ba8af77a80271da23d2d3b94a72985 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_information_about.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_information_about.xml
@@ -2,70 +2,94 @@
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true">
+        android:layout_height="match_parent">
 
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-            <!-- todo separate icon from onboarding? -->
-            <include
-                android:id="@+id/information_about_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:headline="@{@string/information_about_headline}"
-                app:icon="@{@drawable/ic_back}"
-                app:illustration="@{@drawable/ic_information_illustration_about}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/information_about_title}" />
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/information_about_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_back}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/information_about_title}" />
 
-            <TextView
-                android:id="@+id/information_about_body_emphasized"
-                style="@style/textMultilineEmphasized"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_small"
-                android:text="@string/information_about_body_emphasized"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/information_about_header" />
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/information_about_header">
 
-            <TextView
-                android:id="@+id/information_about_body"
-                style="@style/textMultiline"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_small"
-                android:text="@string/information_about_body"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/information_about_body_emphasized" />
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
 
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
+                <include
+                    android:id="@+id/information_about_header_details"
+                    layout="@layout/include_information_details"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:headline="@{@string/information_about_headline}"
+                    app:illustration="@{@drawable/ic_information_illustration_about}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
 
-            <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" />
+                <TextView
+                    android:id="@+id/information_about_body_emphasized"
+                    style="@style/textMultiline"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_small"
+                    android:text="@string/information_about_body_emphasized"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/information_about_header_details" />
+
+                <TextView
+                    android:id="@+id/information_about_body"
+                    style="@style/textMultiline"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_small"
+                    android:text="@string/information_about_body"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/information_about_body_emphasized" />
+
+                <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>
+
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
-            <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>
-    </ScrollView>
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_information_contact.xml b/Corona-Warn-App/src/main/res/layout/fragment_information_contact.xml
index a8b9be9aa338e651c01958eb1381856314c9d502..54f23216215135ed558b64d31cc0a0773504118c 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_information_contact.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_information_contact.xml
@@ -2,99 +2,133 @@
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true">
-
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <include
-                android:id="@+id/information_contact_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:body="@{@string/information_contact_body}"
-                app:headline="@{@string/information_contact_headline}"
-                app:icon="@{@drawable/ic_back}"
-                app:illustration="@{@drawable/ic_information_illustration_contact}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/information_contact_title}" />
-
-            <TextView
-                android:id="@+id/information_contact_subtitle_phone"
-                style="@style/textLargeEmphasized"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_small"
-                android:text="@string/information_contact_subtitle_phone"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/information_contact_header" />
-
-            <include
-                android:id="@+id/information_contact_navigation_row_phone"
-                layout="@layout/include_navigation_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/information_contact_subtitle_phone"
-                app:subtitle="@{@string/information_contact_button_phone}" />
-
-            <TextView
-                android:id="@+id/information_contact_body_phone"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/information_contact_body_phone"
-                app:layout_constraintEnd_toEndOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/information_contact_navigation_row_phone" />
-
-            <TextView
-                android:id="@+id/information_contact_body_open"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                android:text="@string/information_contact_body_open"
-                app:layout_constraintEnd_toEndOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/information_contact_body_phone" />
-
-            <TextView
-                android:id="@+id/information_contact_body_other"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                android:text="@string/information_contact_body_other"
-                app:layout_constraintEnd_toEndOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/information_contact_body_open" />
-
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
-
-            <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>
-    </ScrollView>
+        android:layout_height="match_parent">
+
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/information_contact_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_back}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/information_contact_title}" />
+
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/information_contact_header">
+
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <include
+                    android:id="@+id/information_contact_header_details"
+                    layout="@layout/include_information_details"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:body="@{@string/information_contact_body}"
+                    app:headline="@{@string/information_contact_headline}"
+                    app:illustration="@{@drawable/ic_information_illustration_contact}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
+
+                <include
+                    android:id="@+id/divider"
+                    layout="@layout/include_divider"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    app:layout_constraintEnd_toEndOf="@+id/guideline_end"
+                    app:layout_constraintStart_toStartOf="@id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/information_contact_header_details" />
+
+                <TextView
+                    android:id="@+id/information_contact_subtitle_phone"
+                    style="@style/textLargeEmphasized"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_small"
+                    android:text="@string/information_contact_subtitle_phone"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/divider" />
+
+                <include
+                    android:id="@+id/information_contact_navigation_row_phone"
+                    layout="@layout/include_navigation_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/information_contact_subtitle_phone"
+                    app:subtitle="@{@string/information_contact_button_phone}" />
+
+                <TextView
+                    android:id="@+id/information_contact_body_phone"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/information_contact_body_phone"
+                    app:layout_constraintEnd_toEndOf="@+id/guideline_end"
+                    app:layout_constraintStart_toStartOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/information_contact_navigation_row_phone" />
+
+                <TextView
+                    android:id="@+id/information_contact_body_open"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    android:text="@string/information_contact_body_open"
+                    app:layout_constraintEnd_toEndOf="@+id/guideline_end"
+                    app:layout_constraintStart_toStartOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/information_contact_body_phone" />
+
+                <TextView
+                    android:id="@+id/information_contact_body_other"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    android:text="@string/information_contact_body_other"
+                    app:layout_constraintEnd_toEndOf="@+id/guideline_end"
+                    app:layout_constraintStart_toStartOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/information_contact_body_open" />
+
+                <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>
+
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_information_legal.xml b/Corona-Warn-App/src/main/res/layout/fragment_information_legal.xml
index 3f4c91ec331cf49192444fd656daf349462e2cbf..03fda1730c7b36dff8273189d033236bac1ef8f8 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_information_legal.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_information_legal.xml
@@ -2,75 +2,99 @@
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true">
+        android:layout_height="match_parent">
 
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/information_legal_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_back}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/information_legal_title}" />
 
-            <include
-                android:id="@+id/information_legal_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:headline="@{@string/information_legal_headline}"
-                app:icon="@{@drawable/ic_back}"
-                app:illustration="@{@drawable/ic_information_illustration_legal}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/information_legal_title}" />
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/information_legal_header">
 
-            <TextView
-                android:id="@+id/text_sample_1"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/information_legal_body"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/information_legal_header" />
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
 
-            <TextView
-                android:id="@+id/text_sample_2"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/text_sample_1" />
+                <include
+                    android:id="@+id/information_legal_header_details"
+                    layout="@layout/include_information_details"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:headline="@{@string/information_legal_headline}"
+                    app:illustration="@{@drawable/ic_information_illustration_legal}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
 
-            <TextView
-                android:id="@+id/text_sample_3"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/text_sample_2" />
+                <TextView
+                    android:id="@+id/text_sample_1"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/information_legal_body"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/information_legal_header_details" />
 
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
+                <TextView
+                    android:id="@+id/text_sample_2"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/text_sample_1" />
 
-            <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" />
+                <TextView
+                    android:id="@+id/text_sample_3"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/text_sample_2" />
+
+                <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>
+
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
-            <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>
-    </ScrollView>
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_information_privacy.xml b/Corona-Warn-App/src/main/res/layout/fragment_information_privacy.xml
index 889f75a31c32e29f032ab178dddbc2c635e5a93c..fe958e6ffb0e6463b65531a8dbe90353070084cf 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_information_privacy.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_information_privacy.xml
@@ -2,76 +2,99 @@
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true">
+        android:layout_height="match_parent">
 
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/information_privacy_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_back}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/information_privacy_title}" />
 
-            <!-- todo separate icon from onboarding? -->
-            <include
-                android:id="@+id/information_privacy_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:headline="@{@string/information_privacy_headline}"
-                app:icon="@{@drawable/ic_back}"
-                app:illustration="@{@drawable/ic_information_illustration_privacy}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/information_privacy_title}" />
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/information_privacy_header">
 
-            <TextView
-                android:id="@+id/text_sample_1"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/information_privacy_header" />
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
 
-            <TextView
-                android:id="@+id/text_sample_2"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/text_sample_1" />
+                <include
+                    android:id="@+id/information_privacy_header_details"
+                    layout="@layout/include_information_details"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:headline="@{@string/information_privacy_headline}"
+                    app:illustration="@{@drawable/ic_information_illustration_privacy}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
 
-            <TextView
-                android:id="@+id/text_sample_3"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/text_sample_2" />
+                <TextView
+                    android:id="@+id/text_sample_1"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/information_privacy_header_details" />
 
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
+                <TextView
+                    android:id="@+id/text_sample_2"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/text_sample_1" />
 
-            <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" />
+                <TextView
+                    android:id="@+id/text_sample_3"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/text_sample_2" />
+
+                <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>
+
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
-            <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>
-    </ScrollView>
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_information_technical.xml b/Corona-Warn-App/src/main/res/layout/fragment_information_technical.xml
index f8c799f913dfda89b630a20345abfa17cbe6f89f..0f90814a25f4675d6f761a0117b3dfc0530617c9 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_information_technical.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_information_technical.xml
@@ -2,75 +2,99 @@
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true">
+        android:layout_height="match_parent">
 
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/information_technical_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_back}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/information_technical_title}" />
 
-            <include
-                android:id="@+id/information_technical_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:headline="@{@string/information_technical_headline}"
-                app:icon="@{@drawable/ic_back}"
-                app:illustration="@{@drawable/ic_information_illustration_technical}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/information_technical_title}" />
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/information_technical_header">
 
-            <TextView
-                android:id="@+id/text_sample_1"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/information_technical_header" />
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
 
-            <TextView
-                android:id="@+id/text_sample_2"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/text_sample_1" />
+                <include
+                    android:id="@+id/information_technical_header_details"
+                    layout="@layout/include_information_details"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:headline="@{@string/information_technical_headline}"
+                    app:illustration="@{@drawable/ic_information_illustration_technical}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
 
-            <TextView
-                android:id="@+id/text_sample_3"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/text_sample_2" />
+                <TextView
+                    android:id="@+id/text_sample_1"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/information_technical_header_details" />
 
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
+                <TextView
+                    android:id="@+id/text_sample_2"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/text_sample_1" />
 
-            <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" />
+                <TextView
+                    android:id="@+id/text_sample_3"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/text_sample_2" />
+
+                <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>
+
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
-            <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>
-    </ScrollView>
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_information_terms.xml b/Corona-Warn-App/src/main/res/layout/fragment_information_terms.xml
index b80435e35f89d7578a42ac9ab53cd1c5af1b9872..f01bbfcc3f672e5955d0915ed23397e9aa3607a3 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_information_terms.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_information_terms.xml
@@ -2,75 +2,99 @@
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true">
+        android:layout_height="match_parent">
 
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/information_terms_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_back}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/information_terms_title}" />
 
-            <include
-                android:id="@+id/information_terms_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:headline="@{@string/information_terms_headline}"
-                app:icon="@{@drawable/ic_back}"
-                app:illustration="@{@drawable/ic_information_illustration_terms}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/information_terms_title}" />
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/information_terms_header">
 
-            <TextView
-                android:id="@+id/text_sample_1"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/information_terms_header" />
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
 
-            <TextView
-                android:id="@+id/text_sample_2"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/text_sample_1" />
+                <include
+                    android:id="@+id/information_terms_header_details"
+                    layout="@layout/include_information_details"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:headline="@{@string/information_terms_headline}"
+                    app:illustration="@{@drawable/ic_information_illustration_terms}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
 
-            <TextView
-                android:id="@+id/text_sample_3"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/lorem_ipsum"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toEndOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/text_sample_2" />
+                <TextView
+                    android:id="@+id/text_sample_1"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/information_terms_header_details" />
 
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
+                <TextView
+                    android:id="@+id/text_sample_2"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/text_sample_1" />
 
-            <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" />
+                <TextView
+                    android:id="@+id/text_sample_3"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lorem_ipsum"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toEndOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/text_sample_2" />
+
+                <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>
+
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
-            <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>
-    </ScrollView>
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_main.xml b/Corona-Warn-App/src/main/res/layout/fragment_main.xml
index a9ab393c0b0a4d134832b89ae92c1e1bc3fa8b06..dfaba52e58adcf4540eca2e8c2d9f6c5b2a4e949 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_main.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_main.xml
@@ -126,10 +126,10 @@
             <include
                 android:id="@+id/main_risk"
                 layout="@layout/include_risk_card"
-                android:visibility="@{FormatterSubmissionHelper.formatShowRiskStatusCard(submissionViewModel.testResult)}"
-                android:layout_width="0dp"
+                android:layout_width="@dimen/match_constraint"
                 android:layout_height="wrap_content"
                 android:layout_marginTop="@dimen/spacing_normal"
+                android:visibility="@{FormatterSubmissionHelper.formatShowRiskStatusCard(submissionViewModel.deviceUiState)}"
                 app:layout_constraintEnd_toStartOf="@+id/guideline_end"
                 app:layout_constraintStart_toStartOf="@+id/guideline_start"
                 app:layout_constraintTop_toBottomOf="@+id/main_tracing_divider"
@@ -142,25 +142,52 @@
                 layout="@layout/include_submission_status_card_positive"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                android:visibility="@{FormatterSubmissionHelper.formatShowSubmissionStatusPositiveCard(submissionViewModel.testResult)}"
+                android:visibility="@{FormatterSubmissionHelper.formatShowSubmissionStatusPositiveCard(submissionViewModel.deviceUiState)}"
                 app:layout_constraintEnd_toStartOf="@+id/guideline_end"
                 app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/main_risk"
+                app:layout_constraintTop_toBottomOf="@+id/main_tracing_divider"
                 app:registerDate="@{submissionViewModel.testResultReceivedDate}" />
 
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:id="@+id/main_test_done"
+                style="@style/card"
+                android:layout_width="@dimen/match_constraint"
+                android:layout_height="wrap_content"
+                android:visibility="@{FormatterSubmissionHelper.formatShowSubmissionDoneCard(submissionViewModel.deviceUiState)}"
+                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                app:layout_constraintStart_toStartOf="@+id/guideline_start"
+                app:layout_constraintTop_toBottomOf="@+id/main_tracing_divider">
+
+                <include
+                    layout="@layout/include_submission_done"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
+            </androidx.constraintlayout.widget.ConstraintLayout>
+
             <include
                 android:id="@+id/main_test"
                 layout="@layout/include_submission_status_card"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:layout_marginTop="@dimen/spacing_normal"
-                android:visibility="@{FormatterSubmissionHelper.formatShowSubmissionStatusCard(submissionViewModel.testResult)}"
+                android:visibility="@{FormatterSubmissionHelper.formatShowSubmissionStatusCard(submissionViewModel.deviceUiState)}"
                 app:layout_constraintEnd_toStartOf="@+id/guideline_end"
                 app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/main_test_positive"
+                app:layout_constraintTop_toBottomOf="@+id/main_risk"
                 app:submissionViewModel="@{submissionViewModel}" />
 
+            <androidx.constraintlayout.widget.Barrier
+                android:id="@+id/main_barrier"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                app:barrierDirection="bottom"
+                app:constraint_referenced_ids="main_test, main_test_done, main_test_positive, main_risk"
+                 />
+
             <include
                 android:id="@+id/main_about"
                 layout="@layout/include_main_card"
@@ -175,7 +202,7 @@
                 app:layout_constraintEnd_toStartOf="@+id/guideline_end"
                 app:layout_constraintHorizontal_bias="0.0"
                 app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/main_test"
+                app:layout_constraintTop_toBottomOf="@+id/main_barrier"
                 app:tracingViewModel="@{tracingViewModel}" />
 
             <androidx.constraintlayout.widget.Guideline
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_main_overview.xml b/Corona-Warn-App/src/main/res/layout/fragment_main_overview.xml
index dacbd5d94600b3b2438909f14e3547c8fe23ebfd..2b6dd7ba3d38a3e75e72c7498d6fbff72294b25b 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_main_overview.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_main_overview.xml
@@ -2,214 +2,242 @@
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true">
-
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <!-- todo font adjustments needed through final styles -->
-
-            <include
-                android:id="@+id/main_overview_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:icon="@{@drawable/ic_close}"
-                app:illustration="@{@drawable/ic_main_illustration_overview}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/main_overview_title}" />
-
-            <include
-                android:id="@+id/main_overview_tracing"
-                layout="@layout/include_main_overview_segment"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:body="@{@string/main_overview_body_tracing}"
-                app:icon="@{@drawable/ic_main_overview_1}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_header"
-                app:subtitle="@{@string/main_overview_subtitle_tracing}" />
-
-            <include
-                android:id="@+id/main_overview_risk"
-                layout="@layout/include_main_overview_segment"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:body="@{@string/main_overview_body_risk}"
-                app:icon="@{@drawable/ic_main_overview_2}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_tracing"
-                app:subtitle="@{@string/main_overview_subtitle_risk}" />
+        android:layout_height="match_parent">
+
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/main_overview_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_close}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/main_overview_title}" />
+
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/main_overview_header">
 
             <androidx.constraintlayout.widget.ConstraintLayout
-                android:id="@+id/main_overview_risk_subtitle"
-                style="@style/row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_risk">
-
-                <TextView
-                    style="@style/textLargeEmphasized"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <include
+                    android:id="@+id/main_overview_header_details"
+                    layout="@layout/include_information_details"
                     android:layout_width="0dp"
                     android:layout_height="wrap_content"
-                    android:layout_marginStart="@dimen/guideline_body_title"
-                    android:text="@string/main_overview_subtitle_risk_levels"
+                    app:illustration="@{@drawable/ic_main_illustration_overview}"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent"
                     app:layout_constraintTop_toTopOf="parent" />
 
-            </androidx.constraintlayout.widget.ConstraintLayout>
+                <include
+                    android:id="@+id/main_overview_tracing"
+                    layout="@layout/include_main_overview_segment"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    app:body="@{@string/main_overview_body_tracing}"
+                    app:icon="@{@drawable/ic_main_overview_1}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_header_details"
+                    app:subtitle="@{@string/main_overview_subtitle_tracing}" />
 
-            <include
-                android:id="@+id/main_overview_risk_increased_risk"
-                layout="@layout/include_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:iconStart="@{@drawable/ic_main_overview_circle}"
-                app:iconTint="@{@color/colorRiskCardIncreasedRisk}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_risk_subtitle"
-                app:title="@{@string/main_overview_subtitle_increased_risk}" />
-
-            <include
-                android:id="@+id/main_overview_risk_low_risk"
-                layout="@layout/include_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:iconStart="@{@drawable/ic_main_overview_circle}"
-                app:iconTint="@{@color/colorRiskCardLowRisk}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_risk_increased_risk"
-                app:title="@{@string/main_overview_subtitle_low_risk}" />
-
-            <include
-                android:id="@+id/main_overview_risk_unknown_risk"
-                layout="@layout/include_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:iconStart="@{@drawable/ic_main_overview_circle}"
-                app:iconTint="@{@color/colorRiskCardUnknownRisk}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_risk_low_risk"
-                app:title="@{@string/main_overview_subtitle_unknown_risk}" />
-
-            <include
-                android:id="@+id/main_overview_test"
-                layout="@layout/include_main_overview_segment"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:body="@{@string/main_overview_body_test}"
-                app:icon="@{@drawable/ic_main_overview_3}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_risk_unknown_risk"
-                app:subtitle="@{@string/main_overview_headline_test}" />
-
-            <include
-                android:id="@+id/main_overview_divider"
-                layout="@layout/include_divider"
-                android:layout_width="0dp"
-                android:layout_height="@dimen/card_divider"
-                android:layout_marginTop="@dimen/spacing_small"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@id/main_overview_test" />
+                <include
+                    android:id="@+id/main_overview_risk"
+                    layout="@layout/include_main_overview_segment"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    app:body="@{@string/main_overview_body_risk}"
+                    app:icon="@{@drawable/ic_main_overview_2}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_tracing"
+                    app:subtitle="@{@string/main_overview_subtitle_risk}" />
 
-            <androidx.constraintlayout.widget.ConstraintLayout
-                android:id="@+id/main_overview_glossary_headline"
-                style="@style/row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_small"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_divider">
-
-                <TextView
-                    style="@style/textLargeEmphasized"
+                <androidx.constraintlayout.widget.ConstraintLayout
+                    android:id="@+id/main_overview_risk_subtitle"
+                    style="@style/row"
                     android:layout_width="0dp"
                     android:layout_height="wrap_content"
-                    android:layout_marginStart="@dimen/guideline_body_title"
-                    android:text="@string/main_overview_headline_glossary"
+                    android:layout_marginTop="@dimen/spacing_normal"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent" />
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_risk">
+
+                    <TextView
+                        style="@style/textLargeEmphasized"
+                        android:layout_width="0dp"
+                        android:layout_height="wrap_content"
+                        android:layout_marginStart="@dimen/guideline_body_title"
+                        android:text="@string/main_overview_subtitle_risk_levels"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toTopOf="parent" />
+
+                </androidx.constraintlayout.widget.ConstraintLayout>
+
+                <include
+                    android:id="@+id/main_overview_risk_increased_risk"
+                    layout="@layout/include_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    app:iconStart="@{@drawable/ic_main_overview_circle}"
+                    app:iconTint="@{@color/colorRiskCardIncreasedRisk}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_risk_subtitle"
+                    app:title="@{@string/main_overview_subtitle_increased_risk}" />
+
+                <include
+                    android:id="@+id/main_overview_risk_low_risk"
+                    layout="@layout/include_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:iconStart="@{@drawable/ic_main_overview_circle}"
+                    app:iconTint="@{@color/colorRiskCardLowRisk}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_risk_increased_risk"
+                    app:title="@{@string/main_overview_subtitle_low_risk}" />
+
+                <include
+                    android:id="@+id/main_overview_risk_unknown_risk"
+                    layout="@layout/include_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:iconStart="@{@drawable/ic_main_overview_circle}"
+                    app:iconTint="@{@color/colorRiskCardUnknownRisk}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_risk_low_risk"
+                    app:title="@{@string/main_overview_subtitle_unknown_risk}" />
+
+                <include
+                    android:id="@+id/main_overview_test"
+                    layout="@layout/include_main_overview_segment"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    app:body="@{@string/main_overview_body_test}"
+                    app:icon="@{@drawable/ic_main_overview_3}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_risk_unknown_risk"
+                    app:subtitle="@{@string/main_overview_headline_test}" />
+
+                <include
+                    android:id="@+id/main_overview_divider"
+                    layout="@layout/include_divider"
+                    android:layout_width="0dp"
+                    android:layout_height="@dimen/card_divider"
+                    android:layout_marginTop="@dimen/spacing_small"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@id/main_overview_test" />
+
+                <androidx.constraintlayout.widget.ConstraintLayout
+                    android:id="@+id/main_overview_glossary_headline"
+                    style="@style/row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_small"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_divider">
+
+                    <TextView
+                        style="@style/textLargeEmphasized"
+                        android:layout_width="0dp"
+                        android:layout_height="wrap_content"
+                        android:layout_marginStart="@dimen/guideline_body_title"
+                        android:text="@string/main_overview_headline_glossary"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toTopOf="parent" />
+
+                </androidx.constraintlayout.widget.ConstraintLayout>
+
+                <include
+                    android:id="@+id/main_overview_glossary_tracing"
+                    layout="@layout/include_main_overview_glossary"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:body="@{@string/main_overview_body_glossary_tracing}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_glossary_headline"
+                    app:subtitle="@{@string/main_overview_subtitle_glossary_tracing}" />
+
+                <include
+                    android:id="@+id/main_overview_glossary_calculation"
+                    layout="@layout/include_main_overview_glossary"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:body="@{@string/main_overview_body_glossary_calculation}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_glossary_tracing"
+                    app:subtitle="@{@string/main_overview_subtitle_glossary_calculation}" />
+
+                <include
+                    android:id="@+id/main_overview_glossary_contact"
+                    layout="@layout/include_main_overview_glossary"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:body="@{@string/main_overview_body_glossary_contact}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_glossary_calculation"
+                    app:subtitle="@{@string/main_overview_subtitle_glossary_contact}" />
+
+                <include
+                    android:id="@+id/main_overview_glossary_notification"
+                    layout="@layout/include_main_overview_glossary"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:body="@{@string/main_overview_body_glossary_notification}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_glossary_contact"
+                    app:subtitle="@{@string/main_overview_subtitle_glossary_notification}" />
+
+                <include
+                    android:id="@+id/main_overview_glossary_keys"
+                    layout="@layout/include_main_overview_glossary"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:body="@{@string/main_overview_body_glossary_keys}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/main_overview_glossary_notification"
+                    app:subtitle="@{@string/main_overview_subtitle_glossary_keys}" />
 
             </androidx.constraintlayout.widget.ConstraintLayout>
 
-            <include
-                android:id="@+id/main_overview_glossary_tracing"
-                layout="@layout/include_main_overview_glossary"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:body="@{@string/main_overview_body_glossary_tracing}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_glossary_headline"
-                app:subtitle="@{@string/main_overview_subtitle_glossary_tracing}" />
-
-            <include
-                android:id="@+id/main_overview_glossary_calculation"
-                layout="@layout/include_main_overview_glossary"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:body="@{@string/main_overview_body_glossary_calculation}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_glossary_tracing"
-                app:subtitle="@{@string/main_overview_subtitle_glossary_calculation}" />
-
-            <include
-                android:id="@+id/main_overview_glossary_contact"
-                layout="@layout/include_main_overview_glossary"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:body="@{@string/main_overview_body_glossary_contact}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_glossary_calculation"
-                app:subtitle="@{@string/main_overview_subtitle_glossary_contact}" />
-
-            <include
-                android:id="@+id/main_overview_glossary_notification"
-                layout="@layout/include_main_overview_glossary"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:body="@{@string/main_overview_body_glossary_notification}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_glossary_contact"
-                app:subtitle="@{@string/main_overview_subtitle_glossary_notification}" />
-
-            <include
-                android:id="@+id/main_overview_glossary_keys"
-                layout="@layout/include_main_overview_glossary"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:body="@{@string/main_overview_body_glossary_keys}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/main_overview_glossary_notification"
-                app:subtitle="@{@string/main_overview_subtitle_glossary_keys}" />
-
-        </androidx.constraintlayout.widget.ConstraintLayout>
-    </ScrollView>
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_main_share.xml b/Corona-Warn-App/src/main/res/layout/fragment_main_share.xml
index 45b42ae43ed125e8198155abf18a5bc93e23cb4c..d364e5d2ae451b52b62a384a312ec4b46d0cf846 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_main_share.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_main_share.xml
@@ -7,70 +7,87 @@
         <variable
             name="tracingViewModel"
             type="de.rki.coronawarnapp.ui.viewmodel.TracingViewModel" />
+
     </data>
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true">
-
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <include
-                android:id="@+id/main_share_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:body="@{@string/main_share_body}"
-                app:headline="@{@string/main_share_headline}"
-                app:icon="@{@drawable/ic_close}"
-                app:illustration="@{@drawable/ic_main_illustration_share}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/main_share_title}" />
-
-            <Button
-                android:id="@+id/main_share_button"
-                style="@style/buttonPrimary"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:text="@string/main_share_button"
-                app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/main_share_header"
-                app:layout_constraintVertical_bias="1.0" />
-
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
-
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_bottom"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_end="@dimen/guideline_bottom" />
-
-            <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>
-    </ScrollView>
+        android:layout_height="match_parent">
+
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/main_share_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_close}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/main_share_title}" />
+
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginBottom="@dimen/spacing_normal"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toTopOf="@+id/main_share_button"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/main_share_header">
+
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <include
+                    android:id="@+id/main_share_header_details"
+                    layout="@layout/include_information_details"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:body="@{@string/main_share_body}"
+                    app:headline="@{@string/main_share_headline}"
+                    app:illustration="@{@drawable/ic_main_illustration_share}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
+
+            </androidx.constraintlayout.widget.ConstraintLayout>
+
+        </ScrollView>
+
+        <Button
+            android:id="@+id/main_share_button"
+            style="@style/buttonPrimary"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:text="@string/main_share_button"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+            app:layout_constraintStart_toStartOf="@+id/guideline_start" />
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+        <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>
+
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_onboarding.xml b/Corona-Warn-App/src/main/res/layout/fragment_onboarding.xml
index ed5747abc27c2ad77ebee72f169e9a213c465e5f..9fe27530db2b08d798c504598363e4afd4b9723d 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_onboarding.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_onboarding.xml
@@ -13,11 +13,12 @@
             layout="@layout/include_onboarding"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:layout_marginBottom="@dimen/spacing_normal"
             app:body="@{@string/onboarding_body}"
             app:bodyEmphasized="@{@string/onboarding_body_emphasized}"
             app:headline="@{@string/onboarding_headline}"
             app:illustration="@{@drawable/ic_onboarding_illustration_together}"
-            app:layout_constraintBottom_toTopOf="@+id/guideline_bottom"
+            app:layout_constraintBottom_toTopOf="@+id/onboarding_button_next"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toBottomOf="@+id/guideline_top"
@@ -29,9 +30,9 @@
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:text="@string/onboarding_button_start"
+            app:layout_constraintBottom_toBottomOf="@id/guideline_bottom"
             app:layout_constraintEnd_toEndOf="@id/guideline_end"
-            app:layout_constraintStart_toStartOf="@id/guideline_start"
-            app:layout_constraintTop_toBottomOf="@id/guideline_bottom" />
+            app:layout_constraintStart_toStartOf="@id/guideline_start" />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/guideline_top"
@@ -45,7 +46,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            app:layout_constraintGuide_end="@dimen/guideline_action" />
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/guideline_start"
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_onboarding_notifications.xml b/Corona-Warn-App/src/main/res/layout/fragment_onboarding_notifications.xml
index 1a52491df69ab91381641f91f356844b94643495..dcad119a22b118edd7bfadf046f54a337b01956e 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_onboarding_notifications.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_onboarding_notifications.xml
@@ -20,10 +20,11 @@
             layout="@layout/include_onboarding"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:layout_marginBottom="@dimen/spacing_normal"
             app:body="@{@string/onboarding_notifications_body}"
             app:headline="@{@string/onboarding_notifications_headline}"
             app:illustration="@{@drawable/ic_onboarding_illustration_notification}"
-            app:layout_constraintBottom_toTopOf="@+id/guideline_bottom"
+            app:layout_constraintBottom_toTopOf="@+id/onboarding_button_next"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toBottomOf="@+id/onboarding_button_back"
@@ -35,9 +36,9 @@
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:text="@string/onboarding_button_next"
+            app:layout_constraintBottom_toBottomOf="@id/guideline_bottom"
             app:layout_constraintEnd_toEndOf="@id/guideline_end"
-            app:layout_constraintStart_toStartOf="@id/guideline_start"
-            app:layout_constraintTop_toBottomOf="@id/guideline_bottom" />
+            app:layout_constraintStart_toStartOf="@id/guideline_start" />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/guideline_top"
@@ -51,7 +52,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            app:layout_constraintGuide_end="@dimen/guideline_action" />
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/guideline_start"
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_onboarding_privacy.xml b/Corona-Warn-App/src/main/res/layout/fragment_onboarding_privacy.xml
index 4163bb9cdf82b17cee46f328009b7c15155c8945..8cc273636c24bafaaf13928cabf8c99a1b7fe3dc 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_onboarding_privacy.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_onboarding_privacy.xml
@@ -20,11 +20,12 @@
             layout="@layout/include_onboarding"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:layout_marginBottom="@dimen/spacing_normal"
             app:body="@{@string/onboarding_privacy_body}"
             app:bodyEmphasized="@{@string/onboarding_privacy_body_emphasized}"
             app:headline="@{@string/onboarding_privacy_headline}"
             app:illustration="@{@drawable/ic_onboarding_illustration_privacy}"
-            app:layout_constraintBottom_toTopOf="@+id/guideline_bottom"
+            app:layout_constraintBottom_toTopOf="@+id/onboarding_button_next"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toBottomOf="@+id/onboarding_button_back"
@@ -36,9 +37,9 @@
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:text="@string/onboarding_button_next"
+            app:layout_constraintBottom_toBottomOf="@id/guideline_bottom"
             app:layout_constraintEnd_toEndOf="@id/guideline_end"
-            app:layout_constraintStart_toStartOf="@id/guideline_start"
-            app:layout_constraintTop_toBottomOf="@id/guideline_bottom" />
+            app:layout_constraintStart_toStartOf="@id/guideline_start" />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/guideline_top"
@@ -52,7 +53,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            app:layout_constraintGuide_end="@dimen/guideline_action" />
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/guideline_start"
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_onboarding_test.xml b/Corona-Warn-App/src/main/res/layout/fragment_onboarding_test.xml
index 03214a4ac06ea59b1e850204d2c79e0015bd517b..13f45ca11dc54eaa5dcfcf6c5d02c6f53ff2e0df 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_onboarding_test.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_onboarding_test.xml
@@ -20,10 +20,11 @@
             layout="@layout/include_onboarding"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:layout_marginBottom="@dimen/spacing_normal"
             app:body="@{@string/onboarding_test_body}"
             app:headline="@{@string/onboarding_test_headline}"
             app:illustration="@{@drawable/ic_onboarding_illustration_test}"
-            app:layout_constraintBottom_toTopOf="@+id/guideline_bottom"
+            app:layout_constraintBottom_toTopOf="@+id/onboarding_button_next"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toBottomOf="@+id/onboarding_button_back"
@@ -35,9 +36,9 @@
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:text="@string/onboarding_button_next"
+            app:layout_constraintBottom_toBottomOf="@id/guideline_bottom"
             app:layout_constraintEnd_toEndOf="@id/guideline_end"
-            app:layout_constraintStart_toStartOf="@id/guideline_start"
-            app:layout_constraintTop_toBottomOf="@id/guideline_bottom" />
+            app:layout_constraintStart_toStartOf="@id/guideline_start" />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/guideline_top"
@@ -51,7 +52,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            app:layout_constraintGuide_end="@dimen/guideline_action" />
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/guideline_start"
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_onboarding_tracing.xml b/Corona-Warn-App/src/main/res/layout/fragment_onboarding_tracing.xml
index 56b0bd8f3b3b365f9823b908365e1614c918582f..a8a4f608bf607196047732f7e0120ae2cf5fd02f 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_onboarding_tracing.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_onboarding_tracing.xml
@@ -20,11 +20,12 @@
             layout="@layout/include_onboarding"
             android:layout_width="0dp"
             android:layout_height="0dp"
+            android:layout_marginBottom="@dimen/spacing_normal"
             app:body="@{@string/onboarding_tracing_body}"
             app:bodyEmphasized="@{@string/onboarding_tracing_body_emphasized}"
             app:headline="@{@string/onboarding_tracing_headline}"
             app:illustration="@{@drawable/ic_onboarding_illustration_tracing}"
-            app:layout_constraintBottom_toTopOf="@+id/guideline_bottom"
+            app:layout_constraintBottom_toTopOf="@+id/onboarding_button_next"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toBottomOf="@+id/onboarding_button_back"
@@ -35,21 +36,21 @@
             style="@style/buttonPrimary"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/spacing_small"
             android:text="@string/onboarding_button_next"
+            app:layout_constraintBottom_toTopOf="@id/onboarding_button_disable"
             app:layout_constraintEnd_toEndOf="@id/guideline_end"
-            app:layout_constraintStart_toStartOf="@id/guideline_start"
-            app:layout_constraintTop_toBottomOf="@id/guideline_bottom" />
+            app:layout_constraintStart_toStartOf="@id/guideline_start" />
 
         <Button
             android:id="@+id/onboarding_button_disable"
             style="@style/buttonLight"
             android:layout_width="0dp"
             android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/spacing_small"
             android:text="@string/onboarding_button_disable"
+            app:layout_constraintBottom_toBottomOf="@id/guideline_bottom"
             app:layout_constraintEnd_toEndOf="@id/guideline_end"
-            app:layout_constraintStart_toStartOf="@id/guideline_start"
-            app:layout_constraintTop_toBottomOf="@id/onboarding_button_next" />
+            app:layout_constraintStart_toStartOf="@id/guideline_start" />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/guideline_top"
@@ -63,7 +64,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:orientation="horizontal"
-            app:layout_constraintGuide_end="@dimen/guideline_action_large" />
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
 
         <androidx.constraintlayout.widget.Guideline
             android:id="@+id/guideline_start"
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_risk_details.xml b/Corona-Warn-App/src/main/res/layout/fragment_risk_details.xml
index 8335d8010a8101f2568c0e33efb1553060b95c51..aa31ef4b5d4eeeb79ffa5187a86675231c5a8367 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_risk_details.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_risk_details.xml
@@ -20,198 +20,214 @@
             type="de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel" />
     </data>
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true"
-        tools:context=".ui.riskdetails.RiskDetailsFragment">
-
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:paddingBottom="@dimen/spacing_normal">
-
-            <include
-                android:id="@+id/risk_details_risk_card"
-                layout="@layout/include_risk_card"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:settingsViewModel="@{settingsViewModel}"
-                app:showDetails="@{true}"
-                app:tracingViewModel="@{tracingViewModel}" />
-
-            <TextView
-                android:id="@+id/risk_details_behavior_headline"
-                style="@style/textLargeEmphasized"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                android:text="@string/risk_details_headline_behavior"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/risk_details_risk_card" />
-
-            <TextView
-                android:id="@+id/risk_details_behavior_subtitle"
-                style="@style/textMultiline"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_tiny"
-                android:text="@string/risk_details_subtitle_behavior"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/risk_details_behavior_headline" />
+        android:layout_height="match_parent">
+
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:layout_marginBottom="@dimen/spacing_normal"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toTopOf="@+id/risk_details_button_enable_tracing"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent">
 
             <androidx.constraintlayout.widget.ConstraintLayout
-                android:id="@+id/risk_details_behavior_wrapper"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@id/risk_details_behavior_subtitle">
-
-                <include
-                    android:id="@+id/risk_details_behavior"
-                    layout="@layout/include_risk_details_behavior"
-                    android:layout_width="0dp"
-                    android:layout_height="wrap_content"
-                    android:layout_marginTop="@dimen/spacing_normal"
-                    android:visibility="@{FormatterRiskHelper.formatVisibilityBehavior(tracingViewModel.riskLevel)}"
-                    app:layout_constraintEnd_toEndOf="parent"
-                    app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent"
-                    app:tracingViewModel="@{tracingViewModel}" />
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
 
                 <include
-                    android:id="@+id/risk_details_behavior_increased_risk"
-                    layout="@layout/include_risk_details_behavior_increased_risk"
+                    android:id="@+id/risk_details_risk_card"
+                    layout="@layout/include_risk_card"
                     android:layout_width="0dp"
                     android:layout_height="wrap_content"
-                    android:layout_marginTop="@dimen/spacing_normal"
-                    android:visibility="@{FormatterRiskHelper.formatVisibilityBehaviorIncreasedRisk(tracingViewModel.riskLevel)}"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent"
                     app:layout_constraintTop_toTopOf="parent"
+                    app:settingsViewModel="@{settingsViewModel}"
+                    app:showDetails="@{true}"
                     app:tracingViewModel="@{tracingViewModel}" />
 
-            </androidx.constraintlayout.widget.ConstraintLayout>
-
-            <androidx.constraintlayout.widget.ConstraintLayout
-                android:id="@+id/risk_details_body"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_large"
-                android:background="@color/colorGreyLight"
-                android:padding="@dimen/spacing_normal"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@id/risk_details_behavior_wrapper">
-
                 <TextView
-                    android:id="@+id/risk_details_information_headline"
+                    android:id="@+id/risk_details_behavior_headline"
                     style="@style/textLargeEmphasized"
-                    android:layout_width="match_parent"
+                    android:layout_width="0dp"
                     android:layout_height="wrap_content"
-                    android:text="@string/risk_details_headline_infection_risk"
-                    app:layout_constraintEnd_toEndOf="parent"
-                    app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent" />
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    android:text="@string/risk_details_headline_behavior"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toStartOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/risk_details_risk_card" />
 
                 <TextView
-                    android:id="@+id/risk_details_information_subtitle"
+                    android:id="@+id/risk_details_behavior_subtitle"
                     style="@style/textMultiline"
-                    android:layout_width="match_parent"
+                    android:layout_width="0dp"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="@dimen/spacing_tiny"
-                    android:text="@{FormatterRiskHelper.formatRiskDetailsRiskLevelSubtitle(tracingViewModel.riskLevel)}"
-                    app:layout_constraintEnd_toEndOf="parent"
-                    app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toBottomOf="@+id/risk_details_information_headline" />
+                    android:text="@string/risk_details_subtitle_behavior"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toStartOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/risk_details_behavior_headline" />
 
-                <TextView
-                    android:id="@+id/risk_details_information_body"
-                    style="@style/textMultiline"
+                <androidx.constraintlayout.widget.ConstraintLayout
+                    android:id="@+id/risk_details_behavior_wrapper"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintEnd_toStartOf="@+id/guideline_end"
+                    app:layout_constraintStart_toStartOf="@+id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@id/risk_details_behavior_subtitle">
+
+                    <include
+                        android:id="@+id/risk_details_behavior"
+                        layout="@layout/include_risk_details_behavior"
+                        android:layout_width="0dp"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="@dimen/spacing_normal"
+                        android:visibility="@{FormatterRiskHelper.formatVisibilityBehavior(tracingViewModel.riskLevel)}"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toTopOf="parent"
+                        app:tracingViewModel="@{tracingViewModel}" />
+
+                    <include
+                        android:id="@+id/risk_details_behavior_increased_risk"
+                        layout="@layout/include_risk_details_behavior_increased_risk"
+                        android:layout_width="0dp"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="@dimen/spacing_normal"
+                        android:visibility="@{FormatterRiskHelper.formatVisibilityBehaviorIncreasedRisk(tracingViewModel.riskLevel)}"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toTopOf="parent"
+                        app:tracingViewModel="@{tracingViewModel}" />
+
+                </androidx.constraintlayout.widget.ConstraintLayout>
+
+                <androidx.constraintlayout.widget.ConstraintLayout
+                    android:id="@+id/risk_details_body"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:layout_marginTop="@dimen/spacing_small"
-                    android:text="@{FormatterRiskHelper.formatRiskDetailsRiskLevelBody(tracingViewModel.riskLevel, tracingViewModel.daysSinceLastExposure)}"
-                    android:visibility="@{FormatterHelper.formatVisibilityText(FormatterRiskHelper.formatRiskDetailsRiskLevelBody(tracingViewModel.riskLevel, tracingViewModel.daysSinceLastExposure))}"
+                    android:layout_marginTop="@dimen/spacing_large"
+                    android:background="@color/colorGreyLight"
+                    android:padding="@dimen/spacing_normal"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toBottomOf="@+id/risk_details_information_subtitle" />
+                    app:layout_constraintTop_toBottomOf="@id/risk_details_behavior_wrapper">
+
+                    <TextView
+                        android:id="@+id/risk_details_information_headline"
+                        style="@style/textLargeEmphasized"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:text="@string/risk_details_headline_infection_risk"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toTopOf="parent" />
+
+                    <TextView
+                        android:id="@+id/risk_details_information_subtitle"
+                        style="@style/textMultiline"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="@dimen/spacing_tiny"
+                        android:text="@{FormatterRiskHelper.formatRiskDetailsRiskLevelSubtitle(tracingViewModel.riskLevel)}"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toBottomOf="@+id/risk_details_information_headline" />
+
+                    <TextView
+                        android:id="@+id/risk_details_information_body"
+                        style="@style/textMultiline"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="@dimen/spacing_small"
+                        android:text="@{FormatterRiskHelper.formatRiskDetailsRiskLevelBody(tracingViewModel.riskLevel, tracingViewModel.daysSinceLastExposure)}"
+                        android:visibility="@{FormatterHelper.formatVisibilityText(FormatterRiskHelper.formatRiskDetailsRiskLevelBody(tracingViewModel.riskLevel, tracingViewModel.daysSinceLastExposure))}"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toBottomOf="@+id/risk_details_information_subtitle" />
+
+                    <TextView
+                        android:id="@+id/risk_details_information_body_notice"
+                        style="@style/textMultiline"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="@dimen/spacing_small"
+                        android:text="@string/risk_details_information_body_notice"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toBottomOf="@+id/risk_details_information_body" />
+
+                </androidx.constraintlayout.widget.ConstraintLayout>
+
+                <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" />
 
-                <TextView
-                    android:id="@+id/risk_details_information_body_notice"
-                    style="@style/textMultiline"
-                    android:layout_width="match_parent"
+                <androidx.constraintlayout.widget.Guideline
+                    android:id="@+id/guideline_end"
+                    android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:layout_marginTop="@dimen/spacing_small"
-                    android:text="@string/risk_details_information_body_notice"
-                    app:layout_constraintEnd_toEndOf="parent"
-                    app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toBottomOf="@+id/risk_details_information_body" />
+                    android:orientation="vertical"
+                    app:layout_constraintGuide_end="@dimen/guideline_end" />
 
             </androidx.constraintlayout.widget.ConstraintLayout>
 
-            <Button
-                android:id="@+id/risk_details_button_update"
-                style="@style/buttonPrimary"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                android:enabled="@{FormatterRiskHelper.formatButtonUpdateEnabled(settingsViewModel.isManualKeyRetrievalEnabled())}"
-                android:text="@{FormatterRiskHelper.formatButtonUpdateText(settingsViewModel.manualKeyRetrievalText)}"
-                android:visibility="@{FormatterRiskHelper.formatDetailsButtonUpdateVisibility(settingsViewModel.isBackgroundJobEnabled(), tracingViewModel.riskLevel)}"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/risk_details_body"
-                tools:text="@string/risk_details_button_update" />
-
-            <Button
-                android:id="@+id/risk_details_button_enable_tracing"
-                style="@style/buttonGrey"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                android:text="@string/risk_card_button_enable_tracing"
-                android:visibility="@{FormatterRiskHelper.formatRiskDetailsButtonEnableTracingVisibility(tracingViewModel.riskLevel)}"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/risk_details_button_update"
-                tools:text="@string/risk_card_button_enable_tracing" />
-
-            <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_bottom"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_end="@dimen/guideline_bottom" />
-
-            <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.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
-
-        </androidx.constraintlayout.widget.ConstraintLayout>
-
-    </ScrollView>
+        </ScrollView>
+
+        <Button
+            android:id="@+id/risk_details_button_enable_tracing"
+            style="@style/buttonGrey"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:text="@string/risk_card_button_enable_tracing"
+            android:visibility="@{FormatterRiskHelper.formatRiskDetailsButtonEnableTracingVisibility(tracingViewModel.riskLevel)}"
+            app:layout_constraintBottom_toTopOf="@+id/risk_details_button_update"
+            app:layout_constraintEnd_toStartOf="@+id/guideline_end_outer"
+            app:layout_constraintStart_toStartOf="@+id/guideline_start_outer"
+            tools:text="@string/risk_card_button_enable_tracing" />
+
+        <Button
+            android:id="@+id/risk_details_button_update"
+            style="@style/buttonPrimary"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:enabled="@{FormatterRiskHelper.formatButtonUpdateEnabled(settingsViewModel.isManualKeyRetrievalEnabled())}"
+            android:text="@{FormatterRiskHelper.formatButtonUpdateText(settingsViewModel.manualKeyRetrievalText)}"
+            android:visibility="@{FormatterRiskHelper.formatDetailsButtonUpdateVisibility(settingsViewModel.isBackgroundJobEnabled(), tracingViewModel.riskLevel)}"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toStartOf="@+id/guideline_end_outer"
+            app:layout_constraintStart_toStartOf="@+id/guideline_start_outer"
+            tools:text="@string/risk_details_button_update" />
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_start_outer"
+            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_outer"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            app:layout_constraintGuide_end="@dimen/guideline_end" />
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_settings.xml b/Corona-Warn-App/src/main/res/layout/fragment_settings.xml
index d28ec71c076048589dce423f41b8f1c7e1517756..677f97666dcc200d60321584251722a3ae349f5c 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_settings.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_settings.xml
@@ -17,128 +17,120 @@
 
     </data>
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true"
-        tools:context=".ui.settings.SettingsFragment">
-
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <include
-                android:id="@+id/settings_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:icon="@{@drawable/ic_close}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/settings_title}" />
-
-            <include
-                android:id="@+id/settings_tracing"
-                layout="@layout/include_setting_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:body="@{@string/settings_tracing_body_description}"
-                app:icon="@{@drawable/ic_settings_tracing_active}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/settings_header"
-                app:showDivider="@{true}"
-                app:color="@{FormatterSettingsHelper.formatIconColor(tracingViewModel.isTracingEnabled())}"
-                app:statusText="@{FormatterSettingsHelper.formatTracingStatusText(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
-                app:subtitle="@{@string/settings_tracing_title}"
-                app:tracingViewModel="@{tracingViewModel}" />
-
-            <include
-                android:id="@+id/settings_notifications"
-                layout="@layout/include_setting_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:body="@{@string/settings_notifications_body_description}"
-                app:icon="@{@drawable/ic_settings_notification}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/settings_tracing"
-                app:showDivider="@{true}"
-                app:color="@{FormatterSettingsHelper.formatIconColor(settingsViewModel.isNotificationsEnabled(), settingsViewModel.isNotificationsRiskEnabled(), settingsViewModel.isNotificationsTestEnabled())}"
-                app:statusText="@{FormatterSettingsHelper.formatNotificationsStatusText(settingsViewModel.isNotificationsEnabled(), settingsViewModel.isNotificationsRiskEnabled(), settingsViewModel.isNotificationsTestEnabled())}"
-                app:subtitle="@{@string/settings_notifications_title}"
-                app:tracingViewModel="@{tracingViewModel}" />
+        android:layout_height="match_parent">
+
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/settings_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_close}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/settings_title}" />
+
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/settings_header">
 
             <androidx.constraintlayout.widget.ConstraintLayout
-                android:id="@+id/settings_reset"
-                style="@style/row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/settings_notifications">
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
 
-                <androidx.constraintlayout.widget.ConstraintLayout
+                <include
+                    android:id="@+id/settings_tracing"
+                    layout="@layout/include_setting_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    app:body="@{@string/settings_tracing_body_description}"
+                    app:color="@{FormatterSettingsHelper.formatIconColor(tracingViewModel.isTracingEnabled())}"
+                    app:icon="@{@drawable/ic_settings_tracing_active}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent"
+                    app:showDivider="@{true}"
+                    app:statusText="@{FormatterSettingsHelper.formatTracingStatusText(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
+                    app:subtitle="@{@string/settings_tracing_title}"
+                    app:tracingViewModel="@{tracingViewModel}" />
+
+                <include
+                    android:id="@+id/settings_notifications"
+                    layout="@layout/include_setting_row"
                     android:layout_width="0dp"
                     android:layout_height="wrap_content"
-                    android:layout_marginStart="@dimen/guideline_body_title"
+                    app:body="@{@string/settings_notifications_body_description}"
+                    app:color="@{FormatterSettingsHelper.formatIconColor(settingsViewModel.isNotificationsEnabled(), settingsViewModel.isNotificationsRiskEnabled(), settingsViewModel.isNotificationsTestEnabled())}"
+                    app:icon="@{@drawable/ic_settings_notification}"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent">
+                    app:layout_constraintTop_toBottomOf="@+id/settings_tracing"
+                    app:showDivider="@{true}"
+                    app:statusText="@{FormatterSettingsHelper.formatNotificationsStatusText(settingsViewModel.isNotificationsEnabled(), settingsViewModel.isNotificationsRiskEnabled(), settingsViewModel.isNotificationsTestEnabled())}"
+                    app:subtitle="@{@string/settings_notifications_title}"
+                    app:tracingViewModel="@{tracingViewModel}" />
 
-                    <TextView
-                        android:id="@+id/settings_reset_subtitle"
-                        style="@style/textDanger"
-                        android:layout_width="0dp"
-                        android:layout_height="wrap_content"
-                        android:text="@string/settings_reset_button_positive"
-                        app:layout_constraintEnd_toEndOf="parent"
-                        app:layout_constraintStart_toStartOf="parent"
-                        app:layout_constraintTop_toTopOf="parent" />
+                <androidx.constraintlayout.widget.ConstraintLayout
+                    android:id="@+id/settings_reset"
+                    style="@style/row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/settings_notifications">
 
-                    <TextView
-                        android:id="@+id/settings_reset_body"
+                    <androidx.constraintlayout.widget.ConstraintLayout
                         android:layout_width="0dp"
                         android:layout_height="wrap_content"
-                        android:text="@string/settings_reset_body_description"
+                        android:layout_marginStart="@dimen/guideline_body_title"
                         app:layout_constraintEnd_toEndOf="parent"
                         app:layout_constraintStart_toStartOf="parent"
-                        app:layout_constraintTop_toBottomOf="@+id/settings_reset_subtitle" />
+                        app:layout_constraintTop_toTopOf="parent">
+
+                        <TextView
+                            android:id="@+id/settings_reset_subtitle"
+                            style="@style/textDanger"
+                            android:layout_width="0dp"
+                            android:layout_height="wrap_content"
+                            android:text="@string/settings_reset_button_positive"
+                            app:layout_constraintEnd_toEndOf="parent"
+                            app:layout_constraintStart_toStartOf="parent"
+                            app:layout_constraintTop_toTopOf="parent" />
+
+                        <TextView
+                            android:id="@+id/settings_reset_body"
+                            android:layout_width="0dp"
+                            android:layout_height="wrap_content"
+                            android:text="@string/settings_reset_body_description"
+                            app:layout_constraintEnd_toEndOf="parent"
+                            app:layout_constraintStart_toStartOf="parent"
+                            app:layout_constraintTop_toBottomOf="@+id/settings_reset_subtitle" />
+
+                    </androidx.constraintlayout.widget.ConstraintLayout>
 
                 </androidx.constraintlayout.widget.ConstraintLayout>
 
             </androidx.constraintlayout.widget.ConstraintLayout>
 
-            <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_bottom"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_end="@dimen/guideline_bottom" />
-
-            <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.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
-
-        </androidx.constraintlayout.widget.ConstraintLayout>
-    </ScrollView>
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_settings_notifications.xml b/Corona-Warn-App/src/main/res/layout/fragment_settings_notifications.xml
index 4b80ee38eb0299f4bb19080e05b418bc85f3f43c..c3130193878046750f897ff4752c4bb3d3c7c5e4 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_settings_notifications.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_settings_notifications.xml
@@ -9,103 +9,120 @@
 
         <import type="de.rki.coronawarnapp.util.formatter.FormatterSettingsHelper" />
 
-        <variable
-            name="tracingViewModel"
-            type="de.rki.coronawarnapp.ui.viewmodel.TracingViewModel" />
-
         <variable
             name="settingsViewModel"
             type="de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel" />
     </data>
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true"
-        tools:context=".ui.settings.SettingsNotificationFragment">
-
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <include
-                android:id="@+id/settings_details_header_notifications"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:body="@{FormatterSettingsHelper.formatNotificationsDescription(settingsViewModel.isNotificationsEnabled())}"
-                app:headline="@{FormatterSettingsHelper.formatNotificationsTitle(settingsViewModel.isNotificationsEnabled())}"
-                app:icon="@{@drawable/ic_back}"
-                app:illustration="@{FormatterSettingsHelper.formatNotificationImage(settingsViewModel.isNotificationsEnabled())}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/settings_notifications_title}" />
-
-            <include
-                android:id="@+id/settings_switch_row_notifications_risk"
-                layout="@layout/include_settings_switch_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:visibility="@{FormatterHelper.formatVisibility(settingsViewModel.isNotificationsEnabled())}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/settings_details_header_notifications"
-                app:showDivider="@{true}"
-                app:status="@{settingsViewModel.isNotificationsRiskEnabled()}"
-                app:statusText="@{FormatterSettingsHelper.formatStatus(settingsViewModel.isNotificationsRiskEnabled())}"
-                app:enabled="@{true}"
-                app:subtitle="@{@string/settings_notifications_subtitle_update_risk}" />
-
-            <include
-                android:id="@+id/settings_switch_row_notifications_test"
-                layout="@layout/include_settings_switch_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:visibility="@{FormatterHelper.formatVisibility(settingsViewModel.isNotificationsEnabled())}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/settings_switch_row_notifications_risk"
-                app:showDivider="@{true}"
-                app:status="@{settingsViewModel.isNotificationsTestEnabled()}"
-                app:enabled="@{true}"
-                app:statusText="@{FormatterSettingsHelper.formatStatus(settingsViewModel.isNotificationsTestEnabled())}"
-                app:subtitle="@{@string/settings_notifications_subtitle_update_test}" />
-
-            <include
-                android:id="@+id/settings_navigation_row_system"
-                layout="@layout/include_navigation_row"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                android:visibility="@{FormatterHelper.formatVisibilityInverted(settingsViewModel.isNotificationsEnabled())}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toBottomOf="@+id/settings_switch_row_notifications_test"
-                app:subtitle="@{@string/settings_notifications_button_open_settings}" />
-
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
-
-            <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>
-    </ScrollView>
+        android:layout_height="match_parent">
+
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/settings_notifications_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_back}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/settings_notifications_title}" />
+
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/settings_notifications_header">
+
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <include
+                    android:id="@+id/settings_notifications_header_details"
+                    layout="@layout/include_information_details"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:body="@{FormatterSettingsHelper.formatNotificationsDescription(settingsViewModel.isNotificationsEnabled())}"
+                    app:headline="@{FormatterSettingsHelper.formatNotificationsTitle(settingsViewModel.isNotificationsEnabled())}"
+                    app:illustration="@{FormatterSettingsHelper.formatNotificationImage(settingsViewModel.isNotificationsEnabled())}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
+
+                <include
+                    android:id="@+id/settings_switch_row_notifications_risk"
+                    layout="@layout/include_settings_switch_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:visibility="@{FormatterHelper.formatVisibility(settingsViewModel.isNotificationsEnabled())}"
+                    app:enabled="@{true}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/settings_notifications_header_details"
+                    app:showDivider="@{true}"
+                    app:status="@{settingsViewModel.isNotificationsRiskEnabled()}"
+                    app:statusText="@{FormatterSettingsHelper.formatStatus(settingsViewModel.isNotificationsRiskEnabled())}"
+                    app:subtitle="@{@string/settings_notifications_subtitle_update_risk}" />
+
+                <include
+                    android:id="@+id/settings_switch_row_notifications_test"
+                    layout="@layout/include_settings_switch_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:visibility="@{FormatterHelper.formatVisibility(settingsViewModel.isNotificationsEnabled())}"
+                    app:enabled="@{true}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/settings_switch_row_notifications_risk"
+                    app:showDivider="@{true}"
+                    app:status="@{settingsViewModel.isNotificationsTestEnabled()}"
+                    app:statusText="@{FormatterSettingsHelper.formatStatus(settingsViewModel.isNotificationsTestEnabled())}"
+                    app:subtitle="@{@string/settings_notifications_subtitle_update_test}" />
+
+                <include
+                    android:id="@+id/settings_navigation_row_system"
+                    layout="@layout/include_navigation_row"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    android:visibility="@{FormatterHelper.formatVisibilityInverted(settingsViewModel.isNotificationsEnabled())}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@+id/settings_switch_row_notifications_test"
+                    app:subtitle="@{@string/settings_notifications_button_open_settings}" />
+
+                <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>
+
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_settings_reset.xml b/Corona-Warn-App/src/main/res/layout/fragment_settings_reset.xml
index efc8f4f3ac2af795583bf52c24255bfec06137f5..b3d4f8ec0fe5c81862c8f3e4edeaccc224a0713b 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_settings_reset.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_settings_reset.xml
@@ -3,105 +3,121 @@
     xmlns:app="http://schemas.android.com/apk/res-auto"
     xmlns:tools="http://schemas.android.com/tools">
 
-    <data>
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
 
-        <variable
-            name="tracingViewModel"
-            type="de.rki.coronawarnapp.ui.viewmodel.TracingViewModel" />
-    </data>
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/settings_reset_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_back}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/settings_reset_title}" />
+
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toTopOf="@+id/settings_reset_button_delete"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/settings_reset_header">
+
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
+
+                <include
+                    android:id="@+id/settings_reset_header_details"
+                    layout="@layout/include_information_details"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    app:body="@{@string/settings_reset_body}"
+                    app:headline="@{@string/settings_reset_headline}"
+                    app:illustration="@{@drawable/ic_settings_illustration_reset}"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
+
+                <include
+                    android:id="@+id/settings_reset_keys"
+                    layout="@layout/include_tracing_status_card"
+                    android:layout_width="@dimen/match_constraint"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    app:body="@{@string/settings_reset_body_keys}"
+                    app:headline="@{@string/settings_reset_headline_keys}"
+                    app:icon="@{@drawable/ic_settings_reset_circle}"
+                    app:layout_constraintEnd_toEndOf="@id/guideline_end"
+                    app:layout_constraintStart_toStartOf="@id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/settings_reset_header_details" />
+
+                <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>
+
+        </ScrollView>
+
+        <Button
+            android:id="@+id/settings_reset_button_delete"
+            style="@style/buttonReset"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/spacing_small"
+            android:text="@string/settings_reset_button_positive"
+            app:layout_constraintBottom_toTopOf="@+id/settings_reset_button_cancel"
+            app:layout_constraintEnd_toStartOf="@+id/guideline_end_outer"
+            app:layout_constraintStart_toStartOf="@+id/guideline_start_outer" />
+
+        <Button
+            android:id="@+id/settings_reset_button_cancel"
+            style="@style/buttonLight"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:text="@string/settings_reset_button_negative"
+            app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
+            app:layout_constraintEnd_toStartOf="@+id/guideline_end_outer"
+            app:layout_constraintStart_toStartOf="@+id/guideline_start_outer" />
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_start_outer"
+            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_outer"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="vertical"
+            app:layout_constraintGuide_end="@dimen/guideline_end" />
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
 
-    <ScrollView
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true"
-        tools:context="de.rki.coronawarnapp.ui.settings.SettingsResetFragment">
-
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <include
-                android:id="@+id/settings_details_header_reset"
-                layout="@layout/include_information_details_header"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                app:body="@{@string/settings_reset_body}"
-                app:headline="@{@string/settings_reset_headline}"
-                app:icon="@{@drawable/ic_back}"
-                app:illustration="@{@drawable/ic_settings_illustration_reset}"
-                app:layout_constraintBottom_toTopOf="@id/guideline_bottom"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:layout_constraintVertical_bias="0"
-                app:title="@{@string/settings_reset_title}" />
-
-            <include
-                android:id="@+id/settings_reset_keys"
-                layout="@layout/include_tracing_status_card"
-                android:layout_width="@dimen/match_constraint"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:body="@{@string/settings_reset_body_keys}"
-                app:headline="@{@string/settings_reset_headline_keys}"
-                app:icon="@{@drawable/ic_settings_reset_circle}"
-                app:layout_constraintEnd_toEndOf="@id/guideline_end"
-                app:layout_constraintStart_toStartOf="@id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/settings_details_header_reset" />
-
-            <Button
-                android:id="@+id/settings_reset_button_delete"
-                style="@style/buttonReset"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                android:text="@string/settings_reset_button_positive"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/settings_reset_keys" />
-
-            <Button
-                android:id="@+id/settings_reset_button_cancel"
-                style="@style/buttonLight"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_small"
-                android:text="@string/settings_reset_button_negative"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@id/settings_reset_button_delete"
-                app:layout_constraintBottom_toBottomOf="@+id/guideline_bottom"
-                app:layout_constraintVertical_bias="0"/>
-
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
-
-            <androidx.constraintlayout.widget.Guideline
-                android:id="@+id/guideline_bottom"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_end="@dimen/guideline_bottom" />
-
-            <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>
-
-    </ScrollView>
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_settings_tracing.xml b/Corona-Warn-App/src/main/res/layout/fragment_settings_tracing.xml
index ce5b6138924a4ec190010664cccd43b2184c840a..8d7461b91021820be988428ef85e89dcb21ed981 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_settings_tracing.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_settings_tracing.xml
@@ -1,8 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <layout 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:app="http://schemas.android.com/apk/res-auto">
 
     <data>
 
@@ -19,156 +18,187 @@
             type="de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel" />
     </data>
 
-    <ScrollView
+    <androidx.constraintlayout.widget.ConstraintLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:fillViewport="true"
-        tools:context="de.rki.coronawarnapp.ui.settings.SettingsTracingFragment">
-
-        <androidx.constraintlayout.widget.ConstraintLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
-
-            <include
-                android:id="@+id/settings_tracing_header"
-                layout="@layout/include_information_details_header"
-                android:layout_width="@dimen/match_constraint"
-                android:layout_height="wrap_content"
-                app:headline="@{@string/settings_tracing_headline}"
-                app:icon="@{@drawable/ic_close}"
-                app:illustration="@{FormatterSettingsHelper.formatTracingStatusImage(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent"
-                app:title="@{@string/settings_tracing_title}" />
-
-            <include
-                android:id="@+id/settings_tracing_switch_row"
-                layout="@layout/include_settings_switch_row"
-                android:layout_width="@dimen/match_constraint"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:enabled="@{FormatterSettingsHelper.formatTracingSwitchEnabled(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
-                app:showDivider="@{true}"
-                app:layout_constraintTop_toBottomOf="@+id/settings_tracing_header"
-                app:status="@{FormatterSettingsHelper.formatTracingSwitch(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
-                app:statusText="@{FormatterSettingsHelper.formatTracingStatusText(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
-                app:subtitle="@{@string/settings_tracing_title}" />
+        android:layout_height="match_parent">
+
+        <!-- todo font adjustments needed through final styles -->
+        <include
+            android:id="@+id/settings_tracing_header"
+            layout="@layout/include_header"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            app:icon="@{@drawable/ic_close}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent"
+            app:title="@{@string/settings_tracing_title}" />
+
+        <ScrollView
+            style="@style/fadingScrollView"
+            android:layout_width="0dp"
+            android:layout_height="0dp"
+            android:fillViewport="true"
+            app:layout_constraintBottom_toBottomOf="parent"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/settings_tracing_header">
 
             <androidx.constraintlayout.widget.ConstraintLayout
-                android:id="@+id/settings_tracing_status"
-                android:layout_width="@dimen/match_constraint"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_small"
-                app:layout_constraintEnd_toEndOf="@id/guideline_end"
-                app:layout_constraintStart_toStartOf="@id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/settings_tracing_switch_row">
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content">
 
                 <include
-                    android:id="@+id/settings_tracing_status_bluetooth"
-                    layout="@layout/include_tracing_status_card"
-                    android:layout_width="@dimen/match_constraint"
+                    android:id="@+id/settings_tracing_header_details"
+                    layout="@layout/include_information_details"
+                    android:layout_width="0dp"
                     android:layout_height="wrap_content"
-                    android:visibility="@{FormatterSettingsHelper.formatTracingStatusVisibilityBluetooth(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
-                    app:body="@{@string/settings_tracing_status_bluetooth_body}"
-                    app:buttonText="@{@string/settings_tracing_status_bluetooth_button}"
-                    app:headline="@{@string/settings_tracing_status_bluetooth_headline}"
-                    app:icon="@{@drawable/ic_settings_tracing_bluetooth}"
+                    app:headline="@{@string/settings_tracing_headline}"
+                    app:illustration="@{FormatterSettingsHelper.formatTracingStatusImage(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent"
                     app:layout_constraintTop_toTopOf="parent" />
 
                 <include
-                    android:id="@+id/settings_tracing_status_connection"
-                    layout="@layout/include_tracing_status_card"
+                    android:id="@+id/settings_tracing_switch_row"
+                    layout="@layout/include_settings_switch_row"
                     android:layout_width="@dimen/match_constraint"
                     android:layout_height="wrap_content"
-                    android:visibility="@{FormatterSettingsHelper.formatTracingStatusConnection(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
-                    app:body="@{@string/settings_tracing_status_connection_body}"
-                    app:buttonText="@{@string/settings_tracing_status_connection_button}"
-                    app:headline="@{@string/settings_tracing_status_connection_headline}"
-                    app:icon="@{@drawable/ic_settings_tracing_connection}"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    app:enabled="@{FormatterSettingsHelper.formatTracingSwitchEnabled(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
                     app:layout_constraintEnd_toEndOf="parent"
                     app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent" />
+                    app:layout_constraintTop_toBottomOf="@+id/settings_tracing_header_details"
+                    app:showDivider="@{true}"
+                    app:status="@{FormatterSettingsHelper.formatTracingSwitch(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
+                    app:statusText="@{FormatterSettingsHelper.formatTracingStatusText(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
+                    app:subtitle="@{@string/settings_tracing_title}" />
 
                 <androidx.constraintlayout.widget.ConstraintLayout
-                    android:id="@+id/settings_tracing_status_tracing"
+                    android:id="@+id/settings_tracing_status"
                     android:layout_width="@dimen/match_constraint"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="@dimen/spacing_small"
-                    android:visibility="@{FormatterSettingsHelper.formatTracingStatusVisibilityTracing(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
-                    app:layout_constraintEnd_toEndOf="parent"
-                    app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent">
+                    app:layout_constraintEnd_toEndOf="@id/guideline_end"
+                    app:layout_constraintStart_toStartOf="@id/guideline_start"
+                    app:layout_constraintTop_toBottomOf="@+id/settings_tracing_switch_row">
 
-                    <de.rki.coronawarnapp.ui.view.CircleProgress
-                        android:id="@+id/settings_tracing_status_tracing_circle_progress"
-                        android:layout_width="40dp"
-                        android:layout_height="40dp"
-                        app:circleWidth="10"
-                        app:layout_constraintBottom_toBottomOf="parent"
+                    <include
+                        android:id="@+id/settings_tracing_status_bluetooth"
+                        layout="@layout/include_tracing_status_card"
+                        android:layout_width="@dimen/match_constraint"
+                        android:layout_height="wrap_content"
+                        android:visibility="@{FormatterSettingsHelper.formatTracingStatusVisibilityBluetooth(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
+                        app:body="@{@string/settings_tracing_status_bluetooth_body}"
+                        app:buttonText="@{@string/settings_tracing_status_bluetooth_button}"
+                        app:headline="@{@string/settings_tracing_status_bluetooth_headline}"
+                        app:icon="@{@drawable/ic_settings_tracing_bluetooth}"
+                        app:layout_constraintEnd_toEndOf="parent"
                         app:layout_constraintStart_toStartOf="parent"
-                        app:layout_constraintTop_toTopOf="parent"
-                        app:progress="@{tracingViewModel.activeTracingDaysInRetentionPeriod}" />
+                        app:layout_constraintTop_toTopOf="parent" />
+
+                    <include
+                        android:id="@+id/settings_tracing_status_connection"
+                        layout="@layout/include_tracing_status_card"
+                        android:layout_width="@dimen/match_constraint"
+                        android:layout_height="wrap_content"
+                        android:visibility="@{FormatterSettingsHelper.formatTracingStatusConnection(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
+                        app:body="@{@string/settings_tracing_status_connection_body}"
+                        app:buttonText="@{@string/settings_tracing_status_connection_button}"
+                        app:headline="@{@string/settings_tracing_status_connection_headline}"
+                        app:icon="@{@drawable/ic_settings_tracing_connection}"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toTopOf="parent" />
+
+                    <androidx.constraintlayout.widget.ConstraintLayout
+                        android:id="@+id/settings_tracing_status_tracing"
+                        android:layout_width="@dimen/match_constraint"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="@dimen/spacing_small"
+                        android:visibility="@{FormatterSettingsHelper.formatTracingStatusVisibilityTracing(tracingViewModel.isTracingEnabled(), settingsViewModel.isBluetoothEnabled(), settingsViewModel.isConnectionEnabled())}"
+                        app:layout_constraintEnd_toEndOf="parent"
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toTopOf="parent">
+
+                        <TextView
+                            android:id="@+id/settings_tracing_status_tracing_body"
+                            style="@style/textMultiline"
+                            android:layout_width="@dimen/match_constraint"
+                            android:layout_height="wrap_content"
+                            android:layout_marginEnd="@dimen/spacing_small"
+                            android:text="@{FormatterSettingsHelper.formatTracingStatusBody(tracingViewModel.activeTracingDaysInRetentionPeriod)}"
+                            app:layout_constraintBottom_toBottomOf="parent"
+                            app:layout_constraintEnd_toStartOf="@+id/settings_tracing_status_tracing_circle_progress"
+                            app:layout_constraintStart_toStartOf="parent"
+                            app:layout_constraintTop_toTopOf="parent" />
+
+                        <de.rki.coronawarnapp.ui.view.CircleProgress
+                            android:id="@+id/settings_tracing_status_tracing_circle_progress"
+                            android:layout_width="40dp"
+                            android:layout_height="40dp"
+                            app:circleWidth="10"
+                            app:layout_constraintBottom_toBottomOf="parent"
+                            app:layout_constraintEnd_toEndOf="parent"
+                            app:layout_constraintTop_toTopOf="parent"
+                            app:progress="@{tracingViewModel.activeTracingDaysInRetentionPeriod}" />
+
+                    </androidx.constraintlayout.widget.ConstraintLayout>
+
+                </androidx.constraintlayout.widget.ConstraintLayout>
+
+
+                <androidx.constraintlayout.widget.ConstraintLayout
+                    android:id="@+id/risk_details_body"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/spacing_normal"
+                    android:background="@color/colorGreyLight"
+                    android:padding="@dimen/spacing_normal"
+                    app:layout_constraintBottom_toBottomOf="parent"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toBottomOf="@id/settings_tracing_status">
 
                     <TextView
-                        android:id="@+id/settings_tracing_status_tracing_body"
+                        android:id="@+id/settings_tracing_body"
                         style="@style/textMultiline"
                         android:layout_width="@dimen/match_constraint"
                         android:layout_height="wrap_content"
-                        android:layout_marginStart="@dimen/spacing_small"
-                        android:text="@{FormatterSettingsHelper.formatTracingStatusBody(tracingViewModel.isTracingEnabled(), tracingViewModel.activeTracingDaysInRetentionPeriod)}"
+                        android:text="@string/settings_tracing_body_text"
                         app:layout_constraintBottom_toBottomOf="parent"
                         app:layout_constraintEnd_toEndOf="parent"
-                        app:layout_constraintStart_toEndOf="@+id/settings_tracing_status_tracing_circle_progress"
-                        app:layout_constraintTop_toTopOf="parent" />
+                        app:layout_constraintStart_toStartOf="parent"
+                        app:layout_constraintTop_toTopOf="parent"
+                        app:layout_constraintVertical_bias="0.0" />
 
                 </androidx.constraintlayout.widget.ConstraintLayout>
 
+                <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>
 
-            <TextView
-                android:id="@+id/settings_tracing_body"
-                style="@style/textMultiline"
-                android:layout_width="@dimen/match_constraint"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_small"
-                android:text="@string/settings_tracing_body_text"
-                app:layout_constraintEnd_toEndOf="@id/guideline_end"
-                app:layout_constraintStart_toStartOf="@id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@id/settings_tracing_status" />
-
-            <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_bottom"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_end="@dimen/guideline_bottom" />
-
-            <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.Guideline
-                android:id="@+id/guideline_top"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintGuide_begin="@dimen/guideline_top" />
-
-        </androidx.constraintlayout.widget.ConstraintLayout>
-    </ScrollView>
+        </ScrollView>
+
+        <androidx.constraintlayout.widget.Guideline
+            android:id="@+id/guideline_bottom"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            app:layout_constraintGuide_end="@dimen/guideline_bottom" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_done.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_done.xml
index c4043d70c55251e2adeece8a55a1bd30386ae098..1568a90b1356ce8c9c0d5ce63eed13457b389e63 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_submission_done.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_done.xml
@@ -19,55 +19,13 @@
             android:layout_height="wrap_content">
 
             <include
-                android:id="@+id/submission_done_header"
-                layout="@layout/include_information_details_header"
+                android:id="@+id/submission_done_include"
+                layout="@layout/include_submission_done"
                 android:layout_width="@dimen/match_constraint"
                 android:layout_height="wrap_content"
-                app:body="@{@string/submission_done_body}"
-                app:headline="@{@string/submission_done_headline}"
-                app:title="@{@string/submission_done_title}"
-                app:icon="@{@drawable/ic_close}"
-                app:illustration="@{@drawable/ic_submission_illustration_thanks}"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent" />
-
-            <TextView
-                android:id="@+id/submission_done_subtitle"
-                style="@style/textSubTitle"
-                android:layout_width="@dimen/match_constraint"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                android:text="@string/submission_done_subtitle"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/submission_done_header" />
-
-            <include
-                android:id="@+id/submission_done_contagious"
-                layout="@layout/include_risk_details_behavior_row"
-                android:layout_width="@dimen/match_constraint"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:body="@{@string/submission_done_contagious}"
-                app:icon="@{@drawable/ic_risk_card_contact_increased}"
-                app:layout_constraintEnd_toStartOf="@+id/guideline_end"
-                app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/submission_done_subtitle"
-                app:riskLevel="@{RiskLevelConstants.INCREASED_RISK}" />
-
-            <include
-                android:id="@+id/submission_done_isolate"
-                layout="@layout/include_risk_details_behavior_row"
-                android:layout_width="@dimen/match_constraint"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/spacing_normal"
-                app:body="@{@string/submission_done_isolate}"
-                app:icon="@{@drawable/ic_risk_details_home}"
                 app:layout_constraintEnd_toStartOf="@+id/guideline_end"
                 app:layout_constraintStart_toStartOf="@+id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/submission_done_contagious"
-                app:riskLevel="@{RiskLevelConstants.INCREASED_RISK}" />
+                app:layout_constraintTop_toTopOf="@+id/guideline_top" />
 
             <Button
                 android:id="@+id/submission_done_button_done"
@@ -79,7 +37,7 @@
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="@id/guideline_end"
                 app:layout_constraintStart_toStartOf="@id/guideline_start"
-                app:layout_constraintTop_toBottomOf="@+id/submission_done_isolate" />
+                app:layout_constraintTop_toBottomOf="@+id/submission_done_include" />
 
             <androidx.constraintlayout.widget.Guideline
                 android:id="@+id/guideline_top"
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml
index 1af644159c8e835882e72e65372be2655b3865bc..1a0bbe2b10cab260f269300edb753405292088b8 100644
--- a/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml
+++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_test_result.xml
@@ -31,7 +31,7 @@
             style="?android:attr/progressBarStyle"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:visibility="@{FormatterSubmissionHelper.formatTestResultSpinnerVisible(submissionViewModel.testResultState)}"
+            android:visibility="@{FormatterSubmissionHelper.formatTestResultSpinnerVisible(submissionViewModel.uiStateState)}"
             app:layout_constraintBottom_toBottomOf="@+id/submission_test_result_button_container"
             app:layout_constraintEnd_toStartOf="@+id/submission_test_result_guideline_end"
             app:layout_constraintStart_toStartOf="@+id/submission_test_result_guideline_start"
@@ -43,7 +43,7 @@
             android:layout_height="@dimen/match_constraint"
             android:layout_marginBottom="@dimen/spacing_normal"
             android:fillViewport="true"
-            android:visibility="@{FormatterSubmissionHelper.formatTestResultVisible(submissionViewModel.testResultState)}"
+            android:visibility="@{FormatterSubmissionHelper.formatTestResultVisible(submissionViewModel.uiStateState)}"
             app:layout_constraintBottom_toTopOf="@+id/submission_test_result_button_container"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
@@ -62,7 +62,7 @@
                     app:layout_constraintStart_toStartOf="@+id/guideline_start"
                     app:layout_constraintTop_toTopOf="parent"
                     app:registerDate="@{submissionViewModel.testResultReceivedDate}"
-                    app:testResult="@{submissionViewModel.testResult}" />
+                    app:deviceUIState="@{submissionViewModel.deviceUiState}" />
 
                 <TextView
                     android:id="@+id/submission_test_result_subtitle"
@@ -81,7 +81,7 @@
                     android:layout_width="@dimen/match_constraint"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="@dimen/spacing_normal"
-                    android:visibility="@{FormatterSubmissionHelper.formatTestResultPendingStepsVisible(submissionViewModel.testResult)}"
+                    android:visibility="@{FormatterSubmissionHelper.formatTestResultPendingStepsVisible(submissionViewModel.deviceUiState)}"
                     app:layout_constraintEnd_toEndOf="@+id/guideline_end"
                     app:layout_constraintStart_toStartOf="@+id/guideline_start"
                     app:layout_constraintTop_toBottomOf="@+id/submission_test_result_subtitle" />
@@ -92,7 +92,7 @@
                     android:layout_width="@dimen/match_constraint"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="@dimen/spacing_normal"
-                    android:visibility="@{FormatterSubmissionHelper.formatTestResultNegativeStepsVisible(submissionViewModel.testResult)}"
+                    android:visibility="@{FormatterSubmissionHelper.formatTestResultNegativeStepsVisible(submissionViewModel.deviceUiState)}"
                     app:layout_constraintEnd_toEndOf="@+id/guideline_end"
                     app:layout_constraintStart_toStartOf="@+id/guideline_start"
                     app:layout_constraintTop_toBottomOf="@+id/submission_test_result_subtitle" />
@@ -103,7 +103,7 @@
                     android:layout_width="@dimen/match_constraint"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="@dimen/spacing_normal"
-                    android:visibility="@{FormatterSubmissionHelper.formatTestResultPositiveStepsVisible(submissionViewModel.testResult)}"
+                    android:visibility="@{FormatterSubmissionHelper.formatTestResultPositiveStepsVisible(submissionViewModel.deviceUiState)}"
                     app:layout_constraintEnd_toEndOf="@+id/guideline_end"
                     app:layout_constraintStart_toStartOf="@+id/guideline_start"
                     app:layout_constraintTop_toBottomOf="@+id/submission_test_result_subtitle" />
@@ -114,7 +114,7 @@
                     android:layout_width="@dimen/match_constraint"
                     android:layout_height="wrap_content"
                     android:layout_marginTop="@dimen/spacing_normal"
-                    android:visibility="@{FormatterSubmissionHelper.formatTestResultInvalidStepsVisible(submissionViewModel.testResult)}"
+                    android:visibility="@{FormatterSubmissionHelper.formatTestResultInvalidStepsVisible(submissionViewModel.deviceUiState)}"
                     app:layout_constraintEnd_toEndOf="@+id/guideline_end"
                     app:layout_constraintStart_toStartOf="@+id/guideline_start"
                     app:layout_constraintTop_toBottomOf="@+id/submission_test_result_subtitle" />
@@ -128,7 +128,7 @@
             android:id="@+id/submission_test_result_button_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:visibility="@{FormatterSubmissionHelper.formatTestResultVisible(submissionViewModel.testResultState)}"
+            android:visibility="@{FormatterSubmissionHelper.formatTestResultVisible(submissionViewModel.uiStateState)}"
             app:layout_constraintBottom_toBottomOf="@id/submission_test_result_guideline_bottom">
 
             <Button
@@ -139,7 +139,7 @@
                 android:layout_marginHorizontal="@dimen/spacing_normal"
                 android:layout_marginVertical="@dimen/spacing_small"
                 android:text="@string/submission_test_result_pending_refresh_button"
-                android:visibility="@{FormatterSubmissionHelper.formatTestResultPendingStepsVisible(submissionViewModel.testResult)}"
+                android:visibility="@{FormatterSubmissionHelper.formatTestResultPendingStepsVisible(submissionViewModel.deviceUiState)}"
                 app:layout_constraintBottom_toTopOf="@+id/submission_test_result_button_pending_remove_test"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent" />
@@ -152,7 +152,7 @@
                 android:layout_marginHorizontal="@dimen/spacing_normal"
                 android:layout_marginVertical="@dimen/spacing_small"
                 android:text="@string/submission_test_result_pending_remove_test_button"
-                android:visibility="@{FormatterSubmissionHelper.formatTestResultPendingStepsVisible(submissionViewModel.testResult)}"
+                android:visibility="@{FormatterSubmissionHelper.formatTestResultPendingStepsVisible(submissionViewModel.deviceUiState)}"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent" />
@@ -165,7 +165,7 @@
                 android:layout_marginHorizontal="@dimen/spacing_normal"
                 android:layout_marginVertical="@dimen/spacing_small"
                 android:text="@string/submission_test_result_invalid_remove_test_button"
-                android:visibility="@{FormatterSubmissionHelper.formatTestResultInvalidStepsVisible(submissionViewModel.testResult)}"
+                android:visibility="@{FormatterSubmissionHelper.formatTestResultInvalidStepsVisible(submissionViewModel.deviceUiState)}"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent" />
@@ -178,7 +178,7 @@
                 android:layout_marginHorizontal="@dimen/spacing_normal"
                 android:layout_marginVertical="@dimen/spacing_small"
                 android:text="@string/submission_test_result_positive_continue_button"
-                android:visibility="@{FormatterSubmissionHelper.formatTestResultPositiveStepsVisible(submissionViewModel.testResult)}"
+                android:visibility="@{FormatterSubmissionHelper.formatTestResultPositiveStepsVisible(submissionViewModel.deviceUiState)}"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent" />
@@ -191,7 +191,7 @@
                 android:layout_marginHorizontal="@dimen/spacing_normal"
                 android:layout_marginVertical="@dimen/spacing_small"
                 android:text="@string/submission_test_result_negative_remove_test_button"
-                android:visibility="@{FormatterSubmissionHelper.formatTestResultNegativeStepsVisible(submissionViewModel.testResult)}"
+                android:visibility="@{FormatterSubmissionHelper.formatTestResultNegativeStepsVisible(submissionViewModel.deviceUiState)}"
                 app:layout_constraintBottom_toBottomOf="parent"
                 app:layout_constraintEnd_toEndOf="parent"
                 app:layout_constraintStart_toStartOf="parent" />
diff --git a/Corona-Warn-App/src/main/res/layout/fragment_test_risk_level_calculation.xml b/Corona-Warn-App/src/main/res/layout/fragment_test_risk_level_calculation.xml
new file mode 100644
index 0000000000000000000000000000000000000000..de86e326eb36ded52f49cba93a3719ae9d60d120
--- /dev/null
+++ b/Corona-Warn-App/src/main/res/layout/fragment_test_risk_level_calculation.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <data>
+
+        <import type="de.rki.coronawarnapp.util.formatter.FormatterSettingsHelper" />
+        <import type="de.rki.coronawarnapp.util.formatter.FormatterSubmissionHelper" />
+
+        <variable
+            name="submissionViewModel"
+            type="de.rki.coronawarnapp.ui.viewmodel.SubmissionViewModel" />
+
+        <variable
+            name="tracingViewModel"
+            type="de.rki.coronawarnapp.ui.viewmodel.TracingViewModel" />
+
+        <variable
+            name="settingsViewModel"
+            type="de.rki.coronawarnapp.ui.viewmodel.SettingsViewModel" />
+    </data>
+
+    <ScrollView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_margin="@dimen/spacing_normal"
+        android:fillViewport="true">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_margin="@dimen/spacing_normal"
+            android:orientation="vertical">
+
+            <TextView
+                style="@style/textTitle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="Preview (no interaction possible)" />
+
+            <include
+                android:id="@+id/test_risk_card"
+                layout="@layout/include_risk_card"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/spacing_normal"
+                android:visibility="@{FormatterSubmissionHelper.formatShowRiskStatusCard(submissionViewModel.deviceUiState)}"
+                app:settingsViewModel="@{settingsViewModel}"
+                app:showDetails="@{false}"
+                app:tracingViewModel="@{tracingViewModel}" />
+
+            <Button
+                android:id="@+id/button_retrieve_diagnosis_keys"
+                style="@style/buttonPrimary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/spacing_normal"
+                android:text="Retrieve Diagnosis Keys" />
+
+            <Button
+                android:id="@+id/button_provide_key_via_qr"
+                style="@style/buttonPrimary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/spacing_normal"
+                android:text="Retrieve Local QR Code" />
+
+            <Button
+                android:id="@+id/button_calculate_risk_level"
+                style="@style/buttonPrimary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/spacing_normal"
+                android:text="Calculate Risk Level" />
+
+            <TextView
+                android:id="@+id/label_exposure_summary_title"
+                style="@style/textSubTitle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/spacing_normal"
+                android:text="Exposure Summary" />
+
+            <TextView
+                android:id="@+id/label_exposure_summary"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="-" />
+
+            <TextView
+                android:id="@+id/label_risk_score_title"
+                style="@style/textSubTitle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="Risk Score" />
+
+            <TextView
+                android:id="@+id/label_risk_score"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="-" />
+
+            <TextView
+                android:id="@+id/label_backend_parameters_title"
+                style="@style/textSubTitle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="Backend Parameters" />
+
+            <TextView
+                android:id="@+id/label_backend_parameters"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="-" />
+
+            <TextView
+                android:id="@+id/label_formula_title"
+                style="@style/textSubTitle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="Used Formula" />
+
+            <TextView
+                android:id="@+id/label_formula"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="-" />
+
+            <TextView
+                android:id="@+id/label_full_config_title"
+                style="@style/textSubTitle"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="Full Backend Configuration" />
+
+            <TextView
+                android:id="@+id/label_full_config"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginBottom="@dimen/spacing_normal"
+                android:text="-" />
+
+        </LinearLayout>
+    </ScrollView>
+</layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/include_onboarding.xml b/Corona-Warn-App/src/main/res/layout/include_onboarding.xml
index 091237a3cea41e7fab6107ad043c56014c132c7a..868466029851c399624c9cd274736bd738501fc0 100644
--- a/Corona-Warn-App/src/main/res/layout/include_onboarding.xml
+++ b/Corona-Warn-App/src/main/res/layout/include_onboarding.xml
@@ -62,7 +62,7 @@
 
             <TextView
                 android:id="@+id/onboarding_subtitle"
-                style="@style/textMultilineEmphasized"
+                style="@style/textMultiline"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:layout_marginTop="@dimen/spacing_small"
diff --git a/Corona-Warn-App/src/main/res/layout/include_risk_card.xml b/Corona-Warn-App/src/main/res/layout/include_risk_card.xml
index 9337b43f218cc4150434a3754a7314b81ab385f5..39332776c979f4adbb640197c5233b0ede7c1166 100644
--- a/Corona-Warn-App/src/main/res/layout/include_risk_card.xml
+++ b/Corona-Warn-App/src/main/res/layout/include_risk_card.xml
@@ -168,8 +168,8 @@
                         app:layout_constraintEnd_toEndOf="parent"
                         app:layout_constraintStart_toStartOf="parent"
                         app:layout_constraintTop_toTopOf="parent"
-                        app:progress="@{tracingViewModel.activeTracingDaysInRetentionPeriod}"
                         app:circleWidth="5"
+                        app:progress="@{tracingViewModel.activeTracingDaysInRetentionPeriod}"
                         app:progressColor="@color/stableIconColor" />
 
                 </androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/Corona-Warn-App/src/main/res/layout/include_row.xml b/Corona-Warn-App/src/main/res/layout/include_row.xml
index ec63a3bb6a45499ac16e87947e1c18ff62a706e9..2141885a816fc573fd054846137720c72e8a42c8 100644
--- a/Corona-Warn-App/src/main/res/layout/include_row.xml
+++ b/Corona-Warn-App/src/main/res/layout/include_row.xml
@@ -64,7 +64,7 @@
 
             <TextView
                 android:id="@+id/main_row_item_headline"
-                style="@style/textLargeEmphasized"
+                style="@style/textMultiline"
                 android:layout_width="0dp"
                 android:layout_height="wrap_content"
                 android:text="@{title}"
diff --git a/Corona-Warn-App/src/main/res/layout/include_submission_done.xml b/Corona-Warn-App/src/main/res/layout/include_submission_done.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8973f3e63f4fc9e6162e372120b6b74fe85d9ab5
--- /dev/null
+++ b/Corona-Warn-App/src/main/res/layout/include_submission_done.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <data>
+
+        <import type="de.rki.coronawarnapp.risk.RiskLevelConstants" />
+    </data>
+
+    <androidx.constraintlayout.widget.ConstraintLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+
+        <include
+            android:id="@+id/submission_done_header"
+            layout="@layout/include_information_details_header"
+            android:layout_width="@dimen/match_constraint"
+            android:layout_height="wrap_content"
+            app:title="@{@string/submission_done_title}"
+            app:body="@{@string/submission_done_body}"
+            app:illustration="@{@drawable/ic_submission_illustration_thanks}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
+        <TextView
+            android:id="@+id/submission_done_subtitle"
+            style="@style/textSubTitle"
+            android:layout_width="@dimen/match_constraint"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/spacing_normal"
+            android:text="@string/submission_done_subtitle"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/submission_done_header" />
+
+        <include
+            android:id="@+id/submission_done_contagious"
+            layout="@layout/include_risk_details_behavior_row"
+            android:layout_width="@dimen/match_constraint"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/spacing_normal"
+            app:body="@{@string/submission_done_contagious}"
+            app:icon="@{@drawable/ic_risk_card_contact_increased}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/submission_done_subtitle"
+            app:riskLevel="@{RiskLevelConstants.INCREASED_RISK}" />
+
+        <include
+            android:id="@+id/submission_done_isolate"
+            layout="@layout/include_risk_details_behavior_row"
+            android:layout_width="@dimen/match_constraint"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/spacing_normal"
+            app:body="@{@string/submission_done_isolate}"
+            app:icon="@{@drawable/ic_risk_details_home}"
+            app:layout_constraintEnd_toEndOf="parent"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toBottomOf="@+id/submission_done_contagious"
+            app:riskLevel="@{RiskLevelConstants.INCREASED_RISK}" />
+
+    </androidx.constraintlayout.widget.ConstraintLayout>
+</layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/include_submission_status_card.xml b/Corona-Warn-App/src/main/res/layout/include_submission_status_card.xml
index caafc36e79c395a2039e4d5cb97bda46534fcaed..41a1af9439eccd1765de70043dc9cfea65fe8c55 100644
--- a/Corona-Warn-App/src/main/res/layout/include_submission_status_card.xml
+++ b/Corona-Warn-App/src/main/res/layout/include_submission_status_card.xml
@@ -24,12 +24,12 @@
             layout="@layout/include_submission_status_card_content"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:visibility="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentVisible(submissionViewModel.deviceRegistered, submissionViewModel.testResultState)}"
+            android:visibility="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentVisible(submissionViewModel.deviceRegistered, submissionViewModel.uiStateState)}"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent"
-            app:testResult="@{submissionViewModel.testResult}" />
+            app:deviceUIState="@{submissionViewModel.deviceUiState}" />
 
         <include
             android:id="@+id/submission_status_card_unregistered"
@@ -47,7 +47,7 @@
             layout="@layout/include_submission_status_card_fetching"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:visibility="@{FormatterSubmissionHelper.formatSubmissionStatusCardFetchingVisible(submissionViewModel.deviceRegistered, submissionViewModel.testResultState)}"
+            android:visibility="@{FormatterSubmissionHelper.formatSubmissionStatusCardFetchingVisible(submissionViewModel.deviceRegistered, submissionViewModel.uiStateState)}"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
diff --git a/Corona-Warn-App/src/main/res/layout/include_submission_status_card_content.xml b/Corona-Warn-App/src/main/res/layout/include_submission_status_card_content.xml
index da52b909d66b53d276d5b92d9e94cd3017b94f25..4ea2ee7406aa1fea61df540b65c2abcff4506247 100644
--- a/Corona-Warn-App/src/main/res/layout/include_submission_status_card_content.xml
+++ b/Corona-Warn-App/src/main/res/layout/include_submission_status_card_content.xml
@@ -7,8 +7,8 @@
         <import type="de.rki.coronawarnapp.util.formatter.FormatterSubmissionHelper" />
 
         <variable
-            name="testResult"
-            type="de.rki.coronawarnapp.util.formatter.TestResult" />
+            name="deviceUIState"
+            type="de.rki.coronawarnapp.util.DeviceUIState" />
     </data>
 
     <androidx.constraintlayout.widget.ConstraintLayout
@@ -22,7 +22,7 @@
             style="@style/textTitle"
             android:layout_width="@dimen/match_constraint"
             android:layout_height="wrap_content"
-            android:text="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentTitleText(testResult)}"
+            android:text="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentTitleText(deviceUIState)}"
             app:layout_constraintEnd_toStartOf="@+id/submission_status_card_unregistered_icon"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent" />
@@ -33,9 +33,9 @@
             android:layout_width="@dimen/match_constraint"
             android:layout_height="wrap_content"
             android:layout_marginVertical="@dimen/spacing_tiny"
-            android:text="@{FormatterSubmissionHelper.formatTestResultStatusText(testResult)}"
-            android:textColor="@{FormatterSubmissionHelper.formatTestResultStatusColor(testResult)}"
-            android:visibility="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentStatusTextVisible(testResult)}"
+            android:text="@{FormatterSubmissionHelper.formatTestResultStatusText(deviceUIState)}"
+            android:textColor="@{FormatterSubmissionHelper.formatTestResultStatusColor(deviceUIState)}"
+            android:visibility="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentStatusTextVisible(deviceUIState)}"
             app:layout_constraintBottom_toTopOf="@+id/submission_status_card_content_body"
             app:layout_constraintEnd_toStartOf="@+id/submission_status_card_unregistered_icon"
             app:layout_constraintStart_toStartOf="@+id/submission_status_card_content_title"
@@ -47,7 +47,7 @@
             android:layout_width="@dimen/match_constraint"
             android:layout_marginBottom="@dimen/spacing_normal"
             android:layout_height="wrap_content"
-            android:text="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentBodyText(testResult)}"
+            android:text="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentBodyText(deviceUIState)}"
             app:layout_constraintBottom_toTopOf="@+id/submission_status_card_content_button"
             app:layout_constraintEnd_toStartOf="@+id/submission_status_card_unregistered_icon"
             app:layout_constraintStart_toStartOf="@+id/submission_status_card_content_title" />
@@ -58,7 +58,7 @@
             android:layout_height="wrap_content"
             style="@style/buttonPrimary"
             android:layout_marginTop="@dimen/spacing_normal"
-            android:text="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentButtonText(testResult)}"
+            android:text="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentButtonText(deviceUIState)}"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toBottomOf="@+id/submission_status_card_unregistered_icon" />
@@ -68,7 +68,7 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             app:layout_constraintEnd_toEndOf="parent"
-            android:background="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentIcon(testResult)}"
+            android:background="@{FormatterSubmissionHelper.formatSubmissionStatusCardContentIcon(deviceUIState)}"
             app:layout_constraintTop_toTopOf="@+id/submission_status_card_content_title" />
     </androidx.constraintlayout.widget.ConstraintLayout>
 </layout>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/layout/include_submission_status_card_positive.xml b/Corona-Warn-App/src/main/res/layout/include_submission_status_card_positive.xml
index 15178a69e3f88483d792992676c47f9a53baed3d..2d6874951377491f894a7838f93031955b5f854a 100644
--- a/Corona-Warn-App/src/main/res/layout/include_submission_status_card_positive.xml
+++ b/Corona-Warn-App/src/main/res/layout/include_submission_status_card_positive.xml
@@ -4,7 +4,7 @@
 
     <data>
 
-        <import type="de.rki.coronawarnapp.util.formatter.TestResult" />
+        <import type="de.rki.coronawarnapp.util.DeviceUIState" />
 
         <import type="de.rki.coronawarnapp.risk.RiskLevelConstants" />
 
@@ -48,7 +48,7 @@
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintTop_toBottomOf="@+id/submission_status_card_positive_title"
                 app:registerDate="@{registerDate}"
-                app:testResult="@{TestResult.POSITIVE}" />
+                app:deviceUIState="@{DeviceUIState.PAIRED_POSITIVE}" />
 
             <TextView
                 android:id="@+id/submission_status_card_positive_result_subtitle"
diff --git a/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml b/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml
index cd46b913f841b41f2ac5b84e9557b95b2f8dd0ac..4bf8e10242f33c9f3fc91249971396d24b6a889a 100644
--- a/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml
+++ b/Corona-Warn-App/src/main/res/layout/include_test_result_card.xml
@@ -9,8 +9,8 @@
             name="registerDate"
             type="java.util.Date" />
         <variable
-            name="testResult"
-            type="de.rki.coronawarnapp.util.formatter.TestResult" />
+            name="deviceUIState"
+            type="de.rki.coronawarnapp.util.DeviceUIState" />
     </data>
 
     <androidx.constraintlayout.widget.ConstraintLayout
@@ -32,7 +32,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 app:layout_constraintBottom_toBottomOf="parent"
-                android:background="@{FormatterSubmissionHelper.formatTestStatusIcon(testResult)}"
+                android:background="@{FormatterSubmissionHelper.formatTestStatusIcon(deviceUIState)}"
                 app:layout_constraintEnd_toEndOf="parent" />
 
             <TextView
@@ -50,7 +50,7 @@
                 android:layout_height="wrap_content"
                 style="@style/testResultCardLargeText"
                 android:text="@string/test_result_card_virus_name_text"
-                android:visibility="@{FormatterSubmissionHelper.formatTestResultVirusNameTextVisible(testResult)}"
+                android:visibility="@{FormatterSubmissionHelper.formatTestResultVirusNameTextVisible(deviceUIState)}"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintTop_toBottomOf="@+id/test_result_card_headline" />
 
@@ -61,7 +61,7 @@
                 android:layout_width="@dimen/match_constraint"
                 android:text="@string/test_result_card_status_invalid"
                 android:layout_marginEnd="@dimen/spacing_large"
-                android:visibility="@{FormatterSubmissionHelper.formatTestResultInvalidStatusTextVisible(testResult)}"
+                android:visibility="@{FormatterSubmissionHelper.formatTestResultInvalidStatusTextVisible(deviceUIState)}"
                 app:layout_constraintEnd_toStartOf="@+id/test_result_card_status_icon"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintTop_toBottomOf="@+id/test_result_card_headline" />
@@ -73,7 +73,7 @@
                 android:layout_height="wrap_content"
                 android:layout_marginEnd="@dimen/spacing_large"
                 android:text="@string/test_result_card_status_pending"
-                android:visibility="@{FormatterSubmissionHelper.formatTestResultPendingStatusTextVisible(testResult)}"
+                android:visibility="@{FormatterSubmissionHelper.formatTestResultPendingStatusTextVisible(deviceUIState)}"
                 app:layout_constraintEnd_toStartOf="@+id/test_result_card_status_icon"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintTop_toBottomOf="@+id/test_result_card_headline" />
@@ -83,9 +83,9 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 style="@style/testResultCardLargeText"
-                android:text="@{FormatterSubmissionHelper.formatTestResultStatusText(testResult)}"
-                android:textColor="@{FormatterSubmissionHelper.formatTestResultStatusColor(testResult)}"
-                android:visibility="@{FormatterSubmissionHelper.formatTestResultStatusTextVisible(testResult)}"
+                android:text="@{FormatterSubmissionHelper.formatTestResultStatusText(deviceUIState)}"
+                android:textColor="@{FormatterSubmissionHelper.formatTestResultStatusColor(deviceUIState)}"
+                android:visibility="@{FormatterSubmissionHelper.formatTestResultStatusTextVisible(deviceUIState)}"
                 app:layout_constraintStart_toStartOf="parent"
                 app:layout_constraintTop_toBottomOf="@+id/test_result_card_virus_name" />
 
diff --git a/Corona-Warn-App/src/main/res/menu/menu_main.xml b/Corona-Warn-App/src/main/res/menu/menu_main.xml
index 8f6206fcd83d92af936e30957a756e03cdda42c8..35ebff47bd5c0154441ce2f7ad96128e639fcf9e 100644
--- a/Corona-Warn-App/src/main/res/menu/menu_main.xml
+++ b/Corona-Warn-App/src/main/res/menu/menu_main.xml
@@ -12,6 +12,9 @@
     <item
         android:id="@+id/menu_test_api"
         android:title="@string/menu_test_api" />
+    <item
+        android:id="@+id/menu_test_risk_level"
+        android:title="@string/menu_test_risk_level" />
     <item
         android:id="@+id/menu_notification_test"
         android:title="@string/menu_test_notification" />
diff --git a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
index 1f9b6b78908e995d421a857d3c60f5ef5eb18e86..3cae79a5ca3ee633dfbeeb4d0cc5fd30826d8314 100644
--- a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
+++ b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
@@ -38,6 +38,9 @@
         <action
             android:id="@+id/action_mainFragment_to_mainOverviewFragment"
             app:destination="@id/mainOverviewFragment" />
+        <action
+            android:id="@+id/action_mainFragment_to_testRiskLevelCalculation"
+            app:destination="@id/testRiskLevelCalculation" />
     </fragment>
 
     <fragment
@@ -309,4 +312,9 @@
             android:id="@+id/action_submissionContactFragment_to_submissionTanFragment"
             app:destination="@id/submissionTanFragment" />
     </fragment>
+    <fragment
+        android:id="@+id/testRiskLevelCalculation"
+        android:name="de.rki.coronawarnapp.TestRiskLevelCalculation"
+        android:label="fragment_test_risk_level_calculation"
+        tools:layout="@layout/fragment_test_risk_level_calculation" />
 </navigation>
diff --git a/Corona-Warn-App/src/main/res/values/integers.xml b/Corona-Warn-App/src/main/res/values/integers.xml
deleted file mode 100644
index 92946c0300b8e1b29406a31cb354488e3ee17a5a..0000000000000000000000000000000000000000
--- a/Corona-Warn-App/src/main/res/values/integers.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<resources>
-    <integer name="submission_tan_length">7</integer>
-</resources>
\ No newline at end of file
diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml
index e6a73261ca19c44a1d29cb03ef92507adb9c0f5d..67c0ffa1160e33c934aed0343111c91da12d3a1b 100644
--- a/Corona-Warn-App/src/main/res/values/strings.xml
+++ b/Corona-Warn-App/src/main/res/values/strings.xml
@@ -4,81 +4,107 @@
                Preference Keys
     ######################################
     TODO: Check what is needed -->
+
+    <!-- NOTR -->
     <string name="preference_name">
         <xliff:g id="preference">shared_preferences_cwa</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_onboarding_completed">
         <xliff:g id="preference">preference_onboarding_completed</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_reset_app">
         <xliff:g id="preference">preference_reset_app</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_only_wifi">
         <xliff:g id="preference">preference_only_wifi</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_tracing">
         <xliff:g id="preference">preference_tracing</xliff:g>
     </string>
-    <string name="preference_m_timestamp_diagnosis_keys_fetch">
-        <xliff:g id="preference">preference_m_timestamp_diagnosis_keys_fetch</xliff:g>
+    <!-- NOTR -->
+    <string name="preference_timestamp_diagnosis_keys_fetch">
+        <xliff:g id="preference">preference_timestamp_diagnosis_keys_fetch</xliff:g>
     </string>
-    <string name="preference_m_timestamp_manual_diagnosis_keys_retrieval">
-        <xliff:g id="preference">preference_m_timestamp_manual_diagnosis_keys_retrieval</xliff:g>
+    <!-- NOTR -->
+    <string name="preference_timestamp_manual_diagnosis_keys_retrieval">
+        <xliff:g id="preference">preference_timestamp_manual_diagnosis_keys_retrieval</xliff:g>
     </string>
-    <string name="preference_m_string_google_api_token">
+    <!-- NOTR -->
+    <string name="preference_string_google_api_token">
         <xliff:g id="preference">preference_m_string_google_api_token</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_notifications_enabled">
         <xliff:g id="preference">preference_notifications_enabled</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_notifications_risk_enabled">
          <xliff:g id="preference">preference_notifications_risk_enabled</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_notifications_test_enabled">
          <xliff:g id="preference">preference_notifications_test_enabled</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_background_job_allowed">
         <xliff:g id="preference">preference_background_job_enabled</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_mobile_data_allowed">
         <xliff:g id="preference">preference_mobile_data_enabled</xliff:g>
     </string>
-    <string name="preference_m_registration_token">
-        <xliff:g id="preference">preference_m_registration_token</xliff:g>
+    <!-- NOTR -->
+    <string name="preference_registration_token">
+        <xliff:g id="preference">preference_registration_token</xliff:g>
     </string>
     <string name="preference_device_pairing_successful_time">
         <xliff:g id="preference">preference_device_pairing_successful_time</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_initial_tracing_activation_time">
         <xliff:g id="preference">preference_initial_tracing_activation_time</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_initial_result_received_time">
         <xliff:g id="preference">preference_initial_result_received_time</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_risk_level_score">
         <xliff:g id="preference">preference_risk_level_score</xliff:g>
     </string>
-    <string name="preference_m_test_guid">
-        <xliff:g id="preference">preference_m_test_guid</xliff:g>
+    <!-- NOTR -->
+    <string name="preference_test_guid">
+        <xliff:g id="preference">preference_test_guid</xliff:g>
     </string>
-    <string name="preference_m_is_allowed_to_submit_diagnosis_keys">
-        <xliff:g id="preference">preference_m_is_allowed_to_submit_diagnosis_keys</xliff:g>
+    <!-- NOTR -->
+    <string name="preference_is_allowed_to_submit_diagnosis_keys">
+        <xliff:g id="preference">preference_is_allowed_to_submit_diagnosis_keys</xliff:g>
     </string>
-    <string name="preference_m_auth_code">
-        <xliff:g id="preference">preference_m_auth_code</xliff:g>
+    <!-- NOTR -->
+    <string name="preference_auth_code">
+        <xliff:g id="preference">preference_auth_code</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_database_password">
         <xliff:g id="preference">preference_database_password</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_total_non_active_tracing">
         <xliff:g id="preference">preference_total_non_active_tracing</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_last_non_active_tracing_timestamp">
         <xliff:g id="preference">preference_last_non_active_tracing_timestamp</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_number_successful_submissions">
         <xliff:g id="preference">preference_number_successful_submissions</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="preference_teletan">
         <xliff:g id="preference">preference_teletan</xliff:g>
     </string>
@@ -86,20 +112,24 @@
     <!-- ####################################
                      Menu
     ###################################### -->
-    <!-- Todo remove 'final' comments once all text are finalized, strings flagged with final can still change however its unlikely  -->
+
     <!-- Todo pluralize strings when necessary -->
     <!-- Todo include date formats when necessary -->
-    <string name="menu_help">Ãœberblick</string> <!-- final -->
-    <string name="menu_information">App-Informationen</string> <!-- final -->
-    <string name="menu_settings">Einstellungen</string> <!-- final -->
+    <!-- XMIT: application overview -->
+    <string name="menu_help">Ãœberblick</string>
+    <!-- XMIT: application information -->
+    <string name="menu_information">App-Informationen</string>
+    <!-- XMIT: application settings -->
+    <string name="menu_settings">Einstellungen</string>
 
     <!-- ####################################
                Notification
-    ######################################
-    TODO MOST OF THIS SHOULD BE TRANSLATABLE -->
+    ###################################### -->
+    <!-- NOTR -->
     <string name="notification_channel_id">
         <xliff:g id="notification_channel_id">de.rki.coronawarnapp.notification.exposureNotificationChannelId</xliff:g>
     </string>
+    <!-- NOTR -->
     <string name="notification_id">
         <xliff:g id="notification_id">1</xliff:g>
     </string>
@@ -109,100 +139,168 @@
     <string name="notification_body">Es gibt Neuigkeiten von Ihrer Corona-Warn-App</string>
 
     <!-- ####################################
-                    Risk Card
+                  Risk Card
     ###################################### -->
-    <!-- Generic -->
-    <string name="risk_card_body_contact">Bisher keine Risiko-Begegnungen</string> <!-- final -->
-    <string name="risk_card_body_contact_value">%1$s Risikobegegnungen</string>
-    <string name="risk_card_body_saved_days">%1$s von 14 Tagen aktiv</string> <!-- final -->
+
+    <!-- XTXT: risk card - no contact yet -->
+    <string name="risk_card_body_contact">Bisher keine Risiko-Begegnungen</string>
+    <plurals name="risk_card_body_contact_value">
+        <item quantity="one">%1$s Risikobegegnung</item>
+        <item quantity="other">%1$s Risikobegegnungen</item>
+    </plurals>
+    <!-- XTXT: risk card - tracing active for x out of 14 days -->
+    <string name="risk_card_body_saved_days">%1$s von 14 Tagen aktiv</string>
     <string name="risk_card_body_not_yet_fetched">Kontakte wurden noch nicht überprüft.</string>
     <string name="risk_card_body_time_fetched">Aktualisiert: %1$s</string>
     <string name="risk_card_body_next_update">Nächste Aktualisierung in: %1$s</string>
-    <string name="risk_card_button_update">Aktualisieren</string> <!-- final -->
+    <!-- XBUT: risk card - update risk -->
+    <string name="risk_card_button_update">Aktualisieren</string>
     <string name="risk_card_button_cooldown">Aktualisierung in %1$s</string>
-    <string name="risk_card_button_enable_tracing">Risiko-Ermittlung einschalten</string> <!-- final -->
-    <string name="risk_card_body_tracing_off">Aktivieren Sie die Risiko-Ermittlung, um Ihre heutige Risiko-Einschätzung zu berechnen.</string> <!-- final -->
-    <!-- LOW_RISK -->
-    <string name="risk_card_low_risk_headline">Niedriges Risiko</string>  <!-- final -->
-    <!-- INCREASED_RISK -->
-    <string name="risk_card_increased_risk_headline">Erhöhtes Risiko</string> <!-- final -->
-    <string name="risk_card_increased_risk_body_contact_last">%1$s Tage seit der letzten Begegnung</string>
-    <!-- UNKNOWN_RISK -->
-    <string name="risk_card_unknown_risk_headline">Unbekanntes Risiko</string>  <!-- final -->
-    <string name="risk_card_unknown_risk_body">Da Sie die Risiko-Ermittlung noch nicht lange genug aktiviert haben, konnten wir für Sie kein Infektionsrisiko berechnen.</string> <!-- final -->
-    <!-- NO_CALCULATION_POSSIBLE -->
-    <string name="risk_card_no_calculation_possible_headline">Risiko-Ermittlung gestoppt</string> <!-- final -->
+    <!-- XBUT: risk card - activate tracing -->
+    <string name="risk_card_button_enable_tracing">Risiko-Ermittlung einschalten</string>
+    <!-- XTXT: risk card - tracing is off, user should activate to get an updated risk level -->
+    <string name="risk_card_body_tracing_off">Aktivieren Sie die Risiko-Ermittlung, um Ihre heutige Risiko-Einschätzung zu berechnen.</string>
+    <!-- XHED: risk card - low risk headline -->
+    <string name="risk_card_low_risk_headline">Niedriges Risiko</string>
+    <!-- XHED: risk card - increased risk headline -->
+    <string name="risk_card_increased_risk_headline">Erhöhtes Risiko</string>
+    <plurals name="risk_card_increased_risk_body_contact_last">
+        <item quantity="one">%1$s Tag seit der letzten Begegnung</item>
+        <item quantity="other">%1$s Tage seit der letzten Begegnung</item>
+    </plurals>
+    <!-- XHED: risk card - unknown risk headline -->
+    <string name="risk_card_unknown_risk_headline">Unbekanntes Risiko</string>
+    <!-- XTXT: risk card - tracing isn't active long enough, so a new risk level can't be calculated -->
+    <string name="risk_card_unknown_risk_body">Da Sie die Risiko-Ermittlung noch nicht lange genug aktiviert haben, konnten wir für Sie kein Infektionsrisiko berechnen.</string>
+    <!-- XHED: risk card - tracing stopped headline, due to no possible calculation -->
+    <string name="risk_card_no_calculation_possible_headline">Risiko-Ermittlung gestoppt</string>
     <string name="risk_card_no_calculation_possible_body_saved_risk">Letzte Ermittlung:<xliff:g id="line_break">\n</xliff:g>%1$s</string>
-    <!-- OUTDATED_RISK-->
-    <string name="risk_card_outdated_risk_headline">Risiko-Ermittlung nicht möglich</string> <!-- final -->
-    <string name="risk_card_outdated_risk_body">Ihre Risiko-Berechnung konnte seit mehr als 24 Stunden nicht aktualisiert werden.</string> <!-- final -->
-    <!-- LOADING -->
-    <string name="risk_card_loading_headline">Prüfung läuft…</string> <!-- final -->
-    <string name="risk_card_loading_body">Es werden aktuelle Daten heruntergeladen und geprüft. Dies kann mehrere Minuten dauern.</string> <!-- final -->
+    <!-- XHED: risk card -  outdated risk headline, calculation isn't possible -->
+    <string name="risk_card_outdated_risk_headline">Risiko-Ermittlung nicht möglich</string>
+    <!-- XTXT: risk card - outdated risk, calculation couldn't be updated in the last 24 hours -->
+    <string name="risk_card_outdated_risk_body">Ihre Risiko-Berechnung konnte seit mehr als 24 Stunden nicht aktualisiert werden.</string>
+    <!-- XHED: risk card - loading headline, update is ongoing -->
+    <string name="risk_card_loading_headline">Prüfung läuft…</string>
+    <!-- XTXT: risk card - loading, data is downloaded and will be checked, this can take several minutes -->
+    <string name="risk_card_loading_body">Es werden aktuelle Daten heruntergeladen und geprüft. Dies kann mehrere Minuten dauern.</string>
 
     <!-- ####################################
                     Main
     ###################################### -->
-    <string name="main_about_headline">Häufige Fragen</string> <!-- final -->
-    <string name="main_about_body">Hier finden Sie Antworten auf häufig gestellte Fragen rund um die Corona-Warn-App.</string> <!-- final -->
+
+    <!-- XHED: main, FAQ -->
+    <string name="main_about_headline">Häufige Fragen</string>
+    <!-- XTXT: main, explains faq on card -->
+    <string name="main_about_body">Hier finden Sie Antworten auf häufig gestellte Fragen rund um die Corona-Warn-App.</string>
+    <!-- NOTR todo insert english link in translation file http://www.bundesregierung.de/corona-warn-app-faq-englisch -->
+    <string name="main_about_link">http://www.bundesregierung.de/corona-warn-app-faq</string>
 
     <!-- ####################################
-                   Main - Share
+               Main - Share
     ###################################### -->
-    <string name="main_share_title">Corona-Warn-App teilen</string>  <!-- final -->
-    <string name="main_share_headline">Gemeinsam Corona bekämpfen</string> <!-- final -->
-    <string name="main_share_body">Je mehr Menschen mitmachen, desto besser durchbrechen wir Infektionsketten. Laden Sie Familie, Freunde und Bekannte ein!</string> <!-- final -->
-    <string name="main_share_button">Download-Link versenden</string> <!-- final -->
-    <string name="main_share_message">Gemeinsam Corona bekämpfen<xliff:g id="line_break">\n</xliff:g>Ich bin dabei. Du auch?<xliff:g id="line_break">\n</xliff:g><xliff:g id="link_play_store">https://www.coronawarn.app/</xliff:g><xliff:g id="line_break">\n</xliff:g></string> <!-- final -->
-    <string name="submission_result_button_dialog_close">OK</string>
+
+    <!-- XHED: Share app link page title -->
+    <string name="main_share_title">Corona-Warn-App teilen</string>
+    <!-- XHED: Share app link page subtitle -->
+    <string name="main_share_headline">Gemeinsam Corona bekämpfen</string>
+    <!-- YTXT: Share app link page body -->
+    <string name="main_share_body">Je mehr Menschen mitmachen, desto besser durchbrechen wir Infektionsketten. Laden Sie Familie, Freunde und Bekannte ein!</string>
+    <!-- XBUT: Share app link page button -->
+    <string name="main_share_button">Download-Link versenden</string>
+    <!-- YMSG: Message when sharing is executed -->
+    <string name="main_share_message">Gemeinsam Corona bekämpfen<xliff:g id="line_break">\n</xliff:g>Ich bin dabei. Du auch?<xliff:g id="line_break">\n</xliff:g><xliff:g id="link_play_store">https://www.coronawarn.app/</xliff:g><xliff:g id="line_break">\n</xliff:g></string>
+
 
     <!-- ####################################
-                   Main - Overview
+                Main - Overview
     ###################################### -->
+
+    <!-- XHED: App overview page title -->
     <string name="main_overview_title">Ãœberblick</string>
+    <!-- XHED: App overview subtitle for tracing explanation-->
     <string name="main_overview_subtitle_tracing">Risiko-Ermittlung</string>
-    <string name="main_overview_body_tracing">Die Risiko-Ermittung ist eine der drei zentralen Funktionen der App. Ist sie aktiv, werden Begegnungen aufgezeichnet. Sie brauchen sich um ncihts mehr zu kümmern.</string>
+    <!-- YTXT: App overview body text about tracing -->
+    <string name="main_overview_body_tracing">Die Risiko-Ermittlung ist eine der drei zentralen Funktionen der App. Ist sie aktiv, werden Begegnungen aufgezeichnet. Sie brauchen sich um nichts mehr zu kümmern.</string>
+    <!-- XHED: App overview subtitle for risk explanation -->
     <string name="main_overview_subtitle_risk">Infektionsrisiko</string>
-    <string name="main_overview_body_risk">Sind Sie innerhalb der letzten 14 Tage einer corona- positiven Person begegnet, berechnet die App Ihr persönliches Infektionsrisiko. Als Grundlage dafür misst sie, über welche dauer und mit welchem Abstand eine Begegnung stattfand.</string>
+    <!-- YTXT: App overview body text about risk levels -->
+    <string name="main_overview_body_risk">Sind Sie innerhalb der letzten 14 Tage einer Corona-positiven Person begegnet, berechnet die App Ihr persönliches Infektionsrisiko. Als Grundlage dafür misst sie, über welche Dauer und mit welchem Abstand eine Begegnung stattfand.</string>
+    <!-- XHED: App overview subtitle for risk level list -->
     <string name="main_overview_subtitle_risk_levels">Folgende Risikostufen können angezeigt werden:</string>
+    <!-- XTXT: App overview increased risk level -->
     <string name="main_overview_subtitle_increased_risk">Erhöhtes Risiko</string>
+    <!-- XTXT: App overview low risk level -->
     <string name="main_overview_subtitle_low_risk">Niedriges Risiko</string>
+    <!-- XTXT: App overview unknown risk level -->
     <string name="main_overview_subtitle_unknown_risk">Unbekanntes Risiko</string>
+    <!-- XHED: App overview subtitle for test procedure explanation -->
     <string name="main_overview_headline_test">Benachrichtigung Anderer</string>
-    <string name="main_overview_body_test">Eine weitere zentrale Funktion. Hier können Sie Ihren Test registrieren und seinen Status abfragen. Bei einem positiven Test können Sie andere warnen und damit Infektionsketten unterbrechen.</string>
-    <string name="main_overview_headline_glossary">Wichtige Begriffe:</string>
-    <string name="main_overview_subtitle_glossary_tracing">Begegnungs-Aufzeichnung</string>
-    <string name="main_overview_body_glossary_tracing">Liste der empfangenen und vorübergehend im Betriebssystemspeicher abgelegten kurzlebigen Zufallscodes. Diese Liste wird bei der Risiko-Überprüfung gelesen. Alle Zufallscodes werden nach 14 Tagen automatisch gelöscht.</string>
-    <string name="main_overview_subtitle_glossary_calculation">Risiko-Überprüfung</string>
-    <string name="main_overview_body_glossary_calculation">Abfrage der Begegnungs-Aufzeichnung und Abgleich mit den gemeldeten Infektionen anderer Nutzerinnen und Nutzer. Die Risiko-Überprüfung erfolgt automatisch ungefähr alle zwei Stunden. </string>
-    <string name="main_overview_subtitle_glossary_contact">Risiko-Begegnung</string>
-    <string name="main_overview_body_glossary_contact">Jede Begegnungen mit einer Corona-positiv getesteten Person, der Sie über einen längeren Zeitraum und in geringer Distanz begegnet sind.</string>
-    <string name="main_overview_subtitle_glossary_notification">Risiko-Benachrichtigung</string>
-    <string name="main_overview_body_glossary_notification">Die Anzeige von Risiko-Begegnungen in der Corona-Warn-App.</string>
-    <string name="main_overview_subtitle_glossary_keys">Zufallscode</string>
-    <string name="main_overview_body_glossary_keys">Die Zufallscodes sind zufällig erzeugte Zahlen- und Buchstabenkombinationen. Sie werden zwischen benachbarten Smartphones ausgetauscht. Zufallskennungen lassen sich nicht einer bestimmten Person zuordnen und werden nach 14 Tagen automatisch gelöscht. Eine Corona-positiv getestete Person kann ihre Zufallscodes der letzten bis zu 14 Tage freiwillig mit anderen CWA-Nutzern teilen.</string>
-
-    <!-- ####################################
-               Risk Details
-    ###################################### -->
-    <string name="risk_details_headline_behavior">Verhalten</string> <!-- final -->
-    <string name="risk_details_subtitle_behavior">So verhalten Sie sich richtig</string> <!-- final -->
-    <string name="risk_details_behavior_body_stay_home">Begeben Sie sich umgehend nach Hause bzw. bleiben Sie zu Hause.</string> <!-- final -->
-    <string name="risk_details_behavior_body_contact_doctor">Für Fragen zu auftretenden Symptomen, Testmöglichkeiten und weiteren Isolationsmaßnahmen wenden Sie sich bitte an eine der folgenden Stellen:</string> <!-- final -->
-    <string name="risk_details_behavior_body_wash_hands">Waschen Sie Ihre Hände regelmäßig.</string> <!-- final -->
-    <string name="risk_details_behavior_body_wear_mask">Tragen Sie einen Mundschutz bei Kontakt mit anderen Personen.</string> <!-- final -->
-    <string name="risk_details_behavior_body_stay_away">Halten Sie mindestens 1,5 Meter Abstand zu anderen Personen.</string> <!-- final -->
-    <string name="risk_details_behavior_body_cough_sneeze">Niesen oder husten Sie in die Armbeuge oder in ein Taschentuch.</string> <!-- final -->
-    <string name="risk_details_behavior_increased_body_1">- Ihre Hausärztin/Ihren Hausarzt</string> <!-- final -->
-    <string name="risk_details_behavior_increased_body_2">- Den Kassenärztlichen Bereitschaftsdienst unter der Telefonnummer: 116117</string> <!-- final -->
-    <string name="risk_details_behavior_increased_body_3">- Ihr Gesundheitsamt</string> <!-- final -->
-    <string name="risk_details_headline_infection_risk">Infektionsrisiko</string> <!-- final -->
-    <string name="risk_details_subtitle_infection_risk_past">So wurde Ihr Risiko ermittelt</string> <!-- final -->
-    <string name="risk_details_subtitle_infection_risk">So wird Ihr Risiko ermittelt</string> <!-- final -->
-    <string name="risk_details_information_body_unknown_risk">Da Sie die Risiko-Ermittlung noch nicht lange genug aktiviert haben, konnten wir für Sie kein Infektionsrisiko berechnen.</string> <!-- final -->
+    <!-- YTXT: App overview body text about rest procedure -->
+    <string name="main_overview_body_test">Eine weitere zentrale Funktion. Hier können Sie Ihren Test registrieren und seinen Status abfragen. Bei einem positiven Test können Sie andere warnen und damit Infektionsketten unterbrechen.</string>
+    <!-- XHED: App overview headline for glossary -->
+   <string name="main_overview_headline_glossary">Wichtige Begriffe:</string>
+    <!-- XHED: App overview subtitle for glossary key storage -->
+   <string name="main_overview_subtitle_glossary_tracing">Begegnungs-Aufzeichnung</string>
+    <!-- YTXT: App overview body for glossary key storage -->
+   <string name="main_overview_body_glossary_tracing">Liste der empfangenen und vorübergehend im Betriebssystemspeicher abgelegten kurzlebigen Zufallscodes. Diese Liste wird bei der Risiko-Überprüfung gelesen. Alle Zufallscodes werden nach 14 Tagen automatisch gelöscht.</string>
+    <!-- XHED: App overview subtitle for glossary risk calculation  -->
+   <string name="main_overview_subtitle_glossary_calculation">Risiko-Überprüfung</string>
+    <!-- YTXT: App overview body for glossary risk calculation -->
+   <string name="main_overview_body_glossary_calculation">Abfrage der Begegnungs-Aufzeichnung und Abgleich mit den gemeldeten Infektionen anderer Nutzerinnen und Nutzer. Die Risiko-Überprüfung erfolgt automatisch ungefähr alle zwei Stunden.</string>
+    <!-- XHED: App overview subtitle for glossary contact  -->
+   <string name="main_overview_subtitle_glossary_contact">Risiko-Begegnungen</string>
+    <!-- YTXT: App overview body for glossary contact -->
+   <string name="main_overview_body_glossary_contact">Jene Begegnungen mit einer Corona-positiv getesteten Person, die über einen längeren Zeitraum und in geringer Distanz stattfanden.</string>
+    <!-- XHED: App overview subtitle for glossary notifications -->
+   <string name="main_overview_subtitle_glossary_notification">Risiko-Benachrichtigung</string>
+    <!-- YTXT: App overview body for glossary notifications -->
+   <string name="main_overview_body_glossary_notification">Die Anzeige von Risiko-Begegnungen in der Corona-Warn-App.</string>
+    <!-- XHED: App overview subtitle for glossary keys -->
+   <string name="main_overview_subtitle_glossary_keys">Zufallscode</string>
+    <!-- YTXT: App overview body for glossary keys -->
+   <string name="main_overview_body_glossary_keys">Die Zufallscodes sind zufällig erzeugte Zahlen- und Buchstabenkombinationen. Sie werden zwischen benachbarten Smartphones ausgetauscht. Zufallskennungen lassen sich nicht einer bestimmten Person zuordnen und werden nach 14 Tagen automatisch gelöscht. Eine Corona-positiv getestete Person kann ihre Zufallscodes der letzten bis zu 14 Tage freiwillig mit anderen CWA-Nutzern teilen.</string>
+
+   <!-- ####################################
+              Risk Details
+   ###################################### -->
+
+    <!-- XHED: risk details - headline, how a user should act -->
+    <string name="risk_details_headline_behavior">Verhalten</string>
+    <!-- XHED: risk details - multiline headline, bold, how to act correct -->
+    <string name="risk_details_subtitle_behavior">So verhalten Sie sich richtig</string>
+    <!-- XMSG: risk details - go/stay home, something like a bullet point -->
+    <string name="risk_details_behavior_body_stay_home">Begeben Sie sich umgehend nach Hause bzw. bleiben Sie zu Hause.</string>
+    <!-- XMSG: risk details - get in touch with the corresponding people, something like a bullet point -->
+    <string name="risk_details_behavior_body_contact_doctor">Für Fragen zu auftretenden Symptomen, Testmöglichkeiten und weiteren Isolationsmaßnahmen wenden Sie sich bitte an eine der folgenden Stellen:</string>
+    <!-- XMSG: risk details - wash your hands, something like a bullet point -->
+    <string name="risk_details_behavior_body_wash_hands">Waschen Sie Ihre Hände regelmäßig.</string>
+    <!-- XMSG: risk details - wear a face mask, something like a bullet point -->
+    <string name="risk_details_behavior_body_wear_mask">Tragen Sie einen Mundschutz bei Kontakt mit anderen Personen.</string>
+    <!-- XMSG: risk details - stay 1,5 away, something like a bullet point -->
+    <string name="risk_details_behavior_body_stay_away">Halten Sie mindestens 1,5 Meter Abstand zu anderen Personen.</string>
+    <!-- XMSG: risk details - cough/sneeze, something like a bullet point -->
+    <string name="risk_details_behavior_body_cough_sneeze">Niesen oder husten Sie in die Armbeuge oder in ein Taschentuch.</string>
+    <!-- XMSG: risk details - contact your doctor, bullet point -->
+    <string name="risk_details_behavior_increased_body_1">- Ihre Hausärztin/Ihren Hausarzt</string>
+    <!-- XMSG: risk details - panel doctor on-call service, bullet point -->
+    <string name="risk_details_behavior_increased_body_2">- Den Kassenärztlichen Bereitschaftsdienst unter der Telefonnummer: 116117</string>
+    <!-- XMSG: risk details - public health department, bullet point -->
+    <string name="risk_details_behavior_increased_body_3">- Ihr Gesundheitsamt</string>
+    <!-- XHED: risk details - infection risk headline, below behaviors -->
+    <string name="risk_details_headline_infection_risk">Infektionsrisiko</string>
+    <!-- XHED: risk details - how your risk level was calculated, below behaviors -->
+    <string name="risk_details_subtitle_infection_risk_past">So wurde Ihr Risiko ermittelt</string>
+    <!-- XHED: risk details - how your risk level will be calculated, below behaviors -->
+    <string name="risk_details_subtitle_infection_risk">So wird Ihr Risiko ermittelt</string>
+    <!-- XMSG: risk details - risk couldn't be calculated tracing wasn't enabled long enough, below behaviors -->
+    <string name="risk_details_information_body_unknown_risk">Da Sie die Risiko-Ermittlung noch nicht lange genug aktiviert haben, konnten wir für Sie kein Infektionsrisiko berechnen.</string>
+    <!-- XMSG: risk details - risk calculation wasn't possible for 24h, below behaviors -->
     <string name="risk_details_information_body_outdated_risk">Ihre Risiko-Berechnung konnte seit mehr als 24 Stunden nicht aktualisiert werden.</string>
     <string name="risk_details_information_body_low_risk">Sie haben ein niedriges Infektionsrisiko, da keine Begegnung mit nachweislich Coronapositiv getesteten Personen aufgezeichnet wurde oder sich Ihre Begegnung auf kurze Zeit und einen größeren Abstand beschränkt hat.</string> <!-- final -->
-    <string name="risk_details_information_body_increased_risk">Sie haben ein erhöhtes Infektionsrisiko, da Sie zuletzt vor %1$s Tagen mindestens einer- Corona positiv-getesteten Person über einen längeren Zeitraum und mit einem geringen Abstand begegnet sind.</string>
+    <plurals name="risk_details_information_body_increased_risk">
+        <item quantity="one">Sie haben ein erhöhtes Infektionsrisiko, da Sie zuletzt vor %1$s Tag mindestens einer- Corona positiv-getesteten Person über einen längeren Zeitraum und mit einem geringen Abstand begegnet sind.</item>
+        <item quantity="other">Sie haben ein erhöhtes Infektionsrisiko, da Sie zuletzt vor %1$s Tagen mindestens einer- Corona positiv-getesteten Person über einen längeren Zeitraum und mit einem geringen Abstand begegnet sind.</item>
+    </plurals>
     <string name="risk_details_information_body_notice">Das Infektionsrisiko wird anhand der Daten der Risiko-Ermittlung unter Berücksichtigung von Abstand und Dauer lokal auf Ihrem Smartphone berechnet. Ihr Infektionsrisiko ist für niemanden einsehbar und wird nicht weitergegeben.</string> <!-- final -->
     <string name="risk_details_button_update">@string/risk_card_button_update</string>
     <string name="risk_details_button_enable_tracing">@string/risk_card_button_enable_tracing</string>
@@ -210,329 +308,487 @@
     <!-- ####################################
               Onboarding
     ###################################### -->
+
     <string name="onboarding_image_description">IS MISSING</string>
     <string name="onboarding_button_disable">Nicht aktivieren</string>
     <!-- XBUT: onboarding - next -->
-    <string name="onboarding_button_next">Weiter</string> <!-- final -->
+    <string name="onboarding_button_next">Weiter</string>
     <!-- XBUT: onboarding - start -->
-    <string name="onboarding_button_start">Los Geht\'s</string> <!-- final -->
+    <string name="onboarding_button_start">Los geht\'s</string>
+    <!-- XTXT: onboarding - back description for screen reader -->
     <string name="onboarding_button_back_description">Zurück</string>
-    <!-- 1 Together -->
     <!-- XHED: onboarding(together) - fight corona -->
-    <string name="onboarding_headline">Gemeinsam Corona bekämpfen</string> <!-- final -->
+    <string name="onboarding_headline">Gemeinsam Corona bekämpfen</string>
     <!-- XHED: onboarding(together) - two/three line headline under an illustration -->
-    <string name="onboarding_subtitle">Mehr Schutz für Sie und uns alle. Mit der Corona-Warn-App durchbrechen wir Infektionsketten schneller.</string> <!-- final -->
+    <string name="onboarding_subtitle">Mehr Schutz für Sie und uns alle. Mit der Corona-Warn-App durchbrechen wir Infektionsketten schneller.</string>
     <!-- YTXT: onboarding(together) - inform about the app -->
-    <string name="onboarding_body">Machen Sie Ihr Smartphone zum Corona-Warn-System. Überblicken Sie Ihren Risikostatus und erfahren Sie, ob in den letzten 14 Tagen infizierte Personen in ihrer Nähe waren.</string> <!-- final -->
+    <string name="onboarding_body">Machen Sie Ihr Smartphone zum Corona-Warn-System. Überblicken Sie Ihren Risikostatus und erfahren Sie, ob in den letzten 14 Tagen infizierte Personen in ihrer Nähe waren.</string>
     <!-- YTXT: onboarding(together) - explain application -->
-    <string name="onboarding_body_emphasized">Die App merkt sich Begegnungen zwischen Menschen, indem ihre Smartphones verschlüsselte Zufallscodes austauschen. Und zwar ohne dabei auf persönliche Daten zuzugreifen.</string> <!-- final -->
-    <!-- 2 Privacy -->
+    <string name="onboarding_body_emphasized">Die App merkt sich Begegnungen zwischen Menschen, indem ihre Smartphones verschlüsselte Zufallscodes austauschen. Und zwar ohne dabei auf persönliche Daten zuzugreifen.</string>
     <string name="onboarding_privacy_headline">Datenschutz</string>
     <string name="onboarding_privacy_subtitle">Verantwortliche Stelle im Sinne des Art. 4 Abs. 7 DSGVO: \n \n Robert Koch-Institut\nNordufer 20\n13353 Berlin</string>
     <string name="onboarding_privacy_body">@string/lorem_ipsum</string>
     <string name="onboarding_privacy_body_emphasized">@string/lorem_ipsum</string>
-    <!-- 3 Tracing -->
     <!-- XHED: onboarding(tracing) - how to enable tracing -->
-    <string name="onboarding_tracing_headline">Wie Sie die Risiko-Ermittlung ermöglichen</string> <!-- final -->
+    <string name="onboarding_tracing_headline">Wie Sie die Risiko-Ermittlung ermöglichen</string>
     <!-- XHED: onboarding(tracing) - two/three line headline under an illustration -->
-    <string name="onboarding_tracing_subtitle">Um zu erkennen, ob für Sie ein Ansteckungsrisiko vorliegt, müssen Sie die Risiko-Ermittlung aktivieren.</string> <!-- final -->
+    <string name="onboarding_tracing_subtitle">Um zu erkennen, ob für Sie ein Ansteckungsrisiko vorliegt, müssen Sie die Risiko-Ermittlung aktivieren.</string>
     <!-- YTXT: onboarding(tracing) - explain tracing -->
-    <string name="onboarding_tracing_body">Die Risiko-Ermittlung funktioniert, indem Ihr Handy per Bluetooth verschlüsselte Zufallscodes anderer Nutzerinnen und Nutzer empfängt und Ihren eigenen Zufallscode an deren Smartphones weitergibt. Die Funktion lässt sich jederzeit wieder deaktivieren.</string> <!-- final -->
+    <string name="onboarding_tracing_body">Die Risiko-Ermittlung funktioniert, indem Ihr Handy per Bluetooth verschlüsselte Zufallscodes anderer Nutzerinnen und Nutzer empfängt und Ihren eigenen Zufallscode an deren Smartphones weitergibt. Die Funktion lässt sich jederzeit wieder deaktivieren.</string>
     <!-- YTXT: onboarding(tracing) - explain tracing -->
-    <string name="onboarding_tracing_body_emphasized">Die verschlüsselten Zufallscodes geben nur Auskunft über das Datum, die Dauer und die anhand der Signalstärke berechnete Entfernung zu Ihren Mitmenschen. Persönliche Daten wie Name, Adresse oder Aufenthaltsort werden zu keiner Zeit erfasst. Konkrete Rückschlüsse auf Personen sind nicht möglich.</string> <!-- final -->
+    <string name="onboarding_tracing_body_emphasized">Die verschlüsselten Zufallscodes geben nur Auskunft über das Datum, die Dauer und die anhand der Signalstärke berechnete Entfernung zu Ihren Mitmenschen. Persönliche Daten wie Name, Adresse oder Aufenthaltsort werden zu keiner Zeit erfasst. Konkrete Rückschlüsse auf Personen sind nicht möglich.</string>
+    <!-- XTXT: onboarding(tracing) - dialog about tracing permission declined -->
     <string name="onboarding_tracing_dialog_headline">Berechtigung</string>
     <!-- YMSI: onboarding(tracing) - dialog about tracing -->
-    <string name="onboarding_tracing_dialog_body">Corona-Warn-App kann dadurch keine Benachrichtigungen zum COVID-19-Risikostatus versenden und empfangen. Sie können die Funktion jederzeit ausschalten.</string> <!-- final -->
+    <string name="onboarding_tracing_dialog_body">Corona-Warn-App kann dadurch keine Benachrichtigungen zum COVID-19-Risikostatus versenden und empfangen. Sie können die Funktion jederzeit ausschalten.</string>
     <!-- XBUT: onboarding(tracing) - positive button (right) -->
-    <string name="onboarding_tracing_dialog_button_positive">Nicht aktivieren</string> <!-- final -->
-    <!-- XBUT: onboarding(tracing) - negative button (right)-->
-    <string name="onboarding_tracing_dialog_button_negative">Zurück</string> <!-- final -->
-    <!-- 4 Test -->
-    <!-- XHED: onboarding(test) - about positive tests-->
-    <string name="onboarding_test_headline">Falls Sie positiv getestet werden …</string> <!-- final -->
+    <string name="onboarding_tracing_dialog_button_positive">Nicht aktivieren</string>
+    <!-- XBUT: onboarding(tracing) - negative button (right) -->
+    <string name="onboarding_tracing_dialog_button_negative">Zurück</string>
+    <!-- XHED: onboarding(test) - about positive tests -->
+    <string name="onboarding_test_headline">Falls Sie positiv getestet werden …</string>
     <!-- XHED: onboarding(test) - two/three line headline under an illustration -->
-    <string name="onboarding_test_subtitle">… teilen Sie es bitte über die Corona-Warn-App mit. Freiwillig und sicher. Für die Gesundheit aller.</string> <!-- final -->
+    <string name="onboarding_test_subtitle">… teilen Sie es bitte über die Corona-Warn-App mit. Freiwillig und sicher. Für die Gesundheit aller.</string>
     <!-- YTXT: onboarding(test) - explain test -->
-    <string name="onboarding_test_body">Ihre Mitteilung wird zuverlässig verschlüsselt über einen sicheren Server weiterverarbeitet. Die Personen, deren verschlüsselte Zufallscodes Sie gesammelt haben, erhalten nun eine Warnung und Informationen darüber, wie sie weiter vorgehen sollen.</string> <!-- final -->
-    <!-- 5 Datashare -->
-    <!-- XHED: onboarding(datashare) - about positive tests-->
-    <string name="onboarding_notifications_headline">Warnungen erhalten, Risiken erkennen</string> <!-- final -->
+    <string name="onboarding_test_body">Ihre Mitteilung wird zuverlässig verschlüsselt über einen sicheren Server weiterverarbeitet. Die Personen, deren verschlüsselte Zufallscodes Sie gesammelt haben, erhalten nun eine Warnung und Informationen darüber, wie sie weiter vorgehen sollen.</string>
+    <!-- XHED: onboarding(datashare) - about positive tests -->
+    <string name="onboarding_notifications_headline">Warnungen erhalten, Risiken erkennen</string>
     <!-- XHED: onboarding(datashare) - two/three line headline under an illustration -->
-    <string name="onboarding_notifications_subtitle">Die App kann Sie automatisch über Ihren Risikostatus informieren und bei Neuinfektionen von Menschen, denen Sie begegnet sind, warnen. Erlauben Sie der App jetzt, Sie zu benachrichtigen.</string> <!-- final -->
+    <string name="onboarding_notifications_subtitle">Die App kann Sie automatisch über Ihren Risikostatus informieren und bei Neuinfektionen von Menschen, denen Sie begegnet sind, warnen. Erlauben Sie der App jetzt, Sie zu benachrichtigen.</string>
     <!-- YTXT: onboarding(datashare) - explain test -->
-    <string name="onboarding_notifications_body">Auf diese Weise können Sie sich zum Schutz Ihrer Mitmenschen in Isolation begeben und nach entsprechender Abklärung testen lassen.</string> <!-- final -->
+    <string name="onboarding_notifications_body">Auf diese Weise können Sie sich zum Schutz Ihrer Mitmenschen in Isolation begeben und nach entsprechender Abklärung testen lassen.</string>
 
     <!-- ####################################
                   Settings
     ###################################### -->
+
+    <!-- XHED: settings - settings overview page title -->
     <string name="settings_title">Einstellungen</string>
+    <!-- XTXT: settings - on, like a label next to a setting -->
     <string name="settings_on">An</string>
+    <!-- XTXT: settings - off, like a label next to a setting -->
     <string name="settings_off">Aus</string>
-    <!-- Tracing -->
+    <!-- XHED: settings(tracing) - page title -->
     <string name="settings_tracing_title">Risiko-Ermittlung</string>
-    <string name="settings_tracing_headline">Aktivieren Sie die Aufzeichnung Ihrer Begegnungen</string>
-    <string name="settings_tracing_body_description">Erlauben Sie Erfassung und Weitergabe von Covid-19-Zufalls-IDs.</string>
-    <string name="settings_tracing_body_active">Risiko-Ermittlung Aktiv</string>
-    <string name="settings_tracing_body_inactive">Risiko-Ermittlung Gestoppt</string>
-    <string name="settings_tracing_body_active_description">Risiko-Ermittlung ist aktiv. Eine verlässliche Risikoprüfung kann nur mit dauerhaft aktivierter Risiko-Ermittlung durchgeführt werden.</string>
-    <string name="settings_tracing_body_inactive_description">Risiko-Ermittlung ist gestoppt. Eine verlässliche Risikoprüfung kann nur mit dauerhaft aktivierter Risiko-Ermittlung durchgeführt werden.</string>
-    <string name="settings_tracing_body_text">@string/lorem_ipsum</string>
+    <!-- XHED: settings(tracing) - headline bellow illustration -->
+    <string name="settings_tracing_headline">So funktioniert die Aufzeichnung Ihrer Begegnungen</string>
+    <!-- XTXT: settings(tracing) - explain text in settings overview under headline -->
+    <string name="settings_tracing_body_description">Erlauben Sie die Aufzeichnung und Weitergabe von Zufallcodes.</string>
+    <!-- XTXT: settings(tracing) - shows status under header in home, active -->
+    <string name="settings_tracing_body_active">Risiko-Ermittlung aktiv</string>
+    <!-- XTXT: settings(tracing) - shows status under header in home, inactive -->
+    <string name="settings_tracing_body_inactive">Risiko-Ermittlung gestoppt</string>
+    <!-- YTXT: settings(tracing) - explains tracings -->
+    <string name="settings_tracing_body_text">Um zu erkennen, ob für Sie ein Ansteckungsrisiko vorliegt, müssen Sie die Risiko-Ermittlung aktivieren. Die Risiko- Ermittlung funktioniert, indem Ihr Handy per Bluetooth verschlüsselte Zufallscodes anderer Nutzerinnen und Nutzer empfängt und Ihren eigenen Zufallscode an deren Smartphones weitergibt. Die Funktion lässt sich jederzeit wieder deaktivieren.<xliff:g id="line_break">\n</xliff:g><xliff:g id="line_break">\n</xliff:g>Die verschlüsselten Zufallscodes geben nur Auskunft über das Datum, die Dauer und die anhand der Signalstärke berechnete Entfernung zu Ihren Mitmenschen. Persönliche Daten wie Name, Adresse oder Aufenthaltsort werden zu keiner Zeit erfasst. Konkrete Rückschlüsse auf Personen sind nicht möglich.</string>
+    <!-- XTXT: settings(tracing) - status next to switch under title -->
     <string name="settings_tracing_status_active">Aktiv</string>
+    <!-- XTXT: settings(tracing) - status next to switch under title -->
     <string name="settings_tracing_status_inactive">Gestoppt</string>
+    <!-- XTXT: settings(tracing) - status next to switch under title -->
     <string name="settings_tracing_status_restricted">Eingeschränkt</string>
+    <!-- XTXT: settings(tracing) - shows status under header in home, no internet -->
     <string name="settings_tracing_body_connection_inactive">Keine Internetverbindung</string>
+    <!-- XTXT: settings(tracing) - shows status under header in home, no bluetooth -->
     <string name="settings_tracing_body_bluetooth_inactive">Bluetooth deaktiviert</string>
+    <!--XHED : settings(tracing) - headline on card about the current status and what to do -->
     <string name="settings_tracing_status_bluetooth_headline">Bluetooth aktivieren</string>
-    <string name="settings_tracing_status_bluetooth_body">Die Risiko-Ermittlung benötigt aktiviertes Bluetooth um Begegnungen zu protokollieren. Bitte aktivieren Sie Bluetooth in Ihren Einstellungen.</string>
-    <string name="settings_tracing_status_bluetooth_button">Einstellungen öffnen</string>
-    <string name="settings_tracing_status_connection_headline">Internetverbindung aktivieren</string>
-    <string name="settings_tracing_status_connection_body">Die Risiko-Ermittlung benötigt eine Internetverbindung um Risikobegegnungen berechnen zu können. Bitte aktivieren Sie WLAN oder Mobile Daten in Ihren Einstellungen.</string>
-    <string name="settings_tracing_status_connection_button">Einstellungen öffnen</string>
-    <string name="settings_tracing_status_body_active">Risiko-Ermittlung ist seit %1$s Tagen aktiv.</string>
-    <string name="settings_tracing_status_body_inactive">Die Risiko-Ermittlung umfasst %1$s von 14 Tagen.</string>
-    <!-- Notifications -->
-    <string name="settings_notifications_title">Mitteilungen</string>
-    <string name="settings_notifications_headline_active">Möchten Sie Mitteilungen zu Ihrem Covid-19-Risikostatus aktivieren?</string>
-    <string name="settings_notifications_headline_inactive">Mitteilungen sind deaktiviert</string>
-    <string name="settings_notifications_body_description">Erlauben Sie automatische Mitteilungen zu Covid-19-Risikostatus.</string>
+    <!-- XTXT: settings(tracing) - explains user what to do on card if bluetooth is disabled -->
+    <string name="settings_tracing_status_bluetooth_body">Die Risiko-Ermittlung benötigt aktiviertes Bluetooth, um Begegnungen aufzuzeichnen. Bitte aktivieren Sie Bluetooth in Ihren Geräte-Einstellungen.</string>
+    <!-- XBUT: settings(tracing) - go to operating system settings button on card -->
+    <string name="settings_tracing_status_bluetooth_button">Geräte-Einstellungen öffnen</string>
+    <!--XHED : settings(tracing) - headline on card about the current status and what to do -->
+    <string name="settings_tracing_status_connection_headline">Internetverbindung herstellen</string>
+    <!-- XTXT: settings(tracing) - explains user what to do on card if connection is disabled -->
+    <string name="settings_tracing_status_connection_body">Die Risiko-Ermittlung benötigt eine Internetverbindung, um Risiko-Begegnungen berechnen zu können. Bitte aktivieren Sie WLAN oder mobile Daten in Ihren Geräte-Einstellungen.</string>
+    <!-- XBUT: settings(tracing) - go to operating system settings button on card -->
+    <string name="settings_tracing_status_connection_button">Geräte-Einstellungen öffnen</string>
+    <!-- XTXT: settings(tracing) - explains the circle progress indicator to the right with the current value -->
+    <plurals name="settings_tracing_status_body_active">
+        <item quantity="one">Die Risiko-Ermittlung ist seit insgesamt einem Tag aktiv. Eine verlässliche Risiko-Überprüfung kann nur mit einer dauerhaft aktivierten Risiko-Ermittlung erfolgen.</item>
+        <item quantity="other">Die Risiko-Ermittlung ist seit insgesamt %1$s Tagen aktiv. Eine verlässliche Risiko-Überprüfung kann nur mit einer dauerhaft aktivierten Risiko-Ermittlung erfolgen.</item>
+    </plurals>
+    <!-- XHED: settings(notification) - notification page title -->
+    <string name="settings_notifications_title">Benachrichtigungen</string>
+    <!-- XHED: settings(notification) - multiline headline below illustration, active -->
+    <string name="settings_notifications_headline_active">Möchten Sie Benachrichtigungen zu Ihrem Covid-19-Risikostatus aktivieren?</string>
+    <!-- XHED: settings(notification) - multiline headline below illustration, inactive -->
+    <string name="settings_notifications_headline_inactive">Benachrichtigungen sind ausgestellt</string>
+    <!-- XTXT: settings(notification) - text in row on settings overview -->
+    <string name="settings_notifications_body_description">Erlauben Sie automatische Benachrichtigungen zu Covid-19-Risikostatus.</string>
     <string name="settings_notifications_body_active">Legen Sie fest, zu welchen Themen Sie informiert beiben möchten.</string>
-    <string name="settings_notifications_body_inactive">Um Mitteilungen zu aktivieren, müssen Sie Mitteilungen für die Corona-Warn-App in Ihren Telefoneinstellungen zulassen.</string>
-    <string name="settings_notifications_subtitle_notification">@string/settings_notifications_title</string>
-    <string name="settings_notifications_subtitle_update_risk">Ändern Ihres Infektionsrisikos</string>
+    <!-- XTXT: settings(notification) - explains what the user has to do to activate settings -->
+    <string name="settings_notifications_body_inactive">Um Benachrichtigungen zu aktivieren, müssen Sie Benachrichtigungen für die Corona-Warn-App in Ihren Geräte-Einstellungen zulassen.</string>
+    <!-- XHED: settings - notification headline on settings overview -->
+    <string name="settings_notifications_subtitle_notification">Benachrichtigungen</string>
+    <!-- XTXT: settings(notification) - next to a switch -->
+    <string name="settings_notifications_subtitle_update_risk">Änderungen Ihres Infektionsrisikos</string>
+    <!-- XTXT: settings(notification) - next to a switch -->
     <string name="settings_notifications_subtitle_update_test">Status Ihres COVID-19-Tests</string>
-    <string name="settings_notifications_subtitle_update_news">Update zu COVID-19</string>
-    <string name="settings_notifications_subtitle_update_app">Neue App Funktionen</string>
-    <string name="settings_notifications_button_open_settings">Einstellungen öffnen</string>
-    <!-- Reset-->
+    <!-- XBUT: settings(notification) - go to operating settings -->
+    <string name="settings_notifications_button_open_settings">Geräte-Einstellungen öffnen</string>
+    <!-- XBUT: settings - go to reset application -->
     <string name="settings_reset_title">Anwendung zurücksetzen</string>
+    <!-- XTXT: settings(reset) - explains the user what do expect when he navigates to reset -->
     <string name="settings_reset_body_description">Löschen Sie alle Ihre Daten in der App.</string>
+    <!-- XHED: settings(reset) - multiline headline below illustration -->
     <string name="settings_reset_headline">Sind Sie sicher, dass Sie die Anwendung zurücksetzen wollen?</string>
+    <!-- XTXT: settings(reset) - explains the consequences -->
     <string name="settings_reset_body">Sie werden nicht mehr über Ihre Risiko-Begegnungen informiert und können andere Nutzerinnen und Nutzer nicht mehr warnen.</string>
+    <!-- XHED: settings(reset) - on card, explains user to go to the operating system settings -->
     <string name="settings_reset_headline_keys">Begegnungs-<xliff:g id="line_break">\n</xliff:g>Aufzeichnungen löschen</string>
+    <!-- XTXT: settings(reset) - on card -->
     <string name="settings_reset_body_keys">Die Begegnungs-Aufzeichnung muss separat in den Geräte Einstellungen gelöscht werden.</string>
+    <!-- XBUT: settings(reset) - triggers reset -->
     <string name="settings_reset_button_positive">Anwendung zurücksetzen</string>
+    <!-- XBUT: settings(reset) - cancel reset and navigates the suer back to the settings -->
     <string name="settings_reset_button_negative">Abbrechen</string>
 
     <!-- ####################################
                App Information
     ###################################### -->
+
     <!-- XHED: Page title for menu information page -->
-    <string name="information_title">App-Informationen</string>  <!-- final -->
+    <string name="information_title">App-Informationen</string>
+    <!-- XTXT: Version information text -->
     <string name="information_version">Version: %1s</string>
     <!-- XHED: Page title for about information page, also menu item / button text -->
-    <string name="information_about_title">Ãœber die App</string>  <!-- final -->
+    <string name="information_about_title">Ãœber die App</string>
     <!-- XHED: Subtitle for about information page -->
-    <string name="information_about_headline">Gemeinsam Corona bekämpfen</string> <!-- final -->
+    <string name="information_about_headline">Gemeinsam Corona bekämpfen</string>
     <!-- YTXT: Body text for about information page -->
-    <string name="information_about_body_emphasized">Das Robert Koch-Institut (RKI) als zentrale Einrichtung des Bundes im Bereich der Öffentlichen Gesundheit und als nationalesPublic-Health-Institut veröffentlicht die Corona-Warn-App für die gesamte Bundesregierung. Die App ist die digitale Ergänzung zu Abstandhalten, Hygiene und Alltagsmaske.</string> <!-- final -->
+    <string name="information_about_body_emphasized">Das Robert Koch-Institut (RKI) als zentrale Einrichtung des Bundes im Bereich der Öffentlichen Gesundheit und als nationalesPublic-Health-Institut veröffentlicht die Corona-Warn-App für die gesamte Bundesregierung. Die App ist die digitale Ergänzung zu Abstandhalten, Hygiene und Alltagsmaske.</string>
     <!-- YTXT: Body text for about information page -->
-    <string name="information_about_body">Wer sie nutzt, hilft, Infektionsketten schnell nachzuverfolgen und zu durchbrechen. Die App speichert dezentral – auf Ihrem Smartphone –  Begegnungen mit anderen.Sie werden informiert, wenn Sie Kontakt mit nachweislich infizierten Personen hatten.Ihre Privatsphärebleibt dabeibestens geschützt.</string> <!-- final -->
+    <string name="information_about_body">Wer sie nutzt, hilft, Infektionsketten schnell nachzuverfolgen und zu durchbrechen. Die App speichert dezentral – auf Ihrem Smartphone –  Begegnungen mit anderen.Sie werden informiert, wenn Sie Kontakt mit nachweislich infizierten Personen hatten.Ihre Privatsphärebleibt dabeibestens geschützt.</string>
     <!-- XHED: Page title for privacy information page, also menu item / button text -->
-    <string name="information_privacy_title">Datenschutzinformation</string> <!-- final -->
+    <string name="information_privacy_title">Datenschutzinformation</string>
     <string name="information_privacy_headline">@string/lorem_ipsum</string>
     <!-- XHED: Page title for terms of use information page, also menu item / button text -->
-    <string name="information_terms_title">Nutzungsbedingungen</string> <!-- final -->
+    <string name="information_terms_title">Nutzungsbedingungen</string>
     <string name="information_terms_headline">@string/lorem_ipsum</string>
     <!-- XHED: Page title for technical contact and hotline information page, also menu item / button text -->
-    <string name="information_contact_title">Technische Hotline</string> <!-- final -->
+    <string name="information_contact_title">Technische Hotline</string>
     <!-- XHED: Subtitle for technical contact and hotline information page -->
-    <string name="information_contact_headline">Wie können wir Ihnen helfen?</string> <!-- final -->
+    <string name="information_contact_headline">Wie können wir Ihnen helfen?</string>
     <!-- YTXT: Body text for technical contact and hotline information page -->
-    <string name="information_contact_body">Für technische Fragen rund um die Corona-Warn-App können Sie sich direkt an unsere  technische Hotline wenden.</string> <!-- final -->
+    <string name="information_contact_body">Für technische Fragen rund um die Corona-Warn-App können Sie sich direkt an unsere  technische Hotline wenden.</string>
     <!-- XHED: Subtitle for technical contact and hotline information page -->
-    <string name="information_contact_subtitle_phone">Technische Hotline:</string> <!-- final -->
+    <string name="information_contact_subtitle_phone">Technische Hotline:</string>
     <!-- XLNK: Button / hyperlink to phone call for technical contact and hotline information page -->
-    <string name="information_contact_button_phone">+49 (0)800 7540001</string> <!-- final -->
+    <string name="information_contact_button_phone">+49 (0)800 7540001</string>
+    <!-- MOTR todo phone number to be called replace in english file-->
+    <string name="information_contact_phone_call_number">tel:+49 800 7540001</string>
     <!-- XTXT: Body text for technical contact and hotline information page -->
-    <string name="information_contact_body_phone">Unser Kundenservice ist für Sie da.</string> <!-- final -->
+    <string name="information_contact_body_phone">Unser Kundenservice ist für Sie da.</string>
     <!-- YTXT: Body text for technical contact and hotline information page -->
-    <string name="information_contact_body_open">Unsere Öffnungszeiten:<xliff:g id="line_break">\n</xliff:g>Mo – Fr: 08:00 – 22:00 Uhr<xliff:g id="line_break">\n</xliff:g>Sa – So: 10:00 – 22:00 Uhr<xliff:g id="line_break">\n</xliff:g>Es gelten die Preise Ihres Telefonanbieters.</string> <!-- final -->
+    <string name="information_contact_body_open">Unsere Öffnungszeiten:<xliff:g id="line_break">\n</xliff:g>Mo – Fr: 08:00 – 22:00 Uhr<xliff:g id="line_break">\n</xliff:g>Sa – So: 10:00 – 22:00 Uhr<xliff:g id="line_break">\n</xliff:g>Es gelten die Preise Ihres Telefonanbieters.</string>
     <!-- YTXT: Body text for technical contact and hotline information page -->
-    <string name="information_contact_body_other">Für gesundheitliche Fragen, wenden Sie sich bitte an Ihre Hausarztpraxis oder die Hotline des ärztlichen Bereitschaftsdienstes 116 117.</string> <!-- final -->
+    <string name="information_contact_body_other">Für gesundheitliche Fragen, wenden Sie sich bitte an Ihre Hausarztpraxis oder die Hotline des ärztlichen Bereitschaftsdienstes 116 117.</string>
     <!-- XLNK: Menu item / hyper link / button text for navigation to FAQ website -->
-    <string name="information_help_title">Häufige Fragen</string> <!-- final -->
+    <string name="information_help_title">Häufige Fragen</string>
     <!-- XHED: Page title for technical information page, also menu item / button text -->
-    <string name="information_technical_title">Rechtliche Hinweise</string> <!-- final -->
+    <string name="information_technical_title">Rechtliche Hinweise</string>
     <string name="information_technical_headline">FTP/SFTP/FTPS client uses libs</string>
     <!-- XHED: Page title for legal information page, also menu item / button text -->
-    <string name="information_legal_title">Impressum</string> <!-- final -->
+    <string name="information_legal_title">Impressum</string>
     <string name="information_legal_headline">Herausgeber</string>
     <string name="information_legal_body">SAP Deutschland SE &amp; Co. KG \n \nHauptsitz: \nSAP Deutschland SE &amp; Co. KG \nHasso-Plattner-Ring 7 \n69190 Walldorf </string>
 
     <!-- ####################################
              Submission
     ###################################### -->
+
     <!-- Permission Rationale Dialog -->
     <string name="submission_qr_code_scan_permission_rationale_dialog_headline">Kamera Berechtigung benötigt</string>
     <string name="submission_qr_code_scan_permission_rationale_dialog_body">Bitte erlauben Sie die Autorisierung der Kamera für das Scannen von QR-Codes.</string>
-
     <string name="submission_qr_code_scan_permission_rationale_dialog_button_positive">Erlauben</string>
     <string name="submission_qr_code_scan_permission_rationale_dialog_button_negative">Nicht erlauben</string>
 
     <!-- QR Code Scan Successful Dialog -->
     <string name="submission_qr_code_scan_successful_dialog_headline">Scan erfolgreich</string>
     <string name="submission_qr_code_scan_successful_dialog_body">Der QR-Code wurde erfolgreich gescannt</string>
-
     <string name="submission_qr_code_scan_successful_dialog_button_positive">Registrieren</string>
     <string name="submission_qr_code_scan_successful_dialog_button_negative">Abbrechen</string>
+
     <!-- QR Code Scan Invalid Dialog -->
     <string name="submission_qr_code_scan_invalid_dialog_headline">Falscher QR Code</string>
     <string name="submission_qr_code_scan_invalid_dialog_body">Es scheint, dass der falsche QR-Code gescannt wurde</string>
-
     <string name="submission_qr_code_scan_invalid_dialog_button_positive">Erneut versuchen</string>
     <string name="submission_qr_code_scan_invalid_dialog_button_negative">Abbrechen</string>
+
     <!-- QR Code Scan Screen -->
+    <!-- YTXT: instruction text for QR code scanning  -->
     <string name="submission_qr_code_scan_body">Positionieren Sie den QR Code in den Rahmen</string>
+
     <!-- Register Device Screen -->
     <string name="submission_register_device_headline">Gerät Registrieren</string>
     <string name="submission_register_device_body">@string/lorem_ipsum</string>
+
     <!-- Submission Test Result -->
-    <string name="submission_test_result_headline">Test-Ergebnis</string> <!--final -->
-    <string name="submission_test_result_subtitle">Info zum Ablauf:</string> <!-- final -->
+    <!-- XHED: Page headline for test result  -->
+    <string name="submission_test_result_headline">Test-Ergebnis</string>
+    <!-- XHED: Page subheadline for test result  -->
+    <string name="submission_test_result_subtitle">Info zum Ablauf:</string>
+    <!-- XBUT:  test result submission - finish button -->
     <string name="submission_test_result_button_finish">Abschließen</string>
-
-    <string name="submission_test_result_steps_added_heading">Test erfolgreich hinzugefügt</string> <!-- final -->
-    <string name="submission_test_result_steps_added_body">Ihr Test wurde in der Corona-Warn-App hinterlegt.</string> <!-- final -->
-
-    <string name="submission_test_result_pending_steps_waiting_heading">Test-Ergebnis noch nicht verfügbar</string> <!-- final -->
-    <string name="submission_test_result_pending_steps_waiting_body">Ihr Test-Ergebnis steht noch nicht zur Verfügung.</string> <!-- final -->
-    <string name="submission_test_result_pending_refresh_button">Aktualisieren</string> <!-- final -->
-    <string name="submission_test_result_pending_remove_test_button">Test entfernen</string> <!-- final -->
-
-    <string name="submission_test_result_negative_steps_negative_heading">Ihr Test-Ergebnis</string> <!-- final -->
-    <string name="submission_test_result_negative_steps_negative_body">Der Labortest hat keinen Nachweis für das Coronavirus SARS-CoV-2 bei Ihnen ergeben. \n\nBitte entfernen Sie den Test wieder aus der Corona-Warn-App, damit Sie bei Bedarf einen neuen Test hinterlegen können.</string> <!-- final -->
-    <string name="submission_test_result_negative_remove_test_button">Test entfernen</string> <!-- final -->
-
-    <string name="submission_test_result_positive_steps_positive_heading">Ihr Test-Ergebnis</string> <!-- final -->
-    <string name="submission_test_result_positive_steps_positive_body">Ihr Test-Ergebnis wurde erfolgreich als “Positiv” verifiziert.</string> <!-- final -->
-    <string name="submission_test_result_positive_steps_warning_others_heading">Andere warnen</string> <!-- final -->
-    <string name="submission_test_result_positive_steps_warning_others_body">Ihre Zufallscodes der letzten 14 Tage teilen, um andere zu schützen und die Infektionskette zu unterbrechen.</string> <!-- final -->
-    <string name="submission_test_result_positive_continue_button">Weiter</string> <!-- final -->
-
-    <string name="submission_test_result_invalid_steps_invalid_heading">Ihr Test-Ergebnis</string> <!-- final -->
-    <string name="submission_test_result_invalid_steps_invalid_body">Es gab ein Problem bei der Auswertung Ihres Tests. Bitte kontaktieren Sie das Gesundheitsamt um Information zum weiteren Vorgehen zu erhalten. Bitte entfernen Sie den Test wieder aus der Corona-Warn-App, damit Sie bei Bedarf einen neuen Test hinterlegen können.</string> <!-- final -->
-    <string name="submission_test_result_invalid_remove_test_button">Test entfernen</string> <!-- final -->
-
+    <!-- XHED: Page headline for results next steps  -->
+    <string name="submission_test_result_steps_added_heading">Test erfolgreich hinzugefügt</string>
+    <!-- YTXT: Body text for for results next steps  -->
+    <string name="submission_test_result_steps_added_body">Ihr Test wurde in der Corona-Warn-App hinterlegt.</string>
+    <!-- XHED: Page headline for pending test result next steps  -->
+    <string name="submission_test_result_pending_steps_waiting_heading">Test-Ergebnis noch nicht verfügbar</string>
+    <!-- YTXT: Body text for next steps section of waiting test result page -->
+    <string name="submission_test_result_pending_steps_waiting_body">Ihr Test-Ergebnis steht noch nicht zur Verfügung.</string>
+    <!-- XBUT: test result pending : refresh button -->
+    <string name="submission_test_result_pending_refresh_button">Aktualisieren</string>
+    <!-- XBUT: test result pending : remove the test button -->
+    <string name="submission_test_result_pending_remove_test_button">Test entfernen</string>
+    <!-- XHED: Page headline for negative test result next steps  -->
+    <string name="submission_test_result_negative_steps_negative_heading">Ihr Test-Ergebnis</string>
+    <!-- YTXT: Body text for next steps section of test negative result -->
+    <string name="submission_test_result_negative_steps_negative_body">Der Labortest hat keinen Nachweis für das Coronavirus SARS-CoV-2 bei Ihnen ergeben. \n\nBitte entfernen Sie den Test wieder aus der Corona-Warn-App, damit Sie bei Bedarf einen neuen Test hinterlegen können.</string>
+    <!-- XBUT: negative test result : remove the test button -->
+    <string name="submission_test_result_negative_remove_test_button">Test entfernen</string>
+    <!-- XHED: Page headline for positive test result screen  -->
+    <string name="submission_test_result_positive_steps_positive_heading">Ihr Test-Ergebnis</string>
+    <!-- YTXT: Body text for next steps section of test positive result-->
+    <string name="submission_test_result_positive_steps_positive_body">Ihr Test-Ergebnis wurde erfolgreich als “Positiv” verifiziert.</string>
+    <!-- XHED: Page headline for other warnings screen  -->
+    <string name="submission_test_result_positive_steps_warning_others_heading">Andere warnen</string>
+    <!-- YTXT: Body text for for other warnings screen-->
+    <string name="submission_test_result_positive_steps_warning_others_body">Ihre Zufallscodes der letzten 14 Tage teilen, um andere zu schützen und die Infektionskette zu unterbrechen.</string>
+    <!-- XBUT: positive test result : continue button -->
+    <string name="submission_test_result_positive_continue_button">Weiter</string>
+    <!-- XHED: Page headline for invalid test result screen  -->
+    <string name="submission_test_result_invalid_steps_invalid_heading">Ihr Test-Ergebnis</string>
+    <!-- YTXT: Body text for next steps section of invalid test result-->
+    <string name="submission_test_result_invalid_steps_invalid_body">Es gab ein Problem bei der Auswertung Ihres Tests. Bitte kontaktieren Sie das Gesundheitsamt um Information zum weiteren Vorgehen zu erhalten. Bitte entfernen Sie den Test wieder aus der Corona-Warn-App, damit Sie bei Bedarf einen neuen Test hinterlegen können.</string>
+    <!-- XBUT: invalid test result : remove the test button -->
+    <string name="submission_test_result_invalid_remove_test_button">Test entfernen</string>
+    <!-- XHED: Dialog title for tracing required dailog  -->
     <string name="submission_test_result_dialog_tracing_required_title">Risiko-Ermittlung erforderlich</string>
+    <!-- YTXT: Dialog text for tracing required dialog-->
     <string name="submission_test_result_dialog_tracing_required_message">Bitte aktivieren Sie die Risiko-Ermittlung um andere zu warnen.</string>
+    <!-- XBUT: tracing required : OK button -->
     <string name="submission_test_result_dialog_tracing_required_button">OK</string>
 
     <!-- Submission Tan -->
-    <string name="submission_tan_title">TAN Eingabe</string> <!-- final -->
-    <string name="submission_tan_body">Die TAN ist 7-stellig und Groß- und Kleinschreibung muss nicht beachtet werden.</string> <!-- final -->
-    <string name="submission_tan_button_text">Weiter</string> <!-- final -->
+    <!-- XHED: Page title for TAN submission pge -->
+    <string name="submission_tan_title">TAN Eingabe</string>
+    <!-- YTXT: Body text for the tan submission page -->
+    <string name="submission_tan_body">Die TAN ist 7-stellig und Groß- und Kleinschreibung muss beachtet werden.\n\nGeben Sie bitte die Ihnen mitgeteilte TAN ein:</string>
+    <!-- XBUT: Submit TAN button -->
+    <string name="submission_tan_button_text">Weiter</string>
+
     <!-- Submission Intro -->
+    <!-- XHED: Page title for menu at the start of the submission process  -->
     <string name="submission_intro_title">Wurden Sie getestet?</string>
-    <string name="submission_intro_headline">So funktionert das Corona-Warn-System</string> <!-- final -->
-    <string name="submission_intro_text_a">Damit die Corona-Warn-App funktioniert, sind wir auf die Mithilfe von Corona-positiven Personen angewiesen.</string> <!-- final -->
-    <string name="submission_intro_text_b">Da nur verschlüsselte Zufallscodes ausgetauscht werden, bleiben Sie unerkannt. Sie können jetzt wie folgt vorgehen:</string> <!-- final -->
-    <string name="submission_intro_button_next">Weiter</string> <!-- final -->
+    <!-- XHED: Page headline for menu the at start of the submission process  -->
+    <string name="submission_intro_headline">So funktionert das Corona-Warn-System</string>
+    <!-- YTXT: submission introduction text part 1 -->
+    <string name="submission_intro_text_a">Damit die Corona-Warn-App funktioniert, sind wir auf die Mithilfe von Corona-positiven Personen angewiesen.</string>
+    <!-- YTXT: submission introduction text part 2 -->
+    <string name="submission_intro_text_b">Da nur verschlüsselte Zufallscodes ausgetauscht werden, bleiben Sie unerkannt. Sie können jetzt wie folgt vorgehen:</string>
+    <!-- XBUT: Submission introduction next button-->
+    <string name="submission_intro_button_next">Weiter</string>
+
     <!-- Notification -->
+    <!-- XHED: Dialog headline for result dialog  -->
     <string name="submission_result_dialog_headline">Danke für die Mithilfe!</string>
+    <!-- YTXT: Body text for result dialog -->
     <string name="submission_result_dialog_body">Ihr verifizierter Befund wurde anonym übertragen.</string>
 
     <!-- Dispatcher -->
-    <string name="submission_dispatcher_headline">Auswahl</string> <!-- final -->
-
-    <string name="submission_dispatcher_subheadline">Welche Informationen liegen Ihnen vor?</string> <!-- final -->
-    <string name="submission_dispatcher_card_qr">Dokument mit QR-Code</string> <!-- final -->
-    <string name="submission_dispatcher_qr_card_text">Registrieren Sie Ihren Test, indem Sie den QR-Code ihres Test-Dokument scannen</string> <!-- final -->
-
+    <!-- XHED: Page headline for dispatcher menu  -->
+    <string name="submission_dispatcher_headline">Auswahl</string>
+    <!-- XHED: Page subheadline for dispatcher menu  -->
+    <string name="submission_dispatcher_subheadline">Welche Informationen liegen Ihnen vor?</string>
+    <!-- YTXT: Dispatcher text for QR code option -->
+    <string name="submission_dispatcher_card_qr">Dokument mit QR-Code</string>
+    <!-- YTXT: Body text for QR code dispatcher option -->
+    <string name="submission_dispatcher_qr_card_text">Registrieren Sie Ihren Test, indem Sie den QR-Code ihres Test-Dokument scannen</string>
+    <!-- XHED: Dialog headline for dispatcher QR prviacy dialog  -->
     <string name="submission_dispatcher_qr_privacy_dialog_headline">Datenschutz</string>
     <string name="submission_dispatcher_qr_privacy_dialog_body">@string/lorem_ipsum</string>
+    <!-- XBUT: submission(dispatcher QR Dialog) - positive button (right) -->
     <string name="submission_dispatcher_qr_privacy_dialog_button_positive">Erlauben</string>
+    <!-- XBUT: submission(dispatcher QR Dialog) - negative button (left) -->
     <string name="submission_dispatcher_qr_privacy_dialog_button_negative">Nicht Erlauben</string>
-
-    <string name="submission_dispatcher_card_tan_code">TAN-Code</string> <!-- final -->
-    <string name="submission_dispatcher_tan_code_card_text">Registrieren Sie Ihren Test per manuekker TAN Eingabe</string> <!-- final -->
-
-    <string name="submission_dispatcher_card_tan_tele">Noch keine TAN?</string> <!-- final -->
-    <string name="submission_dispatcher_tan_tele_card_text">Bitte rufen Sie uns an, falls Sie Positiv getestet wurden</string> <!-- final -->
+    <!-- YTXT: Dispatcher text for TAN code option -->
+    <string name="submission_dispatcher_card_tan_code">TAN-Code</string>
+    <!-- YTXT: Body text for TAN code dispatcher option -->
+    <string name="submission_dispatcher_tan_code_card_text">Registrieren Sie Ihren Test per manuekker TAN Eingabe</string>
+    <!-- YTXT: Dispatcher text for TELE-TAN option -->
+    <string name="submission_dispatcher_card_tan_tele">Noch keine TAN?</string>
+    <!-- YTXT: Body text for TELE_TAN dispatcher option -->
+    <string name="submission_dispatcher_tan_tele_card_text">Bitte rufen Sie uns an, falls Sie Positiv getestet wurden</string>
 
     <!-- Submission Positive Other Warning -->
-    <string name="submission_positive_other_warning_title">Andere warnen</string> <!-- final -->
-    <string name="submission_positive_other_warning_headline">Helfen Sie mit!</string> <!-- final -->
-    <string name="submission_positive_other_warning_body">Als Nächstes können Sie dafür sorgen, dass das Corona-Warn-System Ihre lokal gespeicherten Zufallscodes der letzten 14 Tage an andere verteilt. So können Sie Ihre Mitmenschen warnen und helfen, die Infektionskette zu unterbrechen. \n\n Da nur unpersönliche Zufallscodes übertragen werden, bleibt Ihre Identität unbekannt.</string> <!-- final -->
+    <!-- XHED: Page title for the positive result additional warning page-->
+    <string name="submission_positive_other_warning_title">Andere warnen</string>
+    <!-- XHED: Page headline for the positive result additional warning page-->
+    <string name="submission_positive_other_warning_headline">Helfen Sie mit!</string>
+    <!-- YTXT: Body text for the positive result additional warning page-->
+    <string name="submission_positive_other_warning_body">Als Nächstes können Sie dafür sorgen, dass das Corona-Warn-System Ihre lokal gespeicherten Zufallscodes der letzten 14 Tage an andere verteilt. So können Sie Ihre Mitmenschen warnen und helfen, die Infektionskette zu unterbrechen. \n\n Da nur unpersönliche Zufallscodes übertragen werden, bleibt Ihre Identität unbekannt.</string>
     <string name="submission_positive_other_warning_data_security_body">+Data-Security Text</string>
-    <string name="submission_positive_other_warning_button">Weiter</string> <!-- final -->
-    <string name="submission_positive_dialog_confirmation_title">Zufalls-IDs mit der App "Corona-Warn" teilen?</string> <!-- final -->
-    <string name="submission_positive_dialog_confirmation_body">Deine zufälligen IDs der letzten 14 Tage werden dazu genutzt, andere darüber zu informieren, dass du in ihrer Nähe gewesen bist und sie daher möglicherweise in Kontakt mit COVID-19 gekommen sind.</string> <!-- final -->
-    <string name="submission_positive_dialog_confirmation_positive">Erlauben</string> <!-- final -->
-    <string name="submission_positive_dialog_confirmation_negative">Nicht erlauben</string> <!-- final -->
+    <!-- XBUT: other warning continue button -->
+    <string name="submission_positive_other_warning_button">Weiter</string>
+    <!-- XHED: Dialog title for positive other warning dialog  -->
+    <string name="submission_positive_dialog_confirmation_title">Zufalls-IDs mit der App "Corona-Warn" teilen?</string>
+    <!-- YTXT: Body text for the positive result confirmation dialog-->
+    <string name="submission_positive_dialog_confirmation_body">Deine zufälligen IDs der letzten 14 Tage werden dazu genutzt, andere darüber zu informieren, dass du in ihrer Nähe gewesen bist und sie daher möglicherweise in Kontakt mit COVID-19 gekommen sind.</string>
+    <!-- XBUT: submission(positive other warning) - positive button (right) -->
+    <string name="submission_positive_dialog_confirmation_positive">Erlauben</string>
+    <!-- XBUT: submission(positive other warning) - negative button (left) -->
+    <string name="submission_positive_dialog_confirmation_negative">Nicht erlauben</string>
 
     <!-- Submission Done -->
-    <string name="submission_done_title">Vielen Dank!</string> <!-- final -->
-    <string name="submission_done_headline">Sie haben einen wichtigen Beitrag geleistet!</string> <!-- final -->
+    <!-- XHED: Page title for completed submission page -->
+    <string name="submission_done_title">Vielen Dank!</string>
+    <!-- XHED: Page subheadline for completed submission page -->
+    <string name="submission_done_headline">Sie haben einen wichtigen Beitrag geleistet!</string>
+    <!-- YTXT: Body text for completed submission page -->
     <string name="submission_done_body">Sie haben einen wichtigen Beitrag geleistet! Dank Ihrer Mithilfe können Andere gewarnt werden und entsprechend reagieren.</string>
+    <!-- XHED: Page subtitle for completed submission page -->
     <string name="submission_done_subtitle">Bitte beachten Sie:</string>
+    <!-- YTXT: text after submission: contagious -->
     <string name="submission_done_contagious">Sie sind ansteckend.</string>
+    <!-- YTXT: text after submission: isolate -->
     <string name="submission_done_isolate">Bitte isolieren Sie sich von anderen Personen.</string>
+    <!-- XBUT: submission finished button -->
     <string name="submission_done_button_done">Fertig</string>
+
     <!-- Submission Contact -->
+    <!-- XHED: Page title for contact page in submission flow -->
     <string name="submission_contact_title">TAN anfragen</string>
+    <!-- XHED: Page headline for contact page in submission flow -->
     <string name="submission_contact_headline">Info zum Ablauf:</string>
+    <!-- YTXT: Body text for contact page in submission flow-->
     <string name="submission_contact_body">Wir teilen Ihnen Ihren TAN-Code gerne per Telefon mit.</string>
+    <!-- XBUT: submission contact call button -->
     <string name="submission_contact_button_call">Anrufen</string>
+    <!-- XBUT: submission contact enter tan button -->
     <string name="submission_contact_button_enter">TAN-Code eingeben</string>
+    <!-- YTXT: Body text for step 1 of contact page -->
     <string name="submission_contact_step_1_body"><![CDATA[Hotline anrufen & TAN erfragen:]]></string>
+    <!-- XLNK: Button / hyperlink to phone call for TAN contact page -->
     <string name="submission_contact_number">0800 7540002</string>
+    <!-- YTXT: Body text for step 2 of contact page-->
     <string name="submission_contact_step_2_body">Test per TAN-Eingabe in der App registrieren</string>
+
     <!-- Submission Status Card -->
+    <!-- XHED: Page title for the various submission status: fetching -->
     <string name="submission_status_card_title_fetching">Datenabruf…</string>
+    <!-- XHED: Page title for the various submission status: unregistered -->
     <string name="submission_status_card_title_unregistered">Wurden Sie getestet?</string>
+    <!-- XHED: Page title for the various submission status: pending -->
     <string name="submission_status_card_title_pending">Ergebnis liegt noch nicht vor</string>
+    <!-- XHED: Page title for the various submission status: available -->
     <string name="submission_status_card_title_available">Ihr Ergebnis liegt vor</string>
+    <!-- YTXT: Body text for submission status: fetching -->
     <string name="submission_status_card_body_fetching">Das Ergebnis wird aktualisiert</string>
+    <!-- YTXT: Body text for submission status: unregistered -->
     <string name="submission_status_card_body_unregistered">Helfen Sie mit, die Infektionskette zu durchbrechen und warnen Sie Andere.</string>
+    <!-- YTXT: Body text for submission status: pending -->
     <string name="submission_status_card_body_pending">Die Auswertung dauert zwischen 1–3 Tagen.</string>
+    <!-- YTXT: Body text for submission status: invalid -->
     <string name="submission_status_card_body_invalid">Ihr test könnte nicht ausgewertet werden.</string>
+    <!-- YTXT: Body text for submission status: positive -->
     <string name="submission_status_card_body_positive">Sie wurden positiv auf SARS-CoV-2 getestet.</string>
+    <!-- YTXT: Body text for submission status: negative -->
     <string name="submission_status_card_body_negative">Sie wurden negativ auf SARS-CoV-2 getestet.</string>
+    <!-- XBUT: submission status card unregistered button -->
     <string name="submission_status_card_button_unregistered">Informieren &amp; mitmachen</string>
+    <!-- XBUT: submission status card show results button -->
     <string name="submission_status_card_button_show_results">Ergebnis anzeigen</string>
+    <!-- XBUT: submission status card show details button -->
     <string name="submission_status_card_button_show_details">Details anzeigen</string>
+    <!-- XHED: submission status card positive result title -->
     <string name="submission_status_card_positive_result_title">Positives Ergebnis</string>
+    <!-- XHED: submission status card positive result subtitle -->
     <string name="submission_status_card_positive_result_subtitle">Bitte beachten Sie:</string>
+    <!-- XBUT: submission status card show positive result button -->
     <string name="submission_status_card_positive_result_show_button">Test-Ergebnis anzeigen</string>
+    <!-- YTXT: text for contagious card -->
     <string name="submission_status_card_positive_result_contagious">@string/submission_done_contagious</string>
+    <!-- YTXT: text for isolate card -->
     <string name="submission_status_card_positive_result_isolate">@string/submission_done_isolate</string>
+    <!-- YTXT: text for share result card-->
     <string name="submission_status_card_positive_result_share">Teilen Sie Ihre Zufallskennungen, damit andere gewarnt werden können.</string>
+
     <!-- Test Result Card -->
     <string name="test_result_card_headline">Ihr Befund:</string>
+    <!-- YTXT: virus name text -->
     <string name="test_result_card_virus_name_text">SARS-CoV-2</string>
+    <!-- YTXT: registered at text -->
     <string name="test_result_card_registered_at_text">Registriert am %tF</string>
+    <!-- YTXT: negative status text -->
     <string name="test_result_card_status_negative">Negativ</string>
+    <!-- YTXT: positive status text -->
     <string name="test_result_card_status_positive">Positiv</string>
+    <!-- YTXT: invalid status text -->
     <string name="test_result_card_status_invalid">Auswertung nicht möglich</string>
+    <!-- YTXT: pending status text -->
     <string name="test_result_card_status_pending">Ergebnis liegt noch nicht vor</string>
 
+    <!-- XBUT: submission result dialog close button -->
+    <string name="submission_result_button_dialog_close">OK</string>
+
+    <!-- ####################################
+               Generic Error Messages
+        ###################################### -->
+    <string name="errors_generic_headline">Etwas ist schief gelaufen</string>
+    <string name="errors_generic_details_headline">Ursache</string>
+    <string name="errors_generic_button_positive">Okay</string>
+    <string name="errors_generic_button_negative">Details</string>
+    <string name="errors_generic_text_unknown_error_cause">Ein unbekanntes Problem ist aufgetreten</string>
 
     <!-- ####################################
            Just for Development
     ###################################### -->
+    <!-- NOTR -->
     <string name="lorem_ipsum">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</string>
     <!-- TODO test fragment only - remove after test fragment is deleted-->
+    <!-- NOTR -->
     <string name="menu_test_api">Test API</string>
+    <!-- NOTR -->
+    <string name="menu_test_risk_level">Test Risk Level</string>
+    <!-- NOTR -->
     <string name="menu_test_notification">Test Notification</string>
+    <!-- NOTR -->
     <string name="test_api_button_api_launch">Android API Test(Manual Test)</string>
+    <!-- NOTR -->
     <string name="test_api_button_start">Start (Broadcast/Receive Bluetooth)</string>
+    <!-- NOTR -->
     <string name="test_api_button_get_exposure_keys">Get Exposure keys (my keys history from api)</string>
+    <!-- NOTR -->
     <string name="test_api_button_share_my_keys">Share my keys via Email</string>
+    <!-- NOTR -->
     <string name="test_api_button_enter_other_keys">Submit Exposure Key</string>
+    <!-- NOTR -->
     <string name="test_api_button_show_qr_code">Show QR Code</string>
+    <!-- NOTR -->
     <string name="test_api_button_submit_keys">Submit keys to Server</string>
+    <!-- NOTR -->
     <string name="test_api_button_scan_qr_code">Scan Exposure Key</string>
+    <!-- NOTR -->
     <string name="test_api_button_check_exposure">Check Exposure Summary</string>
+    <!-- NOTR -->
     <string name="test_api_exposure_summary_headline">Exposure summary</string>
+    <!-- NOTR -->
     <string name="test_api_body_daysSinceLastExposure">Days since last exposure: %1$s</string>
+    <!-- NOTR -->
     <string name="test_api_body_attenuation">Attenuation Durations in Minutes: %1$s</string>
+    <!-- NOTR -->
     <string name="test_api_body_summation_risk">Summation Risk Score: %1$s</string>
+    <!-- NOTR -->
     <string name="test_api_body_matchedKeyCount">Matched key count: %1$s</string>
+    <!-- NOTR -->
     <string name="test_api_body_maximumRiskScore">Maximum risk score %1$s</string>
+    <!-- NOTR -->
     <string name="test_api_body_my_keys">My keys (count: %1$d) </string>
+    <!-- NOTR -->
     <string name="test_api_body_other_keys">Other key </string>
+    <!-- NOTR -->
     <string name="test_api_calculate_risk_level">Calculate Risk Level</string>
 
-    <!-- TODO: Remove or change this placeholder text -->
-    <string name="hello_blank_fragment">Hello blank fragment</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 d520458a6634dfe737b3583cb0f49c77ddb55902..285842c941ed470778d627f6579b51f3755c3ced 100644
--- a/Corona-Warn-App/src/main/res/values/styles.xml
+++ b/Corona-Warn-App/src/main/res/values/styles.xml
@@ -238,7 +238,6 @@
         <item name="android:alpha">0</item>
         <item name="android:background">@null</item>
         <item name="android:inputType">textPassword</item>
-        <item name="android:maxLength">@integer/submission_tan_length</item>
         <item name="android:singleLine">true</item>
     </style>
 
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelCalculationTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelCalculationTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..b4dd3853f5bdd59d5866577ef98ea18b02bd64ec
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/RiskLevelCalculationTest.kt
@@ -0,0 +1,102 @@
+package de.rki.coronawarnapp.risk
+
+import com.google.android.gms.nearby.exposurenotification.ExposureSummary
+import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass
+import junit.framework.TestCase.assertEquals
+import org.junit.Test
+
+class RiskLevelCalculationTest {
+
+    @Test
+    fun calculateRiskScoreZero() {
+        val riskScore =
+            RiskLevelCalculation.calculateRiskScore(
+                buildAttenuationDuration(0.5, 0.5, 1.0),
+                buildSummary(0, 0, 0, 0)
+            )
+
+        assertEquals(0.0, riskScore)
+    }
+
+    @Test
+    fun calculateRiskScoreLow() {
+        val riskScore =
+            RiskLevelCalculation.calculateRiskScore(
+                buildAttenuationDuration(0.5, 0.5, 1.0),
+                buildSummary(156, 10, 10, 10)
+            )
+
+        assertEquals(124.8, riskScore)
+    }
+
+    @Test
+    fun calculateRiskScoreMid() {
+        val riskScore =
+            RiskLevelCalculation.calculateRiskScore(
+                buildAttenuationDuration(0.5, 0.5, 1.0),
+                buildSummary(256, 15, 15, 15)
+            )
+
+        assertEquals(307.2, riskScore)
+    }
+
+    @Test
+    fun calculateRiskScoreHigh() {
+        val riskScore =
+            RiskLevelCalculation.calculateRiskScore(
+                buildAttenuationDuration(0.5, 0.5, 1.0),
+                buildSummary(512, 30, 30, 30)
+            )
+
+        assertEquals(1228.8, riskScore)
+    }
+
+    @Test
+    fun calculateRiskScoreMax() {
+        val riskScore =
+            RiskLevelCalculation.calculateRiskScore(
+                buildAttenuationDuration(0.5, 0.5, 1.0),
+                buildSummary(4096, 30, 30, 30)
+            )
+
+        assertEquals(9830.4, riskScore)
+    }
+
+    private fun buildAttenuationDuration(
+        high: Double,
+        mid: Double,
+        low: Double,
+        norm: Int = 25,
+        offset: Int = 0
+    ): ApplicationConfigurationOuterClass.AttenuationDuration {
+        return ApplicationConfigurationOuterClass.AttenuationDuration
+            .newBuilder()
+            .setRiskScoreNormalizationDivisor(norm)
+            .setDefaultBucketOffset(offset)
+            .setWeights(
+                ApplicationConfigurationOuterClass.Weights
+                    .newBuilder()
+                    .setHigh(high)
+                    .setMid(mid)
+                    .setLow(low)
+                    .build()
+            )
+            .build()
+    }
+
+    private fun buildSummary(
+        maxRisk: Int = 0,
+        lowAttenuation: Int = 0,
+        midAttenuation: Int = 0,
+        highAttenuation: Int = 0
+    ): ExposureSummary {
+        val intArray = IntArray(3)
+        intArray[0] = lowAttenuation
+        intArray[1] = midAttenuation
+        intArray[2] = highAttenuation
+        return ExposureSummary.ExposureSummaryBuilder()
+            .setMaximumRiskScore(maxRisk)
+            .setAttenuationDurations(intArray)
+            .build()
+    }
+}
\ No newline at end of file
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/service/submission/SubmissionServiceTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/service/submission/VerificationServiceTest.kt
similarity index 54%
rename from Corona-Warn-App/src/test/java/de/rki/coronawarnapp/service/submission/SubmissionServiceTest.kt
rename to Corona-Warn-App/src/test/java/de/rki/coronawarnapp/service/submission/VerificationServiceTest.kt
index ed2a111ce2ac1afc9406a23de54c672464b10a62..4d0c06f803f98f441e216e1e6ddaf9723c6c54bf 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/service/submission/SubmissionServiceTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/service/submission/VerificationServiceTest.kt
@@ -1,25 +1,33 @@
 package de.rki.coronawarnapp.service.submission
 
 import org.hamcrest.CoreMatchers.equalTo
-import org.hamcrest.CoreMatchers.nullValue
 import org.hamcrest.MatcherAssert.assertThat
 import org.junit.Test
 
-class SubmissionServiceTest {
+class VerificationServiceTest {
 
     @Test
-    fun extractGUID() {
+    fun containsValidGUID() {
         // valid
         val guid = "123456-12345678-1234-4DA7-B166-B86D85475064"
         assertThat(
-            SubmissionService.extractGUID("https://bs-sd.de/covid-19/?$guid"),
-            equalTo(guid)
+            SubmissionService.containsValidGUID("https://bs-sd.de/covid-19/?$guid"),
+            equalTo(true)
         )
 
         // invalid
         assertThat(
-            SubmissionService.extractGUID("https://no-guid-here"),
-            nullValue()
+            SubmissionService.containsValidGUID("https://no-guid-here"),
+            equalTo(false)
+        )
+    }
+    
+    @Test
+    fun extractGUID() {
+        val guid = "123456-12345678-1234-4DA7-B166-B86D85475064"
+        assertThat(
+            SubmissionService.extractGUID("https://bs-sd.de/covid-19/?$guid"),
+            equalTo(guid)
         )
     }
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/ExposureSummaryRepositoryTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/ExposureSummaryRepositoryTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0fbfc2dcf9d916426dbe26b8fed14690e341295a
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/ExposureSummaryRepositoryTest.kt
@@ -0,0 +1,88 @@
+package de.rki.coronawarnapp.storage
+
+import com.google.android.gms.nearby.exposurenotification.ExposureSummary
+import io.mockk.MockKAnnotations
+import io.mockk.coEvery
+import io.mockk.coVerify
+import io.mockk.every
+import io.mockk.impl.annotations.MockK
+import io.mockk.mockk
+import io.mockk.unmockkAll
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * ExposureSummaryRepository test.
+ */
+class ExposureSummaryRepositoryTest {
+
+    @MockK
+    private lateinit var dao: ExposureSummaryDao
+    private lateinit var repository: ExposureSummaryRepository
+
+    @Before
+    fun setUp() {
+        MockKAnnotations.init(this)
+        repository = ExposureSummaryRepository(dao)
+
+        coEvery { dao.getExposureSummaryEntities() } returns listOf()
+        coEvery { dao.getLatestExposureSummary() } returns null
+        coEvery { dao.insertExposureSummaryEntity(any()) } returns 0
+    }
+
+    /**
+     * Test DAO is called.
+     */
+    @Test
+    fun testGet() {
+        runBlocking {
+            repository.getExposureSummaryEntities()
+
+            coVerify {
+                dao.getExposureSummaryEntities()
+            }
+        }
+    }
+
+    /**
+     * Test DAO is called.
+     */
+    @Test
+    fun testGetLatest() {
+        runBlocking {
+            repository.getLatestExposureSummary()
+
+            coVerify {
+                dao.getLatestExposureSummary()
+            }
+        }
+    }
+
+    /**
+     * Test DAO is called.
+     */
+    @Test
+    fun testInsert() {
+        val es = mockk<ExposureSummary>()
+        every { es.attenuationDurationsInMinutes } returns intArrayOf(0)
+        every { es.daysSinceLastExposure } returns 1
+        every { es.matchedKeyCount } returns 1
+        every { es.maximumRiskScore } returns 0
+        every { es.summationRiskScore } returns 0
+
+        runBlocking {
+            repository.insertExposureSummaryEntity(es)
+
+            coVerify {
+                dao.insertExposureSummaryEntity(any())
+            }
+        }
+    }
+
+    @After
+    fun cleanUp() {
+        unmockkAll()
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/keycache/KeyCacheRepositoryTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/keycache/KeyCacheRepositoryTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..ce1c1fa67bb58461bf2e043b828529892509d3d8
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/keycache/KeyCacheRepositoryTest.kt
@@ -0,0 +1,84 @@
+package de.rki.coronawarnapp.storage.keycache
+
+import io.mockk.MockKAnnotations
+import io.mockk.Runs
+import io.mockk.coEvery
+import io.mockk.coVerify
+import io.mockk.coVerifyOrder
+import io.mockk.impl.annotations.MockK
+import io.mockk.just
+import io.mockk.unmockkAll
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import java.net.URI
+
+/**
+ * KeyCacheRepository test.
+ */
+class KeyCacheRepositoryTest {
+
+    @MockK
+    private lateinit var keyCacheDao: KeyCacheDao
+
+    private lateinit var keyCacheRepository: KeyCacheRepository
+
+    @Before
+    fun setUp() {
+        MockKAnnotations.init(this)
+        keyCacheRepository = KeyCacheRepository(keyCacheDao)
+
+        // DAO tests in another test
+        coEvery { keyCacheDao.getAllEntries() } returns listOf()
+        coEvery { keyCacheDao.getHours() } returns listOf()
+        coEvery { keyCacheDao.clear() } just Runs
+        coEvery { keyCacheDao.clearHours() } just Runs
+        coEvery { keyCacheDao.insertEntry(any()) } returns 0
+    }
+
+    /**
+     * Test clear order.
+     */
+    @Test
+    fun testClear() {
+        runBlocking {
+            keyCacheRepository.clear()
+
+            coVerifyOrder {
+                keyCacheDao.getAllEntries()
+
+                keyCacheDao.clear()
+            }
+        }
+
+        runBlocking {
+            keyCacheRepository.clearHours()
+
+            coVerifyOrder {
+                keyCacheDao.getHours()
+
+                keyCacheDao.clearHours()
+            }
+        }
+    }
+
+    /**
+     * Test insert order.
+     */
+    @Test
+    fun testInsert() {
+        runBlocking {
+            keyCacheRepository.createEntry(key = "1", type = KeyCacheRepository.DateEntryType.DAY, uri = URI("1"))
+
+            coVerify {
+                keyCacheDao.insertEntry(any())
+            }
+        }
+    }
+
+    @After
+    fun cleanUp() {
+        unmockkAll()
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepositoryTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepositoryTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..08b01eca2c4421c12fe6e05715d8c5ac2780db04
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepositoryTest.kt
@@ -0,0 +1,70 @@
+package de.rki.coronawarnapp.storage.tracing
+
+import io.mockk.MockKAnnotations
+import io.mockk.Runs
+import io.mockk.coEvery
+import io.mockk.coVerify
+import io.mockk.impl.annotations.MockK
+import io.mockk.just
+import io.mockk.unmockkAll
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import java.util.Date
+
+/**
+ * TracingIntervalRepository test.
+ */
+class TracingIntervalRepositoryTest {
+
+    @MockK
+    private lateinit var dao: TracingIntervalDao
+    private lateinit var repository: TracingIntervalRepository
+
+    @Before
+    fun setUp() {
+        MockKAnnotations.init(this)
+        repository = TracingIntervalRepository(dao)
+
+        coEvery { dao.deleteOutdatedIntervals(any()) } just Runs
+        coEvery { dao.insertInterval(any()) } just Runs
+        coEvery { dao.getAllIntervals() } returns listOf()
+    }
+
+    /**
+     * Test DAO is called.
+     */
+    @Test
+    fun testCreate() {
+        val today = Date().time
+
+        runBlocking {
+            repository.createInterval(today - 1, today)
+
+            coVerify {
+                dao.insertInterval(any())
+            }
+        }
+    }
+
+    /**
+     * Test DAO is called.
+     */
+    @Test
+    fun testGet() {
+        runBlocking {
+            repository.getIntervals()
+
+            coVerify {
+                dao.deleteOutdatedIntervals(any())
+                dao.getAllIntervals()
+            }
+        }
+    }
+
+    @After
+    fun cleanUp() {
+        unmockkAll()
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/transaction/RiskLevelTransactionTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/transaction/RiskLevelTransactionTest.kt
index 0b7d19b4f90010c6f6d34f67708fea2ac1af2171..83ec19259cf2fb8f836ef85ba7de0a96c403305b 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/transaction/RiskLevelTransactionTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/transaction/RiskLevelTransactionTest.kt
@@ -10,9 +10,10 @@ import de.rki.coronawarnapp.risk.RiskLevel.UNDETERMINED
 import de.rki.coronawarnapp.risk.RiskLevel.UNKNOWN_RISK_INITIAL
 import de.rki.coronawarnapp.risk.RiskLevel.UNKNOWN_RISK_OUTDATED_RESULTS
 import de.rki.coronawarnapp.risk.TimeVariables
+import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass
 import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass.RiskScoreClass
 import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass.RiskScoreClassification
-import de.rki.coronawarnapp.service.riskscoreclassification.RiskScoreClassificationService
+import de.rki.coronawarnapp.service.applicationconfiguration.ApplicationConfigurationService
 import de.rki.coronawarnapp.storage.ExposureSummaryRepository
 import de.rki.coronawarnapp.storage.RiskLevelRepository
 import io.mockk.MockKAnnotations
@@ -40,7 +41,7 @@ class RiskLevelTransactionTest {
         MockKAnnotations.init(this)
 
         mockkObject(InternalExposureNotificationClient)
-        mockkObject(RiskScoreClassificationService)
+        mockkObject(ApplicationConfigurationService)
         mockkObject(RiskLevelRepository)
         mockkObject(RiskLevelTransaction)
         mockkObject(TimeVariables)
@@ -159,13 +160,9 @@ class RiskLevelTransactionTest {
 
         val testRiskLevel = INCREASED_RISK
 
-        val testRiskScoreClassification = buildRiskScoreClassification(
-            2749,
-            2750,
-            4096
-        )
+        val testAppConfig = buildTestAppConfig()
 
-        val testExposureSummary = buildSummary(2751)
+        val testExposureSummary = buildSummary(1600, 0, 30, 15)
 
         // tracing is activated
         coEvery { InternalExposureNotificationClient.asyncIsEnabled() } returns true
@@ -178,7 +175,7 @@ class RiskLevelTransactionTest {
         every { TimeVariables.getTimeActiveTracingDuration() } returns TimeUnit.HOURS.toMillis(2)
 
         // the risk score of the last exposure summary is above the high min threshold
-        coEvery { RiskScoreClassificationService.asyncRetrieveRiskScoreClassification() } returns testRiskScoreClassification
+        coEvery { ApplicationConfigurationService.asyncRetrieveApplicationConfiguration() } returns testAppConfig
         coEvery { esRepositoryMock.getLatestExposureSummary() } returns testExposureSummary
 
         runBlocking {
@@ -197,11 +194,14 @@ class RiskLevelTransactionTest {
                 RiskLevelTransaction["executeCheckUnknownRiskOutdatedResults"]()
                 RiskLevelTransaction["isValidResult"](UNDETERMINED)
 
-                RiskLevelTransaction["executeRetrieveRiskThreshold"]()
+                RiskLevelTransaction["executeRetrieveApplicationConfiguration"]()
 
                 RiskLevelTransaction["executeRetrieveExposureSummary"]()
 
-                RiskLevelTransaction["executeCheckIncreasedRisk"](testRiskScoreClassification, testExposureSummary)
+                RiskLevelTransaction["executeCheckIncreasedRisk"](
+                    testAppConfig,
+                    testExposureSummary
+                )
                 RiskLevelTransaction["isValidResult"](testRiskLevel)
 
                 RiskLevelRepository.setRiskLevelScore(testRiskLevel)
@@ -216,13 +216,9 @@ class RiskLevelTransactionTest {
 
         val testRiskLevel = UNKNOWN_RISK_INITIAL
 
-        val testRiskScoreClassification = buildRiskScoreClassification(
-            2749,
-            2750,
-            4096
-        )
+        val testAppConfig = buildTestAppConfig()
 
-        val testExposureSummary = buildSummary(2749)
+        val testExposureSummary = buildSummary()
 
         val twoHoursBelowMinActiveTracingDuration =
             TimeUnit.HOURS.toMillis(TimeVariables.getMinActivatedTracingTime().minus(2).toLong())
@@ -238,7 +234,7 @@ class RiskLevelTransactionTest {
         every { TimeVariables.getTimeActiveTracingDuration() } returns twoHoursBelowMinActiveTracingDuration
 
         // the exposure summary risk score is not below high min score
-        coEvery { RiskScoreClassificationService.asyncRetrieveRiskScoreClassification() } returns testRiskScoreClassification
+        coEvery { ApplicationConfigurationService.asyncRetrieveApplicationConfiguration() } returns testAppConfig
         coEvery { esRepositoryMock.getLatestExposureSummary() } returns testExposureSummary
 
         runBlocking {
@@ -257,11 +253,14 @@ class RiskLevelTransactionTest {
                 RiskLevelTransaction["executeCheckUnknownRiskOutdatedResults"]()
                 RiskLevelTransaction["isValidResult"](UNDETERMINED)
 
-                RiskLevelTransaction["executeRetrieveRiskThreshold"]()
+                RiskLevelTransaction["executeRetrieveApplicationConfiguration"]()
 
                 RiskLevelTransaction["executeRetrieveExposureSummary"]()
 
-                RiskLevelTransaction["executeCheckIncreasedRisk"](testRiskScoreClassification, testExposureSummary)
+                RiskLevelTransaction["executeCheckIncreasedRisk"](
+                    testAppConfig,
+                    testExposureSummary
+                )
                 RiskLevelTransaction["isValidResult"](UNDETERMINED)
 
                 RiskLevelTransaction["executeCheckUnknownRiskInitialTracingDuration"]()
@@ -279,13 +278,9 @@ class RiskLevelTransactionTest {
 
         val testRiskLevel = LOW_LEVEL_RISK
 
-        val testRiskScoreClassification = buildRiskScoreClassification(
-            2749,
-            2750,
-            4096
-        )
+        val testAppConfig = buildTestAppConfig()
 
-        val testExposureSummary = buildSummary(2749)
+        val testExposureSummary = buildSummary(10)
 
         val twoHoursAboveMinActiveTracingDuration =
             TimeUnit.HOURS.toMillis(TimeVariables.getMinActivatedTracingTime().plus(2).toLong())
@@ -300,7 +295,7 @@ class RiskLevelTransactionTest {
         // the active tracing duration is above the threshold
         every { TimeVariables.getTimeActiveTracingDuration() } returns twoHoursAboveMinActiveTracingDuration
 
-        coEvery { RiskScoreClassificationService.asyncRetrieveRiskScoreClassification() } returns testRiskScoreClassification
+        coEvery { ApplicationConfigurationService.asyncRetrieveApplicationConfiguration() } returns testAppConfig
         coEvery { esRepositoryMock.getLatestExposureSummary() } returns testExposureSummary
 
         runBlocking {
@@ -319,11 +314,14 @@ class RiskLevelTransactionTest {
                 RiskLevelTransaction["executeCheckUnknownRiskOutdatedResults"]()
                 RiskLevelTransaction["isValidResult"](UNDETERMINED)
 
-                RiskLevelTransaction["executeRetrieveRiskThreshold"]()
+                RiskLevelTransaction["executeRetrieveApplicationConfiguration"]()
 
                 RiskLevelTransaction["executeRetrieveExposureSummary"]()
 
-                RiskLevelTransaction["executeCheckIncreasedRisk"](testRiskScoreClassification, testExposureSummary)
+                RiskLevelTransaction["executeCheckIncreasedRisk"](
+                    testAppConfig,
+                    testExposureSummary
+                )
                 RiskLevelTransaction["isValidResult"](UNDETERMINED)
 
                 RiskLevelTransaction["executeCheckUnknownRiskInitialTracingDuration"]()
@@ -340,6 +338,41 @@ class RiskLevelTransactionTest {
         unmockkAll()
     }
 
+    private fun buildTestAppConfig(
+        lowMax: Int = 2749,
+        highMin: Int = 2750,
+        highMax: Int = 4096
+    ): ApplicationConfigurationOuterClass.ApplicationConfiguration {
+        return ApplicationConfigurationOuterClass.ApplicationConfiguration
+            .newBuilder()
+            .setRiskScoreClasses(buildRiskScoreClassification(lowMax, highMin, highMax))
+            .setAttenuationDuration(buildAttenuationDuration())
+            .build()
+    }
+
+    private fun buildAttenuationDuration(): ApplicationConfigurationOuterClass.AttenuationDuration {
+        return ApplicationConfigurationOuterClass.AttenuationDuration
+            .newBuilder()
+            .setRiskScoreNormalizationDivisor(25)
+            .setDefaultBucketOffset(0)
+            .setThresholds(
+                ApplicationConfigurationOuterClass.Thresholds
+                    .newBuilder()
+                    .setLower(50)
+                    .setUpper(70)
+                    .build()
+            )
+            .setWeights(
+                ApplicationConfigurationOuterClass.Weights
+                    .newBuilder()
+                    .setHigh(1.0)
+                    .setMid(1.0)
+                    .setLow(1.0)
+                    .build()
+            )
+            .build()
+    }
+
     private fun buildRiskScoreClassification(
         lowMax: Int,
         highMin: Int,
@@ -369,7 +402,19 @@ class RiskLevelTransactionTest {
             .build()
     }
 
-    private fun buildSummary(maxRisk: Int): ExposureSummary {
-        return ExposureSummary.ExposureSummaryBuilder().setMaximumRiskScore(maxRisk).build()
+    private fun buildSummary(
+        maxRisk: Int = 0,
+        lowAttenuation: Int = 0,
+        midAttenuation: Int = 0,
+        highAttenuation: Int = 0
+    ): ExposureSummary {
+        val intArray = IntArray(3)
+        intArray[0] = lowAttenuation
+        intArray[1] = midAttenuation
+        intArray[2] = highAttenuation
+        return ExposureSummary.ExposureSummaryBuilder()
+            .setMaximumRiskScore(maxRisk)
+            .setAttenuationDurations(intArray)
+            .build()
     }
 }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/CachedKeyFileHolderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/CachedKeyFileHolderTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..8985994fe0cff07d41b67d6e1a944fa532add3f5
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/CachedKeyFileHolderTest.kt
@@ -0,0 +1,74 @@
+package de.rki.coronawarnapp.util
+
+import android.content.Context
+import de.rki.coronawarnapp.CoronaWarnApplication
+
+import de.rki.coronawarnapp.storage.keycache.KeyCacheRepository
+import io.mockk.MockKAnnotations
+import io.mockk.Runs
+import io.mockk.coEvery
+import io.mockk.coVerifyOrder
+import io.mockk.every
+import io.mockk.impl.annotations.MockK
+import io.mockk.just
+import io.mockk.mockkObject
+import io.mockk.unmockkAll
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import java.util.Date
+
+/**
+ * CachedKeyFileHolder test.
+ */
+class CachedKeyFileHolderTest {
+
+    @MockK
+    private lateinit var keyCacheRepository: KeyCacheRepository
+
+    @MockK
+    private lateinit var context: Context
+
+    @Before
+    fun setUp() {
+        MockKAnnotations.init(this)
+        mockkObject(CoronaWarnApplication.Companion)
+        mockkObject(KeyCacheRepository.Companion)
+        every { CoronaWarnApplication.getAppContext() } returns context
+        every { KeyCacheRepository.getDateRepository(any()) } returns keyCacheRepository
+        mockkObject(CachedKeyFileHolder)
+        coEvery { keyCacheRepository.deleteOutdatedEntries() } just Runs
+    }
+
+    /**
+     * Test call order is correct.
+     */
+    @Test
+    fun testAsyncFetchFiles() {
+        val date = Date()
+
+        coEvery { keyCacheRepository.getDates() } returns listOf()
+        coEvery { keyCacheRepository.getFilesFromEntries() } returns listOf()
+        every { CachedKeyFileHolder["getDatesFromServer"]() } returns arrayListOf<String>()
+
+        runBlocking {
+
+            CachedKeyFileHolder.asyncFetchFiles(date)
+
+            coVerifyOrder {
+                CachedKeyFileHolder.asyncFetchFiles(date)
+                keyCacheRepository.deleteOutdatedEntries()
+                CachedKeyFileHolder["getDatesFromServer"]()
+                CachedKeyFileHolder["getMissingDaysFromDiff"](arrayListOf<String>())
+                keyCacheRepository.getDates()
+                keyCacheRepository.getFilesFromEntries()
+            }
+        }
+    }
+
+    @After
+    fun cleanUp() {
+        unmockkAll()
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/CallHelperTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/CallHelperTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..7b581d0e55af657c3fa98d68e9e67061b9f60614
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/CallHelperTest.kt
@@ -0,0 +1,26 @@
+package de.rki.coronawarnapp.util
+
+import de.rki.coronawarnapp.ui.BaseFragment
+import io.mockk.Runs
+import io.mockk.every
+import io.mockk.just
+import io.mockk.mockk
+import io.mockk.verify
+import org.junit.Test
+
+/**
+ * CallHelper test.
+ */
+class CallHelperTest {
+
+    /**
+     * Test activity called.
+     */
+    @Test
+    fun testCall() {
+        val fragment = mockk<BaseFragment>()
+        every { fragment.startActivity(any()) } just Runs
+        CallHelper.call(fragment, "+77777777777")
+        verify(exactly = 1) { fragment.startActivity(any()) }
+    }
+}
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/ConnectivityHelperTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/ConnectivityHelperTest.kt
new file mode 100644
index 0000000000000000000000000000000000000000..aaee12ffe4eaf14c9ed5fc75e8837b6d19425f59
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/ConnectivityHelperTest.kt
@@ -0,0 +1,165 @@
+package de.rki.coronawarnapp.util
+
+import android.bluetooth.BluetoothAdapter
+import android.content.Context
+import android.content.Intent
+import android.net.ConnectivityManager
+import android.net.NetworkRequest
+import io.mockk.MockKAnnotations
+import io.mockk.every
+import io.mockk.impl.annotations.MockK
+import io.mockk.mockk
+import io.mockk.mockkConstructor
+import io.mockk.mockkObject
+import io.mockk.mockkStatic
+import io.mockk.unmockkAll
+import org.junit.After
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertNull
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+
+/**
+ * ConnectivityHelper test.
+ */
+class ConnectivityHelperTest {
+
+    @MockK
+    private lateinit var bAdapter: BluetoothAdapter
+
+    @MockK
+    private lateinit var context: Context
+
+    @Before
+    fun setUp() {
+        MockKAnnotations.init(this)
+        mockkStatic(BluetoothAdapter::class)
+    }
+
+    /**
+     * Test network callback behavior.
+     */
+    @Test
+    fun testNetworkCallback() {
+        var registered: Boolean? = null
+        var available: Boolean? = null
+        val callback = object : ConnectivityHelper.NetworkCallback() {
+            override fun onNetworkAvailable() {
+                available = true
+            }
+            override fun onNetworkUnavailable() {
+                available = false
+            }
+        }
+        mockkConstructor(NetworkRequest.Builder::class)
+        mockkObject(NetworkRequest.Builder())
+        val request = mockk<NetworkRequest>()
+        val manager = mockk<ConnectivityManager>()
+        every { anyConstructed<NetworkRequest.Builder>().addCapability(any()).addCapability(any()).build() } returns request
+        every { context.getSystemService(Context.CONNECTIVITY_SERVICE) } returns manager
+        every { manager.registerNetworkCallback(any(), callback) } answers { registered = true }
+        every { manager.unregisterNetworkCallback(callback) } answers { registered = false }
+
+        // register
+        ConnectivityHelper.registerNetworkStatusCallback(context, callback)
+
+        assertEquals(registered, true)
+        assertEquals(available, false)
+
+        // network found
+        callback.onAvailable(mockk())
+        assertEquals(available, true)
+
+        // loss of network
+        callback.onLost(mockk())
+        assertEquals(available, false)
+
+        // unregister
+        ConnectivityHelper.unregisterNetworkStatusCallback(context, callback)
+        assertEquals(registered, false)
+    }
+
+    /**
+     * Test bluetooth callback behaviour.
+     */
+    @Test
+    fun testBluetoothCallback() {
+        var registered: Boolean? = null
+        var available: Boolean? = null
+        val callback = object : ConnectivityHelper.BluetoothCallback() {
+            override fun onBluetoothAvailable() {
+                available = true
+            }
+
+            override fun onBluetoothUnavailable() {
+                available = false
+            }
+        }
+
+        val turnOn = mockk<Intent>()
+        every { turnOn.action } returns BluetoothAdapter.ACTION_STATE_CHANGED
+        every { turnOn.getIntExtra(BluetoothAdapter.EXTRA_STATE, any()) } returns BluetoothAdapter.STATE_ON
+
+        val turnOff = mockk<Intent>()
+        every { turnOff.action } returns BluetoothAdapter.ACTION_STATE_CHANGED
+        every { turnOff.getIntExtra(BluetoothAdapter.EXTRA_STATE, any()) } returns BluetoothAdapter.STATE_OFF
+
+        every { BluetoothAdapter.getDefaultAdapter() } returns bAdapter
+        every { context.registerReceiver(any(), any()) } answers {
+            registered = true
+            mockk()
+        }
+        every { context.unregisterReceiver(any()) } answers { registered = false }
+
+        // turned on
+        every { bAdapter.isEnabled } returns true
+
+        // register
+        ConnectivityHelper.registerBluetoothStatusCallback(context, callback)
+
+        assertNotNull(callback.recevier)
+        assertEquals(registered, true)
+        assertEquals(available, true)
+
+        // turned off
+        callback.recevier?.onReceive(context, turnOff)
+        assertEquals(available, false)
+
+        // turned on
+        callback.recevier?.onReceive(context, turnOn)
+        assertEquals(available, true)
+
+        // unregister
+        ConnectivityHelper.unregisterBluetoothStatusCallback(context, callback)
+
+        assertNull(callback.recevier)
+        assertEquals(registered, false)
+    }
+
+    /**
+     * Test bluetooth state.
+     */
+    @Test
+    fun testBluetoothState() {
+        // no bluetooth hardware
+        assertFalse(ConnectivityHelper.isBluetoothEnabled())
+
+        every { BluetoothAdapter.getDefaultAdapter() } returns bAdapter
+
+        // check turned off
+        every { bAdapter.isEnabled } returns false
+        assertFalse(ConnectivityHelper.isBluetoothEnabled())
+
+        // check turned on
+        every { bAdapter.isEnabled } returns true
+        assertTrue(ConnectivityHelper.isBluetoothEnabled())
+    }
+
+    @After
+    fun cleanUp() {
+        unmockkAll()
+    }
+}
diff --git a/Server-Protocol-Buffer/src/main/proto/applicationConfiguration.proto b/Server-Protocol-Buffer/src/main/proto/applicationConfiguration.proto
index 3b2094a3bb5a729ffe4810a236ab2c0ff70f8e57..44990658bc674ddbbfface190d0a786afee5e473 100644
--- a/Server-Protocol-Buffer/src/main/proto/applicationConfiguration.proto
+++ b/Server-Protocol-Buffer/src/main/proto/applicationConfiguration.proto
@@ -8,16 +8,20 @@ message ApplicationConfiguration {
     RiskScoreClassification riskScoreClasses = 2;
 
     RiskScoreParameters exposureConfig = 3;
+
+    AttenuationDuration attenuationDuration = 4;
+
+    ApplicationVersionConfiguration appVersion = 5;
 }
 
 message RiskScoreParameters {
 
     // App-specific mapping
     TransmissionRiskParameter transmission = 1;
-    double transmissionWeight= 2;
+    double transmissionWeight = 2;
 
     DurationRiskParameter duration = 3;
-    double durationWeight= 4;
+    double durationWeight = 4;
 
     DaysSinceLastExposureRiskParameter daysSinceLastExposure = 5;
     double daysWeight= 6;
@@ -88,4 +92,38 @@ message RiskScoreClass {
     int32 min = 2;
     int32 max = 3;
     string url = 4;
+}
+
+message AttenuationDuration {
+    Thresholds thresholds = 1;
+    Weights weights = 2;
+    int32 defaultBucketOffset = 3;
+    int32 riskScoreNormalizationDivisor = 4;
+}
+
+message Thresholds {
+    int32 lower = 1;
+    int32 upper = 2;
+}
+
+message Weights {
+    double low = 1;
+    double mid = 2;
+    double high = 3;
+}
+
+message ApplicationVersionConfiguration {
+    ApplicationVersionInfo ios = 1;
+    ApplicationVersionInfo android = 2;
+}
+
+message ApplicationVersionInfo {
+    SemanticVersion latest = 1;
+    SemanticVersion min = 2;
+}
+
+message SemanticVersion {
+    uint32 major = 1;
+    uint32 minor = 2;
+    uint32 patch = 3;
 }
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
index 9246d92e09d6d80b19520fa0ceed336135780f8d..b63abd23eafe1ccc20660116fe2a4b432793a721 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -16,6 +16,7 @@ android.enableJetifier=true
 org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
 android.useAndroidX=true
 org.gradle.parallel=true
+org.gradle.dependency.verification.console=verbose
 
 # Variables for Server URLs. The variables in local.properties will override these
 SUBMISSION_CDN_URL=