-
Notifications
You must be signed in to change notification settings - Fork 30
Raise RTSP message limit so iOS mirror-stream SETUP isn't rejected - #11
Raise RTSP message limit so iOS mirror-stream SETUP isn't rejected #11mhoogenbosch wants to merge 1 commit into
Conversation
An iOS/iPadOS mirroring SETUP request carries a large binary plist
(~77 KB observed from an iPhone 17 on iOS 26). RtspRequestReader capped
request bodies at MAX_MESSAGE_BYTES = 64 KB and rejected anything larger
("Request body too large — rejecting"), so the video-stream SETUP was
dropped. The sender set up the audio stream, briefly played audio, then
tore the whole session down when its video SETUP got no response —
screen stayed black.
Raise MAX_MESSAGE_BYTES to 1 MB. That clears the observed ~77 KB SETUP
with ample headroom for future senders, and is trivially safe on a LAN
(the body is still read into a single bounded ByteArray).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request increases the MAX_MESSAGE_BYTES constant in RtspHandler.kt from 64 KB to 1 MB to accommodate larger binary plist payloads from iOS/iPadOS mirror-stream SETUP requests, preventing video stream rejections. I have no feedback to provide as there are no review comments.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
mhoogenbosch
commented
Jul 6, 2026
Issues are disabled on the repo, so posting the related iOS 26 findings here (separate from this PR's body-limit fix, which stands on its own). Tested with iPhone 17 / iOS 26.5.2 (sourceVersion=950.7.1) on a Nokia Streaming Box 8010, googletv debug build.
1. Screen mirroring — sender sends no stream SETUP after RECORD. With the body-limit fix in, the control session fully completes (pair-verify, fp-setup v=0x03, mirror keys, event channel, RECORD OK) and then only POST /feedback every 2 s, indefinitely and stably. There is never a mirror SETUP plist: streams=list[...] (no type 96 or 110), so nothing streams. Older senders emit the stream SETUP right after RECORD. Suspect GET /info (InfoResponder: model=AppleTV5,3, sourceVersion=220.68, features=0x1E5A7FFFF7) no longer matches what iOS 26 needs before opening the mirror video stream. fp-setup phase-1 mode varies across attempts (0/1/2).
2. /play video playback — unhandled POST /fp-setup2. Via an app's AirPlay button, iOS 26 reconnects, does GET /server-info, two fp-setup phases OK, then POST /fp-setup2 (120-byte body) → Unknown/unhandled RTSP: POST /fp-setup2, ~30 s stall, disconnect. iOS 26 seems to require this newer FairPlay step before it will proceed with /play.
3. mDNS (minor). (a) _airplay._tcp registration throws NameConflictException when the service name equals the system device name Google TV already advertises for Cast — leaves AirPlay "Disabled"; a distinct Device Name works around it (the code comment expects NsdManager auto-rename, but this Android build throws). (b) MdnsService.restart() on each teardown races the async unregister, so the name climbs ... (2), (3) and the device disappears/renames in the picker until a full restart.
Happy to capture full plists / the /fp-setup2 body hex / /info dumps if that helps chase the iOS 26 negotiation.
...ected iOS 26 senders emit a ~77 KB binary-plist SETUP for the mirror stream, which exceeded the 64 KB cap — the reader rejected it and the sender tore the session down right after audio started. Same fix as upstream PR #11. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
...ected iOS 26 senders emit a ~77 KB binary-plist SETUP for the mirror stream, which exceeded the 64 KB cap — the reader rejected it and the sender tore the session down right after audio started. Same fix as upstream PR mazer666#11. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sigurdshilfe
commented
Aug 26, 2026
Hi @mazer666, sorry to comment here, but it seems the 'Issues' tab is disabled for this repository. I'm experiencing two critical bugs on Sony Android TV 12. Describe the bug
I am experiencing two specific issues with PhairPlay on my Sony TV:
Screensaver interrupts casting: When casting for a long time (around 1 hour) or when the TV's power-saving/screensaver timer triggers, PhairPlay does not prevent the screen from sleeping. The TV automatically switches to the screensaver. Other casting apps usually prevent this.
Discovery fails after deep sleep: If I turn off the TV via the remote (standby mode) and turn it back on after 3-4 hours, PhairPlay can no longer be discovered by any Apple device. This happens in both Sony's Normal mode and Pro mode.
To Reproduce
Issue 1: Start AirPlay mirroring. Wait for the TV's screensaver timeout. The cast is interrupted by the screensaver.
Issue 2: Put the TV to sleep via the remote. Wait 3-4 hours. Turn on the TV, launch PhairPlay, and try to search for the TV via AirPlay. It will not show up.
Expected behavior
PhairPlay should keep the screen awake (FLAG_KEEP_SCREEN_ON or WakeLock) during an active casting session.
PhairPlay should properly re-initialize the network broadcast service (mDNS) when the TV wakes up from standby.
Environment:
TV Model: Sony X90J
OS: Android TV 12
Sender Devices: macOS 15.7.9, iPhone 13 / 16 Pro Max (iOS 18.7.2 / iOS 26.6)
Hi @mazer666, sorry to comment here, but it seems the 'Issues' tab is disabled for this repository. I'm experiencing two critical bugs on Sony Android TV 12. Describe the bug I am experiencing two specific issues with PhairPlay on my Sony TV:
Screensaver interrupts casting: When casting for a long time (around 1 hour) or when the TV's power-saving/screensaver timer triggers, PhairPlay does not prevent the screen from sleeping. The TV automatically switches to the screensaver. Other casting apps usually prevent this. Discovery fails after deep sleep: If I turn off the TV via the remote (standby mode) and turn it back on after 3-4 hours, PhairPlay can no longer be discovered by any Apple device. This happens in both Sony's Normal mode and Pro mode. To Reproduce Issue 1: Start AirPlay mirroring. Wait for the TV's screensaver timeout. The cast is interrupted by the screensaver. Issue 2: Put the TV to sleep via the remote. Wait 3-4 hours. Turn on the TV, launch PhairPlay, and try to search for the TV via AirPlay. It will not show up. Expected behavior PhairPlay should keep the screen awake (FLAG_KEEP_SCREEN_ON or WakeLock) during an active casting session. PhairPlay should properly re-initialize the network broadcast service (mDNS) when the TV wakes up from standby. Environment: TV Model: Sony X90J OS: Android TV 12 Sender Devices: macOS 15.7.9, iPhone 13 / 16 Pro Max (iOS 18.7.2 / iOS 26.6)
I created a fork for this APK, and fixed lot's of bugs.
https://github.com/mhoogenbosch/PhairPlay
Maybe it helps you, if not, feel free to raise an issue.
-- edit
You are right, there was no way of making sure the screensaver wouldn't pop on. I fixed this in my fork, en will create a PR for this upstream repo.
mhoogenbosch
commented
Aug 27, 2026
@sigurdshilfe both of your findings are fixed and sent upstream as #13.
You were right on both counts, and neither turned out to be Sony-specific — I could reproduce them on a Fire TV. There was no FLAG_KEEP_SCREEN_ON and no wake lock anywhere in the app, so nothing ever kept the screen up during a session. And an NsdManager registration does not survive the Wi-Fi interface going down in standby, with no code path to bring it back: on wake the receiver is still listening on port 7000 and still thinks it is running, while being invisible to every sender.
One extra thing came out of the second one: CHANGE_WIFI_MULTICAST_STATE has been in the manifest from the start but nothing ever used it, so Wi-Fi power-save was free to drop the multicast frames that carry every AirPlay query. That is now held by a MulticastLock while advertising, and may well be part of why discovery felt flaky beyond the standby case.
Verified on hardware by bouncing a TV's own Wi-Fi — the advertisement comes back within a second of the network returning, display name intact.
If you would rather not wait for #13 to be reviewed, the same fixes are in my fork's v1.1.0-mh.7 release with prebuilt APKs for Google TV and Fire TV: https://github.com/mhoogenbosch/PhairPlay/releases/tag/v1.1.0-mh.7 — adb install -r keeps your settings and display name. Do let me know if the standby case still bites you after that; I could only test it by forcing the interface down, not by leaving a TV off for four hours.
Problem
When mirroring from an iPhone (observed: iPhone 17, iOS 26.5.2), the AirPlay session established fine (pair-verify, fp-setup, mirror keys, RECORD) and the audio stream even played briefly — but then the sender tore the whole session down and the screen stayed black.
The debug log showed the cause:
The iOS mirror-stream
SETUPrequest carries a large binary plist (~77 KB in my capture).RtspRequestReadercaps request bodies atMAX_MESSAGE_BYTES = 65536(64 KB) and returnsnullfor anything larger, so the video stream SETUP was dropped. The sender set up the audio stream (small SETUP), played ~1 s of audio, then gave up when its video SETUP got no response.Fix
Raise
MAX_MESSAGE_BYTES(inRtspHandler) from 64 KB to 1 MB. This clears the observed ~77 KB SETUP with ample headroom, and stays trivially safe on a LAN — the body is still read into a single boundedByteArray(contentLength).Testing
Built
assembleGoogletvDebug, sideloaded on a Nokia Streaming Box 8010 (Google TV). Before: audio played ~1 s then instantClient disconnected. After: the session stays up and audio streaming is stable (continuous/feedbackkeep-alives for minutes, no teardown).Note: full iOS 26 screen-mirror video still doesn't render on my end for other reasons (the sender doesn't emit a stream SETUP after RECORD on iOS 26, and the
/playvideo-playback path hits an unhandledPOST /fp-setup2) — I'll file those separately as an issue. This PR is scoped to the body-limit bug, which is a clear regression blocker on its own.🤖 Generated with Claude Code