diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientViewModel.kt b/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientViewModel.kt index a29271d2..53a848dd 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientViewModel.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/client/ClientViewModel.kt @@ -5,6 +5,9 @@ import android.content.IntentFilter import android.content.ServiceConnection import android.net.wifi.p2p.WifiP2pDevice import android.os.IBinder +import android.os.Parcelable +import androidx.annotation.RequiresApi +import androidx.core.os.BuildCompat import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.MutableLiveData @@ -13,13 +16,19 @@ import be.mygod.vpnhotspot.App.Companion.app import be.mygod.vpnhotspot.RepeaterService import be.mygod.vpnhotspot.net.IpNeighbour import be.mygod.vpnhotspot.net.MacAddressCompat +import be.mygod.vpnhotspot.net.MacAddressCompat.Companion.toCompat +import be.mygod.vpnhotspot.net.TetherType import be.mygod.vpnhotspot.net.TetheringManager import be.mygod.vpnhotspot.net.TetheringManager.localOnlyTetheredIfaces import be.mygod.vpnhotspot.net.TetheringManager.tetheredIfaces import be.mygod.vpnhotspot.net.monitor.IpNeighbourMonitor +import be.mygod.vpnhotspot.net.wifi.WifiApManager +import be.mygod.vpnhotspot.net.wifi.WifiClient +import be.mygod.vpnhotspot.root.WifiApCommands import be.mygod.vpnhotspot.util.broadcastReceiver -class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callback, DefaultLifecycleObserver { +class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callback, DefaultLifecycleObserver, + WifiApManager.SoftApCallbackCompat { private var tetheredInterfaces = emptySet() private val receiver = broadcastReceiver { _, intent -> tetheredInterfaces = (intent.tetheredIfaces ?: return@broadcastReceiver).toSet() + @@ -29,6 +38,7 @@ class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callb private var repeater: RepeaterService.Binder? = null private var p2p: Collection = emptyList() + private var wifiAp = emptyList>() private var neighbours: Collection = emptyList() val clients = MutableLiveData>() val fullMode = object : DefaultLifecycleObserver { @@ -42,11 +52,18 @@ class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callb private fun populateClients() { val clients = HashMap, Client>() - val group = repeater?.group - val p2pInterface = group?.`interface` - if (p2pInterface != null) { - for (client in p2p) clients[p2pInterface to MacAddressCompat.fromString(client.deviceAddress)] = - WifiP2pClient(p2pInterface, client) + repeater?.group?.`interface`?.let { p2pInterface -> + for (client in p2p) { + val addr = MacAddressCompat.fromString(client.deviceAddress!!) + clients[p2pInterface to addr] = object : Client(addr, p2pInterface) { + override val icon: Int get() = TetherType.WIFI_P2P.icon + } + } + } + for (client in wifiAp) { + clients[client] = object : Client(client.second, client.first) { + override val icon: Int get() = TetherType.WIFI.icon + } } for (neighbour in neighbours) { val key = neighbour.dev to neighbour.lladdr @@ -70,8 +87,10 @@ class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callb override fun onStart(owner: LifecycleOwner) { app.registerReceiver(receiver, IntentFilter(TetheringManager.ACTION_TETHER_STATE_CHANGED)) IpNeighbourMonitor.registerCallback(this, false) + if (BuildCompat.isAtLeastS()) WifiApCommands.registerSoftApCallback(this) } override fun onStop(owner: LifecycleOwner) { + if (BuildCompat.isAtLeastS()) WifiApCommands.unregisterSoftApCallback(this) IpNeighbourMonitor.unregisterCallback(this) app.unregisterReceiver(receiver) } @@ -94,4 +113,12 @@ class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callb this.neighbours = neighbours populateClients() } + + @RequiresApi(31) + override fun onConnectedClientsChanged(clients: List) { + wifiAp = clients.mapNotNull { + val client = WifiClient(it) + client.apInstanceIdentifier?.run { this to client.macAddress.toCompat() } + } + } } diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/client/WifiP2pClient.kt b/mobile/src/main/java/be/mygod/vpnhotspot/client/WifiP2pClient.kt deleted file mode 100644 index fa805954..00000000 --- a/mobile/src/main/java/be/mygod/vpnhotspot/client/WifiP2pClient.kt +++ /dev/null @@ -1,10 +0,0 @@ -package be.mygod.vpnhotspot.client - -import android.net.wifi.p2p.WifiP2pDevice -import be.mygod.vpnhotspot.net.MacAddressCompat -import be.mygod.vpnhotspot.net.TetherType - -class WifiP2pClient(p2pInterface: String, p2p: WifiP2pDevice) : - Client(MacAddressCompat.fromString(p2p.deviceAddress!!), p2pInterface) { - override val icon: Int get() = TetherType.WIFI_P2P.icon -} diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApManager.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApManager.kt index 60e2d157..707fa807 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApManager.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApManager.kt @@ -88,10 +88,7 @@ object WifiApManager { * @param clients the currently connected clients */ @RequiresApi(30) - fun onConnectedClientsChanged(clients: List) { - @Suppress("DEPRECATION") - onNumClientsChanged(clients.size) - } + fun onConnectedClientsChanged(clients: List) = onNumClientsChanged(clients.size) /** * Called when information of softap changes. diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/root/WifiApCommands.kt b/mobile/src/main/java/be/mygod/vpnhotspot/root/WifiApCommands.kt index b51a9eb6..bea331cd 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/root/WifiApCommands.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/root/WifiApCommands.kt @@ -25,7 +25,6 @@ object WifiApCommands { } @Parcelize data class OnNumClientsChanged(val numClients: Int) : SoftApCallbackParcel() { - @Suppress("DEPRECATION") override fun dispatch(callback: WifiApManager.SoftApCallbackCompat) = callback.onNumClientsChanged(numClients) } @@ -121,7 +120,7 @@ object WifiApCommands { is SoftApCallbackParcel.OnInfoChanged -> synchronized(callbacks) { lastCallback.info = parcel } is SoftApCallbackParcel.OnCapabilityChanged -> synchronized(callbacks) { lastCallback.capability = parcel } } - for (callback in synchronized(callbacks) { callbacks }) parcel.dispatch(callback) + for (callback in synchronized(callbacks) { callbacks.toList() }) parcel.dispatch(callback) } @RequiresApi(28) fun registerSoftApCallback(callback: WifiApManager.SoftApCallbackCompat) = synchronized(callbacks) { @@ -137,8 +136,8 @@ object WifiApCommands { SmartSnackbar.make(e).show() } } - lastCallback - } else null + null + } else lastCallback }?.toSequence()?.forEach { it?.dispatch(callback) } @RequiresApi(28) fun unregisterSoftApCallback(callback: WifiApManager.SoftApCallbackCompat) = synchronized(callbacks) {