L2cap shim layer with legacy

Bug: 141758481
Test: compiles and gracefully fails connect operation
Change-Id: Id0cdc9f0cd8efed18f9a3b6df24207726f0bbd3a
diff --git a/system/main/shim/entry.cc b/system/main/shim/entry.cc
index a460de6..8768818 100644
--- a/system/main/shim/entry.cc
+++ b/system/main/shim/entry.cc
@@ -50,6 +50,10 @@
   return GetGabeldorscheStack()->GetHciLayer();
 }
 
+bluetooth::shim::IL2cap* bluetooth::shim::GetL2cap() {
+  return GetGabeldorscheStack()->GetL2cap();
+}
+
 bluetooth::shim::IPage* bluetooth::shim::GetPage() {
   return GetGabeldorscheStack()->GetPage();
 }
diff --git a/system/main/shim/entry.h b/system/main/shim/entry.h
index fd8ef0e..a4d4cf4 100644
--- a/system/main/shim/entry.h
+++ b/system/main/shim/entry.h
@@ -43,6 +43,7 @@
 bluetooth::shim::IConnectability* GetConnectability();
 bluetooth::shim::IInquiry* GetInquiry();
 bluetooth::shim::IHciLayer* GetHciLayer();
+bluetooth::shim::IL2cap* GetL2cap();
 bluetooth::shim::IPage* GetPage();
 
 }  // namespace shim
diff --git a/system/main/shim/l2c_api.cc b/system/main/shim/l2c_api.cc
index 4ba961b..5b6c49c 100644
--- a/system/main/shim/l2c_api.cc
+++ b/system/main/shim/l2c_api.cc
@@ -23,18 +23,21 @@
 
 static bluetooth::shim::L2cap shim_l2cap;
 
+/**
+ * Classic Service Registration APIs
+ */
 uint16_t bluetooth::shim::L2CA_Register(uint16_t client_psm,
-                                        tL2CAP_APPL_INFO* p_cb_info,
+                                        tL2CAP_APPL_INFO* callbacks,
                                         bool enable_snoop) {
   if (L2C_INVALID_PSM(client_psm)) {
     LOG_ERROR(LOG_TAG, "%s Invalid classic psm:0x%04x", __func__, client_psm);
     return 0;
   }
 
-  if ((p_cb_info->pL2CA_ConfigCfm_Cb == nullptr) ||
-      (p_cb_info->pL2CA_ConfigInd_Cb == nullptr) ||
-      (p_cb_info->pL2CA_DataInd_Cb == nullptr) ||
-      (p_cb_info->pL2CA_DisconnectInd_Cb == nullptr)) {
+  if ((callbacks->pL2CA_ConfigCfm_Cb == nullptr) ||
+      (callbacks->pL2CA_ConfigInd_Cb == nullptr) ||
+      (callbacks->pL2CA_DataInd_Cb == nullptr) ||
+      (callbacks->pL2CA_DisconnectInd_Cb == nullptr)) {
     LOG_ERROR(LOG_TAG, "%s Invalid classic callbacks psm:0x%04x", __func__,
               client_psm);
     return 0;
@@ -43,7 +46,7 @@
   /**
    * Check if this is a registration for an outgoing-only connection.
    */
-  bool is_outgoing_connection_only = p_cb_info->pL2CA_ConnectInd_Cb == nullptr;
+  bool is_outgoing_connection_only = callbacks->pL2CA_ConnectInd_Cb == nullptr;
   uint16_t psm = shim_l2cap.ConvertClientToRealPsm(client_psm,
                                                    is_outgoing_connection_only);
 
@@ -53,13 +56,13 @@
               __func__, client_psm, psm);
     return 0;
   }
-  shim_l2cap.Classic().RegisterPsm(psm, p_cb_info);
+  shim_l2cap.Classic().RegisterPsm(psm, callbacks);
 
   LOG_INFO(LOG_TAG, "%s classic client_psm:0x%04x psm:0x%04x", __func__,
            client_psm, psm);
 
-  // TODO(cmanton) Register this service with GD
-  // TODO(cmanton) Fake out a config negotiator
+  shim_l2cap.Register(psm, callbacks, enable_snoop);
+
   return psm;
 }
 
