Skip to content

Shared refactoring for Media3 integration#5147

Merged
sztomek merged 5 commits intomedia3/05-legacy-servicefrom
media3/06a-shared-refactoring
Apr 8, 2026
Merged

Shared refactoring for Media3 integration#5147
sztomek merged 5 commits intomedia3/05-legacy-servicefrom
media3/06a-shared-refactoring

Conversation

@sztomek
Copy link
Copy Markdown
Contributor

@sztomek sztomek commented Mar 19, 2026

Description

Prep work for wiring the Media3 session into the app. This refactors shared playback components so the next PR can plug them in cleanly, with no behavior change when the MEDIA3_SESSION flag is off (now defaulting to false).

Key changes: extract SleepTimerHandler for reuse across legacy and Media3 services, add suspend variants to MediaSessionActions, switch PocketCastsForwardingPlayer from Bitmap to ByteArray artwork and fix double-invoked transport callbacks, add a hasReceivedUpdate guard to CastStatePlayer, and enrich Media3SessionCallback/Media3LibrarySessionCallback with podcast/episode resolution for media item and playback resumption. LegacyPlaybackService is simplified by delegating sleep timer logic to the new handler and gains an onTaskRemoved override. BrowseTreeProvider visibility is tightened to internal and Up Next is removed from the root browse tree.

Testing Instructions

Just review the code pls

Checklist

  • If this is a user-facing change, I have added an entry in CHANGELOG.md
  • Ensure the linter passes (./gradlew spotlessApply to automatically apply formatting/linting)
  • I have considered whether it makes sense to add tests for my changes
  • All strings that need to be localized are in modules/services/localization/src/main/res/values/strings.xml
  • Any jetpack compose components I added or changed are covered by compose previews
  • I have updated (or requested that someone edit) the spreadsheet to reflect any new or changed analytics.

@sztomek sztomek added this to the 8.10 milestone Mar 19, 2026
@sztomek sztomek requested a review from a team as a code owner March 19, 2026 13:55
@sztomek sztomek requested review from Copilot and geekygecko and removed request for a team March 19, 2026 13:55
@sztomek sztomek added [Type] Enhancement Improve an existing feature. [Area] Playback Episode playback issue labels Mar 19, 2026
@dangermattic
Copy link
Copy Markdown
Collaborator

dangermattic commented Mar 19, 2026

2 Warnings
⚠️ This PR is larger than 500 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.
⚠️ Class SleepTimerHandler is missing tests, but unit-tests-exemption label was set to ignore this.

Generated by 🚫 Danger

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Prep work to support wiring a Media3 MediaSession into the app by refactoring shared playback components and aligning callback / player behavior with Media3 controller expectations (while defaulting MEDIA3_SESSION to off).

Changes:

  • Default MEDIA3_SESSION feature flag to false and refactor playback plumbing to be reusable across legacy + Media3 paths.
  • Add Media3-focused behavior updates: forwarding player metadata handling/interception, callback resolution of podcast/episode metadata, and Cast state guarding.
  • Tighten/adjust automotive browse tree + converters and update/expand unit tests around the new behavior.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
modules/services/utils/src/main/java/au/com/shiftyjelly/pocketcasts/utils/featureflag/Feature.kt Defaults Media3 session feature flag to off.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/SleepTimerHandler.kt New shared sleep-timer handler extracted for reuse.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/LegacyPlaybackService.kt Delegates sleep timer to handler and adds onTaskRemoved behavior.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/MediaSessionActions.kt Adds suspend variants for MediaSession-driven actions and refactors search-play path.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/MediaEventQueue.kt Changes to accept a scope provider instead of a direct scope.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/MediaSessionManager.kt Updates queue construction to match MediaEventQueue API change.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/Media3SessionCallback.kt Adds episode/podcast resolution for media items, adds command helpers, refines media-button behavior.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/Media3LibrarySessionCallback.kt Enriches playback resumption with metadata and artwork; sets automotive connected flag.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PocketCastsForwardingPlayer.kt Switches artwork to ByteArray, avoids double-invoked transport callbacks, intercepts Media3 controller playlist calls, adds clearMetadata().
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/CastStatePlayer.kt Adds “has received update” guard to avoid non-sensical initial state.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/BrowseTreeProvider.kt Tightens visibility and removes Up Next from root browse tree; makes playlist helpers visible for testing.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/auto/MediaItemCompatConverter.kt Uses artist instead of subtitle for compat subtitle mapping.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PocketCastsForwardingPlayerTest.kt Updates/expands tests for transport callback precedence and Media3 interception behavior.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/MediaEventQueueTest.kt Updates tests for new MediaEventQueue(scopeProvider=...) API.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/Media3SessionCallbackTest.kt Expands tests for suspend action routing, rating support, media item resolution, and media-button handling.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/Media3LibrarySessionCallbackTest.kt Expands resumption tests to assert metadata/artwork and automotive flag behavior.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/CastStatePlayerTest.kt Updates expectations for new initial idle state behavior.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/auto/MediaItemCompatConverterTest.kt Updates test to reflect artist usage.

You can also share your feedback on Copilot code review. Take the survey.

@sztomek sztomek modified the milestones: 8.10, 8.9 Mar 20, 2026
@sztomek sztomek force-pushed the media3/05-legacy-service branch from 7992866 to 08ef9b3 Compare March 27, 2026 16:04
@sztomek sztomek force-pushed the media3/06a-shared-refactoring branch from 1777fc2 to c2754bf Compare March 27, 2026 16:09
@wpmobilebot wpmobilebot modified the milestones: 8.9, 8.10 Mar 30, 2026
@wpmobilebot
Copy link
Copy Markdown
Collaborator

