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

Commit d4690c9e authored by Jack He's avatar Jack He Committed by Hansong Zhang
Browse files

HFP: Workaround for car kits that do not send AT+BAC command

* Some misbehaving HF devices (e.g. some Hyundai car kits) indicate
  their support on Wide Band Speech and Codec Negotiation, but do not
  send the required AT+BAC command during Service Level Connection
  setup. However, such car kits still expect Fluoride to do codec
  negotiation during SCO setup.
* This CL adds a workaround so that when HF indicates support for WBS
  and codec negotiation, Fluoride will attempt codec negotiation even
  though AT+BAC is never received.
* Store the SDP feature locally. If WBS is supported and no AT+BAC is
  received, use the SDP features to set the suported codec.

Bug: 77883405
Test: make, connect SCO to and from Hyundai car kits
Change-Id: I2be6007022183cac5b9006f37089a587b4a67372
parent 806b8591
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
@@ -464,6 +464,20 @@ void bta_ag_rfc_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
                         __func__, p_scb->peer_addr.ToString().c_str());
      p_scb->peer_version = HFP_HSP_VERSION_UNKNOWN;
    }
    size_t sdp_features_size = sizeof(p_scb->peer_sdp_features);
    if (btif_config_get_bin(
            p_scb->peer_addr.ToString(), HFP_SDP_FEATURES_CONFIG_KEY,
            (uint8_t*)&p_scb->peer_sdp_features, &sdp_features_size)) {
      bool sdp_wbs_support = p_scb->peer_sdp_features & BTA_AG_FEAT_WBS_SUPPORT;
      if (!p_scb->received_at_bac && sdp_wbs_support) {
        p_scb->codec_updated = true;
        p_scb->peer_codecs = BTA_AG_CODEC_CVSD & BTA_AG_CODEC_MSBC;
        p_scb->sco_codec = UUID_CODEC_MSBC;
      }
    } else {
      APPL_TRACE_WARNING("%s: Failed read cached peer HFP SDP features for %s",
                         __func__, p_scb->peer_addr.ToString().c_str());
    }
  }

  /* set up AT command interpreter */
+1 −0
Original line number Diff line number Diff line
@@ -1186,6 +1186,7 @@ void bta_ag_at_hfp_cback(tBTA_AG_SCB* p_scb, uint16_t cmd, uint8_t arg_type,

    case BTA_AG_AT_BAC_EVT:
      bta_ag_send_ok(p_scb);
      p_scb->received_at_bac = true;

      /* store available codecs from the peer */
      if ((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) &&
+2 −0
Original line number Diff line number Diff line
@@ -204,6 +204,7 @@ struct tBTA_AG_SCB {
  tBTA_SEC cli_sec_mask;                /* client security mask */
  tBTA_AG_FEAT features;                /* features registered by application */
  tBTA_AG_PEER_FEAT peer_features;      /* peer device features */
  uint16_t peer_sdp_features;           /* peer device SDP features */
  uint16_t peer_version;                /* profile version of peer device */
  uint16_t hsp_version;                 /* HSP profile version before SDP */
  uint16_t sco_idx;                     /* SCO handle */
@@ -232,6 +233,7 @@ struct tBTA_AG_SCB {
  alarm_t* collision_timer;
  alarm_t* ring_timer;
  alarm_t* codec_negotiation_timer;
  bool received_at_bac; /* indicate AT+BAC is received at least once */
  tBTA_AG_PEER_CODEC peer_codecs; /* codecs for eSCO supported by the peer */
  tBTA_AG_PEER_CODEC sco_codec;   /* codec to be used for eSCO connection */
  tBTA_AG_PEER_CODEC
+2 −0
Original line number Diff line number Diff line
@@ -327,12 +327,14 @@ static tBTA_AG_SCB* bta_ag_scb_alloc(void) {
      /* initialize variables */
      p_scb->in_use = true;
      p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
      p_scb->received_at_bac = false;
      p_scb->codec_updated = false;
      p_scb->codec_fallback = false;
      p_scb->peer_codecs = BTA_AG_CODEC_CVSD;
      p_scb->sco_codec = BTA_AG_CODEC_CVSD;
      p_scb->peer_version = HFP_HSP_VERSION_UNKNOWN;
      p_scb->hsp_version = HSP_VERSION_1_2;
      p_scb->peer_sdp_features = 0;
      /* set up timers */
      p_scb->ring_timer = alarm_new("bta_ag.scb_ring_timer");
      p_scb->collision_timer = alarm_new("bta_ag.scb_collision_timer");
+26 −2
Original line number Diff line number Diff line
@@ -361,8 +361,32 @@ bool bta_ag_sdp_find_attr(tBTA_AG_SCB* p_scb, tBTA_SERVICE_MASK service) {
        /* Found attribute. Get value. */
        /* There might be race condition between SDP and BRSF.  */
        /* Do not update if we already received BRSF.           */
        if (p_scb->peer_features == 0)
          p_scb->peer_features = p_attr->attr_value.v.u16;
        uint16_t sdp_features = p_attr->attr_value.v.u16;
        bool sdp_wbs_support = sdp_features & BTA_AG_FEAT_WBS_SUPPORT;
        if (!p_scb->received_at_bac && sdp_wbs_support) {
          // Workaround for misbehaving HFs (e.g. some Hyundai car kit) that:
          // 1. Indicate WBS support in SDP and codec negotiation in BRSF
          // 2. But do not send required AT+BAC command
          // Will assume mSBC is enabled and try codec negotiation by default
          p_scb->codec_updated = true;
          p_scb->peer_codecs = BTA_AG_CODEC_CVSD & BTA_AG_CODEC_MSBC;
          p_scb->sco_codec = UUID_CODEC_MSBC;
        }
        if (sdp_features != p_scb->peer_sdp_features) {
          p_scb->peer_sdp_features = sdp_features;
          if (btif_config_set_bin(
                  p_scb->peer_addr.ToString(), HFP_SDP_FEATURES_CONFIG_KEY,
                  (const uint8_t*)&sdp_features, sizeof(sdp_features))) {
            btif_config_save();
          } else {
            APPL_TRACE_WARNING(
                "%s: Failed to store peer HFP SDP Features for %s", __func__,
                p_scb->peer_addr.ToString().c_str());
          }
        }
        if (p_scb->peer_features == 0) {
          p_scb->peer_features = sdp_features & HFP_SDP_BRSF_FEATURES_MASK;
        }
      }
    } else {
      /* No peer version caching for HSP, use discovered one directly */
Loading