L2CAP connection fails on A16 GrapheneOS
Commented on #188 as well, but creating a new issue as I have gathered some more potentially helpful info.
As zygisk does not work on rooted GrapheneOS, I can't (correct me if I'm wrong) use the Xposed framework. Thus I'm installing the btl2capfix module with Magisk.
I tried the module from #61 using the nightly build and got the same error mentioned in #188. I then tried investigating the module to see if it does what it has to. Android is not my expertise so my assumptions might be wrong but here are my findings (looking at the phones filesystem after module install and reboot):
- My phones bluetooth library is located at
/apex/com.android.bt/lib64/libbluetooth_jni.so. -
post-data-fs.shcreates an overlay mount from/data/adb/modules_update/btl2capfix/apex/com.android.bt/lib64to/apex/com.android.bt/lib64
Contents ofpost-data-fs.sh:#!/system/bin/sh mount -t overlay overlay -o lowerdir=/apex/com.android.bt/lib64,upperdir=/data/adb/modules_update/btl2capfix/apex/com.android.bt/lib64,workdir=/data/adb/modules_update/btl2capfix/apex/com.android.bt/work /apex/com.android.bt/lib64 -
/data/adb/modules_update/does not exist, but/data/adb/modules/btl2capfix/does - With this info I tried patching the module to instead mount
/data/adb/modules/btl2capfix/apex/com.android.bt/lib64to/apex/.../lib64 - After installing the modified module I checked the sha512 hashes for both files and they didn't match +
mount | grep overlay | grep bluetoothandmount | grep apex.*btdidn't return anything to indicate an overlay mount to/apex/.../lib64 - I then tried to instead create a bind mount, that did not work as well. Then I tried the bind mount, but in
service.shinstead ofpost-data-fs.sh. This finally worked
By worked I mean the sha512 hashes of/data/adb/modules/btl2capfix/apex/com.android.bt/lib64/libbluetooth_jni.soand/apex/com.android.bt/lib64/libbluetooth_jni.somatched. I'm not sure that's the correct way to measure success in this case, but there was a change. - I copied the patched
libbluetooth_jni.sofile over to my computer to check if the patches were successful. I looked at the addresses dispalyed for both functions is the Magisk install log and both had a return at the start of the function - matching the hex incustomize.sh - Even with the now confirmed patched
libbluetooth_jni.sobind mounted into/apex/.../lib64, the same error of L2CAP connection failing persisted.
I captured troubleshooting logs with the module mentioned in #61: airpods_log_1759102497486.txt And the modified version with bind mounting and matching file hashes: airpods_log_1759102773514.txt
I am aware that this is a massive edge case as Pixel phones with A16 seem to work when using the Xposed framework. I might be the only person trying to run Librepods on a Pixel6 running rooted GrapheneOS.
I am very thankful for your continued work on this project. Let me know if I can provide any additional information.
Hi!
As zygisk does not work on rooted OxygenOS
Which OxygenOS version? I have used it with A14, not sure why A15 would break it.
Weirdly, Android seems to be using the patched library anyway without the bind mounts too, or the patched function is not called anyway. I couldn't find any logs saying this.
The problem is this. If you are able to use xposed, I can try to create another hook for this function and force the modes to be equal.
Also, are you on Graphene or OxygenOS?
Late night mistake, I meant to write GrapheneOS. I edited the original issue to fix the typo.
Is it possible to patch l2c_fcr_adj_our_rsp_options by installing a Magisk module (like I did above) or is xposed necessary?
Late night mistake, I meant to write GrapheneOS. I edited the original issue to fix the typo.
Got it. I don't know about GrapheneOS. Is there a reason why it doesn't work? quick google search just shows people suggesting not to do it, but not that it doesn't work.
Is it possible to patch l2c_fcr_adj_our_rsp_options by installing a Magisk module (like I did above) or is xposed necessary?
Sorry, I was looking at the wrong code. We'd have to patch this itself. I don't have much knowledge about that, though. And here, xposed will also be a bit difficult because it's part of a big function.
I'm not that knowledgeable about root/GrapheneOS myself, but when I tried to enable Zygisk from Magisk settings it still said "reboot to apply settings" regardless of how many times I rebootes the phone. There might be a way to enable it, but I couldn't make it work.
The patch would just make it so that "Verify two sides are in compatible modes before continuing" if statement is alwats false? I could try to create that patch. Shouldn't be too difficult?
I'm not that knowledgeable about root/GrapheneOS myself, but when I tried to enable Zygisk from Magisk settings it still said "reboot to apply settings" regardless of how many times I rebootes the phone. There might be a way to enable it, but I couldn't make it work.
You could try installing https://github.com/PerformanC/ReZygisk.
The patch would just make it so that "Verify two sides are in compatible modes before continuing" if statement is alwats false?
Yup, and bypass the disconnection. Actually, breaking that if-else chain before calling l2cu_send_peer_disc_req(p_ccb) is what we want.
You could try installing https://github.com/PerformanC/ReZygisk.
ReZygisk installed successfully, but GrapheneOS didn't allow opening the LSPosed manager. It tried to use DCL from memory, which is restricted for preinstalled apps (Shell in this case). I didn't find any workaround for this.
Yup, and bypass the disconnection. Actually, breaking that if-else chain before calling l2cu_send_peer_disc_req(p_ccb) is what we want.
This worked somewhat. I had to manually locate the memory address of the comparison. Don't know if/how to make it automatic like the 2 function patches currently in btl2capfix.
I set the address (0x009308d4 for me) to 1f2003d5 (nop) and the L2CAP error disappeared. Had no luck with the overlay mount, only my modified bind mount approach.
To recap:
I successfully got rid of the "L2CAP connection fails" error message by switching to a bind mount and patching the if (p_ccb->our_cfg.fcr.mode != p_ccb->peer_cfg.fcr.mode) comparison to a nop instruction.
What works:
- Battery indicator
- ANC/Transparency mode switching and indicator
What doesn't seem to work:
- Head tracking (both the default and alternative packets)
- Switching the longpress actions
- Media play/pause with inear detection
- Disabling Volume Control (works regardless of switch state in UI)
- "Disconnect AirPods when not wearing" - music still plays with AirPods on table
Based on this: maybe the error isn't displayed, but the connection is still not successful? Or maybe I have to set IRK and ENV_KEY manually?
Thiis is the customize.sh that worked:
customize_bind.sh
ReZygisk installed successfully, but GrapheneOS didn't allow opening the LSPosed manager. It tried to use DCL from memory, which is restricted for preinstalled apps (Shell in this case). I didn't find any workaround for this.
Okay, thanks for trying!
Only those two things working is weird. Do these work only after some time of the connection or stay working till the airpods are connected?
Or maybe I have to set IRK and ENV_KEY manually?
Nope, you shouldn't need to- that's just for BLE (scanning when AirPods are nearby. And anyway, if you can change the noise control modes, the app has already probably fetched the keys.
Don't know if/how to make it automatic like the 2 function patches currently in btl2capfix.
would probably have to find out based on the log string, and work up to the nearest if comparison. Too much effort for now.
Could you please collect the logs yourself with adb for the bluetooth process and the app's process? Because the connection is apparently successful, the troubleshooter might not be exactly helpful.
Happy to report that when I installed 0.20.0-alpha some things started working. Not sure if it was a case of reinstalling or rebooting or the update itself.
Inear detection worked great, head tracking didn't and iirc some other things as well. Sometimes there was also a weird moment where the airpods disconnected and reconnected a couple of times before getting a stable connection. They also seemed to disconnect right after media stopped playing, then reconnect and pause the media when I pressed play on something.
An OTA update I just did seems to have broken the magisk patch - airpods keep disconnecting and even when they do connect, LibrePods doesn't see them.
I'll provide the app logs right now: _data_user_0_me.kavishdevar.librepods_files_logs_airpods_log_20251004_213842.txt
I'll try checking if the memory address of that if statement changed and collect adb logs tomorrow. What command should I use for collecting logs via adb?
Happy to report that when I installed 0.20.0-alpha some things started working. Not sure if it was a case of reinstalling or rebooting or the update itself.
Great to hear that! Haven't changed any connection part. Probably rebooting or something might've fixed.
head tracking didn't and iirc some other things as well.
Could you please try enabling alternate head tracking packets from app settings?
They also seemed to disconnect right after media stopped playing, then reconnect and pause the media when I pressed play on something.
That's weird, this should only happen when there is another device connected too, and that takes ownership of the connection. And this needs a different hook, which you do not have. I'll try to reproduce.
An OTA update I just did seems to have broken the magisk patch
Yeah, you will have to repatch the library. Does your Bluetooth work after the OTA? If the library was changed, it usually should just stop working entirely.
For logs (after you have repatched the library):
dumpsys package me.kavishdevar.librepods | grep -m 1 "uid="
dumpsys package com.google.android.bluetooth | grep -m 1 "uid="
And, then logcat --uid=uid1,uid2.
@kavishdevar is it possible if someone can test out a change on bluetooth stack,
https://github.com/danascape/android_packages_modules_Bluetooth/commit/f369e7813ed86a1439823bfb43cd8bae1492cfb4
^ Based on the comments in the issuetracker, Ill reframe commit message later on
I can help out with AOSP-based patchsets for airpods support, and until next month I wont have access to airpods to try it out myself, just leaving this here, incase someone tries it out.
Thanks
Thank you so much, @danascape! I don't have sources downloaded. I'll test with a GSI when I have and get back to you.