@@ -107,62 +110,20 @@
   shim_l2cap.Le().DeallocatePsm(psm);
 }
 
+/**
+ * Classic Connection Oriented Channel APIS
+ */
 uint16_t bluetooth::shim::L2CA_ErtmConnectReq(uint16_t psm,
-                                              const RawAddress& p_bd_addr,
+                                              const RawAddress& raw_address,
                                               tL2CAP_ERTM_INFO* p_ertm_info) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd addr:%s p_ertm_info:%p", __func__,
-           psm, p_bd_addr.ToString().c_str(), p_ertm_info);
-  return 0;
+  CHECK(p_ertm_info == nullptr)
+      << "UNIMPLEMENTED set enhanced retransmission mode config";
+  return shim_l2cap.Connect(psm, raw_address);
 }
 
 uint16_t bluetooth::shim::L2CA_ConnectReq(uint16_t psm,
-                                          const RawAddress& p_bd_addr) {
-  return bluetooth::shim::L2CA_ErtmConnectReq(psm, p_bd_addr, nullptr);
-}
-
-uint16_t bluetooth::shim::L2CA_RegisterLECoc(uint16_t psm,
-                                             tL2CAP_APPL_INFO* p_cb_info) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd p_cb_info:%p", __func__, psm,
-           p_cb_info);
-  return 0;
-}
-
-void bluetooth::shim::L2CA_DeregisterLECoc(uint16_t psm) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd", __func__, psm);
-}
-
-uint16_t bluetooth::shim::L2CA_ConnectLECocReq(uint16_t psm,
-                                               const RawAddress& p_bd_addr,
-                                               tL2CAP_LE_CFG_INFO* p_cfg) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd addr:%s p_cfg:%p", __func__, psm,
-           p_bd_addr.ToString().c_str(), p_cfg);
-  return 0;
-}
-
-bool bluetooth::shim::L2CA_ConnectLECocRsp(const RawAddress& p_bd_addr,
-                                           uint8_t id, uint16_t lcid,
-                                           uint16_t result, uint16_t status,
-                                           tL2CAP_LE_CFG_INFO* p_cfg) {
-  LOG_INFO(LOG_TAG,
-           "UNIMPLEMENTED %s addr:%s id:%hhd lcid:%hd result:%hd status:%hd "
-           "p_cfg:%p",
-           __func__, p_bd_addr.ToString().c_str(), id, lcid, result, status,
-           p_cfg);
-  return false;
-}
-
-bool bluetooth::shim::L2CA_GetPeerLECocConfig(uint16_t lcid,
-                                              tL2CAP_LE_CFG_INFO* peer_cfg) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s lcid:%hd peer_cfg:%p", __func__, lcid,
-           peer_cfg);
-  return false;
-}
-
-bool bluetooth::shim::L2CA_SetConnectionCallbacks(
-    uint16_t local_cid, const tL2CAP_APPL_INFO* callbacks) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s lcid:%hd callbacks:%p", __func__,
-           local_cid, callbacks);
-  return false;
+                                          const RawAddress& raw_address) {
+  return bluetooth::shim::L2CA_ErtmConnectReq(psm, raw_address, nullptr);
 }
 
 bool bluetooth::shim::L2CA_ErtmConnectRsp(const RawAddress& p_bd_addr,
@@ -204,6 +165,92 @@
   return false;
 }
 
