Two field reports, one chain: a dismissed alarm came back. Measured on the
emulator, three separate causes, all fixed here.
1. The alarm-clock entry launched an activity. On Android 14+ that launch is
refused from the background and then *deferred*, so the window surfaced
later — after the alarm had been acknowledged — and the siren played again
for a delivered alert. The entry is now a broadcast to AlarmWakeReceiver,
which only wakes the process and re-posts the takeover notification, and
ignores an entry that outlived its arming. The one activity PendingIntent
left is the alarm-clock show intent, which only the user can invoke.
2. A dismissal could be lost. `acknowledgeAlarm` returned early when the
device identity had not loaded, and the queue's entry required a deviceId,
so the ack was silently dropped and the ledger still owed the alarm. The
queue accepts an entry without one (measured: the service takes a
device-token ack with no deviceId) and the flush resolves the identity.
Nothing raises — and the armed service does not start listening — until the
queued dismissals have been read, so a restart cannot ring before the seed.
3. Acknowledging now unsubscribes the device (owner ruling: a dismissal is
leaving). The ack settles the ledger first, then the subscription row goes;
the takeover closes itself and Home reports "Acknowledged — this device
unsubscribed". A leftover subscription was a live address that kept ringing
on every launch.
Also: an alarm is only sounded for an alert this device still follows (or a
trigger event that actually arrived), and the takeover never renders the raw
alert id as its headline — that fallback is what made a stale launch look like
an alarm for "dbf1a4c2-…".
Verified on the emulator: join → trigger → acknowledge → subscription row gone,
alert delivered, app returns Home by itself; force-stop and reopen is silent
for the whole session (no audio, no notification, no takeover).