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 7735bc4ced327496573f3297d5d3bf0e4941ba73..c6c6bba9de200e336b15b2a8022d1cd54cff6ef7 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 @@ -585,13 +585,4 @@ object LocalData { ****************************************************/ fun getSharedPreferenceInstance(): SharedPreferences = globalEncryptedSharedPreferencesInstance - - fun getBackgroundWorkRelatedPreferences() = listOf( - CoronaWarnApplication.getAppContext().getString(R.string.preference_background_job_allowed), - CoronaWarnApplication.getAppContext().getString(R.string.preference_mobile_data_allowed) - ) - - fun getLastFetchDatePreference() = - CoronaWarnApplication.getAppContext() - .getString(R.string.preference_timestamp_diagnosis_keys_fetch) } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt index 918f0ad3a4b6525feede3c0d278cbb39952fe9ed..308385ca1c5f3ca5275e9b74ba9db20c9c99b2bc 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/storage/SettingsRepository.kt @@ -24,7 +24,6 @@ object SettingsRepository { val isManualKeyRetrievalEnabled = MutableLiveData(true) val isConnectionEnabled = MutableLiveData(true) val isBluetoothEnabled = MutableLiveData(true) - val isMobileDataEnabled = MutableLiveData(true) val isBackgroundJobEnabled = MutableLiveData(true) // TODO should go to a formatter @@ -97,40 +96,11 @@ object SettingsRepository { } /** - * Toggle mobile data in shared preferences and refresh it afterwards. - * - * @see LocalData - */ - fun toggleMobileDataEnabled() { - LocalData.toggleMobileDataEnabled() - refreshMobileDataEnabled() - } - - /** - * Refresh mobile data with the current shared preferences state. - * - * @see LocalData - */ - fun refreshMobileDataEnabled() { - isMobileDataEnabled.value = LocalData.isMobileDataEnabled() - } - - /** - * Toggle background job in shared preferences and refresh it afterwards. - * - * @see LocalData - */ - fun toggleBackgroundJobEnabled() { - LocalData.toggleBackgroundJobEnabled() - refreshBackgroundJobEnabled() - } - - /** - * Refresh background job with the current shared preferences state. + * Refresh global bluetooth state to point out that tracing isn't working * - * @see LocalData + * @see ConnectivityHelper */ - fun refreshBackgroundJobEnabled() { - isBackgroundJobEnabled.value = LocalData.isBackgroundJobEnabled() + fun updateBackgroundJobEnabled(value: Boolean) { + isBackgroundJobEnabled.postValue(value) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt index 09135325489850b11231aec6aaed146d1447f934..1d03c732ac9f6b026c4635b1d90b9a778c66d6aa 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivity.kt @@ -2,6 +2,7 @@ package de.rki.coronawarnapp.ui.main import android.content.Intent import android.os.Bundle +import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager @@ -55,10 +56,6 @@ class MainActivity : AppCompatActivity() { } } - init { - scheduleWork() - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) @@ -66,12 +63,15 @@ class MainActivity : AppCompatActivity() { } /** - * Register network and bluetooth callback. + * Register network, bluetooth and data saver callback. */ override fun onResume() { super.onResume() ConnectivityHelper.registerNetworkStatusCallback(this, callbackNetwork) ConnectivityHelper.registerBluetoothStatusCallback(this, callbackBluetooth) + Log.d(TAG, "Background work is available: ${!ConnectivityHelper.isDataSaverEnabled(this)}") + settingsViewModel.updateBackgroundJobEnabled(!ConnectivityHelper.isDataSaverEnabled(this)) + scheduleWork() showDialogWithStacktraceIfPreviouslyCrashed() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainFragment.kt index 53404e0f9d1bfb0a53ca7ee0188e94699adf4c90..3634469bef86a8e221bf079ddb0826aa109edc7e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainFragment.kt @@ -72,7 +72,6 @@ class MainFragment : BaseFragment() { tracingViewModel.refreshLastTimeDiagnosisKeysFetchedDate() tracingViewModel.refreshIsTracingEnabled() tracingViewModel.refreshActiveTracingDaysInRetentionPeriod() - settingsViewModel.refreshBackgroundJobEnabled() TimerHelper.checkManualKeyRetrievalTimer() submissionViewModel.refreshDeviceUIState() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/riskdetails/RiskDetailsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/riskdetails/RiskDetailsFragment.kt index 13e9e6564aee8e45f3758bb32e2c5e4a0b2056dc..893a95287d2e233ea1705fff63b2be362e0ddaca 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/riskdetails/RiskDetailsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/riskdetails/RiskDetailsFragment.kt @@ -57,7 +57,6 @@ class RiskDetailsFragment : BaseFragment() { tracingViewModel.refreshRiskLevel() tracingViewModel.refreshExposureSummary() tracingViewModel.refreshLastTimeDiagnosisKeysFetchedDate() - settingsViewModel.refreshBackgroundJobEnabled() TimerHelper.checkManualKeyRetrievalTimer() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt index 55f10e0461720bb023f0518023bc4f6a7a8237c8..f7aab9c197b6a7b57fe0ea6e1d0f1e2f3598d6da 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsFragment.kt @@ -57,8 +57,6 @@ class SettingsFragment : BaseFragment() { settingsViewModel.refreshNotificationsEnabled(requireContext()) settingsViewModel.refreshNotificationsRiskEnabled() settingsViewModel.refreshNotificationsTestEnabled() - settingsViewModel.refreshMobileDataEnabled() - settingsViewModel.refreshBackgroundJobEnabled() } private fun setButtonOnClickListener() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt index 7a4f6cbc0c4fbe736bbc53e695dee92e08e33d4c..382d34f0557875ca0ecdc281d5c96a6059c793cc 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/settings/SettingsTracingFragment.kt @@ -81,8 +81,7 @@ class SettingsTracingFragment : BaseFragment(), override fun onStartPermissionGranted() { tracingViewModel.refreshIsTracingEnabled() - // TODO - BackgroundWorkScheduler.checkStart() + BackgroundWorkScheduler.startWorkScheduler() Toast.makeText(requireContext(), "Tracing started successfully", Toast.LENGTH_SHORT).show() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt index ada13e7039f1c0c47b42c17a178232cc0437ed2e..05809e74ce9dffcc402dc2ab24cad6c391a51459 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/viewmodel/SettingsViewModel.kt @@ -22,10 +22,6 @@ class SettingsViewModel : ViewModel() { val isBluetoothEnabled: LiveData<Boolean> = SettingsRepository.isBluetoothEnabled - // Todo bind to os settings, change to general network availability, cannot be set within the app - // Will impact UI if no network connection is found, persistent storing is not necessary - val isMobileDataEnabled: LiveData<Boolean> = SettingsRepository.isMobileDataEnabled - // Todo bind to os settings, care API 23 / API 24 onwards // Will impact UI if background activity is not permitted, persistent storing is not necessary val isBackgroundJobEnabled: LiveData<Boolean> = SettingsRepository.isBackgroundJobEnabled @@ -102,24 +98,11 @@ class SettingsViewModel : ViewModel() { } /** - * Refresh & toggle mobile data enabled - */ - fun refreshMobileDataEnabled() { - SettingsRepository.refreshMobileDataEnabled() - } - - fun toggleMobileDataEnabled() { - SettingsRepository.toggleMobileDataEnabled() - } - - /** - * Refresh & toggle background job enabled + * Update background job enabled + * + * @param value */ - fun refreshBackgroundJobEnabled() { - SettingsRepository.refreshBackgroundJobEnabled() - } - - fun toggleBackgroundJobEnabled() { - SettingsRepository.toggleBackgroundJobEnabled() + fun updateBackgroundJobEnabled(value: Boolean) { + SettingsRepository.updateBackgroundJobEnabled(value) } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt index 6118ea66109abe08a796a35d718f7c2cddbfc722..457de57a667cafdba40b88c47c899fa93bbaf9fe 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ConnectivityHelper.kt @@ -9,6 +9,7 @@ import android.net.ConnectivityManager import android.net.Network import android.net.NetworkCapabilities import android.net.NetworkRequest +import android.os.Build import android.util.Log import de.rki.coronawarnapp.exception.ExceptionCategory import de.rki.coronawarnapp.exception.report @@ -120,6 +121,23 @@ object ConnectivityHelper { } } + /** + * For API level 24+ check if data saver is enabled + * Else always return false + * + * @param context the context + * + * @return Boolean + * + * @see ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED + */ + fun isDataSaverEnabled(context: Context): Boolean { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager + connectivityManager.restrictBackgroundStatus != ConnectivityManager.RESTRICT_BACKGROUND_STATUS_DISABLED + } else false + } + /** * Get bluetooth enabled status. * diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterRiskHelper.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterRiskHelper.kt index 29adcd8d9e2e4ed8db1cb1a0dfaff924928f30a4..2b26669bfa76401e1dd1077238d59bb459a728a1 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterRiskHelper.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/formatter/FormatterRiskHelper.kt @@ -255,8 +255,7 @@ fun formatTimeFetched( */ fun formatNextUpdate( riskLevelScore: Int?, - isBackgroundJobEnabled: Boolean?, - nextUpdate: Date + isBackgroundJobEnabled: Boolean? ): String { val appContext = CoronaWarnApplication.getAppContext() return if (isBackgroundJobEnabled != true) { @@ -266,9 +265,7 @@ fun formatNextUpdate( RiskLevelConstants.UNKNOWN_RISK_INITIAL, RiskLevelConstants.LOW_LEVEL_RISK, RiskLevelConstants.INCREASED_RISK -> appContext.getString( - R.string.risk_card_body_next_update, - DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM) - .format(nextUpdate) + R.string.risk_card_body_next_update ) else -> "" } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundConstants.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundConstants.kt index 3c5c8eb804a04274fab523463dd4bf4a34f1e989..a36174aeac4bc1859222d0ef21d03b368550d8c5 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundConstants.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundConstants.kt @@ -38,7 +38,7 @@ object BackgroundConstants { * Total tries count for diagnosis key retrieval per day * Internal requirement */ - const val DIAGNOSIS_KEY_RETRIEVAL_TRIES_PER_DAY = 12 + const val DIAGNOSIS_KEY_RETRIEVAL_TRIES_PER_DAY = 1 /** * Maximum tries count for diagnosis key retrieval per day @@ -84,4 +84,9 @@ object BackgroundConstants { * @see TimeUnit.MINUTES */ const val TIME_RANGE_MAX = 1439 + + /** + * Retries before work would set as FAILED + */ + const val WORKER_RETRY_COUNT_THRESHOLD = 3 } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkScheduler.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkScheduler.kt index 88f2db0be3ef6b5ddc7ff61fa38616dceb9cbc46..a40cef82d73a7e947f7c26f856833b27899b6a3f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkScheduler.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/BackgroundWorkScheduler.kt @@ -1,7 +1,7 @@ package de.rki.coronawarnapp.worker -import android.content.SharedPreferences.OnSharedPreferenceChangeListener import android.util.Log +import androidx.work.BackoffPolicy import androidx.work.Constraints import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.ExistingWorkPolicy @@ -9,14 +9,14 @@ import androidx.work.NetworkType import androidx.work.OneTimeWorkRequestBuilder import androidx.work.Operation import androidx.work.PeriodicWorkRequestBuilder +import androidx.work.WorkInfo import androidx.work.WorkManager import de.rki.coronawarnapp.BuildConfig import de.rki.coronawarnapp.CoronaWarnApplication -import de.rki.coronawarnapp.storage.LocalData -import de.rki.coronawarnapp.storage.TracingRepository import org.joda.time.DateTime import org.joda.time.DateTimeZone import org.joda.time.Instant +import java.util.concurrent.ExecutionException import java.util.concurrent.TimeUnit /** @@ -78,11 +78,6 @@ object BackgroundWorkScheduler { BackgroundConstants.DIAGNOSIS_KEY_RETRIEVAL_TRIES_PER_DAY .coerceAtMost(BackgroundConstants.GOOGLE_API_MAX_CALLS_PER_DAY) - /** - * Shared preferences listener - */ - private var sharedPrefListener: OnSharedPreferenceChangeListener? = null - /** * Work manager instance */ @@ -90,27 +85,44 @@ object BackgroundWorkScheduler { /** * Start work scheduler - * Subscribe shared preferences listener for changes. If any changes regarding background work - * occurred, then reschedule periodic work or stop it (depends on changes occurred). - * Two keys are monitored: - * - preference_background_jonboarding_allowed - * - preference_mobile_data_allowed - * @see LocalData.getBackgroundWorkRelatedPreferences() + * Checks if periodic worker was already scheduled. If not - reschedule it again. + * + * @see isWorkActive */ fun startWorkScheduler() { - sharedPrefListener = OnSharedPreferenceChangeListener { _, key -> - if (LocalData.getBackgroundWorkRelatedPreferences().contains(key)) { - logSharedPreferencesChange(key) - checkStart() - } else if (key == LocalData.getLastFetchDatePreference()) { - TracingRepository.refreshLastTimeDiagnosisKeysFetchedDate() + val isPeriodicWorkActive = isWorkActive(WorkTag.DIAGNOSIS_KEY_RETRIEVAL_PERIODIC_WORKER.tag) + logWorkActiveStatus(WorkTag.DIAGNOSIS_KEY_RETRIEVAL_PERIODIC_WORKER.tag, isPeriodicWorkActive) + if (!isPeriodicWorkActive) WorkType.DIAGNOSIS_KEY_BACKGROUND_PERIODIC_WORK.start() + } + + /** + * Checks if defined work is active + * Non-active means worker was Cancelled, Failed or have not been enqueued at all + * + * @param tag String tag of the worker + * + * @return Boolean + * + * @see WorkInfo.State.CANCELLED + * @see WorkInfo.State.FAILED + */ + private fun isWorkActive(tag: String): Boolean { + val workStatus = workManager.getWorkInfosByTag(tag) + var result = true + try { + val workInfoList = workStatus.get() + if (workInfoList.size == 0) result = false + for (info in workInfoList) { + if (info.state == WorkInfo.State.CANCELLED || info.state == WorkInfo.State.FAILED) { + result = false + } } + } catch (e: ExecutionException) { + result = false + } catch (e: InterruptedException) { + result = false } - LocalData.getSharedPreferenceInstance().registerOnSharedPreferenceChangeListener( - sharedPrefListener - ) - // TODO: Reimplement after clarifications - WorkType.DIAGNOSIS_KEY_BACKGROUND_PERIODIC_WORK.start() + return result } /** @@ -125,31 +137,21 @@ object BackgroundWorkScheduler { } /** - * Check start periodic work - * If background work is enabled, than reschedule it. else - stop it. + * Schedule diagnosis key one time work * - * @see LocalData.isBackgroundJobEnabled() - * @see WorkType.DIAGNOSIS_KEY_BACKGROUND_PERIODIC_WORK + * @see WorkType.DIAGNOSIS_KEY_BACKGROUND_ONE_TIME_WORK */ - fun checkStart() { - if (LocalData.isBackgroundJobEnabled()) { - WorkType.DIAGNOSIS_KEY_BACKGROUND_ONE_TIME_WORK.stop() - WorkType.DIAGNOSIS_KEY_BACKGROUND_PERIODIC_WORK.start() - } else { - stopWorkScheduler() - } + fun scheduleDiagnosisKeyPeriodicWork() { + WorkType.DIAGNOSIS_KEY_BACKGROUND_PERIODIC_WORK.start() } /** * Schedule diagnosis key one time work * - * @see LocalData.isBackgroundJobEnabled() * @see WorkType.DIAGNOSIS_KEY_BACKGROUND_ONE_TIME_WORK */ fun scheduleDiagnosisKeyOneTimeWork() { - if (LocalData.isBackgroundJobEnabled()) { - WorkType.DIAGNOSIS_KEY_BACKGROUND_ONE_TIME_WORK.start() - } + WorkType.DIAGNOSIS_KEY_BACKGROUND_ONE_TIME_WORK.start() } /** @@ -164,15 +166,6 @@ object BackgroundWorkScheduler { WorkType.DIAGNOSIS_KEY_BACKGROUND_ONE_TIME_WORK -> enqueueDiagnosisKeyBackgroundOneTimeWork() } - /** - * Stop work by unique name - * - * @return Operation - * - * @see WorkType - */ - private fun WorkType.stop(): Operation = workManager.cancelUniqueWork(this.uniqueName) - /** * Enqueue diagnosis key periodic work and log it * Replace with new if older work exists. @@ -204,11 +197,13 @@ object BackgroundWorkScheduler { /** * Build diagnosis key periodic work request * Set "kind delay" for accessibility reason. + * Backoff criteria set to Linear type. * * @return PeriodicWorkRequest * * @see WorkTag.DIAGNOSIS_KEY_RETRIEVAL_PERIODIC_WORKER * @see BackgroundConstants.DIAGNOSIS_KEY_PERIODIC_KIND_DELAY + * @see BackoffPolicy.LINEAR */ private fun buildDiagnosisKeyRetrievalPeriodicWork() = PeriodicWorkRequestBuilder<DiagnosisKeyRetrievalPeriodicWorker>( @@ -220,16 +215,24 @@ object BackgroundWorkScheduler { BackgroundConstants.DIAGNOSIS_KEY_PERIODIC_KIND_DELAY, TimeUnit.MINUTES ) + .setBackoffCriteria( + BackoffPolicy.LINEAR, + BackgroundConstants.DIAGNOSIS_KEY_PERIODIC_KIND_DELAY, + TimeUnit.MINUTES + ) .build() /** * Build diagnosis key one time work request * Set random initial delay for security reason. + * Backoff criteria set to Linear type. * * @return OneTimeWorkRequest * * @see WorkTag.DIAGNOSIS_KEY_RETRIEVAL_ONE_TIME_WORKER * @see buildDiagnosisKeyRetrievalOneTimeWork + * @see BackgroundConstants.DIAGNOSIS_KEY_PERIODIC_KIND_DELAY + * @see BackoffPolicy.LINEAR */ private fun buildDiagnosisKeyRetrievalOneTimeWork() = OneTimeWorkRequestBuilder<DiagnosisKeyRetrievalOneTimeWorker>() @@ -243,6 +246,11 @@ object BackgroundWorkScheduler { ) ), TimeUnit.MINUTES ) + .setBackoffCriteria( + BackoffPolicy.LINEAR, + BackgroundConstants.DIAGNOSIS_KEY_PERIODIC_KIND_DELAY, + TimeUnit.MINUTES + ) .build() /** @@ -256,29 +264,19 @@ object BackgroundWorkScheduler { /** * Constraints for diagnosis key one time work - * Depends on current application settings. + * Requires battery not low and any network connection + * Mobile data usage is handled on OS level in application settings * * @return Constraints * - * @see LocalData.isMobileDataEnabled() + * @see NetworkType.CONNECTED */ - private fun getConstraintsForDiagnosisKeyOneTimeBackgroundWork(): Constraints { - val builder = Constraints.Builder() - if (LocalData.isMobileDataEnabled()) { - if (BuildConfig.DEBUG) Log.d( - TAG, "${WorkType.DIAGNOSIS_KEY_BACKGROUND_ONE_TIME_WORK}:" + - "$BackgroundConstants.NETWORK_ROAMING_ALLOWED" - ) - builder.setRequiredNetworkType(NetworkType.CONNECTED) - } else { - if (BuildConfig.DEBUG) Log.d( - TAG, "${WorkType.DIAGNOSIS_KEY_BACKGROUND_ONE_TIME_WORK}:" + - "$BackgroundConstants.NETWORK_ROAMING_FORBIDDEN" - ) - builder.setRequiredNetworkType(NetworkType.NOT_ROAMING) - } - return builder.build() - } + private fun getConstraintsForDiagnosisKeyOneTimeBackgroundWork() = + Constraints + .Builder() + .setRequiresBatteryNotLow(true) + .setRequiredNetworkType(NetworkType.CONNECTED) + .build() /** * Log operation schedule @@ -296,9 +294,9 @@ object BackgroundWorkScheduler { .also { if (BuildConfig.DEBUG) Log.d(TAG, "Canceling all work with tag ${workTag.tag}") } /** - * Log shared preferences change + * Log work active status */ - private fun logSharedPreferencesChange(key: String) { - if (BuildConfig.DEBUG) Log.d(TAG, "Shared preferences was changed in key: $key") + private fun logWorkActiveStatus(tag: String, active: Boolean) { + if (BuildConfig.DEBUG) Log.d(TAG, "Work type $tag is active: $active") } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisKeyRetrievalOneTimeWorker.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisKeyRetrievalOneTimeWorker.kt index 777edc0c31bb55699c69bb18030e81bb34c885d3..5f31a256bc8fa2aaad3a24e006fae54ab172f677 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisKeyRetrievalOneTimeWorker.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisKeyRetrievalOneTimeWorker.kt @@ -5,8 +5,6 @@ import android.util.Log import androidx.work.CoroutineWorker import androidx.work.WorkerParameters import de.rki.coronawarnapp.BuildConfig -import de.rki.coronawarnapp.exception.ExceptionCategory -import de.rki.coronawarnapp.exception.report import de.rki.coronawarnapp.transaction.RetrieveDiagnosisKeysTransaction /** @@ -30,13 +28,18 @@ class DiagnosisKeyRetrievalOneTimeWorker(val context: Context, workerParams: Wor * @see RetrieveDiagnosisKeysTransaction */ override suspend fun doWork(): Result { - if (BuildConfig.DEBUG) Log.d(TAG, "Background job started...") + if (BuildConfig.DEBUG) Log.d(TAG, "Background job started. Run attempt: $runAttemptCount") + + if (runAttemptCount > BackgroundConstants.WORKER_RETRY_COUNT_THRESHOLD) { + if (BuildConfig.DEBUG) Log.d(TAG, "Background job failed after $runAttemptCount attempts. Rescheduling") + return Result.failure() + } + var result = Result.success() try { RetrieveDiagnosisKeysTransaction.start() } catch (e: Exception) { - e.report(ExceptionCategory.JOB) - return Result.failure() + result = Result.retry() } - return Result.success() + return result } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisKeyRetrievalPeriodicWorker.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisKeyRetrievalPeriodicWorker.kt index 1caccef0b738e4d9f446aee9fa6f02890ca07da3..f7d7eee4f2f243a70ea5d494c5d73c9cbc0f219c 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisKeyRetrievalPeriodicWorker.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/worker/DiagnosisKeyRetrievalPeriodicWorker.kt @@ -5,8 +5,6 @@ import android.util.Log import androidx.work.CoroutineWorker import androidx.work.WorkerParameters import de.rki.coronawarnapp.BuildConfig -import de.rki.coronawarnapp.exception.ExceptionCategory -import de.rki.coronawarnapp.exception.report /** * Periodic diagnosis key retrieval work @@ -27,16 +25,23 @@ class DiagnosisKeyRetrievalPeriodicWorker(val context: Context, workerParams: Wo * * @return Result * + * @see BackgroundWorkScheduler.scheduleDiagnosisKeyPeriodicWork() * @see BackgroundWorkScheduler.scheduleDiagnosisKeyOneTimeWork() */ override suspend fun doWork(): Result { - if (BuildConfig.DEBUG) Log.d(TAG, "Background job started...") + if (BuildConfig.DEBUG) Log.d(TAG, "Background job started. Run attempt: $runAttemptCount") + + if (runAttemptCount > BackgroundConstants.WORKER_RETRY_COUNT_THRESHOLD) { + if (BuildConfig.DEBUG) Log.d(TAG, "Background job failed after $runAttemptCount attempts. Rescheduling") + BackgroundWorkScheduler.scheduleDiagnosisKeyPeriodicWork() + return Result.failure() + } + var result = Result.success() try { BackgroundWorkScheduler.scheduleDiagnosisKeyOneTimeWork() } catch (e: Exception) { - e.report(ExceptionCategory.JOB) - return Result.failure() + result = Result.retry() } - return Result.success() + return result } } diff --git a/Corona-Warn-App/src/main/res/layout/include_risk_card.xml b/Corona-Warn-App/src/main/res/layout/include_risk_card.xml index 31f9e683f4138334cdf9c095506b33625c74c4d4..6c7e4acf01323c113ae031e718140b69ca1e743b 100644 --- a/Corona-Warn-App/src/main/res/layout/include_risk_card.xml +++ b/Corona-Warn-App/src/main/res/layout/include_risk_card.xml @@ -209,7 +209,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_normal" - android:visibility="@{FormatterHelper.formatVisibilityText(FormatterRiskHelper.formatNextUpdate(tracingViewModel.riskLevel, settingsViewModel.isBackgroundJobEnabled(), tracingViewModel.nextUpdate))}" + android:visibility="@{FormatterHelper.formatVisibilityText(FormatterRiskHelper.formatNextUpdate(tracingViewModel.riskLevel, settingsViewModel.isBackgroundJobEnabled()))}" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/risk_card_row_time_fetched"> @@ -227,7 +227,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_small" - android:text="@{FormatterRiskHelper.formatNextUpdate(tracingViewModel.riskLevel, settingsViewModel.isBackgroundJobEnabled(), tracingViewModel.nextUpdate)}" + android:text="@{FormatterRiskHelper.formatNextUpdate(tracingViewModel.riskLevel, settingsViewModel.isBackgroundJobEnabled())}" android:textColor="@{FormatterRiskHelper.formatStableTextColor(tracingViewModel.riskLevel)}" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" diff --git a/Corona-Warn-App/src/main/res/values/strings.xml b/Corona-Warn-App/src/main/res/values/strings.xml index 6f3c230cc69bf6845d91b49df6a35dff5de74df8..15c559b77e70a80004c808fbb2f16b80ce971f73 100644 --- a/Corona-Warn-App/src/main/res/values/strings.xml +++ b/Corona-Warn-App/src/main/res/values/strings.xml @@ -164,7 +164,7 @@ <string name="risk_card_body_saved_days">%1$s von 14 Tagen aktiv</string> <string name="risk_card_body_not_yet_fetched">Kontakte wurden noch nicht überprüft.</string> <string name="risk_card_body_time_fetched">Aktualisiert: %1$s</string> - <string name="risk_card_body_next_update">Nächste Aktualisierung in: %1$s</string> + <string name="risk_card_body_next_update">Tägliche Aktualisierung</string> <!-- XBUT: risk card - update risk --> <string name="risk_card_button_update">Aktualisieren</string> <string name="risk_card_button_cooldown">Aktualisierung in %1$s</string>