mirror of
https://github.com/screentinker/screentinker.git
synced 2026-08-14 14:23:14 -06:00
The player opened duplicate/rapid WebSocket connections for the same device_id: connect() was unconditional (disconnect + forceNew socket) and reachable from every lifecycle entry point (boot, service start, MainActivity/ProvisioningActivity bind, foreground re-bind, START_STICKY). A ROM that re-binds on foreground (MAXHUB PROC_STATE_TOP, isBindService:true) therefore re-invoked connect() repeatedly -> a burst of sockets, each evicted by the next (the 8-in-9s storm). Fire TV never re-binds like that, so it never reproduced. - ConnectionGuard (new, pure/testable — service is the shell, per the OtaThrottle pattern): shouldOpenNewSocket(hasSocket, sameUrl, socketActive) — reuse a live/self-healing socket to the same url; open a new one only when none is usable. - WebSocketService: connect() is now idempotent (@Synchronized + ConnectionGuard) — every entry point reuses the one socket, never opens a duplicate; body split into openSocket(). socketActive / currentUrl track the single socket. - Single owner: onStartCommand now calls connect() so the SERVICE owns the one connection (idempotent across START_STICKY restarts), not whichever activity binds. - Reconnect discipline: on io server/client disconnect (which Socket.IO does NOT auto-reconnect) mark the socket inert and schedule exactly ONE backed-off re-open — never a blind re-open loop; a transport drop keeps socketActive=true so Socket.IO's own reconnect is reused. Test: ConnectionGuardTest (5, incl. 8-rapid-binds-all-reuse). :app:testDebugUnitTest green (ConnectionGuard 5, OtaThrottle 7, ScheduleEval 1). NOT bumped/signed/released — Dan builds+signs with the BMG keystore; 1.9.2-patch2 (server net) covers un-updated devices. |
||
|---|---|---|
| .. | ||
| src | ||
| build.gradle.kts | ||
| proguard-rules.pro | ||