Koensayr: Bluetooth metadata on the Y1 (and other stuff!)
Disclaimer: This is a firmware patcher. It modifies the /system partition on your Y1. I take no responsibility if you brick the device. Only try this if you understand what the patches are doing and how to recover if something goes sideways (worst case: re-flash a known-good stock rom.zip via MTKClient and you're back to square one). If you can't follow the README's setup steps or read the patch source, please don't run it.
A bit of background for anyone new to this project: I started Koensayr as a way to teach myself agentic AI workflows on something genuinely hard, rather than continuing to ignore the whole AI space. "Fix the Artists --> Albums workflow on a $60 MP3 player" was the original scope. A few weeks and an embarrassingly deep dive into the MediaTek AVRCP stack later, here we are.
For reference, my two previous posts are here and here.
Back on May 7 I posted that AVRCP metadata over Bluetooth was finally showing up on the Y1, but warned it was still WIP status and not spec-compliant. That's no longer the case.. It's ready for wider testing. I still expect bugs, but I can't do a larger-scale test on devices that I don't own. I only tested this on a few endpoints that I had available (Kia EV6, Samsung The Frame Pro TV, Sonos Roam, and one still being debugged: Chevrolet Bolt EV) and suspect that other devices may or may not behave differently. Either way, more data points aren't a bad thing.
After patching with Koensayr, when you pair the Y1 to a car head unit / Bluetooth speaker / TV / anything else that implements the receiving end of AVRCP, here's what you get:
- Track metadata on the peer screen - Title, Artist, Album, Genre, track number, total tracks, and duration all show up on the Now Playing screen of whatever you've paired to.
- Live playhead - the progress bar on the car screen moves in real time.
- Discrete PLAY / PAUSE / STOP / NEXT / PREV - clean PASSTHROUGH routing from steering-wheel buttons, including on head units that don't tolerate the "PLAY toggles to pause" behaviour some media targets do.
- A2DP stream survives pauses - silence-timeout was tearing down the audio connection on the stock firmware, which broke some car setups that didn't auto-reconnect. Fixed that.
- Strict-spec compatibility - infotainment systems that gate the Now Playing pane on the target advertising the right device class / event set / character-set capability should now pass those checks. Hardware-tested across a small set of receivers at this point and the AVRCP Target 1.3 feature compliance scorecard closes every Mandatory and every Optional row.
Plus, stock firmware 3.0.7 is supported as of today (alongside 3.0.2). The MediaTek Bluetooth binaries didn't change between the two releases (only the music APK did) so the smali patches now handle both versions automatically.
For my fellow nerds: The stock AVRCP target on this device is MediaTek's, hardcoded for AVRCP 1.0 passthrough (no metadata, no event subscriptions, nothing). Getting full 1.3 behaviour required injecting a trampoline chain into libextavrcp_jni.so that catches inbound AVRCP commands, builds spec-compliant 1.3 responses by calling the response-builder primitives already present in libextavrcp.so, and pushes them back to the AVCTP layer. A small Android service (Y1Bridge) and the patched music app feed live state through a watched-files protocol so the trampolines always have fresh metadata to emit. Full architecture diagram, byte-level patch reference, and the investigation trail are in the repo's docs/.
How to use:
GitHub: github.com/SeanathanVT/koensayr. Linux host required (mounts system.img via loopback and uses GNU sed, Mac/Windows users will need a Linux VM).
Roughly: one-time setup clones MTKClient and builds the two artifacts that --all needs.. src/su (the ~900-byte setuid su binary for --root, built with make) and src/Y1Bridge (the Android service that satisfies the MtkBt Binder contract for --avrcp, built with Gradle). Then drop your stock rom.zip (3.0.2 or 3.0.7) into staging/, run ./apply.bash --all, and the script handles the rest: pulling system.img out of the zip, loop-mounting it, applying every patch, unmounting, and flashing to the device via MTKClient. You will be prompted to plug in the Y1 and hit the boot button next to the USB-C port. You can also shut it down normally, keep it unplugged, and then just plug it in when it's ready to flash.
The README's Quick start section has the exact commands and toolchain prerequisites. Individual flags (--avrcp, --bluetooth, --music-apk, --adb, --remove-apps, --root) are all selectable on their own if you don't want the full bundle.
Caveats:
- You need the right
rom.zipMD5 from one of the supported builds (v3.0.2, v3.0.7). To prevent weirdness, unsupported versions will be rejected by the patcher. - Receivers that don't implement AVRCP correctly (some cheap BT speakers, some older car infotainment systems) may not properly render metadata regardless of what the Y1 sends. Most modern infotainment systems work; if you've got a strict one that doesn't, debug logs may need to be provided to troubleshoot and resolve (again, I can't reproduce every quirk locally as I don't have every possible Bluetooth endpoint available for testing purposes).
Let me know how it works for you, and if you encounter any weirdness with your own Bluetooth devices! If you find bugs and you know what you are doing and would like to implement any changes / fixes, feel free to fork, fix, and submit a Pull Request to that end! Or don't, that's the beauty of open source. :)
Also, thanks to those of you who've been DMing me about this project over the last few weeks. I hope it's interesting to you, and maybe something from this effort will get pulled into the Rockbox effort. I'd love to at least get a shoutout by the Rockbox team if anything from this project is used upstream (even the Bluetooth stack research stuff), but if not, it's cool. Side note, I've been messing with a more native port of Rockbox (Linux-based, not APK-based, bypassing Android entirely), but that's a post for another day.
Stay curious, y'all!
Edit 1: I should note that if your Y1 is already paired to something, you may need to clear / re-pair it before your endpoint "recognizes" the new feature set and allows metadata to flow.
Edit 2: Well, my SD card finally shat the bed. Can't even reformat it or wipe it with dd via ADB because I just get I/O errors. Tight.