Remove rfcomm_security_records map, store records in tBTA_JV_PCB instead.

The map is globally keyed by SCN, which causes issues when SCNs are
reused (server vs client, or different device connections). tBTA_JV_PCBs
are distinct for every (port, device, server/client) tuple, and so fit
this use-case.

Tag: #stability
Bug: 230553684
Test: Manual (see bug)
Change-Id: Iae24f07fd5d19f66126abfe61052fab96d1b1bdf
diff --git a/system/bta/ag/bta_ag_sdp.cc b/system/bta/ag/bta_ag_sdp.cc
index e9af15c..bb39a43 100644
--- a/system/bta/ag/bta_ag_sdp.cc
+++ b/system/bta/ag/bta_ag_sdp.cc
@@ -271,7 +271,6 @@
         bta_ag_cb.profile[i].sdp_handle = 0;
       }
       BTM_FreeSCN(bta_ag_cb.profile[i].scn);
-      RFCOMM_ClearSecurityRecord(bta_ag_cb.profile[i].scn);
       bta_sys_remove_uuid(bta_ag_uuid[i]);
     }
   }
diff --git a/system/bta/hf_client/bta_hf_client_sdp.cc b/system/bta/hf_client/bta_hf_client_sdp.cc
index 96b7a6d..4625b6d 100755
--- a/system/bta/hf_client/bta_hf_client_sdp.cc
+++ b/system/bta/hf_client/bta_hf_client_sdp.cc
@@ -204,7 +204,6 @@
     SDP_DeleteRecord(client_cb->sdp_handle);
     client_cb->sdp_handle = 0;
     BTM_FreeSCN(client_cb->scn);
-    RFCOMM_ClearSecurityRecord(client_cb->scn);
     bta_sys_remove_uuid(UUID_SERVCLASS_HF_HANDSFREE);
   }
 }
diff --git a/system/bta/jv/bta_jv_act.cc b/system/bta/jv/bta_jv_act.cc
index 6f50077..db8b05c 100644
--- a/system/bta/jv/bta_jv_act.cc
+++ b/system/bta/jv/bta_jv_act.cc
@@ -317,15 +317,11 @@
     p_pcb->handle = 0;
     p_cb->curr_sess--;
     if (p_cb->curr_sess == 0) {
-      RFCOMM_ClearSecurityRecord(p_cb->scn);
       p_cb->scn = 0;
       p_cb->p_cback = NULL;
       p_cb->handle = 0;
       p_cb->curr_sess = -1;
     }
-    if (remove_server) {
-      RFCOMM_ClearSecurityRecord(p_cb->scn);
-    }
   }
   return status;
 }
@@ -1356,7 +1352,6 @@
   bta_jv.rfc_cl_init = evt_data;
   p_cback(BTA_JV_RFCOMM_CL_INIT_EVT, &bta_jv, rfcomm_slot_id);
   if (bta_jv.rfc_cl_init.status == BTA_JV_FAILURE) {
-    RFCOMM_ClearSecurityRecord(remote_scn);
     if (handle) RFCOMM_RemoveConnection(handle);
   }
 }
@@ -1532,6 +1527,7 @@
   tPORT_STATE port_state;
   uint32_t event_mask = BTA_JV_RFC_EV_MASK;
   tBTA_JV_PCB* p_pcb = NULL;
