fix(alarms): apply silence-after mid-ring and close missed one-shots
Review fixes for the silence-after setting. Changing the alarm's silence-after now re-measures a ring in progress at once, through AlarmEngine.onSilenceAfterChanged: past the new window it closes as missed, inside it the backstop moves. onAutoSilence also re-arms instead of closing a ring that is still inside the current window, so a backstop armed for a shorter window cannot end a ring early. A cycle the resolver closes as missed (a ring past its window, or a snooze that never fired) now disables a one-shot alarm, as the engine's own close does. A short window made that path much easier to reach, and the alarm was being armed for the same time the next day. A late snooze is kept for the window or ten minutes, whichever is longer, so a short window never makes a promised snooze easier to lose than in v1. A timer that has gone quiet stays quiet when the setting is raised: the lapsed anchor moves back past the hard stop. The timer's heads-up is now keyed to the session anchor rather than the window's end, so editing the setting mid-ring no longer counts as a new session and alerts again. A negative stored value now reads as the default instead of Never. The picker offers a stored value that matches no choice, and the wake-lock timeout is one shared constant. Refs #17
This commit is contained in:
1 parent
412e54db09
commit
1c323d5b4c
20 files changed
+397
-88
No files matched your search
+30
-14
@@ -1163,26 +1163,37 @@ Never), **10 minutes** by default, AOSP DeskClock's default and v1's fixed
|
||||
value, so an upgrade changes nothing. Snoozing keeps it open.
|
||||
|
||||
The window is read from `ClockDefaults.alarmSilenceAfter` everywhere a ring is
|
||||
measured: the resolver's ringing and late-snooze checks, the backstop `onFire`
|
||||
arms, how late a snooze fire may arrive, and whether a ring interrupted by a
|
||||
reboot is resumed. `AlarmResolver.resolve` takes it without a default, so no
|
||||
caller can measure against a window the user did not choose.
|
||||
measured: the resolver's ringing check, the backstop `onFire` arms, and whether
|
||||
a ring interrupted by a reboot is resumed. `AlarmResolver.resolve` takes it
|
||||
without a default, so no caller can measure against a window the user did not
|
||||
choose. How late a snooze may come due and still ring is the window **or
|
||||
`AlarmRing.SNOOZE_GRACE` (v1's ten minutes), whichever is longer**: a short
|
||||
"Silence after" must not make a promised snooze easier to lose to a reboot.
|
||||
|
||||
**"Never" is an hour.** The backstop is also what stops a phone left at home
|
||||
from ringing until its battery is flat, what bounds the ring services' wake
|
||||
locks, and what keeps a reboot hours later from resuming a ring nobody was
|
||||
there for. So "Never" maps to `SilenceAfter.HARD_STOP` (60 minutes), longer
|
||||
than any finite choice, and the settings hint says so in words. Stored values
|
||||
are clamped to 0..60 on read, on write and from a backup, so no value can make
|
||||
a ring outlast it.
|
||||
go through `SilenceAfter.sanitise` on read, on write and from a backup: over 60
|
||||
is 60, so no value can make a ring outlast the hard stop, and a negative one is
|
||||
the default rather than the clamp's floor, which would be "Never".
|
||||
|
||||
A ring started under one window keeps the backstop it was armed with. When the
|
||||
window is shortened mid-ring, the next re-resolution closes the ring once it is
|
||||
past the new window, and `persist` then stops the ring service and cancels the
|
||||
backstop with it: storage says nothing rings, so nothing may. The same applies
|
||||
to any ring the resolver closes (a clock jumped forward, a ringing alarm
|
||||
switched off), which earlier only cleared `ringingSince` and left the sound to
|
||||
the backstop.
|
||||
Changing the setting mid-ring applies at once. The settings screen calls
|
||||
`AlarmEngine.onSilenceAfterChanged()`, which measures the ring in progress
|
||||
against the new window from when it *started*: past it, the cycle closes as
|
||||
missed through `closeCycleLocked`; inside it, the backstop moves to the new
|
||||
end. As a second line, `onAutoSilence` re-arms rather than closes a ring that
|
||||
is still inside the current window, so a backstop armed for a shorter one can
|
||||
never end a ring early.
|
||||
|
||||
Whenever the resolver closes a ring (a clock jumped forward, a ringing alarm
|
||||
switched off, a reboot outlasting the window), `persist` stops the ring service
|
||||
and cancels the backstop: storage says nothing rings, so nothing may. Earlier
|
||||
that path only cleared `ringingSince` and left the sound to the backstop. And a
|
||||
cycle the resolver closes as missed (a ring past its window, or a snooze that
|
||||
never fired) **disables a one-shot alarm**, exactly as `closeCycleLocked`
|
||||
does; falling through would have armed it for the same time tomorrow.
|
||||
|
||||
A **non-repeating alarm is disabled when its cycle closes, never when it opens**.
|
||||
Disabling it at the start would clear its own snooze and the alarm would vanish
|
||||
@@ -1924,7 +1935,12 @@ The window is the timer's own **"Silence after"** setting
|
||||
default: the same choices as the alarm's and the same one-hour "Never", but a
|
||||
separate value, because coupling the two would make one number answer two
|
||||
questions. `TimerRingPolicy` reads it from the defaults it already takes, so a
|
||||
change applies on the service's next pass. Unlike an alarm's, a timer's
|
||||
change applies on the service's next pass. A session that has gone quiet stays
|
||||
quiet: on auto-silence the policy moves the stored anchor back past
|
||||
`SilenceAfter.HARD_STOP`, so raising the setting afterwards cannot start it
|
||||
ringing again. The service's one heads-up is keyed to the session's anchor
|
||||
(`Sound.openedAt`) rather than to the window's end, which an edit can move
|
||||
without making a new session. Unlike an alarm's, a timer's
|
||||
**auto-silence stops the noise and leaves the row `EXPIRED`.** An auto-silenced
|
||||
alarm is a *missed* alarm and its cycle closes; an auto-silenced timer has still
|
||||
finished, and the user coming back must be able to see that and add a minute
|
||||
|
||||
+2
-1
@@ -151,7 +151,8 @@ other unknown field.
|
||||
are how long a ringing alarm or a finished timer keeps going before it stops on
|
||||
its own: whole minutes, with `0` meaning "Never" (which still stops after an
|
||||
hour). A file without them, from before the setting existed, imports as `10`,
|
||||
the value it was made with. Out-of-range values clamp to 0..60.
|
||||
the value it was made with. A value over 60 reads as 60 (which is what Never
|
||||
rings for anyway); a negative one reads as the default, 10.
|
||||
|
||||
Every numeric/duration value is clamped on *apply* using the same ranges and encoding
|
||||
as the existing preference setters, never on parse.
|
||||
|
||||
Reference in new issue
Block a user