[PR #453] fix(android): support non-rooted OnePlus 12 / OxygenOS 16 #405

Open
opened 2026-03-02 12:41:04 +03:00 by kerem · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/kavishdevar/librepods/pull/453
Author: @teng-lin
Created: 2/10/2026
Status: 🔄 Open

Base: mainHead: fix/android-oneplus12-oxygenos16


📝 Commits (10+)

  • fa02d4f chore: add .worktrees/ to .gitignore
  • 46d19c5 fix(android): support non-rooted OnePlus 12 / OxygenOS 16
  • aff8014 fix(android): show loading spinner when service is binding
  • 58b15fb fix(android): prevent concurrent L2CAP connectToSocket calls
  • b162ee5 fix(android): use single notification ID to avoid duplicate notifications
  • 8c287b5 fix(android): thread-safety, receiver leak, and reconnect issues
  • 7e52ae2 fix(android): make notification and phone permissions optional
  • dde12db fix(android): reclaim AACP control when audio source returns to phone
  • 725cfb7 fix(android): reconnect L2CAP when A2DP resumes playing
  • aadcaf1 fix(android): detect stale socket in connectToSocket guard

📊 Changes

7 files changed (+163 additions, -54 deletions)

View changed files

📝 .gitignore (+1 -0)
📝 README.md (+21 -0)
📝 android/app/src/main/java/me/kavishdevar/librepods/MainActivity.kt (+32 -15)
📝 android/app/src/main/java/me/kavishdevar/librepods/composables/NoiseControlSettings.kt (+16 -8)
📝 android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt (+75 -28)
📝 android/app/src/main/java/me/kavishdevar/librepods/utils/AACPManager.kt (+3 -3)
📝 android/app/src/main/java/me/kavishdevar/librepods/utils/RadareOffsetFinder.kt (+15 -0)

📄 Description

Summary

This PR enables LibrePods to work on non-rooted OnePlus 12 phones with OxygenOS 16, bringing full ANC, transparency, audio control, and other core features without requiring root or Xposed.

Changes

  • Thread safety fixes: Convert AACP collections to CopyOnWriteArrayList/ConcurrentHashMap to prevent ConcurrentModificationException
  • Receiver lifecycle management: Wrap BroadcastReceivers in DisposableEffect with proper unregistration
  • Service lifecycle cleanup: Remove duplicate unbindService call in onDestroy
  • Optional notification permission: Make POST_NOTIFICATIONS and READ_PHONE_STATE optional - don't block main screen
  • Audio source switching: Automatically reclaim AACP control when audio source returns to local device
  • L2CAP reconnection: Trigger L2CAP reconnect when A2DP resumes playing after device switch
  • Stale socket detection: Use AACP connectedDevices as reliable liveness indicator instead of inputStream.available()

Testing

  • ANC/transparency switching works
  • Audio source switching between Mac and phone maintains control
  • Battery monitoring functional
  • All customizations available
  • No battery drain or thermal issues
  • Clean logs without spurious errors

Compatibility

  • Non-rooted OxygenOS/ColorOS 16 (SDK 36): Full support
  • All other Android systems: Unchanged - still require root + Xposed/btl2capfix
  • Rooted devices: Cleaner logs, no functional regression

Device Tested

  • OnePlus 12 (OxygenOS 16, SDK 36, non-rooted)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Loading indicator shown while background service starts.
  • Bug Fixes / Improvements

    • More reliable Bluetooth connection, reconnection, and takeover flows with stronger guards to avoid duplicate operations.
    • Improved permission checks, receiver lifecycle handling and cleanup to reduce crashes/leaks.
    • Safer background service start/bind behavior, notification consistency, and battery/metadata short-circuiting.
    • Thread-safe collections used for command handling.
  • Documentation

    • Added non-root setup instructions for OxygenOS/ColorOS 16+ devices.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/kavishdevar/librepods/pull/453 **Author:** [@teng-lin](https://github.com/teng-lin) **Created:** 2/10/2026 **Status:** 🔄 Open **Base:** `main` ← **Head:** `fix/android-oneplus12-oxygenos16` --- ### 📝 Commits (10+) - [`fa02d4f`](https://github.com/kavishdevar/librepods/commit/fa02d4fd88ac99ae77dbb9b32b752d9b050ed2d5) chore: add .worktrees/ to .gitignore - [`46d19c5`](https://github.com/kavishdevar/librepods/commit/46d19c568cb974116ed9d561964f480ccd9772c0) fix(android): support non-rooted OnePlus 12 / OxygenOS 16 - [`aff8014`](https://github.com/kavishdevar/librepods/commit/aff8014a97d105779f92a34071263dc4f0435724) fix(android): show loading spinner when service is binding - [`58b15fb`](https://github.com/kavishdevar/librepods/commit/58b15fb551932c44df6ce10aa854c4b4c8da23ed) fix(android): prevent concurrent L2CAP connectToSocket calls - [`b162ee5`](https://github.com/kavishdevar/librepods/commit/b162ee5ff355040e61c2f2f9ebd7c7ef6625bf1e) fix(android): use single notification ID to avoid duplicate notifications - [`8c287b5`](https://github.com/kavishdevar/librepods/commit/8c287b58bc7b0d8911849dfa9fdf94d8a6d5e6b8) fix(android): thread-safety, receiver leak, and reconnect issues - [`7e52ae2`](https://github.com/kavishdevar/librepods/commit/7e52ae20aa7f91af4cb897bd75526c2494a1c6cb) fix(android): make notification and phone permissions optional - [`dde12db`](https://github.com/kavishdevar/librepods/commit/dde12db00b44a7b3ef70f8e174de31fb93b28bae) fix(android): reclaim AACP control when audio source returns to phone - [`725cfb7`](https://github.com/kavishdevar/librepods/commit/725cfb71ba736877657508cb533855ac8f6f5079) fix(android): reconnect L2CAP when A2DP resumes playing - [`aadcaf1`](https://github.com/kavishdevar/librepods/commit/aadcaf1c6e587b8f780f11643a10e52e488c5e2a) fix(android): detect stale socket in connectToSocket guard ### 📊 Changes **7 files changed** (+163 additions, -54 deletions) <details> <summary>View changed files</summary> 📝 `.gitignore` (+1 -0) 📝 `README.md` (+21 -0) 📝 `android/app/src/main/java/me/kavishdevar/librepods/MainActivity.kt` (+32 -15) 📝 `android/app/src/main/java/me/kavishdevar/librepods/composables/NoiseControlSettings.kt` (+16 -8) 📝 `android/app/src/main/java/me/kavishdevar/librepods/services/AirPodsService.kt` (+75 -28) 📝 `android/app/src/main/java/me/kavishdevar/librepods/utils/AACPManager.kt` (+3 -3) 📝 `android/app/src/main/java/me/kavishdevar/librepods/utils/RadareOffsetFinder.kt` (+15 -0) </details> ### 📄 Description ## Summary This PR enables LibrePods to work on non-rooted OnePlus 12 phones with OxygenOS 16, bringing full ANC, transparency, audio control, and other core features without requiring root or Xposed. ### Changes - **Thread safety fixes**: Convert AACP collections to CopyOnWriteArrayList/ConcurrentHashMap to prevent ConcurrentModificationException - **Receiver lifecycle management**: Wrap BroadcastReceivers in DisposableEffect with proper unregistration - **Service lifecycle cleanup**: Remove duplicate unbindService call in onDestroy - **Optional notification permission**: Make POST_NOTIFICATIONS and READ_PHONE_STATE optional - don't block main screen - **Audio source switching**: Automatically reclaim AACP control when audio source returns to local device - **L2CAP reconnection**: Trigger L2CAP reconnect when A2DP resumes playing after device switch - **Stale socket detection**: Use AACP connectedDevices as reliable liveness indicator instead of inputStream.available() ### Testing - ✅ ANC/transparency switching works - ✅ Audio source switching between Mac and phone maintains control - ✅ Battery monitoring functional - ✅ All customizations available - ✅ No battery drain or thermal issues - ✅ Clean logs without spurious errors ### Compatibility - Non-rooted OxygenOS/ColorOS 16 (SDK 36): **Full support** ✅ - All other Android systems: Unchanged - still require root + Xposed/btl2capfix - Rooted devices: Cleaner logs, no functional regression ### Device Tested - OnePlus 12 (OxygenOS 16, SDK 36, non-rooted) 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Loading indicator shown while background service starts. * **Bug Fixes / Improvements** * More reliable Bluetooth connection, reconnection, and takeover flows with stronger guards to avoid duplicate operations. * Improved permission checks, receiver lifecycle handling and cleanup to reduce crashes/leaks. * Safer background service start/bind behavior, notification consistency, and battery/metadata short-circuiting. * Thread-safe collections used for command handling. * **Documentation** * Added non-root setup instructions for OxygenOS/ColorOS 16+ devices. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/librepods#405
No description provided.