+  tBTA_SEC sec_mask;
   if (p_cb->max_sess > 1) {
     for (i = 0; i < p_cb->max_sess; i++) {
       if (p_cb->rfc_hdl[i] != 0) {
@@ -1562,10 +1558,16 @@
             << ", si=" << si;
     if (used < p_cb->max_sess && listen == 1 && si) {
       si--;
-      if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, true,
-                                  BTA_JV_DEF_RFC_MTU, RawAddress::kAny,
-                                  &(p_cb->rfc_hdl[si]),
-                                  bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS) {
+      if (PORT_GetSecurityMask(p_pcb_open->port_handle, &sec_mask) !=
+          PORT_SUCCESS) {
+        LOG(ERROR) << __func__
+                   << ": RFCOMM_CreateConnection failed: invalid port_handle";
+      }
+
+      if (RFCOMM_CreateConnectionWithSecurity(
+              p_cb->sec_id, p_cb->scn, true, BTA_JV_DEF_RFC_MTU,
+              RawAddress::kAny, &(p_cb->rfc_hdl[si]), bta_jv_port_mgmt_sr_cback,
+              sec_mask) == PORT_SUCCESS) {
         p_cb->curr_sess++;
         p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1];
         p_pcb->state = BTA_JV_ST_SR_LISTEN;
@@ -1652,7 +1654,6 @@
   if (bta_jv.rfc_start.status == BTA_JV_SUCCESS) {
     PORT_SetDataCOCallback(handle, bta_jv_port_data_co_cback);
   } else {
-    RFCOMM_ClearSecurityRecord(local_scn);
     if (handle) RFCOMM_RemoveConnection(handle);
   }
 }
diff --git a/system/stack/include/btm_api_types.h b/system/stack/include/btm_api_types.h
index 3e68f46..ec49380 100644
--- a/system/stack/include/btm_api_types.h
+++ b/system/stack/include/btm_api_types.h
@@ -283,6 +283,7 @@
   }
 }
 
+/* BTM_SEC security masks */
 enum : uint16_t {
   /* Nothing required */
   BTM_SEC_NONE = 0x0000,
diff --git a/system/stack/include/port_api.h b/system/stack/include/port_api.h
index 832832f..ed4733a 100644
--- a/system/stack/include/port_api.h
+++ b/system/stack/include/port_api.h
@@ -191,13 +191,6 @@
                                                tPORT_CALLBACK* p_mgmt_cb,
                                                uint16_t sec_mask);
 
-extern void RFCOMM_ClearSecurityRecord(uint32_t scn);
-
-extern int RFCOMM_CreateConnection(uint16_t uuid, uint8_t scn, bool is_server,
-                                   uint16_t mtu, const RawAddress& bd_addr,
-                                   uint16_t* p_handle,
-                                   tPORT_CALLBACK* p_mgmt_cb);
-
 /*******************************************************************************
  *
  * Function         RFCOMM_RemoveConnection
@@ -434,4 +427,15 @@
  ******************************************************************************/
 extern const char* PORT_GetResultString(const uint8_t result_code);
 
+/*******************************************************************************
+ *
+ * Function         PORT_GetSecurityMask
+ *
+ * Description      This function returns the security bitmask for a port.
+ *
+ * Returns          the security bitmask.
+ *
+ ******************************************************************************/
+extern int PORT_GetSecurityMask(uint16_t handle, uint16_t* sec_mask);
+
 #endif /* PORT_API_H */
diff --git a/system/stack/rfcomm/port_api.cc b/system/stack/rfcomm/port_api.cc
index cca0f05..3af79ab 100644
--- a/system/stack/rfcomm/port_api.cc
+++ b/system/stack/rfcomm/port_api.cc
@@ -71,30 +71,13 @@
                                             "Invalid SCN",
                                             "Unknown result code"};
 
