mirror of
https://github.com/d4rken-org/capod.git
synced 2026-09-14 18:26:11 -04:00
Play auto-refunds (and revokes) purchases not acknowledged within 3 days. The in-process ack machinery covers every case where the process lives long enough; what it cannot cover is a process death around the Play sheet (aggressive OEM task killers) followed by the user not reopening the app before the deadline. Add a gplay-only WorkManager safety net: - PurchaseAckWorker: self-completing sweep via a new bounded BillingManager.ensureAllAcknowledged() that refreshes and acknowledges in the same coroutine (the reactive ack collector is async, so a worker cannot prove its acks happened through it). Retries with exponential backoff until the purchase's refund deadline, then gives up visibly. - PurchaseAckScheduler: two unique work identities. A launch watch (REPLACE, armed and awaited before launchBillingFlow with a 30min delay so it cannot complete while the user is still in the sheet) and a discovered-purchase rescue (KEEP, 1min delay, armed directly from an ack pass that finds unacknowledged purchases, pre-attempt). Separate identities so a new purchase flow can never displace a pending rescue. Both triggers are fail-open: a broken WorkManager never blocks a purchase or an ack. WorkManager resolves via Provider at first arm so eager Application-time construction of the billing stack cannot trigger WorkManager's on-demand initialization prematurely. - Nothing cancels the work from the foreground path: an ack pass can see zero unacked purchases while the sheet is still open, so the worker completes itself after its own reconciliation instead. The ack pass now runs under a mutex (the worker sweep and the reactive collector would otherwise race the token bookkeeping) and reports per-outcome counts for the sweep result mapping. This is a port of d4rken-org/sdmaid-se#2685; the ported sources are byte-identical to the donor apart from the package rename. CAPod had no explicit WorkManager wiring at all (work-runtime only arrived transitively through Glance), so this also adds it: - addWorkerManager() pinning androidx.work 2.7.1, the version already resolved via Glance, plus androidx.hilt:hilt-work and its KSP compiler. work-runtime-ktx is required at 2.7.1: CoroutineWorker, Operation.await, OneTimeWorkRequestBuilder and workDataOf all still live in the ktx artifact at that version. androidx.hilt moves 1.0.0 -> 1.2.0 (by conflict resolution) because 1.0.0's hilt-compiler ships no KSP SymbolProcessorProvider, so @HiltWorker would generate nothing. - WorkManagerModule providing the singleton WorkManager. - App implements Configuration.Provider with the injected HiltWorkerFactory. WorkManager 2.7.1 still declares that interface as getWorkManagerConfiguration(), not the later property form. - The manifest removes androidx.work's startup initializer so the on-demand configuration is the one that takes effect. FOSS stays untouched behaviour-wise: all new billing types live in src/gplay, workers need no manifest entry, and the worker factory resolves the worker only in gplay variants.