Files
RustDeskandClaude Opus 5 e6dd925ab0 fix(android): close outgoing sessions when the task is swiped away (#15753)
* fix(android): close outgoing sessions when the task is swiped away

Swiping RustDesk away from recents destroys the UI but does not
necessarily end the process: when MainService is running (screen share
enabled, or started at boot) the process survives, and with it the
native io_loop of any active outgoing session.

That orphaned io_loop keeps echoing TestDelay (client.rs handle_test_delay
runs entirely on the network thread, no UI involved), which keeps
refreshing last_recv_time on the controlled side. Its 30s inactivity
timeout in server/connection.rs therefore never fires, so the remote
session stays established with no UI left to close it, and the peer
cannot be reconnected to.

Close client sessions from Service.onTaskRemoved, which fires only on
explicit task removal -- not on Home or backgrounding, so ordinary
backgrounding is unaffected. The service itself keeps running, so
incoming connections and the device staying reachable are unchanged.

This complements 152c5c71b, which covered the route-pop path via
dispose(); dispose() does not run when the task is removed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(android): also close sessions on activity destroy

Review follow-up. onTaskRemoved only reaches MainService, but the
accessibility InputService keeps the process alive on its own: a user
with input control enabled and screen sharing off has a surviving
process after a swipe while MainService is not running, so the callback
never fires and the session still outlives its UI. onTaskRemoved cannot
cover that -- InputService is bound by the system, not started, so the
callback is not delivered there.

Close from MainActivity.onDestroy() as well, which runs while the
process is still alive regardless of which service keeps it up. Guarded
on isFinishing so a destroy for recreation (configuration change, "don't
keep activities") does not tear down a live session. Both paths are
idempotent.

Also drop the now-wrong "on task removed" wording from the Rust log,
which has two distinct callers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(android): release held keys before draining the session map

close_all_sessions drained SESSIONS first, then called
release_remote_keys. The release path sends through get_cur_session(),
which resolves against SESSIONS, so every generated key-up was dropped
after take_remote_keys() had already cleared TO_RELEASE: a key held as
the task is removed stays down on the controlled side until its own
timeout, with the state lost locally.

Release first, while a session is still registered. It is a no-op when
no key is held, so the previous is_empty() guard is not needed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-04 11:18:14 +08:00
..
2026-07-10 15:21:48 +08:00