From c9d18b00a4789d5e91a14e47e63925c9240d292e Mon Sep 17 00:00:00 2001 From: Kevin Hester Date: Sat, 20 Mar 2021 17:47:02 +0800 Subject: [PATCH] don't let user update firmware without setting a region. --- .../com/geeksville/mesh/IMeshService.aidl | 3 ++ .../java/com/geeksville/mesh/model/UIState.kt | 11 ++--- .../geeksville/mesh/service/MeshService.kt | 48 ++++++++++++------- .../geeksville/mesh/ui/SettingsFragment.kt | 39 +++++++-------- 4 files changed, 53 insertions(+), 48 deletions(-) diff --git a/app/src/main/aidl/com/geeksville/mesh/IMeshService.aidl b/app/src/main/aidl/com/geeksville/mesh/IMeshService.aidl index a9ee757d0..17382d016 100644 --- a/app/src/main/aidl/com/geeksville/mesh/IMeshService.aidl +++ b/app/src/main/aidl/com/geeksville/mesh/IMeshService.aidl @@ -113,4 +113,7 @@ interface IMeshService { Return a number 0-100 for progress. -1 for completed and success, -2 for failure */ int getUpdateStatus(); + + int getRegion(); + void setRegion(int regionCode); } diff --git a/app/src/main/java/com/geeksville/mesh/model/UIState.kt b/app/src/main/java/com/geeksville/mesh/model/UIState.kt index fe4175e9b..6b79ba688 100644 --- a/app/src/main/java/com/geeksville/mesh/model/UIState.kt +++ b/app/src/main/java/com/geeksville/mesh/model/UIState.kt @@ -134,15 +134,10 @@ class UIViewModel(private val app: Application) : AndroidViewModel(app), Logging } } - var region: RadioConfigProtos.RegionCode? - get() = radioConfig.value?.preferences?.region + var region: RadioConfigProtos.RegionCode + get() = meshService?.region?.let { RadioConfigProtos.RegionCode.forNumber(it) } ?: RadioConfigProtos.RegionCode.Unset set(value) { - val config = radioConfig.value - if (value != null && config != null) { - val builder = config.toBuilder() - builder.preferencesBuilder.region = value - setRadioConfig(builder.build()) - } + meshService?.region = value.number } /// hardware info about our local device (can be null) diff --git a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt index fafc47bf9..2d1749955 100644 --- a/app/src/main/java/com/geeksville/mesh/service/MeshService.kt +++ b/app/src/main/java/com/geeksville/mesh/service/MeshService.kt @@ -1313,6 +1313,28 @@ class MeshService : Service(), Logging { } + private fun setRegionOnDevice() { + val curConfigRegion = + radioConfig?.preferences?.region ?: RadioConfigProtos.RegionCode.Unset + + if (curConfigRegion.number != curRegionValue && curRegionValue != RadioConfigProtos.RegionCode.Unset_VALUE) + if (deviceVersion >= minFirmwareVersion) { + info("Telling device to upgrade region") + + // Tell the device to set the new region field (old devices will simply ignore this) + radioConfig?.let { currentConfig -> + val newConfig = currentConfig.toBuilder() + + val newPrefs = currentConfig.preferences.toBuilder() + newPrefs.regionValue = curRegionValue + newConfig.preferences = newPrefs.build() + + sendRadioConfig(newConfig.build()) + } + } else + warn("Device is too old to understand region changes") + } + /** * If we are updating nodes we might need to use old (fixed by firmware build) * region info to populate our new universal ROMs. @@ -1346,23 +1368,7 @@ class MeshService : Service(), Logging { } // If nothing was set in our (new style radio preferences, but we now have a valid setting - slam it in) - if (curConfigRegion == RadioConfigProtos.RegionCode.Unset && curRegionValue != RadioConfigProtos.RegionCode.Unset_VALUE) { - if (deviceVersion >= minFirmwareVersion) { - info("Telling device to upgrade region") - - // Tell the device to set the new region field (old devices will simply ignore this) - radioConfig?.let { currentConfig -> - val newConfig = currentConfig.toBuilder() - - val newPrefs = currentConfig.preferences.toBuilder() - newPrefs.regionValue = curRegionValue - newConfig.preferences = newPrefs.build() - - sendRadioConfig(newConfig.build()) - } - } else - warn("Device is too old to understand region changes") - } + setRegionOnDevice() } } @@ -1651,7 +1657,7 @@ class MeshService : Service(), Logging { offlineSentPackets.add(p) } - val binder = object : IMeshService.Stub() { + private val binder = object : IMeshService.Stub() { override fun setDeviceAddress(deviceAddr: String?) = toRemoteExceptions { debug("Passing through device change to radio service: ${deviceAddr.anonymize}") @@ -1675,6 +1681,12 @@ class MeshService : Service(), Logging { } override fun getUpdateStatus(): Int = SoftwareUpdateService.progress + override fun getRegion(): Int = curRegionValue + + override fun setRegion(regionCode: Int) = toRemoteExceptions { + curRegionValue = regionCode + setRegionOnDevice() + } override fun startFirmwareUpdate() = toRemoteExceptions { doFirmwareUpdate() diff --git a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt index fde6466bd..11d552ab3 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/SettingsFragment.kt @@ -524,7 +524,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { } /// Set the correct update button configuration based on current progress - private fun refreshUpdateButton() { + private fun refreshUpdateButton(enable: Boolean) { debug("Reiniting the udpate button") val info = model.myNodeInfo.value val service = model.meshService @@ -535,7 +535,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { val progress = service.updateStatus - binding.updateFirmwareButton.isEnabled = + binding.updateFirmwareButton.isEnabled = enable && (progress < 0) // if currently doing an upgrade disable button if (progress >= 0) { @@ -572,7 +572,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { val connected = model.isConnected.value val isConnected = connected == MeshService.ConnectionState.CONNECTED - binding.nodeSettings.visibility = if(isConnected) View.VISIBLE else View.GONE + binding.nodeSettings.visibility = if (isConnected) View.VISIBLE else View.GONE if (connected == MeshService.ConnectionState.DISCONNECTED) model.ownerName.value = "" @@ -582,25 +582,19 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { val spinner = binding.regionSpinner val unsetIndex = regions.indexOf(RadioConfigProtos.RegionCode.Unset.name) spinner.onItemSelectedListener = null - if(region != null) { - debug("current region is $region") - var regionIndex = regions.indexOf(region.name) - if(regionIndex == -1) // Not found, probably because the device has a region our app doesn't yet understand. Punt and say Unset - regionIndex = unsetIndex - // We don't want to be notified of our own changes, so turn off listener while making them - spinner.setSelection(regionIndex, false) - spinner.onItemSelectedListener = regionSpinnerListener - spinner.isEnabled = true - } - else { - warn("region is unset!") - spinner.setSelection(unsetIndex, false) - spinner.isEnabled = false // leave disabled, because we can't get our region - } + debug("current region is $region") + var regionIndex = regions.indexOf(region.name) + if (regionIndex == -1) // Not found, probably because the device has a region our app doesn't yet understand. Punt and say Unset + regionIndex = unsetIndex + + // We don't want to be notified of our own changes, so turn off listener while making them + spinner.setSelection(regionIndex, false) + spinner.onItemSelectedListener = regionSpinnerListener + spinner.isEnabled = true // If actively connected possibly let the user update firmware - refreshUpdateButton() + refreshUpdateButton(region != RadioConfigProtos.RegionCode.Unset) // Update the status string (highest priority messages first) val info = model.myNodeInfo.value @@ -620,7 +614,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { } } - private val regionSpinnerListener = object : AdapterView.OnItemSelectedListener{ + private val regionSpinnerListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected( parent: AdapterView<*>, view: View, @@ -652,7 +646,8 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { // init our region spinner val spinner = binding.regionSpinner - val regionAdapter = ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, regions) + val regionAdapter = + ArrayAdapter(requireContext(), android.R.layout.simple_spinner_item, regions) regionAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item) spinner.adapter = regionAdapter @@ -965,7 +960,7 @@ class SettingsFragment : ScreenFragment("Settings"), Logging { private val updateProgressReceiver: BroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { - refreshUpdateButton() + refreshUpdateButton(true) } }