RL: process BroadcastReceiver actions outside UI thread

This commit is contained in:
Milos Kozak 2022-06-21 12:03:58 +02:00
parent 5a0fc8da74
commit e8928e554f
5 changed files with 170 additions and 244 deletions

View file

@ -4,10 +4,8 @@ import android.content.Intent
import android.content.res.Configuration
import android.os.Binder
import android.os.IBinder
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkTargetFrequency
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice
@ -21,6 +19,7 @@ import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicDeviceTyp
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicConst
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil
import info.nightscout.shared.logging.LTag
import javax.inject.Inject
import javax.inject.Singleton
@ -33,7 +32,6 @@ class RileyLinkMedtronicService : RileyLinkService() {
@Inject lateinit var medtronicPumpPlugin: MedtronicPumpPlugin
@Inject lateinit var medtronicUtil: MedtronicUtil
@Inject lateinit var medtronicPumpStatus: MedtronicPumpStatus
@Inject lateinit var rfSpy: RFSpy
@Inject lateinit var medtronicCommunicationManager: MedtronicCommunicationManager
@Inject lateinit var medtronicUIComm: MedtronicUIComm
@ -79,7 +77,7 @@ class RileyLinkMedtronicService : RileyLinkService() {
// get most recently used RileyLink address and name
rileyLinkServiceData.rileyLinkAddress = sp.getString(RileyLinkConst.Prefs.RileyLinkAddress, "")
rileyLinkServiceData.rileyLinkName = sp.getString(RileyLinkConst.Prefs.RileyLinkName, "")
rfspy.startReader()
rfSpy.startReader()
aapsLogger.debug(LTag.PUMPCOMM, "RileyLinkMedtronicService newly constructed")
}

View file

@ -69,7 +69,7 @@ public class RileyLinkOmnipodService extends RileyLinkService {
rileyLinkServiceData.rileyLinkAddress = sp.getString(RileyLinkConst.Prefs.RileyLinkAddress, "");
rileyLinkServiceData.rileyLinkName = sp.getString(RileyLinkConst.Prefs.RileyLinkName, "");
rfspy.startReader();
rfSpy.startReader();
aapsLogger.debug(LTag.PUMPBTCOMM, "RileyLinkOmnipodService newly constructed");
}

View file

@ -1,232 +0,0 @@
package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service;
/**
* Created by andy on 10/23/18.
*/
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import dagger.android.DaggerBroadcastReceiver;
import dagger.android.HasAndroidInjector;
import info.nightscout.androidaps.interfaces.ActivePlugin;
import info.nightscout.shared.logging.AAPSLogger;
import info.nightscout.shared.logging.LTag;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkFirmwareVersion;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpDevice;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.DiscoverGattServicesTask;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.InitializePumpManagerTask;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTask;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask;
import info.nightscout.shared.sharedPreferences.SP;
/**
* I added this class outside of RileyLinkService, because for now it's very important part of RL framework and
* where we get a lot of problems. Especially merging between AAPS and RileyLinkAAPS. I might put it back at
* later time
*/
public class RileyLinkBroadcastReceiver extends DaggerBroadcastReceiver {
@Inject HasAndroidInjector injector;
@Inject SP sp;
@Inject AAPSLogger aapsLogger;
@Inject RileyLinkServiceData rileyLinkServiceData;
@Inject ServiceTaskExecutor serviceTaskExecutor;
@Inject ActivePlugin activePlugin;
RileyLinkService serviceInstance;
protected Map<String, List<String>> broadcastIdentifiers = null;
//String deviceSpecificPrefix;
public RileyLinkBroadcastReceiver(RileyLinkService serviceInstance) {
this.serviceInstance = serviceInstance;
createBroadcastIdentifiers();
}
private void createBroadcastIdentifiers() {
this.broadcastIdentifiers = new HashMap<>();
// Bluetooth
this.broadcastIdentifiers.put("Bluetooth", Arrays.asList( //
RileyLinkConst.Intents.BluetoothConnected, //
RileyLinkConst.Intents.BluetoothReconnected));
// TuneUp
this.broadcastIdentifiers.put("TuneUp", Arrays.asList( //
RileyLinkConst.IPC.MSG_PUMP_tunePump, //
RileyLinkConst.IPC.MSG_PUMP_quickTune));
// RileyLink
this.broadcastIdentifiers.put("RileyLink", Arrays.asList( //
RileyLinkConst.Intents.RileyLinkDisconnected, //
RileyLinkConst.Intents.RileyLinkReady, //
RileyLinkConst.Intents.RileyLinkDisconnected, //
RileyLinkConst.Intents.RileyLinkNewAddressSet, //
RileyLinkConst.Intents.RileyLinkDisconnect));
}
private RileyLinkService getServiceInstance() {
RileyLinkPumpDevice pumpDevice = (RileyLinkPumpDevice) activePlugin.getActivePump();
return pumpDevice.getRileyLinkService();
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent == null) {
aapsLogger.error(LTag.PUMPBTCOMM, "onReceive: received null intent");
} else {
String action = intent.getAction();
if (action == null) {
aapsLogger.error("onReceive: null action");
} else {
aapsLogger.debug(LTag.PUMPBTCOMM, "Received Broadcast: " + action);
if (!processBluetoothBroadcasts(action) && //
!processRileyLinkBroadcasts(action, context) && //
!processTuneUpBroadcasts(action) && //
!processApplicationSpecificBroadcasts(action, intent) //
) {
aapsLogger.error(LTag.PUMPBTCOMM, "Unhandled broadcast: action=" + action);
}
}
}
}
public void registerBroadcasts(Context context) {
IntentFilter intentFilter = new IntentFilter();
for (Map.Entry<String, List<String>> stringListEntry : broadcastIdentifiers.entrySet()) {
for (String intentKey : stringListEntry.getValue()) {
intentFilter.addAction(intentKey);
}
}
LocalBroadcastManager.getInstance(context).registerReceiver(this, intentFilter);
}
private boolean processRileyLinkBroadcasts(String action, Context context) {
RileyLinkService rileyLinkService = getServiceInstance();
if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnected)) {
if (((BluetoothManager)context.getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter().isEnabled()) {
rileyLinkServiceData.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.RileyLinkUnreachable);
} else {
rileyLinkServiceData.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled);
}
return true;
} else if (action.equals(RileyLinkConst.Intents.RileyLinkReady)) {
aapsLogger.warn(LTag.PUMPBTCOMM, "RileyLinkConst.Intents.RileyLinkReady");
// sendIPCNotification(RT2Const.IPC.MSG_note_WakingPump);
rileyLinkService.rileyLinkBLE.enableNotifications();
rileyLinkService.rfspy.startReader(); // call startReader from outside?
rileyLinkService.rfspy.initializeRileyLink();
String bleVersion = rileyLinkService.rfspy.getBLEVersionCached();
RileyLinkFirmwareVersion rlVersion = rileyLinkServiceData.firmwareVersion;
aapsLogger.debug(LTag.PUMPBTCOMM, "RfSpy version (BLE113): " + bleVersion);
rileyLinkService.rileyLinkServiceData.versionBLE113 = bleVersion;
// if (isLoggingEnabled())
aapsLogger.debug(LTag.PUMPBTCOMM, "RfSpy Radio version (CC110): " + rlVersion.name());
this.rileyLinkServiceData.firmwareVersion = rlVersion;
ServiceTask task = new InitializePumpManagerTask(injector, context);
serviceTaskExecutor.startTask(task);
aapsLogger.info(LTag.PUMPBTCOMM, "Announcing RileyLink open For business");
return true;
} else if (action.equals(RileyLinkConst.Intents.RileyLinkNewAddressSet)) {
String RileylinkBLEAddress = sp.getString(RileyLinkConst.Prefs.RileyLinkAddress, "");
if (RileylinkBLEAddress.equals("")) {
aapsLogger.error("No Rileylink BLE Address saved in app");
} else {
// showBusy("Configuring Service", 50);
// rileyLinkBLE.findRileyLink(RileylinkBLEAddress);
rileyLinkService.reconfigureRileyLink(RileylinkBLEAddress);
// MainApp.getServiceClientConnection().setThisRileylink(RileylinkBLEAddress);
}
return true;
} else if (action.equals(RileyLinkConst.Intents.RileyLinkDisconnect)) {
rileyLinkService.disconnectRileyLink();
return true;
} else {
return false;
}
}
public boolean processBluetoothBroadcasts(String action) {
if (action.equals(RileyLinkConst.Intents.BluetoothConnected)) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Bluetooth - Connected");
serviceTaskExecutor.startTask(new DiscoverGattServicesTask(injector));
return true;
} else if (action.equals(RileyLinkConst.Intents.BluetoothReconnected)) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Bluetooth - Reconnecting");
getServiceInstance().bluetoothInit();
serviceTaskExecutor.startTask(new DiscoverGattServicesTask(injector, true));
return true;
} else {
return false;
}
}
private boolean processTuneUpBroadcasts(String action) {
if (this.broadcastIdentifiers.get("TuneUp").contains(action)) {
if (serviceInstance.getRileyLinkTargetDevice().isTuneUpEnabled()) {
serviceTaskExecutor.startTask(new WakeAndTuneTask(injector));
}
return true;
} else {
return false;
}
}
public boolean processApplicationSpecificBroadcasts(String action, Intent intent) {
return false;
}
public void unregisterBroadcasts(Context context) {
LocalBroadcastManager.getInstance(context).unregisterReceiver(this);
}
}

