Reaction: Fix case popup flickering when one AirPod is out of the case#606
Merged
Conversation
When one pod is out of the case, the out-of-case pod broadcasts bit4-only frames whose lid byte is stale and decodes to a phantom OPEN even while the case is shut, interleaved ~1:1 with the correct in-case-pod (bit6) frames. The derived lid state flapped OPEN<->CLOSED, so the case-open popup re-popped ~0.5s after closing and sometimes lingered. Verified on AirPods Pro 1 (issue log) and Pro 3 (live BLE capture). - Trust the lid bit only from in-case-pod (bit6) or both-in-case (bit2) frames; bit4-only frames now decode to UNKNOWN, and the real state is recovered from a recent in-case broadcast (matches LibrePods). - getLatestCaseLidState recovers from history within a 2s age window instead of a fixed frame count, so a missed CLOSED can't keep a stale OPEN. - Don't refresh the show-cooldown on a non-CLOSED hide, so a transient UNKNOWN can't suppress a genuine re-open. - Add a freshness backstop: dismiss the popup if a fresh OPEN broadcast stops arriving (device left BLE range while open). - Key popup/auto-connect de-duplication on the derived lid state, not just raw advertisement bytes, since the effective lid can change while bytes don't. Closes #598
6771969 to
b4c8031
Compare
@mvanhorn independently fixed #598 in #605 by no longer resetting the case cooldown on close, throttling the re-pop. We cherry-picked that commit above to keep his authorship/credit, but this PR instead removes the underlying lid-state flapping at its source (out-of-case pod's stale lid byte -> UNKNOWN), so the cooldown can keep resetting on close and a genuine close->reopen still shows the popup. Reverting his change here so the two approaches don't stack; thanks @mvanhorn for the parallel work.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Fixes the case‑open popup misbehaving when you're wearing one AirPod and the other is in the case. In that situation the popup would flicker — re‑appearing about half a second after you closed the lid — and sometimes stay on screen until you dismissed it by hand. It now shows once when you open the case and dismisses reliably when you close it (or when the AirPods go out of range while open).
Closes #598
Technical Context
bit4‑only (status bit6=0), the in‑case frame isbit6=1.bit4‑only "one pod in case, this pod out" frame decodes toUNKNOWN, and the real state is recovered from a recent in‑case broadcast. This matches LibrePods' decoder, which gates onisThisPodInTheCase.ble.seenLastAt), not overall device freshness, so a live AAP socket can't keep a stale lid on screen.BlePodMonitor's snapshot selection can still pick abit4‑only frame as the visible snapshot. The derived lid state is correct regardless, so this is now cosmetic (it can briefly surface that frame's battery/RSSI). The popup overlay is shared with the connection popup, so a stale‑close can dismiss a visible connection popup when both toggles are enabled — this is pre‑existing overlay behavior, not new here.Review checklist
bit4‑only (one‑pod‑out) frames →UNKNOWN;bit6/bit2frames unchanged (DualApplePodsTest)getLatestCaseLidStaterecovers CLOSED from in‑case history for a phantom current frame and never surfaces a phantom OPENdevice.ble?.seenLastAt(BLE), not AAP/cacheAutoConnectCASE_OPEN or the overview lid display now thatUNKNOWNcan be returnedcaseLidState(popup + auto‑connect) so derived‑lid transitions aren't swallowed