Skip to content

[draft] Cast: move route socket operations off main thread#3470

Draft
emulatronicGIT wants to merge 5 commits into
microg:masterfrom
emulatronicGIT:codex/cast-route-main-thread-fix
Draft

[draft] Cast: move route socket operations off main thread#3470
emulatronicGIT wants to merge 5 commits into
microg:masterfrom
emulatronicGIT:codex/cast-route-main-thread-fix

Conversation

@emulatronicGIT
Copy link
Copy Markdown

This is a small follow-up branch for #3351, based on the current master branch and including the existing Cast connection lifecycle commits from that PR plus one additional fix for the crash reported in #3351 (comment).

The additional change moves CastMediaRouteController route connect/disconnect/release work onto a single background executor. That avoids calling ChromeCast.connect() from the media route provider handler/main path, which is what triggers the reported NetworkOnMainThreadException when selecting a Cast route.

What changed in the follow-up commit:

  • onSelect() schedules chromecast.connect() on a single-thread executor.
  • onUnselect() and onRelease() schedule disconnect on the same executor.
  • late work submitted after release is ignored instead of crashing.

Validation:

  • git diff --check fork/master..HEAD
  • JAVA_HOME=/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home ANDROID_HOME=/opt/homebrew/share/android-commandlinetools ./gradlew :play-services-cast-core:compileDebugJavaWithJavac

I cannot test actual Chromecast playback from this machine. The useful runtime check is whether the LogFox NetworkOnMainThreadException is gone and whether YouTube progresses past route selection.

FloodExLLC and others added 5 commits May 13, 2026 13:04
The ChromeCast object was created but connect() was never called
before launchApp(), sendRawRequest() etc., causing all outgoing
operations to fail with IOException because no socket existed.

- Add ensureConnected() helper; call it at the top of every
  outgoing operation (launchApplication, joinApplication,
  sendMessage, stopApplication)
- Fix launchApplication() to guard against a null Application
  response instead of NPE-ing on app.sessionId
- Implement joinApplication() properly: query device status,
  join an already-running matching session (wasLaunched=false),
  and only fall back to launching when the app is absent
chromecast.connect() throws both IOException and GeneralSecurityException
(a checked exception). The ensureConnected() helper only declared
throws IOException, causing a compile error.

Wrap the connect() call to catch GeneralSecurityException and rethrow
as IOException so all callers remain unchanged.

Fixes: microg#3351
onSelect() and onUnselect() were stubs. The Cast device connection
lifecycle must mirror the route selection lifecycle so the socket
is open before the Cast session begins and closed when the user
switches away.

- onSelect(): open TCP/TLS connection to the Cast device
- onUnselect() / onUnselect(int): close the connection
- onRelease(): close the connection when the controller is destroyed
….onSelect()

Same fix as CastDeviceControllerImpl: chromecast.connect() throws both
IOException and GeneralSecurityException. Update the catch clause to
handle both using a multi-catch.
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.

2 participants