View file

@ -0,0 +1,160 @@
package info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service
import android.bluetooth.BluetoothManager
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.os.Handler
import android.os.HandlerThread
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import dagger.android.DaggerBroadcastReceiver
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkPumpDevice
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.DiscoverGattServicesTask
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.InitializePumpManagerTask
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTask
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask
import info.nightscout.shared.logging.AAPSLogger
import info.nightscout.shared.logging.LTag
import info.nightscout.shared.sharedPreferences.SP
import javax.inject.Inject
class RileyLinkBroadcastReceiver : DaggerBroadcastReceiver() {
@Inject lateinit var injector: HasAndroidInjector
@Inject lateinit var sp: SP
@Inject lateinit var aapsLogger: AAPSLogger
@Inject lateinit var rileyLinkServiceData: RileyLinkServiceData
@Inject lateinit var serviceTaskExecutor: ServiceTaskExecutor
@Inject lateinit var activePlugin: ActivePlugin
private var handler = Handler(HandlerThread(this::class.simpleName + "Handler").also { it.start() }.looper)
private val broadcastIdentifiers: MutableMap<String, List<String>> = HashMap()
init {
createBroadcastIdentifiers()
}
private val rileyLinkService: RileyLinkService
get() = (activePlugin.activePump as RileyLinkPumpDevice).rileyLinkService
private fun createBroadcastIdentifiers() {
// Bluetooth
broadcastIdentifiers["Bluetooth"] = listOf(
RileyLinkConst.Intents.BluetoothConnected,
RileyLinkConst.Intents.BluetoothReconnected
)
// TuneUp
broadcastIdentifiers["TuneUp"] = listOf(
RileyLinkConst.IPC.MSG_PUMP_tunePump,
RileyLinkConst.IPC.MSG_PUMP_quickTune
)
// RileyLink
broadcastIdentifiers["RileyLink"] = listOf(
RileyLinkConst.Intents.RileyLinkDisconnected,
RileyLinkConst.Intents.RileyLinkReady,
RileyLinkConst.Intents.RileyLinkDisconnected,
RileyLinkConst.Intents.RileyLinkNewAddressSet,
RileyLinkConst.Intents.RileyLinkDisconnect
)
}
override fun onReceive(context: Context, intent: Intent) {
super.onReceive(context, intent)
val action = intent.action ?: return
handler.post {
aapsLogger.debug(LTag.PUMPBTCOMM, "Received Broadcast: $action")
if (!processBluetoothBroadcasts(action) && !processRileyLinkBroadcasts(action, context) && !processTuneUpBroadcasts(action))
aapsLogger.error(LTag.PUMPBTCOMM, "Unhandled broadcast: action=$action")
}
}
fun registerBroadcasts(context: Context) {
val intentFilter = IntentFilter()
for ((_, value) in broadcastIdentifiers)
for (intentKey in value)
intentFilter.addAction(intentKey)
LocalBroadcastManager.getInstance(context).registerReceiver(this, intentFilter)
}
fun unregisterBroadcasts(context: Context) {
LocalBroadcastManager.getInstance(context).unregisterReceiver(this)
}
private fun processRileyLinkBroadcasts(action: String, context: Context): Boolean =
when (action) {
RileyLinkConst.Intents.RileyLinkDisconnected -> {
if ((context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager).adapter.isEnabled)
rileyLinkServiceData.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.RileyLinkUnreachable)
else
rileyLinkServiceData.setServiceState(RileyLinkServiceState.BluetoothError, RileyLinkError.BluetoothDisabled)
true
}
RileyLinkConst.Intents.RileyLinkReady -> {
aapsLogger.warn(LTag.PUMPBTCOMM, "RileyLinkConst.Intents.RileyLinkReady")
// sendIPCNotification(RT2Const.IPC.MSG_note_WakingPump);
rileyLinkService.rileyLinkBLE.enableNotifications()
rileyLinkService.rfSpy.startReader() // call startReader from outside?
rileyLinkService.rfSpy.initializeRileyLink()
val bleVersion = rileyLinkService.rfSpy.bleVersionCached
val rlVersion = rileyLinkServiceData.firmwareVersion
aapsLogger.debug(LTag.PUMPBTCOMM, "RfSpy version (BLE113): $bleVersion")
rileyLinkService.rileyLinkServiceData.versionBLE113 = bleVersion
aapsLogger.debug(LTag.PUMPBTCOMM, "RfSpy Radio version (CC110): " + rlVersion.name)
rileyLinkServiceData.firmwareVersion = rlVersion
val task: ServiceTask = InitializePumpManagerTask(injector, context)
serviceTaskExecutor.startTask(task)
aapsLogger.info(LTag.PUMPBTCOMM, "Announcing RileyLink open For business")
true
}
RileyLinkConst.Intents.RileyLinkNewAddressSet -> {
val rileylinkBLEAddress = sp.getString(RileyLinkConst.Prefs.RileyLinkAddress, "")
if (rileylinkBLEAddress == "") {
aapsLogger.error("No Rileylink BLE Address saved in app")
} else rileyLinkService.reconfigureRileyLink(rileylinkBLEAddress)
true
}
RileyLinkConst.Intents.RileyLinkDisconnect -> {
rileyLinkService.disconnectRileyLink()
true
}
else -> false
}
private fun processBluetoothBroadcasts(action: String): Boolean =
when (action) {
RileyLinkConst.Intents.BluetoothConnected -> {
aapsLogger.debug(LTag.PUMPBTCOMM, "Bluetooth - Connected")
serviceTaskExecutor.startTask(DiscoverGattServicesTask(injector))
true
}
RileyLinkConst.Intents.BluetoothReconnected -> {
aapsLogger.debug(LTag.PUMPBTCOMM, "Bluetooth - Reconnecting")
rileyLinkService.bluetoothInit()
serviceTaskExecutor.startTask(DiscoverGattServicesTask(injector, true))
true
}
else -> false
}
private fun processTuneUpBroadcasts(action: String): Boolean =
if (broadcastIdentifiers["TuneUp"]?.contains(action) == true) {
if (rileyLinkService.rileyLinkTargetDevice.isTuneUpEnabled) serviceTaskExecutor.startTask(WakeAndTuneTask(injector))
true
} else false
}