-int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn,
-                                        bool is_server, uint16_t mtu,
-                                        const RawAddress& bd_addr,
-                                        uint16_t* p_handle,
-                                        tPORT_CALLBACK* p_mgmt_cb,
-                                        uint16_t sec_mask) {
-  rfcomm_security_records[scn] = sec_mask;
-
-  return RFCOMM_CreateConnection(uuid, scn, is_server, mtu, bd_addr, p_handle,
-                                 p_mgmt_cb);
-}
-
-extern void RFCOMM_ClearSecurityRecord(uint32_t scn) {
-  rfcomm_security_records.erase(scn);
-}
-
 /*******************************************************************************
  *
- * Function         RFCOMM_CreateConnection
+ * Function         RFCOMM_CreateConnectionWithSecurity
  *
- * Description      RFCOMM_CreateConnection function is used from the
- *                  application to establish serial port connection to the peer
- *                  device, or allow RFCOMM to accept a connection from the peer
- *                  application.
+ * Description      RFCOMM_CreateConnectionWithSecurity function is used from
+ *the application to establish serial port connection to the peer device, or
+ *allow RFCOMM to accept a connection from the peer application.
  *
  * Parameters:      scn          - Service Channel Number as registered with
  *                                 the SDP (server) or obtained using SDP from
@@ -102,12 +85,12 @@
  *                  is_server    - true if requesting application is a server
  *                  mtu          - Maximum frame size the application can accept
  *                  bd_addr      - address of the peer (client)
- *                  mask         - specifies events to be enabled.  A value
- *                                 of zero disables all events.
  *                  p_handle     - OUT pointer to the handle.
  *                  p_mgmt_cb    - pointer to callback function to receive
  *                                 connection up/down events.
- * Notes:
+ *                  sec_mask     - bitmask of BTM_SEC_* values indicating the
+ *                                 minimum security requirements for this
+ *connection Notes:
  *
  * Server can call this function with the same scn parameter multiple times if
  * it is ready to accept multiple simulteneous connections.
@@ -118,9 +101,12 @@
  * (scn * 2 + 1) dlci.
  *
  ******************************************************************************/
-int RFCOMM_CreateConnection(uint16_t uuid, uint8_t scn, bool is_server,
-                            uint16_t mtu, const RawAddress& bd_addr,
-                            uint16_t* p_handle, tPORT_CALLBACK* p_mgmt_cb) {
+int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn,
+                                        bool is_server, uint16_t mtu,
+                                        const RawAddress& bd_addr,
+                                        uint16_t* p_handle,
+                                        tPORT_CALLBACK* p_mgmt_cb,
+                                        uint16_t sec_mask) {
   *p_handle = 0;
 
   if ((scn == 0) || (scn >= PORT_MAX_RFC_PORTS)) {
@@ -176,6 +162,7 @@
                << ", dlci=" << +dlci;
     return PORT_NO_RESOURCES;
   }
+  p_port->sec_mask = sec_mask;
   *p_handle = p_port->handle;
 
   // Get default signal state
@@ -1126,7 +1113,6 @@
  ******************************************************************************/
 void RFCOMM_Init(void) {
   memset(&rfc_cb, 0, sizeof(tRFC_CB)); /* Init RFCOMM control block */
-  rfcomm_security_records = {};
   rfc_lcid_mcb = {};
 
   rfc_cb.rfc.last_mux = MAX_BD_CONNECTIONS;
@@ -1173,3 +1159,23 @@
 
   return result_code_strings[result_code];
 }
+
+/*******************************************************************************
+ *
+ * Function         PORT_GetSecurityMask
+ *
+ * Description      This function returns the security bitmask for a port.
+ *
+ * Returns          A result code, and writes the bitmask into the output
+ *parameter.
+ *
+ ******************************************************************************/
+int PORT_GetSecurityMask(uint16_t handle, uint16_t* sec_mask) {
+  /* Check if handle is valid to avoid crashing */
+  if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
+    return (PORT_BAD_HANDLE);
+  }
+  tPORT* p_port = &rfc_cb.port.port[handle - 1];
+  *sec_mask = p_port->sec_mask;
+  return (PORT_SUCCESS);
+}
diff --git a/system/stack/rfcomm/port_int.h b/system/stack/rfcomm/port_int.h
index e406d4a..61935b1 100644
--- a/system/stack/rfcomm/port_int.h
+++ b/system/stack/rfcomm/port_int.h
@@ -189,6 +189,8 @@
   bool keep_port_handle;    /* true if port is not deallocated when closing */
   /* it is set to true for server when allocating port */
   uint16_t keep_mtu; /* Max MTU that port can receive by server */
