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

Commit 10a6c6a1 authored by Hansong Zhang's avatar Hansong Zhang
Browse files

L2cap: Don't erase link when outgoing packet pending

Otherwise we will post to L2cap handler DataController::OnSdu with
deleted object.

Test: LE mouse
Bug: 179326888
Tag: #gd-refactor
Change-Id: I517ac9890cc8d3894067bcad346a80765d24aeca
parent d8717fce
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -452,6 +452,17 @@ void Link::AddEncryptionChangeListener(EncryptionChangeListener listener) {
  encryption_change_listener_.push_back(listener);
}

void Link::OnPendingPacketChange(Cid local_cid, bool has_packet) {
  if (has_packet) {
    remaining_packets_to_be_sent_++;
  } else {
    remaining_packets_to_be_sent_--;
  }
  if (link_manager_ != nullptr) {
    link_manager_->OnPendingPacketChange(GetDevice().GetAddress(), remaining_packets_to_be_sent_);
  }
}

}  // namespace internal
}  // namespace classic
}  // namespace l2cap
+4 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <atomic>
#include <memory>
#include <unordered_map>

@@ -199,6 +200,8 @@ class Link : public l2cap::internal::ILink, public hci::acl_manager::ConnectionM
    return role_;
  }

  void OnPendingPacketChange(Cid local_cid, bool has_packet) override;

 private:
  friend class DumpsysHelper;
  void connect_to_pending_dynamic_channels();
@@ -229,6 +232,7 @@ class Link : public l2cap::internal::ILink, public hci::acl_manager::ConnectionM
  bool used_by_security_module_ = false;
  bool has_requested_authentication_ = false;
  std::list<EncryptionChangeListener> encryption_change_listener_;
  std::atomic_int remaining_packets_to_be_sent_ = 0;
  DISALLOW_COPY_AND_ASSIGN(Link);
};

+16 −1
Original line number Diff line number Diff line
@@ -123,6 +123,17 @@ void LinkManager::RegisterLinkPropertyListener(os::Handler* handler, LinkPropert
  link_property_listener_ = listener;
}

void LinkManager::OnPendingPacketChange(hci::Address remote, int num_packets) {
  if (disconnected_links_.count(remote) != 0 && num_packets == 0) {
    links_.erase(remote);
    links_with_pending_packets_.erase(remote);
  } else if (num_packets != 0) {
    links_with_pending_packets_.emplace(remote);
  } else {
    links_with_pending_packets_.erase(remote);
  }
}

Link* LinkManager::GetLink(const hci::Address device) {
  if (links_.find(device) == links_.end()) {
    return nullptr;
@@ -314,8 +325,12 @@ void LinkManager::OnDisconnect(hci::Address device, hci::ErrorCode status) {
    link_property_callback_handler_->CallOn(link_property_listener_, &LinkPropertyListener::OnLinkDisconnected, device);
  }

  if (links_with_pending_packets_.count(device) != 0) {
    disconnected_links_.emplace(device);
  } else {
    links_.erase(device);
  }
}

void LinkManager::OnAuthenticationComplete(hci::ErrorCode hci_status, hci::Address device) {
  if (link_security_interface_listener_handler_ != nullptr) {
+6 −0
Original line number Diff line number Diff line
@@ -108,6 +108,10 @@ class LinkManager : public hci::acl_manager::ConnectionCallbacks {
  // Registerlink callbacks
  void RegisterLinkPropertyListener(os::Handler* handler, LinkPropertyListener* listener);

  // Reported by link to indicate how many pending packets are remaining to be set.
  // If there is anything outstanding, don't delete link
  void OnPendingPacketChange(hci::Address remote, int num_packets);

 private:
  // Handles requests from LinkSecurityInterface
  friend class LinkSecurityInterfaceImpl;
@@ -135,6 +139,8 @@ class LinkManager : public hci::acl_manager::ConnectionCallbacks {
  LinkSecurityInterfaceListener* link_security_interface_listener_ = nullptr;
  LinkPropertyListener* link_property_listener_ = nullptr;
  os::Handler* link_property_callback_handler_ = nullptr;
  std::unordered_set<hci::Address> disconnected_links_;
  std::unordered_set<hci::Address> links_with_pending_packets_;

  DISALLOW_COPY_AND_ASSIGN(LinkManager);
};
+4 −0
Original line number Diff line number Diff line
@@ -32,6 +32,10 @@ class ILink {
  virtual void SendDisconnectionRequest(Cid local_cid, Cid remote_cid) = 0;
  virtual hci::AddressWithType GetDevice() const = 0;

  // Used by sender to indicate whether there is any pending packet to be sent.
  // If there is pending packet, don't delete the link.
  virtual void OnPendingPacketChange(Cid local_cid, bool has_packet) {}

  // To be used by LE credit based channel data controller over LE link
  virtual void SendLeCredit(Cid local_cid, uint16_t credit) {}

Loading