Support ap identifier for WifiClient

This commit is contained in:
Mygod
2021-05-26 21:52:43 -04:00
parent 168c9ff6f1
commit ea076d9602
7 changed files with 59 additions and 35 deletions

View File

@@ -155,6 +155,7 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
* (since API 30) `Landroid/net/TetheringManager$TetheringEventCallback;->onTetherableInterfaceRegexpsChanged(Landroid/net/TetheringManager$TetheringInterfaceRegexps;)V,blocked` * (since API 30) `Landroid/net/TetheringManager$TetheringEventCallback;->onTetherableInterfaceRegexpsChanged(Landroid/net/TetheringManager$TetheringInterfaceRegexps;)V,blocked`
* (since API 30) `Landroid/net/TetheringManager;->TETHERING_WIGIG:I,blocked` * (since API 30) `Landroid/net/TetheringManager;->TETHERING_WIGIG:I,blocked`
* (since API 31) `Landroid/net/wifi/SoftApInfo;->getApInstanceIdentifier()Ljava/lang/String;,blocked` * (since API 31) `Landroid/net/wifi/SoftApInfo;->getApInstanceIdentifier()Ljava/lang/String;,blocked`
* (since API 31) `Landroid/net/wifi/WifiClient;->getApInstanceIdentifier()Ljava/lang/String;,blocked`
* (prior to API 30) `Landroid/net/wifi/WifiConfiguration$KeyMgmt;->FT_PSK:I,lo-prio,max-target-o` * (prior to API 30) `Landroid/net/wifi/WifiConfiguration$KeyMgmt;->FT_PSK:I,lo-prio,max-target-o`
* (prior to API 30) `Landroid/net/wifi/WifiConfiguration$KeyMgmt;->WPA_PSK_SHA256:I,blocked` * (prior to API 30) `Landroid/net/wifi/WifiConfiguration$KeyMgmt;->WPA_PSK_SHA256:I,blocked`
* (since API 23, prior to API 30) `Landroid/net/wifi/WifiConfiguration;->AP_BAND_2GHZ:I,lo-prio,max-target-o` * (since API 23, prior to API 30) `Landroid/net/wifi/WifiConfiguration;->AP_BAND_2GHZ:I,lo-prio,max-target-o`

View File

@@ -6,7 +6,6 @@ import android.content.ClipData
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.MacAddress
import android.os.Build import android.os.Build
import android.os.Parcelable import android.os.Parcelable
import android.provider.Settings import android.provider.Settings
@@ -27,10 +26,7 @@ import be.mygod.vpnhotspot.R
import be.mygod.vpnhotspot.databinding.ListitemInterfaceBinding import be.mygod.vpnhotspot.databinding.ListitemInterfaceBinding
import be.mygod.vpnhotspot.net.TetherType import be.mygod.vpnhotspot.net.TetherType
import be.mygod.vpnhotspot.net.TetheringManager import be.mygod.vpnhotspot.net.TetheringManager
import be.mygod.vpnhotspot.net.wifi.SoftApCapability import be.mygod.vpnhotspot.net.wifi.*
import be.mygod.vpnhotspot.net.wifi.SoftApConfigurationCompat
import be.mygod.vpnhotspot.net.wifi.SoftApInfo
import be.mygod.vpnhotspot.net.wifi.WifiApManager
import be.mygod.vpnhotspot.root.WifiApCommands import be.mygod.vpnhotspot.root.WifiApCommands
import be.mygod.vpnhotspot.util.format import be.mygod.vpnhotspot.util.format
import be.mygod.vpnhotspot.util.joinToSpanned import be.mygod.vpnhotspot.util.joinToSpanned
@@ -182,12 +178,18 @@ sealed class TetherManager(protected val parent: TetheringFragment) : Manager(),
this.capability = capability this.capability = capability
data.notifyChange() data.notifyChange()
} }
override fun onBlockedClientConnecting(client: MacAddress, blockedReason: Int) { @RequiresApi(30)
override fun onBlockedClientConnecting(client: Parcelable, blockedReason: Int) {
@Suppress("NAME_SHADOWING")
val client = WifiClient(client)
val macAddress = client.macAddress
var name = macAddress.toString()
if (BuildCompat.isAtLeastS()) client.apInstanceIdentifier?.let { name += "%$it" }
val reason = WifiApManager.clientBlockLookup(blockedReason, true) val reason = WifiApManager.clientBlockLookup(blockedReason, true)
Timber.i("$client blocked from connecting: $reason ($blockedReason)") Timber.i("$name blocked from connecting: $reason ($blockedReason)")
SmartSnackbar.make(parent.getString(R.string.tethering_manage_wifi_client_blocked, client, reason)).apply { SmartSnackbar.make(parent.getString(R.string.tethering_manage_wifi_client_blocked, name, reason)).apply {
action(R.string.tethering_manage_wifi_copy_mac) { action(R.string.tethering_manage_wifi_copy_mac) {
app.clipboard.setPrimaryClip(ClipData.newPlainText(null, client.toString())) app.clipboard.setPrimaryClip(ClipData.newPlainText(null, macAddress.toString()))
} }
}.show() }.show()
} }

