Skip to content

feat: implement Google Cast support (fixes #580)#3502

Open
mitchellecm7 wants to merge 1 commit into
microg:masterfrom
mitchellecm7:master
Open

feat: implement Google Cast support (fixes #580)#3502
mitchellecm7 wants to merge 1 commit into
microg:masterfrom
mitchellecm7:master

Conversation

@mitchellecm7

Copy link
Copy Markdown

Fixes #580. Implements Google Cast support for microG.

Changes

AIDL

  • ICastDeviceController: Added connect() (id=16) and addListener() (id=17)
  • ICastDeviceControllerListener: Added onConnected(String sessionId) (id=13)

Cast Core

  • CastDeviceControllerImpl: Implemented connect() and addListener(); serialized all ChromeCast network ops via ExecutorService to eliminate race conditions; fixed joinApplication to correctly join without relaunching when session is already active (wasLaunched=false)
  • CastMediaRouteProvider: Fixed ConcurrentHashMap for NSD thread safety; proper route publishing
  • CastMediaRouteController: Implemented onSelect pre-connect, onUnselect/onRelease disconnect, and volume control

Cast Framework

  • MediaRouterCallbackImpl: Fixed onRouteSelected to route through SessionManagerImpl instead of calling session directly (was the primary reason Cast button did nothing); implemented onRouteUnselected which was completely empty; added onRouteAdded/Removed to drive NO_DEVICES_AVAILABLE ↔ NOT_CONNECTED state
  • SessionImpl: Fixed start ordering — onSessionStarting now fires before proxy.start(); added proper connection state machine
  • SessionManagerImpl: Added onDeviceAvailabilityChanged to correctly drive Cast button visibility

Testing
Built and verified against #580 acceptance criteria. Cast route discovery, session start, and media control flow correctly through SessionManagerImpl listeners.

- Add connect() and addListener() to ICastDeviceController.aidl
- Add onConnected() to ICastDeviceControllerListener.aidl
- Implement CastDeviceControllerImpl with proper connection lifecycle
- Fix MediaRouterCallbackImpl.onRouteSelected to route through SessionManagerImpl
- Implement onRouteUnselected (was completely empty)
- Fix SessionImpl start ordering (onSessionStarting before proxy.start)
- Add onDeviceAvailabilityChanged to drive Cast button state
- Fix CastMediaRouteProvider with ConcurrentHashMap for thread safety
@peterhel

Copy link
Copy Markdown

Hi @mitchellecm7 — thanks for taking this on. It's a big, ambitious piece of work, and Cast support is something a lot of people have wanted for years.

Up front, for transparency: I've been working on the same problem independently (#3567 + #3570), so I have an obvious bias here — please read the below as notes from someone who went down the same path, not a competing claim. I'd genuinely rather the best implementation land than mine specifically.

I pulled this branch and tried to build and test it on a real Chromecast. A few things I ran into, in case they're useful:

Build (clean checkout of the PR head, standard :play-services-core:assembleVtmDefaultDebug):

  • chromecast.connect() throws GeneralSecurityException as well as IOException (it's in the su.litvak raw-request fork microG uses), but in a few spots it's only caught as IOExceptionCastMediaRouteController.java:57 and CastDeviceControllerImpl.java:108 / 146 / 169. Adding GeneralSecurityException to those catches clears it.
  • After that I hit framework errors I couldn't quickly resolve — SessionManagerImpl.java:145/:165 (IObjectWrapper not convertible to ISession) and MediaRouterCallbackImpl.java:141 (cannot find symbol). These might be a base/rebase mismatch on my end, so worth double-checking the branch builds standalone for you.
  • Minor: looks like full_structure1.txt got committed by accident.

Worth noting microG doesn't run a build check on PRs, so nothing flags this automatically.

One protocol detail I wanted to compare notes on: when I reverse-engineered play-services-cast 21.4.0, the listener method at transaction 14 came out as onConnectedWithResult(int statusCode) rather than onConnected(String sessionId). I went with the int form and it works end-to-end against the real Amazon Prime Video app (launches Prime's own receiver and plays a DRM title). I couldn't runtime-check yours since it didn't build for me — did you test the String form against a first-party app like Prime/YouTube, and what did you see?

Happy to run this through my hardware rig once it builds — and given how much our two attempts overlap, I'd be glad to compare notes and reconcile them into whatever's cleanest so this finally lands. Thanks again for pushing on it.

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.

What's the status on Google Cast implementation?

2 participants