Changing the reminder time does not move it, rescheduling can fire it early, and a zone change never re-aims it #72
Labels
No Label
P0
P1
P2
release-blocker
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: null/Privacy-Period-Tracker#72
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Verified against WorkManager 2.11.2's own bytecode, not only the app's code.
What is true now.
ReminderScheduler.schedule(core/notifications/.../ReminderScheduler.kt:39-55) enqueues a 1-day periodic request withsetInitialDelayunderExistingPeriodicWorkPolicy.UPDATE.WorkerUpdater.updateWorkImplcopieslastEnqueueTimeandperiodCountfrom the old spec, andWorkSpec.calculateNextRunTimecomputesperiodCount == 0 ? lastEnqueueTime + initialDelay : lastEnqueueTime + interval. Two consequences:schedule()BEFORE the first run — which every process start does, via the coordinator — sets the next run to original enqueue time + new delay, which is in the past by the next morning, so it fires early and every later period anchors off that.Also:
resetPeriodic()anchors the next period at completion time, so reminders drift later daily; the KDoc at:24-26says the work is KEEP-replaced while:52uses UPDATE; anddelayUntil(reminderTime, ZoneId.systemDefault())is evaluated once at schedule time with no receiver forACTION_TIMEZONE_CHANGEDorACTION_TIME_CHANGEDanywhere in the app (grep confirms none).What it costs. A user who moves her reminder to the evening keeps getting it in the morning, and a user who flies across time zones gets it at the wrong hour indefinitely. Both read as 'this app's reminders are broken'.
What to do. Read the existing
WorkInfo.nextScheduleTimeMillis; enqueue with KEEP when nothing exists; leave an overdue run alone (moving it skips today); leave it alone when it is already within a few minutes of the target; otherwise UPDATE withsetNextScheduleTimeOverride(target). Add an unexported receiver for the two clock broadcasts that asks the coordinator to reschedule. Rewrite the KDoc to match the code and the screen copy to match reality.Traps. Do NOT add a flex interval to make the 'few minutes either side' copy true —
calculateNextRunTimeputs the first run atstart + interval − flex, so a 15-minute flex would skip today's reminder entirely. Do NOT useCANCEL_AND_REENQUEUEfrom the coordinator: it runs at every process start including the worker's own and would cancel the running worker. BOOT_COMPLETED needs no app receiver — WorkManager's ownRescheduleReceiverhandles it (its AAR manifest declares only that action, which is why the clock broadcasts do need one).Verify:
changing the reminder time moves the next run,scheduling again with the same time leaves the next run aloneandan overdue run is not pushed to tomorrowin a newWorkManagerReminderSchedulerTestusingWorkManagerTestInitHelperwith a fixed clock;a clock change re-runs the schedule even when nothing else changedinReminderCoordinatorTest.