Send the comma's Bluetooth address in the head unit pairing request

LeaseAwarePhone (used for every wireless session) had no adapter() method,
so Supervisor._adapter_address() hit AttributeError, swallowed it, and
returned "". The Bluetooth-service pairing request was therefore never sent
(bluetooth_opened always logged phone_address: "").

A 2020 myChevrolet (head unit 2.46.1.6) through an AAWireless Two+ then
accepted and acknowledged video but never showed it. A real phone sends the
pairing request about 1 s into the session; the car shows Android Auto once
its hands-free link to that address is up.

Pass adapter() through to the wrapped BluezPhone. It is a read-only property
lookup, so it needs no phone-role lease, like devices() and device().
_adapter_address() now logs adapter_address_unavailable instead of failing
silently.

Tested on the car (session-000052): phone_address sent, pairing response
received, picture displayed, touch input worked, 20-29 fps fully acked.

Co-authored-by: droobah <34214975+droobah@users.noreply.github.com>
This commit is contained in:
dirwin31
2026-11-01 13:26:31 -08:00
committed by Danny
parent 085aa2a173
commit 745b1e94de
3 changed files with 8 additions and 1 deletions
@@ -830,6 +830,7 @@ class LeaseAwarePhone:
def devices(self): return self.phone.devices()
def device(self, address): return self.phone.device(address)
def snapshot(self, address): return self.phone.snapshot(address)
def adapter(self): return self.phone.adapter() # this comma's address, for the head unit's pairing request
def acquire(self, phone_class: bool = True) -> None:
if self.lease is None:
@@ -1489,7 +1489,9 @@ class Supervisor:
"""This comma's Bluetooth address for the head unit's pairing request; empty when BlueZ is not up."""
try:
return str(self._bluez.adapter()[1].get("Address", "")).upper() if self._bluez is not None else ""
except Exception: # DBus errors vary; the pairing request is optional
except Exception as error: # DBus errors vary; the pairing request is optional
# Never silent: a missing adapter() once left every wireless session without the request (no address, no picture).
self.log("adapter_address_unavailable", kind=type(error).__name__, error=str(error)[:120])
return ""
def _project(self, result, lease, ident, connect=None, fragment_acks: bool = False) -> None:
@@ -261,8 +261,12 @@ def test_donor_phone_uses_same_lease_and_does_not_take_over_independently(tmp_pa
def devices(self):
return []
def adapter(self):
return '/org/bluez/hci0', {'Address': '39:90:21:64:07:00'}
phone = FakePhone()
wrapper = LeaseAwarePhone(shared, state['session'], lambda *a, **k: None, lambda log: phone)
assert wrapper.adapter()[1]['Address'] == '39:90:21:64:07:00' # read before any lease, for the pairing request
with pytest.raises(BluetoothAdmissionError, match='not active'):
wrapper.register_hfp()
wrapper.acquire_pairing()