refactor: migrate nodeDB to Room database (#717)

This commit is contained in:
Andre K 2023-09-05 08:19:26 -03:00 committed by GitHub
parent 99d7147efe
commit 83722159be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 742 additions and 148 deletions

View file

@ -7,7 +7,6 @@ import android.content.pm.ServiceInfo
import android.os.IBinder
import android.os.RemoteException
import androidx.core.app.ServiceCompat
import androidx.core.content.edit
import com.geeksville.mesh.analytics.DataPair
import com.geeksville.mesh.android.GeeksvilleApplication
import com.geeksville.mesh.android.Logging
@ -41,7 +40,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.json.Json
import java.util.*
import java.util.concurrent.ConcurrentLinkedQueue
import java.util.concurrent.TimeUnit
@ -242,9 +240,6 @@ class MeshService : Service(), Logging {
// Switch to the IO thread
serviceScope.handledLaunch {
loadSettings() // Load our last known node DB
// We in turn need to use the radiointerface service
radioInterfaceService.connect()
}
radioInterfaceService.connectionState.onEach(::onRadioConnectionState)
@ -256,6 +251,8 @@ class MeshService : Service(), Logging {
radioConfigRepository.channelSetFlow.onEach { channelSet = it }
.launchIn(serviceScope)
loadSettings() // Load our last known node DB
// the rest of our init will happen once we are in radioConnection.onServiceConnected
}
@ -299,8 +296,6 @@ class MeshService : Service(), Logging {
override fun onDestroy() {
info("Destroying mesh service")
saveSettings()
// Make sure we aren't using the notification first
ServiceCompat.stopForeground(this, ServiceCompat.STOP_FOREGROUND_REMOVE)
serviceNotifications.close()
@ -313,26 +308,8 @@ class MeshService : Service(), Logging {
/// BEGINNING OF MODEL - FIXME, move elsewhere
///
private fun getPrefs() = getSharedPreferences("service-prefs", Context.MODE_PRIVATE)
private fun installNewNodeDB(ni: MyNodeInfo, nodes: List<NodeInfo>) {
/// Save information about our mesh to disk, so we will have it when we next start the service (even before we hear from our device)
private fun saveSettings() = synchronized(nodeDBbyNodeNum) {
myNodeInfo?.let { myInfo ->
val settings = MeshServiceSettingsData(
myInfo = myInfo,
nodeDB = nodeDBbyNodeNum.values.toTypedArray(),
)
val json = Json { isLenient = true; allowSpecialFloatingPointValues = true }
val asString = json.encodeToString(MeshServiceSettingsData.serializer(), settings)
debug("Saving settings")
getPrefs().edit {
// FIXME, not really ideal to store this bigish blob in preferences
putString("json", asString)
}
}
}
private fun installNewNodeDB(ni: MyNodeInfo, nodes: Array<NodeInfo>) {
discardNodeDB() // Get rid of any old state
myNodeInfo = ni
@ -347,11 +324,11 @@ class MeshService : Service(), Logging {
private fun loadSettings() {
try {
getPrefs().getString("json", null)?.let { asString ->
serviceScope.handledLaunch {
val json = Json { isLenient = true; allowSpecialFloatingPointValues = true }
val settings = json.decodeFromString(MeshServiceSettingsData.serializer(), asString)
installNewNodeDB(settings.myInfo, settings.nodeDB)
val myInfo = radioConfigRepository.getMyNodeInfo()
val nodeDB = radioConfigRepository.getNodes()
if (myInfo != null && nodeDB != null) installNewNodeDB(myInfo, nodeDB)
// Note: we do not haveNodeDB = true because that means we've got a valid db from a real device (rather than this possibly stale hint)
}
@ -455,8 +432,12 @@ class MeshService : Service(), Logging {
// This might have been the first time we know an ID for this node, so also update the by ID map
val userId = info.user?.id.orEmpty()
if (userId.isNotEmpty())
if (userId.isNotEmpty()) {
nodeDBbyID[userId] = info
if (haveNodeDB) serviceScope.handledLaunch {
radioConfigRepository.upsert(info)
}
}
// parcelable is busted
if (withBroadcast)
@ -1027,9 +1008,6 @@ class MeshService : Service(), Logging {
/// Perform all the steps needed once we start waiting for device sleep to complete
fun startDeviceSleep() {
// Just in case the user uncleanly reboots the phone, save now (we normally save in onDestroy)
saveSettings()
stopPacketQueue()
stopLocationRequests()
@ -1063,9 +1041,6 @@ class MeshService : Service(), Logging {
}
fun startDisconnect() {
// Just in case the user uncleanly reboots the phone, save now (we normally save in onDestroy)
saveSettings()
stopPacketQueue()
stopLocationRequests()
@ -1405,6 +1380,10 @@ class MeshService : Service(), Logging {
regenMyNodeInfo() // we have a node db now, so can possibly find a better hwmodel
myNodeInfo = newMyNodeInfo // we might have just updated myNodeInfo
serviceScope.handledLaunch {
radioConfigRepository.installNodeDB(newMyNodeInfo, nodeDBbyID.values.toList())
}
sendAnalytics()
if (deviceVersion < minDeviceVersion || appVersion < minAppVersion) {

View file

@ -1,30 +0,0 @@
package com.geeksville.mesh.service
import com.geeksville.mesh.MyNodeInfo
import com.geeksville.mesh.NodeInfo
import kotlinx.serialization.Serializable
/// Our saved preferences as stored on disk
@Serializable
data class MeshServiceSettingsData(
val nodeDB: Array<NodeInfo>,
val myInfo: MyNodeInfo,
) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as MeshServiceSettingsData
if (!nodeDB.contentEquals(other.nodeDB)) return false
if (myInfo != other.myInfo) return false
return true
}
override fun hashCode(): Int {
var result = nodeDB.contentHashCode()
result = 31 * result + myInfo.hashCode()
return result
}
}