View file

@ -41,18 +41,18 @@ abstract class RileyLinkService : DaggerService() {
@Inject lateinit var rileyLinkServiceData: RileyLinkServiceData
@Inject lateinit var activePlugin: ActivePlugin
@Inject lateinit var rileyLinkBLE: RileyLinkBLE // android-bluetooth management
@Inject lateinit var rfspy: RFSpy // interface for RL xxx Mhz radio.
@Inject lateinit var rfSpy: RFSpy // interface for RL xxx Mhz radio.
private val bluetoothAdapter: BluetoothAdapter? get() = (context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager?)?.adapter
protected var mBroadcastReceiver: RileyLinkBroadcastReceiver? = null
protected var broadcastReceiver: RileyLinkBroadcastReceiver? = null
private var bluetoothStateReceiver: RileyLinkBluetoothStateReceiver? = null
override fun onCreate() {
super.onCreate()
rileyLinkUtil.encoding = encoding
initRileyLinkServiceData()
mBroadcastReceiver = RileyLinkBroadcastReceiver(this)
mBroadcastReceiver?.registerBroadcasts(this)
broadcastReceiver = RileyLinkBroadcastReceiver()
broadcastReceiver?.registerBroadcasts(this)
bluetoothStateReceiver = RileyLinkBluetoothStateReceiver()
bluetoothStateReceiver?.registerBroadcasts(this)
}
@ -80,7 +80,7 @@ abstract class RileyLinkService : DaggerService() {
super.onDestroy()
rileyLinkBLE.disconnect() // dispose of Gatt (disconnect and close)
mBroadcastReceiver?.unregisterBroadcasts(this)
broadcastReceiver?.unregisterBroadcasts(this)
bluetoothStateReceiver?.unregisterBroadcasts(this)
}
@ -139,7 +139,7 @@ abstract class RileyLinkService : DaggerService() {
}
}
// FIXME: This needs to be run in a session so that is interruptible, has a separate thread, etc.
// FIXME: This needs to be run in a session so that is incorruptible, has a separate thread, etc.
fun doTuneUpDevice() {
rileyLinkServiceData.setRileyLinkServiceState(RileyLinkServiceState.TuneUpDevice)
setPumpDeviceState(PumpDeviceState.Sleeping)
@ -178,7 +178,7 @@ abstract class RileyLinkService : DaggerService() {
get() = rileyLinkServiceData.targetDevice
fun changeRileyLinkEncoding(encodingType: RileyLinkEncodingType?) {
rfspy.setRileyLinkEncoding(encodingType)
rfSpy.setRileyLinkEncoding(encodingType)
}
val error: RileyLinkError?