Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0112684d authored by William Escande's avatar William Escande Committed by Gerrit Code Review
Browse files

Merge changes from topic "convergence_sdp_serialization"

* changes:
  SDP: split the sdpu_process_pend_ccb
  SDP Use reference instead of int / pointer
  SDP code cleanup duplication
  SDP: TEST Handle race condition in HID SDP
  SDP: Handle race condition in HID SDP
  SDP: TEST Serialize sdp connections from profiles
  SDP: Serialize sdp connections from profiles/BT APP
  Prepare SDP for convergence
parents 7cb623f1 9bb77245
Loading
Loading
Loading
Loading
+16 −3
Original line number Diff line number Diff line
@@ -1286,7 +1286,12 @@ cc_test {
// Bluetooth stack connection multiplexing
cc_test {
    name: "net_test_stack_sdp",
    defaults: ["fluoride_defaults"],
    test_suites: ["device-tests"],
    host_supported: true,
    defaults: [
        "fluoride_defaults",
        "mts_defaults",
    ],
    local_include_dirs: [
        "include",
        "test/common",
@@ -1300,10 +1305,18 @@ cc_test {
    ],
    srcs: [
        ":TestCommonMockFunctions",
        ":TestMockBtif",
        ":TestMockOsi",
        ":TestMockStackL2cap",
        ":TestMockStackMetrics",
        "sdp/sdp_api.cc",
        "sdp/sdp_discovery.cc",
        "sdp/sdp_server.cc",
        "sdp/sdp_db.cc",
        "sdp/sdp_main.cc",
        "sdp/sdp_utils.cc",
        "test/common/mock_btif_config.cc",
        "test/stack_sdp_utils_test.cc",
        "test/sdp/stack_sdp_test.cc",
        "test/sdp/stack_sdp_utils_test.cc",
    ],
    shared_libs: [
        "libcutils",
+56 −47
Original line number Diff line number Diff line
@@ -256,20 +256,23 @@ static void sdp_disconnect_ind(uint16_t l2cap_cid, bool ack_needed) {
    SDP_TRACE_WARNING("SDP - Rcvd L2CAP disc, unknown CID: 0x%x", l2cap_cid);
    return;
  }
  tCONN_CB& ccb = *p_ccb;

  SDP_TRACE_EVENT("SDP - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
  /* Tell the user if there is a callback */
  if (p_ccb->p_cb)
    (*p_ccb->p_cb)(((p_ccb->con_state == SDP_STATE_CONNECTED)
                        ? SDP_SUCCESS
                        : SDP_CONN_FAILED));
  else if (p_ccb->p_cb2)
    (*p_ccb->p_cb2)(
        ((p_ccb->con_state == SDP_STATE_CONNECTED) ? SDP_SUCCESS
                                                   : SDP_CONN_FAILED),
        p_ccb->user_data);
  const tSDP_REASON reason =
      (ccb.con_state == SDP_STATE_CONNECTED) ? SDP_SUCCESS : SDP_CONN_FAILED;
  sdpu_callback(ccb, reason);

  sdpu_release_ccb(p_ccb);
  if (ack_needed) {
    SDP_TRACE_WARNING("SDP - Rcvd L2CAP disc, process pend sdp ccb: 0x%x",
                      l2cap_cid);
    sdpu_process_pend_ccb_new_cid(ccb);
  } else {
    SDP_TRACE_WARNING("SDP - Rcvd L2CAP disc, clear pend sdp ccb: 0x%x",
                      l2cap_cid);
    sdpu_clear_pend_ccb(ccb);
  }

  sdpu_release_ccb(ccb);
}

/*******************************************************************************
@@ -345,13 +348,23 @@ tCONN_CB* sdp_conn_originate(const RawAddress& p_bd_addr) {
   */
  p_ccb->con_state = SDP_STATE_CONN_SETUP;

  // Look for any active sdp connection on the remote device
  cid = sdpu_get_active_ccb_cid(p_bd_addr);

  if (cid == 0) {
    p_ccb->con_state = SDP_STATE_CONN_SETUP;
    cid = L2CA_ConnectReq2(BT_PSM_SDP, p_bd_addr, BTM_SEC_NONE);
  } else {
    p_ccb->con_state = SDP_STATE_CONN_PEND;
    SDP_TRACE_WARNING("SDP already active for peer %s. cid=%#0x",
                      p_bd_addr.ToString().c_str(), cid);
  }

  /* Check if L2CAP started the connection process */
  if (cid == 0) {
    SDP_TRACE_WARNING("%s: SDP - Originate failed for peer %s", __func__,
                      p_bd_addr.ToString().c_str());
    sdpu_release_ccb(p_ccb);
    sdpu_release_ccb(*p_ccb);
    return (NULL);
  }
  p_ccb->connection_id = cid;
@@ -368,24 +381,26 @@ tCONN_CB* sdp_conn_originate(const RawAddress& p_bd_addr) {
 *
 ******************************************************************************/
void sdp_disconnect(tCONN_CB* p_ccb, tSDP_REASON reason) {
  SDP_TRACE_EVENT("SDP - disconnect  CID: 0x%x", p_ccb->connection_id);
  tCONN_CB& ccb = *p_ccb;
  SDP_TRACE_EVENT("SDP - disconnect  CID: 0x%x", ccb.connection_id);

  /* Check if we have a connection ID */
  if (p_ccb->connection_id != 0) {
    L2CA_DisconnectReq(p_ccb->connection_id);
    p_ccb->disconnect_reason = reason;
  if (ccb.connection_id != 0) {
    ccb.disconnect_reason = reason;
    if (SDP_SUCCESS == reason && sdpu_process_pend_ccb_same_cid(*p_ccb)) {
      sdpu_callback(ccb, reason);
      sdpu_release_ccb(ccb);
      return;
    } else {
      L2CA_DisconnectReq(ccb.connection_id);
    }
  }

  /* If at setup state, we may not get callback ind from L2CAP */
  /* Call user callback immediately */
  if (p_ccb->con_state == SDP_STATE_CONN_SETUP) {
    /* Tell the user if there is a callback */
    if (p_ccb->p_cb)
      (*p_ccb->p_cb)(reason);
    else if (p_ccb->p_cb2)
      (*p_ccb->p_cb2)(reason, p_ccb->user_data);

    sdpu_release_ccb(p_ccb);
  if (ccb.con_state == SDP_STATE_CONN_SETUP) {
    sdpu_callback(ccb, reason);
    sdpu_release_ccb(ccb);
  }
}

@@ -409,17 +424,13 @@ static void sdp_disconnect_cfm(uint16_t l2cap_cid,
                      l2cap_cid);
    return;
  }
  tCONN_CB& ccb = *p_ccb;

  SDP_TRACE_EVENT("SDP - Rcvd L2CAP disc cfm, CID: 0x%x", l2cap_cid);

  /* Tell the user if there is a callback */
  if (p_ccb->p_cb)
    (*p_ccb->p_cb)(static_cast<tSDP_STATUS>(p_ccb->disconnect_reason));
  else if (p_ccb->p_cb2)
    (*p_ccb->p_cb2)(static_cast<tSDP_STATUS>(p_ccb->disconnect_reason),
                    p_ccb->user_data);

  sdpu_release_ccb(p_ccb);
  sdpu_callback(ccb, static_cast<tSDP_STATUS>(ccb.disconnect_reason));
  sdpu_process_pend_ccb_new_cid(ccb);
  sdpu_release_ccb(ccb);
}

/*******************************************************************************
@@ -433,16 +444,14 @@ static void sdp_disconnect_cfm(uint16_t l2cap_cid,
 *
 ******************************************************************************/
void sdp_conn_timer_timeout(void* data) {
  tCONN_CB* p_ccb = (tCONN_CB*)data;

  SDP_TRACE_EVENT("SDP - CCB timeout in state: %d  CID: 0x%x", p_ccb->con_state,
                  p_ccb->connection_id);

  L2CA_DisconnectReq(p_ccb->connection_id);
  /* Tell the user if there is a callback */
  if (p_ccb->p_cb)
    (*p_ccb->p_cb)(SDP_CONN_FAILED);
  else if (p_ccb->p_cb2)
    (*p_ccb->p_cb2)(SDP_CONN_FAILED, p_ccb->user_data);
  sdpu_release_ccb(p_ccb);
  tCONN_CB& ccb = *(tCONN_CB*)data;

  SDP_TRACE_EVENT("SDP - CCB timeout in state: %d  CID: 0x%x", ccb.con_state,
                  ccb.connection_id);

  L2CA_DisconnectReq(ccb.connection_id);

  sdpu_callback(ccb, SDP_CONN_FAILED);
  sdpu_clear_pend_ccb(ccb);
  sdpu_release_ccb(ccb);
}
+160 −7
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@
#include "stack/include/avrc_api.h"
#include "stack/include/avrc_defs.h"
#include "stack/include/bt_hdr.h"
#include "stack/include/btm_api_types.h"
#include "stack/include/sdp_api.h"
#include "stack/include/sdpdefs.h"
#include "stack/include/stack_metrics_logging.h"
@@ -320,9 +321,12 @@ tCONN_CB* sdpu_find_ccb_by_cid(uint16_t cid) {

  /* Look through each connection control block */
  for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
    if ((p_ccb->con_state != SDP_STATE_IDLE) && (p_ccb->connection_id == cid))
    if ((p_ccb->con_state != SDP_STATE_IDLE) &&
        (p_ccb->con_state != SDP_STATE_CONN_PEND) &&
        (p_ccb->connection_id == cid)) {
      return (p_ccb);
    }
  }

  /* If here, not found */
  return (NULL);
@@ -380,6 +384,23 @@ tCONN_CB* sdpu_allocate_ccb(void) {
  return (NULL);
}

/*******************************************************************************
 *
 * Function         sdpu_callback
 *
 * Description      Tell the user if they have a callback
 *
 * Returns          void
 *
 ******************************************************************************/
void sdpu_callback(tCONN_CB& ccb, tSDP_REASON reason) {
  if (ccb.p_cb) {
    (ccb.p_cb)(reason);
  } else if (ccb.p_cb2) {
    (ccb.p_cb2)(reason, ccb.user_data);
  }
}

/*******************************************************************************
 *
 * Function         sdpu_release_ccb
@@ -389,17 +410,149 @@ tCONN_CB* sdpu_allocate_ccb(void) {
 * Returns          void
 *
 ******************************************************************************/
void sdpu_release_ccb(tCONN_CB* p_ccb) {
void sdpu_release_ccb(tCONN_CB& ccb) {
  /* Ensure timer is stopped */
  alarm_cancel(p_ccb->sdp_conn_timer);
  alarm_cancel(ccb.sdp_conn_timer);

  /* Drop any response pointer we may be holding */
  p_ccb->con_state = SDP_STATE_IDLE;
  p_ccb->is_attr_search = false;
  ccb.con_state = SDP_STATE_IDLE;
  ccb.is_attr_search = false;

  /* Free the response buffer */
  if (p_ccb->rsp_list) SDP_TRACE_DEBUG("releasing SDP rsp_list");
  osi_free_and_reset((void**)&p_ccb->rsp_list);
  if (ccb.rsp_list) SDP_TRACE_DEBUG("releasing SDP rsp_list");
  osi_free_and_reset((void**)&ccb.rsp_list);
}

/*******************************************************************************
 *
 * Function         sdpu_get_active_ccb_cid
 *
 * Description      This function checks if any sdp connecting is there for
 *                  same remote and returns cid if its available
 *
 *                  RawAddress : Remote address
 *
 * Returns          returns cid if any active sdp connection, else 0.
 *
 ******************************************************************************/
uint16_t sdpu_get_active_ccb_cid(const RawAddress& remote_bd_addr) {
  uint16_t xx;
  tCONN_CB* p_ccb;

  // Look through each connection control block for active sdp on given remote
  for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
    if ((p_ccb->con_state == SDP_STATE_CONN_SETUP) ||
        (p_ccb->con_state == SDP_STATE_CFG_SETUP) ||
        (p_ccb->con_state == SDP_STATE_CONNECTED)) {
      if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG &&
          p_ccb->device_address == remote_bd_addr) {
        return p_ccb->connection_id;
      }
    }
  }

  // No active sdp channel for this remote
  return 0;
}

/*******************************************************************************
 *
 * Function         sdpu_process_pend_ccb
 *
 * Description      This function process if any sdp ccb pending for connection
 *                  and reuse the same connection id
 *
 *                  tCONN_CB&: connection control block that trigget the process
 *
 * Returns          returns true if any pending ccb, else false.
 *
 ******************************************************************************/
bool sdpu_process_pend_ccb_same_cid(tCONN_CB& ccb) {
  uint16_t xx;
  tCONN_CB* p_ccb;

  // Look through each connection control block for active sdp on given remote
  for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
    if ((p_ccb->con_state == SDP_STATE_CONN_PEND) &&
        (p_ccb->connection_id == ccb.connection_id) &&
        (p_ccb->con_flags & SDP_FLAGS_IS_ORIG)) {
      p_ccb->con_state = SDP_STATE_CONNECTED;
      sdp_disc_connected(p_ccb);
      return true;
    }
  }
  // No pending SDP channel for this remote
  return false;
}

/*******************************************************************************
 *
 * Function         sdpu_process_pend_ccb_new_cid
 *
 * Description      This function process if any sdp ccb pending for connection
 *                  and update their connection id with a new L2CA connection
 *
 *                  tCONN_CB&: connection control block that trigget the process
 *
 * Returns          returns true if any pending ccb, else false.
 *
 ******************************************************************************/
bool sdpu_process_pend_ccb_new_cid(tCONN_CB& ccb) {
  uint16_t xx;
  tCONN_CB* p_ccb;
  uint16_t new_cid = 0;
  bool new_conn = false;

  // Look through each ccb to replace the obsolete cid with a new one.
  for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
    if ((p_ccb->con_state == SDP_STATE_CONN_PEND) &&
        (p_ccb->connection_id == ccb.connection_id) &&
        (p_ccb->con_flags & SDP_FLAGS_IS_ORIG)) {
      if (!new_conn) {
        // Only change state of the first ccb
        p_ccb->con_state = SDP_STATE_CONN_SETUP;
        new_cid =
            L2CA_ConnectReq2(BT_PSM_SDP, p_ccb->device_address, BTM_SEC_NONE);
        new_conn = true;
      }
      // Check if L2CAP started the connection process
      if (new_cid != 0) {
        // update alls cid to the new one for future reference
        p_ccb->connection_id = new_cid;
      } else {
        sdpu_callback(*p_ccb, SDP_CONN_FAILED);
        sdpu_release_ccb(*p_ccb);
      }
    }
  }
  return new_conn && new_cid != 0;
}

/*******************************************************************************
 *
 * Function         sdpu_clear_pend_ccb
 *
 * Description      This function releases if any sdp ccb pending for connection
 *
 *                  uint16_t : Remote CID
 *
 * Returns          returns none.
 *
 ******************************************************************************/
void sdpu_clear_pend_ccb(tCONN_CB& ccb) {
  uint16_t xx;
  tCONN_CB* p_ccb;

  // Look through each connection control block for active sdp on given remote
  for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
    if ((p_ccb->con_state == SDP_STATE_CONN_PEND) &&
        (p_ccb->connection_id == ccb.connection_id) &&
        (p_ccb->con_flags & SDP_FLAGS_IS_ORIG)) {
      sdpu_callback(*p_ccb, SDP_CONN_FAILED);
      sdpu_release_ccb(*p_ccb);
    }
  }
  return;
}

/*******************************************************************************
+12 −3
Original line number Diff line number Diff line
@@ -123,11 +123,12 @@ typedef struct {
} tSDP_CONT_INFO;

/* Define the SDP Connection Control Block */
typedef struct {
struct tCONN_CB {
#define SDP_STATE_IDLE 0
#define SDP_STATE_CONN_SETUP 1
#define SDP_STATE_CFG_SETUP 2
#define SDP_STATE_CONNECTED 3
#define SDP_STATE_CONN_PEND 4
  uint8_t con_state;

#define SDP_FLAGS_IS_ORIG 0x01
@@ -166,8 +167,11 @@ typedef struct {
  uint16_t cont_offset;     /* Continuation state data in the server response */
  tSDP_CONT_INFO cont_info; /* structure to hold continuation information for
                               the server response */
  tCONN_CB() = default;

} tCONN_CB;
 private:
  tCONN_CB(const tCONN_CB&) = delete;
};

/*  The main SDP control block */
typedef struct {
@@ -199,7 +203,7 @@ extern void sdpu_log_attribute_metrics(const RawAddress& bda,
extern tCONN_CB* sdpu_find_ccb_by_cid(uint16_t cid);
extern tCONN_CB* sdpu_find_ccb_by_db(const tSDP_DISCOVERY_DB* p_db);
extern tCONN_CB* sdpu_allocate_ccb(void);
extern void sdpu_release_ccb(tCONN_CB* p_ccb);
extern void sdpu_release_ccb(tCONN_CB& p_ccb);

extern uint8_t* sdpu_build_attrib_seq(uint8_t* p_out, uint16_t* p_attr,
                                      uint16_t num_attrs);
@@ -236,6 +240,11 @@ extern bool sdpu_is_service_id_avrc_target(const tSDP_ATTRIBUTE* p_attr);
extern bool spdu_is_avrcp_version_valid(const uint16_t version);
extern void sdpu_set_avrc_target_version(const tSDP_ATTRIBUTE* p_attr,
                                         const RawAddress* bdaddr);
extern uint16_t sdpu_get_active_ccb_cid(const RawAddress& remote_bd_addr);
extern bool sdpu_process_pend_ccb_same_cid(tCONN_CB& ccb);
extern bool sdpu_process_pend_ccb_new_cid(tCONN_CB& ccb);
extern void sdpu_clear_pend_ccb(tCONN_CB& ccb);
extern void sdpu_callback(tCONN_CB& ccb, tSDP_REASON reason);

/* Functions provided by sdp_db.cc
 */
+0 −37
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2022 The Android Open Source Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 ******************************************************************************/

#include "mock_btif_config.h"

static bluetooth::manager::MockBtifConfigInterface* btif_config_interface =
    nullptr;

void bluetooth::manager::SetMockBtifConfigInterface(
    MockBtifConfigInterface* mock_btif_config_interface) {
  btif_config_interface = mock_btif_config_interface;
}

bool btif_config_get_bin(const std::string& section, const std::string& key,
                         uint8_t* value, size_t* length) {
  return btif_config_interface->GetBin(section, key, value, length);
}

size_t btif_config_get_bin_length(const std::string& section,
                                  const std::string& key) {
  return btif_config_interface->GetBinLength(section, key);
}
Loading