Treat KEYCODE_MEDIA_PLAY as play-only to stop repeated Android Auto pauses - #5535
Treat KEYCODE_MEDIA_PLAY as play-only to stop repeated Android Auto pauses#5535joashrajin wants to merge 5 commits into
Conversation
Wireless Android Auto head units send redundant KEYCODE_MEDIA_PLAY events while playback is already running. Since the key was routed into the play/pause toggle, each redundant play event paused playback, causing the repeated-pause loop reported in PCDROID-516. PCDROID-516
|
Claude finished @joashrajin's task in 1m 45s —— View job Code Review
I traced the change through ✅ What's correct
🟡 Suggestions (non-blocking)1. The legacy 2. Duplicated logic across two callbacks. 3. Minor: VerdictThe fix is correct and minimal, and the reasoning in the PR body matches what the code does. The only thing I'd genuinely want addressed before merge is a note on the legacy |
|
Claude finished @joashrajin's task in 2m 5s —— View job Code Review
Nice, focused fix. The root cause analysis is sound: since #3297 routed Correctness ✅
Suggestions / things worth noting1. Test coverage is asymmetric. The 3 new tests cover 2. Duplicated logic + comment across two files. The guard block (comment, 3. 4. Behavioral edge (expected, not a bug): a non-spec-compliant device that uses Nits
Overall this looks correct, minimal, and low-risk. The main thing I'd want before merge is the on-device confirmation and a decision on the legacy-path test gap. |
|
Claude finished @joashrajin's task in 2m 3s —— View job Code Review
I traced the redundant ✅ Correctness
🟡 Suggestions (non-blocking)
Nits
VerdictCorrect, focused, and low-risk. Nothing blocking in the code; the two things I'd want before merge are the on-device confirmation and a decision on the legacy-path test gap (item 2). |
| if (playOnly && playbackManager.isPlaying()) { | ||
| LogBuffer.i(LogBuffer.TAG_PLAYBACK, "Ignoring KEYCODE_MEDIA_PLAY because playback is already playing") | ||
| return | ||
| } |
There was a problem hiding this comment.
This guard is identical to the one just added in Media3SessionCallback.handleMediaButtonSingleTap (comment, isPlaying() check, log line, early return). Since the two callbacks must stay behaviourally in lockstep for play-only semantics, consider hoisting this into a single shared helper — e.g. an extension on PlaybackManager:
fun PlaybackManager.playIfNotPlaying(sourceView: SourceView) {
if (isPlaying()) return
playQueue(sourceView)
}Then both single-tap handlers become if (playOnly) playbackManager.playIfNotPlaying(source) else playbackManager.playPause(source). This also removes the double isPlaying() read (guard + playPause()) and the tiny TOCTOU window between them. Non-blocking — the current duplication is correct, just drift-prone.
There was a problem hiding this comment.
Pull request overview
Adjusts media-button handling so KEYCODE_MEDIA_PLAY behaves as a play-only command (instead of a play/pause toggle) to prevent wireless Android Auto head units from repeatedly pausing playback when they emit redundant play events.
Changes:
- Route single-tap handling with a
playOnlyflag when the originating key isKEYCODE_MEDIA_PLAY(Media3 + legacy MediaSessionCompat paths). - Ignore
KEYCODE_MEDIA_PLAYsingle taps when playback is already running (prevents accidental toggling into pause). - Add unit tests covering the new
KEYCODE_MEDIA_PLAYplay-only behavior and ensuringKEYCODE_MEDIA_PLAY_PAUSEstill toggles.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/Media3SessionCallbackTest.kt | Adds tests for play-only semantics and ensures play/pause toggle remains unchanged for KEYCODE_MEDIA_PLAY_PAUSE. |
| modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/MediaSessionManager.kt | Applies play-only semantics to legacy MediaSessionCompat single-tap handling for KEYCODE_MEDIA_PLAY. |
| modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/Media3SessionCallback.kt | Applies play-only semantics to Media3 session callback single-tap handling for KEYCODE_MEDIA_PLAY. |
| CHANGELOG.md | Documents the wireless Android Auto repeated-pausing fix under 8.17 bug fixes. |
…ling Addresses review feedback: shares the KEYCODE_MEDIA_PLAY play-only guard between the Media3 and legacy session callbacks, removes the duplicated isPlaying() read, and adds direct unit coverage of the helper so both paths rely on tested logic.
|
Addressed the review feedback in 13a6806: extracted |
|
Claude finished @joashrajin's task in 1m 11s —— View job Code Review — follow-up on
|
|
Version |
…android-auto-repeatedly-pauses-when-bluetooth-is # Conflicts: # CHANGELOG.md
|
Claude finished @joashrajin's task in 1m 1s —— View job Code Review
Re-reviewed after the latest push (merge of ✅ Correctness (re-verified)
✅ Tests
🟢 Notes (non-blocking)
VerdictCorrect, minimal, and low-risk. Nothing blocking in the diff; the only outstanding item is the manual Android Auto confirmation. |
Description
Wireless Android Auto users report that playback repeatedly pauses a few seconds after pressing play (PCDROID-516, #3543). Logs show the head unit (
com.google.android.projection.gearhead) sending redundantKEYCODE_MEDIA_PLAYkey events while playback is already running. Since #3297 routedKEYCODE_MEDIA_PLAYinto the same single-tap play/pause toggle asKEYCODE_MEDIA_PLAY_PAUSE, each redundant play event toggled playback into a pause — producing the play/pause loop.This PR gives
KEYCODE_MEDIA_PLAYits explicit play-only semantics: a single tap from it is ignored when playback is already running, in bothMedia3SessionCallbackand the legacyMediaSessionManager. The key stays in theMediaEventQueuemulti-tap system, so the headset double/triple-tap skip behavior introduced by #3297 (and the Pixel Buds spurious-event suppression) is unchanged, andKEYCODE_MEDIA_PLAY_PAUSE/KEYCODE_HEADSETHOOKstill toggle as before.This should fix the repeated-pause loop; it needs on-device verification with a wireless Android Auto head unit (see TODOs below).
Fixes PCDROID-516
Testing Instructions
Unit tests:
./gradlew :modules:services:repositories:testDebugUnitTest --tests "*Media3SessionCallbackTest*"KEYCODE_MEDIA_PLAY is ignored while already playing,KEYCODE_MEDIA_PLAY_PAUSE still toggles while playing)On device:
Screenshots or Screencast
n/a — no UI changes.
Checklist
./gradlew spotlessApplyto automatically apply formatting/linting)Media3SessionCallbackTestmodules/services/localization/src/main/res/values/strings.xml— n/a, no stringsI have tested any UI changes...
n/a — no UI changes.