Skip to content

bluetooth: recover adapter power state from missed transitions - #1156

Open
neheb wants to merge 1 commit into
quickshell-mirror:masterfrom
neheb:fix/bluetooth-power-state-recovery
Open

neheb wants to merge 1 commit into
quickshell-mirror:masterfrom
neheb:fix/bluetooth-power-state-recovery

Conversation

@neheb

@neheb neheb commented Sep 17, 2026

Copy link
Copy Markdown

Summary

BluetoothAdapter.enabled / state can get permanently stuck on a transitional power state
(Enabling / Disabling) even though the adapter is actually powered and in use.

BlueZ can report an adapter as off-enabling / on-disabling without ever emitting the
PropertiesChanged that completes the transition, for example when a controller is
re-registered while it is still coming up (in the reproduction: a dev-id change from hci1
to hci0). Quickshell applies the transitional Powered=false snapshot and, with no follow-up
change ever arriving, keeps reporting the adapter as "off" forever.

Reproduced live on the omarchy shell (see omacom/omarchy#9561 for
the same bug reported from the shell side):

  • adapter hci0 was tracked with PowerState=Enabling / Powered=false during
    re-registration, and Powered=true was never applied afterwards;
  • yet bluetoothctl show reports the controller Powered: yes / PowerState: on, and a
    connected AirPods Pro is the default PipeWire sink and streaming audio.

Fix

When the adapter is observed in a transitional power state, re-read its properties via GetAll
until it settles on a terminal state (Enabled / Disabled / Blocked) or before that a
follow-up properties change arrives. Polling is bounded to 40 attempts at a 250 ms interval
(10 s ceiling) so it always terminates.

These are reads only (no Set), so the fix cannot interfere with setEnabled or other clients
toggling the adapter.

@neheb
neheb force-pushed the fix/bluetooth-power-state-recovery branch 2 times, most recently from 5f51cc7 to e7156ac Compare September 17, 2026 22:52
BlueZ can leave an adapter in a transitional power state without ever emitting the PropertiesChanged that completes the transition, if the adapter is registered (e.g. re-registered after a controller swap) while it is still powering on or off. The adapter's enabled/state would then be stuck mid-transition forever, even though the device is connected and in use.

Re-read the adapter power state after it is observed in a transitional state and keep polling (at most 40 attempts / 10 seconds, paced by a single-shot QTimer that is stopped on any terminal state change) until it settles on a terminal state or the timer is cancelled.
@neheb
neheb force-pushed the fix/bluetooth-power-state-recovery branch from e7156ac to ff24918 Compare September 17, 2026 22:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant