mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 06:25:21 +00:00
Debug button (#377)
* feat(debug): add DebugSettingsManager + DebugSettingsSheet scaffold and AboutSheet entry; groundwork for verbose logging, GATT controls, relay stats, device/scan views * fix(debug): wire debug sheet launch via onShowDebug in AboutSheet from ChatScreen; add public start/stop server/client methods} * fix(about): remove misplaced debug item block inside PoW section; keep debug launcher managed by ChatScreen only * feat(debug): wire DebugSettingsSheet role switches to explicit startServer/stopServer and startClient/stopClient; expose role controls + disconnectAll on BluetoothConnectionManager; fix syntax error; build passes * feat(debug): add connect/disconnect helpers; wire DebugSettingsSheet connect/disconnect actions to BluetoothConnectionManager * feat(debug): add debug settings button at bottom of AboutSheet; wire onShowDebug callback to open DebugSettingsSheet from ChatScreen * feat(debug): wire verbose logging into chat view via DebugSettingsManager; add rolling relay stats; push connected devices and scan results; ensure GATT role stop closes connections; log incoming packets and relay events; add UI polling for devices; build passes * chore(debug-branch): remove unrelated files that were mistakenly added in first commit; keep only intended debug settings changes * fix(chat): prevent mesh→geohash leak Root cause: - DebugSettingsManager→chat bridge appended system logs to the global timeline regardless of active channel - MeshDelegateHandler added public mesh messages to UI unconditionally Fixes: - Only inject debug system messages when selected location channel is Mesh - Only add public mesh messages to UI when Mesh is selected (still send notifications) Build: ./gradlew assembleDebug } * fix(timeline): restore message persistence across channel switches Root cause: - NostrGeohashService.switchLocationChannel() called messageManager.clearMessages() which wiped ALL messages (mesh + debug + geohash) from main timeline - Geohash events were adding to main timeline, causing cross-contamination Fixes: - Remove messageManager.clearMessages() from channel switching - ChatScreen displayMessages now routes to separate storage: - Mesh: messages (main timeline, includes debug logs when Mesh selected) - Geohash: viewModel.getGeohashMessages(geohash) from separate history - Private: privateChats[peerID] - Channels: channelMessages[channel] - Geohash events no longer add to main timeline, only to geohash history - Mesh messages always stored to preserve history when switching away Result: Each chat type has persistent separate storage, no message loss * Debug/relay logs: use MessageType names; include device route in verbose packet logs. * Verbose device-peer assignment and connection/disconnection logs with peerId, deviceId, nickname; packet relay log uses MessageType names.} * Debug logs API: include nickname and deviceId for incoming/relay; update callers.} * Fix compile: import MessageType; correct debug manager API usage and remove stray insertion; build.} * Respect relay toggle; helper to log relay with deviceId.} * PacketRelayManager: add relay toggle and unified logging helper; clean file header comments; build fixes.} * changes * Geohash local echo: do not add to mesh timeline; rely on geohash history and ChatScreen display for location channels. * persisting * persist debug settings * gitignore * gatt server / client controls * debugger * max connection settings and graph * more graph * better logging * refactor logging
This commit is contained in:
@@ -14,6 +14,8 @@ import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.*
|
||||
import kotlinx.coroutines.Job
|
||||
import com.bitchat.android.ui.debug.DebugSettingsManager
|
||||
import com.bitchat.android.ui.debug.DebugScanResult
|
||||
|
||||
/**
|
||||
* Manages GATT client operations, scanning, and client-side connections
|
||||
@@ -44,6 +46,21 @@ class BluetoothGattClientManager(
|
||||
private val bluetoothAdapter: BluetoothAdapter? = bluetoothManager.adapter
|
||||
private val bleScanner: BluetoothLeScanner? = bluetoothAdapter?.bluetoothLeScanner
|
||||
|
||||
/**
|
||||
* Public: Connect to a device by MAC address (for debug UI)
|
||||
*/
|
||||
fun connectToAddress(deviceAddress: String): Boolean {
|
||||
val device = bluetoothAdapter?.getRemoteDevice(deviceAddress)
|
||||
return if (device != null) {
|
||||
val rssi = connectionTracker.getBestRSSI(deviceAddress) ?: -50
|
||||
connectToDevice(device, rssi)
|
||||
true
|
||||
} else {
|
||||
Log.w(TAG, "connectToAddress: No device for $deviceAddress")
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
// Scan management
|
||||
private var scanCallback: ScanCallback? = null
|
||||
|
||||
@@ -63,6 +80,18 @@ class BluetoothGattClientManager(
|
||||
* Start client manager
|
||||
*/
|
||||
fun start(): Boolean {
|
||||
// Respect debug setting
|
||||
try {
|
||||
if (!com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().gattClientEnabled.value) {
|
||||
Log.i(TAG, "Client start skipped: GATT Client disabled in debug settings")
|
||||
return false
|
||||
}
|
||||
} catch (_: Exception) { }
|
||||
|
||||
if (isActive) {
|
||||
Log.d(TAG, "GATT client already active; start is a no-op")
|
||||
return true
|
||||
}
|
||||
if (!permissionManager.hasBluetoothPermissions()) {
|
||||
Log.e(TAG, "Missing Bluetooth permissions")
|
||||
return false
|
||||
@@ -98,9 +127,25 @@ class BluetoothGattClientManager(
|
||||
* Stop client manager
|
||||
*/
|
||||
fun stop() {
|
||||
if (!isActive) {
|
||||
// Idempotent stop
|
||||
stopScanning()
|
||||
stopRSSIMonitoring()
|
||||
Log.i(TAG, "GATT client manager stopped (already inactive)")
|
||||
return
|
||||
}
|
||||
|
||||
isActive = false
|
||||
|
||||
connectionScope.launch {
|
||||
// Disconnect all client connections decisively
|
||||
try {
|
||||
val conns = connectionTracker.getConnectedDevices().values.filter { it.isClient && it.gatt != null }
|
||||
conns.forEach { dc ->
|
||||
try { dc.gatt?.disconnect() } catch (_: Exception) { }
|
||||
}
|
||||
} catch (_: Exception) { }
|
||||
|
||||
stopScanning()
|
||||
stopRSSIMonitoring()
|
||||
Log.i(TAG, "GATT client manager stopped")
|
||||
@@ -111,7 +156,8 @@ class BluetoothGattClientManager(
|
||||
* Handle scan state changes from power manager
|
||||
*/
|
||||
fun onScanStateChanged(shouldScan: Boolean) {
|
||||
if (shouldScan) {
|
||||
val enabled = try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().gattClientEnabled.value } catch (_: Exception) { true }
|
||||
if (shouldScan && enabled) {
|
||||
startScanning()
|
||||
} else {
|
||||
stopScanning()
|
||||
@@ -158,7 +204,9 @@ class BluetoothGattClientManager(
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
private fun startScanning() {
|
||||
if (!permissionManager.hasBluetoothPermissions() || bleScanner == null || !isActive) return
|
||||
// Respect debug setting
|
||||
val enabled = try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().gattClientEnabled.value } catch (_: Exception) { true }
|
||||
if (!permissionManager.hasBluetoothPermissions() || bleScanner == null || !isActive || !enabled) return
|
||||
|
||||
// Rate limit scan starts to prevent "scanning too frequently" errors
|
||||
val currentTime = System.currentTimeMillis()
|
||||
@@ -282,10 +330,34 @@ class BluetoothGattClientManager(
|
||||
|
||||
// Store RSSI from scan results for later use (especially for server connections)
|
||||
connectionTracker.updateScanRSSI(deviceAddress, rssi)
|
||||
|
||||
// Publish scan result to debug UI buffer
|
||||
try {
|
||||
DebugSettingsManager.getInstance().addScanResult(
|
||||
DebugScanResult(
|
||||
deviceName = device.name,
|
||||
deviceAddress = deviceAddress,
|
||||
rssi = rssi,
|
||||
peerID = null // peerID unknown at scan time
|
||||
)
|
||||
)
|
||||
} catch (_: Exception) { }
|
||||
|
||||
// Power-aware RSSI filtering
|
||||
if (rssi < powerManager.getRSSIThreshold()) {
|
||||
Log.d(TAG, "Skipping device $deviceAddress due to weak signal: $rssi < ${powerManager.getRSSIThreshold()}")
|
||||
// Even if we skip connecting, still publish scan result to debug UI
|
||||
try {
|
||||
val pid: String? = null // We don't know peerID until packet exchange
|
||||
DebugSettingsManager.getInstance().addScanResult(
|
||||
DebugScanResult(
|
||||
deviceName = device.name,
|
||||
deviceAddress = deviceAddress,
|
||||
rssi = rssi,
|
||||
peerID = pid
|
||||
)
|
||||
)
|
||||
} catch (_: Exception) { }
|
||||
return
|
||||
}
|
||||
|
||||
@@ -474,7 +546,9 @@ class BluetoothGattClientManager(
|
||||
* Restart scanning for power mode changes
|
||||
*/
|
||||
fun restartScanning() {
|
||||
if (!isActive) return
|
||||
// Respect debug setting
|
||||
val enabled = try { com.bitchat.android.ui.debug.DebugSettingsManager.getInstance().gattClientEnabled.value } catch (_: Exception) { true }
|
||||
if (!isActive || !enabled) return
|
||||
|
||||
connectionScope.launch {
|
||||
stopScanning()
|
||||
@@ -489,4 +563,4 @@ class BluetoothGattClientManager(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user