diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/RoutingManager.kt b/mobile/src/main/java/be/mygod/vpnhotspot/RoutingManager.kt index 468a20c3..d0919620 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/RoutingManager.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/RoutingManager.kt @@ -6,14 +6,12 @@ import androidx.core.os.BuildCompat import be.mygod.vpnhotspot.App.Companion.app import be.mygod.vpnhotspot.net.Routing import be.mygod.vpnhotspot.net.TetherType -import be.mygod.vpnhotspot.net.TetheringManager import be.mygod.vpnhotspot.net.wifi.WifiDoubleLock import be.mygod.vpnhotspot.widget.SmartSnackbar import timber.log.Timber import java.net.NetworkInterface -abstract class RoutingManager(private val caller: Any, val downstream: String, - private val forceWifi: Boolean = false) : TetheringManager.TetheringEventCallback { +abstract class RoutingManager(private val caller: Any, val downstream: String, private val forceWifi: Boolean = false) { companion object { private const val KEY_MASQUERADE_MODE = "service.masqueradeMode" var masqueradeMode: Routing.MasqueradeMode @@ -63,7 +61,13 @@ abstract class RoutingManager(private val caller: Any, val downstream: String, fun start() = when (val other = active.putIfAbsent(downstream, this)) { null -> { if (isWifi) WifiDoubleLock.acquire(this) - if (!forceWifi && BuildCompat.isAtLeastR()) TetheringManager.registerTetheringEventCallback(null, this) + if (!forceWifi && BuildCompat.isAtLeastR()) TetherType.listener[this] = { + val isWifiNow = TetherType.ofInterface(downstream).isWifi + if (isWifi != isWifiNow) { + if (isWifi) WifiDoubleLock.release(this) else WifiDoubleLock.acquire(this) + isWifi = isWifiNow + } + } initRouting() } this -> true // already started @@ -72,13 +76,6 @@ abstract class RoutingManager(private val caller: Any, val downstream: String, open fun ifaceHandler(iface: NetworkInterface) { } - override fun onTetherableInterfaceRegexpsChanged() { - val isWifiNow = TetherType.ofInterface(downstream).isWifi - if (isWifi == isWifiNow) return - if (isWifi) WifiDoubleLock.release(this) else WifiDoubleLock.acquire(this) - isWifi = isWifiNow - } - private fun initRouting() = try { routing = Routing(caller, downstream, this::ifaceHandler).apply { try { @@ -100,7 +97,7 @@ abstract class RoutingManager(private val caller: Any, val downstream: String, fun stop() { if (active.remove(downstream, this)) { - if (!forceWifi && BuildCompat.isAtLeastR()) TetheringManager.unregisterTetheringEventCallback(this) + if (!forceWifi && BuildCompat.isAtLeastR()) TetherType.listener -= this if (isWifi) WifiDoubleLock.release(this) routing?.revert() } diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt index 5bf38433..b019cccc 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientsFragment.kt @@ -30,7 +30,7 @@ import be.mygod.vpnhotspot.Empty import be.mygod.vpnhotspot.R import be.mygod.vpnhotspot.databinding.FragmentClientsBinding import be.mygod.vpnhotspot.databinding.ListitemClientBinding -import be.mygod.vpnhotspot.net.TetheringManager +import be.mygod.vpnhotspot.net.TetherType import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor import be.mygod.vpnhotspot.net.monitor.TrafficRecorder import be.mygod.vpnhotspot.room.AppDatabase @@ -47,7 +47,7 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.text.NumberFormat -class ClientsFragment : Fragment(), TetheringManager.TetheringEventCallback { +class ClientsFragment : Fragment() { @Parcelize data class NicknameArg(val mac: Long, val nickname: CharSequence) : Parcelable class NicknameDialogFragment : AlertDialogFragment() { @@ -230,7 +230,8 @@ class ClientsFragment : Fragment(), TetheringManager.TetheringEventCallback { } override fun onStart() { - if (BuildCompat.isAtLeastR()) TetheringManager.registerTetheringEventCallback(null, this) + // icon might be changed due to TetherType changes + if (BuildCompat.isAtLeastR()) TetherType.listener[this] = { adapter.notifyItemRangeChanged(0, adapter.size) } super.onStart() // we just put these two thing together as this is the only place we need to use this event for now TrafficRecorder.foregroundListeners[this] = adapter::updateTraffic @@ -244,11 +245,6 @@ class ClientsFragment : Fragment(), TetheringManager.TetheringEventCallback { override fun onStop() { TrafficRecorder.foregroundListeners -= this super.onStop() - if (BuildCompat.isAtLeastR()) TetheringManager.unregisterTetheringEventCallback(this) - } - - override fun onTetherableInterfaceRegexpsChanged() { - // icon might be changed due to TetherType changes - adapter.notifyItemRangeChanged(0, adapter.size) + if (BuildCompat.isAtLeastR()) TetherType.listener -= this } } diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringFragment.kt index b8aa283a..e6a33d82 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringFragment.kt @@ -38,7 +38,7 @@ import java.lang.reflect.InvocationTargetException import java.net.NetworkInterface import java.net.SocketException -class TetheringFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickListener, TetheringManager.TetheringEventCallback { +class TetheringFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClickListener { companion object { const val START_REPEATER = 4 const val START_LOCAL_ONLY_HOTSPOT = 1 @@ -255,17 +255,15 @@ class TetheringFragment : Fragment(), ServiceConnection, Toolbar.OnMenuItemClick lifecycleScope.launchWhenStarted { adapter.notifyInterfaceChanged() } } requireContext().registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)) - if (BuildCompat.isAtLeastR()) TetheringManager.registerTetheringEventCallback(null, this) + if (BuildCompat.isAtLeastR()) TetherType.listener[this] = { + lifecycleScope.launchWhenStarted { adapter.notifyTetherTypeChanged() } + } } override fun onServiceDisconnected(name: ComponentName?) { (binder ?: return).routingsChanged -= this binder = null - if (BuildCompat.isAtLeastR()) TetheringManager.unregisterTetheringEventCallback(this) + if (BuildCompat.isAtLeastR()) TetherType.listener -= this requireContext().unregisterReceiver(receiver) } - - override fun onTetherableInterfaceRegexpsChanged() { - lifecycleScope.launchWhenStarted { adapter.notifyTetherTypeChanged() } - } } diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringTileService.kt b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringTileService.kt index 8f00cb56..ce377e3f 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringTileService.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetheringTileService.kt @@ -26,8 +26,7 @@ import java.io.IOException import java.lang.reflect.InvocationTargetException @RequiresApi(24) -sealed class TetheringTileService : KillableTileService(), TetheringManager.StartTetheringCallback, - TetheringManager.TetheringEventCallback { +sealed class TetheringTileService : KillableTileService(), TetheringManager.StartTetheringCallback { protected val tileOff by lazy { Icon.createWithResource(application, icon) } protected val tileOn by lazy { Icon.createWithResource(application, R.drawable.ic_quick_settings_tile_on) } @@ -52,12 +51,12 @@ sealed class TetheringTileService : KillableTileService(), TetheringManager.Star // we need to initialize tethered ASAP for onClick, which is not achievable using registerTetheringEventCallback tethered = registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)) ?.tetheredIfaces - if (BuildCompat.isAtLeastR()) TetheringManager.registerTetheringEventCallback(null, this) + if (BuildCompat.isAtLeastR()) TetherType.listener[this] = this::updateTile updateTile() } override fun onStopListening() { - if (BuildCompat.isAtLeastR()) TetheringManager.unregisterTetheringEventCallback(this) + if (BuildCompat.isAtLeastR()) TetherType.listener -= this unregisterReceiver(receiver) stopAndUnbind(this) super.onStopListening() @@ -132,7 +131,6 @@ sealed class TetheringTileService : KillableTileService(), TetheringManager.Star error?.let { Toast.makeText(this, TetheringManager.tetherErrorMessage(it), Toast.LENGTH_LONG).show() } updateTile() } - override fun onTetherableInterfaceRegexpsChanged() = updateTile() class Wifi : TetheringTileService() { override val labelString get() = R.string.tethering_manage_wifi diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/TetherType.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/TetherType.kt index fa43bccd..f0842986 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/TetherType.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/TetherType.kt @@ -5,6 +5,7 @@ import androidx.annotation.RequiresApi import androidx.core.os.BuildCompat import be.mygod.vpnhotspot.App.Companion.app import be.mygod.vpnhotspot.R +import be.mygod.vpnhotspot.util.Event0 import java.util.regex.Pattern enum class TetherType { @@ -36,6 +37,9 @@ enum class TetherType { private val ethernetRegex: Pattern? private var requiresUpdate = true + @RequiresApi(30) // unused on lower APIs + val listener = Event0() + private fun Pair.getRegexs(name: String) = second .getStringArray(second.getIdentifier(name, "array", first)) .filterNotNull() @@ -56,6 +60,7 @@ enum class TetherType { @RequiresApi(30) override fun onTetherableInterfaceRegexpsChanged() { requiresUpdate = true + listener() } /**