diff --git a/system/btif/src/bluetooth.cc b/system/btif/src/bluetooth.cc
index efd77da4c04ecb72e6e46e94e7b98ad91e5b9f55..cce99c2248c6c07bab57fa8160367fb57095bbad 100644
--- a/system/btif/src/bluetooth.cc
+++ b/system/btif/src/bluetooth.cc
@@ -178,6 +178,8 @@ bt_status_t btif_sdp_execute_service(bool b_enable);
 bt_status_t btif_hh_connect(const tAclLinkSpec* link_spec);
 bt_status_t btif_hd_execute_service(bool b_enable);
 
+extern void gatt_tcb_dump(int fd);
+
 /*******************************************************************************
  *  Callbacks from bluetooth::core (see go/invisalign-bt)
  ******************************************************************************/
@@ -810,6 +812,7 @@ static void dump(int fd, const char** arguments) {
   btif_sock_dump(fd);
   bluetooth::avrcp::AvrcpService::DebugDump(fd);
   btif_debug_config_dump(fd);
+  gatt_tcb_dump(fd);
   device_debug_iot_config_dump(fd);
   BTA_HfClientDumpStatistics(fd);
   wakelock_debug_dump(fd);
diff --git a/system/stack/gatt/gatt_main.cc b/system/stack/gatt/gatt_main.cc
index 959df2502b1b8c79976aa3af8925d57c38b0ec00..c09cbc6d0ecaf4d080c1262071b03ed3ba51f1d1 100644
--- a/system/stack/gatt/gatt_main.cc
+++ b/system/stack/gatt/gatt_main.cc
@@ -45,6 +45,7 @@
 #include "stack/btm/btm_sec.h"
 #include "stack/eatt/eatt.h"
 #include "stack/gatt/gatt_int.h"
+#include "stack/include/acl_api.h"
 #include "stack/include/bt_hdr.h"
 #include "stack/include/bt_psm_types.h"
 #include "stack/include/bt_types.h"
@@ -526,6 +527,13 @@ static void gatt_le_connect_cback(uint16_t chan, const RawAddress& bd_addr,
     p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_LE);
     if (!p_tcb) {
       log::error("CCB max out, no rsources");
+      if (IS_FLAG_ENABLED(gatt_drop_acl_on_out_of_resources_fix)) {
+        log::error("Disconnecting address:{} due to out of resources.",
+                   ADDRESS_TO_LOGGABLE_CSTR(bd_addr));
+        // When single FIXED channel cannot be created, there is no reason to
+        // keep the link
+        btm_remove_acl(bd_addr, transport);
+      }
       return;
     }
 
diff --git a/system/stack/gatt/gatt_utils.cc b/system/stack/gatt/gatt_utils.cc
index 575d24f005d10771bdc112496950a6b97ebc6b07..b48593da7f7a70f54d551035867cbd1837a37e4b 100644
--- a/system/stack/gatt/gatt_utils.cc
+++ b/system/stack/gatt/gatt_utils.cc
@@ -436,6 +436,36 @@ tGATT_TCB* gatt_find_tcb_by_addr(const RawAddress& bda,
   return p_tcb;
 }
 
+/*******************************************************************************
+ *
+ * Function     gatt_tcb_dump
+ *
+ * Description  Print gatt_cb.tcb[] into dumpsys
+ *
+ * Returns      void
+ *
+ ******************************************************************************/
+void gatt_tcb_dump(int fd) {
+  std::stringstream stream;
+  int in_use_cnt = 0;
+
+  for (int i = 0; i < GATT_MAX_PHY_CHANNEL; i++) {
+    tGATT_TCB* p_tcb = &gatt_cb.tcb[i];
+
+    if (p_tcb->in_use) {
+      in_use_cnt++;
+      stream << "  id: " << +p_tcb->tcb_idx
+             << "  address: " << ADDRESS_TO_LOGGABLE_STR(p_tcb->peer_bda)
+             << "  transport: " << bt_transport_text(p_tcb->transport)
+             << "  ch_state: " << gatt_channel_state_text(p_tcb->ch_state);
+      stream << "\n";
+    }
+  }
+
+  dprintf(fd, "TCB (GATT_MAX_PHY_CHANNEL: %d) in_use: %d\n%s\n",
+          GATT_MAX_PHY_CHANNEL, in_use_cnt, stream.str().c_str());
+}
+
 /*******************************************************************************
  *
  * Function         gatt_allocate_tcb_by_bdaddr
diff --git a/system/test/mock/mock_stack_gatt_main.cc b/system/test/mock/mock_stack_gatt_main.cc
index 5a6bf35641745f5b58f4522964aaccdb130d944b..50cd730a672e1b195aab54d789f46d5cc5bc6165 100644
--- a/system/test/mock/mock_stack_gatt_main.cc
+++ b/system/test/mock/mock_stack_gatt_main.cc
@@ -108,3 +108,7 @@ void gatt_update_app_use_link_flag(tGATT_IF /* gatt_if */,
                                    bool /* check_acl_link */) {
   inc_func_call_count(__func__);
 }
+
+void gatt_tcb_dump(int fd) {
+  inc_func_call_count(__func__);
+}