Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79324061 authored by Arman Uguray's avatar Arman Uguray
Browse files

service: Add connection state tracking to Adapter

Added the IsDeviceConnected method to Adapter and also an
Observer method that other components can use to track the ACL
state between the local adapter and a remote device.

Bug: 25157450
Change-Id: If9bc25ab58b4a9b5430753405fb64834c0946050
parent 9d619255
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -42,6 +42,11 @@ void Adapter::Observer::OnAdapterStateChanged(Adapter* adapter,
  // Default implementation does nothing
}

void Adapter::Observer::OnDeviceConnectionStateChanged(
    Adapter* adapter, const std::string& device_address, bool connected) {
  // Default implementation does nothing
}

Adapter::Adapter()
    : state_(ADAPTER_STATE_OFF),
      address_(kDefaultAddress),
@@ -162,6 +167,11 @@ bool Adapter::IsMultiAdvertisementSupported() const {
  return local_le_features_.max_adv_instance >= kMinAdvInstancesForMultiAdv;
}

bool Adapter::IsDeviceConnected(const std::string& device_address) {
  std::lock_guard<std::mutex> lock(connected_devices_lock_);
  return connected_devices_.find(device_address) != connected_devices_.end();
}

LowEnergyClientFactory* Adapter::GetLowEnergyClientFactory() const {
  return ble_client_factory_.get();
}
@@ -244,6 +254,37 @@ void Adapter::AdapterPropertiesCallback(bt_status_t status,
  }
}

void Adapter::AclStateChangedCallback(bt_status_t status,
                                      const bt_bdaddr_t& remote_bdaddr,
                                      bt_acl_state_t state) {
  std::string device_address = BtAddrString(&remote_bdaddr);
  bool connected = (state == BT_ACL_STATE_CONNECTED);
  LOG(INFO) << "ACL state changed: " << device_address << " - connected: "
            << (connected ? "true" : "false");

  // If this is reported with an error status, I suppose the best thing we can
  // do is to log it and ignore the event.
  if (status != BT_STATUS_SUCCESS) {
    LOG(ERROR) << "AclStateChangedCallback called with status: "
               << BtStatusText(status);
    return;
  }

  // Introduce a scope to manage |connected_devices_lock_| with RAII.
  {
    std::lock_guard<std::mutex> lock(connected_devices_lock_);
    if (connected)
      connected_devices_.insert(device_address);
    else
      connected_devices_.erase(device_address);
  }

  std::lock_guard<std::mutex> lock(observers_lock_);
  FOR_EACH_OBSERVER(
      Observer, observers_,
      OnDeviceConnectionStateChanged(this, device_address, connected));
}

