ADFA-4960: resumable clone SEND (app-scoped) + clone notification - #312
Merged
Conversation
…ation The send rsync daemon already survives backgrounding/swipe (a foreground service keeps the process; the daemon is a native child of it) — same profile as receive. The only gap was that send's live state lived in Fragment fields, so a recreated CloneFragment fell back to the fork; and clone used the generic WatchdogService notification (-> MainActivity), which doesn't return to the Clone screen. - CloneSendSession: process-scoped holder (mirrors SyncProgressRepository for receive) carrying what the share screen redraws from — mode, tempPass (the QR secret, not recomputable), hostHasRootfs, librarySplit, shareAnyway. Set when the daemon comes up, cleared on stop. Process-scoped on purpose: it and the daemon share one lifetime, so a true process kill leaves no false resume. - CloneFragment: re-binds on onCreateView when a send session is active (land on the share screen, skip a re-start); writes/clears the session; and now uses CloneShareService for keep-alive. - CloneShareService: clone-specific foreground keep-alive (own channel + id 8, holds the CPU/Wi-Fi locks) whose notification content intent returns to LibraryActivity + nav_clone. Receive uses it too. - LibraryActivity: land on the Clone tab on a plain reopen when a SEND session is active (already did so for receive). True process death is out of scope (receive doesn't survive it either). Wants a device pass.
#1 CloneShareService: on a START_STICKY null-intent restart with no active clone (session + daemon died with the process), stopSelf instead of resurrecting a stale 'transferring' notification / locks. #2 CloneSendSession.begin: set the volatile active flag last so a reader that sees it also sees the rest of the fields.
…ot gate (device fixes) Device testing revealed two problems the earlier analysis missed: 1) Swipe cut the transfer. Root cause: SyncStateViewModel.onCleared() called transport.stop() (it is ViewModel-scoped, ADFA-4492). Swiping the app finishes the Activity -> the ViewModel is cleared -> the daemon/pull is killed, even though CloneShareService keeps the PROCESS alive. This hit send AND receive. Fix: the transport is now process-scoped (static), and onCleared() does NOT tear it down while a clone is in flight (CloneSendSession.isActive() || SyncProgressRepository.isActive()) — only when nothing is running. The native rsync child now stays with the process the service keeps alive. 2) Reopening during a clone (e.g. tapping the notification) sat on the boot gate 'loading forever'. LibraryActivity waits behind the gate for the server, but a clone intentionally stops it. Fix: when a deep-env op holds the lock (EnvironmentLock.ownerHeld), lift the gate immediately and show the UI we routed to (the Clone tab); the op boots the server when it finishes, never the gate. Note: a device whose OEM/phantom-process killer reaps the app or the rsync child on swipe is a deeper issue beyond this fix, but the self-inflicted onCleared kill is gone. Wants a re-test.
#1 SyncStateViewModel.getTransport(): double-checked lazy init on a volatile field, so the now process-global transport is never built twice by the main thread + a probe's IO thread (a stray RsyncManager/rsync child a later stop() couldn't reach). #2 SyncFragment.onDestroyView() (old UI): don't stop the shared transport / drop the network binding while a clone is in flight — that old-UI teardown would otherwise kill the clone daemon and strand its lock + keep-alive. Follow-ups noted in the PR: daemon liveness check on re-bind; CONFIRM-phase network binding on onCleared.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The send rsync daemon already survives backgrounding/swipe (a foreground service keeps the process;
the daemon is a native child). The gaps were that send's live state lived in Fragment fields (a
recreated screen fell back to the fork) and clone used the generic WatchdogService notification
(→ MainActivity), which never returned to the Clone screen.
share screen redraws from — mode, tempPass (the QR secret, not recomputable), hostHasRootfs,
librarySplit, shareAnyway. Set when the daemon comes up, cleared on stop. Process-scoped on purpose:
it and the daemon share one lifetime, so a true kill leaves no false resume.
locks) whose notification returns to LibraryActivity + nav_clone. Receive uses it too.
Out of scope: true process death (receive doesn't survive it either). Pending a device pass.