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

@@ -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>