Skip to content

Device: Fix AirPods Max 2 wear detection#572

Merged
d4rken merged 1 commit into
mainfrom
fix/issue-548-max2-wear-detection
May 1, 2026
Merged

Device: Fix AirPods Max 2 wear detection#572
d4rken merged 1 commit into
mainfrom
fix/issue-548-max2-wear-detection

Conversation

@d4rken

@d4rken d4rken commented May 1, 2026

Copy link
Copy Markdown
Member

What changed

Fixes wear detection on AirPods Max 2. The app used to show "in-ear" all the time — even when the headphones were sitting on a desk — so auto play/pause never triggered. Now the dashboard reflects whether the headphones are actually being worn, and auto play/pause works as expected when both earcups come off.

Technical Context

  • Root cause: Max 2 reused Max gen 1's BLE advertisement decoding, which reads bit 5 of the status byte. On A3454 bit 5 is always set while advertising; the actual ear-wear state is encoded in bits 1 and 3 (the per-earcup sensors). Reading bit 5 always returned true.
  • The two earcup bits are OR'd into a single boolean. AND-ing would match macOS UX (one earcup off ⇒ pause) but breaks Android: phones without the L2CAP/AAP-derived keys only see one of the two bits reliably (the reporter observed 0x23 for "both worn" and 0x21 for "neither" — bit 1 only). AND would falsely report "not worn" during normal use on those phones.
  • Side effect: removing only one earcup will not pause media — both earcups need to come off. This is a deliberate trade-off that fixes the reporter's primary complaint without breaking the Android-only path.
  • Scope: Max 2 (A3454) only. Max gen 1 (A2096) has different bit semantics with shipping tests; left unchanged. Max USB-C (A3184) only has a 0x2B sample where old and new logic both return worn; cannot determine its layout without an unworn sample, so left unchanged pending a follow-up.

Review checklist

  • Confirm dashboard In ear flag toggles between worn/unworn states on a real Max 2
  • Confirm auto play/pause triggers when both earcups come off
  • Confirm the value flowing through the dashboard is BLE-derived, not AAP-derived (debug overlay should show pubStatus toggling 0x21 ↔ 0x23)

Closes #548

Bit 5 of pubStatus is always set on A3454 and no longer carries the wear flag (unlike Max gen 1). Read bits 1 and 3 instead — the per-earcup sensors. OR rather than AND so phones that only see one bit reliably still report worn correctly.

Closes #548
@d4rken d4rken added bug Something isn't working device support coms/BLE Uses Apple's Proximity Payloads, based on BLE broadcasted advertisements. labels May 1, 2026
@d4rken d4rken merged commit 5a8c4b9 into main May 1, 2026
11 checks passed
@d4rken d4rken deleted the fix/issue-548-max2-wear-detection branch May 1, 2026 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working coms/BLE Uses Apple's Proximity Payloads, based on BLE broadcasted advertisements. device support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Airpods Max 2] Wear detection (non AAP connection) doesn't function, app thinks the headphones are being worn constantly

1 participant