7. use the Wear OS app as a remote display for phone sessions
status
accepted — not yet implemented. the wear app today is still only the standalone player described in "context": it syncs bundles and completed sessions over the Data Layer but cannot act as a remote display. this ADR records the agreed design for when the feature is built.
deciders
phase 11 design discussion
date
2026-09-07
context
the Wear OS app is currently a standalone player: it receives synced
meditations through the Wearable Data Layer, runs its own
MeditationPlayerController and RecitationPlayerController, and plays audio,
bells, soundscapes, and tts prompts locally on the watch.
users have asked to use the watch as a remote for a session started on the phone, with all audio still coming from the phone and the watch acting as a glanceable display and control surface.
decision
add a global "use watch as remote" setting in the phone app. when enabled,
starting a timer, breathing, or recitation session on the phone pushes
lightweight real-time state to the paired watch over the Wearable Data Layer
MessageClient. the watch renders the phone's player state without starting its
own audio, timers, or counters.
remote-mode behavior
- audio, tts, bells, soundscapes, segment timing, counting, and session logging all remain on the phone. the watch is a pure display and control surface.
- the remote toggle is a single global setting in the phone settings. the watch does not need a matching toggle; it enters remote mode whenever it receives an active remote-session message from the paired phone.
- the phone sends state messages on a new data-layer path such as
/sync/player_stateor/player/control. messages include elapsed time, remaining time, current segment, current count, play/paused/completed state, and the meditationsyncId. - watch transport controls (play, pause, stop, and recitation increment/decrement) send commands back to the phone. the phone is authoritative; the watch updates when the phone's controller emits the next state.
- for recitation, the phone's existing debounce and input handling remain the source of truth. the round-trip latency over bluetooth is acceptable because the phone already debounces raw input events.
- display behavior: in ambient mode, the watch shows a minimal "session running" view with total elapsed/remaining time. when the watch becomes active (wrist raise or tap), it shows the live state including per-second time or current count.
- entry flow:
- if the watch app is already in the foreground, it auto-routes to the remote player screen when the phone session starts.
- if the watch app is in the background, the phone triggers an
OngoingActivityon the watch. the user taps the ongoing-activity indicator to open the app. the ongoing activity does not auto-open on wrist raise. - disconnect behavior: the phone session continues. the watch stops updating and re-syncs state when the connection is restored.
- conflict: if the watch is already in its own standalone session when a phone
remote request arrives, the watch rejects the request (for example by sending a
busyresponse). it does not kill, discard, or save the standalone session.
scope
this decision covers the architecture and ux contract. the actual wire format, message paths, and new remote-only watch screens are implementation details to be worked out in the owning phase.
consequences
positive:
- the watch can be used as a wrist remote without syncing media to it for every session.
- both timer/breathing and recitation modes can share the same remote approach
because
MeditationPlayerControllerandRecitationPlayerControlleralready expose state streams suitable for driving a remote ui. - the existing standalone wear player remains intact; remote mode is opt-in from the phone and can be disabled at any time.
- the watch does not need its own copy of the meditation being played, because it only displays state sent by the phone.
negative:
- requires a new real-time control protocol over
MessageClientand new remote-only watch screens that do not instantiate the local player controllers. - the watch app must remain alive and connected; if the watch app is killed by the os or bluetooth drops, the remote display stops until the user reopens it.
- adds a runtime state ("remote mode") alongside the current standalone wear player, increasing the test matrix and the number of edge cases to handle (connection loss, reconnect, busy conflicts, ambient transitions).
- the current
DataLayerChannelonly exposes request/response and queued session-message methods; it will need extensions for streaming/tick messages and command messages, plus an event stream so the watch can receive messages while it is in the foreground.