Skip to content

RFC: sync Respect Phone DND to the watch (companion half)#304

Draft
vvzvlad wants to merge 1 commit into
coredevices:masterfrom
vvzvlad:rfc/respect-phone-dnd
Draft

RFC: sync Respect Phone DND to the watch (companion half)#304
vvzvlad wants to merge 1 commit into
coredevices:masterfrom
vvzvlad:rfc/respect-phone-dnd

Conversation

@vvzvlad

@vvzvlad vvzvlad commented Jul 22, 2026

Copy link
Copy Markdown

Paired PR: the firmware half lives in coredevices/PebbleOS#1772 (branch rfc/phone-dnd-silent) — it reads the ANCS silent flag, honours the wire SILENT bit platform-neutrally, and enforces quiet delivery when the synced notifRespectPhoneSilence pref is on. Each PR stands alone: firmware without this app change is inert; this app change without the firmware syncs a pref no watch reads.

Not compiled: this machine has no JDK 17 / Android SDK, so the change was verified by manual compile-correctness passes (property/interface threading, exhaustive whens, signatures, wire encoding) but has NOT been built. Build + run before treating as working code.

What this does

The firmware half honors a per-notification "silent" wire flag (bit 6 of the TimelineItem flags byte) and a syncable watch pref notifRespectPhoneSilence: when the pref is on, silent-flagged notifications get quiet delivery — stored and listed, no popup/vibration/backlight. This PR is the minimal app side that turns it on, reusing the existing toggle instead of adding a second one.

The single control is the existing "Respect Phone Do Not Disturb" toggle (Phone → Notifications). It was Android-only — gated on notification-filtering support, which iOS lacks because ANCS delivers notifications straight to the watch, bypassing the app. This PR:

  • un-gates that one toggle so it shows on both platforms, and
  • on change, mirrors it to a hidden synced watch pref notifRespectPhoneSilence — a BoolWatchPref with userVisible = false, so it is the firmware key and rides the existing watch-pref sync, but renders no row of its own (no duplicate toggle).

iOS — the app can't see the notification stream (ANCS goes phone→watch directly), so enforcement is firmware-side (coredevices/PebbleOS#1772); toggling just syncs the pref and the firmware acts on the ANCS silent bit.

Android — unchanged: the toggle still writes the existing respectDoNotDisturb config (the local-drop behaviour), and additionally syncs the pref, which is a harmless no-op there. See the next section for why the Android behaviour is deliberately left as-is.

This PR also declares TimelineItem.Flag.SILENT(6) — the wire-protocol counterpart of the firmware header bit — so the contract is documented in one place, even though nothing in this PR emits it.

⚖️ The Android wiring is a maintainer decision — this PR deliberately does NOT change Android

On Android the app is in the notification path, so unlike iOS it can act on DND itself. What should it do with a notification the phone delivered silently (DND/Focus)? Two defensible answers, and which one ships is your call — this PR takes neither on Android, it leaves the status quo in place:

Option A — drop (status quo, what this PR keeps). The existing respectDoNotDisturb toggle doesn't forward DND-suppressed notifications; they never reach the watch. Pros: watch stays clean, zero new moving parts, no firmware dependency. Cons: the notification is gone from the watch — it exists in the phone's shade but leaves no trace on the wrist; and it diverges from what the firmware currently does on iOS (lists it silently). That divergence is a design choice, not a platform limit — the firmware could equally discard silent notifications on iOS instead of listing them — but as written, iOS lists and Android drops.

Option B — forward-but-quiet (NOT implemented here). The app would forward the notification tagged with SILENT; the firmware stores and lists it without alerting. Pros: the watch stays a complete mirror of the phone's list, just without the buzz — identical to iOS, and matches how the phone itself treats DND (deliver quietly, not discard). Cons: changes what existing Android users see (notifications that used to vanish would appear, silently); on old firmware that ignores bit 6 they would arrive alerting.

My preference: Option B (keep them on the watch). I think keeping the notifications on the watch is the more correct behaviour — they can still be read, they just don't interrupt while DND is on. That mirrors the phone itself, where DND'd notifications stay visible in the shade rather than being discarded; dropping them on the watch throws away information the user may still want. I've left this PR on the conservative status quo (Option A) rather than change Android behaviour unilaterally, but my vote is Option B on both platforms.

The only Android-relevant addition here is the SILENT(6) wire-flag definition, so that if maintainers later choose Option B it needs no protocol change — just the emit path (set the flag when matchesInterruptionFilter() is false, per-notification, so Focus per-sender exceptions still alert).

Tests

  • TimelineFlagSilentTest (commonTest): TimelineItem.Flag.SILENT.value == 6 and makeFlags(listOf(SILENT)) emits bit 6 (0x40).

Not run locally (no toolchain) — see the warning at the top.

Known trade-offs

  • Old firmware + new pref: on iOS, enabling the toggle while running firmware that doesn't understand the pref simply does nothing (the firmware ignores an unknown synced pref). No misbehaviour — the feature just stays off until the firmware half ships.
  • No reverse sync: the toggle's checked state reads the respectDoNotDisturb config and its handler mirrors that value to the synced pref, so the two stay consistent from the UI (reset-to-defaults also skips the hidden pref). Nothing reads the pref back into the config, so they could only diverge if something wrote the pref watch-side independently — a path that doesn't exist today (the pref has no watch UI). Noted for completeness.

The existing phone-side "Respect Phone Do Not Disturb" toggle was
Android-only (gated on notification filtering, which iOS lacks because
ANCS delivers notifications straight to the watch). Un-gate it so it
shows on both platforms and, on change, mirror it to a synced watch
pref (notifRespectPhoneSilence) that the firmware reads to enforce quiet
delivery from the ANCS silent flag on iOS.

The synced pref is a hidden BoolWatchPref (userVisible = false) so it
does not render a second, duplicate row - the phone toggle stays the
sole UI control. Also declare the TimelineItem SILENT wire flag (bit 6)
as the documented counterpart of the firmware header bit; Android
notification handling is intentionally unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Vlad Zaytsev <git@vvzvlad.xyz>
@CLAassistant

CLAassistant commented Jul 22, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants