Skip to content

Reaction: Don't auto-resume music after a manual pause#590

Merged
d4rken merged 4 commits into
mainfrom
fix/auto-play-respects-user-pause
May 7, 2026
Merged

Reaction: Don't auto-resume music after a manual pause#590
d4rken merged 4 commits into
mainfrom
fix/auto-play-respects-user-pause

Conversation

@d4rken

@d4rken d4rken commented May 6, 2026

Copy link
Copy Markdown
Member

What changed

Auto play now matches how AirPods behave on iPhone/Mac:

  • Bug fix: pausing music yourself (via the phone, the AirPods stem, or sleep detection) and putting your pods back in no longer makes the app auto-resume. Auto-resume now only follows an Auto pause caused by removing a pod.
  • New opt-in setting "Start music on wear" (per device): turn this on to restore the old behavior where putting your pods on tries to start music even if nothing was paused. Off by default.

Long conversations still work normally — taking a pod out for 30 seconds (or 30 minutes) and putting it back in resumes whatever Auto pause stopped, no time limit.

Technical Context

  • Default Auto play now strictly resumes a pause CAPod itself dispatched via the ear-removal flow. The previous condition (!isCurrentlyPlaying || wasRecentlyPausedByCap) was the bug — !isCurrentlyPlaying matched any music-stopped state including a manual user pause, so pod re-insertion fired a play key over the user's intent.
  • MediaControl.wasRecentlyPausedByCap is now a sticky boolean. Set when sendPause(rememberForResume = true) dispatches, cleared in sendPlay, also cleared on inactive→active playback transitions via AudioManager.AudioPlaybackCallback. Replaces the previous 15-second timer, which was too short for typical pod-out conversations and had a race where music starting from another source could leave a stale window that triggered a stray play key on the next pod-in.
  • sendPause(rememberForResume: Boolean = false) — only PlayPause's auto-pause branch passes true. SleepReaction and StemPressReaction (via sendPlayPause) keep the default false, so a stem-press pause or sleep-pause doesn't arm the auto-resume flag — and an explicit sendPause() that actually dispatches will clear a prior auto-resume flag, so a sleep-pause that happens after an ear-removal pause supersedes it.
  • New sendStop() for stem-mapped MEDIA_STOP clears the auto-resume flag — Stop is an explicit "stay stopped" intent.
  • capPaused is set before the suspending sendKey() dispatch — without that ordering, a playback config callback firing during dispatch could clear the flag and leave it stale-true.
  • AudioPlaybackCallback registration uses null for the Handler (Android defaults to the main looper) so JVM unit tests with mocked AudioManager don't need Robolectric.
  • New per-device ReactionConfig.startMusicOnWear: Boolean = false, persisted via AppleDeviceProfile.@SerialName("reactionStartMusicOnWear"). Default false for both new and legacy-migrated profiles, so the bug is fixed by default for all existing users.
  • The play decision is now: transition && (wasRecentlyPausedByCap || (startMusicOnWear && !isCurrentlyPlaying)) — applied identically in normal mode, one-pod mode, and BLE-only autoplay confirmation.

Review checklist

  • Bug repro: while music plays, manually pause via phone → take a pod out → put it back → music does not auto-resume.
  • Stem-pause repro: while music plays, press stem to pause → take pod out → put it back → music does not auto-resume.
  • Sleep-pause repro: sleep detection pauses → pod cycle later → music does not auto-resume.
  • Auto pause cycle works for any duration: take a pod out, wait 30s+, put it back → music resumes.
  • Cold wear default: app cold-start, put pods on with no music history → no play key dispatched.
  • Cold wear opt-in: enable "Start music on wear" → same scenario above fires the play key.
  • Music playing on speaker → put pods on → no double-play (already-active short-circuit).

@d4rken d4rken added the bug Something isn't working label May 6, 2026
d4rken added 3 commits May 7, 2026 13:32
Replaces the origin-tracking machinery with a simpler model that matches Apple's iOS/macOS behavior: auto-play strictly resumes a CAP-dispatched pause, gated by a sticky boolean cleared on inactive→active transitions. The original fire-on-cold-wear behavior is preserved as a per-device opt-in 'Start music on wear' setting.
…sleep

Matches Apple's iOS/macOS behavior: stem-press pauses and sleep-detection pauses are explicit user intent, not eligible for auto-resume on next pod-in. sendPause gains a rememberForResume parameter (default false); only PlayPause's auto-pause branch passes true. New sendStop wrapper clears the auto-resume flag for stem-mapped MEDIA_STOP.
@d4rken d4rken merged commit 8c9094d into main May 7, 2026
11 checks passed
@d4rken d4rken deleted the fix/auto-play-respects-user-pause branch May 7, 2026 12:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant