Merge pull request #434 from mcumings/radioservice-companion

Extract `RadioInterfaceService` companion object functions
pull/435/head
Andre Kirchhoff 2022-05-20 19:12:15 -03:00 zatwierdzone przez GitHub
commit 63db5f61dc
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
7 zmienionych plików z 82 dodań i 88 usunięć

Wyświetl plik

@ -88,7 +88,7 @@ android {
kotlinOptions {
jvmTarget = "1.8"
freeCompilerArgs += [ '-Xopt-in=kotlin.RequiresOptIn' ]
freeCompilerArgs += [ '-opt-in=kotlin.RequiresOptIn' ]
}
lint {
abortOnError false

Wyświetl plik

@ -42,7 +42,6 @@ import com.geeksville.mesh.model.DeviceVersion
import com.geeksville.mesh.model.UIViewModel
import com.geeksville.mesh.repository.radio.RadioInterfaceService
import com.geeksville.mesh.repository.radio.SerialInterface
import com.geeksville.mesh.repository.usb.UsbRepository
import com.geeksville.mesh.service.*
import com.geeksville.mesh.ui.*
import com.geeksville.util.Exceptions
@ -140,7 +139,7 @@ class MainActivity : BaseActivity(), Logging,
val model: UIViewModel by viewModels()
@Inject
internal lateinit var usbRepository: UsbRepository
internal lateinit var radioInterfaceService: RadioInterfaceService
data class TabInfo(val text: String, val icon: Int, val content: Fragment)
@ -982,7 +981,7 @@ class MainActivity : BaseActivity(), Logging,
errormsg("Bind of MeshService failed")
}
val bonded = RadioInterfaceService.getBondedDeviceAddress(this, usbRepository) != null
val bonded = radioInterfaceService.getBondedDeviceAddress() != null
if (!bonded && usbDevice == null) // we will handle USB later
showSettingsPage()
}

Wyświetl plik

