Skip to content
This repository has been archived by the owner on Jun 20, 2023. It is now read-only.

Better handling of unexpected supportedCountryData from the server (DEV) #1301

Merged
merged 3 commits into from
Oct 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ class AppConfigProvider @Inject constructor(
}

return newConfigParsed?.also {
Timber.v("Saving new valid config.")
Timber.d("Saving new valid config.")
Timber.v("New Config.supportedCountries: %s", it.supportedCountriesList)
configStorage.appConfigRaw = newConfigRaw
}
}
Expand All @@ -99,12 +100,32 @@ class AppConfigProvider @Inject constructor(
Timber.w("No new config available, using last valid.")
getFallback()
}
}.performSanityChecks()

private fun ApplicationConfiguration.performSanityChecks(): ApplicationConfiguration {
var sanityChecked = this

if (sanityChecked.supportedCountriesList == null) {
sanityChecked = sanityChecked.toNewConfig {
clearSupportedCountries()
addAllSupportedCountries(emptyList<String>())
}
}

val countryCheck = sanityChecked.supportedCountriesList
if (countryCheck.size == 1 && !VALID_CC.matches(countryCheck.single())) {
Timber.w("Invalid country data, clearing. (%s)", this.supportedCountriesList)
sanityChecked = sanityChecked.toNewConfig {
clearSupportedCountries()
}
}
return sanityChecked
}

