Skip to content

rocknix: start the bluetooth agent with bluetoothd - #3230

Open
xiaodoudou wants to merge 1 commit into
ROCKNIX:nextfrom
xiaodoudou:bluetooth-agent-after-restart
Open

rocknix: start the bluetooth agent with bluetoothd#3230
xiaodoudou wants to merge 1 commit into
ROCKNIX:nextfrom
xiaodoudou:bluetooth-agent-after-restart

Conversation

@xiaodoudou

Copy link
Copy Markdown
Contributor

Summary

  • What is the goal of this PR?

Pair a bluetooth device, sleep the handheld, wake it up, then try to pair something else. Nothing happens. The device shows up in the list, you select it, and it just doesn't pair. No error anywhere. Reboot and it works again, until the next sleep.

The pairing agent is missing. bluetooth-agent.service has PartOf=bluetooth.service so it stops with bluetoothd, and WantedBy=bluetooth.service so it should come back with it. That WantedBy was never installed: the unit isn't passed to enable_service, so there's no bluetooth.service.wants symlink in the image and nothing pulls the agent back in. The only thing that starts it is rocknix-bluetooth enable, which runs once at boot from autostart.

sleep.sh has always stopped bluetooth in its pre hook and started it again in post, and nothing there changes here, so from the first resume onward bluetoothd is running with nothing behind it. The adapter still scans and lists devices, which is why it looks healthy, but pairing needs an agent to answer the confirmation request and there isn't one.

This took a while to pin down because restarting doesn't reproduce it. PartOf propagates restarts as well as stops, so systemctl restart bluetooth takes the agent down and brings it straight back. Only a discrete stop followed later by a start loses it, which is exactly what the sleep hooks do.

Testing

  • How was this tested?

Built for SM8550 and flashed to an AYN Odin 2.

You don't need to sleep the device to see it, since the hooks amount to a stop and a start:

systemctl stop bluetooth
systemctl start bluetooth
systemctl is-active bluetooth-agent
  • Test results:

That prints inactive before the change and active after.

On the flashed image, three suspend and resume cycles. The agent comes back one second after each resume with NRestarts=0, so it's the new dependency pulling it in rather than something that survived from boot. Paired a controller after a resume, which is the case that silently did nothing before.

One warning if you go poking: don't check this with systemctl is-enabled, it reports disabled either way. It only looks at the config paths, which is why save-sysconfig.service and rocknix-memory-manager.service say the same thing today. The symlink under /usr/lib/systemd/system/bluetooth.service.wants/ is what to look for.

Could someone confirm this on a platform that ships with real suspend? SM8550 is the only hardware I have, and it runs fake suspend on next, so I had to enable real suspend to see this at all (that is #3126, still open). I am going off the quirks for the rest: AMD64, RK3566, SM6115 and SM8750 all set suspendmode mem with no device gate, and sleep.sh is the same file everywhere, so they should all hit it. I have not run it on any of them.

The check is just: sleep the device with bluetooth on, wake it, then systemctl is-active bluetooth-agent. If that comes back inactive, this is a live bug for those users and the fix stands on its own. If it comes back active, then I have this wrong and the only thing affected is SM8550 once real suspend is turned on, in which case this belongs with that work rather than as a separate change.

Additional Context

The agent accepts pairing unconditionally: NoInputNoOutput, RequestConfirmation and RequestAuthorization both return without raising, and main.conf carries JustWorksRepairing=always. So it is now resident more of the time than it was. It never touches Discoverable or Pairable and only starts discovery from /run/bt_discovery_control, so I don't think this widens anything in practice, but you're better placed to judge that than I am.

The call goes in the rocknix package rather than alongside the existing enable_service calls in bluez, because rocknix is the package that ships the unit and its post_install is therefore guaranteed to find it in $INSTALL. From bluez it would depend on which of the two installs first.


AI Usage

Did you use AI tools to help write this code? PARTIALLY

bluetooth-agent.service declares PartOf=bluetooth.service so it follows
bluetoothd down, and WantedBy=bluetooth.service so it comes back up with
it. Only the first half is in effect: the unit is never passed to
enable_service, so the bluetooth.service.wants symlink is absent from
the image and nothing pulls the agent in.

PartOf also propagates restarts, so systemctl restart bluetooth keeps
the agent alive and hides this. What does not survive is a discrete stop
followed later by a start, which is exactly the shape of the suspend
path: sleep.sh stops bluetooth in its pre hook and starts it again in
post. From the first resume onward bluetoothd runs with no agent behind
it. Scanning still lists devices, so the adapter looks healthy, but
pairing from the UI goes nowhere because nothing answers the
confirmation request. rocknix-bluetooth enable, which starts both units
by name, only runs from autostart at boot, so the gap lasts until the
next reboot.

Reproducible without suspending:

  systemctl stop bluetooth
  systemctl start bluetooth
  systemctl is-active bluetooth-agent   # inactive

Enable the unit so the WantedBy symlink ships. Note that systemctl
is-enabled still reports disabled for units enabled this way, as it only
looks at the config paths; the symlink under
/usr/lib/systemd/system/bluetooth.service.wants is what matters.
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