Field log · Sony Bravia KD-43X75WL
Sony's 2023 televisions are sealed shut: signed firmware, verified boot, no bootloader unlock, and none of the homebrew scene that cracked LG open. Getting a bouncing head onto one anyway took no root at all.
Live · dream surface
RunningThree of the four obvious routes were shut before the first command. The fourth was enough to install an APK and write secure settings, which is all this ever needed.
LG's webOS has RootMyTV and a homebrew channel. Samsung's Tizen has a developer-mode sideload path. Sony has scattered XDA threads from the Android 6 era, exploiting kernel bugs that died years ago. There is no Bravia equivalent, and on a 2023 set running Android 12 with verified boot there was never going to be.
So the plan skipped root entirely. The question was never how do we break in — it was how much can be done with the doors Sony left open on purpose. The answer turned out to be: nearly everything, provided you only want to change what the television shows when nobody is looking at it.
Google TV sets advertise Chromecast over mDNS, so discovery should have been one command. It returned nothing — ports 8008 and 8009 are shut on this model, and the cast service never announces itself. The fallback was a port sweep confirmed against Sony's own control API, which answers with the model name and needs no credentials to do it.
Confirming a candidate host
200 OK$ curl -s -X POST http://192.168.50.4/sony/system \ -d '{"method":"getInterfaceInformation","id":1,"params":[],"version":"1.0"}' {"result":[{"productCategory":"tv","productName":"BRAVIA", "modelName":"KD-43X75WL","interfaceVersion":"5.7.0"}],"id":1}
A set in standby answers nothing at all. European energy rules ship networked standby off, so an idle Bravia stays invisible until somebody physically turns it on.
Sony's Scalar API gates the interesting setters behind a pre-shared key. A surprising amount of the read side isn't gated at all. With no credentials whatsoever, the television will hand over its MAC address, its current volume, its power state, and a complete map of what is plugged into it — including the names the owner typed in.
Unauthenticated · /sony/avContent
No key sentHDMI 1 connected=False label=''
HDMI 2 connected=True label='ShitStation5'
HDMI 3 (eARC/ARC) connected=False label=''
HDMI 4 connected=True label=''
AV connected=False label=''
The MAC arrived the same way, listed as the Wake-on-LAN target by getSystemSupportedFunction. A useful leak in both directions: it gave us a DHCP reservation and a wake address, and its 58:96:71 Sony prefix became the fingerprint for locating the second set later.
Setting the key unlocked the rest — full identity, network settings, app list — and immediately closed a door.
prepareAppUpload and installApp would have meant sideloading with no ADB at all. Both answer error [15, "Unsupported Operation"]. They are advertised because consumer sets share an API surface with Sony's professional displays, and simply aren't implemented here.Sony's own signature for that method is afterIstallAction. The typo is in the shipping API. You have to spell it wrong for it to work — on the hardware where it works at all.
Android 11 introduced wireless debugging with a six-digit pairing code, and the natural assumption on an Android 12 device is that you need one. Sony left the legacy port open. adb connect on 5555 triggers an ordinary RSA authorisation prompt on the screen, and that is the entire ceremony.
ro.build.version.release 12 ro.build.version.sdk 31 ro.build.fingerprint Sony/BRAVIA_VH22_EU/BRAVIA_VH22:12/STT2.230505.001.S136 ro.board.platform mt5895 # and the detail that shaped everything after: dumpsys account Accounts: 0 resolve-activity HOME launcherx/.home.VanillaModeHomeActivity
No Google account is signed in, so the launcher runs in vanilla mode and tvrecommendations is already disabled.
| Priority | Component |
|---|---|
| 2 | launcherx/.home.VanillaModeHomeActivity |
| 1 | tungsten.setupwraith/.RecoveryActivity |
| −1000 | tv.settings/.system.FallbackHome |
The whole app is one DreamService. The SDK will produce it from four command-line tools with no Gradle daemon, no wrapper and no dependency resolution: aapt2 compiles and links resources, javac builds against android.jar, d8 produces the dex, apksigner signs it. Thirty lines of shell, about two seconds a build.
Motion is delta-time driven through Choreographer rather than per-frame, so it runs identically whether the panel composites at 50 Hz or 60. The bitmap is scaled once in onSizeChanged instead of every frame. Both sizes are fractions of the screen, which matters more than expected — the dream surface comes up at 1920×1080 even though the panel is 4K. I skipped the colour cycling: the classic DVD tint change is built for a flat vector mark and turns a photograph to mud, but i did consider it, since i know you will be asking.
screenrecord captures the Android UI and the dream perfectly, and will not capture an HDMI source — the console output is invisible to it.Both my tvs exist to run PlayStations. Android's idle timer counts remote-control input, and a DualSense talks to the console, not the screen — so on paper a set displaying a live game looks completely idle, and a bouncing head arriving three minutes into a boss fight was a real possibility.
Rather than guessing this needed to be tested, and turns out it will not, so nothing more to solve here.
| Condition | Elapsed | Result |
|---|---|---|
| Live PS5 signal, HDMI 2 | 135 s | never dreamed |
| Dead input, HDMI 4 (5 V, no signal) | 135 s | never dreamed |
| Android home screen — control | 75 s | dreamed on schedule |
Gaming is safe, and so is leaving a set parked on a dead input. The cost of that safety is that the logo only appears while idling in the Android UI, which on a television wired to a console is not often.
What actually shipped
A signed APK, a three-minute idle timer, and a screensaver that survives reboots because /data/app and the secure settings provider both persist. It is undone by a factory reset or by picking another screensaver in Sony's own menu, and nothing else.
XECAZ