+  uint16_t sec_mask; /* Bitmask of security requirements for this port */
+                     /* see the BTM_SEC_* values in btm_api_types.h */
 } tPORT;
 
 /* Define the PORT/RFCOMM control structure
diff --git a/system/stack/rfcomm/rfc_int.h b/system/stack/rfcomm/rfc_int.h
index 61706a2..f07485e 100644
--- a/system/stack/rfcomm/rfc_int.h
+++ b/system/stack/rfcomm/rfc_int.h
@@ -179,9 +179,6 @@
 
 extern tRFC_CB rfc_cb;
 
-extern std::unordered_map<uint32_t /* scn */, uint16_t /* sec_mask */>
-    rfcomm_security_records;
-
 /* MCB based on the L2CAP's lcid */
 extern std::unordered_map<uint16_t /* cid */, tRFC_MCB*> rfc_lcid_mcb;
 
diff --git a/system/stack/rfcomm/rfc_port_fsm.cc b/system/stack/rfcomm/rfc_port_fsm.cc
index 7c751d1..cd5cbb9 100644
--- a/system/stack/rfcomm/rfc_port_fsm.cc
+++ b/system/stack/rfcomm/rfc_port_fsm.cc
@@ -122,18 +122,12 @@
  ******************************************************************************/
 void rfc_port_sm_state_closed(tPORT* p_port, tRFC_PORT_EVENT event,
                               void* p_data) {
-  uint32_t scn = (uint32_t)(p_port->dlci / 2);
   switch (event) {
     case RFC_PORT_EVENT_OPEN:
       p_port->rfc.state = RFC_STATE_ORIG_WAIT_SEC_CHECK;
-      if (rfcomm_security_records.count(scn) == 0) {
-        rfc_sec_check_complete(nullptr, BT_TRANSPORT_BR_EDR, p_port,
-                               BTM_NO_RESOURCES);
-        return;
-      }
       btm_sec_mx_access_request(p_port->rfc.p_mcb->bd_addr, true,
-                                rfcomm_security_records[scn],
-                                &rfc_sec_check_complete, p_port);
+                                p_port->sec_mask, &rfc_sec_check_complete,
+                                p_port);
       return;
 
     case RFC_PORT_EVENT_CLOSE:
@@ -153,14 +147,9 @@
 
       /* Open will be continued after security checks are passed */
       p_port->rfc.state = RFC_STATE_TERM_WAIT_SEC_CHECK;
-      if (rfcomm_security_records.count(scn) == 0) {
-        rfc_sec_check_complete(nullptr, BT_TRANSPORT_BR_EDR, p_port,
-                               BTM_NO_RESOURCES);
-        return;
-      }
       btm_sec_mx_access_request(p_port->rfc.p_mcb->bd_addr, true,
-                                rfcomm_security_records[scn],
-                                &rfc_sec_check_complete, p_port);
+                                p_port->sec_mask, &rfc_sec_check_complete,
+                                p_port);
       return;
 
     case RFC_PORT_EVENT_UA:
diff --git a/system/stack/rfcomm/rfc_port_if.cc b/system/stack/rfcomm/rfc_port_if.cc
index 300d848..5ef820e 100644
--- a/system/stack/rfcomm/rfc_port_if.cc
+++ b/system/stack/rfcomm/rfc_port_if.cc
@@ -33,7 +33,6 @@
 #include "stack/rfcomm/rfc_int.h"
 
 tRFC_CB rfc_cb;
