diff --git a/README.md b/README.md index 1aca42ab..f9ba8375 100644 --- a/README.md +++ b/README.md @@ -299,6 +299,7 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded * (since API 28) `Landroid/net/wifi/WifiManager;->WIFI_AP_STATE_FAILED:I,sdk,system-api,test-api` * (since API 30) `Landroid/net/wifi/WifiManager;->getSoftApConfiguration()Landroid/net/wifi/SoftApConfiguration;,sdk,system-api,test-api` * (prior to API 30) `Landroid/net/wifi/WifiManager;->getWifiApConfiguration()Landroid/net/wifi/WifiConfiguration;,sdk,system-api,test-api` +* (since API 30) `Landroid/net/wifi/WifiManager;->isApMacRandomizationSupported()Z,sdk,system-api,test-api` * (since API 28) `Landroid/net/wifi/WifiManager;->registerSoftApCallback(Ljava/util/concurrent/Executor;Landroid/net/wifi/WifiManager$SoftApCallback;)V,sdk,system-api,test-api` * (since API 30) `Landroid/net/wifi/WifiManager;->setSoftApConfiguration(Landroid/net/wifi/SoftApConfiguration;)Z,sdk,system-api,test-api` * (prior to API 30) `Landroid/net/wifi/WifiManager;->setWifiApConfiguration(Landroid/net/wifi/WifiConfiguration;)Z,sdk,system-api,test-api` diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherManager.kt b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherManager.kt index d7c8b491..3bb8b282 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherManager.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/manage/TetherManager.kt @@ -28,10 +28,7 @@ import be.mygod.vpnhotspot.net.TetherType import be.mygod.vpnhotspot.net.TetheringManager import be.mygod.vpnhotspot.net.wifi.* 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.* import be.mygod.vpnhotspot.widget.SmartSnackbar import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.GlobalScope @@ -203,7 +200,7 @@ sealed class TetherManager(protected val parent: TetheringFragment) : Manager(), val capability = SoftApCapability(parcel) val numClients = numClients val maxClients = capability.maxSupportedClients - var supportedFeatures = capability.supportedFeatures + var features = capability.supportedFeatures if (BuildCompat.isAtLeastS()) for ((flag, band) in arrayOf( SoftApCapability.SOFTAP_FEATURE_BAND_24G_SUPPORTED to SoftApConfigurationCompat.BAND_2GHZ, SoftApCapability.SOFTAP_FEATURE_BAND_5G_SUPPORTED to SoftApConfigurationCompat.BAND_5GHZ, @@ -212,17 +209,28 @@ sealed class TetherManager(protected val parent: TetheringFragment) : Manager(), )) { if (capability.getSupportedChannelList(band).isEmpty()) continue // reduce double reporting - supportedFeatures = supportedFeatures and flag.inv() + features = features and flag.inv() } val result = parent.resources.getQuantityText(R.plurals.tethering_manage_wifi_capabilities, numClients ?: 0) .format(locale, numClients ?: "?", maxClients, sequence { - var features = supportedFeatures + if (WifiApManager.isApMacRandomizationSupported) yield(parent.getText( + R.string.tethering_manage_wifi_feature_ap_mac_randomization)) + if (Services.wifi.isStaApConcurrencySupported) yield(parent.getText( + R.string.tethering_manage_wifi_feature_sta_ap_concurrency)) + if (BuildCompat.isAtLeastS()) { + if (Services.wifi.isBridgedApConcurrencySupported) yield(parent.getText( + R.string.tethering_manage_wifi_feature_bridged_ap_concurrency)) + if (Services.wifi.isStaBridgedApConcurrencySupported) yield(parent.getText( + R.string.tethering_manage_wifi_feature_sta_bridged_ap_concurrency)) + } if (features != 0L) while (features != 0L) { val bit = features.takeLowestOneBit() yield(SoftApCapability.featureLookup(bit, true)) features = features and bit.inv() - } else yield(parent.getText(R.string.tethering_manage_wifi_no_features)) - }.joinToSpanned()) + } + }.joinToSpanned().let { + if (it.isEmpty()) parent.getText(R.string.tethering_manage_wifi_no_features) else it + }) if (BuildCompat.isAtLeastS()) { val list = SoftApConfigurationCompat.BAND_TYPES.map { band -> val channels = capability.getSupportedChannelList(band) 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 81217656..b3ef3aa2 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 @@ -52,6 +52,13 @@ object WifiApManager { else -> false } + @get:RequiresApi(30) + private val apMacRandomizationSupported by lazy { + WifiManager::class.java.getDeclaredMethod("isApMacRandomizationSupported") + } + @get:RequiresApi(30) + val isApMacRandomizationSupported get() = apMacRandomizationSupported(Services.wifi) as Boolean + private val getWifiApConfiguration by lazy { WifiManager::class.java.getDeclaredMethod("getWifiApConfiguration") } @Suppress("DEPRECATION") private val setWifiApConfiguration by lazy { diff --git a/mobile/src/main/res/values-zh-rCN/strings.xml b/mobile/src/main/res/values-zh-rCN/strings.xml index f79491fc..69f3e8fc 100644 --- a/mobile/src/main/res/values-zh-rCN/strings.xml +++ b/mobile/src/main/res/values-zh-rCN/strings.xml @@ -70,6 +70,10 @@ 已连接 %d 个设备 \n支持频道: %s + 随机接入点 MAC + 桥接 AP 并发 + STA/AP 并发 + STA/桥接 AP 并发 已屏蔽 %1$s:%2$s 复制 MAC diff --git a/mobile/src/main/res/values/strings.xml b/mobile/src/main/res/values/strings.xml index 73ca4bb6..c4ce4b36 100644 --- a/mobile/src/main/res/values/strings.xml +++ b/mobile/src/main/res/values/strings.xml @@ -83,6 +83,10 @@ %1d clients connected \nSupported channels: %s + Randomized AP MAC + Bridged AP concurrency + STA + AP concurrency + STA + Bridged AP concurrency None Blocked %1$s: %2$s Copy MAC