diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 32327027218..aa533f1bc24 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -125,6 +125,8 @@ diff --git a/Corona-Warn-App/build.gradle b/Corona-Warn-App/build.gradle index 1d3229d5b65..384bcddf02b 100644 --- a/Corona-Warn-App/build.gradle +++ b/Corona-Warn-App/build.gradle @@ -276,6 +276,8 @@ dependencies { testImplementation "io.kotest:kotest-runner-junit5:4.2.0" testImplementation "io.kotest:kotest-assertions-core-jvm:4.2.0" testImplementation "io.kotest:kotest-property-jvm:4.2.0" + androidTestImplementation "io.kotest:kotest-assertions-core-jvm:4.2.0" + androidTestImplementation "io.kotest:kotest-property-jvm:4.2.0" // Testing - Instrumentation androidTestImplementation 'androidx.test:runner:1.2.0' diff --git a/Corona-Warn-App/schemas/de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheDatabase/1.json b/Corona-Warn-App/schemas/de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheDatabase/1.json new file mode 100644 index 00000000000..72e78dde4ed --- /dev/null +++ b/Corona-Warn-App/schemas/de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheDatabase/1.json @@ -0,0 +1,76 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "c4ef5f7d4d9672d11c8eb97a63d4a3c5", + "entities": [ + { + "tableName": "keyfiles", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `type` TEXT NOT NULL, `location` TEXT NOT NULL, `day` TEXT NOT NULL, `hour` TEXT, `createdAt` TEXT NOT NULL, `checksumMD5` TEXT, `completed` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "location", + "columnName": "location", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "day", + "columnName": "day", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hour", + "columnName": "hour", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "checksumMD5", + "columnName": "checksumMD5", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isDownloadComplete", + "columnName": "completed", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'c4ef5f7d4d9672d11c8eb97a63d4a3c5')" + ] + } +} \ No newline at end of file diff --git a/Corona-Warn-App/schemas/de.rki.coronawarnapp.storage.keycache.KeyCacheDatabase/1.json b/Corona-Warn-App/schemas/de.rki.coronawarnapp.storage.keycache.KeyCacheDatabase/1.json new file mode 100644 index 00000000000..9d856a5a015 --- /dev/null +++ b/Corona-Warn-App/schemas/de.rki.coronawarnapp.storage.keycache.KeyCacheDatabase/1.json @@ -0,0 +1,82 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "03f6e8cba631c8ef60e506006913a1ad", + "entities": [ + { + "tableName": "keyfiles", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `type` TEXT NOT NULL, `location` TEXT NOT NULL, `day` TEXT NOT NULL, `hour` TEXT, `sourceUrl` TEXT NOT NULL, `createdAt` TEXT NOT NULL, `checksumMD5` TEXT, `completed` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "type", + "columnName": "type", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "location", + "columnName": "location", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "day", + "columnName": "day", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "hour", + "columnName": "hour", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "sourceUrl", + "columnName": "sourceUrl", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "createdAt", + "columnName": "createdAt", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "checksumMD5", + "columnName": "checksumMD5", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "isDownloadComplete", + "columnName": "completed", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": false + }, + "indices": [], + "foreignKeys": [] + } + ], + "views": [], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '03f6e8cba631c8ef60e506006913a1ad')" + ] + } +} \ No newline at end of file diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/diagnosiskeys/storage/KeyCacheDatabaseTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/diagnosiskeys/storage/KeyCacheDatabaseTest.kt new file mode 100644 index 00000000000..ac0ccdefe87 --- /dev/null +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/diagnosiskeys/storage/KeyCacheDatabaseTest.kt @@ -0,0 +1,79 @@ +package de.rki.coronawarnapp.diagnosiskeys.storage + +import android.content.Context +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import de.rki.coronawarnapp.diagnosiskeys.server.LocationCode +import io.kotest.matchers.shouldBe +import kotlinx.coroutines.runBlocking +import org.joda.time.Instant +import org.joda.time.LocalDate +import org.joda.time.LocalTime +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class KeyCacheDatabaseTest { + private val database = KeyCacheDatabase.Factory( + ApplicationProvider.getApplicationContext() + ).create() + private val dao = database.cachedKeyFiles() + + @Test + fun crud() { + val keyDay = CachedKeyInfo( + type = CachedKeyInfo.Type.COUNTRY_DAY, + location = LocationCode("DE"), + day = LocalDate.now(), + hour = null, + createdAt = Instant.now() + ) + val keyHour = CachedKeyInfo( + type = CachedKeyInfo.Type.COUNTRY_HOUR, + location = LocationCode("DE"), + day = LocalDate.now(), + hour = LocalTime.now(), + createdAt = Instant.now() + ) + runBlocking { + dao.clear() + + dao.insertEntry(keyDay) + dao.insertEntry(keyHour) + dao.getAllEntries() shouldBe listOf(keyDay, keyHour) + dao.getEntriesForType(CachedKeyInfo.Type.COUNTRY_DAY.typeValue) shouldBe listOf(keyDay) + dao.getEntriesForType(CachedKeyInfo.Type.COUNTRY_HOUR.typeValue) shouldBe listOf(keyHour) + + dao.updateDownloadState(keyDay.toDownloadUpdate("coffee")) + dao.getEntriesForType(CachedKeyInfo.Type.COUNTRY_DAY.typeValue).single().apply { + isDownloadComplete shouldBe true + checksumMD5 shouldBe "coffee" + } + dao.getEntriesForType(CachedKeyInfo.Type.COUNTRY_HOUR.typeValue).single().apply { + isDownloadComplete shouldBe false + checksumMD5 shouldBe null + } + + dao.updateDownloadState(keyHour.toDownloadUpdate("with milk")) + dao.getEntriesForType(CachedKeyInfo.Type.COUNTRY_DAY.typeValue).single().apply { + isDownloadComplete shouldBe true + checksumMD5 shouldBe "coffee" + } + dao.getEntriesForType(CachedKeyInfo.Type.COUNTRY_HOUR.typeValue).single().apply { + isDownloadComplete shouldBe true + checksumMD5 shouldBe "with milk" + } + + dao.deleteEntry(keyDay) + dao.getAllEntries() shouldBe listOf( + keyHour.copy( + isDownloadComplete = true, + checksumMD5 = "with milk" + ) + ) + + dao.clear() + dao.getAllEntries() shouldBe emptyList() + } + } +} 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 deleted file mode 100644 index 31f173f6c73..00000000000 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/keycache/KeyCacheDaoTest.kt +++ /dev/null @@ -1,88 +0,0 @@ -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() - 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/util/security/DBPasswordTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/util/security/DBPasswordTest.kt index 5f1267524ea..efbab656804 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/util/security/DBPasswordTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/util/security/DBPasswordTest.kt @@ -22,7 +22,8 @@ package de.rki.coronawarnapp.util.security import android.content.Context import androidx.test.core.app.ApplicationProvider import de.rki.coronawarnapp.storage.AppDatabase -import de.rki.coronawarnapp.storage.keycache.KeyCacheEntity +import de.rki.coronawarnapp.storage.tracing.TracingIntervalEntity +import io.kotest.matchers.shouldBe import kotlinx.coroutines.runBlocking import net.sqlcipher.database.SQLiteException import org.hamcrest.Matchers.equalTo @@ -33,8 +34,6 @@ import org.junit.Before import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -import java.util.UUID -import kotlin.random.Random @RunWith(JUnit4::class) class DBPasswordTest { @@ -70,16 +69,14 @@ class DBPasswordTest { @Test fun canLoadDataFromEncryptedDatabase() { runBlocking { - val id = UUID.randomUUID().toString() - val path = UUID.randomUUID().toString() - val type = Random.nextInt(1000) - - insertFakeEntity(id, path, type) - val keyCacheEntity = loadFakeEntity() - - assertThat(keyCacheEntity.id, equalTo(id)) - assertThat(keyCacheEntity.path, equalTo(path)) - assertThat(keyCacheEntity.type, equalTo(type)) + val from = 123L + val to = 456L + insertFakeEntity(from, to) + + loadFakeEntity().apply { + this.from shouldBe from + this.to shouldBe to + } } } @@ -95,34 +92,32 @@ class DBPasswordTest { @Test(expected = SQLiteException::class) fun loadingDataFromDatabaseWillFailWhenPassphraseIsIncorrect() { runBlocking { - val id = UUID.randomUUID().toString() - val path = UUID.randomUUID().toString() - val type = Random.nextInt(1000) - insertFakeEntity(id, path, type) + val from = 123L + val to = 456L + insertFakeEntity(from, to) clearSharedPreferences() AppDatabase.resetInstance() - val keyCacheEntity = loadFakeEntity() - assertThat(keyCacheEntity.id, equalTo(id)) - assertThat(keyCacheEntity.path, equalTo(path)) - assertThat(keyCacheEntity.type, equalTo(type)) + loadFakeEntity().apply { + this.from shouldBe from + this.to shouldBe to + } } } private suspend fun insertFakeEntity( - id: String, - path: String, - type: Int + from: Long, + to: Long ) { - db.dateDao().insertEntry(KeyCacheEntity().apply { - this.id = id - this.path = path - this.type = type + db.tracingIntervalDao().insertInterval(TracingIntervalEntity().apply { + this.from = from + this.to = to }) } - private suspend fun loadFakeEntity(): KeyCacheEntity = db.dateDao().getAllEntries().first() + private suspend fun loadFakeEntity(): TracingIntervalEntity = + db.tracingIntervalDao().getAllIntervals().first() private fun clearSharedPreferences() = SecurityHelper.globalEncryptedSharedPreferencesInstance.edit().clear().commit() diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/util/security/VerificationKeysTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/util/security/VerificationKeysTest.kt new file mode 100644 index 00000000000..f43f22095c6 --- /dev/null +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/util/security/VerificationKeysTest.kt @@ -0,0 +1,71 @@ +package de.rki.coronawarnapp.util.security + +import de.rki.coronawarnapp.exception.CwaSecurityException +import io.kotest.assertions.throwables.shouldThrow +import io.kotest.matchers.shouldBe +import okio.ByteString.Companion.decodeHex +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(JUnit4::class) +class VerificationKeysTest { + + private fun createTool() = VerificationKeys() + + @Test + fun goodBinaryAndSignature() { + val tool = createTool() + tool.hasInvalidSignature( + GOOD_BINARY.decodeHex().toByteArray(), + GOOD_SIGNATURE.decodeHex().toByteArray() + ) shouldBe false + } + + @Test + fun badBinaryGoodSignature() { + val tool = createTool() + tool.hasInvalidSignature( + "123ABC".decodeHex().toByteArray(), + GOOD_SIGNATURE.decodeHex().toByteArray() + ) shouldBe true + } + + @Test + fun goodBinaryBadSignature() { + val tool = createTool() + shouldThrow { + tool.hasInvalidSignature( + GOOD_BINARY.decodeHex().toByteArray(), + "123ABC".decodeHex().toByteArray() + ) + } + } + + @Test + fun badEverything() { + val tool = createTool() + shouldThrow { + tool.hasInvalidSignature( + "123ABC".decodeHex().toByteArray(), + "123ABC".decodeHex().toByteArray() + ) + } + } + + companion object { + private const val GOOD_BINARY = + "080b124d0a230a034c4f57180f221a68747470733a2f2f7777772e636f726f6e617761726e2e6170700a26" + + "0a0448494748100f1848221a68747470733a2f2f7777772e636f726f6e617761726e2e6170701a" + + "640a10080110021803200428053006380740081100000000000049401a0a200128013001380140" + + "012100000000000049402a10080510051805200528053005380540053100000000000034403a0e" + + "1001180120012801300138014001410000000000004940221c0a040837103f1212090000000000" + + "00f03f11000000000000e03f20192a1a0a0a0a041008180212021005120c0a0408011804120408" + + "011804" + private const val GOOD_SIGNATURE = + "0a87010a380a1864652e726b692e636f726f6e617761726e6170702d6465761a02763122033236322a1331" + + "2e322e3834302e31303034352e342e332e321001180122473045022100cf32ff24ea18a1ffcc7f" + + "f4c9fe8d1808cecbc5a37e3e1d4c9ce682120450958c022064bf124b6973a9b510a43d479ff93e" + + "0ef97a5b893c7af4abc4a8d399969cd8a0" + } +} diff --git a/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/RiskLevelAndKeyRetrievalBenchmark.kt b/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/RiskLevelAndKeyRetrievalBenchmark.kt index 85b980a36e0..e92c287573f 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/RiskLevelAndKeyRetrievalBenchmark.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/RiskLevelAndKeyRetrievalBenchmark.kt @@ -5,9 +5,9 @@ import android.text.format.Formatter import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.TransactionException import de.rki.coronawarnapp.exception.reporting.report -import de.rki.coronawarnapp.storage.keycache.KeyCacheRepository import de.rki.coronawarnapp.transaction.RetrieveDiagnosisKeysTransaction import de.rki.coronawarnapp.transaction.RiskLevelTransaction +import de.rki.coronawarnapp.util.di.AppInjector import timber.log.Timber import kotlin.system.measureTimeMillis @@ -19,8 +19,7 @@ class RiskLevelAndKeyRetrievalBenchmark( /** * the key cache instance used to store queried dates and hours */ - private val keyCache = - KeyCacheRepository.getDateRepository(context) + private val keyCache = AppInjector.component.keyCacheRepository /** * Calls the RetrieveDiagnosisKeysTransaction and RiskLevelTransaction and measures them. @@ -36,7 +35,7 @@ class RiskLevelAndKeyRetrievalBenchmark( var resultInfo = StringBuilder() .append( "MEASUREMENT Running for Countries:\n " + - "${countries?.joinToString(", ")}\n\n" + "${countries.joinToString(", ")}\n\n" ) .append("Result: \n\n") .append("#\t Combined \t Download \t Sub \t Risk \t File # \t F. size\n") diff --git a/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/TestForAPIFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/TestForAPIFragment.kt index ac579527077..1e457e5ad9f 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/TestForAPIFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/TestForAPIFragment.kt @@ -33,6 +33,7 @@ import com.google.zxing.integration.android.IntentIntegrator import com.google.zxing.integration.android.IntentResult import com.google.zxing.qrcode.QRCodeWriter import de.rki.coronawarnapp.databinding.FragmentTestForAPIBinding +import de.rki.coronawarnapp.diagnosiskeys.server.LocationCode import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.ExceptionCategory.INTERNAL import de.rki.coronawarnapp.exception.TransactionException @@ -50,8 +51,8 @@ import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.tracing.TracingIntervalRepository import de.rki.coronawarnapp.transaction.RiskLevelTransaction import de.rki.coronawarnapp.ui.viewmodel.TracingViewModel -import de.rki.coronawarnapp.util.CachedKeyFileHolder import de.rki.coronawarnapp.util.KeyFileHelper +import de.rki.coronawarnapp.util.di.AppInjector import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -60,7 +61,6 @@ import org.joda.time.DateTimeZone import timber.log.Timber import java.io.File import java.lang.reflect.Type -import java.util.Date import java.util.UUID @SuppressWarnings("TooManyFunctions", "MagicNumber", "LongMethod") @@ -321,9 +321,9 @@ class TestForAPIFragment : Fragment(), InternalExposureNotificationPermissionHel lastSetCountries = countryCodes // Trigger asyncFetchFiles which will use all Countries passed as parameter - val currentDate = Date(System.currentTimeMillis()) lifecycleScope.launch { - CachedKeyFileHolder.asyncFetchFiles(currentDate, countryCodes) + val locationCodes = countryCodes.map { LocationCode(it) } + AppInjector.component.keyFileDownloader.asyncFetchKeyFiles(locationCodes) updateCountryStatusLabel() } } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/TestRiskLevelCalculation.kt b/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/TestRiskLevelCalculation.kt index 14ddf7a9291..945ddca4e51 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/TestRiskLevelCalculation.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de.rki.coronawarnapp/TestRiskLevelCalculation.kt @@ -27,7 +27,6 @@ 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.FileStorageHelper import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.RiskLevelRepository import de.rki.coronawarnapp.transaction.RetrieveDiagnosisKeysTransaction @@ -36,6 +35,7 @@ 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 de.rki.coronawarnapp.util.di.AppInjector import de.rki.coronawarnapp.util.security.SecurityHelper import kotlinx.android.synthetic.deviceForTesters.fragment_test_risk_level_calculation.* import kotlinx.coroutines.Dispatchers @@ -112,7 +112,7 @@ class TestRiskLevelCalculation : Fragment() { // Database Reset AppDatabase.reset(requireContext()) // Export File Reset - FileStorageHelper.getAllFilesInKeyExportDirectory().forEach { it.delete() } + AppInjector.component.keyCacheRepository.clear() LocalData.lastCalculatedRiskLevel(RiskLevel.UNDETERMINED.raw) LocalData.lastSuccessfullyCalculatedRiskLevel(RiskLevel.UNDETERMINED.raw) @@ -130,6 +130,12 @@ class TestRiskLevelCalculation : Fragment() { } } + binding.buttonClearDiagnosisKeyCache.setOnClickListener { + lifecycleScope.launch { + AppInjector.component.keyCacheRepository.clear() + } + } + startObserving() } diff --git a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_for_a_p_i.xml b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_for_a_p_i.xml index 2452245478a..09ac7491525 100644 --- a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_for_a_p_i.xml +++ b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_for_a_p_i.xml @@ -1,5 +1,7 @@ - + @@ -241,8 +243,7 @@ android:id="@+id/input_country_codes_editText" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_weight="1" - /> + android:layout_weight="1" />