OSDN Git Service

gd shim layer changes
authorChris Manton <cmanton@google.com>
Fri, 8 Nov 2019 23:19:33 +0000 (15:19 -0800)
committerChris Manton <cmanton@google.com>
Sun, 10 Nov 2019 16:48:15 +0000 (08:48 -0800)
Bug: 144171652
Test: bluetooth_test_gd

Change-Id: If56602e1a90d692435b4366b98c959cc4a13e09f

gd/shim/il2cap.h
gd/shim/l2cap.cc
gd/shim/l2cap.h
main/shim/test_stack.cc
main/shim/test_stack.h

index 363c28f..c4e7463 100644 (file)
@@ -34,7 +34,10 @@ using ReadDataReadyCallback = std::function<void(uint16_t cid, std::vector<const
 
 struct IL2cap {
   virtual void RegisterService(uint16_t psm, ConnectionOpenCallback on_open, std::promise<void> completed) = 0;
+  virtual void UnregisterService(uint16_t psm) = 0;
+
   virtual void CreateConnection(uint16_t psm, const std::string address, std::promise<uint16_t> completed) = 0;
+  virtual void CloseConnection(uint16_t cid) = 0;
 
   virtual void SetReadDataReadyCallback(uint16_t cid, ReadDataReadyCallback on_data_ready) = 0;
   virtual void SetConnectionClosedCallback(uint16_t cid, ConnectionClosedCallback on_closed) = 0;
index 9db5f4a..58b10b5 100644 (file)
@@ -19,6 +19,7 @@
 #include <functional>
 #include <future>
 #include <memory>
+#include <mutex>
 #include <queue>
 #include <unordered_map>
 #include <vector>
@@ -47,6 +48,11 @@ static const ConnectionInterfaceDescriptor kInvalidConnectionInterfaceDescriptor
 static const ConnectionInterfaceDescriptor kStartConnectionInterfaceDescriptor = 64;
 static const ConnectionInterfaceDescriptor kMaxConnections = UINT16_MAX - kStartConnectionInterfaceDescriptor - 1;
 
+using ServiceInterfaceCallback =
+    std::function<void(l2cap::Psm psm, l2cap::classic::DynamicChannelManager::RegistrationResult result)>;
+using ConnectionInterfaceCallback =
+    std::function<void(l2cap::Psm psm, std::unique_ptr<l2cap::classic::DynamicChannel>)>;
+
 std::unique_ptr<packet::RawBuilder> MakeUniquePacket(const uint8_t* data, size_t len) {
   packet::RawBuilder builder;
   std::vector<uint8_t> bytes(data, data + len);
@@ -60,7 +66,7 @@ class ConnectionInterface {
   ConnectionInterface(ConnectionInterfaceDescriptor cid, std::unique_ptr<l2cap::classic::DynamicChannel> channel,
                       os::Handler* handler)
       : cid_(cid), channel_(std::move(channel)), handler_(handler), on_data_ready_callback_(nullptr),
-        on_connection_closed_callback_(nullptr) {
+        on_connection_closed_callback_(nullptr), address_(channel_->GetDevice()) {
     channel_->RegisterOnCloseCallback(
         handler_, common::BindOnce(&ConnectionInterface::OnConnectionClosed, common::Unretained(this)));
     channel_->GetQueueUpEnd()->RegisterDequeue(
@@ -69,10 +75,7 @@ class ConnectionInterface {
   }
 
   ~ConnectionInterface() {
-    if (dequeue_registered_) {
-      channel_->GetQueueUpEnd()->UnregisterDequeue();
-      dequeue_registered_ = false;
-    }
+    ASSERT(!dequeue_registered_);
   }
 
   void OnReadReady() {
@@ -86,11 +89,10 @@ class ConnectionInterface {
     on_data_ready_callback_(cid_, data);
   }
 
-  void OnConnectionClosed(hci::ErrorCode error_code) {
-    LOG_DEBUG("Channel interface closed reason:%s cid:%hd device:%s", hci::ErrorCodeText(error_code).c_str(), cid_,
-              channel_->GetDevice().ToString().c_str());
-    ASSERT(on_connection_closed_callback_ != nullptr);
-    on_connection_closed_callback_(cid_, static_cast<int>(error_code));
+  void SetReadDataReadyCallback(ReadDataReadyCallback on_data_ready) {
+    ASSERT(on_data_ready != nullptr);
+    ASSERT(on_data_ready_callback_ == nullptr);
+    on_data_ready_callback_ = on_data_ready;
   }
 
   std::unique_ptr<packet::BasePacketBuilder> WriteReady() {
@@ -103,17 +105,8 @@ class ConnectionInterface {
     return data;
   }
 
-  void SetReadDataReadyCallback(ReadDataReadyCallback on_data_ready) {
-    ASSERT(on_data_ready_callback_ == nullptr);
-    on_data_ready_callback_ = on_data_ready;
-  }
-
-  void SetConnectionClosedCallback(::bluetooth::shim::ConnectionClosedCallback on_connection_closed) {
-    ASSERT(on_connection_closed_callback_ == nullptr);
-    on_connection_closed_callback_ = on_connection_closed;
-  }
-
   void Write(std::unique_ptr<packet::RawBuilder> packet) {
+    LOG_DEBUG("Writing packet cid:%hd size:%zd", cid_, packet->size());
     write_queue_.push(std::move(packet));
     if (!enqueue_registered_) {
       enqueue_registered_ = true;
@@ -123,18 +116,36 @@ class ConnectionInterface {
   }
 
   void Close() {
+    if (dequeue_registered_) {
+      channel_->GetQueueUpEnd()->UnregisterDequeue();
+      dequeue_registered_ = false;
+    }
     ASSERT(write_queue_.empty());
-    channel_->GetQueueUpEnd()->UnregisterDequeue();
     channel_->Close();
   }
 
+  void OnConnectionClosed(hci::ErrorCode error_code) {
+    LOG_DEBUG("Channel interface closed reason:%s cid:%hd device:%s", hci::ErrorCodeText(error_code).c_str(), cid_,
+              address_.ToString().c_str());
+    ASSERT(on_connection_closed_callback_ != nullptr);
+    on_connection_closed_callback_(cid_, static_cast<int>(error_code));
+  }
+
+  void SetConnectionClosedCallback(::bluetooth::shim::ConnectionClosedCallback on_connection_closed) {
+    ASSERT(on_connection_closed != nullptr);
+    ASSERT(on_connection_closed_callback_ == nullptr);
+    on_connection_closed_callback_ = std::move(on_connection_closed);
+  }
+
  private:
-  ConnectionInterfaceDescriptor cid_;
-  std::unique_ptr<l2cap::classic::DynamicChannel> channel_;
+  const ConnectionInterfaceDescriptor cid_;
+  const std::unique_ptr<l2cap::classic::DynamicChannel> channel_;
   os::Handler* handler_;
 
   ReadDataReadyCallback on_data_ready_callback_;
-  ::bluetooth::shim::ConnectionClosedCallback on_connection_closed_callback_;
+  ConnectionClosedCallback on_connection_closed_callback_;
+
+  const hci::Address address_;
 
   std::queue<std::unique_ptr<packet::PacketBuilder<hci::kLittleEndian>>> write_queue_;
 
@@ -152,7 +163,6 @@ struct ConnectionInterfaceManager {
 
   bool Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet);
 
-  bool HasResources() const;
   void SetHandler(os::Handler* handler) {
     handler_ = handler;
   }
@@ -168,38 +178,50 @@ struct ConnectionInterfaceManager {
   ConnectionInterfaceDescriptor current_connection_interface_descriptor_;
   os::Handler* handler_;
 
+  bool HasResources() const;
   bool Exists(ConnectionInterfaceDescriptor id) const;
+  ConnectionInterfaceDescriptor AllocateConnectionInterfaceDescriptor();
 };
 
 ConnectionInterfaceManager::ConnectionInterfaceManager()
     : current_connection_interface_descriptor_(kStartConnectionInterfaceDescriptor) {}
 
-ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(
-    std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
+bool ConnectionInterfaceManager::Exists(ConnectionInterfaceDescriptor cid) const {
+  return cid_to_interface_map_.find(cid) != cid_to_interface_map_.end();
+}
+
+ConnectionInterfaceDescriptor ConnectionInterfaceManager::AllocateConnectionInterfaceDescriptor() {
   ASSERT(HasResources());
   while (Exists(current_connection_interface_descriptor_)) {
     if (++current_connection_interface_descriptor_ == kInvalidConnectionInterfaceDescriptor) {
       current_connection_interface_descriptor_ = kStartConnectionInterfaceDescriptor;
     }
   }
-  auto channel_interface =
-      std::make_unique<ConnectionInterface>(current_connection_interface_descriptor_, std::move(channel), handler_);
-  cid_to_interface_map_[current_connection_interface_descriptor_] = std::move(channel_interface);
-  return current_connection_interface_descriptor_;
+  return current_connection_interface_descriptor_++;
+}
+
+ConnectionInterfaceDescriptor ConnectionInterfaceManager::AddChannel(
+    std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
+  if (!HasResources()) {
+    return kInvalidConnectionInterfaceDescriptor;
+  }
+  ConnectionInterfaceDescriptor cid = AllocateConnectionInterfaceDescriptor();
+
+  auto channel_interface = std::make_unique<ConnectionInterface>(cid, std::move(channel), handler_);
+  cid_to_interface_map_[cid] = std::move(channel_interface);
+  return cid;
 }
 
 void ConnectionInterfaceManager::RemoveConnection(ConnectionInterfaceDescriptor cid) {
-  ASSERT(cid_to_interface_map_.erase(cid) == 1);
+  ASSERT(cid_to_interface_map_.count(cid) == 1);
+  cid_to_interface_map_.find(cid)->second->Close();
+  cid_to_interface_map_.erase(cid);
 }
 
 bool ConnectionInterfaceManager::HasResources() const {
   return cid_to_interface_map_.size() < kMaxConnections;
 }
 
-bool ConnectionInterfaceManager::Exists(ConnectionInterfaceDescriptor cid) const {
-  return cid_to_interface_map_.find(cid) != cid_to_interface_map_.end();
-}
-
 void ConnectionInterfaceManager::SetReadDataReadyCallback(ConnectionInterfaceDescriptor cid,
                                                           ReadDataReadyCallback on_data_ready) {
   ASSERT(Exists(cid));
@@ -220,59 +242,75 @@ bool ConnectionInterfaceManager::Write(ConnectionInterfaceDescriptor cid, std::u
   return true;
 }
 
-struct ServiceManager {
+class ServiceInterface {
  public:
-  void AddService(l2cap::Psm psm, std::unique_ptr<l2cap::classic::DynamicChannelService> service);
-  void RemoveService(l2cap::Psm psm);
-
-  ServiceManager() = default;
+  ServiceInterface(uint16_t psm, ServiceInterfaceCallback register_callback,
+                   ConnectionInterfaceCallback connection_callback)
+      : psm_(psm), register_callback_(register_callback), connection_callback_(connection_callback) {}
 
- private:
-  std::unordered_map<l2cap::Psm, std::unique_ptr<l2cap::classic::DynamicChannelService>> psm_to_service_map_;
+  void OnRegistrationComplete(l2cap::classic::DynamicChannelManager::RegistrationResult result,
+                              std::unique_ptr<l2cap::classic::DynamicChannelService> service) {
+    ASSERT(service_ == nullptr);
+    ASSERT(psm_ == service->GetPsm());
+    LOG_DEBUG("Registration is complete for psm:%hd", psm_);
+    service_ = std::move(service);
+    register_callback_(psm_, result);
+  }
 
-  bool Exists(l2cap::Psm psm) const;
-};
+  void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
+    LOG_DEBUG("Connection is open to device:%s for psm:%hd", channel->GetDevice().ToString().c_str(), psm_);
+    connection_callback_(psm_, std::move(channel));
+  }
 
-void ServiceManager::AddService(l2cap::Psm psm, std::unique_ptr<l2cap::classic::DynamicChannelService> service) {
-  ASSERT(psm_to_service_map_.find(psm) == psm_to_service_map_.end());
-  psm_to_service_map_[psm] = std::move(service);
-}
+  l2cap::SecurityPolicy GetSecurityPolicy() const {
+    return security_policy_;
+  }
 
-void ServiceManager::RemoveService(l2cap::Psm psm) {
-  ASSERT(psm_to_service_map_.erase(psm) == 1);
-}
+  void RegisterService(
+      std::function<void(l2cap::Psm, l2cap::SecurityPolicy security_policy,
+                         l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete,
+                         l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_connection_open)>
+          func) {
+    func(psm_, security_policy_, common::BindOnce(&ServiceInterface::OnRegistrationComplete, common::Unretained(this)),
+         common::Bind(&ServiceInterface::OnConnectionOpen, common::Unretained(this)));
+  }
 
-bool ServiceManager::Exists(l2cap::Psm psm) const {
-  return psm_to_service_map_.find(psm) != psm_to_service_map_.end();
-}
+ private:
+  const l2cap::Psm psm_;
+  std::unique_ptr<l2cap::classic::DynamicChannelService> service_;
+  const l2cap::SecurityPolicy security_policy_;
+  ServiceInterfaceCallback register_callback_;
+  ConnectionInterfaceCallback connection_callback_;
+};
 
 struct L2cap::impl {
   void RegisterService(l2cap::Psm psm, ConnectionOpenCallback on_open, std::promise<void> completed);
+  void UnregisterService(l2cap::Psm psm);
+
   void CreateConnection(l2cap::Psm psm, hci::Address address, std::promise<uint16_t> completed);
+  void CloseConnection(ConnectionInterfaceDescriptor cid);
 
-  void OnRegistrationComplete(l2cap::classic::DynamicChannelManager::RegistrationResult result,
-                              std::unique_ptr<l2cap::classic::DynamicChannelService> service);
-  void OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
-  void OnConnectionFailure(l2cap::classic::DynamicChannelManager::ConnectionResult result);
+  void OnConnectionOpenNever(std::unique_ptr<l2cap::classic::DynamicChannel> channel);
+  void OnConnectionFailureNever(l2cap::classic::DynamicChannelManager::ConnectionResult result);
 
   bool Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet);
 
   impl(L2cap& module, l2cap::classic::L2capClassicModule* l2cap_module);
   ConnectionInterfaceManager connection_interface_manager_;
-  ServiceManager service_manager_;
 
- private:
-  void SyncConnectionOpen(ConnectionInterfaceDescriptor cid);
+  void OpenConnection(l2cap::Psm psm, ConnectionInterfaceDescriptor cid);
 
+ private:
   L2cap& module_;
   l2cap::classic::L2capClassicModule* l2cap_module_{nullptr};
-
-  std::unordered_map<l2cap::Psm, ConnectionOpenCallback> psm_to_connection_open_map_;
-
   std::unique_ptr<l2cap::classic::DynamicChannelManager> dynamic_channel_manager_;
 
-  std::queue<std::promise<void>> register_completed_queue_;
-  std::queue<std::promise<uint16_t>> connect_completed_queue_;
+  std::unordered_map<l2cap::Psm, std::shared_ptr<ServiceInterface>> psm_to_service_interface_map_;
+  std::unordered_map<l2cap::Psm, ConnectionOpenCallback> psm_to_on_open_map_;
+
+  std::mutex mutex_;
+  std::unordered_map<l2cap::Psm, std::promise<void>> psm_to_register_complete_map_;
+  std::unordered_map<l2cap::Psm, std::queue<std::promise<uint16_t>>> psm_to_connect_completed_queue_;
 
   os::Handler* handler_;
 };
@@ -284,40 +322,12 @@ L2cap::impl::impl(L2cap& module, l2cap::classic::L2capClassicModule* l2cap_modul
   connection_interface_manager_.SetHandler(handler_);
 }
 
-void L2cap::impl::OnRegistrationComplete(l2cap::classic::DynamicChannelManager::RegistrationResult result,
-                                         std::unique_ptr<l2cap::classic::DynamicChannelService> service) {
-  LOG_DEBUG("Registration is complete");
-  ASSERT(!register_completed_queue_.empty());
-  auto completed = std::move(register_completed_queue_.front());
-  register_completed_queue_.pop();
-  completed.set_value();
-
-  service_manager_.AddService(service->GetPsm(), std::move(service));
-}
-
-void L2cap::impl::SyncConnectionOpen(ConnectionInterfaceDescriptor cid) {
-  ASSERT(!connect_completed_queue_.empty());
-  auto completed = std::move(connect_completed_queue_.front());
-  connect_completed_queue_.pop();
-  completed.set_value(cid);
+void L2cap::impl::OnConnectionOpenNever(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
+  ASSERT(false);
 }
 
-void L2cap::impl::OnConnectionOpen(std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
-  LOG_DEBUG("Connection is open to connect_queue_size:%zd device:%s", connect_completed_queue_.size(),
-            channel->GetDevice().ToString().c_str());
-
-  ConnectionInterfaceDescriptor cid = kInvalidConnectionInterfaceDescriptor;
-  if (connection_interface_manager_.HasResources()) {
-    cid = connection_interface_manager_.AddChannel(std::move(channel));
-  }
-  if (!connect_completed_queue_.empty()) {
-    SyncConnectionOpen(cid);
-  }
-  // TODO(cmanton) Inform legacy psm service that a new connection is
-  // available
-}
-
-void L2cap::impl::OnConnectionFailure(l2cap::classic::DynamicChannelManager::ConnectionResult result) {
+void L2cap::impl::OnConnectionFailureNever(l2cap::classic::DynamicChannelManager::ConnectionResult result) {
+  ASSERT(false);
   switch (result.connection_result_code) {
     case l2cap::classic::DynamicChannelManager::ConnectionResultCode::SUCCESS:
       LOG_WARN("Connection failed result:success hci:%s", hci::ErrorCodeText(result.hci_error).c_str());
@@ -333,32 +343,91 @@ void L2cap::impl::OnConnectionFailure(l2cap::classic::DynamicChannelManager::Con
                 l2cap::ConnectionResponseResultText(result.l2cap_connection_response_result).c_str());
       break;
   }
-  auto completed = std::move(connect_completed_queue_.front());
-  connect_completed_queue_.pop();
-  completed.set_value(kInvalidConnectionInterfaceDescriptor);
 }
 
-void L2cap::impl::RegisterService(l2cap::Psm psm, ConnectionOpenCallback on_open, std::promise<void> completed) {
-  l2cap::SecurityPolicy security_policy;
-  register_completed_queue_.push(std::move(completed));
+void L2cap::impl::OpenConnection(l2cap::Psm psm, ConnectionInterfaceDescriptor cid) {
+  LOG_INFO("About to call back to client indicating open connection psm:%hd cid:%hd", psm, cid);
+  psm_to_on_open_map_[psm](psm, cid, [cid](std::function<void(uint16_t cid)> func) {
+    LOG_DEBUG("About to run postable on this thread and inform sdp that connection is open");
+    func(cid);
+  });
+}
 
-  psm_to_connection_open_map_[psm] = std::move(on_open);
+void L2cap::impl::RegisterService(l2cap::Psm psm, ConnectionOpenCallback on_open, std::promise<void> completed) {
+  ASSERT(psm_to_service_interface_map_.find(psm) == psm_to_service_interface_map_.end());
+  ASSERT(psm_to_register_complete_map_.find(psm) == psm_to_register_complete_map_.end());
+  ASSERT(psm_to_on_open_map_.find(psm) == psm_to_on_open_map_.end());
+
+  psm_to_on_open_map_[psm] = on_open;
+
+  psm_to_service_interface_map_.emplace(
+      psm, std::make_shared<ServiceInterface>(
+               psm,
+               [this](l2cap::Psm psm, l2cap::classic::DynamicChannelManager::RegistrationResult result) {
+                 LOG_DEBUG("Service has been registered");
+                 ASSERT(psm_to_register_complete_map_.find(psm) != psm_to_register_complete_map_.end());
+                 {
+                   std::unique_lock<std::mutex> lock(mutex_);
+                   auto completed = std::move(psm_to_register_complete_map_[psm]);
+                   psm_to_register_complete_map_.erase(psm);
+                   completed.set_value();
+                 }
+               },
+
+               [this](l2cap::Psm psm, std::unique_ptr<l2cap::classic::DynamicChannel> channel) {
+                 ConnectionInterfaceDescriptor cid = connection_interface_manager_.AddChannel(std::move(channel));
+                 LOG_DEBUG("Connection has been opened cid:%hd psm:%hd", cid, psm);
+                 {
+                   // If initiated locally unblock requestor that
+                   // we now have a connection by providing the
+                   // cid.
+                   std::unique_lock<std::mutex> lock(mutex_);
+                   if (psm_to_connect_completed_queue_.find(psm) != psm_to_connect_completed_queue_.end()) {
+                     if (!psm_to_connect_completed_queue_[psm].empty()) {
+                       LOG_DEBUG("Locally initiated, so inform waiting client of the cid %hd", cid);
+                       auto completed = std::move(psm_to_connect_completed_queue_[psm].front());
+                       psm_to_connect_completed_queue_[psm].pop();
+                       completed.set_value(cid);
+                     }
+                   }
+                   std::this_thread::yield();
+                 }
+                 if (cid != kInvalidConnectionInterfaceDescriptor) {
+                   handler_->Post(common::BindOnce(&L2cap::impl::OpenConnection, common::Unretained(this), psm, cid));
+                 }
+                 usleep(10);
+               }));
+
+  psm_to_service_interface_map_.find(psm)->second->RegisterService(
+      [this](l2cap::Psm psm, l2cap::SecurityPolicy security_policy,
+             l2cap::classic::DynamicChannelManager::OnRegistrationCompleteCallback on_registration_complete,
+             l2cap::classic::DynamicChannelManager::OnConnectionOpenCallback on_connection_open) {
+        bool rc = dynamic_channel_manager_->RegisterService(psm, security_policy, std::move(on_registration_complete),
+                                                            on_connection_open, handler_);
+        ASSERT_LOG(rc == true, "Failed to register classic service");
+      });
+}
 
-  bool rc = dynamic_channel_manager_->RegisterService(
-      psm, security_policy, common::BindOnce(&L2cap::impl::OnRegistrationComplete, common::Unretained(this)),
-      common::Bind(&L2cap::impl::OnConnectionOpen, common::Unretained(this)), handler_);
-  ASSERT_LOG(rc == true, "Failed to register classic service");
+void L2cap::impl::UnregisterService(l2cap::Psm psm) {
+  psm_to_service_interface_map_.erase(psm);
 }
 
 void L2cap::impl::CreateConnection(l2cap::Psm psm, hci::Address address, std::promise<uint16_t> completed) {
   LOG_INFO("Creating connection to psm:%hd device:%s", psm, address.ToString().c_str());
-  connect_completed_queue_.push(std::move(completed));
+  {
+    std::unique_lock<std::mutex> lock(mutex_);
+    psm_to_connect_completed_queue_[psm].push(std::move(completed));
+  }
   bool rc = dynamic_channel_manager_->ConnectChannel(
-      address, psm, common::Bind(&L2cap::impl::OnConnectionOpen, common::Unretained(this)),
-      common::Bind(&L2cap::impl::OnConnectionFailure, common::Unretained(this)), handler_);
+      address, psm, common::Bind(&L2cap::impl::OnConnectionOpenNever, common::Unretained(this)),
+      common::Bind(&L2cap::impl::OnConnectionFailureNever, common::Unretained(this)), handler_);
   ASSERT_LOG(rc == true, "Failed to create classic connection channel");
 }
 
+void L2cap::impl::CloseConnection(ConnectionInterfaceDescriptor cid) {
+  connection_interface_manager_.RemoveConnection(cid);
+}
+
 bool L2cap::impl::Write(ConnectionInterfaceDescriptor cid, std::unique_ptr<packet::RawBuilder> packet) {
   return connection_interface_manager_.Write(cid, std::move(packet));
 }
@@ -368,6 +437,11 @@ void L2cap::RegisterService(uint16_t raw_psm, ConnectionOpenCallback on_open, st
   pimpl_->RegisterService(psm, on_open, std::move(completed));
 }
 
+void L2cap::UnregisterService(uint16_t raw_psm) {
+  l2cap::Psm psm{raw_psm};
+  pimpl_->UnregisterService(psm);
+}
+
 void L2cap::CreateConnection(uint16_t raw_psm, const std::string address_string, std::promise<uint16_t> completed) {
   l2cap::Psm psm{raw_psm};
   hci::Address address;
@@ -376,6 +450,11 @@ void L2cap::CreateConnection(uint16_t raw_psm, const std::string address_string,
   return pimpl_->CreateConnection(psm, address, std::move(completed));
 }
 
+void L2cap::CloseConnection(uint16_t raw_cid) {
+  ConnectionInterfaceDescriptor cid(raw_cid);
+  return pimpl_->CloseConnection(cid);
+}
+
 void L2cap::SetReadDataReadyCallback(uint16_t cid, ReadDataReadyCallback on_data_ready) {
   pimpl_->connection_interface_manager_.SetReadDataReadyCallback(static_cast<ConnectionInterfaceDescriptor>(cid),
                                                                  on_data_ready);
index 5918b20..67a75d9 100644 (file)
@@ -30,7 +30,10 @@ namespace shim {
 class L2cap : public bluetooth::Module, public bluetooth::shim::IL2cap {
  public:
   void RegisterService(uint16_t psm, ConnectionOpenCallback on_open, std::promise<void> completed) override;
+  void UnregisterService(uint16_t psm) override;
+
   void CreateConnection(uint16_t psm, const std::string address, std::promise<uint16_t> completed) override;
+  void CloseConnection(uint16_t cid) override;
 
   void SetReadDataReadyCallback(uint16_t cid, ReadDataReadyCallback on_data_ready) override;
   void SetConnectionClosedCallback(uint16_t cid, ConnectionClosedCallback on_closed) override;
index 14a7f5a..7769fa0 100644 (file)
@@ -34,11 +34,15 @@ void TestGdShimL2cap::RegisterService(
   completed.set_value();
 }
 
+void TestGdShimL2cap::UnregisterService(uint16_t psm) {}
+
 void TestGdShimL2cap::CreateConnection(uint16_t psm, const std::string address,
                                        std::promise<uint16_t> completed) {
   completed.set_value(cid_);
 }
 
+void TestGdShimL2cap::CloseConnection(uint16_t cid) {}
+
 void TestGdShimL2cap::SetReadDataReadyCallback(
     uint16_t cid, bluetooth::shim::ReadDataReadyCallback on_data_ready) {}
 
index 967e7f9..9f90199 100644 (file)
@@ -30,8 +30,10 @@ class TestGdShimL2cap : public bluetooth::shim::IL2cap {
   void RegisterService(uint16_t psm,
                        bluetooth::shim::ConnectionOpenCallback on_open,
                        std::promise<void> completed) override;
+  void UnregisterService(uint16_t psm);
   void CreateConnection(uint16_t psm, const std::string address,
                         std::promise<uint16_t> completed) override;
+  void CloseConnection(uint16_t cid);
   void SetReadDataReadyCallback(
       uint16_t cid,
       bluetooth::shim::ReadDataReadyCallback on_data_ready) override;