+/**
+ * Le Connection Oriented Channel APIs
+ */
+uint16_t bluetooth::shim::L2CA_RegisterLECoc(uint16_t psm,
+                                             tL2CAP_APPL_INFO* callbacks) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd callbacks:%p", __func__, psm,
+           callbacks);
+  return 0;
+}
+
+void bluetooth::shim::L2CA_DeregisterLECoc(uint16_t psm) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd", __func__, psm);
+}
+
+uint16_t bluetooth::shim::L2CA_ConnectLECocReq(uint16_t psm,
+                                               const RawAddress& p_bd_addr,
+                                               tL2CAP_LE_CFG_INFO* p_cfg) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s psm:%hd addr:%s p_cfg:%p", __func__, psm,
+           p_bd_addr.ToString().c_str(), p_cfg);
+  return 0;
+}
+
+bool bluetooth::shim::L2CA_ConnectLECocRsp(const RawAddress& p_bd_addr,
+                                           uint8_t id, uint16_t lcid,
+                                           uint16_t result, uint16_t status,
+                                           tL2CAP_LE_CFG_INFO* p_cfg) {
+  LOG_INFO(LOG_TAG,
+           "UNIMPLEMENTED %s addr:%s id:%hhd lcid:%hd result:%hd status:%hd "
+           "p_cfg:%p",
+           __func__, p_bd_addr.ToString().c_str(), id, lcid, result, status,
+           p_cfg);
+  return false;
+}
+
+bool bluetooth::shim::L2CA_GetPeerLECocConfig(uint16_t lcid,
+                                              tL2CAP_LE_CFG_INFO* peer_cfg) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s lcid:%hd peer_cfg:%p", __func__, lcid,
+           peer_cfg);
+  return false;
+}
+
+/**
+ * Channel Data Writes
+ */
+bool bluetooth::shim::L2CA_SetConnectionCallbacks(
+    uint16_t cid, const tL2CAP_APPL_INFO* callbacks) {
+  return shim_l2cap.SetCallbacks(cid, callbacks);
+}
+
+uint8_t bluetooth::shim::L2CA_DataWriteEx(uint16_t cid, BT_HDR* bt_hdr,
+                                          uint16_t flags) {
+  if (shim_l2cap.IsCongested(cid)) {
+    return L2CAP_DW_CONGESTED;
+  }
+
+  bool write_success = false;
+  switch (flags) {
+    case L2CAP_FLUSHABLE_CH_BASED:
+      write_success = shim_l2cap.Write(cid, bt_hdr);
+      break;
+    case L2CAP_FLUSHABLE_PKT:
+      write_success = shim_l2cap.WriteFlushable(cid, bt_hdr);
+      break;
+    case L2CAP_NON_FLUSHABLE_PKT:
+      write_success = shim_l2cap.WriteNonFlushable(cid, bt_hdr);
+      break;
+  }
+  return write_success ? L2CAP_DW_SUCCESS : L2CAP_DW_FAILED;
+}
+
+uint8_t bluetooth::shim::L2CA_DataWrite(uint16_t cid, BT_HDR* p_data) {
+  return bluetooth::shim::L2CA_DataWriteEx(cid, p_data,
+                                           L2CAP_FLUSHABLE_CH_BASED);
+}
+
+/**
+ * L2cap Layer APIs
+ */
+uint8_t bluetooth::shim::L2CA_SetDesireRole(uint8_t new_role) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+  return 0;
+}
+
+/**
+ * Ping APIs
+ */
 bool bluetooth::shim::L2CA_Ping(const RawAddress& p_bd_addr,
                                 tL2CA_ECHO_RSP_CB* p_callback) {
   LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s addr:%s p_callback:%p", __func__,
@@ -218,18 +265,9 @@
   return false;
 }
 
-bool bluetooth::shim::L2CA_GetIdentifiers(uint16_t lcid, uint16_t* rcid,
-                                          uint16_t* handle) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
-  return false;
-}
-
-bool bluetooth::shim::L2CA_SetIdleTimeout(uint16_t cid, uint16_t timeout,
-                                          bool is_global) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
-  return false;
-}
-
+/**
+ * Link APIs
+ */
 bool bluetooth::shim::L2CA_SetIdleTimeoutByBdAddr(const RawAddress& bd_addr,
                                                   uint16_t timeout,
                                                   tBT_TRANSPORT transport) {
@@ -237,11 +275,6 @@
   return false;
 }
 
-uint8_t bluetooth::shim::L2CA_SetDesireRole(uint8_t new_role) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
-  return 0;
-}
-
 uint16_t bluetooth::shim::L2CA_LocalLoopbackReq(uint16_t psm, uint16_t handle,
                                                 const RawAddress& p_bd_addr) {
   LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
@@ -254,30 +287,6 @@
   return false;
 }
 
-bool bluetooth::shim::L2CA_FlowControl(uint16_t cid, bool data_enabled) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
-  return false;
-}
-
-bool bluetooth::shim::L2CA_SendTestSFrame(uint16_t cid, uint8_t sup_type,
-                                          uint8_t back_track) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
-  return false;
-}
-
-bool bluetooth::shim::L2CA_SetTxPriority(uint16_t cid,
-                                         tL2CAP_CHNL_PRIORITY priority) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
-  return false;
-}
-
-bool bluetooth::shim::L2CA_SetChnlDataRate(uint16_t cid,
-                                           tL2CAP_CHNL_DATA_RATE tx,
-                                           tL2CAP_CHNL_DATA_RATE rx) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
-  return false;
-}
-
 bool bluetooth::shim::L2CA_SetFlushTimeout(const RawAddress& bd_addr,
                                            uint16_t flush_tout) {
   LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
@@ -297,11 +306,9 @@
   return false;
 }
 
-uint8_t bluetooth::shim::L2CA_GetChnlFcrMode(uint16_t lcid) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
-  return 0;
-}
-
+/**
+ * Fixed Channel APIs
+ */
 bool bluetooth::shim::L2CA_RegisterFixedChannel(uint16_t fixed_cid,
                                                 tL2CAP_FIXED_CHNL_REG* p_freg) {
   LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
@@ -334,13 +341,9 @@
   return false;
 }
 
-bool bluetooth::shim::L2CA_SetFixedChannelTout(const RawAddress& rem_bda,
-                                               uint16_t fixed_cid,
-                                               uint16_t idle_tout) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
-  return false;
-}
-
+/**
+ * Channel Configuration API
+ */
 bool bluetooth::shim::L2CA_GetCurrentConfig(
     uint16_t lcid, tL2CAP_CFG_INFO** pp_our_cfg,
     tL2CAP_CH_CFG_BITS* p_our_cfg_bits, tL2CAP_CFG_INFO** pp_peer_cfg,
@@ -356,31 +359,74 @@
   return false;
 }
 
-bool bluetooth::shim::L2CA_RegForNoCPEvt(tL2CA_NOCP_CB* p_cb,
-                                         const RawAddress& p_bda) {
+/**
+ * Channel hygiene APIs
+ */
+bool bluetooth::shim::L2CA_GetIdentifiers(uint16_t lcid, uint16_t* rcid,
+                                          uint16_t* handle) {
   LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
   return false;
 }
 
-uint8_t bluetooth::shim::L2CA_DataWrite(uint16_t cid, BT_HDR* p_data) {
+bool bluetooth::shim::L2CA_SetIdleTimeout(uint16_t cid, uint16_t timeout,
+                                          bool is_global) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+  return false;
+}
+
+bool bluetooth::shim::L2CA_FlowControl(uint16_t cid, bool data_enabled) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+  return false;
+}
+
+bool bluetooth::shim::L2CA_SendTestSFrame(uint16_t cid, uint8_t sup_type,
+                                          uint8_t back_track) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+  return false;
+}
+
+bool bluetooth::shim::L2CA_SetTxPriority(uint16_t cid,
+                                         tL2CAP_CHNL_PRIORITY priority) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+  return false;
+}
+
+bool bluetooth::shim::L2CA_SetChnlDataRate(uint16_t cid,
+                                           tL2CAP_CHNL_DATA_RATE tx,
+                                           tL2CAP_CHNL_DATA_RATE rx) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+  return false;
+}
+
+uint8_t bluetooth::shim::L2CA_GetChnlFcrMode(uint16_t lcid) {
   LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
   return 0;
 }
 
+bool bluetooth::shim::L2CA_SetFixedChannelTout(const RawAddress& rem_bda,
+                                               uint16_t fixed_cid,
+                                               uint16_t idle_tout) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+  return false;
+}
+
 bool bluetooth::shim::L2CA_SetChnlFlushability(uint16_t cid,
                                                bool is_flushable) {
   LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
   return false;
 }
 
-uint8_t bluetooth::shim::L2CA_DataWriteEx(uint16_t cid, BT_HDR* p_data,
-                                          uint16_t flags) {
-  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
-  return false;
-}
-
 uint16_t bluetooth::shim::L2CA_FlushChannel(uint16_t lcid,
                                             uint16_t num_to_flush) {
   LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
   return 0;
 }
+
+/**
+ * Misc APIs
+ */
+bool bluetooth::shim::L2CA_RegForNoCPEvt(tL2CA_NOCP_CB* p_cb,
+                                         const RawAddress& p_bda) {
+  LOG_INFO(LOG_TAG, "UNIMPLEMENTED %s", __func__);
+  return false;
+}
diff --git a/system/main/shim/l2cap.cc b/system/main/shim/l2cap.cc
index 5afbb01..765ba0d 100644
--- a/system/main/shim/l2cap.cc
+++ b/system/main/shim/l2cap.cc
@@ -13,8 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "bt_shim_l2cap"
 
 #include "main/shim/l2cap.h"
+#include "main/shim/entry.h"
+#include "main/shim/shim.h"
+#include "osi/include/allocator.h"
+#include "osi/include/log.h"
+
+constexpr size_t kBtHdrSize = sizeof(BT_HDR);
 
 bool bluetooth::shim::PsmData::IsPsmAllocated(uint16_t psm) const {
   return psm_to_callback_map.find(psm) != psm_to_callback_map.end();
@@ -115,3 +122,92 @@
   }
   return classic_dynamic_psm_;
 }
