Skip to content

Fix casting#3377

Draft
hasali19 wants to merge 1 commit into
microg:masterfrom
hasali19:cast
Draft

Fix casting#3377
hasali19 wants to merge 1 commit into
microg:masterfrom
hasali19:cast

Conversation

@hasali19

@hasali19 hasali19 commented Apr 6, 2026

Copy link
Copy Markdown

Addresses #580

This fixes a few issues preventing casting from working properly. My main focus has been to get casting from the youtube app working. I've tested this on a CCwGTV from an emulator (with a hardcoded address since emulator can't do mDNS) and it seems to be able to start a session and control media playback. The disconnect process is a bit broken so still need to dig into that.

@aquette

aquette commented Apr 12, 2026

Copy link
Copy Markdown

Great to see some activity to fix this lack (missing screen cast on microG), thanks @hasali19 😀
Anything to be consolidated from #3351 ?

@hasali19

Copy link
Copy Markdown
Author

The changes in #3351 didn't work for me, in particular the connection attempts in CastMediaRouteController throw errors. I don't think changes are needed to that class anyway (at least not to get basic casting working)

@peterhel

Copy link
Copy Markdown

Nice work — this builds clean for me (:play-services-core:assembleVtmDefaultDebug → BUILD SUCCESSFUL), which already puts it ahead of a couple of the other Cast PRs, and the connectionless handshake looks right.

Full disclosure so this lands as "someone who walked the same path" rather than a competing claim: I went down the connectionless route too (#3570), reverse-engineering play-services-cast 21.4.0 and validating it against the real Amazon Prime Video app on a hardware Chromecast (Prime launched its own receiver and played a DRM title). The notable thing: we independently converged on the same wire contract. Your connect() = 16, addListener(...) = 17, and the listener callback as an int at = 13 all match what I landed on (I named the last onConnectedWithResult(int) and the register call setListener — cosmetic, since AIDL dispatches by transaction id). That's a good signal it's right, especially since #3502 put onConnected(String sessionId) at that listener slot, which I suspect is wrong — two independent RE passes landing on int is reassuring.

Small bug: CastDeviceControllerImpl.onConnected(int) dereferences listener without a null check, unlike every other onXxx callback in the file — if a connection event lands before addListener() runs, it'll NPE. A if (this.listener != null) guard (matching the siblings) fixes it.

Minor: the "///ALLOW_IPV6" suffix in CastMediaControlIntent.categoryForCast() works but is a bit magic — a one-line comment on the why would help. And in SessionImpl, heads-up that onApplicationConnectionFailure() nulls castContext then dereferences it a couple lines later (pre-existing, not yours, but it'll NPE on the failure path).

Happy to validate on real hardware — I've got a Chromecast-with-Google-TV rig, and since this is YouTube-focused I can try YouTube specifically and report what the receiver does. Thanks for pushing this forward.

@peterhel

Copy link
Copy Markdown

Tested #3377 on real hardware (Pixel 2 + Chromecast, connectionless path): it casts — video plays end-to-end (PLAYING, currentTime advancing, the Chromecast pulled the stream). Your impl + onConnected(int) work in practice, not just the emulator. 🎉

The session was initially unstable, though: microG's CastDynamiteModuleImpl.newReconnectionServiceImpl returns null, and your CastContextImpl wiring makes the SDK start the ReconnectionService, which NPEs on it (...zzq.onCreate() on a null object reference, play-services-cast-framework 19.0.0) → that crash-loops the sender process → which is what threw the stream of onSendMessageSuccess / onTextMessageReceived RemoteExceptions (callbacks landing on a dying listener).

I implemented a minimal no-op newReconnectionServiceImpl (an IReconnectionService.Stub — no-op onCreate/onDestroy, onStartCommand=START_NOT_STICKY, onBind=null) and rebuilt: crash gone, the RemoteExceptions gone, and the cast is clean and stable — video plays, sender stays alive, zero errors.

Since that newReconnectionServiceImpl gap is microG-level (it'll hit any connectionless PR that wires up reconnection, not just this one), I'm putting it up as a small separate fix. With it in place, #3377 casts cleanly here. Nice work getting the connectionless path this far.

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.

3 participants