Support reading AP clients from framework
This commit is contained in:
@@ -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<String>()
|
||||
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<WifiP2pDevice> = emptyList()
|
||||
private var wifiAp = emptyList<Pair<String, MacAddressCompat>>()
|
||||
private var neighbours: Collection<IpNeighbour> = emptyList()
|
||||
val clients = MutableLiveData<List<Client>>()
|
||||
val fullMode = object : DefaultLifecycleObserver {
|
||||
@@ -42,11 +52,18 @@ class ClientViewModel : ViewModel(), ServiceConnection, IpNeighbourMonitor.Callb
|
||||
|
||||
private fun populateClients() {
|
||||
val clients = HashMap<Pair<String, MacAddressCompat>, 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<Parcelable>) {
|
||||
wifiAp = clients.mapNotNull {
|
||||
val client = WifiClient(it)
|
||||
client.apInstanceIdentifier?.run { this to client.macAddress.toCompat() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -88,10 +88,7 @@ object WifiApManager {
|
||||
* @param clients the currently connected clients
|
||||
*/
|
||||
@RequiresApi(30)
|
||||
fun onConnectedClientsChanged(clients: List<Parcelable>) {
|
||||
@Suppress("DEPRECATION")
|
||||
onNumClientsChanged(clients.size)
|
||||
}
|
||||
fun onConnectedClientsChanged(clients: List<Parcelable>) = onNumClientsChanged(clients.size)
|
||||
|
||||
/**
|
||||
* Called when information of softap changes.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user