+
+void bluetooth::shim::L2cap::Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+                                      bool enable_snoop) {
+  LOG_DEBUG(LOG_TAG, "Registering service psm:%hd", psm);
+
+  std::chrono::system_clock::time_point two_seconds =
+      std::chrono::system_clock::now() + std::chrono::seconds(2);
+
+  std::promise<void> register_completed;
+  auto completed = register_completed.get_future();
+  bluetooth::shim::GetL2cap()->RegisterService(psm, enable_snoop,
+                                               std::move(register_completed));
+  completed.wait();
+  if (std::future_status::ready != completed.wait_until(two_seconds)) {
+    LOG_WARN(LOG_TAG, "Timed out registering service to psm:%hd", psm);
+  }
+}
+
+uint16_t bluetooth::shim::L2cap::Connect(uint16_t psm,
+                                         const RawAddress& raw_address) {
+  LOG_DEBUG(LOG_TAG, "Requesting connection to psm:%hd address:%s", psm,
+            raw_address.ToString().c_str());
+
+  std::chrono::system_clock::time_point two_seconds =
+      std::chrono::system_clock::now() + std::chrono::seconds(2);
+
+  std::promise<uint16_t> connect_completed;
+  auto completed = connect_completed.get_future();
+  bluetooth::shim::GetL2cap()->Connect(psm, raw_address.ToString(),
+                                       std::move(connect_completed));
+  if (std::future_status::ready == completed.wait_until(two_seconds)) {
+    return completed.get();
+  }
+  LOG_WARN(LOG_TAG, "Timed out connecting to psm:%hd address:%s", psm,
+           raw_address.ToString().c_str());
+  return 0;
+}
+
+bool bluetooth::shim::L2cap::IsCongested(uint16_t cid) const {
+  LOG_WARN(LOG_TAG, "UNIMPLEMENTED checking congestion on a channel");
+  return false;
+}
+
+bool bluetooth::shim::L2cap::Write(uint16_t cid, BT_HDR* bt_hdr) {
+  const uint8_t* data = bt_hdr->data + bt_hdr->offset;
+  size_t len = bt_hdr->len;
+  return bluetooth::shim::GetL2cap()->Write(cid, data, len);
+}
+
+bool bluetooth::shim::L2cap::WriteFlushable(uint16_t cid, BT_HDR* bt_hdr) {
+  const uint8_t* data = bt_hdr->data + bt_hdr->offset;
+  size_t len = bt_hdr->len;
+  return bluetooth::shim::GetL2cap()->WriteFlushable(cid, data, len);
+}
+
+bool bluetooth::shim::L2cap::WriteNonFlushable(uint16_t cid, BT_HDR* bt_hdr) {
+  const uint8_t* data = bt_hdr->data + bt_hdr->offset;
+  size_t len = bt_hdr->len;
+  return bluetooth::shim::GetL2cap()->WriteNonFlushable(cid, data, len);
+}
+
+bool bluetooth::shim::L2cap::SetCallbacks(uint16_t cid,
+                                          const tL2CAP_APPL_INFO* callbacks) {
+  LOG_ASSERT(cid_to_callback_map_.find(cid) != cid_to_callback_map_.end())
+      << "Registering multiple channel callbacks cid:" << cid;
+  cid_to_callback_map_[cid] = callbacks;
+  bluetooth::shim::GetL2cap()->SetOnReadDataReady(
+      cid, [this](uint16_t cid, std::vector<const uint8_t> data) {
+        LOG_INFO(LOG_TAG, "Got data on cid:%hd len:%zd", cid, data.size());
+
+        BT_HDR* bt_hdr =
+            static_cast<BT_HDR*>(osi_calloc(data.size() + kBtHdrSize));
+        std::copy(data.begin(), data.end(), bt_hdr->data);
+        bt_hdr->len = data.size();
+
+        cid_to_callback_map_[cid]->pL2CA_DataInd_Cb(cid, bt_hdr);
+      });
+  bluetooth::shim::GetL2cap()->SetOnClose(cid, [this, &cid](int error_code) {
+    LOG_DEBUG(LOG_TAG, "Channel closed cid:%hd", cid);
+    cid_to_callback_map_[cid]->pL2CA_DisconnectInd_Cb(cid, true);
+  });
+  return true;
+}
+
+void bluetooth::shim::L2cap::ClearCallbacks(uint16_t cid) {
+  LOG_ASSERT(cid_to_callback_map_.find(cid) == cid_to_callback_map_.end())
+      << "Clearing callbacks that do not exist cid:" << cid;
+  cid_to_callback_map_.erase(cid);
+}
diff --git a/system/main/shim/l2cap.h b/system/main/shim/l2cap.h
index 4860dea..6653a4a 100644
--- a/system/main/shim/l2cap.h
+++ b/system/main/shim/l2cap.h
@@ -60,6 +60,17 @@
   uint16_t ConvertClientToRealPsm(uint16_t psm);
   void RemoveClientPsm(uint16_t client_psm);
 
+  void Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info, bool enable_snoop);
+  uint16_t Connect(uint16_t psm, const RawAddress& raw_address);
+
+  bool Write(uint16_t cid, BT_HDR* bt_hdr);
+  bool WriteFlushable(uint16_t cid, BT_HDR* bt_hdr);
+  bool WriteNonFlushable(uint16_t cid, BT_HDR* bt_hdr);
+  bool IsCongested(uint16_t cid) const;
+
+  bool SetCallbacks(uint16_t cid, const tL2CAP_APPL_INFO* client_callbacks);
+  void ClearCallbacks(uint16_t cid);
+
  private:
   uint16_t GetNextVirtualPsm(uint16_t real_psm);
 
@@ -71,6 +82,7 @@
   uint16_t classic_virtual_psm_;
 
   std::unordered_map<uint16_t, uint16_t> client_psm_to_real_psm_map_;
+  std::unordered_map<uint16_t, const tL2CAP_APPL_INFO*> cid_to_callback_map_;
 };
 
 }  // namespace shim