-std::unordered_map<uint32_t, uint16_t> rfcomm_security_records;
 std::unordered_map<uint16_t /* sci */, tRFC_MCB*> rfc_lcid_mcb;
 
 /*******************************************************************************
diff --git a/system/stack/test/rfcomm/stack_rfcomm_test.cc b/system/stack/test/rfcomm/stack_rfcomm_test.cc
index 8501674..f0812ce 100644
--- a/system/stack/test/rfcomm/stack_rfcomm_test.cc
+++ b/system/stack/test/rfcomm/stack_rfcomm_test.cc
@@ -135,8 +135,9 @@
                        tPORT_CALLBACK* event_callback,
                        uint16_t* server_handle) {
     VLOG(1) << "Step 1";
-    ASSERT_EQ(RFCOMM_CreateConnection(uuid, scn, true, mtu, RawAddress::kAny,
-                                      server_handle, management_callback),
+    ASSERT_EQ(RFCOMM_CreateConnectionWithSecurity(
+                  uuid, scn, true, mtu, RawAddress::kAny, server_handle,
+                  management_callback, 0),
               PORT_SUCCESS);
     ASSERT_EQ(PORT_SetEventMask(*server_handle, PORT_EV_RXCHAR), PORT_SUCCESS);
     ASSERT_EQ(PORT_SetEventCallback(*server_handle, event_callback),
@@ -280,8 +281,9 @@
                   DataWrite(lcid, BtHdrEqual(uih_pn_channel_3)))
           .WillOnce(Return(L2CAP_DW_SUCCESS));
     }
-    ASSERT_EQ(RFCOMM_CreateConnection(uuid, scn, false, mtu, peer_bd_addr,
-                                      client_handle, management_callback),
+    ASSERT_EQ(RFCOMM_CreateConnectionWithSecurity(uuid, scn, false, mtu,
+                                                  peer_bd_addr, client_handle,
+                                                  management_callback, 0),
               PORT_SUCCESS);
     ASSERT_EQ(PORT_SetEventMask(*client_handle, PORT_EV_RXCHAR), PORT_SUCCESS);
     ASSERT_EQ(PORT_SetEventCallback(*client_handle, event_callback),
@@ -724,9 +726,9 @@
   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);
+  int status = RFCOMM_CreateConnectionWithSecurity(
+      test_uuid, test_server_scn, true, test_mtu, RawAddress::kAny,
+      &server_handle, port_mgmt_cback_0, 0);
   ASSERT_EQ(status, PORT_SUCCESS);
   status = PORT_SetEventMask(server_handle, PORT_EV_RXCHAR);
   ASSERT_EQ(status, PORT_SUCCESS);
@@ -739,9 +741,9 @@
   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);
+  status = RFCOMM_CreateConnectionWithSecurity(
+      test_uuid, test_peer_scn, false, test_mtu, test_address, &client_handle_1,
+      port_mgmt_cback_1, 0);
   ASSERT_EQ(status, PORT_SUCCESS);
   status = PORT_SetEventMask(client_handle_1, PORT_EV_RXCHAR);
   ASSERT_EQ(status, PORT_SUCCESS);
diff --git a/system/test/mock/mock_stack_rfcomm_port_api.cc b/system/test/mock/mock_stack_rfcomm_port_api.cc
index ba070c4..ddc169a 100644
--- a/system/test/mock/mock_stack_rfcomm_port_api.cc
+++ b/system/test/mock/mock_stack_rfcomm_port_api.cc
@@ -98,12 +98,6 @@
   mock_function_count_map[__func__]++;
   return 0;
 }
-int RFCOMM_CreateConnection(uint16_t uuid, uint8_t scn, bool is_server,
-                            uint16_t mtu, const RawAddress& bd_addr,
-                            uint16_t* p_handle, tPORT_CALLBACK* p_mgmt_cb) {
-  mock_function_count_map[__func__]++;
-  return 0;
-}
 int RFCOMM_CreateConnectionWithSecurity(uint16_t uuid, uint8_t scn,
                                         bool is_server, uint16_t mtu,
                                         const RawAddress& bd_addr,
@@ -125,7 +119,8 @@
   mock_function_count_map[__func__]++;
   return 0;
 }
-void RFCOMM_ClearSecurityRecord(uint32_t scn) {
+int PORT_GetSecurityMask(uint16_t handle, uint16_t* sec_mask) {
   mock_function_count_map[__func__]++;
+  return 0;
 }
 void RFCOMM_Init(void) { mock_function_count_map[__func__]++; }