Version 8.9 has now entered code-freeze, so the milestone of this PR has been updated to 8.10.

@sztomek sztomek force-pushed the media3/05-legacy-service branch 2 times, most recently from da8949c to bc1dd94 Compare April 1, 2026 17:55
Copilot AI review requested due to automatic review settings April 1, 2026 17:58
@sztomek sztomek force-pushed the media3/06a-shared-refactoring branch from c2754bf to 830ac23 Compare April 1, 2026 17:58
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Refactors shared playback/service components as prep work for wiring Media3 sessions into the app, with the MEDIA3_SESSION feature flag now defaulting to false.

Changes:

  • Default Feature.MEDIA3_SESSION to false and adjust playback/Media3-related plumbing accordingly.
  • Extract shared SleepTimerHandler and simplify LegacyPlaybackService by delegating sleep-timer behavior (plus add onTaskRemoved handling).
  • Update Media3 session callbacks / forwarding player behavior and expand/adjust unit tests for the new interception + metadata resolution paths.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
modules/services/utils/src/main/java/au/com/shiftyjelly/pocketcasts/utils/featureflag/Feature.kt Defaults MEDIA3_SESSION to false.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/SleepTimerHandler.kt New shared sleep timer handler extracted from service logic.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/LegacyPlaybackService.kt Delegates sleep timer behavior to handler; adds onTaskRemoved; small refactors.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PocketCastsForwardingPlayer.kt Fixes transport callback precedence; intercepts Media3 controller protocol methods; adds metadata clearing.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/MediaSessionManager.kt Updates MediaEventQueue construction to use a scope provider.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/MediaSessionActions.kt Adds suspend variants and reworks search/play logic to support Media3 callbacks.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/MediaEventQueue.kt Switches to scopeProvider for queue timing jobs.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/Media3SessionCallback.kt Adds episode/podcast resolution for media items; refactors command handling; updates media button behavior.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/Media3LibrarySessionCallback.kt Enriches playback resumption metadata and adds automotive connected flag side-effect.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/CastStatePlayer.kt Adds “hasReceivedUpdate” guard to avoid non-idle state before first cast update.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/BrowseTreeProvider.kt Tightens visibility; removes Up Next from root; tweaks listening history handling; exposes internals for testing.
modules/services/repositories/src/main/java/au/com/shiftyjelly/pocketcasts/repositories/playback/auto/MediaItemCompatConverter.kt Uses artist instead of subtitle for compat subtitle mapping.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/PocketCastsForwardingPlayerTest.kt Updates/extends tests for callback precedence and Media3 interception paths.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/MediaEventQueueTest.kt Updates tests for scopeProvider API.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/Media3SessionCallbackTest.kt Updates tests for suspend action routing, media button handling, and resolved media items.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/Media3LibrarySessionCallbackTest.kt Updates tests for metadata-enriched resumption + automotive flag behavior.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/CastStatePlayerTest.kt Updates tests for idle-before-first-update behavior.
modules/services/repositories/src/test/java/au/com/shiftyjelly/pocketcasts/repositories/playback/auto/MediaItemCompatConverterTest.kt Updates test to expect artist mapping.

@sztomek sztomek force-pushed the media3/05-legacy-service branch from bc1dd94 to 3327e0e Compare April 1, 2026 20:28
@sztomek sztomek force-pushed the media3/06a-shared-refactoring branch from 830ac23 to c99a9d6 Compare April 1, 2026 20:31
@sztomek sztomek force-pushed the media3/05-legacy-service branch from 3327e0e to 09906b3 Compare April 2, 2026 10:56
@sztomek sztomek force-pushed the media3/06a-shared-refactoring branch from c99a9d6 to c227601 Compare April 2, 2026 10:56
Copilot AI review requested due to automatic review settings April 2, 2026 11:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

@sztomek sztomek force-pushed the media3/05-legacy-service branch from a03231c to b3edfd8 Compare April 8, 2026 08:30
sztomek and others added 5 commits April 8, 2026 10:30
- Store Flow job in SleepTimerHandler.observe() and cancel in dispose()
- Add onError handler to RxJava Observable.interval subscription
- Return empty list instead of null from LegacyPlaybackService.onSearch

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The eventHorizonValue property doesn't exist on SourceView yet at this
point in the branch stack. Use the existing analyticsValue property.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Split dispose() into cancelTimer() and dispose() so stopping the timer
  doesn't kill the state Flow observer
- Cancel existing observeJob before starting a new one to prevent leaks

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract shared resolveArtworkUri and buildEpisodeMediaItem helpers
- Remove duplicated code between Media3SessionCallback and Media3LibrarySessionCallback
- Add blank URL protection in resolveArtworkUri
@sztomek sztomek force-pushed the media3/06a-shared-refactoring branch from 938eaf4 to 52001a3 Compare April 8, 2026 08:38
@sztomek sztomek merged commit 97409db into media3/05-legacy-service Apr 8, 2026
18 checks passed
@sztomek sztomek deleted the media3/06a-shared-refactoring branch April 8, 2026 09:14
sztomek added a commit that referenced this pull request Apr 8, 2026
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Area] Playback Episode playback issue [Type] Enhancement Improve an existing feature. unit-tests-exemption

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants