Refine channel error checking and allow multi-channel auto

This commit is contained in:
Mygod
2021-08-22 23:33:38 -04:00
parent e9081e67d7
commit 2856ad2080
4 changed files with 82 additions and 64 deletions

View File

@@ -226,7 +226,7 @@ class RepeaterManager(private val parent: TetheringFragment) : Manager(), Servic
return null
}
private suspend fun updateConfiguration(config: SoftApConfigurationCompat) {
val (band, channel) = config.requireSingleBand()
val (band, channel) = SoftApConfigurationCompat.requireSingleBand(config.channels)
if (RepeaterService.safeMode) {
RepeaterService.networkName = config.ssid
RepeaterService.deviceAddress = config.bssid

View File

@@ -333,6 +333,33 @@ data class SoftApConfigurationCompat(
Build.VERSION.SDK_INT < 31 || isUserConfiguration(this) as Boolean,
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")
@@ -342,13 +369,6 @@ data class SoftApConfigurationCompat(
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 {
var result = -1
repeat(channels.size()) { i ->
@@ -367,17 +387,6 @@ data class SoftApConfigurationCompat(
}, 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) {
macRandomizationSetting = if (enabled) RANDOMIZATION_PERSISTENT else RANDOMIZATION_NONE
@@ -393,7 +402,7 @@ data class SoftApConfigurationCompat(
@Deprecated("Class deprecated in framework, use toPlatform().toWifiConfiguration()")
@Suppress("DEPRECATION")
fun toWifiConfiguration(): android.net.wifi.WifiConfiguration {
val (band, channel) = requireSingleBand()
val (band, channel) = requireSingleBand(channels)
val wc = underlying as? android.net.wifi.WifiConfiguration
val result = if (wc == null) android.net.wifi.WifiConfiguration() else android.net.wifi.WifiConfiguration(wc)
val original = wc?.toCompat()
@@ -437,11 +446,8 @@ data class SoftApConfigurationCompat(
val builder = if (sac == null) classBuilder.newInstance() else newBuilder.newInstance(sac)
setSsid(builder, ssid)
setPassphrase(builder, if (securityType == SoftApConfiguration.SECURITY_TYPE_OPEN) null else passphrase,
securityType)
if (Build.VERSION.SDK_INT >= 31) setChannels(builder, channels) else {
val (band, channel) = requireSingleBand()
if (channel == 0) setBand(builder, band) else setChannel(builder, channel, band)
}
securityType)
setChannelsCompat(builder, channels)
setBssid(builder, bssid?.toPlatform())
setMaxNumberOfClients(builder, maxNumberOfClients)
setShutdownTimeoutMillis(builder, shutdownTimeoutMillis)

View File

@@ -95,6 +95,19 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
private val currentChannels5G get() = if (arg.p2pMode && !RepeaterService.safeMode) p2pChannels else channels5G
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(
ssid = dialogView.ssid.text.toString(),
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 ->
if (text.isNullOrEmpty()) 0 else text.toString().toLong()
}
if (Build.VERSION.SDK_INT >= 23 || arg.p2pMode) {
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)
}
if (Build.VERSION.SDK_INT >= 23 || arg.p2pMode) channels = generateChannels()
bssid = if (dialogView.bssid.length() != 0) {
MacAddressCompat.fromString(dialogView.bssid.text.toString())
} else null
@@ -291,29 +292,28 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
}
}
dialogView.timeoutWrapper.error = timeoutError
val isBandValid = when {
arg.p2pMode || Build.VERSION.SDK_INT in 23 until 30 -> {
val option5G = dialogView.band5G.selectedItem
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
}
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
}
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
if (valid) null else ""
} else {
if (Build.VERSION.SDK_INT >= 31) setBridgedMode()
try {
SoftApConfigurationCompat.testPlatformValidity(generateChannels())
null
} catch (e: Exception) {
e.readableMessage
}
else -> setBridgedMode()
}
dialogView.bandError.isGone = bandError.isNullOrEmpty()
dialogView.bandError.text = bandError
dialogView.bssidWrapper.error = null
val bssidValid = dialogView.bssid.length() == 0 || try {
MacAddressCompat.fromString(dialogView.bssid.text.toString())
@@ -353,7 +353,7 @@ class WifiApDialogFragment : AlertDialogFragment<WifiApDialogFragment.Arg, WifiA
} else true
val canCopy = timeoutError == null && bssidValid && maxClientError == null && listsNoError
(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
}

View File

@@ -16,11 +16,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="300sp"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="300sp"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
@@ -208,6 +210,16 @@
android:layout_marginTop="8dip"
android:minHeight="@dimen/touch_target_min"
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
android:id="@+id/bridged_mode_opportunistic_shutdown"
style="@style/wifi_item_label"