Support new fields in SoftApInfo

This commit is contained in:
Mygod
2021-05-26 20:56:44 -04:00
parent a69d635f93
commit 50de5a269c
7 changed files with 123 additions and 25 deletions

View File

@@ -154,6 +154,7 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
* (since API 30) `Landroid/net/ConnectivityModuleConnector;->IN_PROCESS_SUFFIX:Ljava/lang/String;` * (since API 30) `Landroid/net/ConnectivityModuleConnector;->IN_PROCESS_SUFFIX:Ljava/lang/String;`
* (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`
* (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`
@@ -176,6 +177,7 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
* (since API 30) `Lcom/android/server/wifi/WifiContext;->ACTION_RESOURCES_APK:Ljava/lang/String;` * (since API 30) `Lcom/android/server/wifi/WifiContext;->ACTION_RESOURCES_APK:Ljava/lang/String;`
* (since API 29) `Lcom/android/server/wifi/p2p/WifiP2pServiceImpl;->ANONYMIZED_DEVICE_ADDRESS:Ljava/lang/String;` * (since API 29) `Lcom/android/server/wifi/p2p/WifiP2pServiceImpl;->ANONYMIZED_DEVICE_ADDRESS:Ljava/lang/String;`
* (since API 30) `Lcom/android/server/SystemServer;->TETHERING_CONNECTOR_CLASS:Ljava/lang/String;` * (since API 30) `Lcom/android/server/SystemServer;->TETHERING_CONNECTOR_CLASS:Ljava/lang/String;`
* (since API 31) `Ldalvik/system/VMDebug;->allowHiddenApiReflectionFrom(Ljava/lang/Class;)V,unsupported`
* (since API 26) `Ljava/lang/invoke/MethodHandles$Lookup;-><init>(Ljava/lang/Class;I)V,unsupported` * (since API 26) `Ljava/lang/invoke/MethodHandles$Lookup;-><init>(Ljava/lang/Class;I)V,unsupported`
* (since API 26) `Ljava/lang/invoke/MethodHandles$Lookup;->ALL_MODES:I,lo-prio,max-target-o` * (since API 26) `Ljava/lang/invoke/MethodHandles$Lookup;->ALL_MODES:I,lo-prio,max-target-o`
* (prior to API 29) `Ljava/net/InetAddress;->parseNumericAddress(Ljava/lang/String;)Ljava/net/InetAddress;,core-platform-api,max-target-p` * (prior to API 29) `Ljava/net/InetAddress;->parseNumericAddress(Ljava/lang/String;)Ljava/net/InetAddress;,core-platform-api,max-target-p`
@@ -256,8 +258,11 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->isClientControlByUserEnabled()Z,sdk,system-api,test-api` * (since API 30) `Landroid/net/wifi/SoftApConfiguration;->isClientControlByUserEnabled()Z,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApInfo;->CHANNEL_WIDTH_*:I,sdk,system-api,test-api` * (since API 30) `Landroid/net/wifi/SoftApInfo;->CHANNEL_WIDTH_*:I,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApInfo;->CHANNEL_WIDTH_INVALID:I,sdk,system-api,test-api` * (since API 30) `Landroid/net/wifi/SoftApInfo;->CHANNEL_WIDTH_INVALID:I,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApInfo;->getAutoShutdownTimeoutMillis()J,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApInfo;->getBssid()Landroid/net/MacAddress;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApInfo;->getBandwidth()I,system-api,whitelist` * (since API 30) `Landroid/net/wifi/SoftApInfo;->getBandwidth()I,system-api,whitelist`
* (since API 30) `Landroid/net/wifi/SoftApInfo;->getFrequency()I,system-api,whitelist` * (since API 30) `Landroid/net/wifi/SoftApInfo;->getFrequency()I,system-api,whitelist`
* (since API 31) `Landroid/net/wifi/SoftApInfo;->getWifiStandard()I,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/WifiClient;->getMacAddress()Landroid/net/MacAddress;,sdk,system-api,test-api` * (since API 30) `Landroid/net/wifi/WifiClient;->getMacAddress()Landroid/net/MacAddress;,sdk,system-api,test-api`
* (prior to API 30) `Landroid/net/wifi/WifiConfiguration$KeyMgmt;->WPA2_PSK:I,sdk,system-api,test-api` * (prior to API 30) `Landroid/net/wifi/WifiConfiguration$KeyMgmt;->WPA2_PSK:I,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/WifiManager$SoftApCallback;->onBlockedClientConnecting(Landroid/net/wifi/WifiClient;I)V,sdk,system-api,test-api` * (since API 30) `Landroid/net/wifi/WifiManager$SoftApCallback;->onBlockedClientConnecting(Landroid/net/wifi/WifiClient;I)V,sdk,system-api,test-api`

View File

@@ -10,6 +10,8 @@ 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
import android.text.SpannableStringBuilder
import android.text.format.DateUtils
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
@@ -29,6 +31,9 @@ import be.mygod.vpnhotspot.net.wifi.SoftApConfigurationCompat
import be.mygod.vpnhotspot.net.wifi.SoftApInfo import be.mygod.vpnhotspot.net.wifi.SoftApInfo
import be.mygod.vpnhotspot.net.wifi.WifiApManager 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.joinToSpanned
import be.mygod.vpnhotspot.util.makeMacSpan
import be.mygod.vpnhotspot.util.readableMessage import be.mygod.vpnhotspot.util.readableMessage
import be.mygod.vpnhotspot.widget.SmartSnackbar import be.mygod.vpnhotspot.widget.SmartSnackbar
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -188,28 +193,40 @@ sealed class TetherManager(protected val parent: TetheringFragment) : Manager(),
override val title get() = parent.getString(R.string.tethering_manage_wifi) override val title get() = parent.getString(R.string.tethering_manage_wifi)
override val tetherType get() = TetherType.WIFI override val tetherType get() = TetherType.WIFI
override val type get() = VIEW_TYPE_WIFI override val type get() = VIEW_TYPE_WIFI
override val text get() = listOfNotNull(failureReason?.let { WifiApManager.failureReasonLookup(it) }, baseError, override val text get() = parent.resources.configuration.locale.let { locale ->
info.run { listOfNotNull(failureReason?.let { WifiApManager.failureReasonLookup(it) }, baseError, info.run {
if (isEmpty()) null else joinToString("\n") @TargetApi(30) { if (isEmpty()) null else joinToSpanned("\n") @TargetApi(30) { parcel ->
val info = SoftApInfo(it) val info = SoftApInfo(parcel)
val frequency = info.frequency val frequency = info.frequency
parent.getString(R.string.tethering_manage_wifi_info, frequency, val channel = SoftApConfigurationCompat.frequencyToChannel(frequency)
SoftApConfigurationCompat.frequencyToChannel(frequency), val bandwidth = SoftApInfo.channelWidthLookup(info.bandwidth, true)
SoftApInfo.channelWidthLookup(info.bandwidth, true)) if (BuildCompat.isAtLeastS()) {
} var bssid = makeMacSpan(info.bssid.toString())
}, info.apInstanceIdentifier?.let { // take the fast route if possible
capability?.let { (maxSupportedClients, supportedFeatures) -> bssid = if (bssid is String) "$bssid%$it" else SpannableStringBuilder(bssid).append("%$it")
app.resources.getQuantityString(R.plurals.tethering_manage_wifi_capabilities, maxSupportedClients,
numClients ?: "?", maxSupportedClients, sequence {
var features = supportedFeatures
if (features == 0L) yield(parent.getString(R.string.tethering_manage_wifi_no_features))
else while (features != 0L) {
val bit = features.takeLowestOneBit()
yield(WifiApManager.featureLookup(bit, true))
features = features and bit.inv()
} }
}.joinToString()) val timeout = info.autoShutdownTimeoutMillis
}).joinToString("\n") parent.getText(if (timeout == 0L) {
R.string.tethering_manage_wifi_info_timeout_disabled
} else R.string.tethering_manage_wifi_info_timeout_enabled).format(locale,
frequency, channel, bandwidth, bssid, info.wifiStandard,
// http://unicode.org/cldr/trac/ticket/3407
DateUtils.formatElapsedTime(timeout / 1000))
} else parent.getText(R.string.tethering_manage_wifi_info).format(locale,
frequency, channel, bandwidth)
}
}, capability?.let { (maxSupportedClients, supportedFeatures) ->
app.resources.getQuantityText(R.plurals.tethering_manage_wifi_capabilities,
maxSupportedClients).format(locale, numClients ?: "?", maxSupportedClients, sequence {
var features = supportedFeatures
if (features != 0L) while (features != 0L) {
val bit = features.takeLowestOneBit()
yield(WifiApManager.featureLookup(bit, true))
features = features and bit.inv()
} else yield(parent.getText(R.string.tethering_manage_wifi_no_features))
}.joinToSpanned())
}).joinToSpanned("\n")
}
override fun start() = TetheringManager.startTethering(TetheringManager.TETHERING_WIFI, true, this) override fun start() = TetheringManager.startTethering(TetheringManager.TETHERING_WIFI, true, this)
override fun stop() = TetheringManager.stopTethering(TetheringManager.TETHERING_WIFI, this::onException) override fun stop() = TetheringManager.stopTethering(TetheringManager.TETHERING_WIFI, this::onException)

View File

@@ -1,20 +1,47 @@
package be.mygod.vpnhotspot.net.wifi package be.mygod.vpnhotspot.net.wifi
import android.annotation.TargetApi
import android.net.MacAddress
import android.os.Parcelable import android.os.Parcelable
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import be.mygod.vpnhotspot.util.ConstantLookup import be.mygod.vpnhotspot.util.ConstantLookup
import be.mygod.vpnhotspot.util.UnblockCentral
import timber.log.Timber
@JvmInline @JvmInline
@RequiresApi(30) @RequiresApi(30)
value class SoftApInfo(val inner: Parcelable) { value class SoftApInfo(val inner: Parcelable) {
companion object { companion object {
private val classSoftApInfo by lazy { Class.forName("android.net.wifi.SoftApInfo") } private val clazz by lazy { Class.forName("android.net.wifi.SoftApInfo") }
private val getFrequency by lazy { classSoftApInfo.getDeclaredMethod("getFrequency") } private val getFrequency by lazy { clazz.getDeclaredMethod("getFrequency") }
private val getBandwidth by lazy { classSoftApInfo.getDeclaredMethod("getBandwidth") } private val getBandwidth by lazy { clazz.getDeclaredMethod("getBandwidth") }
@get:RequiresApi(31)
private val getBssid by lazy { clazz.getDeclaredMethod("getBssid") }
@get:RequiresApi(31)
private val getWifiStandard by lazy { clazz.getDeclaredMethod("getWifiStandard") }
@get:RequiresApi(31)
private val getApInstanceIdentifier by lazy @TargetApi(31) {
UnblockCentral.SoftApInfo_getApInstanceIdentifier(clazz)
}
@get:RequiresApi(31)
private val getAutoShutdownTimeoutMillis by lazy { clazz.getDeclaredMethod("getAutoShutdownTimeoutMillis") }
val channelWidthLookup = ConstantLookup("CHANNEL_WIDTH_") { classSoftApInfo } val channelWidthLookup = ConstantLookup("CHANNEL_WIDTH_") { clazz }
} }
val frequency get() = getFrequency.invoke(inner) as Int val frequency get() = getFrequency.invoke(inner) as Int
val bandwidth get() = getBandwidth.invoke(inner) as Int val bandwidth get() = getBandwidth.invoke(inner) as Int
@get:RequiresApi(31)
val bssid get() = getBssid.invoke(inner) as MacAddress
@get:RequiresApi(31)
val wifiStandard get() = getWifiStandard.invoke(inner) as Int
@get:RequiresApi(31)
val apInstanceIdentifier get() = try {
getApInstanceIdentifier.invoke(inner) as? String
} catch (e: ReflectiveOperationException) {
Timber.w(e)
null
}
@get:RequiresApi(31)
val autoShutdownTimeoutMillis get() = getAutoShutdownTimeoutMillis.invoke(inner) as Long
} }

View File

@@ -0,0 +1,32 @@
package be.mygod.vpnhotspot.util
import android.annotation.SuppressLint
import androidx.annotation.RequiresApi
import timber.log.Timber
/**
* The central object for accessing all the useful blocked APIs. Thanks Google!
*/
@SuppressLint("DiscouragedPrivateApi")
@Suppress("FunctionName")
object UnblockCentral {
/**
* Retrieve this property before doing dangerous shit.
*/
@get:RequiresApi(28)
private val init by lazy {
try {
Class.forName("dalvik.system.VMDebug").getDeclaredMethod("allowHiddenApiReflectionFrom", Class::class.java)
.invoke(null, UnblockCentral::class.java)
true
} catch (e: ReflectiveOperationException) {
Timber.w(e)
false
}
}
@RequiresApi(31)
fun SoftApInfo_getApInstanceIdentifier(clazz: Class<*>) = init.let {
clazz.getDeclaredMethod("getApInstanceIdentifier")
}
}

View File

@@ -126,6 +126,15 @@ fun CharSequence.format(locale: Locale, vararg args: Any) = SpannableStringBuild
} }
} }
fun <T> Iterable<T>.joinToSpanned(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "",
limit: Int = -1, truncated: CharSequence = "...",
transform: ((T) -> CharSequence)? = null) =
joinTo(SpannableStringBuilder(), separator, prefix, postfix, limit, truncated, transform)
fun <T> Sequence<T>.joinToSpanned(separator: CharSequence = ", ", prefix: CharSequence = "", postfix: CharSequence = "",
limit: Int = -1, truncated: CharSequence = "...",
transform: ((T) -> CharSequence)? = null) =
joinTo(SpannableStringBuilder(), separator, prefix, postfix, limit, truncated, transform)
fun makeIpSpan(ip: InetAddress) = ip.hostAddress.let { fun makeIpSpan(ip: InetAddress) = ip.hostAddress.let {
// exclude all bogon IP addresses supported by Android APIs // exclude all bogon IP addresses supported by Android APIs
if (!app.hasTouch || ip.isMulticastAddress || ip.isAnyLocalAddress || ip.isLoopbackAddress || if (!app.hasTouch || ip.isMulticastAddress || ip.isAnyLocalAddress || ip.isLoopbackAddress ||

View File

@@ -59,6 +59,10 @@
<string name="tethering_manage_ncm">USB 网络共享 (NCM)</string> <string name="tethering_manage_ncm">USB 网络共享 (NCM)</string>
<string name="tethering_manage_wigig">WiGig 热点</string> <string name="tethering_manage_wigig">WiGig 热点</string>
<string name="tethering_manage_wifi_info">%1$d MHz, 频道 %2$d, 频宽 %3$s</string> <string name="tethering_manage_wifi_info">%1$d MHz, 频道 %2$d, 频宽 %3$s</string>
<string name="tethering_manage_wifi_info_timeout_enabled">%4$s: Wi\u2011Fi %5$d, %1$d MHz, 频道 %2$d, 频宽 %3$s,
关闭延迟 %6$s</string>
<string name="tethering_manage_wifi_info_timeout_disabled">%4$s: Wi\u2011Fi %5$d, %1$d MHz, 频道 %2$d, 频宽 %3$s,
不自动关闭</string>
<plurals name="tethering_manage_wifi_capabilities"> <plurals name="tethering_manage_wifi_capabilities">
<item quantity="other">已连接 %1$s/%2$d 个设备\n支持功能%3$s</item> <item quantity="other">已连接 %1$s/%2$d 个设备\n支持功能%3$s</item>
</plurals> </plurals>

View File

@@ -70,6 +70,10 @@
<string name="tethering_manage_ncm">USB tethering (NCM)</string> <string name="tethering_manage_ncm">USB tethering (NCM)</string>
<string name="tethering_manage_wigig">WiGig hotspot</string> <string name="tethering_manage_wigig">WiGig hotspot</string>
<string name="tethering_manage_wifi_info">%1$d MHz, channel %2$d, width %3$s</string> <string name="tethering_manage_wifi_info">%1$d MHz, channel %2$d, width %3$s</string>
<string name="tethering_manage_wifi_info_timeout_enabled">%4$s: Wi\u2011Fi %5$d, %1$d MHz, channel %2$d,
width %3$s, idle timeout in %6$s</string>
<string name="tethering_manage_wifi_info_timeout_disabled">%4$s: Wi\u2011Fi %5$d, %1$d MHz, channel %2$d,
width %3$s, idle timeout disabled</string>
<plurals name="tethering_manage_wifi_capabilities"> <plurals name="tethering_manage_wifi_capabilities">
<item quantity="one">%1$s/%2$d client connected\nSupported features: %3$s</item> <item quantity="one">%1$s/%2$d client connected\nSupported features: %3$s</item>
<item quantity="other">%1$s/%2$d clients connected\nSupported features: %3$s</item> <item quantity="other">%1$s/%2$d clients connected\nSupported features: %3$s</item>