App version
v1.0.0-rc1 (FOSS release)
App source
GitHub
Device
Motorola Edge 30 Fusion
Android / OS version
Android 17 (SDK 37), Evolution X (custom ROM)
Root / hook method
Other (describe in additional context)
AirPods model
AirPods Pro 3
AirPods firmware
9442210
What happened
Root: Folkpatch(Apatch fork) + Xposed
Everything LibrePods offers outside of the VendorID/"act as Apple" hook (multi-device connectivity, transparency mode customization, hearing aid setup) works correctly on this device via the systemized priv-app permissions alone — battery status, ear detection, controls, metadata, etc. all function with a fully stable connection.
The problem is isolated specifically to the hook: with it active (either unconditionally via the systemized install, or via "act as Apple" through LSPosed), AirPods connect successfully but then enter a rapid disconnect/reconnect cycle within seconds — multiple A2DP/HEADSET STATE_DISCONNECTED events fire within a 5-second window, repeating continuously. This happens regardless of an iPhone being nearby (tested with the iPhone's Bluetooth fully off, ruling out Apple's cross-device auto-switching as the cause).
With the hook disabled (LibrePods either fully disabled, or LSPosed-enabled with "act as Apple" off), the connection is fully stable — no drops after 10-15+ minutes of normal use, versus consistent disconnects within 2-3 minutes with the hook active.
Root cause, as far as I could trace it: per your own docs and issue tracker, the underlying Android Bluetooth stack L2CAP channel-mode bug that fake_l2c_fcr_chk_chan_modes works around (needed for multipoint/VendorID features) has been confirmed fixed in Android 17. On this device (genuinely running Android 17 / SDK 37), the hook still unconditionally forces l2c_fcr_chk_chan_modes to return 1/true, which appears to conflict with the platform's now-correct native negotiation rather than filling a gap — producing the disconnect cycling.
I decompiled the release APK to check for a way to disable just this hook:
KotlinModule.onPackageLoaded (the Xposed/LSPosed-loaded path) reads getRemotePreferences("me.kavishdevar.librepods").getBoolean("vendor_id_hook", false) and calls NativeBridge.setSdpHook(value) accordingly — so this path is gated by a preference.
However, when LibrePods is installed as a systemized priv-app without being separately enabled as an LSPosed module, the same native hook still fires (confirmed via LibrePodsHook: fake_l2c_fcr_chk_chan_modes called in logcat), independent of the vendor_id_hook preference (which wasn't even present in settings.xml at the time). The systemized/Magisk-module install path appears to apply the hook unconditionally, with no way to opt out short of disabling the whole module.
Enabling LibrePods as an LSPosed module and turning on "act as Apple" (vendor_id_hook = true) reproduces the same disconnect cycling as the systemized-only install — confirming both paths route through the same setSdpHook call.
Turning "act as Apple" off (module still LSPosed-enabled, hook not invoked) is stable, matching the fully-disabled case.
Secondary, separate issue: with "act as Apple"/vendor_id_hook enabled, a second distinct error appears independent of the disconnect cycling, surfacing in-app as a "couldn't connect to socket" toast:
BluetoothSocketManager: Error creating bluetooth socket with constructor 3
java.lang.NoSuchMethodException: Cannot find matching constructor
at org.lsposed.hiddenapibypass.HiddenApiBypass.newInstance
at com.android.bluetooth.bthelper.utils.BluetoothSocketManager.createBluetoothSocket
at com.android.bluetooth.bthelper.pods.PodsService$connectToA2dpProfile$1$onServiceConnected$1.invokeSuspend
This looks like a separate Android-17-specific hidden API signature mismatch in the reflection-based BluetoothSocket construction used for the AACP command channel, unrelated to the L2CAP hook itself.
Suggested fix: would it be possible to have the systemized/Magisk-module install path also respect the vendor_id_hook preference (or a build-time Android-version check) so the hook can be conditionally skipped on Android 17+, similar to how the LSPosed path already works? Right now, since the hook applies unconditionally in the systemized install, the only way to get a stable connection is to disable LibrePods (or its LSPosed scope) entirely — losing every feature, including all the ones that work perfectly without the hook, rather than just losing multipoint/VendorID-specific functionality as would be expected.
Logs
librepods_bug_report_logs.txt
Additional context
Filing this per the request in #487 to report success/failure with build numbers on the L2CAP fix. Also possibly related to #246 (similar disconnect-while-active symptom reported on AirPods Pro 2 with APatch/KernelSU).
App version
v1.0.0-rc1 (FOSS release)
App source
GitHub
Device
Motorola Edge 30 Fusion
Android / OS version
Android 17 (SDK 37), Evolution X (custom ROM)
Root / hook method
Other (describe in additional context)
AirPods model
AirPods Pro 3
AirPods firmware
9442210
What happened
Root: Folkpatch(Apatch fork) + Xposed
Everything LibrePods offers outside of the VendorID/"act as Apple" hook (multi-device connectivity, transparency mode customization, hearing aid setup) works correctly on this device via the systemized priv-app permissions alone — battery status, ear detection, controls, metadata, etc. all function with a fully stable connection.
The problem is isolated specifically to the hook: with it active (either unconditionally via the systemized install, or via "act as Apple" through LSPosed), AirPods connect successfully but then enter a rapid disconnect/reconnect cycle within seconds — multiple A2DP/HEADSET STATE_DISCONNECTED events fire within a 5-second window, repeating continuously. This happens regardless of an iPhone being nearby (tested with the iPhone's Bluetooth fully off, ruling out Apple's cross-device auto-switching as the cause).
With the hook disabled (LibrePods either fully disabled, or LSPosed-enabled with "act as Apple" off), the connection is fully stable — no drops after 10-15+ minutes of normal use, versus consistent disconnects within 2-3 minutes with the hook active.
Root cause, as far as I could trace it: per your own docs and issue tracker, the underlying Android Bluetooth stack L2CAP channel-mode bug that fake_l2c_fcr_chk_chan_modes works around (needed for multipoint/VendorID features) has been confirmed fixed in Android 17. On this device (genuinely running Android 17 / SDK 37), the hook still unconditionally forces l2c_fcr_chk_chan_modes to return 1/true, which appears to conflict with the platform's now-correct native negotiation rather than filling a gap — producing the disconnect cycling.
I decompiled the release APK to check for a way to disable just this hook:
KotlinModule.onPackageLoaded (the Xposed/LSPosed-loaded path) reads getRemotePreferences("me.kavishdevar.librepods").getBoolean("vendor_id_hook", false) and calls NativeBridge.setSdpHook(value) accordingly — so this path is gated by a preference.
However, when LibrePods is installed as a systemized priv-app without being separately enabled as an LSPosed module, the same native hook still fires (confirmed via LibrePodsHook: fake_l2c_fcr_chk_chan_modes called in logcat), independent of the vendor_id_hook preference (which wasn't even present in settings.xml at the time). The systemized/Magisk-module install path appears to apply the hook unconditionally, with no way to opt out short of disabling the whole module.
Enabling LibrePods as an LSPosed module and turning on "act as Apple" (vendor_id_hook = true) reproduces the same disconnect cycling as the systemized-only install — confirming both paths route through the same setSdpHook call.
Turning "act as Apple" off (module still LSPosed-enabled, hook not invoked) is stable, matching the fully-disabled case.
Secondary, separate issue: with "act as Apple"/vendor_id_hook enabled, a second distinct error appears independent of the disconnect cycling, surfacing in-app as a "couldn't connect to socket" toast:
BluetoothSocketManager: Error creating bluetooth socket with constructor 3
java.lang.NoSuchMethodException: Cannot find matching constructor
at org.lsposed.hiddenapibypass.HiddenApiBypass.newInstance
at com.android.bluetooth.bthelper.utils.BluetoothSocketManager.createBluetoothSocket
at com.android.bluetooth.bthelper.pods.PodsService$connectToA2dpProfile$1$onServiceConnected$1.invokeSuspend
This looks like a separate Android-17-specific hidden API signature mismatch in the reflection-based BluetoothSocket construction used for the AACP command channel, unrelated to the L2CAP hook itself.
Suggested fix: would it be possible to have the systemized/Magisk-module install path also respect the vendor_id_hook preference (or a build-time Android-version check) so the hook can be conditionally skipped on Android 17+, similar to how the LSPosed path already works? Right now, since the hook applies unconditionally in the systemized install, the only way to get a stable connection is to disable LibrePods (or its LSPosed scope) entirely — losing every feature, including all the ones that work perfectly without the hook, rather than just losing multipoint/VendorID-specific functionality as would be expected.
Logs
librepods_bug_report_logs.txt
Additional context
Filing this per the request in #487 to report success/failure with build numbers on the L2CAP fix. Also possibly related to #246 (similar disconnect-while-active symptom reported on AirPods Pro 2 with APatch/KernelSU).