From fc8ece091c7dd77026a63b1e18de288bb553f961 Mon Sep 17 00:00:00 2001
From: Mohamed <mohamed.metwalli@sap.com>
Date: Wed, 17 Mar 2021 12:29:27 +0100
Subject: [PATCH] Add check-Ins to submission payload (EXPOSUREAPP-5656)
 (#2602)

* Add check-ins to submission payload

* Use new classes -  map checkin fields

* Rename to transformer

* Satisfy tests

* lint

* Use new models

* Add space to satisfy ktlint the magnificent

* Create DefaultCheckInsTransformerTest.kt

* Clear check-ins after submission

* Fix tests

* Update SubmissionTaskTest.kt

Co-authored-by: Lukas Lechner <lukas.lechner@sap.com>
---
 .../EventRegistrationModule.kt                |  5 +
 .../checkins/CheckInRepository.kt             |  6 ++
 .../checkins/CheckInsTransformer.kt           |  7 ++
 .../checkins/DefaultCheckInsTransformer.kt    | 37 +++++++
 .../coronawarnapp/playbook/DefaultPlaybook.kt |  3 +-
 .../de/rki/coronawarnapp/playbook/Playbook.kt | 22 ++++-
 .../submission/server/SubmissionServer.kt     |  5 +-
 .../submission/task/SubmissionTask.kt         | 19 +++-
 .../DefaultCheckInsTransformerTest.kt         | 96 +++++++++++++++++++
 .../http/playbook/DefaultPlaybookTest.kt      | 15 ++-
 .../submission/server/SubmissionServerTest.kt |  6 +-
 .../submission/task/SubmissionTaskTest.kt     | 43 ++++++---
 12 files changed, 233 insertions(+), 31 deletions(-)
 create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInsTransformer.kt
 create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformer.kt
 create mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformerTest.kt

diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/EventRegistrationModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/EventRegistrationModule.kt
index 82434300f..efc4455a3 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/EventRegistrationModule.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/EventRegistrationModule.kt
@@ -8,10 +8,15 @@ import de.rki.coronawarnapp.eventregistration.checkins.qrcode.DefaultQRCodeVerif
 import de.rki.coronawarnapp.eventregistration.checkins.qrcode.QRCodeVerifier
 import de.rki.coronawarnapp.eventregistration.storage.repo.DefaultTraceLocationRepository
 import de.rki.coronawarnapp.eventregistration.storage.repo.TraceLocationRepository
+import de.rki.coronawarnapp.eventregistration.checkins.CheckInsTransformer
+import de.rki.coronawarnapp.eventregistration.checkins.DefaultCheckInsTransformer
 
 @Module
 abstract class EventRegistrationModule {
 
+    @Binds
+    abstract fun checkInsTransformer(transformer: DefaultCheckInsTransformer): CheckInsTransformer
+
     @Binds
     abstract fun qrCodeVerifier(qrCodeVerifier: DefaultQRCodeVerifier): QRCodeVerifier
 
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInRepository.kt
index 46c790529..248a3c2df 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInRepository.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInRepository.kt
@@ -39,6 +39,12 @@ class CheckInRepository @Inject constructor(
             checkInDao.update(checkIn.toEntity())
         }
     }
+
+    fun clear() {
+        appScope.launch {
+            checkInDao.deleteAll()
+        }
+    }
 }
 
 private fun TraceLocationCheckInEntity.toCheckIn() = CheckIn(
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInsTransformer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInsTransformer.kt
new file mode 100644
index 000000000..23fe7f823
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/CheckInsTransformer.kt
@@ -0,0 +1,7 @@
+package de.rki.coronawarnapp.eventregistration.checkins
+
+import de.rki.coronawarnapp.server.protocols.internal.pt.CheckInOuterClass
+
+interface CheckInsTransformer {
+    fun transform(checkIns: List<CheckIn>): List<CheckInOuterClass.CheckIn>
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformer.kt
new file mode 100644
index 000000000..84bd29c8f
--- /dev/null
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformer.kt
@@ -0,0 +1,37 @@
+package de.rki.coronawarnapp.eventregistration.checkins
+
+import com.google.protobuf.ByteString
+import de.rki.coronawarnapp.server.protocols.internal.pt.CheckInOuterClass
+import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass
+import de.rki.coronawarnapp.util.TimeAndDateExtensions.seconds
+import javax.inject.Inject
+
+class DefaultCheckInsTransformer @Inject constructor() :
+    CheckInsTransformer {
+    override fun transform(checkIns: List<CheckIn>): List<CheckInOuterClass.CheckIn> {
+        return checkIns.map { checkIn ->
+            val traceLocation = TraceLocationOuterClass.TraceLocation.newBuilder()
+                .setGuid(checkIn.guid)
+                .setVersion(checkIn.version)
+                .setType(TraceLocationOuterClass.TraceLocationType.forNumber(checkIn.type))
+                .setDescription(checkIn.description)
+                .setAddress(checkIn.address)
+                .setStartTimestamp(checkIn.traceLocationStart?.seconds ?: 0L)
+                .setEndTimestamp(checkIn.traceLocationEnd?.seconds ?: 0L)
+                .setDefaultCheckInLengthInMinutes(checkIn.defaultCheckInLengthInMinutes ?: 0)
+                .build()
+
+            val signedTraceLocation = TraceLocationOuterClass.SignedTraceLocation.newBuilder()
+                .setLocation(traceLocation)
+                .setSignature(ByteString.copyFrom(checkIn.signature.toByteArray()))
+                .build()
+
+            CheckInOuterClass.CheckIn.newBuilder()
+                .setSignedLocation(signedTraceLocation)
+                .setStartIntervalNumber(checkIn.checkInStart.seconds.toInt())
+                .setEndIntervalNumber(checkIn.checkInEnd?.seconds?.toInt() ?: 0)
+                // TODO .setTransmissionRiskLevel()
+                .build()
+        }
+    }
+}
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/DefaultPlaybook.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/DefaultPlaybook.kt
index 58fe31e80..fffe53cd3 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/DefaultPlaybook.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/DefaultPlaybook.kt
@@ -100,7 +100,8 @@ class DefaultPlaybook @Inject constructor(
                     authCode = authCode,
                     keyList = data.temporaryExposureKeys,
                     consentToFederation = data.consentToFederation,
-                    visitedCountries = data.visitedCountries
+                    visitedCountries = data.visitedCountries,
+                    checkIns = data.checkIns
                 )
                 submissionServer.submitKeysToServer(serverSubmissionData)
                 coroutineScope.launch { followUpPlaybooks() }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/Playbook.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/Playbook.kt
index e2db6aaca..3da7b683d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/Playbook.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/playbook/Playbook.kt
@@ -1,20 +1,31 @@
 package de.rki.coronawarnapp.playbook
 
 import de.rki.coronawarnapp.server.protocols.external.exposurenotification.TemporaryExposureKeyExportOuterClass
+import de.rki.coronawarnapp.server.protocols.internal.pt.CheckInOuterClass
 import de.rki.coronawarnapp.util.formatter.TestResult
 import de.rki.coronawarnapp.verification.server.VerificationKeyType
 
 /**
- * The concept of Plausible Deniability aims to hide the existence of a positive test result by always using a defined “playbook pattern” of requests to the Verification Server and CWA Backend so it is impossible for an attacker to identify which communication was done.
- * The “playbook pattern” represents a well-defined communication pattern consisting of dummy requests and real requests.
- * To hide that a real request was done, the device does multiple of these requests over a longer period of time according to the previously defined communication pattern statistically similar to all apps so it is not possible to infer by observing the traffic if the requests under concern are real or the fake ones.
+ * The concept of Plausible Deniability aims to hide the existence of a positive test result by always using a defined
+ * “playbook pattern” of requests to the Verification Server and CWA Backend so it is impossible for an attacker to
+ * identify which communication was done.
+ *
+ * The “playbook pattern” represents a well-defined communication pattern consisting of fake requests and real
+ * requests.
+ *
+ * To hide that a real request was done, the device does multiple of these requests over a longer period of time
+ * according to the previously defined communication pattern statistically similar to all apps so it is not possible to
+ * infer by observing the traffic if the requests under concern are real or the fake ones.
  */
 interface Playbook {
 
+    /**
+     * @return pair of Registration token [String] & [TestResult]
+     */
     suspend fun initialRegistration(
         key: String,
         keyType: VerificationKeyType
-    ): Pair<String, TestResult> /* registration token & test result*/
+    ): Pair<String, TestResult>
 
     suspend fun testResult(registrationToken: String): TestResult
 
@@ -26,6 +37,7 @@ interface Playbook {
         val registrationToken: String,
         val temporaryExposureKeys: List<TemporaryExposureKeyExportOuterClass.TemporaryExposureKey>,
         val consentToFederation: Boolean,
-        val visitedCountries: List<String>
+        val visitedCountries: List<String>,
+        val checkIns: List<CheckInOuterClass.CheckIn>
     )
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/server/SubmissionServer.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/server/SubmissionServer.kt
index ab8745971..344b175e1 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/server/SubmissionServer.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/server/SubmissionServer.kt
@@ -4,6 +4,7 @@ import com.google.protobuf.ByteString
 import dagger.Lazy
 import de.rki.coronawarnapp.server.protocols.external.exposurenotification.TemporaryExposureKeyExportOuterClass.TemporaryExposureKey
 import de.rki.coronawarnapp.server.protocols.internal.SubmissionPayloadOuterClass.SubmissionPayload
+import de.rki.coronawarnapp.server.protocols.internal.pt.CheckInOuterClass
 
 import de.rki.coronawarnapp.util.PaddingTool.requestPadding
 import kotlinx.coroutines.Dispatchers
@@ -25,7 +26,8 @@ class SubmissionServer @Inject constructor(
         val authCode: String,
         val keyList: List<TemporaryExposureKey>,
         val consentToFederation: Boolean,
-        val visitedCountries: List<String>
+        val visitedCountries: List<String>,
+        val checkIns: List<CheckInOuterClass.CheckIn>
     )
 
     suspend fun submitKeysToServer(
@@ -48,6 +50,7 @@ class SubmissionServer @Inject constructor(
             .setRequestPadding(ByteString.copyFromUtf8(fakeKeyPadding))
             .setConsentToFederation(data.consentToFederation)
             .addAllVisitedCountries(data.visitedCountries)
+            .addAllCheckIns(data.checkIns)
             .build()
 
         api.submitKeys(
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/task/SubmissionTask.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/task/SubmissionTask.kt
index 8232893d4..db90d36d1 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/task/SubmissionTask.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/submission/task/SubmissionTask.kt
@@ -3,6 +3,8 @@ package de.rki.coronawarnapp.submission.task
 import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
 import de.rki.coronawarnapp.appconfig.AppConfigProvider
 import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
+import de.rki.coronawarnapp.eventregistration.checkins.CheckInRepository
+import de.rki.coronawarnapp.eventregistration.checkins.CheckInsTransformer
 import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException
 import de.rki.coronawarnapp.notification.ShareTestResultNotificationService
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
@@ -37,6 +39,8 @@ class SubmissionTask @Inject constructor(
     private val timeStamper: TimeStamper,
     private val shareTestResultNotificationService: ShareTestResultNotificationService,
     private val testResultAvailableNotificationService: TestResultAvailableNotificationService,
+    private val checkInsRepository: CheckInRepository,
+    private val checkInsTransformer: CheckInsTransformer,
     private val analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
 ) : Task<DefaultProgress, SubmissionTask.Result> {
 
@@ -137,11 +141,17 @@ class SubmissionTask @Inject constructor(
         )
         Timber.tag(TAG).d("Transformed keys with symptoms %s from %s to %s", symptoms, keys, transformedKeys)
 
+        val checkIns = checkInsRepository.allCheckIns.first()
+        val transformedCheckIns = checkInsTransformer.transform(checkIns)
+
+        Timber.tag(TAG).d("Transformed CheckIns from: %s to: %s", checkIns, transformedCheckIns)
+
         val submissionData = Playbook.SubmissionData(
-            registrationToken,
-            transformedKeys,
-            true,
-            getSupportedCountries()
+            registrationToken = registrationToken,
+            temporaryExposureKeys = transformedKeys,
+            consentToFederation = true,
+            visitedCountries = getSupportedCountries(),
+            checkIns = transformedCheckIns
         )
 
         checkCancel()
@@ -154,6 +164,7 @@ class SubmissionTask @Inject constructor(
 
         Timber.tag(TAG).d("Submission successful, deleting submission data.")
         tekHistoryStorage.clear()
+        checkInsRepository.clear()
         submissionSettings.symptoms.update { null }
 
         autoSubmission.updateMode(AutoSubmission.Mode.DISABLED)
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformerTest.kt
new file mode 100644
index 000000000..7a7058e96
--- /dev/null
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/eventregistration/checkins/DefaultCheckInsTransformerTest.kt
@@ -0,0 +1,96 @@
+package de.rki.coronawarnapp.eventregistration.checkins
+
+import com.google.protobuf.ByteString
+import de.rki.coronawarnapp.server.protocols.internal.pt.TraceLocationOuterClass
+import io.kotest.matchers.shouldBe
+import org.joda.time.Instant
+import org.junit.jupiter.api.Test
+import testhelpers.BaseTest
+
+class DefaultCheckInsTransformerTest : BaseTest() {
+
+    private val checkInTransformer = DefaultCheckInsTransformer()
+
+    @Test
+    fun `transform check-ins`() {
+        val checkIn1 = CheckIn(
+            id = 0,
+            guid = "3055331c-2306-43f3-9742-6d8fab54e848",
+            version = 1,
+            type = 2,
+            description = "description1",
+            address = "address1",
+            traceLocationStart = Instant.ofEpochMilli(2687955 * 1_000L),
+            traceLocationEnd = Instant.ofEpochMilli(2687991 * 1_000L),
+            defaultCheckInLengthInMinutes = 10,
+            signature = "signature1",
+            checkInStart = Instant.ofEpochMilli(2687955 * 1_000L),
+            checkInEnd = Instant.ofEpochMilli(2687991 * 1_000L),
+            targetCheckInEnd = null,
+            createJournalEntry = true
+        )
+
+        val checkIn2 = CheckIn(
+            id = 1,
+            guid = "fca84b37-61c0-4a7c-b2f8-825cadd506cf",
+            version = 1,
+            type = 1,
+            description = "description2",
+            address = "address2",
+            traceLocationStart = null,
+            traceLocationEnd = null,
+            defaultCheckInLengthInMinutes = 20,
+            signature = "signature2",
+            checkInStart = Instant.ofEpochMilli(2687955 * 1_000L),
+            checkInEnd = null,
+            targetCheckInEnd = null,
+            createJournalEntry = false
+        )
+        
+        val outCheckIns = checkInTransformer.transform(
+            listOf(
+                checkIn1,
+                checkIn2
+            )
+        )
+        outCheckIns.size shouldBe 2
+
+        outCheckIns[0].apply {
+            signedLocation.apply {
+                location.apply {
+                    guid shouldBe "3055331c-2306-43f3-9742-6d8fab54e848"
+                    version shouldBe 1
+                    type shouldBe TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_TEMPORARY_OTHER
+                    description shouldBe "description1"
+                    address shouldBe "address1"
+                    startTimestamp shouldBe 2687955
+                    endTimestamp shouldBe 2687991
+                    defaultCheckInLengthInMinutes shouldBe 10
+                }
+                signature shouldBe ByteString.copyFrom("signature1".toByteArray())
+            }
+            startIntervalNumber shouldBe 2687955
+            endIntervalNumber shouldBe 2687991
+            // TODO transmissionRiskLevel shouldBe
+        }
+
+        outCheckIns[1].apply {
+            signedLocation.apply {
+                location.apply {
+                    guid shouldBe "fca84b37-61c0-4a7c-b2f8-825cadd506cf"
+                    version shouldBe 1
+                    type shouldBe TraceLocationOuterClass.TraceLocationType.LOCATION_TYPE_PERMANENT_OTHER
+                    description shouldBe "description2"
+                    address shouldBe "address2"
+                    startTimestamp shouldBe 0
+                    endTimestamp shouldBe 0
+                    defaultCheckInLengthInMinutes shouldBe 20
+                }
+                signature shouldBe ByteString.copyFrom("signature2".toByteArray())
+            }
+            startIntervalNumber shouldBe 2687955
+            endIntervalNumber shouldBe 0
+            // TODO transmissionRiskLevel shouldBe
+        }
+    }
+}
\ No newline at end of file
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/http/playbook/DefaultPlaybookTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/http/playbook/DefaultPlaybookTest.kt
index f201b17a6..379333320 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/http/playbook/DefaultPlaybookTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/http/playbook/DefaultPlaybookTest.kt
@@ -86,7 +86,8 @@ class DefaultPlaybookTest : BaseTest() {
                 registrationToken = "token",
                 temporaryExposureKeys = listOf(),
                 consentToFederation = true,
-                visitedCountries = listOf("DE")
+                visitedCountries = listOf("DE"),
+                checkIns = emptyList()
             )
         )
 
@@ -107,7 +108,8 @@ class DefaultPlaybookTest : BaseTest() {
                     registrationToken = "token",
                     temporaryExposureKeys = listOf(),
                     consentToFederation = true,
-                    visitedCountries = listOf("DE")
+                    visitedCountries = listOf("DE"),
+                    checkIns = emptyList()
                 )
             )
         } catch (e: Exception) {
@@ -126,7 +128,8 @@ class DefaultPlaybookTest : BaseTest() {
                     registrationToken = "token",
                     temporaryExposureKeys = listOf(),
                     consentToFederation = true,
-                    visitedCountries = listOf("DE")
+                    visitedCountries = listOf("DE"),
+                    checkIns = emptyList()
                 )
             )
         } catch (e: Exception) {
@@ -146,7 +149,8 @@ class DefaultPlaybookTest : BaseTest() {
                     registrationToken = "token",
                     temporaryExposureKeys = listOf(),
                     consentToFederation = true,
-                    visitedCountries = listOf("DE")
+                    visitedCountries = listOf("DE"),
+                    checkIns = emptyList()
                 )
             )
         }
@@ -260,7 +264,8 @@ class DefaultPlaybookTest : BaseTest() {
                     registrationToken = "token",
                     temporaryExposureKeys = listOf(),
                     consentToFederation = true,
-                    visitedCountries = listOf("DE")
+                    visitedCountries = listOf("DE"),
+                    checkIns = emptyList()
                 )
             )
         }
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/server/SubmissionServerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/server/SubmissionServerTest.kt
index 6f2aa826c..1bd51734a 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/server/SubmissionServerTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/server/SubmissionServerTest.kt
@@ -84,7 +84,8 @@ class SubmissionServerTest : BaseTest() {
             authCode = "testAuthCode",
             keyList = listOf(googleKeyList),
             consentToFederation = true,
-            visitedCountries = listOf("DE")
+            visitedCountries = listOf("DE"),
+            checkIns = emptyList()
         )
         server.submitKeysToServer(submissionData)
 