@ -2,8 +2,6 @@ package com.geeksville.mesh.repository.radio
import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import androidx.core.content.edit
import androidx.lifecycle.Lifecycle
@ -15,8 +13,6 @@ import com.geeksville.concurrent.handledLaunch
import com.geeksville.mesh.CoroutineDispatchers
import com.geeksville.mesh.repository.bluetooth.BluetoothRepository
import com.geeksville.mesh.repository.usb.UsbRepository
import com.geeksville.mesh.service.EXTRA_PAYLOAD
import com.geeksville.mesh.service.prefix
import com.geeksville.util.anonymize
import com.geeksville.util.ignoreException
import com.geeksville.util.toRemoteExceptions
@ -42,7 +38,8 @@ class RadioInterfaceService @Inject constructor(
private val dispatchers: CoroutineDispatchers,
private val bluetoothRepository: BluetoothRepository,
private val processLifecycle: Lifecycle,
private val usbRepository: UsbRepository
private val usbRepository: UsbRepository,
@RadioRepositoryQualifier private val prefs: SharedPreferences
): Logging {
private val _connectionState = MutableStateFlow(RadioServiceConnectionState())
@ -85,17 +82,6 @@ class RadioInterfaceService @Inject constructor(
}
companion object : Logging {
/**
* The RECEIVED_FROMRADIO
* Payload will be the raw bytes which were contained within a MeshProtos.FromRadio protobuf
*/
const val RECEIVE_FROMRADIO_ACTION = "$prefix.RECEIVE_FROMRADIO"
/**
* This is broadcast when connection state changed
*/
const val RADIO_CONNECTED_ACTION = "$prefix.CONNECT_CHANGED"
const val DEVADDR_KEY = "devAddr2" // the new name for devaddr
init {
@ -109,61 +95,49 @@ class RadioInterfaceService @Inject constructor(
)
info("Using ${factories.size} interface factories")
}
}
/// This is public only so that SimRadio can bootstrap our message flow
fun broadcastReceivedFromRadio(context: Context, payload: ByteArray) {
val intent = Intent(RECEIVE_FROMRADIO_ACTION)
intent.putExtra(EXTRA_PAYLOAD, payload)
context.sendBroadcast(intent)
}
fun getPrefs(context: Context): SharedPreferences =
context.getSharedPreferences("radio-prefs", Context.MODE_PRIVATE)
/** Return the device we are configured to use, or null for none
* device address strings are of the form:
*
* at
*
* where a is either x for bluetooth or s for serial
* and t is an interface specific address (macaddr or a device path)
*/
@SuppressLint("NewApi")
fun getDeviceAddress(context: Context, usbRepository: UsbRepository): String? {
// If the user has unpaired our device, treat things as if we don't have one
val prefs = getPrefs(context)
var address = prefs.getString(DEVADDR_KEY, null)
// If we are running on the emulator we default to the mock interface, so we can have some data to show to the user
if (address == null && MockInterface.addressValid(context, usbRepository, ""))
address = MockInterface.prefix.toString()
return address
}
/** Like getDeviceAddress, but filtered to return only devices we are currently bonded with
*
* at
*
* where a is either x for bluetooth or s for serial
* and t is an interface specific address (macaddr or a device path)
*/
@SuppressLint("NewApi")
fun getBondedDeviceAddress(context: Context, usbRepository: UsbRepository): String? {
// If the user has unpaired our device, treat things as if we don't have one
val address = getDeviceAddress(context, usbRepository)
/// Interfaces can filter addresses to indicate that address is no longer acceptable
if (address != null) {
val c = address[0]
val rest = address.substring(1)
val isValid = InterfaceFactory.getFactory(c)
?.addressValid(context, usbRepository, rest) ?: false
if (!isValid)
return null
}
return address
/** Return the device we are configured to use, or null for none
* device address strings are of the form:
*
* at
*
* where a is either x for bluetooth or s for serial
* and t is an interface specific address (macaddr or a device path)
*/
fun getDeviceAddress(): String? {
// If the user has unpaired our device, treat things as if we don't have one
var address = prefs.getString(DEVADDR_KEY, null)
// If we are running on the emulator we default to the mock interface, so we can have some data to show to the user
if (address == null && MockInterface.addressValid(context, usbRepository, ""))
address = MockInterface.prefix.toString()
return address
}
/** Like getDeviceAddress, but filtered to return only devices we are currently bonded with
*
* at
*
* where a is either x for bluetooth or s for serial
* and t is an interface specific address (macaddr or a device path)
*/
@SuppressLint("NewApi")
fun getBondedDeviceAddress(): String? {
// If the user has unpaired our device, treat things as if we don't have one
val address = getDeviceAddress()
/// Interfaces can filter addresses to indicate that address is no longer acceptable
if (address != null) {
val c = address[0]
val rest = address.substring(1)
val isValid = InterfaceFactory.getFactory(c)
?.addressValid(context, usbRepository, rest) ?: false
if (!isValid)
return null
}
return address
}
private fun broadcastConnectionChanged(isConnected: Boolean, isPermanent: Boolean) {
@ -214,7 +188,7 @@ class RadioInterfaceService @Inject constructor(
if (radioIf !is NopInterface)
warn("Can't start interface - $radioIf is already running")
else {
val address = getBondedDeviceAddress(context, usbRepository)
val address = getBondedDeviceAddress()
if (address == null)
warn("No bonded mesh radio, can't start interface")
else {
@ -263,7 +237,7 @@ class RadioInterfaceService @Inject constructor(
*/
@SuppressLint("NewApi")
private fun setBondedDeviceAddress(address: String?): Boolean {
return if (getBondedDeviceAddress(context, usbRepository) == address && isStarted) {
return if (getBondedDeviceAddress() == address && isStarted) {
warn("Ignoring setBondedDevice ${address.anonymize}, because we are already using that device")
false
} else {
@ -281,7 +255,7 @@ class RadioInterfaceService @Inject constructor(
debug("Setting bonded device to ${address.anonymize}")
getPrefs(context).edit {
prefs.edit {
if (address == null)
this.remove(DEVADDR_KEY)
else

Wyświetl plik

@ -0,0 +1,19 @@
package com.geeksville.mesh.repository.radio
import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
@Module
@InstallIn(SingletonComponent::class)
object RadioRepositoryModule {
@Provides
@RadioRepositoryQualifier
fun provideSharedPreferences(application: Application): SharedPreferences {
return application.getSharedPreferences("radio-prefs", Context.MODE_PRIVATE)
}
}

Wyświetl plik

@ -0,0 +1,9 @@
package com.geeksville.mesh.repository.radio
import javax.inject.Qualifier
/**
* Qualifier to distinguish radio repository- specific object instances.
*/
@Qualifier
annotation class RadioRepositoryQualifier

Wyświetl plik

@ -22,7 +22,6 @@ import com.geeksville.mesh.repository.location.LocationRepository
import com.geeksville.mesh.repository.radio.BluetoothInterface
import com.geeksville.mesh.repository.radio.RadioInterfaceService
import com.geeksville.mesh.repository.radio.RadioServiceConnectionState
import com.geeksville.mesh.repository.usb.UsbRepository
import com.geeksville.util.*
import com.google.protobuf.ByteString
import com.google.protobuf.InvalidProtocolBufferException
@ -55,9 +54,6 @@ class MeshService : Service(), Logging {
@Inject
lateinit var radioInterfaceService: RadioInterfaceService
@Inject
lateinit var usbRepository: Lazy<UsbRepository>
@Inject
lateinit var locationRepository: LocationRepository
@ -211,7 +207,7 @@ class MeshService : Service(), Logging {
* tell android not to kill us
*/
private fun startForeground() {
val a = RadioInterfaceService.getBondedDeviceAddress(this, usbRepository.get())
val a = radioInterfaceService.getBondedDeviceAddress()
val wantForeground = a != null && a != "n"
info("Requesting foreground service=$wantForeground")
@ -1180,7 +1176,7 @@ class MeshService : Service(), Logging {
private fun regenMyNodeInfo() {
val myInfo = rawMyNodeInfo
if (myInfo != null) {
val a = RadioInterfaceService.getBondedDeviceAddress(this, usbRepository.get())
val a = radioInterfaceService.getBondedDeviceAddress()
val isBluetoothInterface = a != null && a.startsWith("x")
val nodeNum =

Wyświetl plik

@ -4,11 +4,7 @@ import android.annotation.SuppressLint
import android.app.Application
import android.app.PendingIntent
import android.bluetooth.BluetoothDevice
import android.bluetooth.le.BluetoothLeScanner
import android.bluetooth.le.ScanCallback
import android.bluetooth.le.ScanSettings
import android.bluetooth.le.ScanFilter
import android.bluetooth.le.ScanResult
import android.bluetooth.le.*
import android.companion.AssociationRequest
import android.companion.BluetoothDeviceFilter
import android.companion.CompanionDeviceManager
@ -127,6 +123,7 @@ class BTScanModel @Inject constructor(
private val bluetoothRepository: BluetoothRepository,
private val usbRepository: UsbRepository,
private val nsdRepository: NsdRepository,
private val radioInterfaceService: RadioInterfaceService,
) : ViewModel(), Logging {
private val context: Context get() = application.applicationContext
@ -258,7 +255,7 @@ class BTScanModel @Inject constructor(
* returns true if we could start scanning, false otherwise
*/
fun setupScan(): Boolean {
selectedAddress = RadioInterfaceService.getDeviceAddress(context, usbRepository)
selectedAddress = radioInterfaceService.getDeviceAddress()
return if (bluetoothAdapter == null || MockInterface.addressValid(context, usbRepository, "")) {
warn("No bluetooth adapter. Running under emulation?")