wifi aware wip

This commit is contained in:
callebtc
2025-10-21 22:24:55 +02:00
parent 9535ca8940
commit f4341ae1c1
11 changed files with 1490 additions and 2 deletions
@@ -576,9 +576,21 @@ private fun PeerItem(
tint = Color.Gray
)
} else {
val wifiAwarePeers by com.bitchat.android.wifiaware.WifiAwareController.connectedPeers.collectAsState()
val isWifiAware = wifiAwarePeers.containsKey(peerID)
val icon = when {
isWifiAware -> Icons.Filled.Wifi
isDirect -> Icons.Outlined.SettingsInputAntenna
else -> Icons.Filled.Route
}
val cd = when {
isWifiAware -> "Direct WiFi Aware"
isDirect -> "Direct Bluetooth"
else -> "Routed"
}
Icon(
imageVector = if (isDirect) Icons.Outlined.SettingsInputAntenna else Icons.Filled.Route,
contentDescription = if (isDirect) "Direct Bluetooth" else "Routed",
imageVector = icon,
contentDescription = cd,
modifier = Modifier.size(16.dp),
tint = colorScheme.onSurface.copy(alpha = 0.8f)
)
@@ -20,6 +20,10 @@ object DebugPreferenceManager {
// GCS keys (no migration/back-compat)
private const val KEY_GCS_MAX_BYTES = "gcs_max_filter_bytes"
private const val KEY_GCS_FPR = "gcs_filter_fpr_percent"
// Transport master toggles
private const val KEY_BLE_ENABLED = "ble_enabled"
private const val KEY_WIFI_AWARE_ENABLED = "wifi_aware_enabled"
private const val KEY_WIFI_AWARE_VERBOSE = "wifi_aware_verbose"
private lateinit var prefs: SharedPreferences
@@ -100,4 +104,26 @@ object DebugPreferenceManager {
fun setGcsFprPercent(value: Double) {
if (ready()) prefs.edit().putLong(KEY_GCS_FPR, java.lang.Double.doubleToRawLongBits(value)).apply()
}
// Transport toggles
fun getBleEnabled(default: Boolean = true): Boolean =
if (ready()) prefs.getBoolean(KEY_BLE_ENABLED, default) else default
fun setBleEnabled(value: Boolean) {
if (ready()) prefs.edit().putBoolean(KEY_BLE_ENABLED, value).apply()
}
fun getWifiAwareEnabled(default: Boolean = false): Boolean =
if (ready()) prefs.getBoolean(KEY_WIFI_AWARE_ENABLED, default) else default
fun setWifiAwareEnabled(value: Boolean) {
if (ready()) prefs.edit().putBoolean(KEY_WIFI_AWARE_ENABLED, value).apply()
}
fun getWifiAwareVerbose(default: Boolean = false): Boolean =
if (ready()) prefs.getBoolean(KEY_WIFI_AWARE_VERBOSE, default) else default
fun setWifiAwareVerbose(value: Boolean) {
if (ready()) prefs.edit().putBoolean(KEY_WIFI_AWARE_VERBOSE, value).apply()
}
}
@@ -36,6 +36,16 @@ class DebugSettingsManager private constructor() {
private val _packetRelayEnabled = MutableStateFlow(true)
val packetRelayEnabled: StateFlow<Boolean> = _packetRelayEnabled.asStateFlow()
// Master transport toggles
private val _bleEnabled = MutableStateFlow(true)
val bleEnabled: StateFlow<Boolean> = _bleEnabled.asStateFlow()
private val _wifiAwareEnabled = MutableStateFlow(false)
val wifiAwareEnabled: StateFlow<Boolean> = _wifiAwareEnabled.asStateFlow()
private val _wifiAwareVerbose = MutableStateFlow(false)
val wifiAwareVerbose: StateFlow<Boolean> = _wifiAwareVerbose.asStateFlow()
// Connection limit overrides (debug)
private val _maxConnectionsOverall = MutableStateFlow(8)
val maxConnectionsOverall: StateFlow<Int> = _maxConnectionsOverall.asStateFlow()
@@ -54,6 +64,10 @@ class DebugSettingsManager private constructor() {
_maxConnectionsOverall.value = DebugPreferenceManager.getMaxConnectionsOverall(8)
_maxServerConnections.value = DebugPreferenceManager.getMaxConnectionsServer(8)
_maxClientConnections.value = DebugPreferenceManager.getMaxConnectionsClient(8)
// Transport toggles
_bleEnabled.value = DebugPreferenceManager.getBleEnabled(true)
_wifiAwareEnabled.value = DebugPreferenceManager.getWifiAwareEnabled(false)
_wifiAwareVerbose.value = DebugPreferenceManager.getWifiAwareVerbose(false)
} catch (_: Exception) {
// Preferences not ready yet; keep defaults. They will be applied on first change.
}
@@ -140,6 +154,27 @@ class DebugSettingsManager private constructor() {
))
}
fun setBleEnabled(enabled: Boolean) {
DebugPreferenceManager.setBleEnabled(enabled)
_bleEnabled.value = enabled
addDebugMessage(DebugMessage.SystemMessage(if (enabled) "🟢 BLE enabled" else "🔴 BLE disabled"))
}
fun setWifiAwareEnabled(enabled: Boolean) {
DebugPreferenceManager.setWifiAwareEnabled(enabled)
_wifiAwareEnabled.value = enabled
addDebugMessage(DebugMessage.SystemMessage(if (enabled) "🟢 WiFi Aware enabled" else "🔴 WiFi Aware disabled"))
try {
com.bitchat.android.wifiaware.WifiAwareController.setEnabled(enabled)
} catch (_: Exception) { }
}
fun setWifiAwareVerbose(enabled: Boolean) {
DebugPreferenceManager.setWifiAwareVerbose(enabled)
_wifiAwareVerbose.value = enabled
addDebugMessage(DebugMessage.SystemMessage(if (enabled) "🔊 WiFi Aware verbose logging enabled" else "🔇 WiFi Aware verbose logging disabled"))
}
fun setMaxConnectionsOverall(value: Int) {
val clamped = value.coerceIn(1, 32)
DebugPreferenceManager.setMaxConnectionsOverall(clamped)
@@ -197,6 +232,16 @@ class DebugSettingsManager private constructor() {
fun updateConnectedDevices(devices: List<ConnectedDevice>) {
_connectedDevices.value = devices
}
// WiFi Aware debug collections
private val _wifiAwareDiscovered = MutableStateFlow<Map<String, String>>(emptyMap()) // peerID->nickname
val wifiAwareDiscovered: StateFlow<Map<String, String>> = _wifiAwareDiscovered.asStateFlow()
private val _wifiAwareConnected = MutableStateFlow<Map<String, String>>(emptyMap()) // peerID->ip
val wifiAwareConnected: StateFlow<Map<String, String>> = _wifiAwareConnected.asStateFlow()
fun updateWifiAwareDiscovered(map: Map<String, String>) { _wifiAwareDiscovered.value = map }
fun updateWifiAwareConnected(map: Map<String, String>) { _wifiAwareConnected.value = map }
fun updateRelayStats(stats: PacketRelayStats) {
_relayStats.value = stats
@@ -8,6 +8,8 @@ import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Bluetooth
import androidx.compose.material.icons.filled.Wifi
import androidx.compose.material.icons.filled.WifiTethering
import androidx.compose.material.icons.filled.BugReport
import androidx.compose.material.icons.filled.Cancel
import androidx.compose.material.icons.filled.Devices
@@ -53,6 +55,11 @@ fun DebugSettingsSheet(
val seenCapacity by manager.seenPacketCapacity.collectAsState()
val gcsMaxBytes by manager.gcsMaxBytes.collectAsState()
val gcsFpr by manager.gcsFprPercent.collectAsState()
val bleEnabled by manager.bleEnabled.collectAsState()
val wifiAwareEnabled by manager.wifiAwareEnabled.collectAsState()
val wifiAwareVerbose by manager.wifiAwareVerbose.collectAsState()
val wifiAwareDiscovered by manager.wifiAwareDiscovered.collectAsState()
val wifiAwareConnected by manager.wifiAwareConnected.collectAsState()
// Push live connected devices from mesh service whenever sheet is visible
LaunchedEffect(isPresented) {
@@ -76,6 +83,15 @@ fun DebugSettingsSheet(
)
}
manager.updateConnectedDevices(devices)
// Also surface WiFi Aware status
try {
val ctrl = com.bitchat.android.wifiaware.WifiAwareController
val known = ctrl.knownPeers.value
val discovered = ctrl.discoveredPeers.value
val discoveredMap = discovered.associateWith { pid -> known[pid] ?: "" }
manager.updateWifiAwareDiscovered(discoveredMap)
manager.updateWifiAwareConnected(ctrl.connectedPeers.value)
} catch (_: Exception) { }
kotlinx.coroutines.delay(1000)
}
}
@@ -198,6 +214,46 @@ fun DebugSettingsSheet(
}
}
// Transport toggles (BLE + WiFi Aware)
item {
Surface(shape = RoundedCornerShape(12.dp), color = colorScheme.surfaceVariant.copy(alpha = 0.2f)) {
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Icon(Icons.Filled.Devices, contentDescription = null, tint = Color(0xFF4CAF50))
Text("Transports", fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
}
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Filled.Bluetooth, contentDescription = null, tint = Color(0xFF007AFF))
Spacer(Modifier.width(8.dp))
Text("BLE", fontFamily = FontFamily.Monospace, modifier = Modifier.weight(1f))
Switch(checked = bleEnabled, onCheckedChange = {
manager.setBleEnabled(it)
scope.launch {
if (it) {
if (gattServerEnabled) meshService.connectionManager.startServer()
if (gattClientEnabled) meshService.connectionManager.startClient()
} else {
meshService.connectionManager.stopServer()
meshService.connectionManager.stopClient()
}
}
})
}
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Filled.Wifi, contentDescription = null, tint = Color(0xFF9C27B0))
Spacer(Modifier.width(8.dp))
Text("WiFi Aware", fontFamily = FontFamily.Monospace, modifier = Modifier.weight(1f))
Switch(checked = wifiAwareEnabled, onCheckedChange = { manager.setWifiAwareEnabled(it) })
}
Row(verticalAlignment = Alignment.CenterVertically) {
Spacer(Modifier.width(24.dp))
Text("WiFi Aware verbose", fontFamily = FontFamily.Monospace, modifier = Modifier.weight(1f))
Switch(checked = wifiAwareVerbose, onCheckedChange = { manager.setWifiAwareVerbose(it) })
}
}
}
}
// Packet relay controls and stats
item {
Surface(shape = RoundedCornerShape(12.dp), color = colorScheme.surfaceVariant.copy(alpha = 0.2f)) {
@@ -289,6 +345,43 @@ fun DebugSettingsSheet(
}
}
// WiFi Aware controls and status
item {
Surface(shape = RoundedCornerShape(12.dp), color = colorScheme.surfaceVariant.copy(alpha = 0.2f)) {
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Icon(Icons.Filled.WifiTethering, contentDescription = null, tint = Color(0xFF9C27B0))
Text("WiFi Aware", fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Spacer(Modifier.weight(1f))
val running by com.bitchat.android.wifiaware.WifiAwareController.running.collectAsState()
Text(if (running) "running" else "stopped", fontFamily = FontFamily.Monospace, fontSize = 12.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
}
Row(horizontalArrangement = Arrangement.spacedBy(12.dp)) {
AssistChip(onClick = { com.bitchat.android.wifiaware.WifiAwareController.startIfPossible() }, label = { Text("Start") })
AssistChip(onClick = { com.bitchat.android.wifiaware.WifiAwareController.stop() }, label = { Text("Stop") })
AssistChip(onClick = { com.bitchat.android.wifiaware.WifiAwareController.getService()?.sendBroadcastAnnounce() }, label = { Text("Announce") })
}
Text("Discovered: ${wifiAwareDiscovered.size}", fontFamily = FontFamily.Monospace, fontSize = 12.sp)
if (wifiAwareDiscovered.isEmpty()) {
Text("No discoveries yet", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.6f))
} else {
wifiAwareDiscovered.entries.take(50).forEach { (peer, nick) ->
Text("${if (nick.isBlank()) peer.take(8) + "…" else nick} (${peer.take(8)}…) ", fontFamily = FontFamily.Monospace, fontSize = 12.sp)
}
}
Divider()
Text("Connected: ${wifiAwareConnected.size}", fontFamily = FontFamily.Monospace, fontSize = 12.sp)
if (wifiAwareConnected.isEmpty()) {
Text("No active sockets", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.6f))
} else {
wifiAwareConnected.entries.take(50).forEach { (peer, ip) ->
Text("${peer.take(8)}… @ $ip", fontFamily = FontFamily.Monospace, fontSize = 12.sp)
}
}
}
}
}
// Connected devices
item {
Surface(shape = RoundedCornerShape(12.dp), color = colorScheme.surfaceVariant.copy(alpha = 0.2f)) {