Skip to content
This repository was archived by the owner on Jun 20, 2023. It is now read-only.

Commit 348bdce

Browse files
authored
SRS : Teks on fly (EXPOSUREAPP-14489) (#5770)
* Create persisted TEKs * Request OS keys directly * Use os keys * Pass teks * Tests * Don't update cache * Tests * Update TEKHistoryUpdaterTest.kt
1 parent f935d40 commit 348bdce

File tree

19 files changed

+297
-49
lines changed

19 files changed

+297
-49
lines changed

Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/srs/ui/consent/SrsSubmissionConsentFragmentTest.kt

+3-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import androidx.test.internal.runner.junit4.statement.UiThreadStatement
1111
import dagger.Module
1212
import dagger.android.ContributesAndroidInjector
1313
import de.rki.coronawarnapp.R
14+
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
1415
import de.rki.coronawarnapp.util.ui.SingleLiveEvent
1516
import io.mockk.MockKAnnotations
1617
import io.mockk.every
@@ -55,7 +56,8 @@ class SrsSubmissionConsentFragmentTest : BaseUITest() {
5556
setupMockViewModel(
5657
object : SrsSubmissionConsentFragmentViewModel.Factory {
5758
override fun create(
58-
openTypeSelection: Boolean
59+
openTypeSelection: Boolean,
60+
teksSharedViewModel: TeksSharedViewModel
5961
): SrsSubmissionConsentFragmentViewModel = viewModel
6062
}
6163
)

Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/submission/ui/SubmissionTestFragmentViewModel.kt

+4-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,10 @@ class SubmissionTestFragmentViewModel @AssistedInject constructor(
8989

9090
fun submit() = launch {
9191
try {
92-
srsSubmissionRepository.submit(type = SrsSubmissionType.SRS_SELF_TEST)
92+
srsSubmissionRepository.submit(
93+
type = SrsSubmissionType.SRS_SELF_TEST,
94+
keys = tekHistory.value.orEmpty().map { it.key }
95+
)
9396
srsSubmissionResult.postValue(Success)
9497
} catch (e: Exception) {
9598
Timber.e(e, "submit()")

Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_submission.xml

+7
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@
107107
android:gravity="center"
108108
android:text="_________ For DEVs _________" />
109109

110+
<TextView
111+
android:layout_width="match_parent"
112+
android:layout_height="wrap_content"
113+
android:layout_marginTop="24dp"
114+
android:gravity="center"
115+
android:text="Click 'Get TEKs' button before submitting " />
116+
110117
<Button
111118
android:id="@+id/submit"
112119
style="@style/buttonPrimary"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package de.rki.coronawarnapp.srs.core.model
2+
3+
import android.os.Parcelable
4+
import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
5+
import kotlinx.parcelize.Parcelize
6+
7+
@Parcelize
8+
data class TekPatch(
9+
val parcelableTeks: List<ParcelableTek>
10+
) : Parcelable {
11+
12+
fun osKeys(): List<TemporaryExposureKey> = parcelableTeks.map { pKey -> pKey.toTemporaryExposureKey() }
13+
14+
@Parcelize
15+
data class ParcelableTek(
16+
val keyData: ByteArray,
17+
val rollingStartIntervalNumber: Int,
18+
val transmissionRiskLevel: Int,
19+
val rollingPeriod: Int,
20+
val reportType: Int,
21+
val daysSinceOnsetOfSymptoms: Int
22+
) : Parcelable {
23+
24+
fun toTemporaryExposureKey(): TemporaryExposureKey = TemporaryExposureKey.TemporaryExposureKeyBuilder()
25+
.apply {
26+
setKeyData(keyData)
27+
setRollingStartIntervalNumber(rollingStartIntervalNumber)
28+
setTransmissionRiskLevel(transmissionRiskLevel)
29+
setRollingPeriod(rollingPeriod)
30+
setReportType(reportType)
31+
if (daysSinceOnsetOfSymptoms != TemporaryExposureKey.DAYS_SINCE_ONSET_OF_SYMPTOMS_UNKNOWN) {
32+
setDaysSinceOnsetOfSymptoms(daysSinceOnsetOfSymptoms)
33+
}
34+
}.build()
35+
36+
override fun equals(other: Any?): Boolean {
37+
if (this === other) return true
38+
if (javaClass != other?.javaClass) return false
39+
40+
other as ParcelableTek
41+
42+
if (!keyData.contentEquals(other.keyData)) return false
43+
if (rollingStartIntervalNumber != other.rollingStartIntervalNumber) return false
44+
if (transmissionRiskLevel != other.transmissionRiskLevel) return false
45+
if (rollingPeriod != other.rollingPeriod) return false
46+
if (reportType != other.reportType) return false
47+
if (daysSinceOnsetOfSymptoms != other.daysSinceOnsetOfSymptoms) return false
48+
49+
return true
50+
}
51+
52+
override fun hashCode(): Int {
53+
var result = keyData.contentHashCode()
54+
result = 31 * result + rollingStartIntervalNumber
55+
result = 31 * result + transmissionRiskLevel
56+
result = 31 * result + rollingPeriod
57+
result = 31 * result + reportType
58+
result = 31 * result + daysSinceOnsetOfSymptoms
59+
return result
60+
}
61+
}
62+
63+
companion object {
64+
fun patchFrom(osKeys: List<TemporaryExposureKey>) = TekPatch(
65+
parcelableTeks = osKeys.map { oskey -> oskey.toParcelableTek() }
66+
)
67+
}
68+
}
69+
70+
fun TemporaryExposureKey.toParcelableTek() = TekPatch.ParcelableTek(
71+
keyData = this.keyData,
72+
rollingStartIntervalNumber = this.rollingStartIntervalNumber,
73+
transmissionRiskLevel = this.transmissionRiskLevel,
74+
rollingPeriod = this.rollingPeriod,
75+
reportType = this.reportType,
76+
daysSinceOnsetOfSymptoms = this.daysSinceOnsetOfSymptoms
77+
)

Corona-Warn-App/src/main/java/de/rki/coronawarnapp/srs/core/repository/SrsSubmissionRepository.kt

+2-12
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ import de.rki.coronawarnapp.srs.core.server.errorArgs
2828
import de.rki.coronawarnapp.srs.core.storage.SrsDevSettings
2929
import de.rki.coronawarnapp.srs.core.storage.SrsSubmissionSettings
3030
import de.rki.coronawarnapp.submission.Symptoms
31-
import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryStorage
3231
import de.rki.coronawarnapp.submission.task.ExposureKeyHistoryCalculations
3332
import de.rki.coronawarnapp.tag
3433
import de.rki.coronawarnapp.util.TimeStamper
@@ -43,7 +42,6 @@ class SrsSubmissionRepository @Inject constructor(
4342
private val playbook: SrsPlaybook,
4443
private val appConfigProvider: AppConfigProvider,
4544
private val tekCalculations: ExposureKeyHistoryCalculations,
46-
private val tekStorage: TEKHistoryStorage,
4745
private val timeStamper: TimeStamper,
4846
private val checkInsRepo: CheckInRepository,
4947
private val checkInsTransformer: CheckInsTransformer,
@@ -55,7 +53,8 @@ class SrsSubmissionRepository @Inject constructor(
5553
) {
5654
suspend fun submit(
5755
type: SrsSubmissionType,
58-
symptoms: Symptoms = Symptoms.NO_INFO_GIVEN
56+
symptoms: Symptoms = Symptoms.NO_INFO_GIVEN,
57+
keys: List<TemporaryExposureKey>
5958
) {
6059
Timber.tag(TAG).d("submit(type=%s)", type)
6160
val appConfig = appConfigProvider.getAppConfig()
@@ -91,12 +90,6 @@ class SrsSubmissionRepository @Inject constructor(
9190
srsSubmissionSettings.setOtp(srsOtp)
9291
}
9392

94-
val keys: List<TemporaryExposureKey> = runCatching {
95-
tekStorage.tekData.first().flatMap { it.keys }
96-
}.onFailure {
97-
Timber.w(it, "No temporary exposure keys")
98-
}.getOrDefault(emptyList())
99-
10093
val transformedKeys = tekCalculations.transformToKeyHistoryInExternalFormat(keys, symptoms)
10194
Timber.tag(TAG).d("Transformed keys with symptoms %s from %s to %s", symptoms, keys, transformedKeys)
10295

@@ -116,9 +109,6 @@ class SrsSubmissionRepository @Inject constructor(
116109
Timber.tag(TAG).d("Submitting %s", payload)
117110
playbook.submit(payload)
118111

119-
Timber.tag(TAG).d("Submission successful, deleting submission data.")
120-
tekStorage.reset()
121-
122112
Timber.tag(TAG).d("Marking %d submitted CheckIns.", checkIns.size)
123113
checkInsRepo.updatePostSubmissionFlags(checkIns)
124114

Corona-Warn-App/src/main/java/de/rki/coronawarnapp/srs/ui/consent/SrsSubmissionConsentFragment.kt

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import android.view.View
66
import androidx.fragment.app.Fragment
77
import androidx.navigation.fragment.findNavController
88
import androidx.navigation.fragment.navArgs
9+
import androidx.navigation.navGraphViewModels
910
import de.rki.coronawarnapp.R
1011
import de.rki.coronawarnapp.databinding.FragmentSrsSubmissionConsentBinding
1112
import de.rki.coronawarnapp.srs.core.model.SrsSubmissionType
13+
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
1214
import de.rki.coronawarnapp.tracing.ui.tracingConsentDialog
1315
import de.rki.coronawarnapp.ui.submission.SubmissionBlockingDialog
1416
import de.rki.coronawarnapp.util.di.AutoInject
@@ -23,11 +25,15 @@ class SrsSubmissionConsentFragment : Fragment(R.layout.fragment_srs_submission_c
2325

2426
@Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
2527
private val navArgs by navArgs<SrsSubmissionConsentFragmentArgs>()
28+
private val teksSharedViewModel by navGraphViewModels<TeksSharedViewModel>(R.id.srs_nav_graph)
2629
private val viewModel: SrsSubmissionConsentFragmentViewModel by cwaViewModelsAssisted(
2730
factoryProducer = { viewModelFactory },
2831
constructorCall = { factory, _ ->
2932
factory as SrsSubmissionConsentFragmentViewModel.Factory
30-
factory.create(navArgs.openTypeSelection)
33+
factory.create(
34+
navArgs.openTypeSelection,
35+
teksSharedViewModel
36+
)
3137
}
3238
)
3339
private val binding by viewBinding<FragmentSrsSubmissionConsentBinding>()

Corona-Warn-App/src/main/java/de/rki/coronawarnapp/srs/ui/consent/SrsSubmissionConsentFragmentViewModel.kt

+13-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import de.rki.coronawarnapp.exception.ExceptionCategory
1111
import de.rki.coronawarnapp.exception.reporting.report
1212
import de.rki.coronawarnapp.presencetracing.checkins.CheckInRepository
1313
import de.rki.coronawarnapp.presencetracing.checkins.common.completedCheckIns
14+
import de.rki.coronawarnapp.srs.core.model.TekPatch
15+
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
1416
import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryUpdater
1517
import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
1618
import de.rki.coronawarnapp.util.ui.SingleLiveEvent
@@ -22,6 +24,7 @@ import timber.log.Timber
2224

2325
class SrsSubmissionConsentFragmentViewModel @AssistedInject constructor(
2426
@Assisted private val openTypeSelection: Boolean,
27+
@Assisted private val teksSharedViewModel: TeksSharedViewModel,
2528
private val checkInRepository: CheckInRepository,
2629
appConfigProvider: AppConfigProvider,
2730
dispatcherProvider: DispatcherProvider,
@@ -74,6 +77,7 @@ class SrsSubmissionConsentFragmentViewModel @AssistedInject constructor(
7477
suspend fun onTekAvailable(teks: List<TemporaryExposureKey>) {
7578
Timber.tag(TAG).d("onTEKAvailable(teks.size=%d)", teks.size)
7679
showKeysRetrievalProgress.postValue(false)
80+
teksSharedViewModel.setTekPatch(TekPatch.patchFrom(teks))
7781

7882
if (openTypeSelection) {
7983
Timber.tag(TAG).d("Navigate to TestType")
@@ -96,12 +100,17 @@ class SrsSubmissionConsentFragmentViewModel @AssistedInject constructor(
96100
}
97101

98102
fun submissionConsentAcceptButtonClicked() {
99-
tekHistoryUpdater.getTeksOrRequestPermission()
103+
tekHistoryUpdater.getTeksOrRequestPermissionFromOS()
100104
}
101105

102106
fun handleActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
103107
showKeysRetrievalProgress.value = true
104-
tekHistoryUpdater.handleActivityResult(requestCode, resultCode, data)
108+
tekHistoryUpdater.handleActivityResult(
109+
requestCode = requestCode,
110+
resultCode = resultCode,
111+
data = data,
112+
updateCache = false
113+
)
105114
}
106115

107116
fun onConsentCancel() {
@@ -111,7 +120,8 @@ class SrsSubmissionConsentFragmentViewModel @AssistedInject constructor(
111120
@AssistedFactory
112121
interface Factory : CWAViewModelFactory<SrsSubmissionConsentFragmentViewModel> {
113122
fun create(
114-
openTypeSelection: Boolean
123+
openTypeSelection: Boolean,
124+
teksSharedViewModel: TeksSharedViewModel
115125
): SrsSubmissionConsentFragmentViewModel
116126
}
117127

Corona-Warn-App/src/main/java/de/rki/coronawarnapp/srs/ui/symptoms/calendar/SrsSymptomsCalendarFragment.kt

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import androidx.activity.OnBackPressedCallback
88
import androidx.fragment.app.Fragment
99
import androidx.navigation.fragment.findNavController
1010
import androidx.navigation.fragment.navArgs
11+
import androidx.navigation.navGraphViewModels
1112
import de.rki.coronawarnapp.R
1213
import de.rki.coronawarnapp.databinding.FragmentSubmissionSymptomCalendarBinding
1314
import de.rki.coronawarnapp.srs.ui.dialogs.showCloseDialog
1415
import de.rki.coronawarnapp.srs.ui.dialogs.showSubmissionWarningDialog
1516
import de.rki.coronawarnapp.srs.ui.dialogs.showTruncatedSubmissionDialog
17+
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
1618
import de.rki.coronawarnapp.submission.Symptoms
1719
import de.rki.coronawarnapp.ui.dialog.displayDialog
1820
import de.rki.coronawarnapp.util.ExternalActionHelper.openUrl
@@ -30,14 +32,16 @@ class SrsSymptomsCalendarFragment : Fragment(R.layout.fragment_submission_sympto
3032
private val navArgs by navArgs<SrsSymptomsCalendarFragmentArgs>()
3133

3234
@Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
35+
private val teksSharedViewModel by navGraphViewModels<TeksSharedViewModel>(R.id.srs_nav_graph)
3336
private val viewModel: SrsSymptomsCalendarViewModel by cwaViewModelsAssisted(
3437
factoryProducer = { viewModelFactory },
3538
constructorCall = { factory, _ ->
3639
factory as SrsSymptomsCalendarViewModel.Factory
3740
factory.create(
3841
submissionType = navArgs.submissionType,
3942
selectedCheckIns = navArgs.selectedCheckIns,
40-
symptomsIndication = navArgs.symptomIndication
43+
symptomsIndication = navArgs.symptomIndication,
44+
teksSharedViewModel = teksSharedViewModel
4145
)
4246
}
4347
)

Corona-Warn-App/src/main/java/de/rki/coronawarnapp/srs/ui/symptoms/calendar/SrsSymptomsCalendarViewModel.kt

+10-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import de.rki.coronawarnapp.presencetracing.checkins.common.completedCheckIns
1010
import de.rki.coronawarnapp.srs.core.error.SrsSubmissionTruncatedException
1111
import de.rki.coronawarnapp.srs.core.model.SrsSubmissionType
1212
import de.rki.coronawarnapp.srs.core.repository.SrsSubmissionRepository
13+
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
1314
import de.rki.coronawarnapp.submission.Symptoms
1415
import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
1516
import de.rki.coronawarnapp.util.ui.SingleLiveEvent
@@ -26,6 +27,7 @@ class SrsSymptomsCalendarViewModel @AssistedInject constructor(
2627
@Assisted private val submissionType: SrsSubmissionType,
2728
@Assisted private val selectedCheckIns: LongArray,
2829
@Assisted private val symptomsIndication: Symptoms.Indication,
30+
@Assisted private val teksSharedViewModel: TeksSharedViewModel,
2931
dispatcherProvider: DispatcherProvider
3032
) : CWAViewModel(dispatcherProvider) {
3133

@@ -65,8 +67,12 @@ class SrsSymptomsCalendarViewModel @AssistedInject constructor(
6567

6668
try {
6769
srsSubmissionRepository.submit(
68-
submissionType,
69-
Symptoms(startOfSymptoms = symptomStartInternal.value, symptomIndication = symptomsIndication)
70+
type = submissionType,
71+
symptoms = Symptoms(
72+
startOfSymptoms = symptomStartInternal.value,
73+
symptomIndication = symptomsIndication
74+
),
75+
keys = teksSharedViewModel.osTeks()
7076
)
7177
events.postValue(SrsSymptomsCalendarNavigation.GoToThankYouScreen(submissionType))
7278
} catch (e: Exception) {
@@ -135,7 +141,8 @@ class SrsSymptomsCalendarViewModel @AssistedInject constructor(
135141
fun create(
136142
submissionType: SrsSubmissionType,
137143
selectedCheckIns: LongArray?,
138-
symptomsIndication: Symptoms.Indication
144+
symptomsIndication: Symptoms.Indication,
145+
teksSharedViewModel: TeksSharedViewModel
139146
): SrsSymptomsCalendarViewModel
140147
}
141148

Corona-Warn-App/src/main/java/de/rki/coronawarnapp/srs/ui/symptoms/intro/SrsSymptomsIntroductionFragment.kt

+6-1
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@ import androidx.activity.OnBackPressedCallback
88
import androidx.fragment.app.Fragment
99
import androidx.navigation.fragment.findNavController
1010
import androidx.navigation.fragment.navArgs
11+
import androidx.navigation.navGraphViewModels
1112
import de.rki.coronawarnapp.R
1213
import de.rki.coronawarnapp.databinding.FragmentSubmissionSymptomIntroBinding
1314
import de.rki.coronawarnapp.srs.ui.dialogs.showCloseDialog
1415
import de.rki.coronawarnapp.srs.ui.dialogs.showSubmissionWarningDialog
1516
import de.rki.coronawarnapp.srs.ui.dialogs.showTruncatedSubmissionDialog
17+
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
1618
import de.rki.coronawarnapp.submission.Symptoms
1719
import de.rki.coronawarnapp.ui.dialog.displayDialog
1820
import de.rki.coronawarnapp.util.ExternalActionHelper.openUrl
@@ -30,13 +32,16 @@ class SrsSymptomsIntroductionFragment : Fragment(R.layout.fragment_submission_sy
3032
private val navArgs by navArgs<SrsSymptomsIntroductionFragmentArgs>()
3133

3234
@Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
35+
36+
private val teksSharedViewModel by navGraphViewModels<TeksSharedViewModel>(R.id.srs_nav_graph)
3337
private val viewModel: SrsSymptomsIntroductionViewModel by cwaViewModelsAssisted(
3438
factoryProducer = { viewModelFactory },
3539
constructorCall = { factory, _ ->
3640
factory as SrsSymptomsIntroductionViewModel.Factory
3741
factory.create(
3842
submissionType = navArgs.submissionType,
39-
selectedCheckIns = navArgs.selectedCheckIns
43+
selectedCheckIns = navArgs.selectedCheckIns,
44+
teksSharedViewModel = teksSharedViewModel
4045
)
4146
}
4247
)

Corona-Warn-App/src/main/java/de/rki/coronawarnapp/srs/ui/symptoms/intro/SrsSymptomsIntroductionViewModel.kt

+7-3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import de.rki.coronawarnapp.presencetracing.checkins.common.completedCheckIns
99
import de.rki.coronawarnapp.srs.core.error.SrsSubmissionTruncatedException
1010
import de.rki.coronawarnapp.srs.core.model.SrsSubmissionType
1111
import de.rki.coronawarnapp.srs.core.repository.SrsSubmissionRepository
12+
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
1213
import de.rki.coronawarnapp.submission.Symptoms
1314
import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
1415
import de.rki.coronawarnapp.util.ui.SingleLiveEvent
@@ -23,6 +24,7 @@ class SrsSymptomsIntroductionViewModel @AssistedInject constructor(
2324
private val srsSubmissionRepository: SrsSubmissionRepository,
2425
@Assisted private val submissionType: SrsSubmissionType,
2526
@Assisted private val selectedCheckIns: LongArray,
27+
@Assisted private val teksSharedViewModel: TeksSharedViewModel,
2628
dispatcherProvider: DispatcherProvider
2729
) : CWAViewModel(dispatcherProvider) {
2830

@@ -73,8 +75,9 @@ class SrsSymptomsIntroductionViewModel @AssistedInject constructor(
7375

7476
try {
7577
srsSubmissionRepository.submit(
76-
submissionType,
77-
Symptoms(startOfSymptoms = null, symptomIndication = symptomsIndication)
78+
type = submissionType,
79+
symptoms = Symptoms(startOfSymptoms = null, symptomIndication = symptomsIndication),
80+
keys = teksSharedViewModel.osTeks()
7881
)
7982
events.postValue(SrsSymptomsIntroductionNavigation.GoToThankYouScreen(submissionType))
8083
} catch (e: Exception) {
@@ -131,7 +134,8 @@ class SrsSymptomsIntroductionViewModel @AssistedInject constructor(
131134

132135
fun create(
133136
submissionType: SrsSubmissionType,
134-
selectedCheckIns: LongArray?
137+
selectedCheckIns: LongArray?,
138+
teksSharedViewModel: TeksSharedViewModel
135139
): SrsSymptomsIntroductionViewModel
136140
}
137141
}

0 commit comments

Comments
 (0)