companion object {
private val TAG = AppConfigProvider::class.java.simpleName

private val VALID_CC = "^([A-Z]{2,3})$".toRegex()
private const val EXPORT_BINARY_FILE_NAME = "export.bin"
private const val EXPORT_SIGNATURE_FILE_NAME = "export.sig"
private val TAG = AppConfigProvider::class.java.simpleName
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,11 @@ package de.rki.coronawarnapp.service.applicationconfiguration

import com.google.android.gms.nearby.exposurenotification.ExposureConfiguration
import de.rki.coronawarnapp.server.protocols.ApplicationConfigurationOuterClass.ApplicationConfiguration
import de.rki.coronawarnapp.util.CWADebug
import de.rki.coronawarnapp.util.di.AppInjector

object ApplicationConfigurationService {
suspend fun asyncRetrieveApplicationConfiguration(): ApplicationConfiguration {
return AppInjector.component.appConfigProvider.getAppConfig().let {
if (CWADebug.isDebugBuildOrMode) {
// TODO: THIS IS A MOCK -> Remove after Backend is providing this information.
it.toBuilder()
.clearSupportedCountries()
.addAllSupportedCountries(
listOf(
"DE", "UK", "FR", "IT", "ES", "PL", "RO", "NL",
"BE", "CZ", "SE", "PT", "HU", "AT", "CH", "BG", "DK", "FI", "SK",
"NO", "IE", "HR", "SI", "LT", "LV", "EE", "CY", "LU", "MT", "IS"
)
)
.build()
} else {
it
}
}
return AppInjector.component.appConfigProvider.getAppConfig()
}

suspend fun asyncRetrieveExposureConfiguration(): ExposureConfiguration =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@ package de.rki.coronawarnapp.storage.interoperability
import android.text.TextUtils
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Transformations
import de.rki.coronawarnapp.service.applicationconfiguration.ApplicationConfigurationService
import de.rki.coronawarnapp.appconfig.AppConfigProvider
import de.rki.coronawarnapp.storage.LocalData
import de.rki.coronawarnapp.ui.Country
import kotlinx.coroutines.runBlocking
import timber.log.Timber
import java.util.Locale
import javax.inject.Inject
import javax.inject.Singleton

@Singleton
class InteroperabilityRepository @Inject constructor() {
class InteroperabilityRepository @Inject constructor(
private val appConfigProvider: AppConfigProvider
) {

fun saveInteroperabilityUsed() {
LocalData.isInteroperabilityShownAtLeastOnce = true
}

private val _countryList: MutableLiveData<List<String>> = MutableLiveData(listOf())
private val _countryList: MutableLiveData<List<Country>> = MutableLiveData(listOf())
val countryList = Transformations.distinctUntilChanged(_countryList)

init {
Expand All @@ -29,14 +32,18 @@ class InteroperabilityRepository @Inject constructor() {
* Gets all countries from @see ApplicationConfigurationService.asyncRetrieveApplicationConfiguration
* Also changes every country code to lower case
*/

fun getAllCountries() {
runBlocking {
try {
val countries =
ApplicationConfigurationService.asyncRetrieveApplicationConfiguration()
.supportedCountriesList
?.map { it.toLowerCase(Locale.ROOT) } ?: listOf()
val countries = appConfigProvider.getAppConfig()
.supportedCountriesList
.mapNotNull { rawCode ->
val countryCode = rawCode.toLowerCase(Locale.ROOT)

val mappedCountry = Country.values().singleOrNull { it.code == countryCode }
if (mappedCountry == null) Timber.e("Unknown countrycode: %s", rawCode)
mappedCountry
}
_countryList.postValue(countries)
Timber.d("Country list: ${TextUtils.join(System.lineSeparator(), countries)}")
} catch (e: Exception) {
Expand Down
44 changes: 44 additions & 0 deletions Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/Country.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package de.rki.coronawarnapp.ui

import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import de.rki.coronawarnapp.R

enum class Country(
val code: String,
@StringRes val labelRes: Int,
@DrawableRes val iconRes: Int
) {
AT("at", R.string.country_name_at, R.drawable.ic_country_at),
BE("be", R.string.country_name_be, R.drawable.ic_country_be),
BG("bg", R.string.country_name_bg, R.drawable.ic_country_bg),
CH("ch", R.string.country_name_ch, R.drawable.ic_country_ch),
CY("cy", R.string.country_name_cy, R.drawable.ic_country_cy),
CZ("cz", R.string.country_name_cz, R.drawable.ic_country_cz),
DE("de", R.string.country_name_de, R.drawable.ic_country_de),
DK("dk", R.string.country_name_dk, R.drawable.ic_country_dk),
EE("ee", R.string.country_name_ee, R.drawable.ic_country_ee),
ES("es", R.string.country_name_es, R.drawable.ic_country_es),
FI("fi", R.string.country_name_fi, R.drawable.ic_country_fi),
FR("fr", R.string.country_name_fr, R.drawable.ic_country_fr),
UK("uk", R.string.country_name_uk, R.drawable.ic_country_uk),
GR("gr", R.string.country_name_gr, R.drawable.ic_country_gr),
HR("hr", R.string.country_name_hr, R.drawable.ic_country_hr),
HU("hu", R.string.country_name_hu, R.drawable.ic_country_hu),
IE("ie", R.string.country_name_ie, R.drawable.ic_country_ie),
IS("is", R.string.country_name_is, R.drawable.ic_country_is),
IT("it", R.string.country_name_it, R.drawable.ic_country_it),
LI("li", R.string.country_name_li, R.drawable.ic_country_li),
LT("lt", R.string.country_name_lt, R.drawable.ic_country_lt),
LU("lu", R.string.country_name_lu, R.drawable.ic_country_lu),
LV("lv", R.string.country_name_lv, R.drawable.ic_country_lv),
MT("mt", R.string.country_name_mt, R.drawable.ic_country_mt),
NL("nl", R.string.country_name_nl, R.drawable.ic_country_nl),
NO("no", R.string.country_name_no, R.drawable.ic_country_no),
PL("pl", R.string.country_name_pl, R.drawable.ic_country_pl),
PT("pt", R.string.country_name_pt, R.drawable.ic_country_pt),
RO("ro", R.string.country_name_ro, R.drawable.ic_country_ro),
SE("se", R.string.country_name_se, R.drawable.ic_country_se),
SI("si", R.string.country_name_si, R.drawable.ic_country_si),
SK("sk", R.string.country_name_sk, R.drawable.ic_country_sk)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,19 @@ package de.rki.coronawarnapp.ui.view

import android.content.Context
import android.util.AttributeSet
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.res.ResourcesCompat
import de.rki.coronawarnapp.R
import de.rki.coronawarnapp.ui.Country
import java.text.Collator
import java.util.Locale

class CountryList(context: Context, attrs: AttributeSet) :
LinearLayout(context, attrs) {

private var _list: List<String>? = null
var list: List<String>?
get() {
return _list?.map { it.toLowerCase(Locale.ROOT) }
}
private var _list: List<Country>? = null
var list: List<Country>?
get() = _list
set(value) {
_list = value
buildList()
Expand All @@ -34,49 +30,19 @@ class CountryList(context: Context, attrs: AttributeSet) :
private fun buildList() {
this.removeAllViews()
list
?.map { countryCode ->
val countryNameResourceId = context.resources.getIdentifier(
"country_name_$countryCode",
"string",
context.packageName
)
Pair(countryCode, context.getString(countryNameResourceId))
?.map { country ->
context.getString(country.labelRes) to country.iconRes
}
?.sortedWith { a, b ->
Collator.getInstance().compare(a.first, b.first)
}
?.sortedWith(Comparator { a, b ->
Collator.getInstance().compare(a.second, b.second)
})
?.forEachIndexed { index, country ->
?.forEachIndexed { index, (label, iconRes) ->
inflate(context, R.layout.view_country_list_entry, this)
val child = this.getChildAt(index)
this.setEntryValues(child, country.first, country.second)
child.apply {
findViewById<ImageView>(R.id.country_list_entry_image).setImageResource(iconRes)
findViewById<TextView>(R.id.country_list_entry_label).text = label
}
}
}

/**
* Sets the values of the views of each entry in the list
* @param entry the view of the current entry
* @param countryCode needed to determine which country is used for the current entry
* @param selected sets the status of the switch for the current entry
*/
private fun setEntryValues(
entry: View,
countryCode: String,
countryName: String
) {

// get drawable (flag of country) resource if dynamically based on country code
val countryFlagImageDrawableId = context.resources.getIdentifier(
"ic_country_$countryCode",
"drawable",
context.packageName
)

val countryFlagDrawable = ResourcesCompat
.getDrawable(context.resources, countryFlagImageDrawableId, null)

entry.findViewById<ImageView>(R.id.country_list_entry_image)
.setImageDrawable(countryFlagDrawable)

entry.findViewById<TextView>(R.id.country_list_entry_label).text = countryName
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import de.rki.coronawarnapp.ui.submission.SymptomCalendarEvent
import de.rki.coronawarnapp.ui.submission.SymptomIntroductionEvent
import de.rki.coronawarnapp.util.DeviceUIState
import de.rki.coronawarnapp.util.Event
import de.rki.coronawarnapp.util.di.AppInjector
import kotlinx.coroutines.launch
import org.joda.time.LocalDate
import timber.log.Timber
Expand All @@ -38,7 +39,8 @@ class SubmissionViewModel : ViewModel() {

private val _submissionState = MutableLiveData(ApiRequestState.IDLE)
private val _submissionError = MutableLiveData<Event<CwaWebException>>(null)
private val interoperabilityRepository = InteroperabilityRepository()
private val interoperabilityRepository: InteroperabilityRepository
get() = AppInjector.component.interoperabilityRepository

val scanStatus: LiveData<Event<ScanStatus>> = _scanStatus

Expand All @@ -63,7 +65,10 @@ class SubmissionViewModel : ViewModel() {

val symptomIndication = MutableLiveData<Symptoms.Indication?>()
val symptomStart = MutableLiveData<Symptoms.StartOf?>()
val countryList = MutableLiveData(interoperabilityRepository.countryList)

val countryList by lazy {
MutableLiveData(interoperabilityRepository.countryList)
}

fun initSymptoms() {
symptomIndication.postValue(null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import de.rki.coronawarnapp.receiver.ReceiverBinder
import de.rki.coronawarnapp.risk.RiskModule
import de.rki.coronawarnapp.service.ServiceBinder
import de.rki.coronawarnapp.storage.SettingsRepository
import de.rki.coronawarnapp.storage.interoperability.InteroperabilityRepository
import de.rki.coronawarnapp.submission.SubmissionModule
import de.rki.coronawarnapp.transaction.RetrieveDiagnosisInjectionHelper
import de.rki.coronawarnapp.transaction.RiskLevelInjectionHelper
Expand Down Expand Up @@ -78,6 +79,8 @@ interface ApplicationComponent : AndroidInjector<CoronaWarnApplication> {

val playbook: Playbook

val interoperabilityRepository: InteroperabilityRepository

@Component.Factory
interface Factory {
fun create(@BindsInstance app: CoronaWarnApplication): ApplicationComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<data>
<variable
name="countryData"
type="java.util.List&lt;String&gt;" />
type="java.util.List&lt;de.rki.coronawarnapp.ui.Country&gt;" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<variable
name="countryData"
type="java.util.List&lt;String&gt;" />
type="java.util.List&lt;de.rki.coronawarnapp.ui.Country&gt;" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<data>
<variable
name="countryData"
type="java.util.List&lt;String&gt;" />
type="java.util.List&lt;de.rki.coronawarnapp.ui.Country&gt;" />
</data>

<androidx.constraintlayout.widget.ConstraintLayout
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<variable
name="countryData"
type="java.util.List&lt;String&gt;" />
type="java.util.List&lt;de.rki.coronawarnapp.ui.Country&gt;" />

<variable
name="countryListTitle"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<variable
name="countryData"
type="java.util.List&lt;String&gt;" />
type="java.util.List&lt;de.rki.coronawarnapp.ui.Country&gt;" />

<variable
name="title"
Expand Down
2 changes: 1 addition & 1 deletion Corona-Warn-App/src/main/res/layout/include_onboarding.xml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@

<variable
name="countryData"
type="java.util.List&lt;String&gt;" />
type="java.util.List&lt;de.rki.coronawarnapp.ui.Country&gt;" />

</data>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

<variable
name="countryData"
type="java.util.List&lt;String&gt;" />
type="java.util.List&lt;de.rki.coronawarnapp.ui.Country&gt;" />

</data>

Expand Down
Loading