View File

@@ -20,28 +20,26 @@ value class SoftApInfo(val inner: Parcelable) {
@get:RequiresApi(31) @get:RequiresApi(31)
private val getWifiStandard by lazy { clazz.getDeclaredMethod("getWifiStandard") } private val getWifiStandard by lazy { clazz.getDeclaredMethod("getWifiStandard") }
@get:RequiresApi(31) @get:RequiresApi(31)
private val getApInstanceIdentifier by lazy @TargetApi(31) { private val getApInstanceIdentifier by lazy @TargetApi(31) { UnblockCentral.getApInstanceIdentifier(clazz) }
UnblockCentral.SoftApInfo_getApInstanceIdentifier(clazz)
}
@get:RequiresApi(31) @get:RequiresApi(31)
private val getAutoShutdownTimeoutMillis by lazy { clazz.getDeclaredMethod("getAutoShutdownTimeoutMillis") } private val getAutoShutdownTimeoutMillis by lazy { clazz.getDeclaredMethod("getAutoShutdownTimeoutMillis") }
val channelWidthLookup = ConstantLookup("CHANNEL_WIDTH_") { clazz } val channelWidthLookup = ConstantLookup("CHANNEL_WIDTH_") { clazz }
} }
val frequency get() = getFrequency.invoke(inner) as Int val frequency get() = getFrequency(inner) as Int
val bandwidth get() = getBandwidth.invoke(inner) as Int val bandwidth get() = getBandwidth(inner) as Int
@get:RequiresApi(31) @get:RequiresApi(31)
val bssid get() = getBssid.invoke(inner) as MacAddress val bssid get() = getBssid(inner) as MacAddress
@get:RequiresApi(31) @get:RequiresApi(31)
val wifiStandard get() = getWifiStandard.invoke(inner) as Int val wifiStandard get() = getWifiStandard(inner) as Int
@get:RequiresApi(31) @get:RequiresApi(31)
val apInstanceIdentifier get() = try { val apInstanceIdentifier get() = try {
getApInstanceIdentifier.invoke(inner) as? String getApInstanceIdentifier(inner) as? String
} catch (e: ReflectiveOperationException) { } catch (e: ReflectiveOperationException) {
Timber.w(e) Timber.w(e)
null null
} }
@get:RequiresApi(31) @get:RequiresApi(31)
val autoShutdownTimeoutMillis get() = getAutoShutdownTimeoutMillis.invoke(inner) as Long val autoShutdownTimeoutMillis get() = getAutoShutdownTimeoutMillis(inner) as Long
} }

View File