@@ -144,7 +145,8 @@ class SubmissionServerTest : BaseTest() {
             authCode = "39ec4930-7a1f-4d5d-921f-bfad3b6f1269",
             keyList = listOf(googleKeyList),
             consentToFederation = true,
-            visitedCountries = listOf("DE")
+            visitedCountries = listOf("DE"),
+            checkIns = emptyList()
         )
         webServer.enqueue(MockResponse().setBody("{}"))
         server.submitKeysToServer(submissionData)
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/task/SubmissionTaskTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/task/SubmissionTaskTest.kt
index f49adc5f8..81e9e2f53 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/task/SubmissionTaskTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/submission/task/SubmissionTaskTest.kt
@@ -4,6 +4,8 @@ import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
 import de.rki.coronawarnapp.appconfig.AppConfigProvider
 import de.rki.coronawarnapp.appconfig.ConfigData
 import de.rki.coronawarnapp.datadonation.analytics.modules.keysubmission.AnalyticsKeySubmissionCollector
+import de.rki.coronawarnapp.eventregistration.checkins.CheckInRepository
+import de.rki.coronawarnapp.eventregistration.checkins.CheckInsTransformer
 import de.rki.coronawarnapp.exception.NoRegistrationTokenSetException
 import de.rki.coronawarnapp.notification.ShareTestResultNotificationService
 import de.rki.coronawarnapp.notification.TestResultAvailableNotificationService
