diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/manage/RepeaterManager.kt b/mobile/src/main/java/be/mygod/vpnhotspot/manage/RepeaterManager.kt index 796c8282..37522bf6 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/manage/RepeaterManager.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/manage/RepeaterManager.kt @@ -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 diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/SoftApConfigurationCompat.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/SoftApConfigurationCompat.kt index fc4ee751..d9ba375e 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/SoftApConfigurationCompat.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/SoftApConfigurationCompat.kt @@ -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 { + 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 { - 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) diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApDialogFragment.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApDialogFragment.kt index de86fd88..fcb13a4c 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApDialogFragment.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/wifi/WifiApDialogFragment.kt @@ -95,6 +95,19 @@ class WifiApDialogFragment : AlertDialogFragment= 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 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 { - 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 - + +