@@ -81,7 +81,7 @@ object WifiApManager {
fun onNumClientsChanged(numClients: Int) { } fun onNumClientsChanged(numClients: Int) { }
@RequiresApi(30) @RequiresApi(30)
fun onConnectedClientsChanged(clients: List<MacAddress>) { fun onConnectedClientsChanged(clients: List<Parcelable>) {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
onNumClientsChanged(clients.size) onNumClientsChanged(clients.size)
} }
@@ -93,7 +93,7 @@ object WifiApManager {
fun onCapabilityChanged(capability: Parcelable) { } fun onCapabilityChanged(capability: Parcelable) { }
@RequiresApi(30) @RequiresApi(30)
fun onBlockedClientConnecting(client: MacAddress, blockedReason: Int) { } fun onBlockedClientConnecting(client: Parcelable, blockedReason: Int) { }
} }
@RequiresApi(28) @RequiresApi(28)
val failureReasonLookup = ConstantLookup<WifiManager>("SAP_START_FAILURE_", val failureReasonLookup = ConstantLookup<WifiManager>("SAP_START_FAILURE_",
@@ -112,10 +112,6 @@ object WifiApManager {
WifiManager::class.java.getDeclaredMethod("unregisterSoftApCallback", interfaceSoftApCallback) WifiManager::class.java.getDeclaredMethod("unregisterSoftApCallback", interfaceSoftApCallback)
} }
private val getMacAddress by lazy {
Class.forName("android.net.wifi.WifiClient").getDeclaredMethod("getMacAddress")
}
@RequiresApi(28) @RequiresApi(28)
fun registerSoftApCallback(callback: SoftApCallbackCompat, executor: Executor): Any { fun registerSoftApCallback(callback: SoftApCallbackCompat, executor: Executor): Any {
val proxy = Proxy.newProxyInstance(interfaceSoftApCallback.classLoader, val proxy = Proxy.newProxyInstance(interfaceSoftApCallback.classLoader,
@@ -140,18 +136,19 @@ object WifiApManager {
} }
"onConnectedClientsChanged" -> @TargetApi(30) { "onConnectedClientsChanged" -> @TargetApi(30) {
if (Build.VERSION.SDK_INT < 30) Timber.w(Exception("Unexpected onConnectedClientsChanged")) if (Build.VERSION.SDK_INT < 30) Timber.w(Exception("Unexpected onConnectedClientsChanged"))
@Suppress("UNCHECKED_CAST")
callback.onConnectedClientsChanged(when (noArgs) { callback.onConnectedClientsChanged(when (noArgs) {
1 -> args!![0] as? Iterable<*> ?: return null 1 -> args!![0] as List<Parcelable>
2 -> { 2 -> {
Timber.w(Exception("Unexpected onConnectedClientsChanged API 31+")) Timber.w(Exception("Unexpected onConnectedClientsChanged API 31+"))
// dispatchInfoChanged(args!![0]) // dispatchInfoChanged(args!![0])
args!![1] as? Iterable<*> ?: return null args!![1] as List<Parcelable>
} }
else -> { else -> {
Timber.w("Unexpected args for $name: ${args?.contentToString()}") Timber.w("Unexpected args for $name: ${args?.contentToString()}")
return null return null
} }
}.map { getMacAddress(it) as MacAddress }) })
} }
"onInfoChanged" -> @TargetApi(30) { "onInfoChanged" -> @TargetApi(30) {
if (noArgs != 1) Timber.w("Unexpected args for $name: ${args?.contentToString()}") if (noArgs != 1) Timber.w("Unexpected args for $name: ${args?.contentToString()}")
@@ -179,7 +176,7 @@ object WifiApManager {
"onBlockedClientConnecting" -> @TargetApi(30) { "onBlockedClientConnecting" -> @TargetApi(30) {
if (Build.VERSION.SDK_INT < 30) Timber.w(Exception("Unexpected onBlockedClientConnecting")) if (Build.VERSION.SDK_INT < 30) Timber.w(Exception("Unexpected onBlockedClientConnecting"))
if (noArgs != 2) Timber.w("Unexpected args for $name: ${args?.contentToString()}") if (noArgs != 2) Timber.w("Unexpected args for $name: ${args?.contentToString()}")
callback.onBlockedClientConnecting(getMacAddress(args!![0]) as MacAddress, args[1] as Int) callback.onBlockedClientConnecting(args!![0] as Parcelable, args[1] as Int)
} }
else -> callSuper(interfaceSoftApCallback, proxy, method, args) else -> callSuper(interfaceSoftApCallback, proxy, method, args)
} }

View File

@@ -0,0 +1,28 @@
package be.mygod.vpnhotspot.net.wifi
import android.annotation.TargetApi
import android.net.MacAddress
import android.os.Parcelable
import androidx.annotation.RequiresApi
import be.mygod.vpnhotspot.util.UnblockCentral
import timber.log.Timber
@JvmInline
@RequiresApi(30)
value class WifiClient(val inner: Parcelable) {
companion object {
private val clazz by lazy { Class.forName("android.net.wifi.WifiClient") }
private val getMacAddress by lazy { clazz.getDeclaredMethod("getMacAddress") }
@get:RequiresApi(31)
private val getApInstanceIdentifier by lazy @TargetApi(31) { UnblockCentral.getApInstanceIdentifier(clazz) }
}
val macAddress get() = getMacAddress(inner) as MacAddress
@get:RequiresApi(31)
val apInstanceIdentifier get() = try {
getApInstanceIdentifier(inner) as? String
} catch (e: ReflectiveOperationException) {
Timber.w(e)
null
}
}

View File

@@ -32,7 +32,7 @@ object WifiApCommands {
} }
@Parcelize @Parcelize
@RequiresApi(30) @RequiresApi(30)
data class OnConnectedClientsChanged(val clients: List<MacAddress>) : SoftApCallbackParcel() { data class OnConnectedClientsChanged(val clients: List<Parcelable>) : SoftApCallbackParcel() {
override fun dispatch(callback: WifiApManager.SoftApCallbackCompat) = override fun dispatch(callback: WifiApManager.SoftApCallbackCompat) =
callback.onConnectedClientsChanged(clients) callback.onConnectedClientsChanged(clients)
} }
@@ -49,7 +49,7 @@ object WifiApCommands {
} }
@Parcelize @Parcelize
@RequiresApi(30) @RequiresApi(30)
data class OnBlockedClientConnecting(val client: MacAddress, val blockedReason: Int) : SoftApCallbackParcel() { data class OnBlockedClientConnecting(val client: Parcelable, val blockedReason: Int) : SoftApCallbackParcel() {
override fun dispatch(callback: WifiApManager.SoftApCallbackCompat) = override fun dispatch(callback: WifiApManager.SoftApCallbackCompat) =
callback.onBlockedClientConnecting(client, blockedReason) callback.onBlockedClientConnecting(client, blockedReason)
} }
@@ -73,7 +73,7 @@ object WifiApCommands {
override fun onNumClientsChanged(numClients: Int) = override fun onNumClientsChanged(numClients: Int) =
push(SoftApCallbackParcel.OnNumClientsChanged(numClients)) push(SoftApCallbackParcel.OnNumClientsChanged(numClients))
@RequiresApi(30) @RequiresApi(30)
override fun onConnectedClientsChanged(clients: List<MacAddress>) = override fun onConnectedClientsChanged(clients: List<Parcelable>) =
push(SoftApCallbackParcel.OnConnectedClientsChanged(clients)) push(SoftApCallbackParcel.OnConnectedClientsChanged(clients))
@RequiresApi(30) @RequiresApi(30)
override fun onInfoChanged(info: List<Parcelable>) = push(SoftApCallbackParcel.OnInfoChanged(info)) override fun onInfoChanged(info: List<Parcelable>) = push(SoftApCallbackParcel.OnInfoChanged(info))
@@ -81,7 +81,7 @@ object WifiApCommands {
override fun onCapabilityChanged(capability: Parcelable) = override fun onCapabilityChanged(capability: Parcelable) =
push(SoftApCallbackParcel.OnCapabilityChanged(capability)) push(SoftApCallbackParcel.OnCapabilityChanged(capability))
@RequiresApi(30) @RequiresApi(30)
override fun onBlockedClientConnecting(client: MacAddress, blockedReason: Int) = override fun onBlockedClientConnecting(client: Parcelable, blockedReason: Int) =
push(SoftApCallbackParcel.OnBlockedClientConnecting(client, blockedReason)) push(SoftApCallbackParcel.OnBlockedClientConnecting(client, blockedReason))
}) { }) {
scope.launch { scope.launch {

View File

@@ -26,7 +26,5 @@ object UnblockCentral {
} }
@RequiresApi(31) @RequiresApi(31)
fun SoftApInfo_getApInstanceIdentifier(clazz: Class<*>) = init.let { fun getApInstanceIdentifier(clazz: Class<*>) = init.let { clazz.getDeclaredMethod("getApInstanceIdentifier") }
clazz.getDeclaredMethod("getApInstanceIdentifier")
}
} }