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

Commit

Permalink
SRS : Teks on fly (EXPOSUREAPP-14489) (#5770)
Browse files Browse the repository at this point in the history
* Create persisted TEKs

* Request OS keys directly

* Use os keys

* Pass teks

* Tests

* Don't update cache

* Tests

* Update TEKHistoryUpdaterTest.kt
  • Loading branch information
mtwalli authored Dec 21, 2022
1 parent f935d40 commit 348bdce
Show file tree
Hide file tree
Showing 19 changed files with 297 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.test.internal.runner.junit4.statement.UiThreadStatement
import dagger.Module
import dagger.android.ContributesAndroidInjector
import de.rki.coronawarnapp.R
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
import de.rki.coronawarnapp.util.ui.SingleLiveEvent
import io.mockk.MockKAnnotations
import io.mockk.every
Expand Down Expand Up @@ -55,7 +56,8 @@ class SrsSubmissionConsentFragmentTest : BaseUITest() {
setupMockViewModel(
object : SrsSubmissionConsentFragmentViewModel.Factory {
override fun create(
openTypeSelection: Boolean
openTypeSelection: Boolean,
teksSharedViewModel: TeksSharedViewModel
): SrsSubmissionConsentFragmentViewModel = viewModel
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ class SubmissionTestFragmentViewModel @AssistedInject constructor(

fun submit() = launch {
try {
srsSubmissionRepository.submit(type = SrsSubmissionType.SRS_SELF_TEST)
srsSubmissionRepository.submit(
type = SrsSubmissionType.SRS_SELF_TEST,
keys = tekHistory.value.orEmpty().map { it.key }
)
srsSubmissionResult.postValue(Success)
} catch (e: Exception) {
Timber.e(e, "submit()")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,13 @@
android:gravity="center"
android:text="_________ For DEVs _________" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:gravity="center"
android:text="Click 'Get TEKs' button before submitting " />

<Button
android:id="@+id/submit"
style="@style/buttonPrimary"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package de.rki.coronawarnapp.srs.core.model

import android.os.Parcelable
import com.google.android.gms.nearby.exposurenotification.TemporaryExposureKey
import kotlinx.parcelize.Parcelize

@Parcelize
data class TekPatch(
val parcelableTeks: List<ParcelableTek>
) : Parcelable {

fun osKeys(): List<TemporaryExposureKey> = parcelableTeks.map { pKey -> pKey.toTemporaryExposureKey() }

@Parcelize
data class ParcelableTek(
val keyData: ByteArray,
val rollingStartIntervalNumber: Int,
val transmissionRiskLevel: Int,
val rollingPeriod: Int,
val reportType: Int,
val daysSinceOnsetOfSymptoms: Int
) : Parcelable {

fun toTemporaryExposureKey(): TemporaryExposureKey = TemporaryExposureKey.TemporaryExposureKeyBuilder()
.apply {
setKeyData(keyData)
setRollingStartIntervalNumber(rollingStartIntervalNumber)
setTransmissionRiskLevel(transmissionRiskLevel)
setRollingPeriod(rollingPeriod)
setReportType(reportType)
if (daysSinceOnsetOfSymptoms != TemporaryExposureKey.DAYS_SINCE_ONSET_OF_SYMPTOMS_UNKNOWN) {
setDaysSinceOnsetOfSymptoms(daysSinceOnsetOfSymptoms)
}
}.build()

override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false

other as ParcelableTek

if (!keyData.contentEquals(other.keyData)) return false
if (rollingStartIntervalNumber != other.rollingStartIntervalNumber) return false
if (transmissionRiskLevel != other.transmissionRiskLevel) return false
if (rollingPeriod != other.rollingPeriod) return false
if (reportType != other.reportType) return false
if (daysSinceOnsetOfSymptoms != other.daysSinceOnsetOfSymptoms) return false

return true
}

override fun hashCode(): Int {
var result = keyData.contentHashCode()
result = 31 * result + rollingStartIntervalNumber
result = 31 * result + transmissionRiskLevel
result = 31 * result + rollingPeriod
result = 31 * result + reportType
result = 31 * result + daysSinceOnsetOfSymptoms
return result
}
}

companion object {
fun patchFrom(osKeys: List<TemporaryExposureKey>) = TekPatch(
parcelableTeks = osKeys.map { oskey -> oskey.toParcelableTek() }
)
}
}

fun TemporaryExposureKey.toParcelableTek() = TekPatch.ParcelableTek(
keyData = this.keyData,
rollingStartIntervalNumber = this.rollingStartIntervalNumber,
transmissionRiskLevel = this.transmissionRiskLevel,
rollingPeriod = this.rollingPeriod,
reportType = this.reportType,
daysSinceOnsetOfSymptoms = this.daysSinceOnsetOfSymptoms
)
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import de.rki.coronawarnapp.srs.core.server.errorArgs
import de.rki.coronawarnapp.srs.core.storage.SrsDevSettings
import de.rki.coronawarnapp.srs.core.storage.SrsSubmissionSettings
import de.rki.coronawarnapp.submission.Symptoms
import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryStorage
import de.rki.coronawarnapp.submission.task.ExposureKeyHistoryCalculations
import de.rki.coronawarnapp.tag
import de.rki.coronawarnapp.util.TimeStamper
Expand All @@ -43,7 +42,6 @@ class SrsSubmissionRepository @Inject constructor(
private val playbook: SrsPlaybook,
private val appConfigProvider: AppConfigProvider,
private val tekCalculations: ExposureKeyHistoryCalculations,
private val tekStorage: TEKHistoryStorage,
private val timeStamper: TimeStamper,
private val checkInsRepo: CheckInRepository,
private val checkInsTransformer: CheckInsTransformer,
Expand All @@ -55,7 +53,8 @@ class SrsSubmissionRepository @Inject constructor(
) {
suspend fun submit(
type: SrsSubmissionType,
symptoms: Symptoms = Symptoms.NO_INFO_GIVEN
symptoms: Symptoms = Symptoms.NO_INFO_GIVEN,
keys: List<TemporaryExposureKey>
) {
Timber.tag(TAG).d("submit(type=%s)", type)
val appConfig = appConfigProvider.getAppConfig()
Expand Down Expand Up @@ -91,12 +90,6 @@ class SrsSubmissionRepository @Inject constructor(
srsSubmissionSettings.setOtp(srsOtp)
}

val keys: List<TemporaryExposureKey> = runCatching {
tekStorage.tekData.first().flatMap { it.keys }
}.onFailure {
Timber.w(it, "No temporary exposure keys")
}.getOrDefault(emptyList())

val transformedKeys = tekCalculations.transformToKeyHistoryInExternalFormat(keys, symptoms)
Timber.tag(TAG).d("Transformed keys with symptoms %s from %s to %s", symptoms, keys, transformedKeys)

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

Timber.tag(TAG).d("Submission successful, deleting submission data.")
tekStorage.reset()

Timber.tag(TAG).d("Marking %d submitted CheckIns.", checkIns.size)
checkInsRepo.updatePostSubmissionFlags(checkIns)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import android.view.View
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.navigation.navGraphViewModels
import de.rki.coronawarnapp.R
import de.rki.coronawarnapp.databinding.FragmentSrsSubmissionConsentBinding
import de.rki.coronawarnapp.srs.core.model.SrsSubmissionType
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
import de.rki.coronawarnapp.tracing.ui.tracingConsentDialog
import de.rki.coronawarnapp.ui.submission.SubmissionBlockingDialog
import de.rki.coronawarnapp.util.di.AutoInject
Expand All @@ -23,11 +25,15 @@ class SrsSubmissionConsentFragment : Fragment(R.layout.fragment_srs_submission_c

@Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
private val navArgs by navArgs<SrsSubmissionConsentFragmentArgs>()
private val teksSharedViewModel by navGraphViewModels<TeksSharedViewModel>(R.id.srs_nav_graph)
private val viewModel: SrsSubmissionConsentFragmentViewModel by cwaViewModelsAssisted(
factoryProducer = { viewModelFactory },
constructorCall = { factory, _ ->
factory as SrsSubmissionConsentFragmentViewModel.Factory
factory.create(navArgs.openTypeSelection)
factory.create(
navArgs.openTypeSelection,
teksSharedViewModel
)
}
)
private val binding by viewBinding<FragmentSrsSubmissionConsentBinding>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import de.rki.coronawarnapp.exception.ExceptionCategory
import de.rki.coronawarnapp.exception.reporting.report
import de.rki.coronawarnapp.presencetracing.checkins.CheckInRepository
import de.rki.coronawarnapp.presencetracing.checkins.common.completedCheckIns
import de.rki.coronawarnapp.srs.core.model.TekPatch
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
import de.rki.coronawarnapp.submission.data.tekhistory.TEKHistoryUpdater
import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
import de.rki.coronawarnapp.util.ui.SingleLiveEvent
Expand All @@ -22,6 +24,7 @@ import timber.log.Timber

class SrsSubmissionConsentFragmentViewModel @AssistedInject constructor(
@Assisted private val openTypeSelection: Boolean,
@Assisted private val teksSharedViewModel: TeksSharedViewModel,
private val checkInRepository: CheckInRepository,
appConfigProvider: AppConfigProvider,
dispatcherProvider: DispatcherProvider,
Expand Down Expand Up @@ -74,6 +77,7 @@ class SrsSubmissionConsentFragmentViewModel @AssistedInject constructor(
suspend fun onTekAvailable(teks: List<TemporaryExposureKey>) {
Timber.tag(TAG).d("onTEKAvailable(teks.size=%d)", teks.size)
showKeysRetrievalProgress.postValue(false)
teksSharedViewModel.setTekPatch(TekPatch.patchFrom(teks))

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

fun submissionConsentAcceptButtonClicked() {
tekHistoryUpdater.getTeksOrRequestPermission()
tekHistoryUpdater.getTeksOrRequestPermissionFromOS()
}

fun handleActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
showKeysRetrievalProgress.value = true
tekHistoryUpdater.handleActivityResult(requestCode, resultCode, data)
tekHistoryUpdater.handleActivityResult(
requestCode = requestCode,
resultCode = resultCode,
data = data,
updateCache = false
)
}

fun onConsentCancel() {
Expand All @@ -111,7 +120,8 @@ class SrsSubmissionConsentFragmentViewModel @AssistedInject constructor(
@AssistedFactory
interface Factory : CWAViewModelFactory<SrsSubmissionConsentFragmentViewModel> {
fun create(
openTypeSelection: Boolean
openTypeSelection: Boolean,
teksSharedViewModel: TeksSharedViewModel
): SrsSubmissionConsentFragmentViewModel
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.navigation.navGraphViewModels
import de.rki.coronawarnapp.R
import de.rki.coronawarnapp.databinding.FragmentSubmissionSymptomCalendarBinding
import de.rki.coronawarnapp.srs.ui.dialogs.showCloseDialog
import de.rki.coronawarnapp.srs.ui.dialogs.showSubmissionWarningDialog
import de.rki.coronawarnapp.srs.ui.dialogs.showTruncatedSubmissionDialog
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
import de.rki.coronawarnapp.submission.Symptoms
import de.rki.coronawarnapp.ui.dialog.displayDialog
import de.rki.coronawarnapp.util.ExternalActionHelper.openUrl
Expand All @@ -30,14 +32,16 @@ class SrsSymptomsCalendarFragment : Fragment(R.layout.fragment_submission_sympto
private val navArgs by navArgs<SrsSymptomsCalendarFragmentArgs>()

@Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
private val teksSharedViewModel by navGraphViewModels<TeksSharedViewModel>(R.id.srs_nav_graph)
private val viewModel: SrsSymptomsCalendarViewModel by cwaViewModelsAssisted(
factoryProducer = { viewModelFactory },
constructorCall = { factory, _ ->
factory as SrsSymptomsCalendarViewModel.Factory
factory.create(
submissionType = navArgs.submissionType,
selectedCheckIns = navArgs.selectedCheckIns,
symptomsIndication = navArgs.symptomIndication
symptomsIndication = navArgs.symptomIndication,
teksSharedViewModel = teksSharedViewModel
)
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import de.rki.coronawarnapp.presencetracing.checkins.common.completedCheckIns
import de.rki.coronawarnapp.srs.core.error.SrsSubmissionTruncatedException
import de.rki.coronawarnapp.srs.core.model.SrsSubmissionType
import de.rki.coronawarnapp.srs.core.repository.SrsSubmissionRepository
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
import de.rki.coronawarnapp.submission.Symptoms
import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
import de.rki.coronawarnapp.util.ui.SingleLiveEvent
Expand All @@ -26,6 +27,7 @@ class SrsSymptomsCalendarViewModel @AssistedInject constructor(
@Assisted private val submissionType: SrsSubmissionType,
@Assisted private val selectedCheckIns: LongArray,
@Assisted private val symptomsIndication: Symptoms.Indication,
@Assisted private val teksSharedViewModel: TeksSharedViewModel,
dispatcherProvider: DispatcherProvider
) : CWAViewModel(dispatcherProvider) {

Expand Down Expand Up @@ -65,8 +67,12 @@ class SrsSymptomsCalendarViewModel @AssistedInject constructor(

try {
srsSubmissionRepository.submit(
submissionType,
Symptoms(startOfSymptoms = symptomStartInternal.value, symptomIndication = symptomsIndication)
type = submissionType,
symptoms = Symptoms(
startOfSymptoms = symptomStartInternal.value,
symptomIndication = symptomsIndication
),
keys = teksSharedViewModel.osTeks()
)
events.postValue(SrsSymptomsCalendarNavigation.GoToThankYouScreen(submissionType))
} catch (e: Exception) {
Expand Down Expand Up @@ -135,7 +141,8 @@ class SrsSymptomsCalendarViewModel @AssistedInject constructor(
fun create(
submissionType: SrsSubmissionType,
selectedCheckIns: LongArray?,
symptomsIndication: Symptoms.Indication
symptomsIndication: Symptoms.Indication,
teksSharedViewModel: TeksSharedViewModel
): SrsSymptomsCalendarViewModel
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.navigation.navGraphViewModels
import de.rki.coronawarnapp.R
import de.rki.coronawarnapp.databinding.FragmentSubmissionSymptomIntroBinding
import de.rki.coronawarnapp.srs.ui.dialogs.showCloseDialog
import de.rki.coronawarnapp.srs.ui.dialogs.showSubmissionWarningDialog
import de.rki.coronawarnapp.srs.ui.dialogs.showTruncatedSubmissionDialog
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
import de.rki.coronawarnapp.submission.Symptoms
import de.rki.coronawarnapp.ui.dialog.displayDialog
import de.rki.coronawarnapp.util.ExternalActionHelper.openUrl
Expand All @@ -30,13 +32,16 @@ class SrsSymptomsIntroductionFragment : Fragment(R.layout.fragment_submission_sy
private val navArgs by navArgs<SrsSymptomsIntroductionFragmentArgs>()

@Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory

private val teksSharedViewModel by navGraphViewModels<TeksSharedViewModel>(R.id.srs_nav_graph)
private val viewModel: SrsSymptomsIntroductionViewModel by cwaViewModelsAssisted(
factoryProducer = { viewModelFactory },
constructorCall = { factory, _ ->
factory as SrsSymptomsIntroductionViewModel.Factory
factory.create(
submissionType = navArgs.submissionType,
selectedCheckIns = navArgs.selectedCheckIns
selectedCheckIns = navArgs.selectedCheckIns,
teksSharedViewModel = teksSharedViewModel
)
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import de.rki.coronawarnapp.presencetracing.checkins.common.completedCheckIns
import de.rki.coronawarnapp.srs.core.error.SrsSubmissionTruncatedException
import de.rki.coronawarnapp.srs.core.model.SrsSubmissionType
import de.rki.coronawarnapp.srs.core.repository.SrsSubmissionRepository
import de.rki.coronawarnapp.srs.ui.vm.TeksSharedViewModel
import de.rki.coronawarnapp.submission.Symptoms
import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
import de.rki.coronawarnapp.util.ui.SingleLiveEvent
Expand All @@ -23,6 +24,7 @@ class SrsSymptomsIntroductionViewModel @AssistedInject constructor(
private val srsSubmissionRepository: SrsSubmissionRepository,
@Assisted private val submissionType: SrsSubmissionType,
@Assisted private val selectedCheckIns: LongArray,
@Assisted private val teksSharedViewModel: TeksSharedViewModel,
dispatcherProvider: DispatcherProvider
) : CWAViewModel(dispatcherProvider) {

Expand Down Expand Up @@ -73,8 +75,9 @@ class SrsSymptomsIntroductionViewModel @AssistedInject constructor(

try {
srsSubmissionRepository.submit(
submissionType,
Symptoms(startOfSymptoms = null, symptomIndication = symptomsIndication)
type = submissionType,
symptoms = Symptoms(startOfSymptoms = null, symptomIndication = symptomsIndication),
keys = teksSharedViewModel.osTeks()
)
events.postValue(SrsSymptomsIntroductionNavigation.GoToThankYouScreen(submissionType))
} catch (e: Exception) {
Expand Down Expand Up @@ -131,7 +134,8 @@ class SrsSymptomsIntroductionViewModel @AssistedInject constructor(

fun create(
submissionType: SrsSubmissionType,
selectedCheckIns: LongArray?
selectedCheckIns: LongArray?,
teksSharedViewModel: TeksSharedViewModel
): SrsSymptomsIntroductionViewModel
}
}
Loading

0 comments on commit 348bdce

Please sign in to comment.