beacon: stop causing "wireless debugging connected" notification spam

Root cause of the spam the user kept seeing: the service resolved adbd's
own mDNS advertisement repeatedly (every discovery callback, plus a 20s
heartbeat). Resolving that service makes adbd re-arm the connection, and
Android posts a "wireless debugging connected" notification each time —
so the beacon itself was the noise source, independent of the PC-side
connector loops.

Now: resolve each discovered service instance exactly ONCE (guard set,
cleared on onServiceLost so a genuine rotation re-resolves once), and the
heartbeat only re-POSTs the cached port (60s, no mDNS traffic).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mrambossek
2026-07-31 23:12:14 +02:00
co-authored by Claude Opus 5
parent ee4031b086
commit 4c51bd2aad
@@ -38,6 +38,8 @@ class BeaconService : Service() {
private var discoveryListener: NsdManager.DiscoveryListener? = null
@Volatile private var currentPort: Int = -1
/** Service instances already resolved — prevents repeat resolves (notification spam). */
private val resolvedOnce = java.util.Collections.synchronizedSet(mutableSetOf<String>())
private var heartbeat: Job? = null
override fun onBind(intent: Intent?): IBinder? = null
@@ -47,10 +49,14 @@ class BeaconService : Service() {
nsd = getSystemService(Context.NSD_SERVICE) as NsdManager
startForeground(1, buildNotification("Starting…"))
startDiscovery()
// Re-assert the endpoint periodically, but do NOT re-resolve mDNS each time:
// resolving adbd's own advertisement provokes it to re-arm the connection, which fires
// Android's "wireless debugging connected" notification — every cycle. Discovery runs
// once; we only re-POST the cached port (cheap, silent).
heartbeat = scope.launch {
while (true) {
report() // refresh seen_at + re-assert current endpoint
delay(20_000)
delay(60_000)
report()
}
}
Status.set("watching for wireless-debug port…")
@@ -65,12 +71,18 @@ class BeaconService : Service() {
override fun onServiceLost(s: NsdServiceInfo?) {
// adbd stops advertising when Wireless debugging is turned off.
currentPort = -1
s?.serviceName?.let { resolvedOnce.remove(it) } // allow one re-resolve when it returns
val warn = "⚠ Wireless debugging appears OFF (adb mDNS service gone) — re-enable it"
Status.set(warn)
updateNotification(warn)
}
override fun onServiceFound(s: NsdServiceInfo?) {
if (s == null) return
// Resolve ONCE per discovered service instance. Repeatedly resolving adbd's own
// advertisement makes it re-arm the connection and spam the user with
// "wireless debugging connected" notifications.
val key = s.serviceName ?: return
if (!resolvedOnce.add(key)) return
resolve(s)
}
}