fix(android): hold WiFi+wake lock during UPnP cast (locked-screen poll starvation) #97
Reference in New Issue
Block a user
Delete Branch "dev"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Problem
Casting to a UPnP renderer (Sonos) with the screen locked on battery would, after ~12 seconds, drop the renderer and fall back to a silent phone — while the Sonos was streaming fine the whole time.
Confirmed from logcat: shortly after screen-off the phone logged
Unable to resolve host "minstrel.fabledsword.com"(its own DNS dying, not the server), the queue-extend aborted (1/58 appended), the 1 Hz poll then trippedDROP_THRESHOLD, and the local fallback came upactive=null(no network either → silence).Root cause
While casting, the wrapped ExoPlayer is paused, which releases its automatic
WAKE_MODE_NETWORKWiFi/wake locks. Nothing else held the radio awake, so a locked, on-battery phone power-saved the WiFi within seconds and dozed the CPU — starving both the liveness poll to the renderer and the extend calls to the server. (USB charging masks this: no Doze while charging, which is why it only bit on battery.)Fix
New
CastNetworkLock: a high-perf/low-latencyWifiManager.WifiLock+ partialPowerManager.WakeLock, acquired when a UPnP route goes active and released on every teardown path (all funnel throughholder.set(null)→onActiveChanged(null)). Idempotent + synchronized.WAKE_LOCKpermission already declared; minSdk 26 handled viaWIFI_MODE_FULL_LOW_LATENCY(API 29+) /FULL_HIGH_PERFfallback.Testing
Needs a real device test on battery (USB masks the bug): install → cast to Sonos → unplug → lock screen → confirm playback survives past ~15s.
CI verified green on dev (run 986: ktlint / detekt / unit tests).
🤖 Generated with Claude Code