diff --git a/system/bta/ag/bta_ag_act.cc b/system/bta/ag/bta_ag_act.cc
index 34ce19128cca8e2462c52ee1e6ca294fed2300b5..f0ccef204c050a01e9d3bbc3190a208410e54fce 100644
--- a/system/bta/ag/bta_ag_act.cc
+++ b/system/bta/ag/bta_ag_act.cc
@@ -174,12 +174,9 @@ void bta_ag_start_dereg(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
  *
  ******************************************************************************/
 void bta_ag_start_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
-  /* store parameters */
-  if (!data.IsEmpty()) {
-    p_scb->peer_addr = data.api_open.bd_addr;
-    p_scb->open_services = data.api_open.services;
-    p_scb->cli_sec_mask = data.api_open.sec_mask;
-  }
+  p_scb->peer_addr = data.api_open.bd_addr;
+  p_scb->open_services = data.api_open.services;
+  p_scb->cli_sec_mask = data.api_open.sec_mask;
 
   /* Check if RFCOMM has any incoming connection to avoid collision. */
   RawAddress pending_bd_addr = RawAddress::kEmpty;
@@ -329,6 +326,7 @@ void bta_ag_open_fail(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
  *
  ******************************************************************************/
 void bta_ag_rfc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR const tBTA_AG_DATA& data) {
+  RawAddress peer_addr = p_scb->peer_addr;
   /* reinitialize stuff */
   p_scb->conn_handle = 0;
   p_scb->conn_service = 0;
@@ -345,7 +343,7 @@ void bta_ag_rfc_fail(tBTA_AG_SCB* p_scb, UNUSED_ATTR const tBTA_AG_DATA& data) {
   bta_ag_start_servers(p_scb, p_scb->reg_services);
 
   /* call open cback w. failure */
-  bta_ag_cback_open(p_scb, RawAddress::kEmpty, BTA_AG_FAIL_RFCOMM);
+  bta_ag_cback_open(p_scb, peer_addr, BTA_AG_FAIL_RFCOMM);
 }
 
 /*******************************************************************************
@@ -512,29 +510,34 @@ void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
   int status = PORT_CheckConnection(data.rfc.port_handle, &dev_addr, &lcid);
   if (status != PORT_SUCCESS) {
     LOG(ERROR) << __func__ << ", PORT_CheckConnection returned " << status;
+    return;
   }
 
   /* Collision Handling */
   for (tBTA_AG_SCB& ag_scb : bta_ag_cb.scb) {
+    // Cancel any pending collision timers
     if (ag_scb.in_use && alarm_is_scheduled(ag_scb.collision_timer)) {
       alarm_cancel(ag_scb.collision_timer);
-      if (dev_addr == ag_scb.peer_addr) {
-        /* If incoming and outgoing device are same, nothing more to do. */
-        /* Outgoing conn will be aborted because we have successful incoming
-         * conn.  */
-      } else {
-        /* Resume outgoing connection. */
-        tBTA_AG_SCB* other_scb = bta_ag_get_other_idle_scb(p_scb);
-        if (other_scb) {
-          other_scb->peer_addr = ag_scb.peer_addr;
-          other_scb->open_services = ag_scb.open_services;
-          other_scb->cli_sec_mask = ag_scb.cli_sec_mask;
-          bta_ag_resume_open(other_scb);
-        }
+      if (dev_addr != ag_scb.peer_addr && p_scb != &ag_scb) {
+        // Resume outgoing connection if incoming is not on the same device
+        bta_ag_resume_open(&ag_scb);
       }
-
       break;
     }
+    if (dev_addr == ag_scb.peer_addr && p_scb != &ag_scb) {
+      // Fail the outgoing connection to clean up any upper layer states
+      bta_ag_rfc_fail(&ag_scb, tBTA_AG_DATA::kEmpty);
+      // If client port is opened, close it
+      if (ag_scb.conn_handle > 0) {
+        status = RFCOMM_RemoveConnection(ag_scb.conn_handle);
+        if (status != PORT_SUCCESS) {
+          LOG(WARNING) << __func__ << ": RFCOMM_RemoveConnection failed for "
+                       << dev_addr << ", handle "
+                       << std::to_string(ag_scb.conn_handle) << ", error "
+                       << status;
+        }
+      }
+    }
   }
 
   p_scb->peer_addr = dev_addr;
@@ -802,3 +805,32 @@ void bta_ag_setcodec(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
 
   (*bta_ag_cb.p_cback)(BTA_AG_WBS_EVT, (tBTA_AG*)&val);
 }
+
+static void bta_ag_collision_timer_cback(void* data) {
+  if (data == nullptr) {
+    LOG(ERROR) << __func__ << ": data should never be null in a timer callback";
+    return;
+  }
+  /* If the peer haven't opened AG connection     */
+  /* we will restart opening process.             */
+  bta_ag_resume_open(static_cast<tBTA_AG_SCB*>(data));
+}
+
+void bta_ag_handle_collision(tBTA_AG_SCB* p_scb,
+                             UNUSED_ATTR const tBTA_AG_DATA& data) {
+  /* Cancel SDP if it had been started. */
+  if (p_scb->p_disc_db) {
+    SDP_CancelServiceSearch(p_scb->p_disc_db);
+    bta_ag_free_db(p_scb, tBTA_AG_DATA::kEmpty);
+  }
+
+  /* reopen registered servers */
+  /* Collision may be detected before or after we close servers. */
+  if (bta_ag_is_server_closed(p_scb)) {
+    bta_ag_start_servers(p_scb, p_scb->reg_services);
+  }
+
+  /* Start timer to han */
+  alarm_set_on_mloop(p_scb->collision_timer, BTA_AG_COLLISION_TIMEOUT_MS,
+                     bta_ag_collision_timer_cback, p_scb);
+}
\ No newline at end of file
diff --git a/system/bta/ag/bta_ag_int.h b/system/bta/ag/bta_ag_int.h
index 487664f1281c6983c0f1872e3691c2b219a2badf..3082f075433a98c038e4d74c9e92a7ec0c260116 100644
--- a/system/bta/ag/bta_ag_int.h
+++ b/system/bta/ag/bta_ag_int.h
@@ -79,6 +79,7 @@ enum {
   BTA_AG_DISC_FAIL_EVT,
   BTA_AG_RING_TIMEOUT_EVT,
   BTA_AG_SVC_TIMEOUT_EVT,
+  BTA_AG_COLLISION_EVT,
   BTA_AG_MAX_EVT,
 };
 
@@ -306,7 +307,6 @@ extern uint8_t bta_ag_service_to_idx(tBTA_SERVICE_MASK services);
 extern uint16_t bta_ag_idx_by_bdaddr(const RawAddress* peer_addr);
 extern bool bta_ag_other_scb_open(tBTA_AG_SCB* p_curr_scb);
 extern bool bta_ag_scb_open(tBTA_AG_SCB* p_curr_scb);
-extern tBTA_AG_SCB* bta_ag_get_other_idle_scb(tBTA_AG_SCB* p_curr_scb);
 extern void bta_ag_sm_execute(tBTA_AG_SCB* p_scb, uint16_t event,
                               const tBTA_AG_DATA& data);
 extern void bta_ag_sm_execute_by_handle(uint16_t handle, uint16_t event,
@@ -378,6 +378,8 @@ extern void bta_ag_svc_conn_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
 extern void bta_ag_result(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
 extern void bta_ag_setcodec(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
 extern void bta_ag_send_ring(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data);
+extern void bta_ag_handle_collision(tBTA_AG_SCB* p_scb,
+                                    const tBTA_AG_DATA& data);
 
 /* Internal utility functions */
 extern void bta_ag_sco_codec_nego(tBTA_AG_SCB* p_scb, bool result);
diff --git a/system/bta/ag/bta_ag_main.cc b/system/bta/ag/bta_ag_main.cc
index 0f33853213cfb92fbca49cc87d2f1ff361d4c289..dd0a55d2277b511a236a5169ebd594cdd8eef5cf 100644
--- a/system/bta/ag/bta_ag_main.cc
+++ b/system/bta/ag/bta_ag_main.cc
@@ -68,6 +68,7 @@ enum {
   BTA_AG_RESULT,
   BTA_AG_SETCODEC,
   BTA_AG_SEND_RING,
+  BTA_AG_HANDLE_COLLISION,
   BTA_AG_NUM_ACTIONS
 };
 
@@ -133,6 +134,7 @@ static const char* bta_ag_evt_str(uint16_t event) {
     CASE_RETURN_STR(BTA_AG_DISC_FAIL_EVT)
     CASE_RETURN_STR(BTA_AG_RING_TIMEOUT_EVT)
     CASE_RETURN_STR(BTA_AG_SVC_TIMEOUT_EVT)
+    CASE_RETURN_STR(BTA_AG_COLLISION_EVT)
     default:
       return "Unknown AG Event";
   }
@@ -160,7 +162,11 @@ const tBTA_AG_ACTION bta_ag_action[] = {
     bta_ag_sco_conn_close, bta_ag_sco_listen,    bta_ag_sco_open,
     bta_ag_sco_close,      bta_ag_sco_shutdown,  bta_ag_post_sco_open,
     bta_ag_post_sco_close, bta_ag_svc_conn_open, bta_ag_result,
-    bta_ag_setcodec,       bta_ag_send_ring};
+    bta_ag_setcodec,       bta_ag_send_ring,     bta_ag_handle_collision};
+
+static_assert(sizeof(bta_ag_action) / sizeof(tBTA_AG_ACTION) ==
+                  BTA_AG_NUM_ACTIONS,
+              "bta_ag_action must handle all actions");
 
 /* state table information */
 #define BTA_AG_ACTIONS 2    /* number of actions */
@@ -189,7 +195,8 @@ const uint8_t bta_ag_st_init[][BTA_AG_NUM_COLS] = {
     /* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
     /* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
     /* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
-    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}};
+    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST},
+    /* COLLISION_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_INIT_ST}};
 
 /* state table for opening state */
 const uint8_t bta_ag_st_opening[][BTA_AG_NUM_COLS] = {
@@ -216,7 +223,9 @@ const uint8_t bta_ag_st_opening[][BTA_AG_NUM_COLS] = {
     /* DISC_OK_EVT */ {BTA_AG_RFC_DO_OPEN, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
     /* DISC_FAIL_EVT */ {BTA_AG_DISC_FAIL, BTA_AG_IGNORE, BTA_AG_INIT_ST},
     /* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
-    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST}};
+    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPENING_ST},
+    /* COLLISION_EVT */
+    {BTA_AG_HANDLE_COLLISION, BTA_AG_IGNORE, BTA_AG_INIT_ST}};
 
 /* state table for open state */
 const uint8_t bta_ag_st_open[][BTA_AG_NUM_COLS] = {
@@ -243,7 +252,8 @@ const uint8_t bta_ag_st_open[][BTA_AG_NUM_COLS] = {
     /* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
     /* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
     /* RING_TOUT_EVT */ {BTA_AG_SEND_RING, BTA_AG_IGNORE, BTA_AG_OPEN_ST},
-    /* SVC_TOUT_EVT */ {BTA_AG_START_CLOSE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}};
+    /* SVC_TOUT_EVT */ {BTA_AG_START_CLOSE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+    /* COLLISION_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_OPEN_ST}};
 
 /* state table for closing state */
 const uint8_t bta_ag_st_closing[][BTA_AG_NUM_COLS] = {
@@ -269,7 +279,19 @@ const uint8_t bta_ag_st_closing[][BTA_AG_NUM_COLS] = {
     /* DISC_OK_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
     /* DISC_FAIL_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
     /* RING_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
-    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}};
+    /* SVC_TOUT_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST},
+    /* COLLISION_EVT */ {BTA_AG_IGNORE, BTA_AG_IGNORE, BTA_AG_CLOSING_ST}};
+
+constexpr size_t BTA_AG_NUM_EVENTS =
+    BTA_AG_MAX_EVT - BTA_SYS_EVT_START(BTA_ID_AG);
+static_assert(sizeof(bta_ag_st_init) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
+              "bta_ag_st_init must handle all AG events");
+static_assert(sizeof(bta_ag_st_opening) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
+              "bta_ag_st_opening must handle all AG events");
+static_assert(sizeof(bta_ag_st_open) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
+              "bta_ag_st_open must handle all AG events");
+static_assert(sizeof(bta_ag_st_closing) / BTA_AG_NUM_COLS == BTA_AG_NUM_EVENTS,
+              "bta_ag_st_closing must handle all AG events");
 
 /* type for state table */
 typedef const uint8_t (*tBTA_AG_ST_TBL)[BTA_AG_NUM_COLS];
@@ -494,47 +516,6 @@ bool bta_ag_scb_open(tBTA_AG_SCB* p_curr_scb) {
          p_curr_scb->state == BTA_AG_OPEN_ST;
 }
 
-/*******************************************************************************
- *
- * Function         bta_ag_get_other_idle_scb
- *
- * Description      Return other scb if it is in INIT st.
- *
- *
- * Returns          Pointer to other scb if INIT st, NULL otherwise.
- *
- ******************************************************************************/
-tBTA_AG_SCB* bta_ag_get_other_idle_scb(tBTA_AG_SCB* p_curr_scb) {
-  for (tBTA_AG_SCB& scb : bta_ag_cb.scb) {
-    if (scb.in_use && (&scb != p_curr_scb) && (scb.state == BTA_AG_INIT_ST)) {
-      return &scb;
-    }
-  }
-  /* no other scb found */
-  APPL_TRACE_DEBUG("bta_ag_get_other_idle_scb: No idle AG scb");
-  return nullptr;
-}
-
-/*******************************************************************************
- *
- * Function         bta_ag_collision_timer_cback
- *
- * Description      AG connection collision timer callback
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-static void bta_ag_collision_timer_cback(void* data) {
-  tBTA_AG_SCB* p_scb = (tBTA_AG_SCB*)data;
-
-  APPL_TRACE_DEBUG("%s", __func__);
-
-  /* If the peer haven't opened AG connection     */
-  /* we will restart opening process.             */
-  bta_ag_resume_open(p_scb);
-}
-
 /*******************************************************************************
  *
  * Function         bta_ag_collision_cback
@@ -563,24 +544,7 @@ void bta_ag_collision_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status, uint8_t id,
       LOG(WARNING) << __func__ << ": AG found collision (UNKNOWN) for handle "
                    << unsigned(handle) << " device " << peer_addr;
     }
-
-    p_scb->state = BTA_AG_INIT_ST;
-
-    /* Cancel SDP if it had been started. */
-    if (p_scb->p_disc_db) {
-      SDP_CancelServiceSearch(p_scb->p_disc_db);
-      bta_ag_free_db(p_scb, tBTA_AG_DATA::kEmpty);
-    }
-
-    /* reopen registered servers */
-    /* Collision may be detected before or after we close servers. */
-    if (bta_ag_is_server_closed(p_scb)) {
-      bta_ag_start_servers(p_scb, p_scb->reg_services);
-    }
-
-    /* Start timer to han */
-    alarm_set_on_mloop(p_scb->collision_timer, BTA_AG_COLLISION_TIMEOUT_MS,
-                       bta_ag_collision_timer_cback, p_scb);
+    bta_ag_sm_execute(p_scb, BTA_AG_COLLISION_EVT, tBTA_AG_DATA::kEmpty);
   }
 }
 
@@ -595,20 +559,16 @@ void bta_ag_collision_cback(UNUSED_ATTR tBTA_SYS_CONN_STATUS status, uint8_t id,
  *
  ******************************************************************************/
 void bta_ag_resume_open(tBTA_AG_SCB* p_scb) {
-  if (p_scb) {
-    APPL_TRACE_DEBUG("%s: handle=%d, bd_addr=%s", __func__,
-                     bta_ag_scb_to_idx(p_scb),
-                     p_scb->peer_addr.ToString().c_str());
-    /* resume opening process.  */
-    if (p_scb->state == BTA_AG_INIT_ST) {
-      LOG(WARNING) << __func__
-                   << ": handle=" << unsigned(bta_ag_scb_to_idx(p_scb))
-                   << ", bd_addr=" << p_scb->peer_addr;
-      p_scb->state = BTA_AG_OPENING_ST;
-      bta_ag_start_open(p_scb, tBTA_AG_DATA::kEmpty);
-    }
+  if (p_scb->state == BTA_AG_INIT_ST) {
+    LOG(INFO) << __func__ << ": Resume connection to " << p_scb->peer_addr
+              << ", handle" << bta_ag_scb_to_idx(p_scb);
+    tBTA_AG_DATA open_data = {.api_open.bd_addr = p_scb->peer_addr,
+                              .api_open.services = p_scb->open_services,
+                              .api_open.sec_mask = p_scb->cli_sec_mask};
+    bta_ag_sm_execute(p_scb, BTA_AG_API_OPEN_EVT, open_data);
   } else {
-    LOG(ERROR) << __func__ << ": null p_scb";
+    VLOG(1) << __func__ << ": device " << p_scb->peer_addr
+            << " is already in state " << std::to_string(p_scb->state);
   }
 }
 
diff --git a/system/btif/src/btif_hf.cc b/system/btif/src/btif_hf.cc
index 5573160e6b728020a5cb6d155ad14c44fe0c27cd..a3306ecc368602b46f3ce50ddf6dd632c78b51ab 100644
--- a/system/btif/src/btif_hf.cc
+++ b/system/btif/src/btif_hf.cc
@@ -31,6 +31,7 @@
 #include <cstring>
 #include <ctime>
 
+#include <bta/include/bta_ag_api.h>
 #include <hardware/bluetooth.h>
 #include <hardware/bluetooth_headset_callbacks.h>
 #include <hardware/bluetooth_headset_interface.h>
@@ -327,11 +328,11 @@ static void btif_hf_upstreams_evt(uint16_t event, char* p_param) {
                    << unsigned(p_data->open.status);
         btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_DISCONNECTED;
       } else {
-        BTIF_TRACE_WARNING(
-            "%s: AG open failed, but another device connected. status=%d "
-            "state=%d connected device=%s",
-            __func__, p_data->open.status, btif_hf_cb[idx].state,
-            btif_hf_cb[idx].connected_bda.ToString().c_str());
+        LOG(WARNING) << __func__ << ": AG open failed for "
+                     << p_data->open.bd_addr << ", error "
+                     << std::to_string(p_data->open.status)
+                     << ", local device is " << btif_hf_cb[idx].connected_bda
+                     << ". Ignoring as not expecting to open";
         break;
       }
       bt_hf_callbacks->ConnectionStateCallback(btif_hf_cb[idx].state,
diff --git a/system/stack/rfcomm/port_utils.cc b/system/stack/rfcomm/port_utils.cc
index 1218c9120065eb9904cffa3ca73607729532c358..77983757f709233fafdc50a7bd86034655b3acee 100644
--- a/system/stack/rfcomm/port_utils.cc
+++ b/system/stack/rfcomm/port_utils.cc
@@ -319,10 +319,9 @@ tPORT* port_find_mcb_dlci_port(tRFC_MCB* p_mcb, uint8_t dlci) {
 
   uint8_t handle = p_mcb->port_handles[dlci];
   if (handle == 0) {
-    LOG(WARNING) << __func__
-                 << ": Cannot find allocated RFCOMM app port for DLCI "
-                 << std::to_string(dlci) << " on " << p_mcb->bd_addr
-                 << ", p_mcb=" << p_mcb;
+    LOG(INFO) << __func__ << ": Cannot find allocated RFCOMM app port for DLCI "
+              << std::to_string(dlci) << " on " << p_mcb->bd_addr
+              << ", p_mcb=" << p_mcb;
     return nullptr;
   }
   return &rfc_cb.port.port[handle - 1];
diff --git a/system/stack/test/rfcomm/stack_rfcomm_test.cc b/system/stack/test/rfcomm/stack_rfcomm_test.cc
index 8d3d8859dded496829615e88c37d474d80ae3414..3d9da3f34534ce11eeec42b47f6355896b78d972 100644
--- a/system/stack/test/rfcomm/stack_rfcomm_test.cc
+++ b/system/stack/test/rfcomm/stack_rfcomm_test.cc
@@ -712,4 +712,181 @@ TEST_F(StackRfcommTest, SameClientPortMultiDeviceHelloWorld) {
       acl_handle_1, lcid_1, 1));
 }
 
+TEST_F(StackRfcommTest, TestConnectionCollision) {
+  static const uint16_t acl_handle = 0x0008;
+  static const uint16_t old_lcid = 0x004a;
+  static const uint16_t new_lcid = 0x005c;
+  static const uint16_t test_uuid = 0x1112;
+  static const uint8_t test_server_scn = 3;
+  static const uint8_t test_peer_scn = 10;
+  // Must be smaller than L2CAP_MTU_SIZE by at least 4 bytes
+  static const uint16_t test_mtu = 1000;
+  static const RawAddress test_address = GetTestAddress(0);
+  uint16_t server_handle = 0;
+  VLOG(1) << "Step 1";
+  // Prepare a server port
+  int status = RFCOMM_CreateConnection(test_uuid, test_server_scn, true,
+                                       test_mtu, RawAddress::kAny,
+                                       &server_handle, port_mgmt_cback_0);
+  ASSERT_EQ(status, PORT_SUCCESS);
+  status = PORT_SetEventMask(server_handle, PORT_EV_RXCHAR);
+  ASSERT_EQ(status, PORT_SUCCESS);
+  status = PORT_SetEventCallback(server_handle, port_event_cback_0);
+  ASSERT_EQ(status, PORT_SUCCESS);
+
+  VLOG(1) << "Step 2";
+  // Try to connect to a client port
+  uint16_t client_handle_1 = 0;
+  EXPECT_CALL(l2cap_interface_, ConnectRequest(BT_PSM_RFCOMM, test_address))
+      .Times(1)
+      .WillOnce(Return(old_lcid));
+  status = RFCOMM_CreateConnection(test_uuid, test_peer_scn, false, test_mtu,
+                                   test_address, &client_handle_1,
+                                   port_mgmt_cback_1);
+  ASSERT_EQ(status, PORT_SUCCESS);
+  status = PORT_SetEventMask(client_handle_1, PORT_EV_RXCHAR);
+  ASSERT_EQ(status, PORT_SUCCESS);
+  status = PORT_SetEventCallback(client_handle_1, port_event_cback_1);
+  ASSERT_EQ(status, PORT_SUCCESS);
+
+  VLOG(1) << "Step 3";
+  // While our connection is pending, remote device tries to connect to
+  // new_lcid, with L2CAP command id: pending_cmd_id
+  static const uint8_t pending_cmd_id = 0x05;
+  // RFCOMM starts timer for collision:
+  l2cap_appl_info_.pL2CA_ConnectInd_Cb(test_address, new_lcid, BT_PSM_RFCOMM,
+                                       pending_cmd_id);
+
+  VLOG(1) << "Step 4";
+  // Remote reject our connection request saying PSM not allowed
+  // This should trigger RFCOMM to accept remote L2CAP connection at new_lcid
+  EXPECT_CALL(l2cap_interface_, ConnectResponse(test_address, pending_cmd_id,
+                                                new_lcid, L2CAP_CONN_OK, 0))
+      .WillOnce(Return(true));
+  // Followed by configure request for MTU size
+  tL2CAP_CFG_INFO our_cfg_req = {.mtu_present = true, .mtu = L2CAP_MTU_SIZE};
+  EXPECT_CALL(l2cap_interface_,
+              ConfigRequest(new_lcid, PointerMemoryEqual(&our_cfg_req)))
+      .WillOnce(Return(true));
+  l2cap_appl_info_.pL2CA_ConnectCfm_Cb(old_lcid, L2CAP_CONN_NO_PSM);
+
+  VLOG(1) << "Step 5";
+  // Remote device also ask to configure MTU size as well
+  tL2CAP_CFG_INFO peer_cfg_req = {.mtu_present = true, .mtu = test_mtu};
+  // We responded by saying OK
+  tL2CAP_CFG_INFO our_cfg_rsp = {.result = L2CAP_CFG_OK,
+                                 .mtu = peer_cfg_req.mtu};
+  EXPECT_CALL(l2cap_interface_,
+              ConfigResponse(new_lcid, PointerMemoryEqual(&our_cfg_rsp)))
+      .WillOnce(Return(true));
+  l2cap_appl_info_.pL2CA_ConfigInd_Cb(new_lcid, &peer_cfg_req);
+
+  VLOG(1) << "Step 6";
+  // Remote device accepted our MTU size
+  tL2CAP_CFG_INFO peer_cfg_rsp = {.mtu_present = true, .mtu = L2CAP_MTU_SIZE};
+  l2cap_appl_info_.pL2CA_ConfigCfm_Cb(new_lcid, &peer_cfg_rsp);
+
+  // L2CAP collision and connection setup done
+
+  VLOG(1) << "Step 7";
+  // Remote device connect multiplexer channel
+  BT_HDR* sabm_channel_0 = AllocateWrappedIncomingL2capAclPacket(
+      CreateQuickSabmPacket(RFCOMM_MX_DLCI, new_lcid, acl_handle));
+  // We accept
+  BT_HDR* ua_channel_0 = AllocateWrappedOutgoingL2capAclPacket(
+      CreateQuickUaPacket(RFCOMM_MX_DLCI, new_lcid, acl_handle));
+  EXPECT_CALL(l2cap_interface_, DataWrite(new_lcid, BtHdrEqual(ua_channel_0)))
+      .WillOnce(Return(L2CAP_DW_SUCCESS));
+  // And immediately try to configure test_peer_scn
+  BT_HDR* uih_pn_cmd_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+      CreateQuickPnPacket(false, GetDlci(true, test_peer_scn), true, test_mtu,
+                          RFCOMM_PN_CONV_LAYER_CBFC_I >> 4, 0, RFCOMM_K_MAX,
+                          new_lcid, acl_handle));
+  EXPECT_CALL(l2cap_interface_,
+              DataWrite(new_lcid, BtHdrEqual(uih_pn_cmd_to_peer)))
+      .WillOnce(Return(L2CAP_DW_SUCCESS));
+  // Packet should be freed by this method
+  l2cap_appl_info_.pL2CA_DataInd_Cb(new_lcid, sabm_channel_0);
+  osi_free(ua_channel_0);
+  osi_free(uih_pn_cmd_to_peer);
+
+  VLOG(1) << "Step 8";
+  // Peer tries to configure test_server_scn
+  BT_HDR* uih_pn_cmd_from_peer = AllocateWrappedIncomingL2capAclPacket(
+      CreateQuickPnPacket(true, GetDlci(false, test_server_scn), true, test_mtu,
+                          RFCOMM_PN_CONV_LAYER_CBFC_I >> 4, 0, RFCOMM_K_MAX,
+                          new_lcid, acl_handle));
+  // We, as acceptor, must accept
+  BT_HDR* uih_pn_rsp_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+      CreateQuickPnPacket(false, GetDlci(false, test_server_scn), false,
+                          test_mtu, RFCOMM_PN_CONV_LAYER_CBFC_R >> 4, 0,
+                          RFCOMM_K_MAX, new_lcid, acl_handle));
+  EXPECT_CALL(l2cap_interface_,
+              DataWrite(new_lcid, BtHdrEqual(uih_pn_rsp_to_peer)))
+      .Times(1)
+      .WillOnce(Return(L2CAP_DW_SUCCESS));
+  l2cap_appl_info_.pL2CA_DataInd_Cb(new_lcid, uih_pn_cmd_from_peer);
+  osi_free(uih_pn_rsp_to_peer);
+
+  VLOG(1) << "Step 9";
+  // Remote never replies our configuration request for test_peer_scn
+  // But instead connect to test_server_scn directly
+  BT_HDR* sabm_server_scn =
+      AllocateWrappedIncomingL2capAclPacket(CreateQuickSabmPacket(
+          GetDlci(false, test_server_scn), new_lcid, acl_handle));
+  // We must do security check first
+  tBTM_SEC_CALLBACK* security_callback = nullptr;
+  void* p_port = nullptr;
+  EXPECT_CALL(btm_security_internal_interface_,
+              MultiplexingProtocolAccessRequest(
+                  test_address, BT_PSM_RFCOMM, false, BTM_SEC_PROTO_RFCOMM,
+                  test_server_scn, NotNull(), NotNull()))
+      .WillOnce(DoAll(SaveArg<5>(&security_callback), SaveArg<6>(&p_port),
+                      Return(BTM_SUCCESS)));
+  l2cap_appl_info_.pL2CA_DataInd_Cb(new_lcid, sabm_server_scn);
+
+  VLOG(1) << "Step 10";
+  // After security check, we accept the connection
+  ASSERT_TRUE(security_callback);
+  BT_HDR* ua_server_scn =
+      AllocateWrappedOutgoingL2capAclPacket(CreateQuickUaPacket(
+          GetDlci(false, test_server_scn), new_lcid, acl_handle));
+  EXPECT_CALL(l2cap_interface_, DataWrite(new_lcid, BtHdrEqual(ua_server_scn)))
+      .WillOnce(Return(L2CAP_DW_SUCCESS));
+  // Callback should come from server port instead, client port will timeout
+  // in 20 seconds
+  EXPECT_CALL(rfcomm_callback_,
+              PortManagementCallback(PORT_SUCCESS, server_handle, 0));
+  security_callback(&test_address, BT_TRANSPORT_BR_EDR, p_port, BTM_SUCCESS);
+  osi_free(ua_server_scn);
+
+  VLOG(1) << "Step 11";
+  // MPX_CTRL Modem Status Command (MSC)
+  BT_HDR* uih_msc_cmd_from_peer = AllocateWrappedIncomingL2capAclPacket(
+      CreateQuickMscPacket(true, GetDlci(false, test_server_scn), new_lcid,
+                           acl_handle, true, false, true, true, false, true));
+  BT_HDR* uih_msc_rsp_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+      CreateQuickMscPacket(false, GetDlci(false, test_server_scn), new_lcid,
+                           acl_handle, false, false, true, true, false, true));
+  // MPX_CTRL Modem Status Response (MSC)
+  EXPECT_CALL(l2cap_interface_,
+              DataWrite(new_lcid, BtHdrEqual(uih_msc_rsp_to_peer)))
+      .WillOnce(Return(L2CAP_DW_SUCCESS));
+  BT_HDR* uih_msc_cmd_to_peer = AllocateWrappedOutgoingL2capAclPacket(
+      CreateQuickMscPacket(false, GetDlci(false, test_server_scn), new_lcid,
+                           acl_handle, true, false, true, true, false, true));
+  EXPECT_CALL(l2cap_interface_,
+              DataWrite(new_lcid, BtHdrEqual(uih_msc_cmd_to_peer)))
+      .WillOnce(Return(L2CAP_DW_SUCCESS));
+  l2cap_appl_info_.pL2CA_DataInd_Cb(new_lcid, uih_msc_cmd_from_peer);
+  osi_free(uih_msc_rsp_to_peer);
+  osi_free(uih_msc_cmd_to_peer);
+
+  VLOG(1) << "Step 12";
+  BT_HDR* uih_msc_rsp_from_peer = AllocateWrappedIncomingL2capAclPacket(
+      CreateQuickMscPacket(true, GetDlci(false, test_server_scn), new_lcid,
+                           acl_handle, false, false, true, true, false, true));
+  l2cap_appl_info_.pL2CA_DataInd_Cb(new_lcid, uih_msc_rsp_from_peer);
+}
+
 }  // namespace