You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit d2adc62
Browse filesBrowse the repository at this point in the historyBrowse files
Tell iroh when Android changes the network under it
A phone that left the house on 2026-09-15 stopped sharing for seventy-one
minutes and started again the moment it came home. AAPS never faltered: it
sealed 84 epochs into that hole, `holds` climbed 1470 to 1560, and every pass
said `missing 0, lost 0, failures 0`. The data was made and it was kept. It had
nowhere to go.
`relay=disconnected` for 88 consecutive passes, 15:05:25 to 16:16:23, bracketing
both readers' observations exactly — and that is iroh's own
`home_relay_status()`, not our inference. Not doze: AAPS is whitelisted, runs at
targetSdk 32, and a phone sealing an epoch a minute is not one Android has
stopped. Not the carrier, and not the foreground service. Three overnight
failures have now been blamed on doze and caused by something else.
netwatch ships a deliberately empty route monitor for Android, whose whole body
is the comment "Very sad monitor. Android doesn't allow us to do this", and its
wall-time poll is stretched to an hour on mobile and fires on a clock jump
rather than a network one. So iroh cannot see an Android network change at all.
Its own documentation names the platform and the remedy: Android exposes this
to Java, so Java must pass it down. `Endpoint::network_change()` is public. We
had never called it.
Without it nothing does the rebind, the `dns_resolver.reset()`, the fresh net
report, or the nudge that migrates QUIC. The relay is a hostname, so every
reconnect needs DNS, and a resolver still aimed at the network the phone walked
away from keeps failing until it walks back.
A brief wifi toggle does not reproduce any of this, which is why it hid for
days: live connections keep flowing over the wildcard socket via cellular and
nothing has to re-resolve. It needs a change that outlives its connections.
Measured on the loop phone with the fix, wifi off, nine minutes on mobile data:
relay connected throughout, pool steady at 3 peers and 4 buckets where the
failure collapsed to 1, and operations landing on the laptop peer the whole
time — 2084 to 2089. `ss` puts the relay socket's local end on the CGNAT
address, so it genuinely reconnected over mobile rather than surviving.
Notification is trailing-edge: Android delivers these in a steady trickle, about
one every three seconds, and a thread per callback all day is battery a user
gets to refuse. Sleeping before notifying means a burst collapses to one call
that sees the settled network — dropping the last callback of a burst is the
one mistake that would bring the bug back, and this cannot make it. Logging is
capped at once a minute with a count, because the outage was only diagnosable
from AndroidAPS.log and filling it is how that stops being true.
`stop()` is called before `swarmLeave`, which frees the handle: unlike every
other caller this one is driven by an OS callback that can fire during teardown.
This also corrects the record. "Off-LAN is proven" has stood since 2026-09-11
and was measured with the phone on mobile data while still at home.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
0 commit comments