Refine channel error checking and allow multi-channel auto
This commit is contained in:
@@ -226,7 +226,7 @@ class RepeaterManager(private val parent: TetheringFragment) : Manager(), Servic
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
private suspend fun updateConfiguration(config: SoftApConfigurationCompat) {
|
private suspend fun updateConfiguration(config: SoftApConfigurationCompat) {
|
||||||
val (band, channel) = config.requireSingleBand()
|
val (band, channel) = SoftApConfigurationCompat.requireSingleBand(config.channels)
|
||||||
if (RepeaterService.safeMode) {
|
if (RepeaterService.safeMode) {
|
||||||
RepeaterService.networkName = config.ssid
|
RepeaterService.networkName = config.ssid
|
||||||
RepeaterService.deviceAddress = config.bssid
|
RepeaterService.deviceAddress = config.bssid
|
||||||
|
|||||||
@@ -333,6 +333,33 @@ data class SoftApConfigurationCompat(
|
|||||||
Build.VERSION.SDK_INT < 31 || isUserConfiguration(this) as Boolean,
|
Build.VERSION.SDK_INT < 31 || isUserConfiguration(this) as Boolean,
|
||||||
this,
|
this,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only single band/channel can be supplied on API 23-30
|
||||||
|
*/
|
||||||
|
fun requireSingleBand(channels: SparseIntArray): Pair<Int, Int> {
|
||||||
|
require(channels.size() == 1) { "Unsupported number of bands configured" }
|
||||||
|
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)
|
||||||
|
private fun setChannelsCompat(builder: Any, channels: SparseIntArray) = if (Build.VERSION.SDK_INT < 31) {
|
||||||
|
val (band, channel) = requireSingleBand(channels)
|
||||||
|
if (channel == 0) setBand(builder, band) else setChannel(builder, channel, band)
|
||||||
|
} else setChannels(builder, channels)
|
||||||
|
@get:RequiresApi(30)
|
||||||
|
private val staticBuilder by lazy { classBuilder.newInstance() }
|
||||||
|
@RequiresApi(30)
|
||||||
|
fun testPlatformValidity(channels: SparseIntArray) = setChannels(staticBuilder, channels)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@@ -342,13 +369,6 @@ data class SoftApConfigurationCompat(
|
|||||||
bssidAddr = value?.addr
|
bssidAddr = value?.addr
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Only single band/channel can be supplied on API 23-30
|
|
||||||
*/
|
|
||||||
fun requireSingleBand(): Pair<Int, Int> {
|
|
||||||
require(channels.size() == 1) { "Unsupported number of bands configured" }
|
|
||||||
return channels.keyAt(0) to channels.valueAt(0)
|
|
||||||
}
|
|
||||||
fun getChannel(band: Int): Int {
|
fun getChannel(band: Int): Int {
|
||||||
var result = -1
|
var result = -1
|
||||||
repeat(channels.size()) { i ->
|
repeat(channels.size()) { i ->
|
||||||
@@ -367,17 +387,6 @@ data class SoftApConfigurationCompat(
|
|||||||
}, channel)
|
}, channel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun optimizeChannels(channels: SparseIntArray = this.channels) {
|
|
||||||
this.channels = 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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setMacRandomizationEnabled(enabled: Boolean) {
|
fun setMacRandomizationEnabled(enabled: Boolean) {
|
||||||
macRandomizationSetting = if (enabled) RANDOMIZATION_PERSISTENT else RANDOMIZATION_NONE
|
macRandomizationSetting = if (enabled) RANDOMIZATION_PERSISTENT else RANDOMIZATION_NONE
|
||||||
@@ -393,7 +402,7 @@ data class SoftApConfigurationCompat(
|
|||||||
@Deprecated("Class deprecated in framework, use toPlatform().toWifiConfiguration()")
|
@Deprecated("Class deprecated in framework, use toPlatform().toWifiConfiguration()")
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
fun toWifiConfiguration(): android.net.wifi.WifiConfiguration {
|
fun toWifiConfiguration(): android.net.wifi.WifiConfiguration {
|
||||||
val (band, channel) = requireSingleBand()
|
val (band, channel) = requireSingleBand(channels)
|
||||||
val wc = underlying as? android.net.wifi.WifiConfiguration
|
val wc = underlying as? android.net.wifi.WifiConfiguration
|
||||||
val result = if (wc == null) android.net.wifi.WifiConfiguration() else android.net.wifi.WifiConfiguration(wc)
|
val result = if (wc == null) android.net.wifi.WifiConfiguration() else android.net.wifi.WifiConfiguration(wc)
|
||||||
val original = wc?.toCompat()
|
val original = wc?.toCompat()
|
||||||
@@ -438,10 +447,7 @@ data class SoftApConfigurationCompat(
|
|||||||
setSsid(builder, ssid)
|
setSsid(builder, ssid)
|
||||||
setPassphrase(builder, if (securityType == SoftApConfiguration.SECURITY_TYPE_OPEN) null else passphrase,
|
setPassphrase(builder, if (securityType == SoftApConfiguration.SECURITY_TYPE_OPEN) null else passphrase,
|
||||||
securityType)
|
securityType)
|
||||||
if (Build.VERSION.SDK_INT >= 31) setChannels(builder, channels) else {
|
setChannelsCompat(builder, channels)
|
||||||
val (band, channel) = requireSingleBand()
|
|
||||||
if (channel == 0) setBand(builder, band) else setChannel(builder, channel, band)
|
|
||||||
}
|
|
||||||
setBssid(builder, bssid?.toPlatform())
|
setBssid(builder, bssid?.toPlatform())
|
||||||
setMaxNumberOfClients(builder, maxNumberOfClients)
|
setMaxNumberOfClients(builder, maxNumberOfClients)
|
||||||
setShutdownTimeoutMillis(builder, shutdownTimeoutMillis)
|
setShutdownTimeoutMillis(builder, shutdownTimeoutMillis)
|
||||||
|
|||||||
@@ -95,6 +95,19 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
private val currentChannels5G get() = if (arg.p2pMode && !RepeaterService.safeMode) p2pChannels else channels5G
|
private val currentChannels5G get() = if (arg.p2pMode && !RepeaterService.safeMode) p2pChannels else channels5G
|
||||||
override val ret get() = Arg(generateConfig())
|
override val ret get() = Arg(generateConfig())
|
||||||
|
|
||||||
|
private fun generateChannels() = SparseIntArray(4).apply {
|
||||||
|
for ((band, spinner) in arrayOf(SoftApConfigurationCompat.BAND_2GHZ to dialogView.band2G,
|
||||||
|
SoftApConfigurationCompat.BAND_5GHZ to dialogView.band5G,
|
||||||
|
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 {
|
||||||
|
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(),
|
||||||
passphrase = if (dialogView.password.length() != 0) dialogView.password.text.toString() else null).apply {
|
passphrase = if (dialogView.password.length() != 0) dialogView.password.text.toString() else null).apply {
|
||||||
@@ -107,19 +120,7 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
shutdownTimeoutMillis = dialogView.timeout.text.let { text ->
|
shutdownTimeoutMillis = dialogView.timeout.text.let { text ->
|
||||||
if (text.isNullOrEmpty()) 0 else text.toString().toLong()
|
if (text.isNullOrEmpty()) 0 else text.toString().toLong()
|
||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= 23 || arg.p2pMode) {
|
if (Build.VERSION.SDK_INT >= 23 || arg.p2pMode) channels = generateChannels()
|
||||||
val channels = SparseIntArray(4)
|
|
||||||
for ((band, spinner) in arrayOf(SoftApConfigurationCompat.BAND_2GHZ to dialogView.band2G,
|
|
||||||
SoftApConfigurationCompat.BAND_5GHZ to dialogView.band5G,
|
|
||||||
SoftApConfigurationCompat.BAND_6GHZ to dialogView.band6G,
|
|
||||||
SoftApConfigurationCompat.BAND_60GHZ to dialogView.band60G)) {
|
|
||||||
val channel = (spinner.selectedItem as ChannelOption?)?.channel
|
|
||||||
if (channel != null && channel >= 0) channels.append(band, channel)
|
|
||||||
}
|
|
||||||
if (!arg.p2pMode && Build.VERSION.SDK_INT >= 31 && dialogView.bridgedMode.isChecked) {
|
|
||||||
this.channels = channels
|
|
||||||
} else optimizeChannels(channels)
|
|
||||||
}
|
|
||||||
bssid = if (dialogView.bssid.length() != 0) {
|
bssid = if (dialogView.bssid.length() != 0) {
|
||||||
MacAddressCompat.fromString(dialogView.bssid.text.toString())
|
MacAddressCompat.fromString(dialogView.bssid.text.toString())
|
||||||
} else null
|
} else null
|
||||||
@@ -291,10 +292,9 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
dialogView.timeoutWrapper.error = timeoutError
|
dialogView.timeoutWrapper.error = timeoutError
|
||||||
val isBandValid = when {
|
val bandError = if (arg.p2pMode || Build.VERSION.SDK_INT <= 30) {
|
||||||
arg.p2pMode || Build.VERSION.SDK_INT in 23 until 30 -> {
|
|
||||||
val option5G = dialogView.band5G.selectedItem
|
val option5G = dialogView.band5G.selectedItem
|
||||||
when (dialogView.band2G.selectedItem) {
|
val valid = when (dialogView.band2G.selectedItem) {
|
||||||
is ChannelOption.Disabled -> option5G !is ChannelOption.Disabled &&
|
is ChannelOption.Disabled -> option5G !is ChannelOption.Disabled &&
|
||||||
(!arg.p2pMode || RepeaterService.safeMode || option5G !is ChannelOption.Auto)
|
(!arg.p2pMode || RepeaterService.safeMode || option5G !is ChannelOption.Auto)
|
||||||
is ChannelOption.Auto ->
|
is ChannelOption.Auto ->
|
||||||
@@ -302,18 +302,18 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
(!arg.p2pMode || RepeaterService.safeMode) && option5G is ChannelOption.Disabled
|
(!arg.p2pMode || RepeaterService.safeMode) && option5G is ChannelOption.Disabled
|
||||||
else -> option5G is ChannelOption.Disabled
|
else -> option5G is ChannelOption.Disabled
|
||||||
}
|
}
|
||||||
|
if (valid) null else ""
|
||||||
|
} else {
|
||||||
|
if (Build.VERSION.SDK_INT >= 31) setBridgedMode()
|
||||||
|
try {
|
||||||
|
SoftApConfigurationCompat.testPlatformValidity(generateChannels())
|
||||||
|
null
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.readableMessage
|
||||||
}
|
}
|
||||||
Build.VERSION.SDK_INT == 30 -> {
|
|
||||||
var expected = 1
|
|
||||||
var set = 0
|
|
||||||
for (s in arrayOf(dialogView.band2G, dialogView.band5G, dialogView.band6G)) when (s.selectedItem) {
|
|
||||||
is ChannelOption.Auto -> expected = 0
|
|
||||||
!is ChannelOption.Disabled -> ++set
|
|
||||||
}
|
|
||||||
set == expected
|
|
||||||
}
|
|
||||||
else -> setBridgedMode()
|
|
||||||
}
|
}
|
||||||
|
dialogView.bandError.isGone = bandError.isNullOrEmpty()
|
||||||
|
dialogView.bandError.text = bandError
|
||||||
dialogView.bssidWrapper.error = null
|
dialogView.bssidWrapper.error = null
|
||||||
val bssidValid = dialogView.bssid.length() == 0 || try {
|
val bssidValid = dialogView.bssid.length() == 0 || try {
|
||||||
MacAddressCompat.fromString(dialogView.bssid.text.toString())
|
MacAddressCompat.fromString(dialogView.bssid.text.toString())
|
||||||
@@ -353,7 +353,7 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
|
|||||||
} else true
|
} else true
|
||||||
val canCopy = timeoutError == null && bssidValid && maxClientError == null && listsNoError
|
val canCopy = timeoutError == null && bssidValid && maxClientError == null && listsNoError
|
||||||
(dialog as? AlertDialog)?.getButton(DialogInterface.BUTTON_POSITIVE)?.isEnabled =
|
(dialog as? AlertDialog)?.getButton(DialogInterface.BUTTON_POSITIVE)?.isEnabled =
|
||||||
ssidLength in 1..32 && passwordValid && isBandValid && canCopy
|
ssidLength in 1..32 && passwordValid && bandError == null && canCopy
|
||||||
dialogView.toolbar.menu.findItem(android.R.id.copy).isEnabled = canCopy
|
dialogView.toolbar.menu.findItem(android.R.id.copy).isEnabled = canCopy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,10 @@
|
|||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="300sp"
|
android:layout_width="300sp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@@ -208,6 +210,16 @@
|
|||||||
android:layout_marginTop="8dip"
|
android:layout_marginTop="8dip"
|
||||||
android:minHeight="@dimen/touch_target_min"
|
android:minHeight="@dimen/touch_target_min"
|
||||||
android:text="@string/wifi_bridged_mode" />
|
android:text="@string/wifi_bridged_mode" />
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/band_error"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dip"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.Design.Error"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:text="error text placeholder"
|
||||||
|
tools:visibility="visible"/>
|
||||||
<Switch
|
<Switch
|
||||||
android:id="@+id/bridged_mode_opportunistic_shutdown"
|
android:id="@+id/bridged_mode_opportunistic_shutdown"
|
||||||
style="@style/wifi_item_label"
|
style="@style/wifi_item_label"
|
||||||
|
|||||||
Reference in New Issue
Block a user