Repository navigation
ble: record why the stale-pairing clear stays Android-only - #1791
Merged
Merged
Conversation
#1790 said "Android-only and permanently so: CoreBluetooth exposes no bond-removal API." That is true and it is not the whole blocker, and stating it that way invites the next reader to go looking for a way round. The real obstacle is IDENTITY. macOS DOES have a removal call, in IOBluetooth - a separate classic-Bluetooth framework - but it addresses devices by MAC, and CoreBluetooth never exposes one. A peripheral's identity there is CBPeripheral.identifier, a per-app UUID that deliberately is not the hardware address. The only bridge left is matching IOBluetoothDevice.pairedDevices() by NAME, and deleting a pairing on a name match removes the wrong device the moment a user has two straps or has renamed one. That is the exact mistake shouldRemoveStaleBond's guards exist to prevent, so closing the gap that way would be worse than leaving it open. iOS has no route at all. Worth writing down because Apple is not unaware of the condition: didFailToConnect already handles CBError.peerRemovedPairingInformation and publishes the same forget-and-re-pair guide, naming the strap. Both platforms detect it, both give the same advice, and only one can take the step itself. A future audit finding this one-sided should read a decision rather than an oversight. Notes only, on both sides, cross-referencing each other. 638 BLE tests green.
Re-review of my own correction. The note said macOS "does have" a bond-removal call in IOBluetooth. I cannot verify that from this repository, and asserting an Apple SDK capability on recollection is the same move the note exists to correct - inside the correction. It is also unnecessary. The identity blocker makes the API question moot: even if IOBluetooth's removal works on a BLE pairing, it addresses devices by MAC and Apple's side never has one, so the question never arises. That argument is fully checkable from inside the repo, and it is the stronger one. It also had a citation already: BLEManager.epitaphLine's own doc says the peripheral UUID is "per-install, not the hardware address". noop established this before I did; the note now points at it rather than re-deriving it. Grepped BLEManager unfiltered to be sure nothing MAC-shaped had slipped past the earlier filtered search - the only two hits are that doc line and my own comment. The closing line loses "if a future macOS SDK exposes the hardware address" for the same reason, and now turns on CoreBluetooth, which is the framework whose behaviour actually governs this. 638 BLE tests green; doc lint and swiftc -parse clean.
Third pass. Having removed "macOS does have a removal call" as an SDK claim I cannot check from here, I had left "iOS has no route at all ... reserved to the user, by design" standing two lines above it. That is the same kind of assertion, and the second half is worse: it is a claim about Apple's INTENT, not just its API. The note does not need either. The identity blocker covers iOS too - no MAC, so nothing to address - and the app's own guide already tells the user to do it in Settings, which is the observable fact rather than a story about why. A note whose subject is "do not assert what you cannot check" should read that way throughout, including the parts that happen to be conventional wisdom. 638 BLE tests green; doc lint and swiftc -parse clean.
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.
You asked for a mirror of #1790. A mirror is not safely buildable, and this PR records why rather than faking one — with a correction to a claim I made in #1790's merge body.
What I got wrong
#1790 said "Android-only and permanently so: CoreBluetooth exposes no bond-removal API." That is true, and it is not the whole blocker. Stated that way it reads as settled, and it invites the next reader to go hunting for a way round.
The real obstacle is identity, not API
macOS does have a removal call —
IOBluetooth, a separate classic-Bluetooth framework. It addresses devices by MAC, and CoreBluetooth never exposes one: a peripheral's identity there isCBPeripheral.identifier, a per-app UUID that is deliberately not the hardware address. I checked, and nothing inBLEManagerever holds a MAC.That leaves exactly one bridge: enumerate
IOBluetoothDevice.pairedDevices()and match by name. Deleting a pairing on a name match removes the wrong device the moment a user has two straps or has renamed one — which is precisely the mistakeshouldRemoveStaleBond's guards exist to prevent. Closing the gap that way would be worse than leaving it open.iOS has no route at all. Forgetting a pairing is a Settings → Bluetooth action reserved to the user by design.
Why this is worth writing down
Apple is not unaware of the condition.
didFailToConnectalready handlesCBError.peerRemovedPairingInformationand publishes the same forget-and-re-pair guide, naming the strap:So both platforms detect it, both give the same advice, and only Android can take the step. A future parity audit finding this one-sided should read a decision, not an oversight — the same treatment
ExplicitBondandBondStateTracealready get.Notes only, one on each side, cross-referencing each other. 638 BLE tests green, doc lint clean,
swiftc -parseclean.One divergence I did NOT change
Apple's stale-bond branch sets the guide and
returns — it schedules nothing. Android's schedules a reconnect and keeps trying, which is how its failure counter climbs to five at all.That means on Apple, a user who clears the pairing in System Settings while the app is open is not picked up until they reconnect by hand. It may well be deliberate — not hammering a strap whose bond is known-stale is defensible — and the comment above it cites #1413's standing-connect handoff for the other failure paths specifically. I am not changing Apple's reconnect behaviour on my reading of it; flagging it for yours.
Re-review: I made the same mistake inside the correction
The first version of these notes said macOS "does have" a bond-removal call in
IOBluetooth. I cannot verify that from this repository. Asserting an Apple SDK capability from recollection is precisely the move this PR exists to correct — and I did it in the correction.It was also unnecessary. The identity blocker makes the API question moot: even if
IOBluetooth's removal works on a BLE pairing, it addresses devices by MAC and Apple's side never has one, so the question never arises. That argument is fully checkable from inside the repo, and it is the stronger one.The note also had a citation available that I had not used.
BLEManager.epitaphLine's own doc already says the peripheral UUID is "per-install, not the hardware address" — noop established this before I did, so the note now points at it rather than re-deriving it. I re-greppedBLEManagerunfiltered to be sure nothing MAC-shaped had slipped past my earlier filtered search; the only two hits are that doc line and my own comment.The closing line lost "if a future macOS SDK exposes the hardware address" for the same reason, and now turns on CoreBluetooth — the framework whose behaviour actually governs this.