bool Adapter::SetAdapterProperty(bt_property_type_t type,
                                 void* value, int length) {
  CHECK(length > 0);
+25 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <atomic>
#include <mutex>
#include <string>
#include <unordered_set>

#include <base/macros.h>
#include <base/observer_list.h>
@@ -44,13 +45,25 @@ class Adapter : public hal::BluetoothInterface::Observer {
  // Observer interface allows other classes to receive notifications from us.
  // All of the methods in this interface are declared as optional to allow
  // different layers to process only those events that they are interested in.
  //
  // All methods take in an |adapter| argument which points to the Adapter
  // object that the Observer instance was added to.
  class Observer {
   public:
    virtual ~Observer() = default;

    // Called when there is a change in the state of the local Bluetooth
    // |adapter| from |prev_state| to |new_state|.
    virtual void OnAdapterStateChanged(Adapter* adapter,
                                       AdapterState prev_state,
                                       AdapterState new_state);

    // Called when there is a change in the connection state between the local
    // |adapter| and a remote device with address |device_address|. If the ACL
    // state changes from disconnected to connected, then |connected| will be
    // true and vice versa.
    virtual void OnDeviceConnectionStateChanged(
        Adapter* adapter, const std::string& device_address, bool connected);
  };

  Adapter();
@@ -91,6 +104,11 @@ class Adapter : public hal::BluetoothInterface::Observer {
  // multi-advertisement feature.
  bool IsMultiAdvertisementSupported() const;

  // Returns true if the remote device with address |device_address| is
  // currently connected. This is not a const method as it modifies the state of
  // the associated internal mutex.
  bool IsDeviceConnected(const std::string& device_address);

  // Returns a pointer to the LowEnergyClientFactory. This can be used to
  // register per-application LowEnergyClient instances to perform BLE GAP
  // operations.
@@ -110,6 +128,9 @@ class Adapter : public hal::BluetoothInterface::Observer {
  void AdapterPropertiesCallback(bt_status_t status,
                                 int num_properties,
                                 bt_property_t* properties) override;
  void AclStateChangedCallback(bt_status_t status,
                               const bt_bdaddr_t& remote_bdaddr,
                               bt_acl_state_t state) override;

  // Sends a request to set the given HAL adapter property type and value.
  bool SetAdapterProperty(bt_property_type_t type, void* value, int length);
@@ -137,6 +158,10 @@ class Adapter : public hal::BluetoothInterface::Observer {
  std::mutex observers_lock_;
  base::ObserverList<Observer> observers_;

  // List of devices addresses that are currently connected.
  std::mutex connected_devices_lock_;
  std::unordered_set<std::string> connected_devices_;

  // Factory used to create per-app LowEnergyClient instances.
  std::unique_ptr<LowEnergyClientFactory> ble_client_factory_;

+6 −4
Original line number Diff line number Diff line
@@ -53,10 +53,12 @@ base::ObserverList<BluetoothGattInterface::ServerObserver>*
                    *GetServerObservers(), func)

#define VERIFY_INTERFACE_OR_RETURN() \
  do { \
    if (!g_interface) { \
    LOG(WARNING) << "Callback received after |g_interface| is NULL"; \
      LOG(WARNING) << "Callback received while |g_interface| is NULL"; \
      return; \
  }
    } \
  } while (0)

void RegisterClientCallback(int status, int client_if, bt_uuid_t* app_uuid) {
  lock_guard<mutex> lock(g_instance_lock);
+34 −16
Original line number Diff line number Diff line
@@ -53,13 +53,17 @@ base::ObserverList<BluetoothInterface::Observer>* GetObservers();
#define FOR_EACH_BLUETOOTH_OBSERVER(func) \
  FOR_EACH_OBSERVER(BluetoothInterface::Observer, *GetObservers(), func)

#define VERIFY_INTERFACE_OR_RETURN() \
  do { \
    if (!g_bluetooth_interface) { \
      LOG(WARNING) << "Callback received while |g_interface| is NULL"; \
      return; \
    } \
  } while (0)

void AdapterStateChangedCallback(bt_state_t state) {
  lock_guard<mutex> lock(g_instance_lock);
  if (!g_bluetooth_interface) {
    LOG(WARNING) << "Callback received after global instance was destroyed";
    return;
  }

  VERIFY_INTERFACE_OR_RETURN();
  VLOG(1) << "Adapter state changed: " << BtStateText(state);
  FOR_EACH_BLUETOOTH_OBSERVER(AdapterStateChangedCallback(state));
}
@@ -68,11 +72,7 @@ void AdapterPropertiesCallback(bt_status_t status,
                               int num_properties,
                               bt_property_t* properties) {
  lock_guard<mutex> lock(g_instance_lock);
  if (!g_bluetooth_interface) {
    LOG(WARNING) << "Callback received after global instance was destroyed";
    return;
  }

  VERIFY_INTERFACE_OR_RETURN();
  VLOG(1) << "Adapter properties changed - status: " << BtStatusText(status)
          << ", num_properties: " << num_properties;
  FOR_EACH_BLUETOOTH_OBSERVER(
@@ -81,15 +81,26 @@ void AdapterPropertiesCallback(bt_status_t status,

void DiscoveryStateChangedCallback(bt_discovery_state_t state) {
  lock_guard<mutex> lock(g_instance_lock);
  if (!g_bluetooth_interface) {
    LOG(WARNING) << "Callback received after global instance was destroyed";
    return;
  }

  VERIFY_INTERFACE_OR_RETURN();
  VLOG(1) << "Discovery state changed - state: " << BtDiscoveryStateText(state);
  FOR_EACH_BLUETOOTH_OBSERVER(DiscoveryStateChangedCallback(state));
}

void AclStateChangedCallback(bt_status_t status,
                             bt_bdaddr_t *remote_bd_addr,
                             bt_acl_state_t state) {
  lock_guard<mutex> lock(g_instance_lock);
  VERIFY_INTERFACE_OR_RETURN();
  CHECK(remote_bd_addr);
  VLOG(1) << "Remote device ACL state changed - status: "
          << BtStatusText(status)
          << " - BD_ADDR: " << BtAddrString(remote_bd_addr)
          << " - state: "
          << ((state == BT_ACL_STATE_CONNECTED) ? "CONNECTED" : "DISCONNECTED");
  FOR_EACH_BLUETOOTH_OBSERVER(
      AclStateChangedCallback(status, *remote_bd_addr, state));
}

void ThreadEventCallback(bt_cb_thread_evt evt) {
  VLOG(1) << "ThreadEventCallback" << BtEventText(evt);

@@ -136,7 +147,7 @@ bt_callbacks_t bt_callbacks = {
  nullptr, /* pin_request_cb  */
  nullptr, /* ssp_request_cb  */
  nullptr, /* bond_state_changed_cb */
  nullptr, /* acl_state_changed_cb */
  AclStateChangedCallback,
  ThreadEventCallback,
  nullptr, /* dut_mode_recv_cb */
  nullptr, /* le_test_mode_cb */
@@ -275,6 +286,13 @@ void BluetoothInterface::Observer::DiscoveryStateChangedCallback(
  // Do nothing.
}

void BluetoothInterface::Observer::AclStateChangedCallback(
    bt_status_t /* status */,
    const bt_bdaddr_t& /* remote_bdaddr */,
    bt_acl_state_t /* state */) {
  // Do nothing.
}

// static
bool BluetoothInterface::Initialize() {
  lock_guard<mutex> lock(g_instance_lock);
+3 −0
Original line number Diff line number Diff line
@@ -54,6 +54,9 @@ class BluetoothInterface {
                                           int num_properties,
                                           bt_property_t* properties);
    virtual void DiscoveryStateChangedCallback(bt_discovery_state_t state);
    virtual void AclStateChangedCallback(bt_status_t status,
                                         const bt_bdaddr_t& remote_bdaddr,
                                         bt_acl_state_t state);

    // TODO(armansito): Complete the list of callbacks.
  };
Loading