Skip to content
Snippets Groups Projects
Unverified Commit d827b587 authored by Matthias Urhahn's avatar Matthias Urhahn Committed by GitHub
Browse files

Merge branch 'release/1.15.x' into feature/4451-technical-support-main

parents 11bc39c2 1b61142f
No related branches found
No related tags found
No related merge requests found
Showing
with 100 additions and 341 deletions
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()
}
}
......@@ -12,6 +12,7 @@ import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.spyk
import kotlinx.coroutines.test.TestCoroutineScope
import org.junit.After
import org.junit.Before
import org.junit.Rule
......@@ -44,6 +45,7 @@ class ContactDiaryEditLocationsFragmentTest : BaseUITest() {
MockKAnnotations.init(this, relaxed = true)
viewModel = spyk(
ContactDiaryEditLocationsViewModel(
TestCoroutineScope(),
contactDiaryRepository,
TestDispatcherProvider()
)
......
......@@ -12,6 +12,7 @@ import io.mockk.MockKAnnotations
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.spyk
import kotlinx.coroutines.test.TestCoroutineScope
import org.junit.After
import org.junit.Before
import org.junit.Rule
......@@ -44,6 +45,7 @@ class ContactDiaryEditPersonsFragmentTest : BaseUITest() {
MockKAnnotations.init(this, relaxed = true)
viewModel = spyk(
ContactDiaryEditPersonsViewModel(
TestCoroutineScope(),
contactDiaryRepository,
TestDispatcherProvider()
)
......
......@@ -42,8 +42,7 @@ object HomeData {
lastExposureDetectionTime = Instant.now(),
lastEncounterAt = null,
allowManualUpdate = false,
daysWithEncounters = 0,
activeTracingDays = 1
daysWithEncounters = 0
),
onCardClick = {},
onUpdateClick = {}
......@@ -56,8 +55,7 @@ object HomeData {
lastExposureDetectionTime = Instant.now(),
lastEncounterAt = Instant.now(),
allowManualUpdate = false,
daysWithEncounters = 1,
activeTracingDays = 1
daysWithEncounters = 1
),
onCardClick = {},
onUpdateClick = {}
......@@ -70,7 +68,6 @@ object HomeData {
lastExposureDetectionTime = Instant.now(),
allowManualUpdate = false,
daysWithEncounters = 1,
activeTracingDays = 1,
lastEncounterAt = Instant.now()
),
onCardClick = {},
......
......@@ -9,7 +9,7 @@ import de.rki.coronawarnapp.statistics.StatisticsData
import de.rki.coronawarnapp.statistics.StatisticsModule
import de.rki.coronawarnapp.statistics.source.StatisticsParser
import de.rki.coronawarnapp.statistics.source.StatisticsServer
import de.rki.coronawarnapp.util.security.VerificationKeys
import de.rki.coronawarnapp.util.security.SignatureValidation
import de.rki.coronawarnapp.util.serialization.SerializationModule
import io.mockk.every
import io.mockk.mockk
......@@ -34,7 +34,7 @@ object Statistics {
val httpClient = HttpModule().defaultHttpClient()
val cdnClient = cdnModule.cdnHttpClient(httpClient)
val url = cdnModule.provideDownloadServerUrl(environmentSetup)
val verificationKeys = VerificationKeys(environmentSetup)
val signatureValidation = SignatureValidation(environmentSetup)
val gsonFactory = GsonConverterFactory.create()
val statisticsServer = StatisticsServer(
......@@ -47,7 +47,7 @@ object Statistics {
)
},
cache = cache,
verificationKeys = verificationKeys
signatureValidation = signatureValidation
)
return runBlocking {
......
......@@ -41,7 +41,6 @@ object TracingData {
),
PeriodLoggedBox.Item(
activeTracingDaysInRetentionPeriod = 0,
tracingStatus = GeneralTracingStatus.Status.TRACING_INACTIVE
),
DetailsLowRiskBox.Item(riskState = RiskState.LOW_RISK, matchedKeyCount = 0)
......@@ -62,7 +61,6 @@ object TracingData {
lastExposureDetectionTime = Instant.now(),
allowManualUpdate = false,
daysWithEncounters = 0,
activeTracingDays = 0,
lastEncounterAt = Instant.now()
)
),
......@@ -72,7 +70,64 @@ object TracingData {
),
PeriodLoggedBox.Item(
activeTracingDaysInRetentionPeriod = 0,
tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE
),
DetailsLowRiskBox.Item(riskState = RiskState.LOW_RISK, matchedKeyCount = 0)
)
)
val LOW_RISK_WITH_ONE_ENCOUNTER = Pair(
TracingDetailsState(
tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE,
riskState = RiskState.LOW_RISK,
isManualKeyRetrievalEnabled = false
),
listOf(
LowRiskBox.Item(
state = LowRisk(
riskState = RiskState.LOW_RISK,
isInDetailsMode = true,
lastExposureDetectionTime = Instant.now(),
allowManualUpdate = false,
daysWithEncounters = 1,
lastEncounterAt = Instant.now()
)
),
BehaviorNormalRiskBox.Item(
tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE,
riskState = RiskState.LOW_RISK
),
PeriodLoggedBox.Item(
tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE
),
DetailsLowRiskBox.Item(riskState = RiskState.LOW_RISK, matchedKeyCount = 0)
)
)
val LOW_RISK_WITH_TWO_ENCOUNTERS = Pair(
TracingDetailsState(
tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE,
riskState = RiskState.LOW_RISK,
isManualKeyRetrievalEnabled = false
),
listOf(
LowRiskBox.Item(
state = LowRisk(
riskState = RiskState.LOW_RISK,
isInDetailsMode = true,
lastExposureDetectionTime = Instant.now(),
allowManualUpdate = false,
daysWithEncounters = 2,
lastEncounterAt = Instant.now()
)
),
BehaviorNormalRiskBox.Item(
tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE,
riskState = RiskState.LOW_RISK
),
PeriodLoggedBox.Item(
tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE
),
DetailsLowRiskBox.Item(riskState = RiskState.LOW_RISK, matchedKeyCount = 0)
......@@ -93,13 +148,11 @@ object TracingData {
lastExposureDetectionTime = Instant.now(),
allowManualUpdate = false,
daysWithEncounters = 1,
activeTracingDays = 5,
lastEncounterAt = Instant.now()
)
),
BehaviorIncreasedRiskBox.Item,
PeriodLoggedBox.Item(
activeTracingDaysInRetentionPeriod = 5,
tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE
),
DetailsIncreasedRiskBox.Item(
......
......@@ -94,6 +94,20 @@ class TracingDetailsFragmentTest : BaseUITest() {
captureScreenshot("tracing_low_risk")
}
@Screenshot
@Test
fun capture_screenshot_tracing_low_risk_with_one_encounter() {
mockData(TracingData.LOW_RISK_WITH_ONE_ENCOUNTER)
captureScreenshot("tracing_low_risk_with_one_encounters")
}
@Screenshot
@Test
fun capture_screenshot_tracing_low_risk_with_two_encounters() {
mockData(TracingData.LOW_RISK_WITH_TWO_ENCOUNTERS)
captureScreenshot("tracing_low_risk_with_two_encounters")
}
@Screenshot
@Test
fun capture_screenshot_tracing_disabled() {
......
package de.rki.coronawarnapp.util.security
import android.content.Context
import androidx.test.core.app.ApplicationProvider
import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository
import de.rki.coronawarnapp.storage.AppDatabase
import de.rki.coronawarnapp.storage.tracing.TracingIntervalEntity
import de.rki.coronawarnapp.storage.tracing.TracingIntervalRepository
import de.rki.coronawarnapp.util.di.AppInjector
import de.rki.coronawarnapp.util.di.ApplicationComponent
import io.kotest.matchers.shouldBe
import io.mockk.MockKAnnotations
import io.mockk.Runs
import io.mockk.coEvery
import io.mockk.every
import io.mockk.impl.annotations.MockK
import io.mockk.just
import io.mockk.mockkObject
import kotlinx.coroutines.runBlocking
import net.sqlcipher.database.SQLiteException
import org.hamcrest.Matchers.equalTo
import org.hamcrest.Matchers.not
import org.junit.Assert.assertThat
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import testhelpers.BaseTestInstrumentation
@RunWith(JUnit4::class)
class DBPasswordTest : BaseTestInstrumentation() {
@MockK lateinit var applicationComponent: ApplicationComponent
@MockK lateinit var encryptedSharedPreferencesFactory: EncryptedPreferencesFactory
@MockK lateinit var errorResetTool: EncryptionErrorResetTool
@MockK lateinit var keyCacheRepository: KeyCacheRepository
private val appContext: Context
get() = ApplicationProvider.getApplicationContext()
private val db: AppDatabase
get() = AppDatabase.getInstance(appContext)
@Before
fun setUp() {
MockKAnnotations.init(this)
mockkObject(AppInjector)
every { AppInjector.component } returns applicationComponent
encryptedSharedPreferencesFactory = EncryptedPreferencesFactory(appContext)
every { applicationComponent.encryptedPreferencesFactory } returns encryptedSharedPreferencesFactory
every { applicationComponent.errorResetTool } returns errorResetTool
every { applicationComponent.keyCacheRepository } returns keyCacheRepository.apply {
coEvery { keyCacheRepository.clear() } just Runs
}
mockkObject(TracingIntervalRepository)
every { TracingIntervalRepository.resetInstance() } just Runs
clearSharedPreferences()
AppDatabase.reset(appContext)
}
@Test
fun generatesPassphraseInCorrectLength() {
val passphrase = SecurityHelper.getDBPassword()
assertTrue(passphrase.size in 32..48)
}
@Test
fun secondPassphraseShouldBeDifferFromFirst() {
val passphrase1 = SecurityHelper.getDBPassword()
clearSharedPreferences()
val passphrase2 = SecurityHelper.getDBPassword()
assertThat(passphrase1, not(equalTo(passphrase2)))
}
@Test
fun canLoadDataFromEncryptedDatabase() {
runBlocking {
val from = 123L
val to = 456L
insertFakeEntity(from, to)
loadFakeEntity().apply {
this.from shouldBe from
this.to shouldBe to
}
}
}
@Test
fun testDbInstanceIsActuallyResetWhenCalled() {
val before = this.db
AppDatabase.reset(appContext)
val after = this.db
assertTrue(before != after)
}
@Test(expected = SQLiteException::class)
fun loadingDataFromDatabaseWillFailWhenPassphraseIsIncorrect() {
runBlocking {
val from = 123L
val to = 456L
insertFakeEntity(from, to)
clearSharedPreferences()
AppDatabase.resetInstance()
loadFakeEntity().apply {
this.from shouldBe from
this.to shouldBe to
}
}
}
private suspend fun insertFakeEntity(
from: Long,
to: Long
) {
db.tracingIntervalDao().insertInterval(
TracingIntervalEntity().apply {
this.from = from
this.to = to
}
)
}
private suspend fun loadFakeEntity(): TracingIntervalEntity =
db.tracingIntervalDao().getAllIntervals().first()
private fun clearSharedPreferences() =
SecurityHelper.globalEncryptedSharedPreferencesInstance.edit().clear().commit()
}
......@@ -23,33 +23,33 @@ class VerificationKeysTest {
every { environmentSetup.appConfigVerificationKey } returns PUB_KEY
}
private fun createTool() = VerificationKeys(environmentSetup)
private fun createTool() = SignatureValidation(environmentSetup)
@Test
fun goodBinaryAndSignature() {
val tool = createTool()
tool.hasInvalidSignature(
tool.hasValidSignature(
GOOD_BINARY.decodeHex().toByteArray(),
GOOD_SIGNATURE.decodeHex().toByteArray()
) shouldBe false
SignatureValidation.parseTEKStyleSignature(GOOD_SIGNATURE.decodeHex().toByteArray())
) shouldBe true
}
@Test
fun badBinaryGoodSignature() {
val tool = createTool()
tool.hasInvalidSignature(
tool.hasValidSignature(
"123ABC".decodeHex().toByteArray(),
GOOD_SIGNATURE.decodeHex().toByteArray()
) shouldBe true
SignatureValidation.parseTEKStyleSignature(GOOD_SIGNATURE.decodeHex().toByteArray())
) shouldBe false
}
@Test
fun goodBinaryBadSignature() {
val tool = createTool()
shouldThrow<CwaSecurityException> {
tool.hasInvalidSignature(
tool.hasValidSignature(
GOOD_BINARY.decodeHex().toByteArray(),
"123ABC".decodeHex().toByteArray()
SignatureValidation.parseTEKStyleSignature("123ABC".decodeHex().toByteArray())
)
}
}
......@@ -58,9 +58,9 @@ class VerificationKeysTest {
fun badEverything() {
val tool = createTool()
shouldThrow<CwaSecurityException> {
tool.hasInvalidSignature(
tool.hasValidSignature(
"123ABC".decodeHex().toByteArray(),
"123ABC".decodeHex().toByteArray()
SignatureValidation.parseTEKStyleSignature("123ABC".decodeHex().toByteArray())
)
}
}
......
......@@ -2,7 +2,6 @@ package de.rki.coronawarnapp.risk.storage
import de.rki.coronawarnapp.risk.RiskLevelResult
import de.rki.coronawarnapp.risk.storage.internal.RiskResultDatabase
import de.rki.coronawarnapp.risk.storage.legacy.RiskLevelResultMigrator
import de.rki.coronawarnapp.util.coroutine.AppScope
import kotlinx.coroutines.CoroutineScope
import timber.log.Timber
......@@ -12,9 +11,8 @@ import javax.inject.Singleton
@Singleton
class DefaultRiskLevelStorage @Inject constructor(
riskResultDatabaseFactory: RiskResultDatabase.Factory,
riskLevelResultMigrator: RiskLevelResultMigrator,
@AppScope scope: CoroutineScope
) : BaseRiskLevelStorage(riskResultDatabaseFactory, riskLevelResultMigrator, scope) {
) : BaseRiskLevelStorage(riskResultDatabaseFactory, scope) {
// 2 days, 6 times per day, data is considered stale after 48 hours with risk calculation
// Taken from TimeVariables.MAX_STALE_EXPOSURE_RISK_RANGE
......
......@@ -34,14 +34,6 @@ class MiscInfoFragment : Fragment(R.layout.fragment_test_deviceinfo), AutoInject
binding.googlePlayServicesVersionInfo.text = "Google Play Services: ${it.gmsVersion}"
binding.exposureNotificationServiceVersionInfo.text = "Exposure Notification Services: ${it.enfVersion}"
}
vm.inActiveTracingIntervals.observe2(this) {
binding.tracingInfosInactiveIntervals.text = "Inactive tracing intervals:\n$it"
}
vm.tracingDaysInRetention.observe2(this) {
binding.tracingInfosActiveTracingRetention.text = "Active tracing days in retention period: $it"
}
}
companion object {
......
......@@ -7,15 +7,12 @@ import com.google.android.gms.common.GoogleApiAvailability
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import de.rki.coronawarnapp.nearby.ENFClient
import de.rki.coronawarnapp.risk.TimeVariables
import de.rki.coronawarnapp.storage.tracing.TracingIntervalRepository
import de.rki.coronawarnapp.util.coroutine.DispatcherProvider
import de.rki.coronawarnapp.util.di.AppContext
import de.rki.coronawarnapp.util.ui.SingleLiveEvent
import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
import kotlinx.coroutines.flow.flow
import org.joda.time.Instant
import timber.log.Timber
class MiscInfoFragmentViewModel @AssistedInject constructor(
......@@ -49,17 +46,6 @@ class MiscInfoFragmentViewModel @AssistedInject constructor(
)
}.asLiveData(context = dispatcherProvider.Default)
val inActiveTracingIntervals = flow {
TracingIntervalRepository.getDateRepository(context)
.getIntervals()
.map { Instant.ofEpochMilli(it.first) to Instant.ofEpochMilli(it.second) }
.let { emit(it.joinToString("\n")) }
}.asLiveData(context = dispatcherProvider.Default)
val tracingDaysInRetention = flow {
emit(TimeVariables.getActiveTracingDaysInRetentionPeriod())
}.asLiveData(context = dispatcherProvider.Default)
@AssistedFactory
interface Factory : SimpleCWAViewModelFactory<MiscInfoFragmentViewModel>
}
......@@ -5,7 +5,6 @@ import de.rki.coronawarnapp.risk.storage.internal.RiskResultDatabase
import de.rki.coronawarnapp.risk.storage.internal.windows.PersistedExposureWindowDao.PersistedScanInstance
import de.rki.coronawarnapp.risk.storage.internal.windows.toPersistedExposureWindow
import de.rki.coronawarnapp.risk.storage.internal.windows.toPersistedScanInstances
import de.rki.coronawarnapp.risk.storage.legacy.RiskLevelResultMigrator
import de.rki.coronawarnapp.util.coroutine.AppScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.firstOrNull
......@@ -16,9 +15,8 @@ import javax.inject.Singleton
@Singleton
class DefaultRiskLevelStorage @Inject constructor(
riskResultDatabaseFactory: RiskResultDatabase.Factory,
riskLevelResultMigrator: RiskLevelResultMigrator,
@AppScope val scope: CoroutineScope
) : BaseRiskLevelStorage(riskResultDatabaseFactory, riskLevelResultMigrator, scope) {
) : BaseRiskLevelStorage(riskResultDatabaseFactory, scope) {
// 14 days, 6 times per day
// For testers keep all the results!
......
......@@ -11,7 +11,6 @@ import de.rki.coronawarnapp.bugreporting.reportProblem
import de.rki.coronawarnapp.bugreporting.storage.repository.BugRepository
import de.rki.coronawarnapp.util.viewmodel.CWAViewModel
import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory
import kotlinx.coroutines.Dispatchers
import timber.log.Timber
class SettingsCrashReportViewModel @AssistedInject constructor(
......@@ -26,7 +25,7 @@ class SettingsCrashReportViewModel @AssistedInject constructor(
createBugEventFormattedText(it)
}
fun deleteAllCrashReports() = launch(Dispatchers.IO) {
fun deleteAllCrashReports() = launch {
crashReportRepository.clear()
}
......
......@@ -9,7 +9,6 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import de.rki.coronawarnapp.appconfig.AppConfigProvider
import de.rki.coronawarnapp.appconfig.ConfigData
import de.rki.coronawarnapp.diagnosiskeys.download.DownloadDiagnosisKeysSettings
import de.rki.coronawarnapp.diagnosiskeys.download.DownloadDiagnosisKeysTask
import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository
......@@ -17,7 +16,6 @@ import de.rki.coronawarnapp.nearby.modules.detectiontracker.ExposureDetectionTra
import de.rki.coronawarnapp.nearby.modules.detectiontracker.latestSubmission
import de.rki.coronawarnapp.risk.RiskLevelTask
import de.rki.coronawarnapp.risk.RiskState
import de.rki.coronawarnapp.risk.TimeVariables
import de.rki.coronawarnapp.risk.result.AggregatedRiskResult
import de.rki.coronawarnapp.risk.storage.RiskLevelStorage
import de.rki.coronawarnapp.risk.tryLatestResultsWithDefaults
......@@ -39,7 +37,6 @@ import org.joda.time.Instant
import org.joda.time.format.DateTimeFormat
import timber.log.Timber
import java.io.File
import java.util.concurrent.TimeUnit
class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor(
@Assisted private val handle: SavedStateHandle,
......@@ -109,31 +106,9 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor(
val backendParameters = appConfigProvider
.currentConfig
.map { it.toReadableString() }
.map { it.rawConfig.riskCalculationParameters.toString() }
.asLiveData()
private fun ConfigData.toReadableString(): String = StringBuilder()
.appendLine("Transmission RiskLevel Multiplier: $transmissionRiskLevelMultiplier")
.appendLine()
.appendLine("Minutes At Attenuation Filters:")
.appendLine(minutesAtAttenuationFilters)
.appendLine()
.appendLine("Minutes At Attenuation Weights:")
.appendLine(minutesAtAttenuationWeights)
.appendLine()
.appendLine("Transmission RiskLevel Encoding:")
.appendLine(transmissionRiskLevelEncoding)
.appendLine()
.appendLine("Transmission RiskLevel Filters:")
.appendLine(transmissionRiskLevelFilters)
.appendLine()
.appendLine("Normalized Time Per Exposure Window To RiskLevel Mapping:")
.appendLine(normalizedTimePerExposureWindowToRiskLevelMapping)
.appendLine()
.appendLine("Normalized Time Per Day To RiskLevel Mapping List:")
.appendLine(normalizedTimePerDayToRiskLevelMappingList)
.toString()
val additionalRiskCalcInfo = combine(
riskLevelStorage.latestAndLastSuccessful,
exposureDetectionTracker.latestSubmission()
......@@ -164,8 +139,6 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor(
.appendLine("Matched key count: $matchedKeyCount")
.appendLine("Days since last Exposure: $daysSinceLastExposure days")
.appendLine("Last key submission: $lastKeySubmission")
.appendLine("Tracing Duration: ${TimeUnit.MILLISECONDS.toDays(TimeVariables.getTimeActiveTracingDuration())} days")
.appendLine("Tracing Duration in last 14 days: ${TimeVariables.getActiveTracingDaysInRetentionPeriod()} days")
.appendLine("Last time risk level calculation $lastTimeRiskLevelCalculation")
.toString()
......@@ -202,7 +175,7 @@ class TestRiskLevelCalculationFragmentCWAViewModel @AssistedInject constructor(
fun shareExposureWindows() {
Timber.d("Creating text file for Exposure Windows")
launch(dispatcherProvider.IO) {
launch {
val exposureWindows = lastRiskResult.firstOrNull()?.exposureWindows?.map { it.toExposureWindowJson() }
val fileNameCompatibleTimestamp = timeStamper.nowUTC.toString(
DateTimeFormat.forPattern("yyyy-MM-DD-HH-mm-ss")
......
......@@ -54,48 +54,6 @@
app:layout_constraintTop_toBottomOf="@+id/google_play_services_version_info" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/tracing_container"
style="@style/Card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="@dimen/spacing_tiny">
<TextView
android:id="@+id/tracing_container_title"
style="@style/headline6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Tracing Infos"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tracing_infos_inactive_intervals"
style="@style/body2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_tiny"
android:text="Inactive tracing intervals: ?"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tracing_container_title" />
<TextView
android:id="@+id/tracing_infos_active_tracing_retention"
style="@style/body2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/spacing_tiny"
android:text="Active tracing days in retention period: ?"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tracing_infos_inactive_intervals" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</layout>
No preview for this file type
12d0b93c0c02c6870ef75c173a53a8ffb9cab6828fbf22e751053329c425eef2
\ No newline at end of file
3d108b3fee7d1b4c227087c82bb804048de8d0542c3f2b26cf507a918201124d
\ No newline at end of file
......@@ -9,11 +9,11 @@ interface ExposureWindowRiskCalculationConfig {
val minutesAtAttenuationWeights: List<RiskCalculationParametersOuterClass.MinutesAtAttenuationWeight>
val transmissionRiskLevelEncoding: RiskCalculationParametersOuterClass.TransmissionRiskLevelEncoding
val transmissionRiskLevelFilters: List<RiskCalculationParametersOuterClass.TrlFilter>
val transmissionRiskLevelMultiplier: Double
val normalizedTimePerExposureWindowToRiskLevelMapping:
List<RiskCalculationParametersOuterClass.NormalizedTimeToRiskLevelMapping>
val normalizedTimePerDayToRiskLevelMappingList:
List<RiskCalculationParametersOuterClass.NormalizedTimeToRiskLevelMapping>
val transmissionRiskValueMapping: List<RiskCalculationParametersOuterClass.TransmissionRiskValueMapping>
val diagnosisKeysDataMapping: DiagnosisKeysDataMapping
interface Mapper {
......
......@@ -6,6 +6,6 @@ import retrofit2.http.GET
interface AppConfigApiV2 {
@GET("/version/v1/app_config_android")
@GET("/version/v2/app_config_android")
suspend fun getApplicationConfiguration(): Response<ResponseBody>
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment