diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/LocalOnlyHotspotService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/LocalOnlyHotspotService.kt index 96e6e0b3..04697d5f 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/LocalOnlyHotspotService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/LocalOnlyHotspotService.kt @@ -12,10 +12,11 @@ import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor import be.mygod.vpnhotspot.util.StickyEvent1 import be.mygod.vpnhotspot.util.broadcastReceiver import be.mygod.vpnhotspot.widget.SmartSnackbar +import kotlinx.coroutines.* import timber.log.Timber @RequiresApi(26) -class LocalOnlyHotspotService : IpNeighbourMonitoringService() { +class LocalOnlyHotspotService : IpNeighbourMonitoringService(), CoroutineScope { companion object { private const val TAG = "LocalOnlyHotspotService" } @@ -38,6 +39,10 @@ class LocalOnlyHotspotService : IpNeighbourMonitoringService() { private val binder = Binder() private var reservation: WifiManager.LocalOnlyHotspotReservation? = null + /** + * Writes and critical reads to routingManager should be protected with this context. + */ + override val coroutineContext = newSingleThreadContext("LocalOnlyHotspotService") + Job() private var routingManager: RoutingManager? = null private var receiverRegistered = false private val receiver = broadcastReceiver { _, intent -> @@ -50,11 +55,11 @@ class LocalOnlyHotspotService : IpNeighbourMonitoringService() { unregisterReceiver() ServiceNotification.stopForeground(this) stopSelf() - } else { + } else launch { val routingManager = routingManager if (routingManager == null) { - this.routingManager = RoutingManager.LocalOnly(this, iface).apply { start() } - IpNeighbourMonitor.registerCallback(this) + this@LocalOnlyHotspotService.routingManager = RoutingManager.LocalOnly(this, iface).apply { start() } + IpNeighbourMonitor.registerCallback(this@LocalOnlyHotspotService) } else check(iface == routingManager.downstream) } } @@ -120,13 +125,16 @@ class LocalOnlyHotspotService : IpNeighbourMonitoringService() { override fun onDestroy() { binder.stop() - unregisterReceiver() + unregisterReceiver(true) super.onDestroy() } - private fun unregisterReceiver() { - routingManager?.destroy() - routingManager = null + private fun unregisterReceiver(exit: Boolean = false) { + launch { + routingManager?.destroy() + routingManager = null + if (exit) cancel() + } if (receiverRegistered) { unregisterReceiver(receiver) IpNeighbourMonitor.unregisterCallback(this) diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt index ac9e8f1a..5d79feb5 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/RepeaterService.kt @@ -23,10 +23,7 @@ import be.mygod.vpnhotspot.net.wifi.WifiP2pManagerHelper.startWps import be.mygod.vpnhotspot.net.wifi.configuration.channelToFrequency import be.mygod.vpnhotspot.util.* import be.mygod.vpnhotspot.widget.SmartSnackbar -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.launch -import kotlinx.coroutines.newSingleThreadContext +import kotlinx.coroutines.* import timber.log.Timber import java.lang.reflect.InvocationTargetException @@ -144,7 +141,7 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene /** * Writes and critical reads to routingManager should be protected with this context. */ - override val coroutineContext = newSingleThreadContext("TetheringService") + Job() + override val coroutineContext = newSingleThreadContext("RepeaterService") + Job() private var routingManager: RoutingManager? = null private var persistNextGroup = false @@ -402,7 +399,10 @@ class RepeaterService : Service(), CoroutineScope, WifiP2pManager.ChannelListene override fun onDestroy() { handler.removeCallbacksAndMessages(null) if (status != Status.IDLE) binder.shutdown() - launch { cleanLocked() } // force clean to prevent leakage + launch { // force clean to prevent leakage + cleanLocked() + cancel() + } if (Build.VERSION.SDK_INT < 29) @Suppress("DEPRECATION") { app.pref.unregisterOnSharedPreferenceChangeListener(this) unregisterReceiver(deviceListener)