This commit is contained in:
Mygod
2022-07-14 22:23:34 -04:00
parent 1517ce4fa1
commit 8ff35f59ed
10 changed files with 261 additions and 75 deletions

View File

@@ -152,7 +152,7 @@ _a.k.a. things that can go wrong if this app doesn't work._
This is a list of stuff that might impact this app's functionality if unavailable.
This is only meant to be an index.
You can read more in the source code.
API restrictions are updated up to [SHA-256 checksum `40674ff4291eb268f86561bf687e69dbd013df9ec9531a460404532a4ac9a761`](https://dl.google.com/developers/android/sc/non-sdk/hiddenapi-flags.csv).
API restrictions are updated up to [SHA-256 checksum `2886a24b6382be8751e86e3c355516c448987c3b0550eb8bb906a34490cfaa3c`](https://dl.google.com/developers/android/tm/non-sdk/hiddenapi-flags.csv).
Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded or implicitly used)
@@ -160,6 +160,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/TetheringManager$TetheringEventCallback;->onTetherableInterfaceRegexpsChanged(Landroid/net/TetheringManager$TetheringInterfaceRegexps;)V,blocked`
* (since API 31) `Landroid/net/wifi/SoftApCapability;->getCountryCode()Ljava/lang/String;,blocked`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration$Builder;->setRandomizedMacAddress(Landroid/net/MacAddress;)Landroid/net/wifi/SoftApConfiguration$Builder;,blocked`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration$Builder;->setUserConfiguration(Z)Landroid/net/wifi/SoftApConfiguration$Builder;,blocked`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration;->BAND_TYPES:[I,blocked`
* (since API 31) `Landroid/net/wifi/SoftApInfo;->getApInstanceIdentifier()Ljava/lang/String;,blocked`
@@ -249,11 +250,13 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
* (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;->build()Landroid/net/wifi/SoftApConfiguration;,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration$Builder;->setAllowedAcsChannels(I[I)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->setAllowedClientList(Ljava/util/List;)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->setAutoShutdownEnabled(Z)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (on API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->setBand(I)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->setBlockedClientList(Ljava/util/List;)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration$Builder;->setBridgedModeOpportunisticShutdownEnabled(Z)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration$Builder;->setBridgedModeOpportunisticShutdownTimeoutMillis(J)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->setBssid(Landroid/net/MacAddress;)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (on API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->setChannel(II)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration$Builder;->setChannels(Landroid/util/SparseIntArray;)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
@@ -262,10 +265,12 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
* (since API 31) `Landroid/net/wifi/SoftApConfiguration$Builder;->setIeee80211axEnabled(Z)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration$Builder;->setIeee80211beEnabled(Z)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration$Builder;->setMacRandomizationSetting(I)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration$Builder;->setMaxChannelBandwidth(I)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->setMaxNumberOfClients(I)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->setPassphrase(Ljava/lang/String;I)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->setShutdownTimeoutMillis(J)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration$Builder;->setSsid(Ljava/lang/String;)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration$Builder;->setVendorElements(Ljava/util/List;)Landroid/net/wifi/SoftApConfiguration$Builder;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->BAND_2GHZ:I,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->BAND_5GHZ:I,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration;->BAND_60GHZ:I,sdk,system-api,test-api`
@@ -273,15 +278,21 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
* (since API 31) `Landroid/net/wifi/SoftApConfiguration;->BAND_*:I,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration;->DEFAULT_TIMEOUT:J,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration;->RANDOMIZATION_NONE:I,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration;->RANDOMIZATION_NON_PERSISTENT:I,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration;->RANDOMIZATION_PERSISTENT:I,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration;->getAllowedAcsChannels(I)[I,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->getAllowedClientList()Ljava/util/List;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->getBand()I,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->getBlockedClientList()Ljava/util/List;,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration;->getBridgedModeOpportunisticShutdownTimeoutMillis()J,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->getChannel()I,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration;->getChannels()Landroid/util/SparseIntArray;,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration;->getMacRandomizationSetting()I,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration;->getMaxChannelBandwidth()I,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->getMaxNumberOfClients()I,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration;->getPersistentRandomizedMacAddress()Landroid/net/MacAddress;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->getShutdownTimeoutMillis()J,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApConfiguration;->getVendorElements()Ljava/util/List;,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->isAutoShutdownEnabled()Z,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration;->isBridgedModeOpportunisticShutdownEnabled()Z,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApConfiguration;->isClientControlByUserEnabled()Z,sdk,system-api,test-api`
@@ -289,6 +300,7 @@ Greylisted/blacklisted APIs or internal constants: (some constants are hardcoded
* (since API 33) `Landroid/net/wifi/SoftApConfiguration;->isIeee80211beEnabled()Z,sdk,system-api,test-api`
* (since API 31) `Landroid/net/wifi/SoftApConfiguration;->isUserConfiguration()Z,sdk,system-api,test-api`
* (since API 30) `Landroid/net/wifi/SoftApInfo;->CHANNEL_WIDTH_*:I,sdk,system-api,test-api`
* (since API 33) `Landroid/net/wifi/SoftApInfo;->CHANNEL_WIDTH_AUTO:I,sdk,system-api,test-api`
* (on 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 30) `Landroid/net/wifi/SoftApInfo;->getBandwidth()I,sdk,system-api,test-api`
@@ -339,6 +351,7 @@ Nonexported system resources:
* (since API 30) `@com.android.networkstack.tethering:array/config_tether_wifi_regexs`
* (since API 30) `@com.android.networkstack.tethering:array/config_tether_wigig_regexs`
* (since API 30) `@com.android.wifi.resources:bool/config_wifi_p2p_mac_randomization_supported`
* (since API 31) `@com.android.wifi.resources:integer/config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond`
* (since API 30) `@com.android.wifi.resources:integer/config_wifiFrameworkSoftApShutDownTimeoutMilliseconds`
Other: Activity `com.android.settings/.Settings$TetherSettingsActivity` is assumed to be exported.

View File

@@ -191,25 +191,31 @@ class RepeaterManager(private val parent: TetheringFragment) : Manager(), Servic
val passphrase = RepeaterService.passphrase
if (networkName != null && passphrase != null) {
return SoftApConfigurationCompat(
ssid = networkName,
passphrase = passphrase,
securityType = SoftApConfiguration.SECURITY_TYPE_WPA2_PSK, // is not actually used
isAutoShutdownEnabled = RepeaterService.isAutoShutdownEnabled,
shutdownTimeoutMillis = RepeaterService.shutdownTimeoutMillis).apply {
ssid = networkName,
passphrase = passphrase,
securityType = SoftApConfiguration.SECURITY_TYPE_WPA2_PSK, // is not actually used
isAutoShutdownEnabled = RepeaterService.isAutoShutdownEnabled,
shutdownTimeoutMillis = RepeaterService.shutdownTimeoutMillis,
macRandomizationSetting = if (WifiApManager.p2pMacRandomizationSupported) {
SoftApConfigurationCompat.RANDOMIZATION_NON_PERSISTENT
} else SoftApConfigurationCompat.RANDOMIZATION_NONE,
).apply {
bssid = RepeaterService.deviceAddress
setChannel(RepeaterService.operatingChannel, RepeaterService.operatingBand)
setMacRandomizationEnabled(WifiApManager.p2pMacRandomizationSupported)
} to false
}
} else binder?.let { binder ->
val group = binder.group ?: binder.fetchPersistentGroup().let { binder.group }
if (group != null) return SoftApConfigurationCompat(
ssid = group.networkName,
securityType = SoftApConfiguration.SECURITY_TYPE_WPA2_PSK, // is not actually used
isAutoShutdownEnabled = RepeaterService.isAutoShutdownEnabled,
shutdownTimeoutMillis = RepeaterService.shutdownTimeoutMillis).run {
ssid = group.networkName,
securityType = SoftApConfiguration.SECURITY_TYPE_WPA2_PSK, // is not actually used
isAutoShutdownEnabled = RepeaterService.isAutoShutdownEnabled,
shutdownTimeoutMillis = RepeaterService.shutdownTimeoutMillis,
macRandomizationSetting = if (WifiApManager.p2pMacRandomizationSupported) {
SoftApConfigurationCompat.RANDOMIZATION_NON_PERSISTENT
} else SoftApConfigurationCompat.RANDOMIZATION_NONE,
).run {
setChannel(RepeaterService.operatingChannel)
setMacRandomizationEnabled(WifiApManager.p2pMacRandomizationSupported)
try {
val config = P2pSupplicantConfiguration(group)
config.init(binder.obtainDeviceAddress()?.toString())

View File

@@ -58,6 +58,17 @@ class TetherTimeoutMonitor(private val timeout: Long = 0,
MIN_SOFT_AP_TIMEOUT_DELAY_MS
} else delay
}
@get:RequiresApi(31)
val defaultTimeoutBridged: Int get() = try {
val info = WifiApManager.resolvedActivity.activityInfo
val resources = app.packageManager.getResourcesForApplication(info.applicationInfo)
resources.getInteger(resources.findIdentifier(
"config_wifiFrameworkSoftApShutDownIdleInstanceInBridgedModeTimeoutMillisecond", "integer",
WifiApManager.RESOURCES_PACKAGE, info.packageName))
} catch (e: RuntimeException) {
Timber.w(e)
MIN_SOFT_AP_TIMEOUT_DELAY_MS
}
}
private var noClient = true

View File

@@ -3,6 +3,7 @@ package be.mygod.vpnhotspot.net.wifi
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.net.MacAddress
import android.net.wifi.ScanResult
import android.net.wifi.SoftApConfiguration
import android.os.Build
import android.os.Parcelable
@@ -16,45 +17,59 @@ import be.mygod.vpnhotspot.util.ConstantLookup
import be.mygod.vpnhotspot.util.UnblockCentral
import kotlinx.parcelize.Parcelize
import timber.log.Timber
import java.lang.reflect.InvocationTargetException
@Parcelize
data class SoftApConfigurationCompat(
var ssid: String? = null,
@Deprecated("Workaround for using inline class with Parcelize, use bssid")
var bssidAddr: Long? = null,
var passphrase: String? = null,
var isHiddenSsid: Boolean = false,
/**
* You should probably set or modify this field directly only when you want to use bridged AP,
* see also [android.net.wifi.WifiManager.isBridgedApConcurrencySupported].
* Otherwise, use [requireSingleBand] and [setChannel].
*/
@TargetApi(23)
var channels: SparseIntArray = SparseIntArray(1).apply { append(BAND_2GHZ, 0) },
var securityType: Int = SoftApConfiguration.SECURITY_TYPE_OPEN,
@TargetApi(30)
var maxNumberOfClients: Int = 0,
@TargetApi(28)
var isAutoShutdownEnabled: Boolean = true,
@TargetApi(28)
var shutdownTimeoutMillis: Long = 0,
@TargetApi(30)
var isClientControlByUserEnabled: Boolean = false,
@RequiresApi(30)
var blockedClientList: List<MacAddress> = emptyList(),
@RequiresApi(30)
var allowedClientList: List<MacAddress> = emptyList(),
@TargetApi(31)
var macRandomizationSetting: Int = RANDOMIZATION_PERSISTENT,
@TargetApi(31)
var isBridgedModeOpportunisticShutdownEnabled: Boolean = true,
@TargetApi(31)
var isIeee80211axEnabled: Boolean = true,
@TargetApi(33)
var isIeee80211beEnabled: Boolean = true,
@TargetApi(31)
var isUserConfiguration: Boolean = true,
var underlying: Parcelable? = null) : Parcelable {
var ssid: String? = null,
@Deprecated("Workaround for using inline class with Parcelize, use bssid")
var bssidAddr: Long? = null,
var passphrase: String? = null,
var isHiddenSsid: Boolean = false,
/**
* You should probably set or modify this field directly only when you want to use bridged AP,
* see also [android.net.wifi.WifiManager.isBridgedApConcurrencySupported].
* Otherwise, use [requireSingleBand] and [setChannel].
*/
@TargetApi(23)
var channels: SparseIntArray = SparseIntArray(1).apply { append(BAND_2GHZ, 0) },
var securityType: Int = SoftApConfiguration.SECURITY_TYPE_OPEN,
@TargetApi(30)
var maxNumberOfClients: Int = 0,
@TargetApi(28)
var isAutoShutdownEnabled: Boolean = true,
@TargetApi(28)
var shutdownTimeoutMillis: Long = 0,
@TargetApi(30)
var isClientControlByUserEnabled: Boolean = false,
@RequiresApi(30)
var blockedClientList: List<MacAddress> = emptyList(),
@RequiresApi(30)
var allowedClientList: List<MacAddress> = emptyList(),
@TargetApi(31)
var macRandomizationSetting: Int = if (Build.VERSION.SDK_INT >= 33) {
RANDOMIZATION_NON_PERSISTENT
} else RANDOMIZATION_PERSISTENT,
@TargetApi(31)
var isBridgedModeOpportunisticShutdownEnabled: Boolean = true,
@TargetApi(31)
var isIeee80211axEnabled: Boolean = true,
@TargetApi(33)
var isIeee80211beEnabled: Boolean = true,
@TargetApi(31)
var isUserConfiguration: Boolean = true,
@TargetApi(33)
var bridgedModeOpportunisticShutdownTimeoutMillis: Long = -1L,
@TargetApi(33)
var vendorElements: List<ScanResult.InformationElement> = emptyList(),
@TargetApi(33)
var persistentRandomizedMacAddress: MacAddress? = null,
@TargetApi(33)
var allowedAcsChannels: Map<Int, Set<Int>> = emptyMap(),
@TargetApi(33)
var maxChannelBandwidth: Int = CHANNEL_WIDTH_AUTO,
var underlying: Parcelable? = null,
) : Parcelable {
companion object {
const val BAND_2GHZ = 1
const val BAND_5GHZ = 2
@@ -82,6 +97,13 @@ data class SoftApConfigurationCompat(
const val RANDOMIZATION_NONE = 0
@TargetApi(31)
const val RANDOMIZATION_PERSISTENT = 1
@TargetApi(33)
const val RANDOMIZATION_NON_PERSISTENT = 2
@TargetApi(33)
const val CHANNEL_WIDTH_AUTO = -1
@TargetApi(30)
const val CHANNEL_WIDTH_INVALID = 0
fun isLegacyEitherBand(band: Int) = band and BAND_LEGACY == BAND_LEGACY
@@ -165,6 +187,10 @@ data class SoftApConfigurationCompat(
android.net.wifi.WifiConfiguration::class.java.getDeclaredField("apChannel")
}
@get:RequiresApi(33)
private val getAllowedAcsChannels by lazy @TargetApi(33) {
SoftApConfiguration::class.java.getDeclaredMethod("getAllowedAcsChannels", Int::class.java)
}
@get:RequiresApi(30)
private val getAllowedClientList by lazy @TargetApi(30) {
SoftApConfiguration::class.java.getDeclaredMethod("getAllowedClientList")
@@ -175,6 +201,10 @@ data class SoftApConfigurationCompat(
private val getBlockedClientList by lazy @TargetApi(30) {
SoftApConfiguration::class.java.getDeclaredMethod("getBlockedClientList")
}
@get:RequiresApi(33)
private val getBridgedModeOpportunisticShutdownTimeoutMillis by lazy @TargetApi(33) {
SoftApConfiguration::class.java.getDeclaredMethod("getBridgedModeOpportunisticShutdownTimeoutMillis")
}
@get:RequiresApi(30)
private val getChannel by lazy @TargetApi(30) {
SoftApConfiguration::class.java.getDeclaredMethod("getChannel")
@@ -187,14 +217,26 @@ data class SoftApConfigurationCompat(
private val getMacRandomizationSetting by lazy @TargetApi(31) {
SoftApConfiguration::class.java.getDeclaredMethod("getMacRandomizationSetting")
}
@get:RequiresApi(33)
private val getMaxChannelBandwidth by lazy @TargetApi(33) {
SoftApConfiguration::class.java.getDeclaredMethod("getMaxChannelBandwidth")
}
@get:RequiresApi(30)
private val getMaxNumberOfClients by lazy @TargetApi(30) {
SoftApConfiguration::class.java.getDeclaredMethod("getMaxNumberOfClients")
}
@get:RequiresApi(33)
private val getPersistentRandomizedMacAddress by lazy @TargetApi(33) {
SoftApConfiguration::class.java.getDeclaredMethod("getPersistentRandomizedMacAddress")
}
@get:RequiresApi(30)
private val getShutdownTimeoutMillis by lazy @TargetApi(30) {
SoftApConfiguration::class.java.getDeclaredMethod("getShutdownTimeoutMillis")
}
@get:RequiresApi(33)
private val getVendorElements by lazy @TargetApi(33) {
SoftApConfiguration::class.java.getDeclaredMethod("getVendorElements")
}
@get:RequiresApi(30)
private val isAutoShutdownEnabled by lazy @TargetApi(30) {
SoftApConfiguration::class.java.getDeclaredMethod("isAutoShutdownEnabled")
@@ -226,6 +268,10 @@ data class SoftApConfigurationCompat(
private val newBuilder by lazy @TargetApi(30) { classBuilder.getConstructor(SoftApConfiguration::class.java) }
@get:RequiresApi(30)
private val build by lazy @TargetApi(30) { classBuilder.getDeclaredMethod("build") }
@get:RequiresApi(33)
private val setAllowedAcsChannels by lazy @TargetApi(33) {
classBuilder.getDeclaredMethod("setAllowedAcsChannels", Int::class.java, IntArray::class.java)
}
@get:RequiresApi(30)
private val setAllowedClientList by lazy @TargetApi(30) {
classBuilder.getDeclaredMethod("setAllowedClientList", java.util.List::class.java)
@@ -244,6 +290,10 @@ data class SoftApConfigurationCompat(
private val setBridgedModeOpportunisticShutdownEnabled by lazy @TargetApi(31) {
classBuilder.getDeclaredMethod("setBridgedModeOpportunisticShutdownEnabled", Boolean::class.java)
}
@get:RequiresApi(33)
private val setBridgedModeOpportunisticShutdownTimeoutMillis by lazy @TargetApi(33) {
classBuilder.getDeclaredMethod("setBridgedModeOpportunisticShutdownTimeoutMillis", Long::class.java)
}
@get:RequiresApi(30)
private val setBssid by lazy @TargetApi(30) {
classBuilder.getDeclaredMethod("setBssid", MacAddress::class.java)
@@ -276,6 +326,10 @@ data class SoftApConfigurationCompat(
private val setMacRandomizationSetting by lazy @TargetApi(31) {
classBuilder.getDeclaredMethod("setMacRandomizationSetting", Int::class.java)
}
@get:RequiresApi(33)
private val setMaxChannelBandwidth by lazy @TargetApi(33) {
classBuilder.getDeclaredMethod("setMaxChannelBandwidth", Int::class.java)
}
@get:RequiresApi(30)
private val setMaxNumberOfClients by lazy @TargetApi(31) {
classBuilder.getDeclaredMethod("setMaxNumberOfClients", Int::class.java)
@@ -284,6 +338,10 @@ data class SoftApConfigurationCompat(
private val setPassphrase by lazy @TargetApi(30) {
classBuilder.getDeclaredMethod("setPassphrase", String::class.java, Int::class.java)
}
@get:RequiresApi(33)
private val setRandomizedMacAddress by lazy @TargetApi(33) {
UnblockCentral.setRandomizedMacAddress(classBuilder)
}
@get:RequiresApi(30)
private val setShutdownTimeoutMillis by lazy @TargetApi(30) {
classBuilder.getDeclaredMethod("setShutdownTimeoutMillis", Long::class.java)
@@ -292,6 +350,10 @@ data class SoftApConfigurationCompat(
private val setSsid by lazy @TargetApi(30) { classBuilder.getDeclaredMethod("setSsid", String::class.java) }
@get:RequiresApi(31)
private val setUserConfiguration by lazy @TargetApi(31) { UnblockCentral.setUserConfiguration(classBuilder) }
@get:RequiresApi(33)
private val setVendorElements by lazy @TargetApi(33) {
classBuilder.getDeclaredMethod("setVendorElements", java.util.List::class.java)
}
@Deprecated("Class deprecated in framework")
@Suppress("DEPRECATION")
@@ -350,13 +412,29 @@ data class SoftApConfigurationCompat(
isClientControlByUserEnabled(this) as Boolean,
getBlockedClientList(this) as List<MacAddress>,
getAllowedClientList(this) as List<MacAddress>,
if (Build.VERSION.SDK_INT >= 31) getMacRandomizationSetting(this) as Int else RANDOMIZATION_PERSISTENT,
Build.VERSION.SDK_INT < 31 || isBridgedModeOpportunisticShutdownEnabled(this) as Boolean,
Build.VERSION.SDK_INT < 31 || isIeee80211axEnabled(this) as Boolean,
Build.VERSION.SDK_INT < 33 || isIeee80211beEnabled(this) as Boolean,
Build.VERSION.SDK_INT < 31 || isUserConfiguration(this) as Boolean,
this,
)
underlying = this,
).also {
if (Build.VERSION.SDK_INT < 31) return@also
it.macRandomizationSetting = getMacRandomizationSetting(this) as Int
it.isBridgedModeOpportunisticShutdownEnabled = isBridgedModeOpportunisticShutdownEnabled(this) as Boolean
it.isIeee80211axEnabled = isIeee80211axEnabled(this) as Boolean
it.isUserConfiguration = isUserConfiguration(this) as Boolean
if (Build.VERSION.SDK_INT < 33) return@also
it.isIeee80211beEnabled = isIeee80211beEnabled(this) as Boolean
it.bridgedModeOpportunisticShutdownTimeoutMillis =
getBridgedModeOpportunisticShutdownTimeoutMillis(this) as Long
it.vendorElements = getVendorElements(this) as List<ScanResult.InformationElement>
it.persistentRandomizedMacAddress = getPersistentRandomizedMacAddress(this) as MacAddress
it.allowedAcsChannels = BAND_TYPES.map { bandType ->
try {
bandType to (getAllowedAcsChannels(this, bandType) as IntArray).toSet()
} catch (e: InvocationTargetException) {
if (e.targetException !is IllegalArgumentException) throw e
null
}
}.filterNotNull().toMap()
it.maxChannelBandwidth = getMaxChannelBandwidth(this) as Int
}
/**
* Only single band/channel can be supplied on API 23-30
@@ -378,7 +456,10 @@ data class SoftApConfigurationCompat(
@RequiresApi(30)
fun testPlatformValidity(bssid: MacAddress) = setBssid(staticBuilder, bssid)
@RequiresApi(30)
fun testPlatformValidity(timeout: Long) = setShutdownTimeoutMillis(staticBuilder, timeout)
fun testPlatformTimeoutValidity(timeout: Long) = setShutdownTimeoutMillis(staticBuilder, timeout)
@RequiresApi(33)
fun testPlatformBridgedTimeoutValidity(timeout: Long) =
setBridgedModeOpportunisticShutdownTimeoutMillis(staticBuilder, timeout)
}
@Suppress("DEPRECATION")
@@ -398,10 +479,6 @@ data class SoftApConfigurationCompat(
}
}
fun setMacRandomizationEnabled(enabled: Boolean) {
macRandomizationSetting = if (enabled) RANDOMIZATION_PERSISTENT else RANDOMIZATION_NONE
}
/**
* Based on:
* https://android.googlesource.com/platform/packages/apps/Settings/+/android-5.0.0_r1/src/com/android/settings/wifi/WifiApDialog.java#88
@@ -478,6 +555,25 @@ data class SoftApConfigurationCompat(
} catch (e: ReflectiveOperationException) {
Timber.w(e) // as far as we are concerned, this field is not used anywhere so ignore for now
}
if (Build.VERSION.SDK_INT >= 33) {
setBridgedModeOpportunisticShutdownTimeoutMillis(builder, bridgedModeOpportunisticShutdownTimeoutMillis)
setVendorElements(builder, vendorElements)
if (sac?.let { getPersistentRandomizedMacAddress(it) as MacAddress } !=
persistentRandomizedMacAddress) try {
setRandomizedMacAddress(builder, persistentRandomizedMacAddress)
} catch (e: ReflectiveOperationException) {
Timber.w(e)
}
for (bandType in BAND_TYPES) {
val value = allowedAcsChannels[bandType] ?: emptySet()
try {
setAllowedAcsChannels(builder, bandType, value.toIntArray())
} catch (e: InvocationTargetException) {
if (value.isNotEmpty()) throw e
}
}
setMaxChannelBandwidth(builder, maxChannelBandwidth)
}
}
return build(builder) as SoftApConfiguration
}

View File

@@ -145,11 +145,14 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
.filter { it.isNotEmpty() }.map { MacAddressCompat.fromString(it).toPlatform() }
blockedClientList = (dialogView.blockedList.text ?: "").split(nonMacChars)
.filter { it.isNotEmpty() }.map { MacAddressCompat.fromString(it).toPlatform() }
setMacRandomizationEnabled(dialogView.macRandomization.isChecked)
macRandomizationSetting = dialogView.macRandomization.selectedItemPosition
isBridgedModeOpportunisticShutdownEnabled = dialogView.bridgedModeOpportunisticShutdown.isChecked
isIeee80211axEnabled = dialogView.ieee80211ax.isChecked
isIeee80211beEnabled = dialogView.ieee80211be.isChecked
isUserConfiguration = dialogView.userConfig.isChecked
bridgedModeOpportunisticShutdownTimeoutMillis = dialogView.bridgedTimeout.text.let { text ->
if (text.isNullOrEmpty()) -1L else text.toString().toLong()
}
}
}
@@ -225,8 +228,15 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
dialogView.ieee80211ax.isGone = true
dialogView.bridgedModeOpportunisticShutdown.isGone = true
dialogView.userConfig.isGone = true
dialogView.bridgedTimeoutWrapper.isGone = true
} else {
dialogView.bridgedTimeoutWrapper.helperText = getString(R.string.wifi_hotspot_timeout_default,
TetherTimeoutMonitor.defaultTimeoutBridged)
}
if (arg.p2pMode || Build.VERSION.SDK_INT < 33) dialogView.ieee80211be.isGone = true
if (arg.p2pMode || Build.VERSION.SDK_INT < 33) {
dialogView.ieee80211be.isGone = true
dialogView.bridgedTimeout.isEnabled = false
} else dialogView.bridgedTimeout.addTextChangedListener(this@WifiApDialogFragment)
base = arg.configuration
populateFromConfiguration()
}
@@ -261,12 +271,14 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
dialogView.clientUserControl.isChecked = base.isClientControlByUserEnabled
dialogView.blockedList.setText(base.blockedClientList.joinToString("\n"))
dialogView.allowedList.setText(base.allowedClientList.joinToString("\n"))
dialogView.macRandomization.isChecked =
base.macRandomizationSetting == SoftApConfigurationCompat.RANDOMIZATION_PERSISTENT
dialogView.macRandomization.setSelection(base.macRandomizationSetting)
dialogView.bridgedModeOpportunisticShutdown.isChecked = base.isBridgedModeOpportunisticShutdownEnabled
dialogView.ieee80211ax.isChecked = base.isIeee80211axEnabled
dialogView.ieee80211be.isChecked = base.isIeee80211beEnabled
dialogView.userConfig.isChecked = base.isUserConfiguration
dialogView.bridgedTimeout.setText(base.bridgedModeOpportunisticShutdownTimeoutMillis.let {
if (it == -1L) "" else it.toString()
})
}
override fun onStart() {
@@ -298,7 +310,7 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
dialogView.passwordWrapper.error = if (passwordValid) null else " "
val timeoutError = dialogView.timeout.text.let { text ->
if (text.isNullOrEmpty()) null else try {
SoftApConfigurationCompat.testPlatformValidity(text.toString().toLong())
SoftApConfigurationCompat.testPlatformTimeoutValidity(text.toString().toLong())
null
} catch (e: Exception) {
e.readableMessage
@@ -355,7 +367,17 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
dialogView.allowedListWrapper.error = allowedListError
blockedListError == null && allowedListError == null
} else true
val canCopy = timeoutError == null && bssidValid && maxClientError == null && listsNoError
val bridgedTimeoutError = dialogView.bridgedTimeout.text.let { text ->
if (text.isNullOrEmpty()) null else try {
SoftApConfigurationCompat.testPlatformBridgedTimeoutValidity(text.toString().toLong())
null
} catch (e: Exception) {
e.readableMessage
}
}
dialogView.bridgedTimeoutWrapper.error = bridgedTimeoutError
val canCopy = timeoutError == null && bssidValid && maxClientError == null && listsNoError &&
bridgedTimeoutError == null
(dialog as? AlertDialog)?.getButton(DialogInterface.BUTTON_POSITIVE)?.isEnabled =
ssidLengthOk && passwordValid && bandError == null && canCopy
dialogView.toolbar.menu.findItem(android.R.id.copy).isEnabled = canCopy

View File

@@ -11,7 +11,6 @@ import android.os.Handler
import android.os.Parcelable
import androidx.annotation.RequiresApi
import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.net.wifi.SoftApConfigurationCompat.Companion.toCompat
import be.mygod.vpnhotspot.util.*
import timber.log.Timber
import java.lang.reflect.InvocationHandler
@@ -289,8 +288,8 @@ object WifiApManager {
if (Build.VERSION.SDK_INT >= 31) return null // ignore old version calls
val arg = args!![0]
val info = SoftApInfo(arg as Parcelable)
callback.onInfoChanged( // check for legacy empty info with CHANNEL_WIDTH_INVALID
if (info.frequency == 0 && info.bandwidth == 0) emptyList() else listOf(arg))
callback.onInfoChanged(if (info.frequency == 0 && info.bandwidth ==
SoftApConfigurationCompat.CHANNEL_WIDTH_INVALID) emptyList() else listOf(arg))
}
Build.VERSION.SDK_INT >= 30 && method.matches("onCapabilityChanged", SoftApCapability.clazz) -> {
callback.onCapabilityChanged(args!![0] as Parcelable)

View File

@@ -1,6 +1,7 @@
package be.mygod.vpnhotspot.util
import android.annotation.SuppressLint
import android.net.MacAddress
import android.net.wifi.SoftApConfiguration
import android.net.wifi.p2p.WifiP2pConfig
import androidx.annotation.RequiresApi
@@ -24,6 +25,11 @@ object UnblockCentral {
@RequiresApi(33)
fun getCountryCode(clazz: Class<*>) = init.let { clazz.getDeclaredMethod("getCountryCode") }
@RequiresApi(33)
fun setRandomizedMacAddress(clazz: Class<*>) = init.let {
clazz.getDeclaredMethod("setRandomizedMacAddress", MacAddress::class.java)
}
@RequiresApi(31)
fun setUserConfiguration(clazz: Class<*>) = init.let {
clazz.getDeclaredMethod("setUserConfiguration", Boolean::class.java)

View File

@@ -261,14 +261,19 @@
android:inputType="textNoSuggestions"
android:maxLength="17" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/mac_randomization"
style="@style/wifi_item_label"
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dip"
android:minHeight="@dimen/touch_target_min"
style="@style/wifi_item_label"
android:text="@string/wifi_mac_randomization" />
<Spinner
android:id="@+id/mac_randomization"
style="@style/wifi_item_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="@dimen/touch_target_min"
android:entries="@array/wifi_mac_randomization"
android:prompt="@string/wifi_mac_randomization" />
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/hidden_ssid"
style="@style/wifi_item_label"
@@ -301,6 +306,24 @@
android:layout_marginTop="8dip"
android:minHeight="@dimen/touch_target_min"
android:text="@string/wifi_bridged_mode_opportunistic_shutdown" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/bridged_timeout_wrapper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dip"
android:hint="@string/wifi_hotspot_timeout_bridged"
app:counterEnabled="true"
app:counterMaxLength="19"
app:errorEnabled="true"
app:suffixText="ms">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/bridged_timeout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/wifi_item_edit_content"
android:inputType="number"
android:maxLength="19" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.materialswitch.MaterialSwitch
android:id="@+id/user_config"
style="@style/wifi_item_label"

View File

@@ -1,5 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools">
<string-array name="wifi_mac_randomization">
<item>@string/wifi_mac_randomization_none</item>
<item>@string/wifi_mac_randomization_persistent</item>
<item>@string/wifi_mac_randomization_non_persistent</item>
</string-array>
<string-array name="settings_service_masquerade" tools:ignore="InconsistentArrays">
<item>@string/settings_service_masquerade_none</item>
<item>@string/settings_service_masquerade_simple</item>

View File

@@ -216,7 +216,11 @@
<string name="wifi_blocked_list">Blocked list of clients</string>
<string name="wifi_allowed_list">Allowed list of clients</string>
<string name="wifi_mac_randomization">Use randomized MAC</string>
<string name="wifi_bridged_mode_opportunistic_shutdown">Enable Bridged mode opportunistic shutdown</string>
<string name="wifi_mac_randomization_none">None</string>
<string name="wifi_mac_randomization_persistent">Persistent</string>
<string name="wifi_mac_randomization_non_persistent">Non-persistent</string>
<string name="wifi_bridged_mode_opportunistic_shutdown">Enable opportunistic shutdown of an instance in bridged AP</string>
<string name="wifi_hotspot_timeout_bridged">Inactive timeout for a bridged instance</string>
<string name="wifi_ieee_80211ax">Enable Wi\u2011Fi 6</string>
<string name="wifi_ieee_80211be">Enable Wi\u2011Fi 7</string>
<string name="wifi_user_config">User Supplied Configuration</string>