Support showing supported channels
This commit is contained in:
@@ -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/SoftApConfiguration;->BAND_TYPES:[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`
|
* (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`
|
||||||
@@ -228,9 +229,14 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
|
|||||||
* (since API 30) `Landroid/net/TetheringManager;->startTethering(Landroid/net/TetheringManager$TetheringRequest;Ljava/util/concurrent/Executor;Landroid/net/TetheringManager$StartTetheringCallback;)V,sdk,system-api,test-api`
|
* (since API 30) `Landroid/net/TetheringManager;->startTethering(Landroid/net/TetheringManager$TetheringRequest;Ljava/util/concurrent/Executor;Landroid/net/TetheringManager$StartTetheringCallback;)V,sdk,system-api,test-api`
|
||||||
* (since API 30) `Landroid/net/TetheringManager;->stopTethering(I)V,sdk,system-api,test-api`
|
* (since API 30) `Landroid/net/TetheringManager;->stopTethering(I)V,sdk,system-api,test-api`
|
||||||
* (since API 30) `Landroid/net/TetheringManager;->unregisterTetheringEventCallback(Landroid/net/TetheringManager$TetheringEventCallback;)V,sdk,system-api,test-api`
|
* (since API 30) `Landroid/net/TetheringManager;->unregisterTetheringEventCallback(Landroid/net/TetheringManager$TetheringEventCallback;)V,sdk,system-api,test-api`
|
||||||
|
* (since API 31) `Landroid/net/wifi/SoftApCapability;->SOFTAP_FEATURE_BAND_24G_SUPPORTED:J,sdk,system-api,test-api`
|
||||||
|
* (since API 31) `Landroid/net/wifi/SoftApCapability;->SOFTAP_FEATURE_BAND_5G_SUPPORTED:J,sdk,system-api,test-api`
|
||||||
|
* (since API 31) `Landroid/net/wifi/SoftApCapability;->SOFTAP_FEATURE_BAND_60G_SUPPORTED:J,sdk,system-api,test-api`
|
||||||
|
* (since API 31) `Landroid/net/wifi/SoftApCapability;->SOFTAP_FEATURE_BAND_6G_SUPPORTED:J,sdk,system-api,test-api`
|
||||||
* (since API 30) `Landroid/net/wifi/SoftApCapability;->SOFTAP_FEATURE_*:J,sdk,system-api,test-api`
|
* (since API 30) `Landroid/net/wifi/SoftApCapability;->SOFTAP_FEATURE_*:J,sdk,system-api,test-api`
|
||||||
* (since API 30) `Landroid/net/wifi/SoftApCapability;->areFeaturesSupported(J)Z,sdk,system-api,test-api`
|
* (since API 30) `Landroid/net/wifi/SoftApCapability;->areFeaturesSupported(J)Z,sdk,system-api,test-api`
|
||||||
* (since API 30) `Landroid/net/wifi/SoftApCapability;->getMaxSupportedClients()I,sdk,system-api,test-api`
|
* (since API 30) `Landroid/net/wifi/SoftApCapability;->getMaxSupportedClients()I,sdk,system-api,test-api`
|
||||||
|
* (since API 31) `Landroid/net/wifi/SoftApCapability;->getSupportedChannelList(I)[I,sdk,system-api,test-api`
|
||||||
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;-><init>()V,sdk,system-api,test-api`
|
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;-><init>()V,sdk,system-api,test-api`
|
||||||
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;-><init>(Landroid/net/wifi/SoftApConfiguration;)V,sdk,system-api,test-api`
|
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;-><init>(Landroid/net/wifi/SoftApConfiguration;)V,sdk,system-api,test-api`
|
||||||
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->build()Landroid/net/wifi/SoftApConfiguration;,sdk,system-api,test-api`
|
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->build()Landroid/net/wifi/SoftApConfiguration;,sdk,system-api,test-api`
|
||||||
|
|||||||
@@ -199,13 +199,23 @@ sealed class TetherManager(protected val parent: TetheringFragment) : Manager(),
|
|||||||
override val type get() = VIEW_TYPE_WIFI
|
override val type get() = VIEW_TYPE_WIFI
|
||||||
|
|
||||||
@TargetApi(30)
|
@TargetApi(30)
|
||||||
private fun formatCapability(locale: Locale) = capability?.let {
|
private fun formatCapability(locale: Locale) = capability?.let { parcel ->
|
||||||
val capability = SoftApCapability(it)
|
val capability = SoftApCapability(parcel)
|
||||||
val numClients = numClients
|
val numClients = numClients
|
||||||
val maxClients = capability.maxSupportedClients
|
val maxClients = capability.maxSupportedClients
|
||||||
val supportedFeatures = capability.supportedFeatures
|
var supportedFeatures = capability.supportedFeatures
|
||||||
app.resources.getQuantityText(R.plurals.tethering_manage_wifi_capabilities, numClients ?: 0).format(locale,
|
if (BuildCompat.isAtLeastS()) for ((flag, band) in arrayOf(
|
||||||
numClients ?: "?", maxClients, sequence {
|
SoftApCapability.SOFTAP_FEATURE_BAND_24G_SUPPORTED to SoftApConfigurationCompat.BAND_2GHZ,
|
||||||
|
SoftApCapability.SOFTAP_FEATURE_BAND_5G_SUPPORTED to SoftApConfigurationCompat.BAND_5GHZ,
|
||||||
|
SoftApCapability.SOFTAP_FEATURE_BAND_6G_SUPPORTED to SoftApConfigurationCompat.BAND_6GHZ,
|
||||||
|
SoftApCapability.SOFTAP_FEATURE_BAND_60G_SUPPORTED to SoftApConfigurationCompat.BAND_60GHZ,
|
||||||
|
)) {
|
||||||
|
if (capability.getSupportedChannelList(band).isEmpty()) continue
|
||||||
|
// reduce double reporting
|
||||||
|
supportedFeatures = supportedFeatures and flag.inv()
|
||||||
|
}
|
||||||
|
val result = parent.resources.getQuantityText(R.plurals.tethering_manage_wifi_capabilities, numClients ?: 0)
|
||||||
|
.format(locale, numClients ?: "?", maxClients, sequence {
|
||||||
var features = supportedFeatures
|
var features = supportedFeatures
|
||||||
if (features != 0L) while (features != 0L) {
|
if (features != 0L) while (features != 0L) {
|
||||||
val bit = features.takeLowestOneBit()
|
val bit = features.takeLowestOneBit()
|
||||||
@@ -213,6 +223,39 @@ sealed class TetherManager(protected val parent: TetheringFragment) : Manager(),
|
|||||||
features = features and bit.inv()
|
features = features and bit.inv()
|
||||||
} else yield(parent.getText(R.string.tethering_manage_wifi_no_features))
|
} else yield(parent.getText(R.string.tethering_manage_wifi_no_features))
|
||||||
}.joinToSpanned())
|
}.joinToSpanned())
|
||||||
|
if (BuildCompat.isAtLeastS()) {
|
||||||
|
val list = SoftApConfigurationCompat.BAND_TYPES.map { band ->
|
||||||
|
val channels = capability.getSupportedChannelList(band)
|
||||||
|
if (channels.isNotEmpty()) StringBuilder().apply {
|
||||||
|
append(SoftApConfigurationCompat.bandLookup(band, true))
|
||||||
|
append(" (")
|
||||||
|
channels.sort()
|
||||||
|
var pending: Int? = null
|
||||||
|
var last = channels[0]
|
||||||
|
append(last)
|
||||||
|
for (channel in channels.asSequence().drop(1)) {
|
||||||
|
if (channel == last + 1) pending = channel else {
|
||||||
|
pending?.let {
|
||||||
|
append('-')
|
||||||
|
append(it)
|
||||||
|
pending = null
|
||||||
|
}
|
||||||
|
append(',')
|
||||||
|
append(channel)
|
||||||
|
}
|
||||||
|
last = channel
|
||||||
|
}
|
||||||
|
pending?.let {
|
||||||
|
append('-')
|
||||||
|
append(it)
|
||||||
|
}
|
||||||
|
append(')')
|
||||||
|
} else null
|
||||||
|
}.filterNotNull()
|
||||||
|
if (list.isNotEmpty()) result.append(parent.getText(R.string.tethering_manage_wifi_supported_channels)
|
||||||
|
.format(locale, list.joinToString("; ")))
|
||||||
|
}
|
||||||
|
result
|
||||||
} ?: numClients?.let { numClients ->
|
} ?: numClients?.let { numClients ->
|
||||||
app.resources.getQuantityText(R.plurals.tethering_manage_wifi_clients, numClients).format(locale,
|
app.resources.getQuantityText(R.plurals.tethering_manage_wifi_clients, numClients).format(locale,
|
||||||
numClients)
|
numClients)
|
||||||
|
|||||||
@@ -11,10 +11,23 @@ value class SoftApCapability(val inner: Parcelable) {
|
|||||||
private val clazz by lazy { Class.forName("android.net.wifi.SoftApCapability") }
|
private val clazz by lazy { Class.forName("android.net.wifi.SoftApCapability") }
|
||||||
private val getMaxSupportedClients by lazy { clazz.getDeclaredMethod("getMaxSupportedClients") }
|
private val getMaxSupportedClients by lazy { clazz.getDeclaredMethod("getMaxSupportedClients") }
|
||||||
private val areFeaturesSupported by lazy { clazz.getDeclaredMethod("areFeaturesSupported", Long::class.java) }
|
private val areFeaturesSupported by lazy { clazz.getDeclaredMethod("areFeaturesSupported", Long::class.java) }
|
||||||
|
@get:RequiresApi(31)
|
||||||
|
private val getSupportedChannelList by lazy {
|
||||||
|
clazz.getDeclaredMethod("getSupportedChannelList", Int::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(31)
|
||||||
|
const val SOFTAP_FEATURE_BAND_24G_SUPPORTED = 32L
|
||||||
|
@RequiresApi(31)
|
||||||
|
const val SOFTAP_FEATURE_BAND_5G_SUPPORTED = 64L
|
||||||
|
@RequiresApi(31)
|
||||||
|
const val SOFTAP_FEATURE_BAND_6G_SUPPORTED = 128L
|
||||||
|
@RequiresApi(31)
|
||||||
|
const val SOFTAP_FEATURE_BAND_60G_SUPPORTED = 256L
|
||||||
val featureLookup by lazy { LongConstantLookup(clazz, "SOFTAP_FEATURE_") }
|
val featureLookup by lazy { LongConstantLookup(clazz, "SOFTAP_FEATURE_") }
|
||||||
}
|
}
|
||||||
|
|
||||||
val maxSupportedClients get() = getMaxSupportedClients.invoke(inner) as Int
|
val maxSupportedClients get() = getMaxSupportedClients(inner) as Int
|
||||||
val supportedFeatures: Long get() {
|
val supportedFeatures: Long get() {
|
||||||
var supportedFeatures = 0L
|
var supportedFeatures = 0L
|
||||||
var probe = 1L
|
var probe = 1L
|
||||||
@@ -24,4 +37,5 @@ value class SoftApCapability(val inner: Parcelable) {
|
|||||||
}
|
}
|
||||||
return supportedFeatures
|
return supportedFeatures
|
||||||
}
|
}
|
||||||
|
fun getSupportedChannelList(band: Int) = getSupportedChannelList(inner, band) as IntArray
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ import androidx.core.os.BuildCompat
|
|||||||
import be.mygod.vpnhotspot.net.MacAddressCompat
|
import be.mygod.vpnhotspot.net.MacAddressCompat
|
||||||
import be.mygod.vpnhotspot.net.MacAddressCompat.Companion.toCompat
|
import be.mygod.vpnhotspot.net.MacAddressCompat.Companion.toCompat
|
||||||
import be.mygod.vpnhotspot.net.monitor.TetherTimeoutMonitor
|
import be.mygod.vpnhotspot.net.monitor.TetherTimeoutMonitor
|
||||||
|
import be.mygod.vpnhotspot.util.ConstantLookup
|
||||||
|
import be.mygod.vpnhotspot.util.UnblockCentral
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class SoftApConfigurationCompat(
|
data class SoftApConfigurationCompat(
|
||||||
@@ -40,10 +43,21 @@ data class SoftApConfigurationCompat(
|
|||||||
companion object {
|
companion object {
|
||||||
const val BAND_2GHZ = 1
|
const val BAND_2GHZ = 1
|
||||||
const val BAND_5GHZ = 2
|
const val BAND_5GHZ = 2
|
||||||
|
@TargetApi(30)
|
||||||
const val BAND_6GHZ = 4
|
const val BAND_6GHZ = 4
|
||||||
|
@TargetApi(31)
|
||||||
const val BAND_60GHZ = 8
|
const val BAND_60GHZ = 8
|
||||||
private const val BAND_LEGACY = BAND_2GHZ or BAND_5GHZ
|
private const val BAND_LEGACY = BAND_2GHZ or BAND_5GHZ
|
||||||
const val BAND_ANY = BAND_LEGACY or BAND_6GHZ
|
const val BAND_ANY = BAND_LEGACY or BAND_6GHZ
|
||||||
|
val BAND_TYPES by lazy {
|
||||||
|
if (BuildCompat.isAtLeastS()) try {
|
||||||
|
return@lazy UnblockCentral.SoftApConfiguration_BAND_TYPES
|
||||||
|
} catch (e: ReflectiveOperationException) {
|
||||||
|
Timber.w(e)
|
||||||
|
}
|
||||||
|
intArrayOf(BAND_2GHZ, BAND_5GHZ, BAND_6GHZ, BAND_60GHZ)
|
||||||
|
}
|
||||||
|
val bandLookup = ConstantLookup<SoftApConfiguration>("BAND_", null, "2GHZ", "5GHZ")
|
||||||
|
|
||||||
fun isLegacyEitherBand(band: Int) = band and BAND_LEGACY == BAND_LEGACY
|
fun isLegacyEitherBand(band: Int) = band and BAND_LEGACY == BAND_LEGACY
|
||||||
|
|
||||||
|
|||||||
@@ -122,8 +122,7 @@ object WifiApManager {
|
|||||||
fun onBlockedClientConnecting(client: Parcelable, 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_", "GENERAL", "NO_CHANNEL")
|
||||||
"SAP_START_FAILURE_GENERAL", "SAP_START_FAILURE_NO_CHANNEL")
|
|
||||||
@get:RequiresApi(30)
|
@get:RequiresApi(30)
|
||||||
val clientBlockLookup by lazy { ConstantLookup<WifiManager>("SAP_CLIENT_") }
|
val clientBlockLookup by lazy { ConstantLookup<WifiManager>("SAP_CLIENT_") }
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import be.mygod.vpnhotspot.App.Companion.app
|
|||||||
import be.mygod.vpnhotspot.R
|
import be.mygod.vpnhotspot.R
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
class ConstantLookup(private val prefix: String, private val lookup29: Array<out String>,
|
class ConstantLookup(private val prefix: String, private val lookup29: Array<out String?>,
|
||||||
private val clazz: () -> Class<*>) {
|
private val clazz: () -> Class<*>) {
|
||||||
private val lookup by lazy {
|
private val lookup by lazy {
|
||||||
SparseArrayCompat<String>().apply {
|
SparseArrayCompat<String>().apply {
|
||||||
@@ -25,16 +25,16 @@ class ConstantLookup(private val prefix: String, private val lookup29: Array<out
|
|||||||
} catch (e: ReflectiveOperationException) {
|
} catch (e: ReflectiveOperationException) {
|
||||||
Timber.w(e)
|
Timber.w(e)
|
||||||
}
|
}
|
||||||
return lookup29.getOrNull(reason)?.let { if (trimPrefix) it.substring(prefix.length) else it }
|
return lookup29.getOrNull(reason)?.let { if (trimPrefix) it else prefix + it }
|
||||||
?: app.getString(R.string.failure_reason_unknown, reason)
|
?: app.getString(R.string.failure_reason_unknown, reason)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
fun ConstantLookup(prefix: String, vararg lookup29: String, clazz: () -> Class<*>) =
|
fun ConstantLookup(prefix: String, vararg lookup29: String?, clazz: () -> Class<*>) =
|
||||||
ConstantLookup(prefix, lookup29, clazz)
|
ConstantLookup(prefix, lookup29, clazz)
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
inline fun <reified T> ConstantLookup(prefix: String, vararg lookup29: String) =
|
inline fun <reified T> ConstantLookup(prefix: String, vararg lookup29: String?) =
|
||||||
ConstantLookup(prefix, lookup29) { T::class.java }
|
ConstantLookup(prefix, lookup29) { T::class.java }
|
||||||
|
|
||||||
class LongConstantLookup(private val clazz: Class<*>, private val prefix: String) {
|
class LongConstantLookup(private val clazz: Class<*>, private val prefix: String) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package be.mygod.vpnhotspot.util
|
package be.mygod.vpnhotspot.util
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
|
import android.net.wifi.SoftApConfiguration
|
||||||
import android.net.wifi.p2p.WifiP2pConfig
|
import android.net.wifi.p2p.WifiP2pConfig
|
||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@@ -28,6 +29,11 @@ object UnblockCentral {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@get:RequiresApi(31)
|
||||||
|
val SoftApConfiguration_BAND_TYPES get() = init.let {
|
||||||
|
SoftApConfiguration::class.java.getField("BAND_TYPES").get(null) as IntArray
|
||||||
|
}
|
||||||
|
|
||||||
@RequiresApi(31)
|
@RequiresApi(31)
|
||||||
fun getApInstanceIdentifier(clazz: Class<*>) = init.let { clazz.getDeclaredMethod("getApInstanceIdentifier") }
|
fun getApInstanceIdentifier(clazz: Class<*>) = init.let { clazz.getDeclaredMethod("getApInstanceIdentifier") }
|
||||||
|
|
||||||
|
|||||||
@@ -69,6 +69,7 @@
|
|||||||
<plurals name="tethering_manage_wifi_clients">
|
<plurals name="tethering_manage_wifi_clients">
|
||||||
<item quantity="other">已连接 %d 个设备</item>
|
<item quantity="other">已连接 %d 个设备</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="tethering_manage_wifi_supported_channels">\n支持频道: %s</string>
|
||||||
<string name="tethering_manage_wifi_no_features">无</string>
|
<string name="tethering_manage_wifi_no_features">无</string>
|
||||||
<string name="tethering_manage_wifi_client_blocked">已屏蔽 %1$s:%2$s</string>
|
<string name="tethering_manage_wifi_client_blocked">已屏蔽 %1$s:%2$s</string>
|
||||||
<string name="tethering_manage_wifi_copy_mac">复制 MAC</string>
|
<string name="tethering_manage_wifi_copy_mac">复制 MAC</string>
|
||||||
|
|||||||
@@ -82,6 +82,7 @@
|
|||||||
<item quantity="one">%d client connected</item>
|
<item quantity="one">%d client connected</item>
|
||||||
<item quantity="other">%1d clients connected</item>
|
<item quantity="other">%1d clients connected</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
|
<string name="tethering_manage_wifi_supported_channels">\nSupported channels: %s</string>
|
||||||
<string name="tethering_manage_wifi_no_features">None</string>
|
<string name="tethering_manage_wifi_no_features">None</string>
|
||||||
<string name="tethering_manage_wifi_client_blocked">Blocked %1$s: %2$s</string>
|
<string name="tethering_manage_wifi_client_blocked">Blocked %1$s: %2$s</string>
|
||||||
<string name="tethering_manage_wifi_copy_mac">Copy MAC</string>
|
<string name="tethering_manage_wifi_copy_mac">Copy MAC</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user