diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTask.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTask.kt index 3f82c5cab167fd5bb9177008c721015f1d8c7d40..d04dc5137d1dc33c3eb31577ef33fade451f4594 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTask.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/DownloadDiagnosisKeysTask.kt @@ -82,11 +82,12 @@ class DownloadDiagnosisKeysTask @Inject constructor( if (wasLastDetectionPerformedRecently(now, exposureConfig, trackedExposureDetections)) { // At most one detection every 6h + Timber.tag(TAG).i("task aborted, because detection was performed recently") return object : Task.Result {} } if (hasRecentDetectionAndNoNewFiles(now, keySyncResult, trackedExposureDetections)) { - // Last check was within 24h, and there are no new files. + Timber.tag(TAG).i("task aborted, last check was within 24h, and there are no new files") return object : Task.Result {} } @@ -104,13 +105,14 @@ class DownloadDiagnosisKeysTask @Inject constructor( val isSubmissionSuccessful = enfClient.provideDiagnosisKeys(availableKeyFiles) Timber.tag(TAG).d("Diagnosis Keys provided (success=%s)", isSubmissionSuccessful) - internalProgress.send(Progress.ApiSubmissionFinished) - throwIfCancelled() - + // EXPOSUREAPP-3878 write timestamp immediately after submission, + // so that progress observers can rely on a clean app state if (isSubmissionSuccessful) { saveTimestamp(currentDate, rollbackItems) } + internalProgress.send(Progress.ApiSubmissionFinished) + return object : Task.Result {} } catch (error: Exception) { Timber.tag(TAG).e(error) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/HourPackageSyncTool.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/HourPackageSyncTool.kt index ad63bbb134ffc3583c9fea34bc4c31e1ee2cb724..a15a2fa6969f165ac04109a4a55e3022a8bf878a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/HourPackageSyncTool.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/HourPackageSyncTool.kt @@ -11,7 +11,6 @@ import de.rki.coronawarnapp.diagnosiskeys.storage.CachedKeyInfo.Type import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository import de.rki.coronawarnapp.storage.DeviceStorage import de.rki.coronawarnapp.util.TimeAndDateExtensions.toLocalDate -import de.rki.coronawarnapp.util.TimeAndDateExtensions.toLocalTime import de.rki.coronawarnapp.util.TimeStamper import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import kotlinx.coroutines.CoroutineScope @@ -19,6 +18,7 @@ import kotlinx.coroutines.Deferred import kotlinx.coroutines.async import kotlinx.coroutines.awaitAll import kotlinx.coroutines.withContext +import org.joda.time.DateTimeZone import org.joda.time.Instant import org.joda.time.LocalDate import org.joda.time.LocalTime @@ -117,10 +117,10 @@ class HourPackageSyncTool @Inject constructor( @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal fun expectNewHourPackages(cachedHours: List<CachedKey>, now: Instant): Boolean { - val previousHour = now.toLocalTime().minusHours(1) - val newestHour = cachedHours.map { it.info.toDateTime() }.maxOrNull()?.toLocalTime() + val today = now.toDateTime(DateTimeZone.UTC) + val newestHour = cachedHours.map { it.info.toDateTime() }.maxOrNull() - return previousHour.hourOfDay != newestHour?.hourOfDay + return today.minusHours(1).hourOfDay != newestHour?.hourOfDay || today.toLocalDate() != newestHour.toLocalDate() } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyPackageSyncSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyPackageSyncSettings.kt index 46499c31230bf37e06c79f5c124a5e02f9f61215..767788b052571ee50d306089dec02aba0a7513d6 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyPackageSyncSettings.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/diagnosiskeys/download/KeyPackageSyncSettings.kt @@ -1,9 +1,11 @@ package de.rki.coronawarnapp.diagnosiskeys.download +import android.annotation.SuppressLint import android.content.Context import com.google.gson.Gson import de.rki.coronawarnapp.util.di.AppContext import de.rki.coronawarnapp.util.preferences.FlowPreference +import de.rki.coronawarnapp.util.preferences.clearAndNotify import de.rki.coronawarnapp.util.serialization.BaseGson import org.joda.time.Instant import javax.inject.Inject @@ -32,6 +34,11 @@ class KeyPackageSyncSettings @Inject constructor( writer = FlowPreference.gsonWriter(gson) ) + @SuppressLint("ApplySharedPref") + fun clear() { + prefs.clearAndNotify() + } + data class LastDownload( val startedAt: Instant, val finishedAt: Instant? = null, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/DefaultExposureDetectionTracker.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/DefaultExposureDetectionTracker.kt index 2c55673ffcd5040d3f55d3f9977cc7910c730769..909a66247fd7405a3239631942052de2892add21 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/DefaultExposureDetectionTracker.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/DefaultExposureDetectionTracker.kt @@ -161,6 +161,13 @@ class DefaultExposureDetectionTracker @Inject constructor( } } + override fun clear() { + Timber.i("clear()") + detectionStates.updateSafely { + emptyMap() + } + } + companion object { private const val TAG = "DefaultExposureDetectionTracker" private const val MAX_ENTRY_SIZE = 5 diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTracker.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTracker.kt index 1f0740acda63411295131ab734d60b5865a38ae5..0d6a6e86b50ea87bc3d58913e6773f339b9f410a 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTracker.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/nearby/modules/detectiontracker/ExposureDetectionTracker.kt @@ -8,4 +8,6 @@ interface ExposureDetectionTracker { fun trackNewExposureDetection(identifier: String) fun finishExposureDetection(identifier: String? = null, result: TrackedExposureDetection.Result) + + fun clear() } 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 f8a0ea1ba9b071b79fa8cee41c0785dd76600598..fd533993e2ecbee697a3ec5fc5c2215ce056b7c1 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 @@ -383,46 +383,24 @@ object LocalData { * SERVER FETCH DATA ****************************************************/ - /** - * Gets the last time the server fetched the diagnosis keys from the server as Date object - * from the EncryptedSharedPrefs - * - * @return timestamp as Date - */ - // TODO should be changed to Long as well to align with other timestamps - fun lastTimeDiagnosisKeysFromServerFetch(): Date? { - val time = getSharedPreferenceInstance().getLong( - CoronaWarnApplication.getAppContext() - .getString(R.string.preference_timestamp_diagnosis_keys_fetch), - 0L - ) - if (time == 0L) return null - - return Date(time) + private val dateMapperForFetchTime: (Long) -> Date? = { + if (it != 0L) Date(it) else null } - fun lastTimeDiagnosisKeysFromServerFetchFlow() = + private val lastTimeDiagnosisKeysFetchedFlowPref by lazy { getSharedPreferenceInstance() - .createFlowPreference<Long?>(CoronaWarnApplication.getAppContext() - .getString(R.string.preference_timestamp_diagnosis_keys_fetch), 0L).flow - .map { if (it != null && it != 0L) Date(it) else null } - - /** - * Sets the last time the server fetched the diagnosis keys from the server as Date object - * from the EncryptedSharedPrefs - * - * @param value timestamp as Date - */ - fun lastTimeDiagnosisKeysFromServerFetch(value: Date?) { - getSharedPreferenceInstance().edit(true) { - putLong( - CoronaWarnApplication.getAppContext() - .getString(R.string.preference_timestamp_diagnosis_keys_fetch), - value?.time ?: 0L - ) - } + .createFlowPreference<Long>(key = "preference_timestamp_diagnosis_keys_fetch", 0L) } + fun lastTimeDiagnosisKeysFromServerFetchFlow() = lastTimeDiagnosisKeysFetchedFlowPref.flow + .map { dateMapperForFetchTime(it) } + + fun lastTimeDiagnosisKeysFromServerFetch() = + dateMapperForFetchTime(lastTimeDiagnosisKeysFetchedFlowPref.value) + + fun lastTimeDiagnosisKeysFromServerFetch(value: Date?) = + lastTimeDiagnosisKeysFetchedFlowPref.update { value?.time ?: 0L } + /** * Gets the last time of successful risk level calculation as long * from the EncryptedSharedPrefs @@ -707,4 +685,8 @@ object LocalData { putBoolean(PREFERENCE_INTEROPERABILITY_IS_USED_AT_LEAST_ONCE, value) } } + + fun clear() { + lastTimeDiagnosisKeysFetchedFlowPref.update { 0L } + } } 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 86690e22520a4689a14f591cf5e5edab61ef853a..fd1064bbfef209742a3e763e9ecd386543311e80 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 @@ -22,8 +22,11 @@ package de.rki.coronawarnapp.util import android.annotation.SuppressLint import android.content.Context import de.rki.coronawarnapp.appconfig.AppConfigProvider +import de.rki.coronawarnapp.diagnosiskeys.download.KeyPackageSyncSettings import de.rki.coronawarnapp.diagnosiskeys.storage.KeyCacheRepository +import de.rki.coronawarnapp.nearby.modules.detectiontracker.ExposureDetectionTracker import de.rki.coronawarnapp.storage.AppDatabase +import de.rki.coronawarnapp.storage.LocalData import de.rki.coronawarnapp.storage.RiskLevelRepository import de.rki.coronawarnapp.storage.SubmissionRepository import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository @@ -43,7 +46,9 @@ class DataReset @Inject constructor( @AppContext private val context: Context, private val keyCacheRepository: KeyCacheRepository, private val appConfigProvider: AppConfigProvider, - private val interoperabilityRepository: InteroperabilityRepository + private val interoperabilityRepository: InteroperabilityRepository, + private val exposureDetectionTracker: ExposureDetectionTracker, + private val keyPackageSyncSettings: KeyPackageSyncSettings ) { private val mutex = Mutex() @@ -56,6 +61,8 @@ class DataReset @Inject constructor( 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 SecurityHelper.resetSharedPrefs() // Reset the current risk level stored in LiveData @@ -65,6 +72,8 @@ class DataReset @Inject constructor( keyCacheRepository.clear() appConfigProvider.clear() interoperabilityRepository.clear() + exposureDetectionTracker.clear() + keyPackageSyncSettings.clear() Timber.w("CWA LOCAL DATA DELETION COMPLETED.") } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/preferences/FlowPreference.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/preferences/FlowPreference.kt index c64cbedfde89f3c164c26e3eb1ea2204102d2bd3..2e97359373b6de42a333ade72b7b4542c5e42a73 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/preferences/FlowPreference.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/preferences/FlowPreference.kt @@ -6,6 +6,7 @@ import com.google.gson.Gson import de.rki.coronawarnapp.util.serialization.fromJson import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow +import timber.log.Timber class FlowPreference<T> constructor( private val preferences: SharedPreferences, @@ -17,6 +18,21 @@ class FlowPreference<T> constructor( private val flowInternal = MutableStateFlow(internalValue) val flow: Flow<T> = flowInternal + private val preferenceChangeListener = + SharedPreferences.OnSharedPreferenceChangeListener { changedPrefs, changedKey -> + if (changedKey != key) return@OnSharedPreferenceChangeListener + + val newValue = reader(changedPrefs, changedKey) + val currentvalue = flowInternal.value + if (currentvalue != newValue && flowInternal.compareAndSet(currentvalue, newValue)) { + Timber.v("%s:%s changed to %s", changedPrefs, changedKey, newValue) + } + } + + init { + preferences.registerOnSharedPreferenceChangeListener(preferenceChangeListener) + } + private var internalValue: T get() = reader(preferences, key) set(newValue) { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/preferences/SharedPreferenceExtensions.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/preferences/SharedPreferenceExtensions.kt new file mode 100644 index 0000000000000000000000000000000000000000..0469b3840d2b9417a4ad728314f57cfa871a63ec --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/preferences/SharedPreferenceExtensions.kt @@ -0,0 +1,17 @@ +package de.rki.coronawarnapp.util.preferences + +import android.content.SharedPreferences +import androidx.core.content.edit +import timber.log.Timber + +fun SharedPreferences.clearAndNotify() { + val currentKeys = this.all.keys.toSet() + Timber.v("%s clearAndNotify(): %s", this, currentKeys) + edit { + currentKeys.forEach { remove(it) } + } + // Clear does not notify anyone using registerOnSharedPreferenceChangeListener + edit(commit = true) { + clear() + } +} 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 370ab58fd4ce02e2358bc1dd9f66557020403546..c1c145e4965c2cd874b65a4c107f0976e59557dd 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 @@ -27,6 +27,7 @@ import androidx.annotation.VisibleForTesting 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 @@ -80,7 +81,7 @@ object SecurityHelper { @SuppressLint("ApplySharedPref") fun resetSharedPrefs() { - globalEncryptedSharedPreferencesInstance.edit().clear().commit() + globalEncryptedSharedPreferencesInstance.clearAndNotify() } private fun getStoredDbPassword(): ByteArray? = 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 03b2b1f7a0f2b3c5313198d83369a2a978d274c4..469ac6b4b49c3c138f8703f8e2d5db12bedf9726 100644 --- a/Corona-Warn-App/src/main/res/values-bg/strings.xml +++ b/Corona-Warn-App/src/main/res/values-bg/strings.xml @@ -20,8 +20,6 @@ <!-- NOTR --> <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string> <!-- NOTR --> - <string name="preference_timestamp_diagnosis_keys_fetch"><xliff:g id="preference">"preference_timestamp_diagnosis_keys_fetch"</xliff:g></string> - <!-- NOTR --> <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string> <!-- NOTR --> <string name="preference_background_job_allowed"><xliff:g id="preference">"preference_background_job_enabled"</xliff:g></string> 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 f8eaa6a2e06e2b1893ce39c6db4ba5b014fb3e53..0d7bf64ba7a61a27cdc2087dc10ef61deb287d8a 100644 --- a/Corona-Warn-App/src/main/res/values-de/strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/strings.xml @@ -21,8 +21,6 @@ <!-- NOTR --> <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string> <!-- NOTR --> - <string name="preference_timestamp_diagnosis_keys_fetch"><xliff:g id="preference">"preference_timestamp_diagnosis_keys_fetch"</xliff:g></string> - <!-- NOTR --> <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string> <!-- NOTR --> <string name="preference_background_job_allowed"><xliff:g id="preference">"preference_background_job_enabled"</xliff:g></string> 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 6b9d4ca42f8c7a9b242d2e1f1862b7caa903e1df..a5e01cdeff99cac3ee50b5509b42354aebefa547 100644 --- a/Corona-Warn-App/src/main/res/values-en/strings.xml +++ b/Corona-Warn-App/src/main/res/values-en/strings.xml @@ -20,8 +20,6 @@ <!-- NOTR --> <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string> <!-- NOTR --> - <string name="preference_timestamp_diagnosis_keys_fetch"><xliff:g id="preference">"preference_timestamp_diagnosis_keys_fetch"</xliff:g></string> - <!-- NOTR --> <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string> <!-- NOTR --> <string name="preference_background_job_allowed"><xliff:g id="preference">"preference_background_job_enabled"</xliff:g></string> 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 e6583c9af191c2f552c6c04953312988958f0e7f..eded35c4be1a262535dce655302b0fba532e50e5 100644 --- a/Corona-Warn-App/src/main/res/values-pl/strings.xml +++ b/Corona-Warn-App/src/main/res/values-pl/strings.xml @@ -20,8 +20,6 @@ <!-- NOTR --> <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string> <!-- NOTR --> - <string name="preference_timestamp_diagnosis_keys_fetch"><xliff:g id="preference">"preference_timestamp_diagnosis_keys_fetch"</xliff:g></string> - <!-- NOTR --> <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string> <!-- NOTR --> <string name="preference_background_job_allowed"><xliff:g id="preference">"preference_background_job_enabled"</xliff:g></string> 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 3bcca1384b7d4d00442d9525c768e0273cbdac85..0c5a9e4f4e0e8f0252b4a82e4df7ddcaa07dac65 100644 --- a/Corona-Warn-App/src/main/res/values-ro/strings.xml +++ b/Corona-Warn-App/src/main/res/values-ro/strings.xml @@ -20,8 +20,6 @@ <!-- NOTR --> <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string> <!-- NOTR --> - <string name="preference_timestamp_diagnosis_keys_fetch"><xliff:g id="preference">"preference_timestamp_diagnosis_keys_fetch"</xliff:g></string> - <!-- NOTR --> <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string> <!-- NOTR --> <string name="preference_background_job_allowed"><xliff:g id="preference">"preference_background_job_enabled"</xliff:g></string> 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 2af4f639b65779e8db88d69aec94612aa733ebb8..78dc5a455f852fb5ba62c532be47921025386790 100644 --- a/Corona-Warn-App/src/main/res/values-tr/strings.xml +++ b/Corona-Warn-App/src/main/res/values-tr/strings.xml @@ -20,8 +20,6 @@ <!-- NOTR --> <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string> <!-- NOTR --> - <string name="preference_timestamp_diagnosis_keys_fetch"><xliff:g id="preference">"preference_timestamp_diagnosis_keys_fetch"</xliff:g></string> - <!-- NOTR --> <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string> <!-- NOTR --> <string name="preference_background_job_allowed"><xliff:g id="preference">"preference_background_job_enabled"</xliff:g></string> diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml index b76608adbad8e9fdfeec178b7849432f9c1ab914..5fe660c6b3eb46767911671628ad782883f3125f 100644 --- a/Corona-Warn-App/src/main/res/values/strings.xml +++ b/Corona-Warn-App/src/main/res/values/strings.xml @@ -21,8 +21,6 @@ <!-- NOTR --> <string name="preference_tracing"><xliff:g id="preference">"preference_tracing"</xliff:g></string> <!-- NOTR --> - <string name="preference_timestamp_diagnosis_keys_fetch"><xliff:g id="preference">"preference_timestamp_diagnosis_keys_fetch"</xliff:g></string> - <!-- NOTR --> <string name="preference_timestamp_manual_diagnosis_keys_retrieval"><xliff:g id="preference">"preference_timestamp_manual_diagnosis_keys_retrieval"</xliff:g></string> <!-- NOTR --> <string name="preference_background_job_allowed"><xliff:g id="preference">"preference_background_job_enabled"</xliff:g></string> diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/HourPackageSyncToolTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/HourPackageSyncToolTest.kt index 062d1bfb4c1fbf45e9fb29d274fbd97c0c7ee93a..f6dae8e55b255f6e8cb3d71bd3c8a7577cb88466 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/HourPackageSyncToolTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/diagnosiskeys/download/HourPackageSyncToolTest.kt @@ -204,6 +204,20 @@ class HourPackageSyncToolTest : CommonSyncToolTest() { instance.expectNewHourPackages(listOf(cachedKey1, cachedKey2), now) shouldBe true } + @Test + fun `EXPECT_NEW_HOUR_PACKAGES does not get confused by same hour on next day`() = runBlockingTest { + val cachedKey1 = mockk<CachedKey>().apply { + every { info } returns mockk<CachedKeyInfo>().apply { + every { toDateTime() } returns Instant.parse("2020-01-01T00:00:03.000Z").toDateTime(DateTimeZone.UTC) + } + } + + val instance = createInstance() + + val now = Instant.parse("2020-01-02T01:00:03.000Z") + instance.expectNewHourPackages(listOf(cachedKey1), now) shouldBe true + } + @Test fun `if keys were revoked skip the EXPECT packages check`() = runBlockingTest { every { timeStamper.nowUTC } returns Instant.parse("2020-01-04T02:00:00.000Z") diff --git a/Corona-Warn-App/src/test/java/testhelpers/preferences/MockFlowPreference.kt b/Corona-Warn-App/src/test/java/testhelpers/preferences/MockFlowPreference.kt index 33d46578e1a956c645d549edc3f793d2fc9b27df..0b855e1b9938ed9d47650a26c85ba5bbe9ba4927 100644 --- a/Corona-Warn-App/src/test/java/testhelpers/preferences/MockFlowPreference.kt +++ b/Corona-Warn-App/src/test/java/testhelpers/preferences/MockFlowPreference.kt @@ -16,5 +16,6 @@ fun <T> mockFlowPreference( val updateCall = arg<(T) -> T>(0) flow.value = updateCall(flow.value) } + return instance } diff --git a/Corona-Warn-App/src/test/java/testhelpers/preferences/MockSharedPreferences.kt b/Corona-Warn-App/src/test/java/testhelpers/preferences/MockSharedPreferences.kt index a6294b00f54bcdbc96ab6bd18195389fc1a79e51..c094e560e5401f80bbf7bedff36af3537cc8a67e 100644 --- a/Corona-Warn-App/src/test/java/testhelpers/preferences/MockSharedPreferences.kt +++ b/Corona-Warn-App/src/test/java/testhelpers/preferences/MockSharedPreferences.kt @@ -3,6 +3,7 @@ package testhelpers.preferences import android.content.SharedPreferences class MockSharedPreferences : SharedPreferences { + private val listeners = mutableListOf<SharedPreferences.OnSharedPreferenceChangeListener>() private val dataMap = mutableMapOf<String, Any>() val dataMapPeek: Map<String, Any> get() = dataMap.toMap() @@ -36,12 +37,12 @@ class MockSharedPreferences : SharedPreferences { dataMap.putAll(newData) } - override fun registerOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener?) { - throw NotImplementedError() + override fun registerOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) { + listeners.add(listener) } - override fun unregisterOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener?) { - throw NotImplementedError() + override fun unregisterOnSharedPreferenceChangeListener(listener: SharedPreferences.OnSharedPreferenceChangeListener) { + listeners.remove(listener) } private fun createEditor( diff --git a/gradle.properties b/gradle.properties index 3802281e4f1879b6ddca5ff34f9f5b3376baaee3..2974345801f04919bc39c70e43305c810b323c9e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,4 +20,4 @@ org.gradle.dependency.verification.console=verbose VERSION_MAJOR=1 VERSION_MINOR=8 VERSION_PATCH=0 -VERSION_BUILD=7 +VERSION_BUILD=1