From 4c51bd2aad7696d35809cf1aa23d38c50755746a Mon Sep 17 00:00:00 2001 From: mrambossek Date: Fri, 31 Jul 2026 23:12:14 +0200 Subject: [PATCH] beacon: stop causing "wireless debugging connected" notification spam MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../app/echo_lot/adbbeacon/BeaconService.kt | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/echolot-app/adb-beacon/src/main/kotlin/app/echo_lot/adbbeacon/BeaconService.kt b/echolot-app/adb-beacon/src/main/kotlin/app/echo_lot/adbbeacon/BeaconService.kt index dfd2eb7..b18f68f 100644 --- a/echolot-app/adb-beacon/src/main/kotlin/app/echo_lot/adbbeacon/BeaconService.kt +++ b/echolot-app/adb-beacon/src/main/kotlin/app/echo_lot/adbbeacon/BeaconService.kt @@ -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()) 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) } }