@@ -59,6 +61,8 @@ class SubmissionTaskTest : BaseTest() {
     @MockK lateinit var appConfigData: ConfigData
     @MockK lateinit var timeStamper: TimeStamper
     @MockK lateinit var analyticsKeySubmissionCollector: AnalyticsKeySubmissionCollector
+    @MockK lateinit var checkInsTransformer: CheckInsTransformer
+    @MockK lateinit var checkInRepository: CheckInRepository
 
     private lateinit var settingSymptomsPreference: FlowPreference<Symptoms?>
 
@@ -109,6 +113,10 @@ class SubmissionTaskTest : BaseTest() {
         every { autoSubmission.updateMode(any()) } just Runs
 
         every { timeStamper.nowUTC } returns Instant.EPOCH.plus(Duration.standardHours(1))
+
+        every { checkInRepository.allCheckIns } returns flowOf(emptyList())
+        every { checkInRepository.clear() } just Runs
+        every { checkInsTransformer.transform(any()) } returns emptyList()
     }
 
     private fun createTask() = SubmissionTask(
@@ -121,7 +129,9 @@ class SubmissionTaskTest : BaseTest() {
         timeStamper = timeStamper,
         autoSubmission = autoSubmission,
         testResultAvailableNotificationService = testResultAvailableNotificationService,
-        analyticsKeySubmissionCollector = analyticsKeySubmissionCollector
+        analyticsKeySubmissionCollector = analyticsKeySubmissionCollector,
+        checkInsRepository = checkInRepository,
+        checkInsTransformer = checkInsTransformer
     )
 
     @Test
@@ -149,14 +159,17 @@ class SubmissionTaskTest : BaseTest() {
             settingSymptomsPreference.value
 
             tekHistoryCalculations.transformToKeyHistoryInExternalFormat(listOf(tek), userSymptoms)
+            checkInRepository.allCheckIns
+            checkInsTransformer.transform(any())
 
             appConfigProvider.getAppConfig()
             playbook.submit(
                 Playbook.SubmissionData(
-                    "regtoken",
-                    listOf(transformedKey),
-                    true,
-                    listOf("NL")
+                    registrationToken = "regtoken",
+                    temporaryExposureKeys = listOf(transformedKey),
+                    consentToFederation = true,
+                    visitedCountries = listOf("NL"),
+                    checkIns = emptyList()
                 )
             )
 
@@ -164,6 +177,7 @@ class SubmissionTaskTest : BaseTest() {
             analyticsKeySubmissionCollector.reportSubmittedInBackground()
 
             tekHistoryStorage.clear()
+            checkInRepository.clear()
             submissionSettings.symptoms
             settingSymptomsPreference.update(match { it.invoke(mockk()) == null })
 
@@ -213,15 +227,17 @@ class SubmissionTaskTest : BaseTest() {
             appConfigProvider.getAppConfig()
             playbook.submit(
                 Playbook.SubmissionData(
-                    "regtoken",
-                    listOf(transformedKey),
-                    true,
-                    listOf("NL")
+                    registrationToken = "regtoken",
+                    temporaryExposureKeys = listOf(transformedKey),
+                    consentToFederation = true,
+                    visitedCountries = listOf("NL"),
+                    checkIns = emptyList()
                 )
             )
         }
         coVerify(exactly = 0) {
             tekHistoryStorage.clear()
+            checkInRepository.clear()
             settingSymptomsPreference.update(any())
             shareTestResultNotificationService.cancelSharePositiveTestResultNotification()
             autoSubmission.updateMode(any())
@@ -250,10 +266,11 @@ class SubmissionTaskTest : BaseTest() {
         coVerifySequence {
             playbook.submit(
                 Playbook.SubmissionData(
-                    "regtoken",
-                    listOf(transformedKey),
-                    true,
-                    listOf("DE")
+                    registrationToken = "regtoken",
+                    temporaryExposureKeys = listOf(transformedKey),
+                    consentToFederation = true,
+                    visitedCountries = listOf("DE"),
+                    checkIns = emptyList()
                 )
             )
         }
-- 
GitLab