Skip to content

Device: Fix battery card flickering near other people's AirPods#616

Merged
d4rken merged 3 commits into
mainfrom
worktree-symptom-b-history-collision
Jun 15, 2026
Merged

Device: Fix battery card flickering near other people's AirPods#616
d4rken merged 3 commits into
mainfrom
worktree-symptom-b-history-collision

Conversation

@d4rken

@d4rken d4rken commented Jun 14, 2026

Copy link
Copy Markdown
Member

What changed

Fixed the battery/status card flickering — signal bars, in-ear and "worn" state briefly dropping
out — that could happen in busy places (a gym, a train) where other people nearby have the same
model
of AirPods. Your own AirPods stay rock-solid on the card now.

Technical Context

  • Root cause: identity tracking has two independent steps per BLE advertisement — the IRK-based
    binding to your profile, and a separate "stable id" recovery that survives address rotation. The
    stable-id recovery has weak fallbacks (case-ignored markings, fuzzy markers) that match on
    low-entropy broadcast data only — model + battery nibbles + colour. A stranger's same-model
    AirPods at a similar battery level satisfies those fallbacks, so its frame (which fails your IRK,
    so it carries no profile) was recovered as your device's id. It then overwrote your device's BLE
    cache slot, and the merged device flapped to cached-only (ble = null) until your next real frame
    re-bound — the visible flicker. Confirmed deterministically by the new test (a foreign frame
    adopting the keyed device's exact identity).
  • Fix: the two weak recovery paths now refuse to hand an IRK-backed (keyed) device's identity to
    a frame that didn't resolve to the same profile. The strong address/IRK recovery paths are
    untouched, so your device's identity still survives RPA rotation.
  • Keyless profiles (users who can't obtain IRK/ENC keys and rely on fuzzy matching) are deliberately
    left exactly as before — their devices were never IRK-backed, so the gate is a no-op for them.
    This does not fix the same flicker for keyless setups; without a key there's no strong identity
    to disambiguate two same-model devices, which is inherent.
  • The "is this device keyed" signal is latched durably on the known-device record (not re-derived
    from the trimmed history window), so it can't erode over a long session.
  • Also stabilizes a flaky AAP handshake-timeout test inherited from the previous change (it asserted
    an exact socket-close count that races between two cleanup paths, and used a tight latch timeout) —
    it was failing intermittently on loaded CI runners, unrelated to this fix.

Review checklist

  • Gate applies only to the weak paths (fuzzy baseSearch, case-ignored search); strong
    address/IRK recovery unchanged
  • boundProfileId is latched on any IRK-matched frame and never cleared by a later unbound frame
  • Keyless devices (boundProfileId == null) keep identical fuzzy-matching behaviour
  • A rejected foreign frame mints its own id (no unbounded knownDevices growth beyond the 30s prune)

@d4rken d4rken added bug Something isn't working coms/BLE Uses Apple's Proximity Payloads, based on BLE broadcasted advertisements. labels Jun 14, 2026
@d4rken d4rken merged commit 352e020 into main Jun 15, 2026
11 checks passed
@d4rken d4rken deleted the worktree-symptom-b-history-collision branch June 15, 2026 07:16
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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant