[bluetooth] Recover BlueZ devices after object removal (#20903)

* [bluetooth] Recover BlueZ devices after object removal

Reset cached adapter and device state when BlueZ removes their DBus objects, and populate GATT services before notifying listeners. This allows always-connected devices to reconnect after device removal or adapter unplug/replug.

Signed-off-by: Vlad Kolotoff <vkolotoff@pm.me>
This commit is contained in:
Vlad Kolotov
2026-06-08 17:47:32 +02:00
committed by GitHub
parent f09e4a114f
commit 6839c31fcd
7 changed files with 240 additions and 1 deletions
@@ -20,6 +20,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
@@ -133,6 +134,20 @@ public abstract class AbstractBluetoothBridgeHandler<BD extends BaseBluetoothDev
discoveryListeners.forEach(listener -> listener.deviceRemoved(device));
}
/**
* Performs the given action on every device currently known to this bridge. Subclasses use this
* to propagate adapter-wide events (e.g. the adapter going away) to all of their devices without
* needing their own copy of the device registry. The action runs while holding the device lock,
* so it should be quick and must not call back into device-registry-mutating methods.
*
* @param action the action to perform on each known device
*/
protected void forEachDevice(Consumer<BD> action) {
synchronized (devices) {
devices.values().forEach(action);
}
}
private boolean shouldRemove(BD device) {
// we can't remove devices with listeners since that means they have a handler.
if (device.hasListeners()) {