From 1b61142ff80d6e472b25b9f32371e610b2353b70 Mon Sep 17 00:00:00 2001 From: chris-cwa <69595386+chris-cwa@users.noreply.github.com> Date: Mon, 8 Mar 2021 16:32:06 +0100 Subject: [PATCH] Drop storage of active tracing time (EXPOSUREAPP-4524) #2503 * - database, active tracing time * fixed unit test * fixed unit test * fixed instrumented tests * fixed unit test * - unused test case * removed more unused code * fixed unit test * ktlint * removed optional parameter Co-authored-by: Alex Paulescu <alex.paulescu@gmail.com> --- .../storage/tracing/TracingIntervalDaoTest.kt | 75 ------ .../coronawarnapp/ui/main/home/HomeData.kt | 7 +- .../coronawarnapp/ui/tracing/TracingData.kt | 9 - .../util/security/DBPasswordTest.kt | 138 ------------ .../risk/storage/DefaultRiskLevelStorage.kt | 4 +- .../miscinfo/MiscInfoFragment.kt | 8 - .../miscinfo/MiscInfoFragmentViewModel.kt | 14 -- .../risk/storage/DefaultRiskLevelStorage.kt | 4 +- ...iskLevelCalculationFragmentCWAViewModel.kt | 4 - .../res/layout/fragment_test_deviceinfo.xml | 42 ---- .../diagnosiskeys/DiagnosisKeysModule.kt | 10 - .../diagnosiskeys/download/KeyDownloadTool.kt | 17 +- .../storage/legacy/KeyCacheLegacyDao.kt | 10 - .../storage/legacy/KeyCacheLegacyEntity.kt | 18 -- .../storage/legacy/LegacyKeyCacheMigration.kt | 104 --------- .../modules/tracing/DefaultTracingStatus.kt | 19 -- .../rki/coronawarnapp/risk/TimeVariables.kt | 107 --------- .../risk/storage/BaseRiskLevelStorage.kt | 12 - .../storage/legacy/RiskLevelResultMigrator.kt | 135 ----------- .../rki/coronawarnapp/storage/AppDatabase.kt | 78 ------- .../storage/DatabaseConstants.kt | 3 - .../storage/ExposureSummaryDao.kt | 18 -- .../storage/ExposureSummaryEntity.kt | 25 -- .../de/rki/coronawarnapp/storage/LocalData.kt | 29 --- .../storage/TracingRepository.kt | 18 -- .../storage/tracing/TracingIntervalDao.kt | 17 -- .../storage/tracing/TracingIntervalEntity.kt | 14 -- .../tracing/TracingIntervalRepository.kt | 55 ----- .../tracing/states/TracingState.kt | 24 +- .../tracing/states/TracingStateProvider.kt | 6 - .../tracing/ui/TracingExplanationDialog.kt | 38 ---- .../TracingDetailsFragmentViewModel.kt | 1 - .../ui/details/TracingDetailsItemProvider.kt | 5 - .../items/periodlogged/PeriodLoggedBox.kt | 5 - .../SettingsTracingFragmentViewModel.kt | 16 +- .../ui/main/home/HomeFragment.kt | 7 - .../ui/main/home/HomeFragmentEvents.kt | 4 - .../ui/main/home/HomeFragmentViewModel.kt | 16 -- .../de/rki/coronawarnapp/util/DataReset.kt | 3 - .../util/security/EncryptionErrorResetTool.kt | 12 - .../util/security/SecurityConstants.kt | 3 - .../util/security/SecurityHelper.kt | 36 --- .../res/layout/fragment_settings_tracing.xml | 27 --- .../layout/tracing_content_increased_view.xml | 30 --- .../res/layout/tracing_content_low_view.xml | 43 +--- ...tracing_details_item_periodlogged_view.xml | 41 ---- .../src/main/res/values-bg/strings.xml | 12 - .../src/main/res/values-de/strings.xml | 6 - .../src/main/res/values-en/strings.xml | 12 - .../src/main/res/values-pl/strings.xml | 12 - .../src/main/res/values-ro/strings.xml | 12 - .../src/main/res/values-tr/strings.xml | 12 - .../src/main/res/values/strings.xml | 7 - .../download/KeyDownloadToolTest.kt | 3 - .../legacy/LegacyKeyCacheMigrationTest.kt | 213 ------------------ .../main/home/HomeFragmentViewModelTest.kt | 10 +- .../risk/storage/BaseRiskLevelStorageTest.kt | 55 +---- .../legacy/RiskLevelResultMigratorTest.kt | 148 ------------ .../storage/DatabaseConstantsTest.kt | 12 - .../tracing/TracingIntervalRepositoryTest.kt | 64 ------ .../tracing/states/IncreasedRiskTest.kt | 1 - .../tracing/states/LowRiskTest.kt | 1 - .../details/TracingDetailsItemProviderTest.kt | 4 - .../util/security/EncryptionResetToolTest.kt | 39 ---- .../storage/DefaultRiskLevelStorageTest.kt | 7 +- .../storage/DefaultRiskLevelStorageTest.kt | 7 +- 66 files changed, 16 insertions(+), 1932 deletions(-) delete mode 100644 Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDaoTest.kt delete mode 100644 Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/util/security/DBPasswordTest.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/KeyCacheLegacyDao.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/KeyCacheLegacyEntity.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/LegacyKeyCacheMigration.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/legacy/RiskLevelResultMigrator.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppDatabase.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/DatabaseConstants.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/ExposureSummaryDao.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/ExposureSummaryEntity.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDao.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalEntity.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepository.kt delete mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/TracingExplanationDialog.kt delete mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/LegacyKeyCacheMigrationTest.kt delete mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/storage/legacy/RiskLevelResultMigratorTest.kt delete mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/DatabaseConstantsTest.kt delete mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepositoryTest.kt diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDaoTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDaoTest.kt deleted file mode 100644 index 39d500254..000000000 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDaoTest.kt +++ /dev/null @@ -1,75 +0,0 @@ -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() - } -} diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeData.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeData.kt index e1f299917..4839c083c 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeData.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeData.kt @@ -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 = {}, diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingData.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingData.kt index 9bc5f2942..b5dcdc27b 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingData.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/tracing/TracingData.kt @@ -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 = 5, lastEncounterAt = Instant.now() ) ), @@ -72,7 +70,6 @@ object TracingData { ), PeriodLoggedBox.Item( - activeTracingDaysInRetentionPeriod = 0, tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE ), DetailsLowRiskBox.Item(riskState = RiskState.LOW_RISK, matchedKeyCount = 0) @@ -93,7 +90,6 @@ object TracingData { lastExposureDetectionTime = Instant.now(), allowManualUpdate = false, daysWithEncounters = 1, - activeTracingDays = 5, lastEncounterAt = Instant.now() ) ), @@ -103,7 +99,6 @@ object TracingData { ), PeriodLoggedBox.Item( - activeTracingDaysInRetentionPeriod = 0, tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE ), DetailsLowRiskBox.Item(riskState = RiskState.LOW_RISK, matchedKeyCount = 0) @@ -124,7 +119,6 @@ object TracingData { lastExposureDetectionTime = Instant.now(), allowManualUpdate = false, daysWithEncounters = 2, - activeTracingDays = 5, lastEncounterAt = Instant.now() ) ), @@ -134,7 +128,6 @@ object TracingData { ), PeriodLoggedBox.Item( - activeTracingDaysInRetentionPeriod = 0, tracingStatus = GeneralTracingStatus.Status.TRACING_ACTIVE ), DetailsLowRiskBox.Item(riskState = RiskState.LOW_RISK, matchedKeyCount = 0) @@ -155,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( 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 deleted file mode 100644 index f06bf3afb..000000000 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/util/security/DBPasswordTest.kt +++ /dev/null @@ -1,138 +0,0 @@ -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() -} diff --git a/Corona-Warn-App/src/device/java/de/rki/coronawarnapp/risk/storage/DefaultRiskLevelStorage.kt b/Corona-Warn-App/src/device/java/de/rki/coronawarnapp/risk/storage/DefaultRiskLevelStorage.kt index 69f2c57f7..8aa8d1bfa 100644 --- a/Corona-Warn-App/src/device/java/de/rki/coronawarnapp/risk/storage/DefaultRiskLevelStorage.kt +++ b/Corona-Warn-App/src/device/java/de/rki/coronawarnapp/risk/storage/DefaultRiskLevelStorage.kt @@ -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 diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/miscinfo/MiscInfoFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/miscinfo/MiscInfoFragment.kt index 599dbd36c..67b2d7be1 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/miscinfo/MiscInfoFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/miscinfo/MiscInfoFragment.kt @@ -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 { diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/miscinfo/MiscInfoFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/miscinfo/MiscInfoFragmentViewModel.kt index e18ff6c3b..95d020e07 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/miscinfo/MiscInfoFragmentViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/miscinfo/MiscInfoFragmentViewModel.kt @@ -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> } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/risk/storage/DefaultRiskLevelStorage.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/risk/storage/DefaultRiskLevelStorage.kt index 1a7bf05f6..6fb9ac512 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/risk/storage/DefaultRiskLevelStorage.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/risk/storage/DefaultRiskLevelStorage.kt @@ -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! diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt index cd78b9e7e..f2fbf7ae8 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/risklevel/ui/TestRiskLevelCalculationFragmentCWAViewModel.kt @@ -16,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 @@ -38,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, @@ -141,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() diff --git a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_deviceinfo.xml b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_deviceinfo.xml index 4bdea42d3..f124fe189 100644 --- a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_deviceinfo.xml +++ b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_deviceinfo.xml @@ -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> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/DiagnosisKeysModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/DiagnosisKeysModule.kt index c106f0a7e..fcf70982c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/DiagnosisKeysModule.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/DiagnosisKeysModule.kt @@ -1,14 +1,10 @@ package de.rki.coronawarnapp.diagnosiskeys -import android.content.Context import dagger.Module import dagger.Provides import de.rki.coronawarnapp.diagnosiskeys.server.DiagnosisKeyApiV1 -import de.rki.coronawarnapp.diagnosiskeys.storage.legacy.KeyCacheLegacyDao import de.rki.coronawarnapp.environment.download.DownloadCDNHttpClient import de.rki.coronawarnapp.environment.download.DownloadCDNServerUrl -import de.rki.coronawarnapp.storage.AppDatabase -import de.rki.coronawarnapp.util.di.AppContext import okhttp3.OkHttpClient import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory @@ -29,10 +25,4 @@ class DiagnosisKeysModule { .addConverterFactory(gsonConverterFactory) .build() .create(DiagnosisKeyApiV1::class.java) - - @Singleton - @Provides - fun legacyKeyCacheDao(@AppContext context: Context): KeyCacheLegacyDao { - return AppDatabase.getInstance(context).dateDao() - } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyDownloadTool.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyDownloadTool.kt index c182eef18..22be3c46e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyDownloadTool.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyDownloadTool.kt @@ -3,17 +3,14 @@ package de.rki.coronawarnapp.diagnosiskeys.download import dagger.Reusable import de.rki.coronawarnapp.appconfig.KeyDownloadConfig import de.rki.coronawarnapp.diagnosiskeys.server.DiagnosisKeyServer -import de.rki.coronawarnapp.diagnosiskeys.server.DownloadInfo import de.rki.coronawarnapp.diagnosiskeys.storage.CachedKey import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository -import de.rki.coronawarnapp.diagnosiskeys.storage.legacy.LegacyKeyCacheMigration import kotlinx.coroutines.withTimeout import timber.log.Timber import javax.inject.Inject @Reusable class KeyDownloadTool @Inject constructor( - private val legacyKeyCache: LegacyKeyCacheMigration, private val keyServer: DiagnosisKeyServer, private val keyCache: KeyCacheRepository ) { @@ -24,24 +21,12 @@ class KeyDownloadTool @Inject constructor( val saveTo = cachedKey.path val keyInfo = cachedKey.info - val preconditionHook: suspend (DownloadInfo) -> Boolean = - { downloadInfo -> - /** - * To try legacy migration, we attempt to the etag as checksum. - * Removing the quotes, the etag can represent the file's MD5 checksum. - */ - val etagAsChecksum = downloadInfo.etag?.removePrefix("\"")?.removeSuffix("\"") - val continueDownload = !legacyKeyCache.tryMigration(etagAsChecksum, saveTo) - continueDownload // Continue download if no migration happened - } - val downloadInfo = withTimeout(downloadConfig.individualDownloadTimeout.millis) { keyServer.downloadKeyFile( locationCode = keyInfo.location, day = keyInfo.day, hour = keyInfo.hour, - saveTo = saveTo, - precondition = preconditionHook + saveTo = saveTo ) } Timber.tag(TAG).v("Download finished: %s -> %s", cachedKey, saveTo) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/KeyCacheLegacyDao.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/KeyCacheLegacyDao.kt deleted file mode 100644 index cd48b1f00..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/KeyCacheLegacyDao.kt +++ /dev/null @@ -1,10 +0,0 @@ -package de.rki.coronawarnapp.diagnosiskeys.storage.legacy - -import androidx.room.Dao -import androidx.room.Query - -@Dao -interface KeyCacheLegacyDao { - @Query("DELETE FROM date") - suspend fun clear() -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/KeyCacheLegacyEntity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/KeyCacheLegacyEntity.kt deleted file mode 100644 index b07327d56..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/KeyCacheLegacyEntity.kt +++ /dev/null @@ -1,18 +0,0 @@ -package de.rki.coronawarnapp.diagnosiskeys.storage.legacy - -import androidx.room.Entity -import androidx.room.Index -import androidx.room.PrimaryKey - -@Entity( - tableName = "date", - indices = [Index("id")] -) -class KeyCacheLegacyEntity { - @PrimaryKey - var id: String = "" - - var path: String = "" - - var type: Int = 0 -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/LegacyKeyCacheMigration.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/LegacyKeyCacheMigration.kt deleted file mode 100644 index b7b4113d7..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/LegacyKeyCacheMigration.kt +++ /dev/null @@ -1,104 +0,0 @@ -package de.rki.coronawarnapp.diagnosiskeys.storage.legacy - -import android.content.Context -import dagger.Lazy -import de.rki.coronawarnapp.risk.TimeVariables -import de.rki.coronawarnapp.util.HashExtensions.hashToMD5 -import de.rki.coronawarnapp.util.TimeStamper -import de.rki.coronawarnapp.util.di.AppContext -import kotlinx.coroutines.sync.Mutex -import kotlinx.coroutines.sync.withLock -import org.joda.time.Duration -import org.joda.time.Instant -import timber.log.Timber -import java.io.File -import javax.inject.Inject - -class LegacyKeyCacheMigration @Inject constructor( - @AppContext private val context: Context, - private val legacyDao: Lazy<KeyCacheLegacyDao>, - private val timeStamper: TimeStamper -) { - - private val cacheDir by lazy { - File(context.cacheDir, "key-export") - } - - private val workMutex = Mutex() - private var isInit = false - private val legacyCacheMap = mutableMapOf<String, File>() - - private suspend fun tryInit() { - if (isInit) return - isInit = true - - if (!cacheDir.exists()) { - Timber.tag(TAG).v("Legacy cache dir doesn't exist, we are done.") - return - } - - try { - legacyDao.get().clear() - } catch (e: Exception) { - // Not good, but not a problem, we don't need the actual entities for migration. - Timber.tag(TAG).w(e, "Failed to clear legacy key cache from db.") - } - - try { - cacheDir.listFiles()?.forEach { file -> - val isExpired = Duration( - Instant.ofEpochMilli(file.lastModified()), - timeStamper.nowUTC - ).standardDays > TimeVariables.getDefaultRetentionPeriodInDays() - - if (isExpired) { - Timber.tag(TAG).d("Deleting expired file: %s", file) - file.delete() - } else { - val md5 = file.hashToMD5() - Timber.tag(TAG).v("MD5 %s for %s", md5, file) - legacyCacheMap[md5] = file - } - } - } catch (e: Exception) { - Timber.tag(TAG).e(e, "Reading legacy cached failed. Clearing.") - cacheDir.deleteRecursively() - } - - if (cacheDir.exists() && cacheDir.listFiles()?.isNullOrEmpty() == true) { - Timber.tag(TAG).v("Legacy cache dir is empty, deleting.") - cacheDir.delete() - } - } - - suspend fun tryMigration(fileMD5: String?, targetPath: File): Boolean = workMutex.withLock { - if (fileMD5 == null) return false - tryInit() - - val legacyFile = legacyCacheMap[fileMD5] ?: return false - Timber.tag(TAG).i("Migrating legacy file for %s to %s", fileMD5, targetPath) - - return try { - legacyFile.inputStream().use { from -> - targetPath.outputStream().use { to -> - from.copyTo(to, DEFAULT_BUFFER_SIZE) - } - } - true - } catch (e: Exception) { - Timber.tag(TAG).e(e, "Failed to migrate %s", legacyFile) - false - } finally { - try { - val removedFile = legacyCacheMap.remove(fileMD5) - if (removedFile?.delete() == true) Timber.tag(TAG).d("Deleted %s", removedFile) - } catch (e: Exception) { - Timber.tag(TAG).e(e, "Failed to delete %s", legacyFile) - } - } - } - - companion object { - private val TAG = this::class.java.simpleName - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt index a34f35c65..208465596 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/tracing/DefaultTracingStatus.kt @@ -4,13 +4,9 @@ import com.google.android.gms.common.api.ApiException import com.google.android.gms.common.api.Status import com.google.android.gms.nearby.exposurenotification.ExposureNotificationClient import com.google.android.gms.nearby.exposurenotification.ExposureNotificationStatusCodes -import de.rki.coronawarnapp.CoronaWarnApplication import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.reporting.report -import de.rki.coronawarnapp.risk.TimeVariables import de.rki.coronawarnapp.storage.LocalData -import de.rki.coronawarnapp.storage.tracing.TracingIntervalRepository -import de.rki.coronawarnapp.util.TimeAndDateExtensions.millisecondsToSeconds import de.rki.coronawarnapp.util.coroutine.AppScope import de.rki.coronawarnapp.util.flow.shareLatest import kotlinx.coroutines.CancellationException @@ -25,7 +21,6 @@ import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch import timber.log.Timber -import java.util.Date import javax.inject.Inject import javax.inject.Singleton import kotlin.coroutines.resume @@ -77,20 +72,6 @@ class DefaultTracingStatus @Inject constructor( client.start() .addOnSuccessListener { cont.resume(it) } .addOnFailureListener { cont.resumeWithException(it) } - }.also { - LocalData.lastNonActiveTracingTimestamp()?.let { ts -> - TracingIntervalRepository.getDateRepository(CoronaWarnApplication.getAppContext()) - .createInterval(ts, System.currentTimeMillis()) - val difference = Date().time.minus(ts).millisecondsToSeconds() - if (difference >= TimeVariables.getDeactivationTracingMeasureThresholdTimeRange()) { - LocalData.totalNonActiveTracing( - LocalData.totalNonActiveTracing().plus(difference) - ) - } - } - LocalData.lastNonActiveTracingTimestamp(null) - LocalData.initialTracingActivationTimestamp() - ?: LocalData.initialTracingActivationTimestamp(System.currentTimeMillis()) } private suspend fun asyncStop() = suspendCoroutine<Void> { cont -> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/TimeVariables.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/TimeVariables.kt index b1f46c2a8..457db5ea6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/TimeVariables.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/TimeVariables.kt @@ -1,16 +1,7 @@ package de.rki.coronawarnapp.risk -import com.google.android.gms.common.api.ApiException -import de.rki.coronawarnapp.CoronaWarnApplication -import de.rki.coronawarnapp.exception.ExceptionCategory -import de.rki.coronawarnapp.exception.reporting.report -import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient -import de.rki.coronawarnapp.storage.LocalData -import de.rki.coronawarnapp.storage.tracing.TracingIntervalRepository import de.rki.coronawarnapp.util.CWADebug import de.rki.coronawarnapp.util.TimeAndDateExtensions.daysToMilliseconds -import de.rki.coronawarnapp.util.TimeAndDateExtensions.roundUpMsToDays -import timber.log.Timber object TimeVariables { @@ -111,102 +102,4 @@ object TimeVariables { * @return max attenuation duration in minutes */ fun getMaxAttenuationDuration() = MAX_ATTENUATION_DURATION - - /**************************************************** - * STORED DATA - ****************************************************/ - /** - * timestamp when the tracing was activated by the user read from the mobile device storage. - * The parameter is only filled once the tracing was activated and - * not if the user activated or deactivates the tracing. - * - * It will change when you reinstall your app and activate tracing again. - * - * @return time in milliseconds when tracing was initially activated - */ - fun getInitialExposureTracingActivationTimestamp(): Long? = - LocalData.initialTracingActivationTimestamp() - - /**************************************************** - * CALCULATED TIME VARIABLES - ****************************************************/ - - /** - * The time the tracing is active. - * - * @return in milliseconds - */ - fun getTimeActiveTracingDuration(): Long = System.currentTimeMillis() - - (getInitialExposureTracingActivationTimestamp() ?: 0L) - - LocalData.totalNonActiveTracing() - - suspend fun getActiveTracingDaysInRetentionPeriod(): Long { - // the active tracing time during the retention period - all non active tracing times - val tracingActiveMS = getTimeRangeFromRetentionPeriod() - val retentionPeriodInMS = getDefaultRetentionPeriodInMS() - val lastNonActiveTracingTimestamp = LocalData.lastNonActiveTracingTimestamp() - val current = System.currentTimeMillis() - val retentionTimestamp = current - retentionPeriodInMS - val inactiveTracingIntervals = TracingIntervalRepository - .getDateRepository(CoronaWarnApplication.getAppContext()) - .getIntervals() - .toMutableList() - - // by default the tracing is assumed to be activated - // if the API is reachable we set the value accordingly - val enIsDisabled = try { - !InternalExposureNotificationClient.asyncIsEnabled() - } catch (e: ApiException) { - e.report(ExceptionCategory.EXPOSURENOTIFICATION) - false - } - - // lastNonActiveTracingTimestamp could be null when en is disabled - // it only gets updated when you turn the en back on - // if en is disabled and lastNonActiveTracingTimestamp != null, only then we add a pair to - // the inactive intervals list to account for the time of inactivity between the last time - // en was not active and now. - if (enIsDisabled && lastNonActiveTracingTimestamp != null) { - val lastTimeTracingWasNotActivated = - LocalData.lastNonActiveTracingTimestamp() ?: current - inactiveTracingIntervals.add(Pair(lastTimeTracingWasNotActivated, current)) - } - val inactiveTracingMS = inactiveTracingIntervals - .map { it.second - maxOf(it.first, retentionTimestamp) } - .sum() - - // because we delete periods that are past 14 days but tracingActiveMS counts from first - // ever activation, there are edge cases where tracingActiveMS gets to be > 14 days - val activeTracingDays = (minOf(tracingActiveMS, retentionPeriodInMS) - inactiveTracingMS).roundUpMsToDays() - return if (activeTracingDays >= 0) { - activeTracingDays - } else { - Timber.w("Negative active tracing days: %d", activeTracingDays) - 0 - } - } - - /**************************************************** - * HELPER FUNCTIONS - ****************************************************/ - - /** - * Return the maximum time of the time range that is used as retention time range. - * The retention time range will be corrected to the initial exposure activation timestamp - * (e.g. when we reset our data or start tracing for the first time after a fresh install) - * - * @return max number of days the server should fetch - */ - private fun getTimeRangeFromRetentionPeriod(): Long { - val activeTracingTimeInMS = - getInitialExposureTracingActivationTimestamp()?.let { - System.currentTimeMillis().minus(it) - } ?: return 0 - - return if (activeTracingTimeInMS > getDefaultRetentionPeriodInMS()) { - getDefaultRetentionPeriodInMS() - } else { - activeTracingTimeInMS - } - } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorage.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorage.kt index a0e337d4b..8b84f9395 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorage.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorage.kt @@ -8,7 +8,6 @@ import de.rki.coronawarnapp.risk.storage.internal.riskresults.PersistedRiskLevel import de.rki.coronawarnapp.risk.storage.internal.riskresults.toPersistedAggregatedRiskPerDateResult import de.rki.coronawarnapp.risk.storage.internal.riskresults.toPersistedRiskResult import de.rki.coronawarnapp.risk.storage.internal.windows.PersistedExposureWindowDaoWrapper -import de.rki.coronawarnapp.risk.storage.legacy.RiskLevelResultMigrator import de.rki.coronawarnapp.util.flow.combine import de.rki.coronawarnapp.util.flow.shareLatest import kotlinx.coroutines.CoroutineScope @@ -19,7 +18,6 @@ import timber.log.Timber abstract class BaseRiskLevelStorage constructor( private val riskResultDatabaseFactory: RiskResultDatabase.Factory, - private val riskLevelResultMigrator: RiskLevelResultMigrator, scope: CoroutineScope ) : RiskLevelStorage { @@ -55,13 +53,6 @@ abstract class BaseRiskLevelStorage constructor( } } - private suspend fun List<RiskLevelTaskResult>.fallbackToLegacyIfEmpty(): List<RiskLevelResult> = - if (isNotEmpty()) { - this - } else { - riskLevelResultMigrator.getLegacyResults() - } - final override val allRiskLevelResults: Flow<List<RiskLevelResult>> = combine( riskResultsTables.allEntries(), exposureWindowsTables.allEntries() @@ -73,7 +64,6 @@ abstract class BaseRiskLevelStorage constructor( Timber.v("Mapping took %dms", (System.currentTimeMillis() - startTime)) } } - .map { results -> results.fallbackToLegacyIfEmpty() } .shareLatest(tag = TAG, scope = scope) override val latestRiskLevelResults: Flow<List<RiskLevelResult>> = riskResultsTables.latestEntries(2) @@ -81,7 +71,6 @@ abstract class BaseRiskLevelStorage constructor( Timber.v("Mapping latestRiskLevelResults:\n%s", results.joinToString("\n")) results.combineWithWindows(null) } - .map { results -> results.fallbackToLegacyIfEmpty() } .shareLatest(tag = TAG, scope = scope) override val latestAndLastSuccessful: Flow<List<RiskLevelResult>> = riskResultsTables.latestAndLastSuccessful() @@ -89,7 +78,6 @@ abstract class BaseRiskLevelStorage constructor( Timber.v("Mapping latestAndLastSuccessful:\n%s", results.joinToString("\n")) results.combineWithWindows(null) } - .map { results -> results.fallbackToLegacyIfEmpty() } .shareLatest(tag = TAG, scope = scope) override suspend fun storeResult(result: RiskLevelResult) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/legacy/RiskLevelResultMigrator.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/legacy/RiskLevelResultMigrator.kt deleted file mode 100644 index 07f3a3fb3..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/risk/storage/legacy/RiskLevelResultMigrator.kt +++ /dev/null @@ -1,135 +0,0 @@ -package de.rki.coronawarnapp.risk.storage.legacy - -import android.content.Context -import android.content.SharedPreferences -import androidx.annotation.VisibleForTesting -import com.google.android.gms.nearby.exposurenotification.ExposureWindow -import dagger.Lazy -import de.rki.coronawarnapp.risk.RiskLevelResult -import de.rki.coronawarnapp.risk.RiskState -import de.rki.coronawarnapp.risk.result.AggregatedRiskResult -import de.rki.coronawarnapp.storage.AppDatabase -import de.rki.coronawarnapp.storage.EncryptedPreferences -import de.rki.coronawarnapp.util.TimeStamper -import de.rki.coronawarnapp.util.di.AppContext -import org.joda.time.Duration -import org.joda.time.Instant -import timber.log.Timber -import javax.inject.Inject -import javax.inject.Singleton - -/** - * TODO Remove this in the future - * Once a significant portion of the user base has already been running 1.8.x, - * this class can be removed to reduce access to the EncryptedPreferences. - */ -@Singleton -class RiskLevelResultMigrator @Inject constructor( - @EncryptedPreferences encryptedPreferences: Lazy<SharedPreferences>, - private val timeStamper: TimeStamper, - @AppContext - private val context: Context -) { - - private val prefs by lazy { encryptedPreferences.get() } - - private fun lastTimeRiskLevelCalculation(): Instant? { - prefs.getLong("preference_timestamp_risk_level_calculation", -1L).also { - Timber.tag(TAG).d("preference_timestamp_risk_level_calculation=$it") - return if (it < 0) null else Instant.ofEpochMilli(it) - } - } - - private fun lastCalculatedRiskLevel(): RiskState? { - val rawRiskLevel = prefs.getInt("preference_risk_level_score", -1) - Timber.tag(TAG).d("preference_risk_level_score=$rawRiskLevel") - return if (rawRiskLevel != -1) mapRiskLevelConstant(rawRiskLevel) else null - } - - private fun lastSuccessfullyCalculatedRiskLevel(): RiskState? { - val rawRiskLevel = prefs.getInt("preference_risk_level_score_successful", -1) - Timber.tag(TAG).d("preference_risk_level_score_successful=$rawRiskLevel") - return if (rawRiskLevel != -1) mapRiskLevelConstant(rawRiskLevel) else null - } - - private suspend fun lastEncounterAt(): Instant? { - return try { - val daysSinceLastExposure = - AppDatabase.getInstance(context) - .exposureSummaryDao() - .getLatestExposureSummary()?.daysSinceLastExposure - if (daysSinceLastExposure == null) { - null - } else { - timeStamper.nowUTC.minus(Duration.standardDays(daysSinceLastExposure.toLong())) - } - } catch (exception: Exception) { - Timber.tag(TAG).w(exception, "failed to select exposure summary dao from enf v1") - null - } - } - - suspend fun getLegacyResults(): List<RiskLevelResult> = try { - val legacyResults = mutableListOf<RiskLevelResult>() - lastCalculatedRiskLevel()?.let { - legacyResults.add( - LegacyResult( - riskState = it, - calculatedAt = lastTimeRiskLevelCalculation() ?: timeStamper.nowUTC, - lastEncounterAt = lastEncounterAt() - ) - ) - } - - lastSuccessfullyCalculatedRiskLevel()?.let { - legacyResults.add( - LegacyResult( - riskState = it, - calculatedAt = timeStamper.nowUTC, - lastEncounterAt = lastEncounterAt() - ) - ) - } - - Timber.tag(TAG).d("legacyResults=$legacyResults") - legacyResults - } catch (e: Exception) { - Timber.tag(TAG).e(e, "Failed to parse legacy risklevel data.") - emptyList() - } - - data class LegacyResult( - override val riskState: RiskState, - override val calculatedAt: Instant, - private val lastEncounterAt: Instant? - ) : RiskLevelResult { - override val failureReason: RiskLevelResult.FailureReason? = null - override val aggregatedRiskResult: AggregatedRiskResult? = null - override val exposureWindows: List<ExposureWindow>? = null - override val matchedKeyCount: Int = 0 - override val daysWithEncounters: Int = 0 - override val lastRiskEncounterAt: Instant? = lastEncounterAt - } - - companion object { - private const val TAG = "RiskLevelResultMigrator" - - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - internal fun mapRiskLevelConstant(value: Int): RiskState = when (value) { - MigrationRiskLevelConstants.LOW_LEVEL_RISK -> RiskState.LOW_RISK - MigrationRiskLevelConstants.INCREASED_RISK -> RiskState.INCREASED_RISK - else -> RiskState.CALCULATION_FAILED - } - } -} - -@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) -internal object MigrationRiskLevelConstants { - const val NO_CALCULATION_POSSIBLE_TRACING_OFF = 1 - const val LOW_LEVEL_RISK = 2 - const val INCREASED_RISK = 3 - const val UNKNOWN_RISK_OUTDATED_RESULTS = 4 - const val UNKNOWN_RISK_OUTDATED_RESULTS_MANUAL = 5 - const val UNKNOWN_RISK_NO_INTERNET = 6 - const val UNDETERMINED = 9001 -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppDatabase.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppDatabase.kt deleted file mode 100644 index 1f37983a9..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/AppDatabase.kt +++ /dev/null @@ -1,78 +0,0 @@ -package de.rki.coronawarnapp.storage - -import android.content.Context -import android.database.sqlite.SQLiteDatabase -import androidx.annotation.VisibleForTesting -import androidx.room.Database -import androidx.room.Room -import androidx.room.RoomDatabase -import androidx.room.TypeConverters -import de.rki.coronawarnapp.diagnosiskeys.storage.legacy.KeyCacheLegacyDao -import de.rki.coronawarnapp.diagnosiskeys.storage.legacy.KeyCacheLegacyEntity -import de.rki.coronawarnapp.storage.tracing.TracingIntervalDao -import de.rki.coronawarnapp.storage.tracing.TracingIntervalEntity -import de.rki.coronawarnapp.storage.tracing.TracingIntervalRepository -import de.rki.coronawarnapp.util.database.CommonConverters -import de.rki.coronawarnapp.util.di.AppInjector -import de.rki.coronawarnapp.util.security.SecurityHelper -import kotlinx.coroutines.runBlocking -import net.sqlcipher.database.SupportFactory -import java.io.File - -@Database( - entities = [ - ExposureSummaryEntity::class, - KeyCacheLegacyEntity::class, - TracingIntervalEntity::class - ], - version = 1, - exportSchema = true -) -@TypeConverters(CommonConverters::class) -abstract class AppDatabase : RoomDatabase() { - - abstract fun exposureSummaryDao(): ExposureSummaryDao - abstract fun dateDao(): KeyCacheLegacyDao - abstract fun tracingIntervalDao(): TracingIntervalDao - - companion object { - @Volatile - private var instance: AppDatabase? = null - - fun getInstance(context: Context): AppDatabase { - return instance ?: synchronized(this) { - instance ?: buildDatabase(context).also { instance = it } - } - } - - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - fun resetInstance() = synchronized(this) { - instance = null - } - - fun reset(context: Context) { - val path: String = context.getDatabasePath(DATABASE_NAME).path - val dbFile = File(path) - if (dbFile.exists()) { - SQLiteDatabase.deleteDatabase(dbFile) - } - resetInstance() - - // reset also the repo instances - val keyRepository = AppInjector.component.keyCacheRepository - runBlocking { keyRepository.clear() } // TODO this is not nice - TracingIntervalRepository.resetInstance() - } - - private fun buildDatabase(context: Context): AppDatabase { - return Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME) - /** - * The fallback behavior is to reset the app as we only store exposure summaries - * and cached references that are non-critical to app operation. - */ - .fallbackToDestructiveMigrationFrom() - .openHelperFactory(SupportFactory(SecurityHelper.getDBPassword())) - .build() - } - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/DatabaseConstants.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/DatabaseConstants.kt deleted file mode 100644 index d7148c9f6..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/DatabaseConstants.kt +++ /dev/null @@ -1,3 +0,0 @@ -package de.rki.coronawarnapp.storage - -const val DATABASE_NAME = "coronawarnapp-db" diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/ExposureSummaryDao.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/ExposureSummaryDao.kt deleted file mode 100644 index 93233ecde..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/ExposureSummaryDao.kt +++ /dev/null @@ -1,18 +0,0 @@ -package de.rki.coronawarnapp.storage - -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.Query - -@Dao -interface ExposureSummaryDao { - - @Query("SELECT * FROM exposure_summary") - suspend fun getExposureSummaryEntities(): List<ExposureSummaryEntity> - - @Query("SELECT * FROM exposure_summary ORDER BY id DESC LIMIT 1") - suspend fun getLatestExposureSummary(): ExposureSummaryEntity? - - @Insert - suspend fun insertExposureSummaryEntity(exposureSummaryEntity: ExposureSummaryEntity): Long -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/ExposureSummaryEntity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/ExposureSummaryEntity.kt deleted file mode 100644 index 8a03e9ed8..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/ExposureSummaryEntity.kt +++ /dev/null @@ -1,25 +0,0 @@ -package de.rki.coronawarnapp.storage - -import androidx.room.Entity -import androidx.room.Index -import androidx.room.PrimaryKey - -@Entity( - tableName = "exposure_summary", - indices = [Index("id")] -) -class ExposureSummaryEntity { - - @PrimaryKey(autoGenerate = true) - var id: Long = 0 - - var daysSinceLastExposure: Int = 0 - - var matchedKeyCount: Int = 0 - - var maximumRiskScore: Int = 0 - - var summationRiskScore: Int = 0 - - var attenuationDurationsInMinutes: List<Int> = arrayListOf() -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt index 139ca0b79..a5cb1011c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/LocalData.kt @@ -261,35 +261,6 @@ object LocalData { ) } - /** - * Gets the boolean if the user has seen the explanation dialog for the - * risk level tracing days - * from the EncryptedSharedPrefs - * - * @return boolean if user is onboarded - */ - fun tracingExplanationDialogWasShown(): Boolean = getSharedPreferenceInstance().getBoolean( - CoronaWarnApplication.getAppContext() - .getString(R.string.preference_risk_days_explanation_shown), - false - ) - - /** - * Sets the boolean if the user has seen the explanation dialog for the - * risk level tracing days - * from the EncryptedSharedPrefs - * - * @param value boolean if onboarding was completed - */ - fun tracingExplanationDialogWasShown(value: Boolean) = - getSharedPreferenceInstance().edit(true) { - putBoolean( - CoronaWarnApplication.getAppContext() - .getString(R.string.preference_risk_days_explanation_shown), - value - ) - } - /** * Sets a boolean depending whether the risk level decreased or not. */ diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt index bb2abf7be..197617c59 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/TracingRepository.kt @@ -7,7 +7,6 @@ import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient import de.rki.coronawarnapp.nearby.modules.detectiontracker.ExposureDetectionTracker import de.rki.coronawarnapp.nearby.modules.detectiontracker.lastSubmission import de.rki.coronawarnapp.risk.RiskLevelTask -import de.rki.coronawarnapp.risk.TimeVariables.getActiveTracingDaysInRetentionPeriod import de.rki.coronawarnapp.task.TaskController import de.rki.coronawarnapp.task.TaskInfo import de.rki.coronawarnapp.task.common.DefaultTaskRequest @@ -20,7 +19,6 @@ import de.rki.coronawarnapp.util.device.BackgroundModeStatus import de.rki.coronawarnapp.util.di.AppContext import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map @@ -36,7 +34,6 @@ import javax.inject.Singleton * * @see LocalData * @see InternalExposureNotificationClient - * @see RiskLevelRepository */ @Singleton class TracingRepository @Inject constructor( @@ -49,9 +46,6 @@ class TracingRepository @Inject constructor( private val backgroundModeStatus: BackgroundModeStatus ) { - private val internalActiveTracingDaysInRetentionPeriod = MutableStateFlow(0L) - val activeTracingDaysInRetentionPeriod: Flow<Long> = internalActiveTracingDaysInRetentionPeriod - val tracingProgress: Flow<TracingProgress> = combine( taskController.tasks.map { it.isDownloadDiagnosisKeysTaskRunning() }, enfClient.isPerformingExposureDetection(), @@ -97,18 +91,6 @@ class TracingRepository @Inject constructor( } } - /** - * Refresh the activeTracingDaysInRetentionPeriod calculation. - * - * @see de.rki.coronawarnapp.risk.TimeVariables - */ - fun refreshActiveTracingDaysInRetentionPeriod() { - scope.launch { - internalActiveTracingDaysInRetentionPeriod.value = - getActiveTracingDaysInRetentionPeriod() - } - } - /** * Launches the RetrieveDiagnosisKeysTransaction and RiskLevelTransaction in the viewModel scope */ diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDao.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDao.kt deleted file mode 100644 index c8b4a854c..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalDao.kt +++ /dev/null @@ -1,17 +0,0 @@ -package de.rki.coronawarnapp.storage.tracing - -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.Query - -@Dao -interface TracingIntervalDao { - @Query("DELETE FROM tracing_interval WHERE `to` < :retentionTimestamp") - suspend fun deleteOutdatedIntervals(retentionTimestamp: Long) - - @Query("SELECT * FROM tracing_interval") - suspend fun getAllIntervals(): List<TracingIntervalEntity> - - @Insert - suspend fun insertInterval(interval: TracingIntervalEntity) -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalEntity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalEntity.kt deleted file mode 100644 index 4457b80af..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalEntity.kt +++ /dev/null @@ -1,14 +0,0 @@ -package de.rki.coronawarnapp.storage.tracing - -import androidx.room.Entity -import androidx.room.Index - -@Entity( - tableName = "tracing_interval", - indices = [Index("from", "to")], - primaryKeys = ["from", "to"] -) -class TracingIntervalEntity { - var from: Long = 0L - var to: Long = 0L -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepository.kt deleted file mode 100644 index 2035405b0..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepository.kt +++ /dev/null @@ -1,55 +0,0 @@ -package de.rki.coronawarnapp.storage.tracing - -import android.content.Context -import de.rki.coronawarnapp.risk.TimeVariables -import de.rki.coronawarnapp.storage.AppDatabase -import timber.log.Timber - -class TracingIntervalRepository(private val tracingIntervalDao: TracingIntervalDao) { - - companion object { - private val TAG: String? = TracingIntervalRepository::class.simpleName - - @Volatile - private var instance: TracingIntervalRepository? = null - - private fun getInstance(tracingIntervalDao: TracingIntervalDao) = - instance ?: synchronized(this) { - instance - ?: TracingIntervalRepository(tracingIntervalDao) - .also { instance = it } - } - - fun resetInstance() = synchronized(this) { - instance = null - } - - fun getDateRepository(context: Context): TracingIntervalRepository { - return getInstance( - AppDatabase.getInstance(context.applicationContext) - .tracingIntervalDao() - ) - } - } - - suspend fun createInterval(from: Long, to: Long) { - Timber.v("Insert Tracing Interval $from, $to") - if (to < from) throw IllegalArgumentException("to cannot be before from") - tracingIntervalDao.insertInterval( - TracingIntervalEntity().apply { - this.from = from - this.to = to - } - ) - } - - suspend fun getIntervals(): List<Pair<Long, Long>> { - val retentionTimestamp = System.currentTimeMillis() - TimeVariables.getDefaultRetentionPeriodInMS() - tracingIntervalDao.deleteOutdatedIntervals(retentionTimestamp) - - return tracingIntervalDao - .getAllIntervals() - .map { Pair(it.from, it.to) } - .also { Timber.d("Intervals: $it") } - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/states/TracingState.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/states/TracingState.kt index a34123bfa..35b60f17d 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/states/TracingState.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/states/TracingState.kt @@ -5,7 +5,6 @@ import android.text.format.DateUtils import androidx.annotation.ColorInt import de.rki.coronawarnapp.R import de.rki.coronawarnapp.risk.RiskState -import de.rki.coronawarnapp.risk.TimeVariables import de.rki.coronawarnapp.tracing.TracingProgress import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat import de.rki.coronawarnapp.util.TimeAndDateExtensions.toLocalDate @@ -33,8 +32,7 @@ data class IncreasedRisk( val lastExposureDetectionTime: Instant?, val lastEncounterAt: Instant?, val allowManualUpdate: Boolean, - val daysWithEncounters: Int, - val activeTracingDays: Int + val daysWithEncounters: Int ) : TracingState() { val showUpdateButton: Boolean = allowManualUpdate && !isInDetailsMode @@ -70,16 +68,6 @@ data class IncreasedRisk( ) } - fun getRiskActiveTracingDaysInRetentionPeriod(context: Context): String { - if (!isInDetailsMode) return "" - - return if (activeTracingDays < TimeVariables.getDefaultRetentionPeriodInDays()) { - context.getString(R.string.risk_card_body_saved_days).format(activeTracingDays) - } else { - context.getString(R.string.risk_card_body_saved_days_full) - } - } - fun getRiskContactLast(context: Context): String? { if (lastEncounterAt == null) return null // caution! lastEncounterAt is null after migration from 1.7.x -> 1.8.x @@ -107,8 +95,7 @@ data class LowRisk( val lastExposureDetectionTime: Instant?, val lastEncounterAt: Instant?, val allowManualUpdate: Boolean, - val daysWithEncounters: Int, - val activeTracingDays: Int + val daysWithEncounters: Int ) : TracingState() { val showUpdateButton: Boolean = allowManualUpdate && !isInDetailsMode @@ -144,13 +131,6 @@ data class LowRisk( ) } - fun getRiskActiveTracingDaysInRetentionPeriod(context: Context): String = - if (activeTracingDays < TimeVariables.getDefaultRetentionPeriodInDays()) { - context.getString(R.string.risk_card_body_saved_days).format(activeTracingDays) - } else { - context.getString(R.string.risk_card_body_saved_days_full) - } - fun getRiskContactLast(context: Context): String? { if (lastEncounterAt == null) return null // caution! lastEncounterAt is null after migration from 1.7.x -> 1.8.x diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/states/TracingStateProvider.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/states/TracingStateProvider.kt index cb94ae132..2e7017757 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/states/TracingStateProvider.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/states/TracingStateProvider.kt @@ -38,9 +38,6 @@ class TracingStateProvider @AssistedInject constructor( riskLevelStorage.latestAndLastSuccessful.onEach { Timber.v("riskLevelResults: $it") }, - tracingRepository.activeTracingDaysInRetentionPeriod.onEach { - Timber.v("activeTracingDaysInRetentionPeriod: $it") - }, exposureDetectionTracker.latestSubmission().onEach { Timber.v("latestSubmission: $it") }, @@ -50,7 +47,6 @@ class TracingStateProvider @AssistedInject constructor( ) { tracingStatus, tracingProgress, riskLevelResults, - activeTracingDaysInRetentionPeriod, latestSubmission, isBackgroundJobEnabled -> @@ -76,7 +72,6 @@ class TracingStateProvider @AssistedInject constructor( lastExposureDetectionTime = latestSubmission?.startedAt, lastEncounterAt = latestCalc.lastRiskEncounterAt, daysWithEncounters = latestCalc.daysWithEncounters, - activeTracingDays = activeTracingDaysInRetentionPeriod.toInt(), allowManualUpdate = !isBackgroundJobEnabled ) latestCalc.riskState == RiskState.INCREASED_RISK -> IncreasedRisk( @@ -85,7 +80,6 @@ class TracingStateProvider @AssistedInject constructor( lastExposureDetectionTime = latestSubmission?.startedAt, lastEncounterAt = latestCalc.lastRiskEncounterAt, daysWithEncounters = latestCalc.daysWithEncounters, - activeTracingDays = activeTracingDaysInRetentionPeriod.toInt(), allowManualUpdate = !isBackgroundJobEnabled ) else -> TracingFailed( diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/TracingExplanationDialog.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/TracingExplanationDialog.kt deleted file mode 100644 index 57882ac32..000000000 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/TracingExplanationDialog.kt +++ /dev/null @@ -1,38 +0,0 @@ -package de.rki.coronawarnapp.tracing.ui - -import android.content.Context -import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.ui.main.home.HomeFragment -import de.rki.coronawarnapp.util.DialogHelper -import javax.inject.Inject - -class TracingExplanationDialog @Inject constructor( - private val homeFragment: HomeFragment -) { - private val context: Context - get() = homeFragment.requireContext() - - fun show(activeTracingDaysInRetentionPeriod: Long, onPositive: () -> Unit) { - // get all text strings and the current active tracing time - val infoPeriodLogged = - context.getString(R.string.risk_details_information_body_period_logged) - val infoPeriodLoggedAssessment = - context.getString( - R.string.risk_details_information_body_period_logged_assessment_under_14_days, - activeTracingDaysInRetentionPeriod.toString() - ) - val infoFAQ = context.getString(R.string.risk_details_explanation_dialog_faq_body) - - val data = DialogHelper.DialogInstance( - context = context, - title = context.getString(R.string.risk_details_explanation_dialog_title), - message = "$infoPeriodLogged\n\n$infoPeriodLoggedAssessment\n\n$infoFAQ", - positiveButton = context.getString(R.string.errors_generic_button_positive), - negativeButton = null, - cancelable = null, - positiveButtonFunction = onPositive, - negativeButtonFunction = {} - ) - DialogHelper.showDialog(data) - } -} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragmentViewModel.kt index e7fa20879..66db20820 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragmentViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsFragmentViewModel.kt @@ -101,7 +101,6 @@ class TracingDetailsFragmentViewModel @AssistedInject constructor( fun refreshData() { launch { tracingRepository.refreshRiskLevel() - tracingRepository.refreshActiveTracingDaysInRetentionPeriod() } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProvider.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProvider.kt index c5a0e75bc..68ffdbac5 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProvider.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProvider.kt @@ -5,7 +5,6 @@ import de.rki.coronawarnapp.datadonation.survey.Surveys import de.rki.coronawarnapp.risk.RiskState import de.rki.coronawarnapp.risk.storage.RiskLevelStorage import de.rki.coronawarnapp.risk.tryLatestResultsWithDefaults -import de.rki.coronawarnapp.storage.TracingRepository import de.rki.coronawarnapp.tracing.GeneralTracingStatus import de.rki.coronawarnapp.tracing.GeneralTracingStatus.Status import de.rki.coronawarnapp.tracing.ui.details.items.DetailsItem @@ -29,7 +28,6 @@ import javax.inject.Inject @Reusable class TracingDetailsItemProvider @Inject constructor( tracingStatus: GeneralTracingStatus, - tracingRepository: TracingRepository, riskLevelStorage: RiskLevelStorage, surveys: Surveys ) { @@ -37,11 +35,9 @@ class TracingDetailsItemProvider @Inject constructor( val state: Flow<List<DetailsItem>> = combine( tracingStatus.generalStatus, riskLevelStorage.latestAndLastSuccessful, - tracingRepository.activeTracingDaysInRetentionPeriod, surveys.availableSurveys ) { status, riskLevelResults, - activeTracingDaysInRetentionPeriod, availableSurveys -> val (latestCalc, _) = riskLevelResults.tryLatestResultsWithDefaults() @@ -72,7 +68,6 @@ class TracingDetailsItemProvider @Inject constructor( if (latestCalc.riskState != RiskState.CALCULATION_FAILED && status != Status.TRACING_INACTIVE) { PeriodLoggedBox.Item( - activeTracingDaysInRetentionPeriod = activeTracingDaysInRetentionPeriod.toInt(), tracingStatus = status ).also { add(it) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/items/periodlogged/PeriodLoggedBox.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/items/periodlogged/PeriodLoggedBox.kt index 7f3fe0d2b..985a26953 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/items/periodlogged/PeriodLoggedBox.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/details/items/periodlogged/PeriodLoggedBox.kt @@ -34,14 +34,9 @@ class PeriodLoggedBox( } data class Item( - val activeTracingDaysInRetentionPeriod: Int, val tracingStatus: GeneralTracingStatus.Status ) : DetailsItem { - fun getRiskActiveTracingDaysInRetentionPeriodLogged(context: Context): String = context.getString( - R.string.risk_details_information_body_period_logged_assessment_under_14_days - ).format(activeTracingDaysInRetentionPeriod) - fun getProgressColor(context: Context) = when (tracingStatus) { GeneralTracingStatus.Status.TRACING_INACTIVE, GeneralTracingStatus.Status.BLUETOOTH_DISABLED, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/settings/SettingsTracingFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/settings/SettingsTracingFragmentViewModel.kt index ca9bc2c5c..37a9cdd1e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/settings/SettingsTracingFragmentViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/tracing/ui/settings/SettingsTracingFragmentViewModel.kt @@ -12,12 +12,10 @@ import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.reporting.report import de.rki.coronawarnapp.nearby.InternalExposureNotificationClient import de.rki.coronawarnapp.nearby.TracingPermissionHelper -import de.rki.coronawarnapp.storage.TracingRepository import de.rki.coronawarnapp.tracing.GeneralTracingStatus import de.rki.coronawarnapp.tracing.ui.details.items.periodlogged.PeriodLoggedBox import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.device.BackgroundModeStatus -import de.rki.coronawarnapp.util.flow.combine import de.rki.coronawarnapp.util.flow.shareLatest import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel @@ -33,20 +31,14 @@ import timber.log.Timber class SettingsTracingFragmentViewModel @AssistedInject constructor( dispatcherProvider: DispatcherProvider, tracingStatus: GeneralTracingStatus, - tracingRepository: TracingRepository, private val backgroundStatus: BackgroundModeStatus, tracingPermissionHelperFactory: TracingPermissionHelper.Factory ) : CWAViewModel(dispatcherProvider = dispatcherProvider) { - val loggingPeriod: LiveData<PeriodLoggedBox.Item> = combine( - tracingRepository.activeTracingDaysInRetentionPeriod, - tracingStatus.generalStatus - ) { activeTracingDays, - status -> - PeriodLoggedBox.Item(activeTracingDays.toInt(), status) - } - .onEach { Timber.v("logginPeriod onEach") } - .asLiveData(dispatcherProvider.Main) + val loggingPeriod: LiveData<PeriodLoggedBox.Item> = + tracingStatus.generalStatus.map { PeriodLoggedBox.Item(it) } + .onEach { Timber.v("logginPeriod onEach") } + .asLiveData(dispatcherProvider.Main) val tracingSettingsState: LiveData<TracingSettingsState> = tracingStatus.generalStatus .map { it.toTracingSettingsState() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt index cf4fa1501..d08a82cd6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt @@ -9,7 +9,6 @@ import androidx.recyclerview.widget.DefaultItemAnimator import androidx.recyclerview.widget.LinearLayoutManager import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.HomeFragmentLayoutBinding -import de.rki.coronawarnapp.tracing.ui.TracingExplanationDialog import de.rki.coronawarnapp.ui.main.home.popups.DeviceTimeIncorrectDialog import de.rki.coronawarnapp.util.ContextExtensions.getColorCompat import de.rki.coronawarnapp.util.DialogHelper @@ -41,7 +40,6 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject { val binding: HomeFragmentLayoutBinding by viewBindingLazy() @Inject lateinit var homeMenu: HomeMenu - @Inject lateinit var tracingExplanationDialog: TracingExplanationDialog @Inject lateinit var deviceTimeIncorrectDialog: DeviceTimeIncorrectDialog private val homeAdapter = HomeAdapter() @@ -80,11 +78,6 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject { vm.popupEvents.observe2(this) { event -> when (event) { - is HomeFragmentEvents.ShowTracingExplanation -> { - tracingExplanationDialog.show(event.activeTracingDaysInRetentionPeriod) { - vm.tracingExplanationWasShown() - } - } HomeFragmentEvents.ShowErrorResetDialog -> { RecoveryByResetDialogFactory(this).showDialog( detailsLink = R.string.errors_generic_text_catastrophic_error_encryption_failure, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt index 595e0aa4f..c99db2506 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt @@ -2,10 +2,6 @@ package de.rki.coronawarnapp.ui.main.home sealed class HomeFragmentEvents { - data class ShowTracingExplanation( - val activeTracingDaysInRetentionPeriod: Long - ) : HomeFragmentEvents() - object ShowErrorResetDialog : HomeFragmentEvents() object ShowDeleteTestDialog : HomeFragmentEvents() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt index 86309e8ec..f10170180 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt @@ -9,7 +9,6 @@ import de.rki.coronawarnapp.appconfig.AppConfigProvider import de.rki.coronawarnapp.deadman.DeadmanNotificationScheduler import de.rki.coronawarnapp.main.CWASettings import de.rki.coronawarnapp.notification.ShareTestResultNotificationService -import de.rki.coronawarnapp.risk.TimeVariables import de.rki.coronawarnapp.statistics.source.StatisticsProvider import de.rki.coronawarnapp.statistics.ui.homecards.StatisticsHomeCard import de.rki.coronawarnapp.storage.LocalData @@ -49,7 +48,6 @@ import de.rki.coronawarnapp.tracing.ui.homecards.TracingProgressCard import de.rki.coronawarnapp.tracing.ui.statusbar.TracingHeaderState import de.rki.coronawarnapp.tracing.ui.statusbar.toHeaderState import de.rki.coronawarnapp.ui.main.home.HomeFragmentEvents.ShowErrorResetDialog -import de.rki.coronawarnapp.ui.main.home.HomeFragmentEvents.ShowTracingExplanation import de.rki.coronawarnapp.ui.main.home.items.FAQCard import de.rki.coronawarnapp.ui.main.home.items.HomeItem import de.rki.coronawarnapp.ui.main.home.items.ReenableRiskCard @@ -96,15 +94,6 @@ class HomeFragmentViewModel @AssistedInject constructor( val popupEvents = SingleLiveEvent<HomeFragmentEvents>() fun showPopUps() { - launch { - if (!LocalData.tracingExplanationDialogWasShown()) { - popupEvents.postValue( - ShowTracingExplanation( - TimeVariables.getActiveTracingDaysInRetentionPeriod() - ) - ) - } - } launch { if (errorResetTool.isResetNoticeToBeShown) { popupEvents.postValue(ShowErrorResetDialog) @@ -293,7 +282,6 @@ class HomeFragmentViewModel @AssistedInject constructor( launch { submissionRepository.refreshDeviceUIState() tracingRepository.refreshRiskLevel() - tracingRepository.refreshActiveTracingDaysInRetentionPeriod() } } @@ -303,10 +291,6 @@ class HomeFragmentViewModel @AssistedInject constructor( } } - fun tracingExplanationWasShown() { - LocalData.tracingExplanationDialogWasShown(true) - } - private fun refreshDiagnosisKeys() { tracingRepository.refreshDiagnosisKeys() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataReset.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataReset.kt index 288055841..01c1799d7 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataReset.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/DataReset.kt @@ -14,7 +14,6 @@ import de.rki.coronawarnapp.main.CWASettings import de.rki.coronawarnapp.nearby.modules.detectiontracker.ExposureDetectionTracker import de.rki.coronawarnapp.risk.storage.RiskLevelStorage import de.rki.coronawarnapp.statistics.source.StatisticsProvider -import de.rki.coronawarnapp.storage.AppDatabase import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.submission.SubmissionRepository import de.rki.coronawarnapp.util.di.AppContext @@ -56,8 +55,6 @@ class DataReset @Inject constructor( @SuppressLint("ApplySharedPref") // We need a commit here to ensure consistency suspend fun clearAllLocalData() = mutex.withLock { Timber.w("CWA LOCAL DATA DELETION INITIATED.") - // Database Reset - AppDatabase.reset(context) // Because LocalData does not behave like a normal shared preference LocalData.clear() // Shared Preferences Reset diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/EncryptionErrorResetTool.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/EncryptionErrorResetTool.kt index 785a30392..ae4f6a47b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/EncryptionErrorResetTool.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/EncryptionErrorResetTool.kt @@ -3,7 +3,6 @@ package de.rki.coronawarnapp.util.security import android.content.Context import android.content.SharedPreferences import androidx.core.content.edit -import de.rki.coronawarnapp.storage.DATABASE_NAME import de.rki.coronawarnapp.util.TimeStamper import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.errors.causes @@ -33,9 +32,6 @@ class EncryptionErrorResetTool @Inject constructor( val sharedPrefsDir = File(appbaseDir, "shared_prefs") File(sharedPrefsDir, "${SecurityConstants.ENCRYPTED_SHARED_PREFERENCES_FILE}.xml") } - private val encryptedDatabaseFile by lazy { - context.getDatabasePath(DATABASE_NAME) - } private val prefs: SharedPreferences by lazy { context.getSharedPreferences("encryption_error_reset_tool", Context.MODE_PRIVATE) } @@ -116,14 +112,6 @@ class EncryptionErrorResetTool @Inject constructor( return false } - // The user may have encountered the error even before a database was created. - if (encryptedDatabaseFile.exists() && !encryptedDatabaseFile.delete()) { - Timber.w("Couldn't delete %s", encryptedDatabaseFile) - // There was a database, but we couldn't delete it - // The database is inaccessible without the matching preferences (which we just deleted). - return false - } - resetPerformedAt = timeStamper.nowUTC isResetNoticeToBeShown = true diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityConstants.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityConstants.kt index d50d30dc2..03bffdb28 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityConstants.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityConstants.kt @@ -2,9 +2,6 @@ package de.rki.coronawarnapp.util.security object SecurityConstants { const val DIGEST_ALGORITHM = "SHA-256" - const val DB_PASSWORD_MIN_LENGTH = 32 - const val DB_PASSWORD_MAX_LENGTH = 48 - const val CWA_APP_SQLITE_DB_PW = "CWA_APP_SQLITE_DB_PW" const val ENCRYPTED_SHARED_PREFERENCES_FILE = "shared_preferences_cwa" const val EXPORT_FILE_SIGNATURE_VERIFICATION_ALGORITHM = "SHA256withECDSA" } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt index c811176af..cad222cb2 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/security/SecurityHelper.kt @@ -8,9 +8,6 @@ import de.rki.coronawarnapp.exception.CwaSecurityException import de.rki.coronawarnapp.util.di.AppInjector import de.rki.coronawarnapp.util.di.ApplicationComponent import de.rki.coronawarnapp.util.preferences.clearAndNotify -import de.rki.coronawarnapp.util.security.SecurityConstants.CWA_APP_SQLITE_DB_PW -import de.rki.coronawarnapp.util.security.SecurityConstants.DB_PASSWORD_MAX_LENGTH -import de.rki.coronawarnapp.util.security.SecurityConstants.DB_PASSWORD_MIN_LENGTH import de.rki.coronawarnapp.util.security.SecurityConstants.ENCRYPTED_SHARED_PREFERENCES_FILE import timber.log.Timber @@ -47,44 +44,11 @@ object SecurityHelper { private val ByteArray.toPreservedString: String get() = Base64.encodeToString(this, Base64.NO_WRAP) - /** - * Retrieves the db password from encrypted shared preferences. The password is automatically - * encrypted when storing the password and decrypted when retrieving the password. - * - * If no password exists yet, a new password is generated and stored into - * encrypted shared preferences. The length of the password will be in the interval - * of [[DB_PASSWORD_MIN_LENGTH], [DB_PASSWORD_MAX_LENGTH]] - */ - fun getDBPassword(): ByteArray = - getStoredDbPassword() ?: storeDbPassword(generateDBPassword()) - @SuppressLint("ApplySharedPref") fun resetSharedPrefs() { globalEncryptedSharedPreferencesInstance.clearAndNotify() } - private fun getStoredDbPassword(): ByteArray? = - globalEncryptedSharedPreferencesInstance - .getString(CWA_APP_SQLITE_DB_PW, null)?.toPreservedByteArray - - private fun storeDbPassword(keyBytes: ByteArray): ByteArray { - globalEncryptedSharedPreferencesInstance - .edit() - .putString(CWA_APP_SQLITE_DB_PW, keyBytes.toPreservedString) - .apply() - return keyBytes - } - - private fun generateDBPassword(): ByteArray { - val secureRandom = SecurityModule().secureRandom() - val max = DB_PASSWORD_MAX_LENGTH - val min = DB_PASSWORD_MIN_LENGTH - val passwordLength = secureRandom.nextInt(max - min + 1) + min - val password = ByteArray(passwordLength) - secureRandom.nextBytes(password) - return password - } - fun <T> withSecurityCatch(doInCatch: () -> T) = try { doInCatch.invoke() } catch (e: Exception) { diff --git a/Corona-Warn-App/src/main/res/layout/fragment_settings_tracing.xml b/Corona-Warn-App/src/main/res/layout/fragment_settings_tracing.xml index d34c66032..617cb80e2 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_settings_tracing.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_settings_tracing.xml @@ -200,33 +200,6 @@ app:layout_constraintStart_toStartOf="@+id/guideline_start" app:layout_constraintTop_toBottomOf="@+id/settings_tracing_status_bluetooth" /> - <TextView - android:id="@+id/risk_details_period_logged_subtitle" - style="@style/subtitle" - gone="@{!settingsTracingState.isTracingStatusTextVisible()}" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginStart="@dimen/spacing_small" - android:layout_marginTop="@dimen/spacing_normal" - android:focusable="true" - android:text="@{loggedPeriod.getRiskActiveTracingDaysInRetentionPeriodLogged(context)}" - app:layout_constraintEnd_toStartOf="@+id/guideline_end" - app:layout_constraintStart_toEndOf="@+id/risk_details_investigation_period_circle_progress" - app:layout_constraintTop_toBottomOf="@+id/risk_details_period_logged_body_notice" /> - - <de.rki.coronawarnapp.ui.view.CircleProgress - android:id="@+id/risk_details_investigation_period_circle_progress" - gone="@{!settingsTracingState.isTracingStatusTextVisible()}" - android:layout_width="@dimen/spacing_huge" - android:layout_height="@dimen/spacing_huge" - android:importantForAccessibility="no" - app:circleWidth="@dimen/circle_large_width" - app:layout_constraintBottom_toBottomOf="@+id/risk_details_period_logged_subtitle" - app:layout_constraintStart_toStartOf="@+id/guideline_start" - app:layout_constraintTop_toTopOf="@+id/risk_details_period_logged_subtitle" - app:progress="@{loggedPeriod.activeTracingDaysInRetentionPeriod}" - app:progressColor="@{loggedPeriod.getProgressColor(context)}" /> - <include layout="@layout/merge_guidelines_card" /> <include layout="@layout/merge_guidelines_side" /> diff --git a/Corona-Warn-App/src/main/res/layout/tracing_content_increased_view.xml b/Corona-Warn-App/src/main/res/layout/tracing_content_increased_view.xml index 869b464ee..2d2c4b51f 100644 --- a/Corona-Warn-App/src/main/res/layout/tracing_content_increased_view.xml +++ b/Corona-Warn-App/src/main/res/layout/tracing_content_increased_view.xml @@ -78,36 +78,6 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/row_contact_last"> - <de.rki.coronawarnapp.ui.view.CircleProgress - android:id="@+id/risk_card_row_saved_days_circle_progress" - android:layout_width="@dimen/circle_small" - android:layout_height="@dimen/circle_small" - android:layout_marginStart="8dp" - app:circleColor="@color/colorStableHairlineLight" - app:circleWidth="@dimen/circle_small_width" - app:disableText="true" - app:layout_constraintBottom_toBottomOf="@+id/risk_card_row_saved_days_body" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@+id/risk_card_row_saved_days_body" - app:progress="@{state.activeTracingDays}" - app:progressColor="@{state.getProgressColorHighRisk(context)}" /> - - <TextView - android:id="@+id/risk_card_row_saved_days_body" - style="@style/subtitle" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/spacing_tiny" - android:layout_marginBottom="@dimen/spacing_tiny" - android:layout_marginStart="24dp" - android:text="@{state.getRiskActiveTracingDaysInRetentionPeriod(context)}" - android:textColor="@color/colorTextPrimary1InvertedStable" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@+id/risk_card_row_saved_days_circle_progress" - app:layout_constraintTop_toTopOf="parent" - tools:text="@string/risk_card_body_saved_days" - tools:textColor="@color/colorStableLight" /> </androidx.constraintlayout.widget.ConstraintLayout> <de.rki.coronawarnapp.ui.view.TracingCardInfoRow diff --git a/Corona-Warn-App/src/main/res/layout/tracing_content_low_view.xml b/Corona-Warn-App/src/main/res/layout/tracing_content_low_view.xml index dd85e6ef0..048ee99fe 100644 --- a/Corona-Warn-App/src/main/res/layout/tracing_content_low_view.xml +++ b/Corona-Warn-App/src/main/res/layout/tracing_content_low_view.xml @@ -72,47 +72,6 @@ app:layout_constraintTop_toBottomOf="@+id/row_contact" tools:text="@string/risk_card_low_risk_most_recent_body_encounters_on_more_than_one_day" /> - <androidx.constraintlayout.widget.ConstraintLayout - android:id="@+id/row_saved_days" - gone="@{state.isGoneOnContentLowView(context)}" - android:layout_width="0dp" - android:layout_height="wrap_content" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/row_contact_last"> - - <de.rki.coronawarnapp.ui.view.CircleProgress - android:id="@+id/risk_card_row_saved_days_circle_progress" - android:layout_width="@dimen/circle_small" - android:layout_height="@dimen/circle_small" - android:layout_marginStart="8dp" - app:circleColor="@color/colorStableHairlineLight" - app:circleWidth="@dimen/circle_small_width" - app:disableText="true" - app:layout_constraintBottom_toBottomOf="@+id/risk_card_row_saved_days_body" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="@+id/risk_card_row_saved_days_body" - app:progress="@{state.activeTracingDays}" - app:progressColor="@{state.getProgressColorLowRisk(context)}" /> - - <TextView - android:id="@+id/risk_card_row_saved_days_body" - style="@style/subtitle" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/spacing_tiny" - android:layout_marginBottom="@dimen/spacing_tiny" - android:layout_marginStart="24dp" - android:text="@{state.getRiskActiveTracingDaysInRetentionPeriod(context)}" - android:textColor="@color/colorTextPrimary1InvertedStable" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@+id/risk_card_row_saved_days_circle_progress" - app:layout_constraintTop_toTopOf="parent" - tools:text="@string/risk_card_body_saved_days" - tools:textColor="@color/colorStableLight" /> - </androidx.constraintlayout.widget.ConstraintLayout> - <de.rki.coronawarnapp.ui.view.TracingCardInfoRow android:id="@+id/row_time_fetched" android:layout_width="0dp" @@ -123,7 +82,7 @@ app:compatIconTint="@color/colorStableLight" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/row_saved_days" + app:layout_constraintTop_toBottomOf="@+id/row_contact_last" tools:text="@string/risk_card_body_not_yet_fetched" /> <Button diff --git a/Corona-Warn-App/src/main/res/layout/tracing_details_item_periodlogged_view.xml b/Corona-Warn-App/src/main/res/layout/tracing_details_item_periodlogged_view.xml index 49c161997..d89197811 100644 --- a/Corona-Warn-App/src/main/res/layout/tracing_details_item_periodlogged_view.xml +++ b/Corona-Warn-App/src/main/res/layout/tracing_details_item_periodlogged_view.xml @@ -60,46 +60,5 @@ app:layout_constraintTop_toBottomOf="@id/risk_details_period_logged_subtitle" /> </androidx.constraintlayout.widget.ConstraintLayout> - <androidx.constraintlayout.widget.ConstraintLayout - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/spacing_normal" - android:focusable="true" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/risk_details_period_logged_layout"> - - <androidx.constraintlayout.widget.ConstraintLayout - android:id="@+id/icon_background" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent"> - - <de.rki.coronawarnapp.ui.view.CircleProgress - android:id="@+id/risk_details_investigation_period_circle_progress" - android:layout_width="@dimen/spacing_huge" - android:layout_height="@dimen/spacing_huge" - android:importantForAccessibility="no" - app:circleWidth="@dimen/circle_large_width" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintTop_toTopOf="parent" - app:progress="@{loggedPeriod.activeTracingDaysInRetentionPeriod}" - app:progressColor="@{loggedPeriod.getProgressColor(context)}" /> - </androidx.constraintlayout.widget.ConstraintLayout> - - <TextView - style="@style/subtitle" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_marginStart="@dimen/spacing_small" - android:text="@{loggedPeriod.getRiskActiveTracingDaysInRetentionPeriodLogged(context)}" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toEndOf="@+id/icon_background" - app:layout_constraintTop_toTopOf="parent" - tools:text="@string/risk_details_information_body_period_logged_assessment_under_14_days" /> - </androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout> </layout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/values-bg/strings.xml b/Corona-Warn-App/src/main/res/values-bg/strings.xml index 658893e14..64892b65d 100644 --- a/Corona-Warn-App/src/main/res/values-bg/strings.xml +++ b/Corona-Warn-App/src/main/res/values-bg/strings.xml @@ -41,8 +41,6 @@ <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> - <!-- NOTR --> - <string name="preference_risk_days_explanation_shown"><xliff:g id="preference">"preference_risk_days_explanation_shown"</xliff:g></string> <!-- #################################### Generics @@ -107,10 +105,6 @@ Risk Card ###################################### --> - <!-- XTXT: risk card - tracing active for x out of 14 days --> - <string name="risk_card_body_saved_days">"РегиÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк е било активно през %1$s от изминалите 14 дни."</string> - <!-- XTXT: risk card- tracing active for 14 out of 14 days --> - <string name="risk_card_body_saved_days_full">"ÐÑма прекъÑване на региÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк"</string> <!-- XTXT; risk card - no update done yet --> <string name="risk_card_body_not_yet_fetched">"Ð’Ñе още не е извършвана проверка на контактите."</string> <!-- XTXT: risk card - last successful update --> @@ -344,8 +338,6 @@ <string name="risk_details_subtitle_period_logged">"Този период Ñе включва в изчиÑлението."</string> <!-- XHED: risk details - infection period logged information body, below behaviors --> <string name="risk_details_information_body_period_logged">"ВашиÑÑ‚ риÑк от заразÑване може да Ñе изчиÑли Ñамо за периодите, в които региÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк е било активно. Затова тази Ñ„ÑƒÐ½ÐºÑ†Ð¸Ñ Ñ‚Ñ€Ñбва да бъде активирана поÑтоÑнно."</string> - <!-- XHED: risk details - infection period logged information body, below behaviors --> - <string name="risk_details_information_body_period_logged_assessment">"РегиÑтрирането на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк покрива поÑледните 14 дни. За този период от време функциÑта е била активна на Ð’Ð°ÑˆÐ¸Ñ Ñмартфон в продължение на %1$s дни. Приложението изтрива автоматично по-Ñтарите региÑтри, тъй като те вече не могат да Ñлужат за предотвратÑване на заразÑването."</string> <!-- XTXT: risk details - infection period days logged/14 --> <string name="risk_details_information_active_tracing_days_circle_progress">"%s/14"</string> <!-- XHED: risk details - how your risk level was calculated, below behaviors --> @@ -380,10 +372,6 @@ <!-- XACT: risk details page title --> <string name="risk_details_accessibility_title">"ВашиÑÑ‚ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° риÑк"</string> - <!-- XHED: one time risk explanation dialog title --> - <string name="risk_details_explanation_dialog_title">"Ð˜Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð¾Ñ‚Ð½Ð¾Ñно функционалноÑтта за региÑтриране на Ð¸Ð·Ð»Ð°Ð³Ð°Ð½Ð¸Ñ Ð½Ð° риÑк"</string> - <!-- YTXT: one time risk explanation dialog - pointing to the faq page for more information--> - <string name="risk_details_explanation_dialog_faq_body">"За повече Ð¸Ð½Ñ„Ð¾Ñ€Ð¼Ð°Ñ†Ð¸Ñ Ð²Ð¸Ð¶Ñ‚Ðµ Ñтраницата „ЧЗВ“."</string> <!-- XHED: risk details - deadman notification title --> <string name="risk_details_deadman_notification_title">"ВашиÑÑ‚ ÑÑ‚Ð°Ñ‚ÑƒÑ Ð½Ð° риÑк"</string> <!-- YTXT: risk details - deadman notification text --> diff --git a/Corona-Warn-App/src/main/res/values-de/strings.xml b/Corona-Warn-App/src/main/res/values-de/strings.xml index f998d8ee2..8d0bdcd39 100644 --- a/Corona-Warn-App/src/main/res/values-de/strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/strings.xml @@ -42,8 +42,6 @@ <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> - <!-- NOTR --> - <string name="preference_risk_days_explanation_shown"><xliff:g id="preference">"preference_risk_days_explanation_shown"</xliff:g></string> <!-- #################################### Generics @@ -389,10 +387,6 @@ <!-- XACT: risk details page title --> <string name="risk_details_accessibility_title">"Ihr Risikostatus"</string> - <!-- XHED: one time risk explanation dialog title --> - <string name="risk_details_explanation_dialog_title">"Information zur Funktionsweise der Risiko-Ermittlung"</string> - <!-- YTXT: one time risk explanation dialog - pointing to the faq page for more information--> - <string name="risk_details_explanation_dialog_faq_body">"Weitere Informationen finden Sie in den FAQ."</string> <!-- XHED: risk details - deadman notification title --> <string name="risk_details_deadman_notification_title">"Ihr Risikostatus"</string> <!-- YTXT: risk details - deadman notification text --> diff --git a/Corona-Warn-App/src/main/res/values-en/strings.xml b/Corona-Warn-App/src/main/res/values-en/strings.xml index d8c0ec6c5..9f51fb3e4 100644 --- a/Corona-Warn-App/src/main/res/values-en/strings.xml +++ b/Corona-Warn-App/src/main/res/values-en/strings.xml @@ -41,8 +41,6 @@ <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> - <!-- NOTR --> - <string name="preference_risk_days_explanation_shown"><xliff:g id="preference">"preference_risk_days_explanation_shown"</xliff:g></string> <!-- #################################### Generics @@ -107,10 +105,6 @@ Risk Card ###################################### --> - <!-- XTXT: risk card - tracing active for x out of 14 days --> - <string name="risk_card_body_saved_days">"Exposure logging was active for %1$s of the past 14 days."</string> - <!-- XTXT: risk card- tracing active for 14 out of 14 days --> - <string name="risk_card_body_saved_days_full">"Exposure logging permanently active"</string> <!-- XTXT; risk card - no update done yet --> <string name="risk_card_body_not_yet_fetched">"Encounters have not yet been checked."</string> <!-- XTXT: risk card - last successful update --> @@ -344,8 +338,6 @@ <string name="risk_details_subtitle_period_logged">"This period is included in the calculation."</string> <!-- XHED: risk details - infection period logged information body, below behaviors --> <string name="risk_details_information_body_period_logged">"Your risk of infection can be calculated only for periods during which exposure logging was active. The logging feature should therefore remain active permanently."</string> - <!-- XHED: risk details - infection period logged information body, below behaviors --> - <string name="risk_details_information_body_period_logged_assessment">"Exposure logging covers the past 14 days. During this time, the logging feature on your smartphone was active for %1$s days. The app automatically deletes older logs, as these are no longer relevant for infection prevention."</string> <!-- XTXT: risk details - infection period days logged/14 --> <string name="risk_details_information_active_tracing_days_circle_progress">"%s/14"</string> <!-- XHED: risk details - how your risk level was calculated, below behaviors --> @@ -380,10 +372,6 @@ <!-- XACT: risk details page title --> <string name="risk_details_accessibility_title">"Your Risk Status"</string> - <!-- XHED: one time risk explanation dialog title --> - <string name="risk_details_explanation_dialog_title">"Information about exposure logging functionality"</string> - <!-- YTXT: one time risk explanation dialog - pointing to the faq page for more information--> - <string name="risk_details_explanation_dialog_faq_body">"For further information, please see our FAQ page."</string> <!-- XHED: risk details - deadman notification title --> <string name="risk_details_deadman_notification_title">"Your Risk Status"</string> <!-- YTXT: risk details - deadman notification text --> diff --git a/Corona-Warn-App/src/main/res/values-pl/strings.xml b/Corona-Warn-App/src/main/res/values-pl/strings.xml index eaa9f8c59..b851b08de 100644 --- a/Corona-Warn-App/src/main/res/values-pl/strings.xml +++ b/Corona-Warn-App/src/main/res/values-pl/strings.xml @@ -41,8 +41,6 @@ <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> - <!-- NOTR --> - <string name="preference_risk_days_explanation_shown"><xliff:g id="preference">"preference_risk_days_explanation_shown"</xliff:g></string> <!-- #################################### Generics @@ -107,10 +105,6 @@ Risk Card ###################################### --> - <!-- XTXT: risk card - tracing active for x out of 14 days --> - <string name="risk_card_body_saved_days">"Rejestrowanie narażenia byÅ‚o aktywne przez %1$s z ostatnich 14 dni."</string> - <!-- XTXT: risk card- tracing active for 14 out of 14 days --> - <string name="risk_card_body_saved_days_full">"Rejestrowanie narażenia stale aktywne"</string> <!-- XTXT; risk card - no update done yet --> <string name="risk_card_body_not_yet_fetched">"Kontakty nie zostaÅ‚y jeszcze sprawdzone."</string> <!-- XTXT: risk card - last successful update --> @@ -344,8 +338,6 @@ <string name="risk_details_subtitle_period_logged">"Ten okres jest uwzglÄ™dniony w obliczeniu."</string> <!-- XHED: risk details - infection period logged information body, below behaviors --> <string name="risk_details_information_body_period_logged">"Ryzyko zakażenia można obliczyć tylko dla okresów, w których rejestrowanie narażenia byÅ‚o aktywne. Dlatego też funkcja rejestrowania powinna być stale aktywna."</string> - <!-- XHED: risk details - infection period logged information body, below behaviors --> - <string name="risk_details_information_body_period_logged_assessment">"Rejestrowanie narażenia obejmuje ostatnie 14 dni. W tym czasie funkcja rejestrowania w Twoim smartfonie byÅ‚a aktywna przez %1$s dni. Aplikacja automatycznie usuwa starsze dzienniki, ponieważ nie sÄ… one już istotne dla zapobiegania zakażeniom."</string> <!-- XTXT: risk details - infection period days logged/14 --> <string name="risk_details_information_active_tracing_days_circle_progress">"%s/14"</string> <!-- XHED: risk details - how your risk level was calculated, below behaviors --> @@ -380,10 +372,6 @@ <!-- XACT: risk details page title --> <string name="risk_details_accessibility_title">"Twój status ryzyka"</string> - <!-- XHED: one time risk explanation dialog title --> - <string name="risk_details_explanation_dialog_title">"Informacje o funkcjonalnoÅ›ci rejestrowania narażenia"</string> - <!-- YTXT: one time risk explanation dialog - pointing to the faq page for more information--> - <string name="risk_details_explanation_dialog_faq_body">"WiÄ™cej informacji znajduje siÄ™ na naszej stronie „CzÄ™sto zadawane pytaniaâ€."</string> <!-- XHED: risk details - deadman notification title --> <string name="risk_details_deadman_notification_title">"Twój status ryzyka"</string> <!-- YTXT: risk details - deadman notification text --> diff --git a/Corona-Warn-App/src/main/res/values-ro/strings.xml b/Corona-Warn-App/src/main/res/values-ro/strings.xml index 9e673a7e8..222ce34eb 100644 --- a/Corona-Warn-App/src/main/res/values-ro/strings.xml +++ b/Corona-Warn-App/src/main/res/values-ro/strings.xml @@ -41,8 +41,6 @@ <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> - <!-- NOTR --> - <string name="preference_risk_days_explanation_shown"><xliff:g id="preference">"preference_risk_days_explanation_shown"</xliff:g></string> <!-- #################################### Generics @@ -107,10 +105,6 @@ Risk Card ###################################### --> - <!-- XTXT: risk card - tracing active for x out of 14 days --> - <string name="risk_card_body_saved_days">"ÃŽn ultimele 14 zile, înregistrarea în jurnal a expunerilor a fost activă timp de %1$s zile."</string> - <!-- XTXT: risk card- tracing active for 14 out of 14 days --> - <string name="risk_card_body_saved_days_full">"ÃŽnregistrarea în jurnal a expunerilor este permanent activă"</string> <!-- XTXT; risk card - no update done yet --> <string name="risk_card_body_not_yet_fetched">"ÃŽntâlnirile nu au fost încă verificate."</string> <!-- XTXT: risk card - last successful update --> @@ -344,8 +338,6 @@ <string name="risk_details_subtitle_period_logged">"Această perioadă este inclusă în calcul."</string> <!-- XHED: risk details - infection period logged information body, below behaviors --> <string name="risk_details_information_body_period_logged">"Riscul dvs. de infectare poate fi calculat doar pentru perioadele în care a fost activă înregistrarea în jurnal a expunerilor. Prin urmare, caracteristica de înregistrare în jurnal trebuie să rămână permanent activă."</string> - <!-- XHED: risk details - infection period logged information body, below behaviors --> - <string name="risk_details_information_body_period_logged_assessment">"ÃŽnregistrarea în jurnal a expunerilor acoperă ultimele 14 zile. ÃŽn această perioadă, caracteristica de înregistrare în jurnal de pe smartphone-ul dvs. a fost activă timp de %1$s zile. AplicaÈ›ia È™terge automat înregistrările mai vechi din jurnal, întrucât acestea nu mai sunt relevante pentru prevenirea infectării."</string> <!-- XTXT: risk details - infection period days logged/14 --> <string name="risk_details_information_active_tracing_days_circle_progress">"%s/14"</string> <!-- XHED: risk details - how your risk level was calculated, below behaviors --> @@ -380,10 +372,6 @@ <!-- XACT: risk details page title --> <string name="risk_details_accessibility_title">"Starea riscului dvs."</string> - <!-- XHED: one time risk explanation dialog title --> - <string name="risk_details_explanation_dialog_title">"InformaÈ›ii despre funcÈ›ionalitatea de înregistrare în jurnal a expunerilor"</string> - <!-- YTXT: one time risk explanation dialog - pointing to the faq page for more information--> - <string name="risk_details_explanation_dialog_faq_body">"Pentru mai multe informaÈ›ii, consultaÈ›i pagina noastră de întrebări frecvente."</string> <!-- XHED: risk details - deadman notification title --> <string name="risk_details_deadman_notification_title">"Starea riscului dvs."</string> <!-- YTXT: risk details - deadman notification text --> diff --git a/Corona-Warn-App/src/main/res/values-tr/strings.xml b/Corona-Warn-App/src/main/res/values-tr/strings.xml index 771a2ed84..4efbf1533 100644 --- a/Corona-Warn-App/src/main/res/values-tr/strings.xml +++ b/Corona-Warn-App/src/main/res/values-tr/strings.xml @@ -41,8 +41,6 @@ <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> - <!-- NOTR --> - <string name="preference_risk_days_explanation_shown"><xliff:g id="preference">"preference_risk_days_explanation_shown"</xliff:g></string> <!-- #################################### Generics @@ -107,10 +105,6 @@ Risk Card ###################################### --> - <!-- XTXT: risk card - tracing active for x out of 14 days --> - <string name="risk_card_body_saved_days">"Maruz kalma günlüğü son 14 günde %1$s gün etkindi."</string> - <!-- XTXT: risk card- tracing active for 14 out of 14 days --> - <string name="risk_card_body_saved_days_full">"Maruz kalma günlüğü sürekli etkin"</string> <!-- XTXT; risk card - no update done yet --> <string name="risk_card_body_not_yet_fetched">"KarşılaÅŸmalar henüz kontrol edilmedi."</string> <!-- XTXT: risk card - last successful update --> @@ -344,8 +338,6 @@ <string name="risk_details_subtitle_period_logged">"Bu dönem hesaplamaya dahil edildi."</string> <!-- XHED: risk details - infection period logged information body, below behaviors --> <string name="risk_details_information_body_period_logged">"Enfeksiyon riskiniz yalnızca maruz kalma günlüğünün etkin olduÄŸu dönemler için hesaplanabilir. Bu nedenle günlüğe kaydetme özelliÄŸinin sürekli etkin kalması gerekir."</string> - <!-- XHED: risk details - infection period logged information body, below behaviors --> - <string name="risk_details_information_body_period_logged_assessment">"Maruz kalma günlüğü son 14 günü kapsar. Bu süre boyunca akıllı telefonunuzdaki günlüğe kaydetme özelliÄŸi %1$s gün etkindi. Uygulama, enfeksiyondan korunma için artık ilgili olmadığından daha eski kayıtları otomatik olarak siler."</string> <!-- XTXT: risk details - infection period days logged/14 --> <string name="risk_details_information_active_tracing_days_circle_progress">"%s/14"</string> <!-- XHED: risk details - how your risk level was calculated, below behaviors --> @@ -380,10 +372,6 @@ <!-- XACT: risk details page title --> <string name="risk_details_accessibility_title">"Risk Durumunuz"</string> - <!-- XHED: one time risk explanation dialog title --> - <string name="risk_details_explanation_dialog_title">"Maruz kalma günlüğü iÅŸlevi hakkında bilgi"</string> - <!-- YTXT: one time risk explanation dialog - pointing to the faq page for more information--> - <string name="risk_details_explanation_dialog_faq_body">"Daha fazla bilgi için lütfen SSS sayfamıza bakın."</string> <!-- XHED: risk details - deadman notification title --> <string name="risk_details_deadman_notification_title">"Risk Durumunuz"</string> <!-- YTXT: risk details - deadman notification text --> diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml index 20e352f30..6b4386185 100644 --- a/Corona-Warn-App/src/main/res/values/strings.xml +++ b/Corona-Warn-App/src/main/res/values/strings.xml @@ -48,8 +48,6 @@ <string name="preference_polling_test_result_started"><xliff:g id="preference">"preference_polling_test_result_started"</xliff:g></string> <!-- NOTR --> <string name="preference_test_result_notification"><xliff:g id="preference">"preference_test_result_notification"</xliff:g></string> - <!-- NOTR --> - <string name="preference_risk_days_explanation_shown"><xliff:g id="preference">"preference_risk_days_explanation_shown"</xliff:g></string> <!-- #################################### Generics @@ -399,11 +397,6 @@ <!-- XACT: risk details page title --> <string name="risk_details_accessibility_title">"Your Risk Status"</string> - <!-- XHED: one time risk explanation dialog title --> - <string name="risk_details_explanation_dialog_title">"Information about exposure logging functionality"</string> - <!-- YTXT: one time risk explanation dialog - pointing to the faq page for more information--> - <string name="risk_details_explanation_dialog_faq_body">"For further information, please see our FAQ page."</string> - <!-- XHED: risk details - deadman notification title --> <string name="risk_details_deadman_notification_title">"Your Risk Status"</string> <!-- YTXT: risk details - deadman notification text --> diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyDownloadToolTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyDownloadToolTest.kt index 2e298c104..de6126928 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyDownloadToolTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyDownloadToolTest.kt @@ -7,7 +7,6 @@ import de.rki.coronawarnapp.diagnosiskeys.server.LocationCode import de.rki.coronawarnapp.diagnosiskeys.storage.CachedKey import de.rki.coronawarnapp.diagnosiskeys.storage.CachedKeyInfo import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository -import de.rki.coronawarnapp.diagnosiskeys.storage.legacy.LegacyKeyCacheMigration import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations @@ -38,7 +37,6 @@ class KeyDownloadToolTest : BaseIOTest() { private val testDir = File(IO_TEST_BASEDIR, this::class.simpleName!!) private val testFile = File(testDir, "testfile") - @MockK private lateinit var legacyKeyCache: LegacyKeyCacheMigration @MockK private lateinit var keyServer: DiagnosisKeyServer @MockK private lateinit var keyCache: KeyCacheRepository @MockK private lateinit var downloadConfig: KeyDownloadConfig @@ -78,7 +76,6 @@ class KeyDownloadToolTest : BaseIOTest() { } private fun createInstance() = KeyDownloadTool( - legacyKeyCache = legacyKeyCache, keyServer = keyServer, keyCache = keyCache ) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/LegacyKeyCacheMigrationTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/LegacyKeyCacheMigrationTest.kt deleted file mode 100644 index dcb966efc..000000000 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/storage/legacy/LegacyKeyCacheMigrationTest.kt +++ /dev/null @@ -1,213 +0,0 @@ -package de.rki.coronawarnapp.diagnosiskeys.storage.legacy - -import android.content.Context -import android.database.SQLException -import dagger.Lazy -import de.rki.coronawarnapp.util.HashExtensions.hashToMD5 -import de.rki.coronawarnapp.util.TimeStamper -import io.kotest.matchers.shouldBe -import io.mockk.MockKAnnotations -import io.mockk.coEvery -import io.mockk.coVerify -import io.mockk.every -import io.mockk.impl.annotations.MockK -import io.mockk.mockk -import kotlinx.coroutines.runBlocking -import org.joda.time.Duration -import org.joda.time.Instant -import org.junit.jupiter.api.AfterEach -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import testhelpers.BaseIOTest -import java.io.File -import java.io.IOException - -class LegacyKeyCacheMigrationTest : BaseIOTest() { - - @MockK - lateinit var context: Context - - @MockK - lateinit var timeStamper: TimeStamper - - @MockK - lateinit var legacyDao: KeyCacheLegacyDao - - private val testDir = File(IO_TEST_BASEDIR, this::class.simpleName!!) - private val legacyDir = File(testDir, "key-export") - - @BeforeEach - fun setup() { - MockKAnnotations.init(this) - testDir.mkdirs() - testDir.exists() shouldBe true - - every { context.cacheDir } returns testDir - every { timeStamper.nowUTC } returns Instant.EPOCH - - coEvery { legacyDao.clear() } returns Unit - } - - @AfterEach - fun teardown() { - testDir.deleteRecursively() - } - - private fun createTool() = LegacyKeyCacheMigration( - context = context, - legacyDao = Lazy { legacyDao }, - timeStamper = timeStamper - ) - - @Test - fun `nothing happens on null checksum`() { - val tool = createTool() - runBlocking { - tool.tryMigration(null, File(testDir, "something")) - } - - coVerify(exactly = 0) { legacyDao.clear() } - } - - @Test - fun `migrate a file successfully`() { - val legacyFile1 = File(legacyDir, "1234.zip") - legacyFile1.parentFile!!.mkdirs() - legacyFile1.writeText("testdata") - legacyFile1.exists() shouldBe true - - val legacyFile1MD5 = legacyFile1.hashToMD5() - legacyFile1MD5.isNotEmpty() shouldBe true - - val migrationTarget = File(testDir, "migratedkey.zip") - - val tool = createTool() - runBlocking { - tool.tryMigration(legacyFile1MD5, migrationTarget) - } - - legacyFile1.exists() shouldBe false - migrationTarget.exists() shouldBe true - migrationTarget.hashToMD5() shouldBe legacyFile1MD5 - - coVerify(exactly = 1) { legacyDao.clear() } - } - - @Test - fun `migrating a single file fails gracefully`() { - val legacyFile1 = File(legacyDir, "1234.zip") - legacyFile1.parentFile!!.mkdirs() - legacyFile1.writeText("testdata") - legacyFile1.exists() shouldBe true - - val legacyFile1MD5 = legacyFile1.hashToMD5() - legacyFile1MD5.isNotEmpty() shouldBe true - - val migrationTarget = mockk<File>() - every { migrationTarget.path } throws IOException() - - val tool = createTool() - runBlocking { - tool.tryMigration(legacyFile1MD5, migrationTarget) - } - - legacyFile1.exists() shouldBe false - - coVerify(exactly = 1) { legacyDao.clear() } - } - - @Test - fun `legacy app database can crash, we don't care`() { - val legacyFile1 = File(legacyDir, "1234.zip") - legacyFile1.parentFile!!.mkdirs() - legacyFile1.writeText("testdata") - legacyFile1.exists() shouldBe true - - val legacyFile1MD5 = legacyFile1.hashToMD5() - legacyFile1MD5.isNotEmpty() shouldBe true - - val migrationTarget = File(testDir, "migratedkey.zip") - - coEvery { legacyDao.clear() } throws SQLException() - - val tool = createTool() - runBlocking { - tool.tryMigration(legacyFile1MD5, migrationTarget) - } - - legacyFile1.exists() shouldBe false - migrationTarget.exists() shouldBe true - migrationTarget.hashToMD5() shouldBe legacyFile1MD5 - - coVerify(exactly = 1) { legacyDao.clear() } - } - - @Test - fun `init failure causes legacy cache to be cleared`() { - val legacyFile1 = File(legacyDir, "1234.zip") - legacyFile1.parentFile!!.mkdirs() - legacyFile1.writeText("testdata") - - val legacyFile1MD5 = legacyFile1.hashToMD5() - legacyFile1MD5.isNotEmpty() shouldBe true - - legacyFile1.setReadable(false) - - val migrationTarget = File(testDir, "migratedkey.zip") - - val tool = createTool() - runBlocking { - tool.tryMigration(legacyFile1MD5, migrationTarget) - } - - legacyFile1.exists() shouldBe false - migrationTarget.exists() shouldBe false - } - - @Test - fun `stale legacy files (older than 15 days) are cleaned up on init`() { - val legacyFile1 = File(legacyDir, "1234.zip") - legacyFile1.parentFile!!.mkdirs() - legacyFile1.writeText("testdata") - - val legacyFile1MD5 = legacyFile1.hashToMD5() - legacyFile1MD5.isNotEmpty() shouldBe true - - every { timeStamper.nowUTC } returns Instant.ofEpochMilli(legacyFile1.lastModified()) - .plus(Duration.standardDays(16)) - - val migrationTarget = File(testDir, "migratedkey.zip") - - coEvery { legacyDao.clear() } throws SQLException() - - val tool = createTool() - runBlocking { - tool.tryMigration(legacyFile1MD5, migrationTarget) - } - - legacyFile1.exists() shouldBe false - migrationTarget.exists() shouldBe false - } - - @Test - fun `init deletes empty cache dir`() { - legacyDir.mkdirs() - legacyDir.exists() shouldBe true - - runBlocking { - val tool = createTool() - tool.tryMigration("doesntmatter", File(testDir, "1")) - } - legacyDir.exists() shouldBe false - legacyDir.parentFile!!.exists() shouldBe true - - runBlocking { - val tool = createTool() - tool.tryMigration("doesntmatter", File(testDir, "1")) - } - legacyDir.exists() shouldBe false - legacyDir.parentFile!!.exists() shouldBe true - - coVerify(exactly = 1) { legacyDao.clear() } - } -} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt index ca7c68ec6..dbbcda67a 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt @@ -6,7 +6,6 @@ import de.rki.coronawarnapp.deadman.DeadmanNotificationScheduler import de.rki.coronawarnapp.environment.BuildConfigWrap import de.rki.coronawarnapp.main.CWASettings import de.rki.coronawarnapp.notification.ShareTestResultNotificationService -import de.rki.coronawarnapp.risk.TimeVariables import de.rki.coronawarnapp.statistics.source.StatisticsProvider import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.TracingRepository @@ -185,16 +184,9 @@ class HomeFragmentViewModelTest : BaseTest() { every { BuildConfigWrap.VERSION_CODE } returns 1120004 every { cwaSettings.lastChangelogVersion.value } returns 1L andThen 1120004 - every { LocalData.tracingExplanationDialogWasShown() } returns false andThen true - mockkObject(TimeVariables) - coEvery { TimeVariables.getActiveTracingDaysInRetentionPeriod() } coAnswers { 1 } - - every { errorResetTool.isResetNoticeToBeShown } returns false andThen true + every { errorResetTool.isResetNoticeToBeShown } returns true with(createInstance()) { - showPopUps() - popupEvents.getOrAwaitValue() shouldBe HomeFragmentEvents.ShowTracingExplanation(1) - showPopUps() popupEvents.getOrAwaitValue() shouldBe HomeFragmentEvents.ShowErrorResetDialog } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorageTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorageTest.kt index 5e52b89da..f792ede47 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorageTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/storage/BaseRiskLevelStorageTest.kt @@ -13,11 +13,9 @@ import de.rki.coronawarnapp.risk.storage.internal.RiskResultDatabase.AggregatedR import de.rki.coronawarnapp.risk.storage.internal.RiskResultDatabase.ExposureWindowsDao import de.rki.coronawarnapp.risk.storage.internal.RiskResultDatabase.Factory import de.rki.coronawarnapp.risk.storage.internal.RiskResultDatabase.RiskResultsDao -import de.rki.coronawarnapp.risk.storage.legacy.RiskLevelResultMigrator import io.kotest.assertions.throwables.shouldThrow import io.kotest.matchers.shouldBe import io.kotest.matchers.shouldNotBe -import io.mockk.Called import io.mockk.MockKAnnotations import io.mockk.Runs import io.mockk.coEvery @@ -25,7 +23,6 @@ import io.mockk.coVerify import io.mockk.every import io.mockk.impl.annotations.MockK import io.mockk.just -import io.mockk.mockk import io.mockk.spyk import io.mockk.verify import kotlinx.coroutines.CoroutineScope @@ -46,7 +43,6 @@ class BaseRiskLevelStorageTest : BaseTest() { @MockK lateinit var riskResultTables: RiskResultsDao @MockK lateinit var exposureWindowTables: ExposureWindowsDao @MockK lateinit var aggregatedRiskPerDateResultDao: AggregatedRiskPerDateResultDao - @MockK lateinit var riskLevelResultMigrator: RiskLevelResultMigrator @BeforeEach fun setup() { @@ -58,8 +54,6 @@ class BaseRiskLevelStorageTest : BaseTest() { every { database.aggregatedRiskPerDate() } returns aggregatedRiskPerDateResultDao every { database.clearAllTables() } just Runs - coEvery { riskLevelResultMigrator.getLegacyResults() } returns emptyList() - every { riskResultTables.allEntries() } returns emptyFlow() every { riskResultTables.latestEntries(2) } returns emptyFlow() every { riskResultTables.latestAndLastSuccessful() } returns emptyFlow() @@ -79,8 +73,7 @@ class BaseRiskLevelStorageTest : BaseTest() { onDeletedOrphanedExposureWindows: () -> Unit = {} ) = object : BaseRiskLevelStorage( scope = scope, - riskResultDatabaseFactory = databaseFactory, - riskLevelResultMigrator = riskLevelResultMigrator + riskResultDatabaseFactory = databaseFactory ) { override val storedResultLimit: Int = storedResultLimit @@ -130,8 +123,6 @@ class BaseRiskLevelStorageTest : BaseTest() { runBlockingTest { val instance = createInstance() instance.allRiskLevelResults.first() shouldBe listOf(testRisklevelResult) - - verify { riskLevelResultMigrator wasNot Called } } } @@ -146,26 +137,11 @@ class BaseRiskLevelStorageTest : BaseTest() { instance.allRiskLevelResults.first() shouldBe listOf(riskLevelResult) verify { - riskLevelResultMigrator wasNot Called riskResultTables.allEntries() } } } - @Test - fun `riskLevelResults returns legacy results if data is empty`() { - coEvery { riskLevelResultMigrator.getLegacyResults() } returns listOf(mockk(), mockk()) - every { riskResultTables.allEntries() } returns flowOf(emptyList()) - every { exposureWindowTables.allEntries() } returns flowOf(emptyList()) - - runBlockingTest { - val instance = createInstance() - instance.allRiskLevelResults.first().size shouldBe 2 - - coVerify { riskLevelResultMigrator.getLegacyResults() } - } - } - // This just tests the mapping, the correctness of the SQL statement is validated in an instrumentation test @Test fun `latestRiskLevelResults with exposure windows are returned from database and mapped`() { @@ -179,27 +155,12 @@ class BaseRiskLevelStorageTest : BaseTest() { instance.latestRiskLevelResults.first() shouldBe listOf(riskLevelResult) verify { - riskLevelResultMigrator wasNot Called riskResultTables.latestEntries(2) exposureWindowTables.getWindowsForResult(listOf(testRiskLevelResultDao.id)) } } } - @Test - fun `latestRiskLevelResults returns legacy results if data is empty`() { - coEvery { riskLevelResultMigrator.getLegacyResults() } returns listOf(mockk(), mockk()) - every { riskResultTables.latestEntries(2) } returns flowOf(emptyList()) - every { exposureWindowTables.allEntries() } returns flowOf(emptyList()) - - runBlockingTest { - val instance = createInstance() - instance.latestRiskLevelResults.first().size shouldBe 2 - - coVerify { riskLevelResultMigrator.getLegacyResults() } - } - } - // This just tests the mapping, the correctness of the SQL statement is validated in an instrumentation test @Test fun `latestAndLastSuccessful with exposure windows are returned from database and mapped`() { @@ -213,26 +174,12 @@ class BaseRiskLevelStorageTest : BaseTest() { instance.latestAndLastSuccessful.first() shouldBe listOf(riskLevelResult) verify { - riskLevelResultMigrator wasNot Called riskResultTables.latestAndLastSuccessful() exposureWindowTables.getWindowsForResult(listOf(testRiskLevelResultDao.id)) } } } - @Test - fun `latestAndLastSuccessful returns legacy results if data is empty`() { - coEvery { riskLevelResultMigrator.getLegacyResults() } returns listOf(mockk(), mockk()) - every { riskResultTables.latestAndLastSuccessful() } returns flowOf(emptyList()) - - runBlockingTest { - val instance = createInstance() - instance.latestAndLastSuccessful.first().size shouldBe 2 - - coVerify { riskLevelResultMigrator.getLegacyResults() } - } - } - @Test fun `errors when storing risklevel result are rethrown`() = runBlockingTest { coEvery { riskResultTables.insertEntry(any()) } throws IllegalStateException("No body expects the...") diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/storage/legacy/RiskLevelResultMigratorTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/storage/legacy/RiskLevelResultMigratorTest.kt deleted file mode 100644 index a122a3eb7..000000000 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/risk/storage/legacy/RiskLevelResultMigratorTest.kt +++ /dev/null @@ -1,148 +0,0 @@ -package de.rki.coronawarnapp.risk.storage.legacy - -import android.content.Context -import androidx.core.content.edit -import de.rki.coronawarnapp.risk.RiskState -import de.rki.coronawarnapp.util.TimeStamper -import io.kotest.matchers.shouldBe -import io.mockk.MockKAnnotations -import io.mockk.every -import io.mockk.impl.annotations.MockK -import kotlinx.coroutines.runBlocking -import org.joda.time.Instant -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test -import testhelpers.BaseTest -import testhelpers.preferences.MockSharedPreferences - -class RiskLevelResultMigratorTest : BaseTest() { - - @MockK lateinit var timeStamper: TimeStamper - @MockK lateinit var context: Context - private val mockPreferences = MockSharedPreferences() - - @BeforeEach - fun setup() { - MockKAnnotations.init(this) - - every { timeStamper.nowUTC } returns Instant.EPOCH.plus(1337) - } - - fun createInstance() = RiskLevelResultMigrator( - timeStamper = timeStamper, - encryptedPreferences = { mockPreferences }, - context = context - ) - - @Test - fun `normal case with full values`() = runBlocking { - mockPreferences.edit { - putInt("preference_risk_level_score", MigrationRiskLevelConstants.INCREASED_RISK) - putInt("preference_risk_level_score_successful", MigrationRiskLevelConstants.LOW_LEVEL_RISK) - putLong("preference_timestamp_risk_level_calculation", 1234567890L) - } - createInstance().apply { - val legacyResults = getLegacyResults() - legacyResults[0].apply { - riskState shouldBe RiskState.INCREASED_RISK - calculatedAt shouldBe Instant.ofEpochMilli(1234567890L) - } - legacyResults[1].apply { - riskState shouldBe RiskState.LOW_RISK - calculatedAt shouldBe Instant.EPOCH.plus(1337) - } - } - } - - @Test - fun `empty list if no previous data was available`() = runBlocking { - mockPreferences.dataMapPeek.isEmpty() shouldBe true - createInstance().getLegacyResults() shouldBe emptyList() - } - - @Test - fun `if no timestamp is available we use the current time`() = runBlocking { - mockPreferences.edit { - putInt("preference_risk_level_score", MigrationRiskLevelConstants.INCREASED_RISK) - putInt("preference_risk_level_score_successful", MigrationRiskLevelConstants.LOW_LEVEL_RISK) - } - createInstance().apply { - val legacyResults = getLegacyResults() - legacyResults[0].apply { - riskState shouldBe RiskState.INCREASED_RISK - calculatedAt shouldBe Instant.EPOCH.plus(1337) - } - legacyResults[1].apply { - riskState shouldBe RiskState.LOW_RISK - calculatedAt shouldBe Instant.EPOCH.plus(1337) - } - } - } - - @Test - fun `last successful is null`() = runBlocking { - mockPreferences.edit { - putInt("preference_risk_level_score_successful", MigrationRiskLevelConstants.INCREASED_RISK) - } - createInstance().apply { - val legacyResults = getLegacyResults() - legacyResults.size shouldBe 1 - legacyResults.first().apply { - riskState shouldBe RiskState.INCREASED_RISK - calculatedAt shouldBe Instant.EPOCH.plus(1337) - } - } - } - - @Test - fun `last successfully calculated is null`() = runBlocking { - mockPreferences.edit { - putInt("preference_risk_level_score", MigrationRiskLevelConstants.INCREASED_RISK) - putLong("preference_timestamp_risk_level_calculation", 1234567890L) - } - createInstance().apply { - val legacyResults = getLegacyResults() - legacyResults.size shouldBe 1 - legacyResults.first().apply { - riskState shouldBe RiskState.INCREASED_RISK - calculatedAt shouldBe Instant.ofEpochMilli(1234567890L) - } - } - } - - @Test - fun `exceptions are handled gracefully`() = runBlocking { - mockPreferences.edit { - putInt("preference_risk_level_score", MigrationRiskLevelConstants.INCREASED_RISK) - } - every { timeStamper.nowUTC } throws Exception("Surprise!") - createInstance().getLegacyResults() shouldBe emptyList() - } - - @Test - fun `legacy risk level mapping`() { - RiskLevelResultMigrator.mapRiskLevelConstant( - MigrationRiskLevelConstants.NO_CALCULATION_POSSIBLE_TRACING_OFF - ) shouldBe RiskState.CALCULATION_FAILED - - RiskLevelResultMigrator.mapRiskLevelConstant( - MigrationRiskLevelConstants.LOW_LEVEL_RISK - ) shouldBe RiskState.LOW_RISK - - RiskLevelResultMigrator.mapRiskLevelConstant( - MigrationRiskLevelConstants.INCREASED_RISK - ) shouldBe RiskState.INCREASED_RISK - - RiskLevelResultMigrator.mapRiskLevelConstant( - MigrationRiskLevelConstants.UNKNOWN_RISK_OUTDATED_RESULTS - ) shouldBe RiskState.CALCULATION_FAILED - - RiskLevelResultMigrator.mapRiskLevelConstant( - MigrationRiskLevelConstants.UNKNOWN_RISK_OUTDATED_RESULTS_MANUAL - ) shouldBe RiskState.CALCULATION_FAILED - - RiskLevelResultMigrator.mapRiskLevelConstant( - MigrationRiskLevelConstants.UNDETERMINED - ) shouldBe RiskState.CALCULATION_FAILED - } -} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/DatabaseConstantsTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/DatabaseConstantsTest.kt deleted file mode 100644 index 1455528be..000000000 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/DatabaseConstantsTest.kt +++ /dev/null @@ -1,12 +0,0 @@ -package de.rki.coronawarnapp.storage - -import org.junit.Assert -import org.junit.Test - -class DatabaseConstantsTest { - - @Test - fun allDatabaseConstants() { - Assert.assertEquals(DATABASE_NAME, "coronawarnapp-db") - } -} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepositoryTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepositoryTest.kt deleted file mode 100644 index 1729c44fd..000000000 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/storage/tracing/TracingIntervalRepositoryTest.kt +++ /dev/null @@ -1,64 +0,0 @@ -package de.rki.coronawarnapp.storage.tracing - -import io.mockk.MockKAnnotations -import io.mockk.Runs -import io.mockk.coEvery -import io.mockk.coVerify -import io.mockk.impl.annotations.MockK -import io.mockk.just -import kotlinx.coroutines.runBlocking -import org.junit.Before -import org.junit.Test -import testhelpers.BaseTest -import java.util.Date - -/** - * TracingIntervalRepository test. - */ -class TracingIntervalRepositoryTest : BaseTest() { - - @MockK - private lateinit var dao: TracingIntervalDao - private lateinit var repository: TracingIntervalRepository - - @Before - fun setUp() { - MockKAnnotations.init(this) - repository = TracingIntervalRepository(dao) - - coEvery { dao.deleteOutdatedIntervals(any()) } just Runs - coEvery { dao.insertInterval(any()) } just Runs - coEvery { dao.getAllIntervals() } returns listOf() - } - - /** - * Test DAO is called. - */ - @Test - fun testCreate() { - val today = Date().time - - runBlocking { - repository.createInterval(today - 1, today) - - coVerify { - dao.insertInterval(any()) - } - } - } - - /** - * Test DAO is called. - */ - @Test - fun testGet() { - runBlocking { - repository.getIntervals() - - coVerify { - dao.deleteOutdatedIntervals(any()) - dao.getAllIntervals() - } - } - } -} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/states/IncreasedRiskTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/states/IncreasedRiskTest.kt index 778e65573..438f59d49 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/states/IncreasedRiskTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/states/IncreasedRiskTest.kt @@ -61,7 +61,6 @@ internal class IncreasedRiskTest { lastExposureDetectionTime = Instant.now(), allowManualUpdate = false, daysWithEncounters = 1, - activeTracingDays = 1, lastEncounterAt = Instant.now() ) } diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/states/LowRiskTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/states/LowRiskTest.kt index 4b997aa7c..8fb93b6e4 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/states/LowRiskTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/states/LowRiskTest.kt @@ -32,7 +32,6 @@ internal class LowRiskTest { lastExposureDetectionTime = Instant.now(), allowManualUpdate = false, daysWithEncounters = 0, - activeTracingDays = 1, lastEncounterAt = null ) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProviderTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProviderTest.kt index b8a3664aa..73be55667 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProviderTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/tracing/ui/details/TracingDetailsItemProviderTest.kt @@ -8,7 +8,6 @@ import de.rki.coronawarnapp.risk.ProtoRiskLevel import de.rki.coronawarnapp.risk.RiskLevelTaskResult import de.rki.coronawarnapp.risk.result.AggregatedRiskResult import de.rki.coronawarnapp.risk.storage.RiskLevelStorage -import de.rki.coronawarnapp.storage.TracingRepository import de.rki.coronawarnapp.tracing.GeneralTracingStatus import de.rki.coronawarnapp.tracing.ui.details.items.additionalinfos.AdditionalInfoLowRiskBox import de.rki.coronawarnapp.tracing.ui.details.items.behavior.BehaviorIncreasedRiskBox @@ -39,7 +38,6 @@ class TracingDetailsItemProviderTest : BaseTest() { @MockK(relaxed = true) lateinit var aggregatedRiskResult: AggregatedRiskResult @MockK lateinit var tracingStatus: GeneralTracingStatus - @MockK lateinit var tracingRepository: TracingRepository @MockK lateinit var riskLevelStorage: RiskLevelStorage @MockK lateinit var surveys: Surveys @@ -51,7 +49,6 @@ class TracingDetailsItemProviderTest : BaseTest() { private fun createInstance() = TracingDetailsItemProvider( tracingStatus = tracingStatus, - tracingRepository = tracingRepository, riskLevelStorage = riskLevelStorage, surveys = surveys ) @@ -63,7 +60,6 @@ class TracingDetailsItemProviderTest : BaseTest() { availableSurveys: List<Surveys.Type> = emptyList() ) { every { tracingStatus.generalStatus } returns flowOf(status) - every { tracingRepository.activeTracingDaysInRetentionPeriod } returns flowOf(0) every { aggregatedRiskResult.totalRiskLevel } returns riskLevel every { surveys.availableSurveys } returns flowOf(availableSurveys) diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/security/EncryptionResetToolTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/security/EncryptionResetToolTest.kt index 9b16e6e67..574b1a009 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/security/EncryptionResetToolTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/util/security/EncryptionResetToolTest.kt @@ -29,14 +29,12 @@ class EncryptionResetToolTest : BaseIOTest() { private val testDir = File(IO_TEST_BASEDIR, this::class.simpleName!!) private val privateFilesDir = File(testDir, "files") private val encryptedPrefsFile = File(testDir, "shared_prefs/shared_preferences_cwa.xml") - private val encryptedDatabaseFile = File(testDir, "databases/coronawarnapp-db") @BeforeEach fun setup() { MockKAnnotations.init(this) every { context.filesDir } returns privateFilesDir - every { context.getDatabasePath("coronawarnapp-db") } returns encryptedDatabaseFile mockPreferences = MockSharedPreferences() every { @@ -65,11 +63,6 @@ class EncryptionResetToolTest : BaseIOTest() { createNewFile() exists() shouldBe true } - encryptedDatabaseFile.apply { - parentFile!!.mkdirs() - createNewFile() - exists() shouldBe true - } } @Test @@ -79,7 +72,6 @@ class EncryptionResetToolTest : BaseIOTest() { createInstance() encryptedPrefsFile.exists() shouldBe true - encryptedDatabaseFile.exists() shouldBe true mockPreferences.dataMapPeek shouldBe emptyMap() } @@ -107,7 +99,6 @@ class EncryptionResetToolTest : BaseIOTest() { createInstance().tryResetIfNecessary(Exception()) encryptedPrefsFile.exists() shouldBe true - encryptedDatabaseFile.exists() shouldBe true } /** @@ -145,7 +136,6 @@ class EncryptionResetToolTest : BaseIOTest() { ) shouldBe false encryptedPrefsFile.exists() shouldBe false - encryptedDatabaseFile.exists() shouldBe false mockPreferences.dataMapPeek.apply { this["ea1851.reset.performedAt"] shouldBe 1234567890L @@ -189,7 +179,6 @@ class EncryptionResetToolTest : BaseIOTest() { ) shouldBe true encryptedPrefsFile.exists() shouldBe false - encryptedDatabaseFile.exists() shouldBe false mockPreferences.dataMapPeek.apply { this["ea1851.reset.performedAt"] shouldBe 1234567890L @@ -214,7 +203,6 @@ class EncryptionResetToolTest : BaseIOTest() { ) shouldBe true encryptedPrefsFile.exists() shouldBe false - encryptedDatabaseFile.exists() shouldBe false mockPreferences.dataMapPeek.apply { this["ea1851.reset.performedAt"] shouldBe 1234567890L @@ -240,7 +228,6 @@ class EncryptionResetToolTest : BaseIOTest() { ) shouldBe true encryptedPrefsFile.exists() shouldBe false - encryptedDatabaseFile.exists() shouldBe false mockPreferences.dataMapPeek.apply { this["ea1851.reset.performedAt"] shouldBe 1234567890L @@ -269,7 +256,6 @@ class EncryptionResetToolTest : BaseIOTest() { ) shouldBe false encryptedPrefsFile.exists() shouldBe true - encryptedDatabaseFile.exists() shouldBe true mockPreferences.dataMapPeek.apply { this["ea1851.reset.performedAt"] shouldBe null @@ -287,7 +273,6 @@ class EncryptionResetToolTest : BaseIOTest() { ) shouldBe false encryptedPrefsFile.exists() shouldBe true - encryptedDatabaseFile.exists() shouldBe true mockPreferences.dataMapPeek.apply { this["ea1851.reset.performedAt"] shouldBe null @@ -307,7 +292,6 @@ class EncryptionResetToolTest : BaseIOTest() { ) shouldBe false encryptedPrefsFile.exists() shouldBe true - encryptedDatabaseFile.exists() shouldBe true mockPreferences.dataMapPeek.apply { this["ea1851.reset.performedAt"] shouldBe null @@ -325,7 +309,6 @@ class EncryptionResetToolTest : BaseIOTest() { ) shouldBe false encryptedPrefsFile.exists() shouldBe false - encryptedDatabaseFile.exists() shouldBe false mockPreferences.dataMapPeek.apply { this["ea1851.reset.performedAt"] shouldBe null @@ -346,28 +329,6 @@ class EncryptionResetToolTest : BaseIOTest() { ) shouldBe false encryptedPrefsFile.exists() shouldBe true - encryptedDatabaseFile.exists() shouldBe true - - mockPreferences.dataMapPeek.apply { - this["ea1851.reset.performedAt"] shouldBe null - this["ea1851.reset.windowconsumed.160"] shouldBe true - this["ea1851.reset.shownotice"] shouldBe null - } - } - - @Test - fun `the reset is considered failed if the database exists and can not be deleted`() { - createMockFiles() - encryptedDatabaseFile.delete() - encryptedDatabaseFile.mkdir() // Can't delete directories with children via `delete()` - File(encryptedDatabaseFile, "prevent deletion").createNewFile() - - createInstance().tryResetIfNecessary( - GeneralSecurityException("decryption failed") - ) shouldBe false - - encryptedPrefsFile.exists() shouldBe false - encryptedDatabaseFile.exists() shouldBe true mockPreferences.dataMapPeek.apply { this["ea1851.reset.performedAt"] shouldBe null diff --git a/Corona-Warn-App/src/testDevice/java/de/rki/coronawarnapp/test/risk/storage/DefaultRiskLevelStorageTest.kt b/Corona-Warn-App/src/testDevice/java/de/rki/coronawarnapp/test/risk/storage/DefaultRiskLevelStorageTest.kt index d0dffa6df..1ea39918f 100644 --- a/Corona-Warn-App/src/testDevice/java/de/rki/coronawarnapp/test/risk/storage/DefaultRiskLevelStorageTest.kt +++ b/Corona-Warn-App/src/testDevice/java/de/rki/coronawarnapp/test/risk/storage/DefaultRiskLevelStorageTest.kt @@ -6,7 +6,6 @@ import de.rki.coronawarnapp.risk.result.AggregatedRiskResult import de.rki.coronawarnapp.risk.storage.DefaultRiskLevelStorage import de.rki.coronawarnapp.risk.storage.internal.RiskResultDatabase import de.rki.coronawarnapp.risk.storage.internal.riskresults.PersistedRiskLevelResultDao -import de.rki.coronawarnapp.risk.storage.legacy.RiskLevelResultMigrator import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations @@ -32,7 +31,6 @@ class DefaultRiskLevelStorageTest : BaseTest() { @MockK lateinit var database: RiskResultDatabase @MockK lateinit var riskResultTables: RiskResultDatabase.RiskResultsDao @MockK lateinit var exposureWindowTables: RiskResultDatabase.ExposureWindowsDao - @MockK lateinit var riskLevelResultMigrator: RiskLevelResultMigrator private val testRiskLevelResultDao = PersistedRiskLevelResultDao( id = "riskresult-id", @@ -75,8 +73,6 @@ class DefaultRiskLevelStorageTest : BaseTest() { every { database.exposureWindows() } returns exposureWindowTables every { database.clearAllTables() } just Runs - coEvery { riskLevelResultMigrator.getLegacyResults() } returns emptyList() - every { riskResultTables.allEntries() } returns flowOf(listOf(testRiskLevelResultDao)) every { riskResultTables.latestEntries(2) } returns emptyFlow() every { riskResultTables.latestAndLastSuccessful() } returns emptyFlow() @@ -93,8 +89,7 @@ class DefaultRiskLevelStorageTest : BaseTest() { scope: CoroutineScope = TestCoroutineScope() ) = DefaultRiskLevelStorage( scope = scope, - riskResultDatabaseFactory = databaseFactory, - riskLevelResultMigrator = riskLevelResultMigrator + riskResultDatabaseFactory = databaseFactory ) @Test diff --git a/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/risk/storage/DefaultRiskLevelStorageTest.kt b/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/risk/storage/DefaultRiskLevelStorageTest.kt index 308b12ed3..af1e3eadf 100644 --- a/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/risk/storage/DefaultRiskLevelStorageTest.kt +++ b/Corona-Warn-App/src/testDeviceForTesters/java/de/rki/coronawarnapp/test/risk/storage/DefaultRiskLevelStorageTest.kt @@ -6,7 +6,6 @@ import de.rki.coronawarnapp.risk.result.AggregatedRiskResult import de.rki.coronawarnapp.risk.storage.DefaultRiskLevelStorage import de.rki.coronawarnapp.risk.storage.internal.RiskResultDatabase import de.rki.coronawarnapp.risk.storage.internal.riskresults.PersistedRiskLevelResultDao -import de.rki.coronawarnapp.risk.storage.legacy.RiskLevelResultMigrator import de.rki.coronawarnapp.server.protocols.internal.v2.RiskCalculationParametersOuterClass import io.kotest.matchers.shouldBe import io.mockk.MockKAnnotations @@ -31,7 +30,6 @@ class DefaultRiskLevelStorageTest : BaseTestInstrumentation() { @MockK lateinit var database: RiskResultDatabase @MockK lateinit var riskResultTables: RiskResultDatabase.RiskResultsDao @MockK lateinit var exposureWindowTables: RiskResultDatabase.ExposureWindowsDao - @MockK lateinit var riskLevelResultMigrator: RiskLevelResultMigrator private val testRiskLevelResultDao = PersistedRiskLevelResultDao( id = "riskresult-id", @@ -74,8 +72,6 @@ class DefaultRiskLevelStorageTest : BaseTestInstrumentation() { every { database.exposureWindows() } returns exposureWindowTables every { database.clearAllTables() } just Runs - coEvery { riskLevelResultMigrator.getLegacyResults() } returns emptyList() - every { riskResultTables.allEntries() } returns flowOf(listOf(testRiskLevelResultDao)) every { riskResultTables.latestEntries(2) } returns emptyFlow() every { riskResultTables.latestAndLastSuccessful() } returns emptyFlow() @@ -90,8 +86,7 @@ class DefaultRiskLevelStorageTest : BaseTestInstrumentation() { private fun createInstance() = DefaultRiskLevelStorage( scope = TestCoroutineScope(), - riskResultDatabaseFactory = databaseFactory, - riskLevelResultMigrator = riskLevelResultMigrator + riskResultDatabaseFactory = databaseFactory ) @Test -- GitLab