Correctly implement bridged AP, third attempt
This commit is contained in:
@@ -24,11 +24,9 @@ data class SoftApConfigurationCompat(
|
|||||||
var passphrase: String? = null,
|
var passphrase: String? = null,
|
||||||
var isHiddenSsid: Boolean = false,
|
var isHiddenSsid: Boolean = false,
|
||||||
/**
|
/**
|
||||||
* To read legacy band/channel pair, use [requireSingleBand]. For easy access, see [getChannel].
|
|
||||||
*
|
|
||||||
* You should probably set or modify this field directly only when you want to use bridged AP,
|
* You should probably set or modify this field directly only when you want to use bridged AP,
|
||||||
* see also [android.net.wifi.WifiManager.isBridgedApConcurrencySupported].
|
* see also [android.net.wifi.WifiManager.isBridgedApConcurrencySupported].
|
||||||
* Otherwise, use [optimizeChannels] or [setChannel].
|
* Otherwise, use [requireSingleBand] and [setChannel].
|
||||||
*/
|
*/
|
||||||
@TargetApi(23)
|
@TargetApi(23)
|
||||||
var channels: SparseIntArray = SparseIntArray(1).apply { append(BAND_2GHZ, 0) },
|
var channels: SparseIntArray = SparseIntArray(1).apply { append(BAND_2GHZ, 0) },
|
||||||
@@ -62,6 +60,10 @@ data class SoftApConfigurationCompat(
|
|||||||
@TargetApi(31)
|
@TargetApi(31)
|
||||||
const val BAND_60GHZ = 8
|
const val BAND_60GHZ = 8
|
||||||
const val BAND_LEGACY = BAND_2GHZ or BAND_5GHZ
|
const val BAND_LEGACY = BAND_2GHZ or BAND_5GHZ
|
||||||
|
@TargetApi(30)
|
||||||
|
const val BAND_ANY_30 = BAND_LEGACY or BAND_6GHZ
|
||||||
|
@TargetApi(31)
|
||||||
|
const val BAND_ANY_31 = BAND_ANY_30 or BAND_60GHZ
|
||||||
val BAND_TYPES by lazy {
|
val BAND_TYPES by lazy {
|
||||||
if (Build.VERSION.SDK_INT >= 31) try {
|
if (Build.VERSION.SDK_INT >= 31) try {
|
||||||
return@lazy UnblockCentral.SoftApConfiguration_BAND_TYPES
|
return@lazy UnblockCentral.SoftApConfiguration_BAND_TYPES
|
||||||
@@ -341,15 +343,6 @@ data class SoftApConfigurationCompat(
|
|||||||
require(channels.size() == 1) { "Unsupported number of bands configured" }
|
require(channels.size() == 1) { "Unsupported number of bands configured" }
|
||||||
return channels.keyAt(0) to channels.valueAt(0)
|
return channels.keyAt(0) to channels.valueAt(0)
|
||||||
}
|
}
|
||||||
fun optimizeChannels(channels: SparseIntArray) = SparseIntArray(channels.size()).apply {
|
|
||||||
var setBand = 0
|
|
||||||
repeat(channels.size()) { i -> if (channels.valueAt(i) == 0) setBand = setBand or channels.keyAt(i) }
|
|
||||||
if (setBand != 0) append(setBand, 0) // merge all bands into one
|
|
||||||
repeat(channels.size()) { i ->
|
|
||||||
val band = channels.keyAt(i)
|
|
||||||
if (band and setBand == 0) put(band, channels.valueAt(i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(30)
|
@RequiresApi(30)
|
||||||
private fun setChannelsCompat(builder: Any, channels: SparseIntArray) = if (Build.VERSION.SDK_INT < 31) {
|
private fun setChannelsCompat(builder: Any, channels: SparseIntArray) = if (Build.VERSION.SDK_INT < 31) {
|
||||||
@@ -369,15 +362,6 @@ data class SoftApConfigurationCompat(
|
|||||||
bssidAddr = value?.addr
|
bssidAddr = value?.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getChannel(band: Int): Int {
|
|
||||||
var result = -1
|
|
||||||
repeat(channels.size()) { i ->
|
|
||||||
if (band and channels.keyAt(i) != band) return@repeat
|
|
||||||
require(result == -1) { "Duplicate band found" }
|
|
||||||
result = channels.valueAt(i)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
fun setChannel(channel: Int, band: Int = BAND_LEGACY) {
|
fun setChannel(channel: Int, band: Int = BAND_LEGACY) {
|
||||||
channels = SparseIntArray(1).apply {
|
channels = SparseIntArray(1).apply {
|
||||||
append(when {
|
append(when {
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ import be.mygod.vpnhotspot.util.readableMessage
|
|||||||
import be.mygod.vpnhotspot.util.showAllowingStateLoss
|
import be.mygod.vpnhotspot.util.showAllowingStateLoss
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
import java.text.DecimalFormat
|
||||||
|
import java.text.DecimalFormatSymbols
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Based on: https://android.googlesource.com/platform/packages/apps/Settings/+/39b4674/src/com/android/settings/wifi/WifiApDialog.java
|
* Based on: https://android.googlesource.com/platform/packages/apps/Settings/+/39b4674/src/com/android/settings/wifi/WifiApDialog.java
|
||||||
@@ -48,26 +50,30 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
companion object {
|
companion object {
|
||||||
private const val BASE64_FLAGS = Base64.NO_PADDING or Base64.NO_WRAP
|
private const val BASE64_FLAGS = Base64.NO_PADDING or Base64.NO_WRAP
|
||||||
private val nonMacChars = "[^0-9a-fA-F:]+".toRegex()
|
private val nonMacChars = "[^0-9a-fA-F:]+".toRegex()
|
||||||
private val baseOptions by lazy { listOf(ChannelOption.Disabled, ChannelOption.Auto) }
|
private val channels2G = (1..14).map { ChannelOption(SoftApConfigurationCompat.BAND_2GHZ, it) }
|
||||||
private val channels2G by lazy {
|
|
||||||
baseOptions + (1..14).map { ChannelOption(it, SoftApConfigurationCompat.BAND_2GHZ) }
|
|
||||||
}
|
|
||||||
private val channels5G by lazy {
|
private val channels5G by lazy {
|
||||||
baseOptions + (1..196).map { ChannelOption(it, SoftApConfigurationCompat.BAND_5GHZ) }
|
channels2G + (1..196).map { ChannelOption(SoftApConfigurationCompat.BAND_5GHZ, it) }
|
||||||
}
|
|
||||||
@get:RequiresApi(30)
|
|
||||||
private val channels6G by lazy {
|
|
||||||
baseOptions + (1..233).map { ChannelOption(it, SoftApConfigurationCompat.BAND_6GHZ) }
|
|
||||||
}
|
|
||||||
@get:RequiresApi(31)
|
|
||||||
private val channels60G by lazy {
|
|
||||||
baseOptions + (1..6).map { ChannelOption(it, SoftApConfigurationCompat.BAND_60GHZ) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun genAutoOptions(band: Int) = (1..band).filter { it and band == it }.map { ChannelOption(it) }
|
||||||
/**
|
/**
|
||||||
* Source: https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/c2fc6a1/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java#1396
|
* Source: https://android.googlesource.com/platform/frameworks/opt/net/wifi/+/c2fc6a1/service/java/com/android/server/wifi/p2p/SupplicantP2pIfaceHal.java#1396
|
||||||
*/
|
*/
|
||||||
private val p2pChannels by lazy {
|
private val p2pUnsafeOptions by lazy {
|
||||||
baseOptions + (15..165).map { ChannelOption(it, SoftApConfigurationCompat.BAND_5GHZ) }
|
listOf(ChannelOption(SoftApConfigurationCompat.BAND_LEGACY)) +
|
||||||
|
channels2G + (15..165).map { ChannelOption(SoftApConfigurationCompat.BAND_5GHZ, it) }
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Also used for legacy soft ap.
|
||||||
|
*/
|
||||||
|
private val p2pSafeOptions by lazy { genAutoOptions(SoftApConfigurationCompat.BAND_LEGACY) + channels5G }
|
||||||
|
@get:RequiresApi(30)
|
||||||
|
private val softApOptions by lazy {
|
||||||
|
val channels6G = channels5G + (1..233).map { ChannelOption(SoftApConfigurationCompat.BAND_6GHZ, it) }
|
||||||
|
if (Build.VERSION.SDK_INT >= 31) {
|
||||||
|
genAutoOptions(SoftApConfigurationCompat.BAND_ANY_31) +
|
||||||
|
channels6G + (1..6).map { ChannelOption(SoftApConfigurationCompat.BAND_60GHZ, it) }
|
||||||
|
} else genAutoOptions(SoftApConfigurationCompat.BAND_ANY_30) + channels6G
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,34 +86,36 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
*/
|
*/
|
||||||
val p2pMode: Boolean = false) : Parcelable
|
val p2pMode: Boolean = false) : Parcelable
|
||||||
|
|
||||||
private open class ChannelOption(val channel: Int = 0, private val band: Int = 0) {
|
private open class ChannelOption(val band: Int = 0, val channel: Int = 0) {
|
||||||
object Disabled : ChannelOption(-1) {
|
object Disabled : ChannelOption(-1) {
|
||||||
override fun toString() = app.getString(R.string.wifi_ap_choose_disabled)
|
override fun toString() = app.getString(R.string.wifi_ap_choose_disabled)
|
||||||
}
|
}
|
||||||
object Auto : ChannelOption() {
|
override fun toString() = if (channel == 0) {
|
||||||
override fun toString() = app.getString(R.string.wifi_ap_choose_auto)
|
val format = DecimalFormat("#.#", DecimalFormatSymbols.getInstance(app.resources.configuration.locale))
|
||||||
}
|
app.getString(R.string.wifi_ap_choose_G, arrayOf(
|
||||||
override fun toString() = "${SoftApConfigurationCompat.channelToFrequency(band, channel)} MHz ($channel)"
|
SoftApConfigurationCompat.BAND_2GHZ to 2.4,
|
||||||
|
SoftApConfigurationCompat.BAND_5GHZ to 5,
|
||||||
|
SoftApConfigurationCompat.BAND_6GHZ to 6,
|
||||||
|
SoftApConfigurationCompat.BAND_60GHZ to 60,
|
||||||
|
).filter { (mask, _) -> band and mask == mask }.joinToString("/") { (_, name) -> format.format(name) })
|
||||||
|
} else "${SoftApConfigurationCompat.channelToFrequency(band, channel)} MHz ($channel)"
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var dialogView: DialogWifiApBinding
|
private lateinit var dialogView: DialogWifiApBinding
|
||||||
private lateinit var base: SoftApConfigurationCompat
|
private lateinit var base: SoftApConfigurationCompat
|
||||||
private var started = false
|
private var started = false
|
||||||
private val currentChannels5G get() = if (arg.p2pMode && !RepeaterService.safeMode) p2pChannels else channels5G
|
private val currentChannels get() = when {
|
||||||
|
arg.p2pMode && !RepeaterService.safeMode -> p2pUnsafeOptions
|
||||||
|
arg.p2pMode || Build.VERSION.SDK_INT < 30 -> p2pSafeOptions
|
||||||
|
else -> softApOptions
|
||||||
|
}
|
||||||
override val ret get() = Arg(generateConfig())
|
override val ret get() = Arg(generateConfig())
|
||||||
|
|
||||||
private fun generateChannels() = SparseIntArray(4).apply {
|
private fun generateChannels() = SparseIntArray(2).apply {
|
||||||
for ((band, spinner) in arrayOf(SoftApConfigurationCompat.BAND_2GHZ to dialogView.band2G,
|
if (!arg.p2pMode && Build.VERSION.SDK_INT >= 31) {
|
||||||
SoftApConfigurationCompat.BAND_5GHZ to dialogView.band5G,
|
(dialogView.bandSecondary.selectedItem as ChannelOption?)?.apply { if (band >= 0) put(band, channel) }
|
||||||
SoftApConfigurationCompat.BAND_6GHZ to dialogView.band6G,
|
|
||||||
SoftApConfigurationCompat.BAND_60GHZ to dialogView.band60G)) {
|
|
||||||
val channel = (spinner.selectedItem as ChannelOption?)?.channel
|
|
||||||
if (channel != null && channel >= 0) append(band, channel)
|
|
||||||
}
|
}
|
||||||
}.let {
|
(dialogView.bandPrimary.selectedItem as ChannelOption).apply { put(band, channel) }
|
||||||
if (arg.p2pMode || Build.VERSION.SDK_INT < 31 || !dialogView.bridgedMode.isChecked || it.size() > 2) {
|
|
||||||
SoftApConfigurationCompat.optimizeChannels(it)
|
|
||||||
} else it
|
|
||||||
}
|
}
|
||||||
private fun generateConfig(full: Boolean = true) = base.copy(
|
private fun generateConfig(full: Boolean = true) = base.copy(
|
||||||
ssid = dialogView.ssid.text.toString(),
|
ssid = dialogView.ssid.text.toString(),
|
||||||
@@ -188,15 +196,10 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
if (!arg.readOnly) onItemSelectedListener = this@WifiApDialogFragment
|
if (!arg.readOnly) onItemSelectedListener = this@WifiApDialogFragment
|
||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= 23 || arg.p2pMode) {
|
if (Build.VERSION.SDK_INT >= 23 || arg.p2pMode) {
|
||||||
dialogView.band2G.configure(channels2G)
|
dialogView.bandPrimary.configure(currentChannels)
|
||||||
dialogView.band5G.configure(currentChannels5G)
|
if (Build.VERSION.SDK_INT >= 31 && !arg.p2pMode) {
|
||||||
if (Build.VERSION.SDK_INT >= 30 && !arg.p2pMode) dialogView.band6G.configure(channels6G)
|
dialogView.bandSecondary.configure(listOf(ChannelOption.Disabled) + currentChannels)
|
||||||
else dialogView.bandWrapper6G.isGone = true
|
} else dialogView.bandSecondary.isGone = true
|
||||||
if (Build.VERSION.SDK_INT >= 31 && !arg.p2pMode) dialogView.band60G.configure(channels60G) else {
|
|
||||||
dialogView.bandWrapper60G.isGone = true
|
|
||||||
dialogView.bridgedMode.isGone = true
|
|
||||||
dialogView.bridgedModeOpportunisticShutdown.isGone = true
|
|
||||||
}
|
|
||||||
} else dialogView.bandGroup.isGone = true
|
} else dialogView.bandGroup.isGone = true
|
||||||
if (arg.p2pMode || Build.VERSION.SDK_INT < 30) dialogView.accessControlGroup.isGone = true
|
if (arg.p2pMode || Build.VERSION.SDK_INT < 30) dialogView.accessControlGroup.isGone = true
|
||||||
else if (!arg.readOnly) {
|
else if (!arg.readOnly) {
|
||||||
@@ -210,41 +213,22 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
else if (arg.p2pMode || Build.VERSION.SDK_INT < 31) dialogView.macRandomization.isGone = true
|
else if (arg.p2pMode || Build.VERSION.SDK_INT < 31) dialogView.macRandomization.isGone = true
|
||||||
if (arg.p2pMode || Build.VERSION.SDK_INT < 31) {
|
if (arg.p2pMode || Build.VERSION.SDK_INT < 31) {
|
||||||
dialogView.ieee80211ax.isGone = true
|
dialogView.ieee80211ax.isGone = true
|
||||||
|
dialogView.bridgedModeOpportunisticShutdown.isGone = true
|
||||||
dialogView.userConfig.isGone = true
|
dialogView.userConfig.isGone = true
|
||||||
}
|
}
|
||||||
base = arg.configuration
|
base = arg.configuration
|
||||||
populateFromConfiguration()
|
populateFromConfiguration()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun locate(band: Int, channels: List<ChannelOption>): Int {
|
private fun locate(i: Int): Int {
|
||||||
val channel = base.getChannel(band)
|
val band = base.channels.keyAt(i)
|
||||||
val selection = channels.indexOfFirst { it.channel == channel }
|
val channel = base.channels.valueAt(i)
|
||||||
|
val selection = currentChannels.indexOfFirst { it.band == band && it.channel == channel }
|
||||||
return if (selection == -1) {
|
return if (selection == -1) {
|
||||||
Timber.w(Exception("Unable to locate $band, $channel, ${arg.p2pMode && !RepeaterService.safeMode}"))
|
Timber.w(Exception("Unable to locate $band, $channel, ${arg.p2pMode && !RepeaterService.safeMode}"))
|
||||||
0
|
0
|
||||||
} else selection
|
} else selection
|
||||||
}
|
}
|
||||||
private var userBridgedMode = false
|
|
||||||
private fun setBridgedMode(): Boolean {
|
|
||||||
var auto = 0
|
|
||||||
var set = 0
|
|
||||||
for (s in arrayOf(dialogView.band2G, dialogView.band5G, dialogView.band6G,
|
|
||||||
dialogView.band60G)) when (s.selectedItem) {
|
|
||||||
is ChannelOption.Auto -> auto = 1
|
|
||||||
!is ChannelOption.Disabled -> ++set
|
|
||||||
}
|
|
||||||
if (auto + set > 1) {
|
|
||||||
if (dialogView.bridgedMode.isEnabled) {
|
|
||||||
userBridgedMode = dialogView.bridgedMode.isChecked
|
|
||||||
dialogView.bridgedMode.isEnabled = false
|
|
||||||
dialogView.bridgedMode.isChecked = true
|
|
||||||
}
|
|
||||||
} else if (!dialogView.bridgedMode.isEnabled) {
|
|
||||||
dialogView.bridgedMode.isEnabled = true
|
|
||||||
dialogView.bridgedMode.isChecked = userBridgedMode
|
|
||||||
}
|
|
||||||
return auto + set > 0
|
|
||||||
}
|
|
||||||
private fun populateFromConfiguration() {
|
private fun populateFromConfiguration() {
|
||||||
dialogView.ssid.setText(base.ssid)
|
dialogView.ssid.setText(base.ssid)
|
||||||
if (!arg.p2pMode) dialogView.security.setSelection(base.securityType)
|
if (!arg.p2pMode) dialogView.security.setSelection(base.securityType)
|
||||||
@@ -252,13 +236,10 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
dialogView.autoShutdown.isChecked = base.isAutoShutdownEnabled
|
dialogView.autoShutdown.isChecked = base.isAutoShutdownEnabled
|
||||||
dialogView.timeout.setText(base.shutdownTimeoutMillis.let { if (it == 0L) "" else it.toString() })
|
dialogView.timeout.setText(base.shutdownTimeoutMillis.let { if (it == 0L) "" else it.toString() })
|
||||||
if (Build.VERSION.SDK_INT >= 23 || arg.p2pMode) {
|
if (Build.VERSION.SDK_INT >= 23 || arg.p2pMode) {
|
||||||
dialogView.band2G.setSelection(locate(SoftApConfigurationCompat.BAND_2GHZ, channels2G))
|
dialogView.bandPrimary.setSelection(locate(0))
|
||||||
dialogView.band5G.setSelection(locate(SoftApConfigurationCompat.BAND_5GHZ, currentChannels5G))
|
if (Build.VERSION.SDK_INT >= 31 && !arg.p2pMode) {
|
||||||
dialogView.band6G.setSelection(locate(SoftApConfigurationCompat.BAND_6GHZ, channels6G))
|
dialogView.bandSecondary.setSelection(if (base.channels.size() > 1) locate(1) + 1 else 0)
|
||||||
dialogView.band60G.setSelection(locate(SoftApConfigurationCompat.BAND_60GHZ, channels60G))
|
}
|
||||||
userBridgedMode = base.channels.size() > 1
|
|
||||||
dialogView.bridgedMode.isChecked = userBridgedMode
|
|
||||||
setBridgedMode()
|
|
||||||
}
|
}
|
||||||
dialogView.bssid.setText(base.bssid?.toString())
|
dialogView.bssid.setText(base.bssid?.toString())
|
||||||
dialogView.hiddenSsid.isChecked = base.isHiddenSsid
|
dialogView.hiddenSsid.isChecked = base.isHiddenSsid
|
||||||
@@ -308,26 +289,14 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dialogView.timeoutWrapper.error = timeoutError
|
dialogView.timeoutWrapper.error = timeoutError
|
||||||
val bandError = if (arg.p2pMode || Build.VERSION.SDK_INT < 30) {
|
val bandError = if (!arg.p2pMode && Build.VERSION.SDK_INT >= 30) {
|
||||||
val option5G = dialogView.band5G.selectedItem
|
|
||||||
val valid = when (dialogView.band2G.selectedItem) {
|
|
||||||
is ChannelOption.Disabled -> option5G !is ChannelOption.Disabled &&
|
|
||||||
(!arg.p2pMode || RepeaterService.safeMode || option5G !is ChannelOption.Auto)
|
|
||||||
is ChannelOption.Auto ->
|
|
||||||
(arg.p2pMode || Build.VERSION.SDK_INT >= 28) && option5G is ChannelOption.Auto ||
|
|
||||||
(!arg.p2pMode || RepeaterService.safeMode) && option5G is ChannelOption.Disabled
|
|
||||||
else -> option5G is ChannelOption.Disabled
|
|
||||||
}
|
|
||||||
if (valid) null else ""
|
|
||||||
} else {
|
|
||||||
if (Build.VERSION.SDK_INT >= 31) setBridgedMode()
|
|
||||||
try {
|
try {
|
||||||
SoftApConfigurationCompat.testPlatformValidity(generateChannels())
|
SoftApConfigurationCompat.testPlatformValidity(generateChannels())
|
||||||
null
|
null
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.readableMessage
|
e.readableMessage
|
||||||
}
|
}
|
||||||
}
|
} else null
|
||||||
dialogView.bandError.isGone = bandError.isNullOrEmpty()
|
dialogView.bandError.isGone = bandError.isNullOrEmpty()
|
||||||
dialogView.bandError.text = bandError
|
dialogView.bandError.text = bandError
|
||||||
dialogView.bssidWrapper.error = null
|
dialogView.bssidWrapper.error = null
|
||||||
|
|||||||
@@ -128,88 +128,27 @@
|
|||||||
android:id="@+id/band_group"
|
android:id="@+id/band_group"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dip"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
<com.google.android.material.divider.MaterialDivider
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
style="@style/wifi_item_divider" />
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
style="@style/wifi_item_subhead"
|
style="@style/wifi_item_label"
|
||||||
android:text="@string/wifi_hotspot_ap_band_title" />
|
android:text="@string/wifi_hotspot_ap_band_title" />
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dip"
|
|
||||||
style="@style/wifi_item_label"
|
|
||||||
android:text="@string/wifi_ap_choose_2G" />
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:id="@+id/band_2G"
|
android:id="@+id/band_primary"
|
||||||
style="@style/wifi_item_content"
|
style="@style/wifi_item_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="@dimen/touch_target_min"
|
android:minHeight="@dimen/touch_target_min"
|
||||||
android:prompt="@string/wifi_ap_choose_2G" />
|
android:prompt="@string/wifi_hotspot_ap_band_title" />
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dip"
|
|
||||||
style="@style/wifi_item_label"
|
|
||||||
android:text="@string/wifi_ap_choose_5G" />
|
|
||||||
<Spinner
|
<Spinner
|
||||||
android:id="@+id/band_5G"
|
android:id="@+id/band_secondary"
|
||||||
style="@style/wifi_item_content"
|
style="@style/wifi_item_content"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="@dimen/touch_target_min"
|
android:minHeight="@dimen/touch_target_min"
|
||||||
android:prompt="@string/wifi_ap_choose_5G" />
|
android:prompt="@string/wifi_hotspot_ap_band_title" />
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/band_wrapper_6G"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dip"
|
|
||||||
android:orientation="vertical">
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
style="@style/wifi_item_label"
|
|
||||||
android:text="@string/wifi_ap_choose_6G" />
|
|
||||||
<Spinner
|
|
||||||
android:id="@+id/band_6G"
|
|
||||||
style="@style/wifi_item_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="@dimen/touch_target_min"
|
|
||||||
android:prompt="@string/wifi_ap_choose_6G" />
|
|
||||||
</LinearLayout>
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/band_wrapper_60G"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dip"
|
|
||||||
android:orientation="vertical">
|
|
||||||
<TextView
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
style="@style/wifi_item_label"
|
|
||||||
android:text="@string/wifi_ap_choose_60G" />
|
|
||||||
<Spinner
|
|
||||||
android:id="@+id/band_60G"
|
|
||||||
style="@style/wifi_item_content"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:minHeight="@dimen/touch_target_min"
|
|
||||||
android:prompt="@string/wifi_ap_choose_60G" />
|
|
||||||
</LinearLayout>
|
|
||||||
<Switch
|
|
||||||
android:id="@+id/bridged_mode"
|
|
||||||
style="@style/wifi_item_label"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dip"
|
|
||||||
android:minHeight="@dimen/touch_target_min"
|
|
||||||
android:text="@string/wifi_bridged_mode" />
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/band_error"
|
android:id="@+id/band_error"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -220,14 +159,6 @@
|
|||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:text="error text placeholder"
|
tools:text="error text placeholder"
|
||||||
tools:visibility="visible"/>
|
tools:visibility="visible"/>
|
||||||
<Switch
|
|
||||||
android:id="@+id/bridged_mode_opportunistic_shutdown"
|
|
||||||
style="@style/wifi_item_label"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="8dip"
|
|
||||||
android:minHeight="@dimen/touch_target_min"
|
|
||||||
android:text="@string/wifi_bridged_mode_opportunistic_shutdown" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@@ -354,6 +285,14 @@
|
|||||||
android:layout_marginTop="8dip"
|
android:layout_marginTop="8dip"
|
||||||
android:minHeight="@dimen/touch_target_min"
|
android:minHeight="@dimen/touch_target_min"
|
||||||
android:text="@string/wifi_ieee_80211ax" />
|
android:text="@string/wifi_ieee_80211ax" />
|
||||||
|
<Switch
|
||||||
|
android:id="@+id/bridged_mode_opportunistic_shutdown"
|
||||||
|
style="@style/wifi_item_label"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dip"
|
||||||
|
android:minHeight="@dimen/touch_target_min"
|
||||||
|
android:text="@string/wifi_bridged_mode_opportunistic_shutdown" />
|
||||||
<Switch
|
<Switch
|
||||||
android:id="@+id/user_config"
|
android:id="@+id/user_config"
|
||||||
style="@style/wifi_item_label"
|
style="@style/wifi_item_label"
|
||||||
|
|||||||
@@ -154,9 +154,7 @@
|
|||||||
<string name="wifi_password">Password</string>
|
<string name="wifi_password">Password</string>
|
||||||
<string name="wifi_hotspot_auto_off" msgid="5858098059725925084">"L\'hotspot Wi‑Fi viene disattivato se non ci sono dispositivi collegati"</string>
|
<string name="wifi_hotspot_auto_off" msgid="5858098059725925084">"L\'hotspot Wi‑Fi viene disattivato se non ci sono dispositivi collegati"</string>
|
||||||
<string name="wifi_hotspot_ap_band_title">Banda AP</string>
|
<string name="wifi_hotspot_ap_band_title">Banda AP</string>
|
||||||
<string name="wifi_ap_choose_auto" msgid="2677800651271769965">"Automatica"</string>
|
<string name="wifi_ap_choose_G" msgid="8724267386885036210">"Banda a %s GHz"</string>
|
||||||
<string name="wifi_ap_choose_2G" msgid="8724267386885036210">"Banda a 2,4 GHz"</string>
|
|
||||||
<string name="wifi_ap_choose_5G" msgid="8813128641914385634">"Banda a 5 GHz"</string>
|
|
||||||
<string name="wifi_advanced_mac_address_title" msgid="6571335466330978393">"Indirizzo MAC"</string>
|
<string name="wifi_advanced_mac_address_title" msgid="6571335466330978393">"Indirizzo MAC"</string>
|
||||||
<string name="wifi_hidden_network" msgid="973162091800925000">"Rete nascosta"</string>
|
<string name="wifi_hidden_network" msgid="973162091800925000">"Rete nascosta"</string>
|
||||||
<string name="wifi_save">Salva</string>
|
<string name="wifi_save">Salva</string>
|
||||||
|
|||||||
@@ -59,11 +59,7 @@
|
|||||||
<string name="wifi_password" msgid="5948219759936151048">"Пароль"</string>
|
<string name="wifi_password" msgid="5948219759936151048">"Пароль"</string>
|
||||||
<string name="wifi_hotspot_auto_off" msgid="5858098059725925084">"Выключать точку доступа Wi‑Fi автоматически, если к ней не подключено ни одного устройства"</string>
|
<string name="wifi_hotspot_auto_off" msgid="5858098059725925084">"Выключать точку доступа Wi‑Fi автоматически, если к ней не подключено ни одного устройства"</string>
|
||||||
<string name="wifi_hotspot_ap_band_title" msgid="1165801173359290681">"Диапазон частот Wi-Fi"</string>
|
<string name="wifi_hotspot_ap_band_title" msgid="1165801173359290681">"Диапазон частот Wi-Fi"</string>
|
||||||
<string name="wifi_ap_choose_auto" msgid="2677800651271769965">"Авто"</string>
|
<string name="wifi_ap_choose_G" msgid="8724267386885036210">"%s ГГц"</string>
|
||||||
<string name="wifi_ap_choose_2G" msgid="8724267386885036210">"2,4 ГГц"</string>
|
|
||||||
<string name="wifi_ap_choose_5G" msgid="8813128641914385634">"5 ГГц"</string>
|
|
||||||
<string name="wifi_ap_choose_6G">"6 ГГц"</string>
|
|
||||||
<string name="wifi_ap_choose_60G">"60 ГГц"</string>
|
|
||||||
<string name="wifi_advanced_mac_address_title" msgid="6571335466330978393">"MAC-адрес"</string>
|
<string name="wifi_advanced_mac_address_title" msgid="6571335466330978393">"MAC-адрес"</string>
|
||||||
<string name="wifi_hidden_network" msgid="973162091800925000">"Скрытая сеть"</string>
|
<string name="wifi_hidden_network" msgid="973162091800925000">"Скрытая сеть"</string>
|
||||||
<string name="wifi_save" msgid="3331121567988522826">"Сохранить"</string>
|
<string name="wifi_save" msgid="3331121567988522826">"Сохранить"</string>
|
||||||
|
|||||||
@@ -180,11 +180,7 @@
|
|||||||
<string name="wifi_hotspot_timeout_default">默认延迟:%d 毫秒</string>
|
<string name="wifi_hotspot_timeout_default">默认延迟:%d 毫秒</string>
|
||||||
<string name="wifi_hotspot_ap_band_title" msgid="1165801173359290681">"AP 频段"</string>
|
<string name="wifi_hotspot_ap_band_title" msgid="1165801173359290681">"AP 频段"</string>
|
||||||
<string name="wifi_ap_choose_disabled">Disabled</string>
|
<string name="wifi_ap_choose_disabled">Disabled</string>
|
||||||
<string name="wifi_ap_choose_auto" msgid="2677800651271769965">"自动"</string>
|
<string name="wifi_ap_choose_G" msgid="8724267386885036210">"%s GHz 频段"</string>
|
||||||
<string name="wifi_ap_choose_2G" msgid="8724267386885036210">"2.4 GHz 频段"</string>
|
|
||||||
<string name="wifi_ap_choose_5G" msgid="8813128641914385634">"5 GHz 频段"</string>
|
|
||||||
<string name="wifi_ap_choose_6G">6 GHz 频段</string>
|
|
||||||
<string name="wifi_ap_choose_60G">60 GHz 频段</string>
|
|
||||||
<string name="wifi_hotspot_access_control_title">访问控制</string>
|
<string name="wifi_hotspot_access_control_title">访问控制</string>
|
||||||
<string name="wifi_hotspot_ap_advanced_title">高级接入点设置</string>
|
<string name="wifi_hotspot_ap_advanced_title">高级接入点设置</string>
|
||||||
<string name="wifi_advanced_mac_address_title" msgid="6571335466330978393">"MAC 地址"</string>
|
<string name="wifi_advanced_mac_address_title" msgid="6571335466330978393">"MAC 地址"</string>
|
||||||
@@ -194,7 +190,6 @@
|
|||||||
<string name="wifi_blocked_list">设备黑名单</string>
|
<string name="wifi_blocked_list">设备黑名单</string>
|
||||||
<string name="wifi_allowed_list">设备白名单</string>
|
<string name="wifi_allowed_list">设备白名单</string>
|
||||||
<string name="wifi_mac_randomization">随机生成 MAC 地址</string>
|
<string name="wifi_mac_randomization">随机生成 MAC 地址</string>
|
||||||
<string name="wifi_bridged_mode">启用无线接入点桥接模式</string>
|
|
||||||
<string name="wifi_bridged_mode_opportunistic_shutdown">启用桥接模式伺机关闭</string>
|
<string name="wifi_bridged_mode_opportunistic_shutdown">启用桥接模式伺机关闭</string>
|
||||||
<string name="wifi_ieee_80211ax">启用 Wi\u2011Fi 6</string>
|
<string name="wifi_ieee_80211ax">启用 Wi\u2011Fi 6</string>
|
||||||
<string name="wifi_user_config">用户提供配置</string>
|
<string name="wifi_user_config">用户提供配置</string>
|
||||||
|
|||||||
@@ -177,11 +177,7 @@
|
|||||||
<string name="wifi_hotspot_timeout_default">默認延遲:%d 毫秒</string>
|
<string name="wifi_hotspot_timeout_default">默認延遲:%d 毫秒</string>
|
||||||
<string name="wifi_hotspot_ap_band_title" msgid="1165801173359290681">AP 頻帶</string>
|
<string name="wifi_hotspot_ap_band_title" msgid="1165801173359290681">AP 頻帶</string>
|
||||||
<string name="wifi_ap_choose_disabled">停用</string>
|
<string name="wifi_ap_choose_disabled">停用</string>
|
||||||
<string name="wifi_ap_choose_auto" msgid="2677800651271769965">自動</string>
|
<string name="wifi_ap_choose_G" msgid="8724267386885036210">%s GHz 頻帶</string>
|
||||||
<string name="wifi_ap_choose_2G" msgid="8724267386885036210">2.4 GHz 頻帶</string>
|
|
||||||
<string name="wifi_ap_choose_5G" msgid="8813128641914385634">5 GHz 頻帶</string>
|
|
||||||
<string name="wifi_ap_choose_6G">6 GHz 頻帶</string>
|
|
||||||
<string name="wifi_ap_choose_60G">60 GHz 頻帶</string>
|
|
||||||
<string name="wifi_advanced_mac_address_title" msgid="6571335466330978393">"MAC 地址"</string>
|
<string name="wifi_advanced_mac_address_title" msgid="6571335466330978393">"MAC 地址"</string>
|
||||||
<string name="wifi_hidden_network" msgid="973162091800925000">"隱藏的網路"</string>
|
<string name="wifi_hidden_network" msgid="973162091800925000">"隱藏的網路"</string>
|
||||||
<string name="wifi_max_clients">允許的連接裝置數量</string>
|
<string name="wifi_max_clients">允許的連接裝置數量</string>
|
||||||
|
|||||||
@@ -203,11 +203,7 @@
|
|||||||
<string name="wifi_hotspot_timeout_default">Default timeout: %dms</string>
|
<string name="wifi_hotspot_timeout_default">Default timeout: %dms</string>
|
||||||
<string name="wifi_hotspot_ap_band_title">AP Band</string>
|
<string name="wifi_hotspot_ap_band_title">AP Band</string>
|
||||||
<string name="wifi_ap_choose_disabled">Disabled</string>
|
<string name="wifi_ap_choose_disabled">Disabled</string>
|
||||||
<string name="wifi_ap_choose_auto">Auto</string>
|
<string name="wifi_ap_choose_G">%s GHz Band</string>
|
||||||
<string name="wifi_ap_choose_2G">2.4 GHz Band</string>
|
|
||||||
<string name="wifi_ap_choose_5G">5 GHz Band</string>
|
|
||||||
<string name="wifi_ap_choose_6G">6 GHz Band</string>
|
|
||||||
<string name="wifi_ap_choose_60G">60 GHz Band</string>
|
|
||||||
<string name="wifi_hotspot_access_control_title">Access Control</string>
|
<string name="wifi_hotspot_access_control_title">Access Control</string>
|
||||||
<string name="wifi_hotspot_ap_advanced_title">Advanced AP Options</string>
|
<string name="wifi_hotspot_ap_advanced_title">Advanced AP Options</string>
|
||||||
<string name="wifi_advanced_mac_address_title">MAC address</string>
|
<string name="wifi_advanced_mac_address_title">MAC address</string>
|
||||||
@@ -217,7 +213,6 @@
|
|||||||
<string name="wifi_blocked_list">Blocked list of clients</string>
|
<string name="wifi_blocked_list">Blocked list of clients</string>
|
||||||
<string name="wifi_allowed_list">Allowed 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_mac_randomization">Use randomized MAC</string>
|
||||||
<string name="wifi_bridged_mode">Enable Bridged Access point (AP) concurrency</string>
|
|
||||||
<string name="wifi_bridged_mode_opportunistic_shutdown">Enable Bridged mode opportunistic shutdown</string>
|
<string name="wifi_bridged_mode_opportunistic_shutdown">Enable Bridged mode opportunistic shutdown</string>
|
||||||
<string name="wifi_ieee_80211ax">Enable Wi\u2011Fi 6</string>
|
<string name="wifi_ieee_80211ax">Enable Wi\u2011Fi 6</string>
|
||||||
<string name="wifi_user_config">User Supplied Configuration</string>
|
<string name="wifi_user_config">User Supplied Configuration</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user