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

Commit 606d9edd authored by Chris Manton's avatar Chris Manton
Browse files

Properly lock and release ACL connection event callbacks

Also protect hci callbacks for disconnect/read remote version

Bug: 213537005
Tag: #refactor
Test: gd/cert/run
BYPASS_LONG_LINES_REASON: Bluetooth likes 120 lines

Change-Id: Ic2f96ba258c4b1e8b896069c5c4efb0c6fc2e2e9
parent d796637e
Loading
Loading
Loading
Loading
+7 −13
Original line number Diff line number Diff line
@@ -91,20 +91,14 @@ struct AclManager::impl {
      return;
    }
    uint16_t handle = packet->GetHandle();
    if (handle == kQualcommDebugHandle) {
    if (handle == kQualcommDebugHandle) return;
    if (classic_impl_->send_packet_upward(
            handle, [&packet](struct acl_manager::assembler* assembler) { assembler->on_incoming_packet(*packet); }))
      return;
    }
    auto connection_pair = classic_impl_->acl_connections_.find(handle);
    if (connection_pair != classic_impl_->acl_connections_.end()) {
      connection_pair->second.assembler_.on_incoming_packet(*packet);
    } else {
      auto le_connection_pair = le_impl_->le_acl_connections_.find(handle);
      if (le_connection_pair == le_impl_->le_acl_connections_.end()) {
        LOG_INFO("Dropping packet of size %zu to unknown connection 0x%0hx", packet->size(), handle);
    if (le_impl_->send_packet_upward(
            handle, [&packet](struct acl_manager::assembler* assembler) { assembler->on_incoming_packet(*packet); }))
      return;
      }
      le_connection_pair->second.assembler_.on_incoming_packet(*packet);
    }
    LOG_INFO("Dropping packet of size %zu to unknown connection 0x%0hx", packet->size(), packet->GetHandle());
  }

  void Dump(
+11 −9
Original line number Diff line number Diff line
@@ -327,16 +327,19 @@ struct ClassicAclConnection::impl {
      const Address& address,
      uint16_t connection_handle)
      : tracker(acl_connection_interface, address, connection_handle), queue_(std::move(queue)) {}
  ConnectionManagementCallbacks* GetEventCallbacks() {
    ASSERT(!callbacks_given_);
    callbacks_given_ = true;
  ConnectionManagementCallbacks* GetEventCallbacks(std::function<void(uint16_t)> invalidate_callbacks) {
    ASSERT_LOG(!invalidate_callbacks_, "Already returned event callbacks for this connection");
    invalidate_callbacks_ = std::move(invalidate_callbacks);
    return &tracker;
  }
  void PutEventCallbacks() {
    if (invalidate_callbacks_) invalidate_callbacks_(tracker.connection_handle_);
    invalidate_callbacks_ = {};
  }

  bool callbacks_given_{false};
  AclConnectionTracker tracker;
  std::shared_ptr<Queue> queue_;
  std::shared_ptr<std::atomic<bool>> is_callback_valid_;
  std::function<void(uint16_t)> invalidate_callbacks_;
};

ClassicAclConnection::ClassicAclConnection()
@@ -350,14 +353,13 @@ ClassicAclConnection::ClassicAclConnection(std::shared_ptr<Queue> queue,
}

ClassicAclConnection::~ClassicAclConnection() {
  if (pimpl_->is_callback_valid_) *pimpl_->is_callback_valid_ = false;
  pimpl_->PutEventCallbacks();
  delete pimpl_;
}

ConnectionManagementCallbacks* ClassicAclConnection::GetEventCallbacks(
    std::shared_ptr<std::atomic<bool>> is_callback_valid) {
  pimpl_->is_callback_valid_ = is_callback_valid;
  return pimpl_->GetEventCallbacks();
    std::function<void(uint16_t)> invalidate_callbacks) {
  return pimpl_->GetEventCallbacks(std::move(invalidate_callbacks));
}

void ClassicAclConnection::RegisterCallbacks(ConnectionManagementCallbacks* callbacks, os::Handler* handler) {
+1 −1
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ class ClassicAclConnection : public AclConnection {
  virtual bool ReadRemoteExtendedFeatures(uint8_t page_number);

  // Called once before passing the connection to the client
  virtual ConnectionManagementCallbacks* GetEventCallbacks(std::shared_ptr<std::atomic<bool>> is_callback_valid);
  virtual ConnectionManagementCallbacks* GetEventCallbacks(std::function<void(uint16_t)> invalidate_callbacks);

 private:
  AclConnectionInterface* acl_connection_interface_;
+290 −265

File changed.

Preview size limit exceeded, changes collapsed.

+10 −10
Original line number Diff line number Diff line
@@ -85,16 +85,17 @@ class LeAclConnectionTracker : public LeConnectionManagementCallbacks {
struct LeAclConnection::impl {
  impl(LeAclConnectionInterface* le_acl_connection_interface, std::shared_ptr<Queue> queue, uint16_t connection_handle)
      : queue_(std::move(queue)), tracker(le_acl_connection_interface, connection_handle) {}
  LeConnectionManagementCallbacks* GetEventCallbacks() {
    ASSERT(!callbacks_given_);
    callbacks_given_ = true;
  LeConnectionManagementCallbacks* GetEventCallbacks(std::function<void(uint16_t)> invalidate_callbacks) {
    ASSERT_LOG(!invalidate_callbacks_, "Already returned event callbacks for this connection");
    invalidate_callbacks_ = std::move(invalidate_callbacks);
    return &tracker;
  }

  bool callbacks_given_{false};
  void PutEventCallbacks() {
    if (invalidate_callbacks_) invalidate_callbacks_(tracker.connection_handle_);
  }
  std::shared_ptr<Queue> queue_;
  LeAclConnectionTracker tracker;
  std::shared_ptr<std::atomic<bool>> is_callback_valid_;
  std::function<void(uint16_t)> invalidate_callbacks_;
};

LeAclConnection::LeAclConnection()
@@ -116,7 +117,7 @@ LeAclConnection::LeAclConnection(
}

LeAclConnection::~LeAclConnection() {
  if (pimpl_->is_callback_valid_) *pimpl_->is_callback_valid_ = false;
  pimpl_->PutEventCallbacks();
  delete pimpl_;
}

@@ -140,9 +141,8 @@ void LeAclConnection::Disconnect(DisconnectReason reason) {
}

LeConnectionManagementCallbacks* LeAclConnection::GetEventCallbacks(
    std::shared_ptr<std::atomic<bool>> is_callback_valid) {
  pimpl_->is_callback_valid_ = is_callback_valid;
  return pimpl_->GetEventCallbacks();
    std::function<void(uint16_t)> invalidate_callbacks) {
  return pimpl_->GetEventCallbacks(std::move(invalidate_callbacks));
}

bool LeAclConnection::LeConnectionUpdate(uint16_t conn_interval_min, uint16_t conn_interval_max, uint16_t conn_latency,
Loading