Commit Graph
2 Commits
Author SHA1 Message Date
JMR-devandClaude Opus 4.8 8904351a96 fix(push): handle Service.onTimeout to survive the dataSync FGS runtime cap
IdleService runs continuously as a FOREGROUND_SERVICE_TYPE_DATA_SYNC
foreground service (push is on by default). With targetSdk 37, Android 14+'s
dataSync FGS runtime cap (~6h per rolling 24h) calls Service.onTimeout(...)
and then force-stops the service — throwing a system FGS-timeout exception —
if it doesn't stop itself. IdleService overrode onStartCommand/onDestroy/onBind
but not onTimeout, so after ~6 cumulative hours push silently died and the app
hit the exception; on API 35+ the budget is cumulative and a restart can't
recover it until the next 24h window.

Override both onTimeout(startId) (deprecated, API 34) and
onTimeout(startId, fgsType) (API 35+); both route to a clean shutdown that
re-asserts the already-scheduled 15-minute periodic sync, swaps the persistent
notification to a degraded "paused" text and DETACHes it so it survives, then
stopForeground(DETACH) + stopSelf so we never leave a dataSync FGS running past
its cap (the exact condition the platform kills on). This mirrors the existing
low-battery PushMode.POLLING fallback.

The push-status text choice is pulled into a pure PushStatusNotification.statusTextRes
seam and unit-tested on the JVM; the built notification's new timed-out text is
covered by PushStatusNotificationInstrumentedTest.

Closes #302

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 02:09:01 -05:00
JMR-devandClaude Opus 4.8 0b44276909 test(reporting): ReportUpload testability seams + push IdleService E2E
Coverage lane 4 (#249) flagged reporting/push classes as unreachable by tests.
Add minimal, behaviour-preserving seams and the tests they unblock (issue #257):

- ReportUploadScheduler: inject Provider<WorkManager> (mirroring SyncScheduler)
  instead of calling the WorkManager.getInstance static that MockK can't stub on
  the abstract WorkManager (AbstractMethodError). New ReportUploadSchedulerTest
  pins the per-report unique-work name + REPLACE policy.
- ReportUploadWorker: take the ingest endpoint via a new @DebugReportEndpoint
  qualifier (provided from BuildConfig.DEBUG_REPORT_ENDPOINT in ReportingModule)
  rather than reading the BuildConfig static inline. New ReportUploadWorkerHttpTest
  drives the transmit path against an in-process JDK HttpServer on loopback and
  covers 2xx success + delete, 4xx failure, 5xx retry/attempt-cap, and network
  error. Production value is unchanged (empty by default).
- IdleService: extract the foreground-notification channel + push-mode-to-text
  logic into PushStatusNotification. New PushStatusNotificationInstrumentedTest
  asserts channel importance and the IDLE/POLLING notification text with a real
  application Context (never a mocked Context).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-03 23:58:00 -05:00