A page under Settings → debug data that shows what actually happened between the phone and a tag when it was rung, so anyone with a tag can report what the accessory answered without a rooted phone or a Mac trace.
#193 needed an iPhone HCI trace, a sysdiagnose and a rooted second phone to find out what an accessory did with a write. Most of that is already visible to the app, and it throws it away.
What the app already has
FindMyAdvertisement tells the separated beacon from the owner-nearby short form, and keeps the raw status byte. Per the DULT draft, that state decides whether a non-owner Sound_Start is accepted at all.
BleGattSoundTrigger enables indications on the control point before writing, but has no onCharacteristicChanged, so the accessory's Command_Response is never read. SUCCESS means the write was acknowledged at the ATT level, not that the accessory accepted the command. An accessory answering Invalid_command reports as a successful ring.
Proposal
Behind the existing enableDebugData setting, like the debug fields on DeviceInfoActivity, show for the last few ring attempts per tag:
- when it was attempted, and the advertisement state (separated or owner-nearby) with the raw status byte from the last sighting
- the services and characteristics found, and which protocol was chosen (DULT, Find My, AirTag)
- each write: characteristic, bytes, ATT status
- each indication received: characteristic, raw bytes, and the decoded opcode and status where known (Command_Response is
0x0302 in DULT)
- how the connection ended
Plus a copy button, so the result can be pasted into an issue as text.
Independently of the debug page
Read the Command_Response in BleGattSoundTrigger, and stop reporting a refused command as success. When the accessory refuses because it is near its owner, the ring screen can say so: "this tag is with its owner's Apple device and can only be rung from there" is more useful than a success that plays nothing.
What it would answer
The open question in #201: does a third-party accessory accept 01 00 03 on 4F860003 once it is separated, and answer Invalid_command while its owner is nearby? With this page, that is one tag, one walk out of range, and a paste.
Decoding belongs in a JVM test (rule 13), and the page gets an inflate test (rule 12). See docs/owner-connected-tags.md for the protocol background.
Drafted by Claude Code
A page under Settings → debug data that shows what actually happened between the phone and a tag when it was rung, so anyone with a tag can report what the accessory answered without a rooted phone or a Mac trace.
#193 needed an iPhone HCI trace, a
sysdiagnoseand a rooted second phone to find out what an accessory did with a write. Most of that is already visible to the app, and it throws it away.What the app already has
FindMyAdvertisementtells the separated beacon from the owner-nearby short form, and keeps the raw status byte. Per the DULT draft, that state decides whether a non-owner Sound_Start is accepted at all.BleGattSoundTriggerenables indications on the control point before writing, but has noonCharacteristicChanged, so the accessory's Command_Response is never read.SUCCESSmeans the write was acknowledged at the ATT level, not that the accessory accepted the command. An accessory answering Invalid_command reports as a successful ring.Proposal
Behind the existing
enableDebugDatasetting, like the debug fields onDeviceInfoActivity, show for the last few ring attempts per tag:0x0302in DULT)Plus a copy button, so the result can be pasted into an issue as text.
Independently of the debug page
Read the Command_Response in
BleGattSoundTrigger, and stop reporting a refused command as success. When the accessory refuses because it is near its owner, the ring screen can say so: "this tag is with its owner's Apple device and can only be rung from there" is more useful than a success that plays nothing.What it would answer
The open question in #201: does a third-party accessory accept
01 00 03on4F860003once it is separated, and answer Invalid_command while its owner is nearby? With this page, that is one tag, one walk out of range, and a paste.Decoding belongs in a JVM test (rule 13), and the page gets an inflate test (rule 12). See
docs/owner-connected-tags.mdfor the protocol background.