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

Commit c3ebb7c2 authored by Marie Janssen's avatar Marie Janssen
Browse files

AVRCP: unify Get{Element,Item}Attributes response.

GetElementAttributes response and GetItemAttributes response share the
same format and require the same checks for length.

Test: play media on carkit, see media. especially with long items.
Bug: 32407250
Bug: 30571638
Change-Id: I8623e7d662f7a39112b7527b6f5ab63c5e32379c
parent 946e591a
Loading
Loading
Loading
Loading
+14 −14
Original line number Diff line number Diff line
@@ -319,7 +319,7 @@ static void handle_get_playstatus_response(tBTA_AV_META_MSG* pmeta_msg,
                                           tAVRC_GET_PLAY_STATUS_RSP* p_rsp);
static void handle_set_addressed_player_response(tBTA_AV_META_MSG *pmeta_msg, tAVRC_RSP *p_rsp);
static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg,
                                          tAVRC_GET_ELEM_ATTRS_RSP* p_rsp);
                                          tAVRC_GET_ATTRS_RSP* p_rsp);
static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg,
                                             tAVRC_RSP* p_rsp);
static bt_status_t get_play_status_cmd(btif_rc_device_cb_t* p_dev);
@@ -2060,10 +2060,10 @@ static bt_status_t get_element_attr_rsp(bt_bdaddr_t* bd_addr, uint8_t num_attr,
    }
    avrc_rsp.get_play_status.status = AVRC_STS_NO_ERROR;
  }
  avrc_rsp.get_elem_attrs.num_attr = num_attr;
  avrc_rsp.get_elem_attrs.p_attrs = element_attrs;
  avrc_rsp.get_elem_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
  avrc_rsp.get_elem_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);
  avrc_rsp.get_attrs.num_attrs = num_attr;
  avrc_rsp.get_attrs.p_attrs = element_attrs;
  avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ELEMENT_ATTR;
  avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ELEMENT_ATTR);

  /* Send the response */
  send_metamsg_rsp(p_dev, IDX_GET_ELEMENT_ATTR_RSP,
@@ -2623,8 +2623,8 @@ static bt_status_t get_item_attr_rsp(bt_bdaddr_t* bd_addr,
      fill_avrc_attr_entry(item_attrs, num_attr, p_attrs);
    }
  }
  avrc_rsp.get_attrs.attr_count = num_attr;
  avrc_rsp.get_attrs.p_attr_list = item_attrs;
  avrc_rsp.get_attrs.num_attrs = num_attr;
  avrc_rsp.get_attrs.p_attrs = item_attrs;
  avrc_rsp.get_attrs.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES;
  avrc_rsp.get_attrs.opcode = opcode_from_pdu(AVRC_PDU_GET_ITEM_ATTRIBUTES);

@@ -3086,8 +3086,8 @@ static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,
      break;

    case AVRC_PDU_GET_ELEMENT_ATTR:
      avrc_response.get_elem_attrs.status = BTIF_RC_STS_TIMEOUT;
      handle_get_elem_attr_response(&meta_msg, &avrc_response.get_elem_attrs);
      avrc_response.get_attrs.status = BTIF_RC_STS_TIMEOUT;
      handle_get_elem_attr_response(&meta_msg, &avrc_response.get_attrs);
      break;

    case AVRC_PDU_GET_PLAY_STATUS:
@@ -3975,13 +3975,13 @@ static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg,
 *
 **************************************************************************/
static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg,
                                          tAVRC_GET_ELEM_ATTRS_RSP* p_rsp) {
                                          tAVRC_GET_ATTRS_RSP* p_rsp) {
  btif_rc_device_cb_t* p_dev =
      btif_rc_get_device_by_handle(pmeta_msg->rc_handle);

  if (p_rsp->status == AVRC_STS_NO_ERROR) {
    bt_bdaddr_t rc_addr;
    size_t buf_size = p_rsp->num_attr * sizeof(btrc_element_attr_val_t);
    size_t buf_size = p_rsp->num_attrs * sizeof(btrc_element_attr_val_t);
    btrc_element_attr_val_t* p_attr =
        (btrc_element_attr_val_t*)osi_calloc(buf_size);

@@ -3992,7 +3992,7 @@ static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg,

    bdcpy(rc_addr.address, p_dev->rc_addr);

    for (int i = 0; i < p_rsp->num_attr; i++) {
    for (int i = 0; i < p_rsp->num_attrs; i++) {
      p_attr[i].attr_id = p_rsp->p_attrs[i].attr_id;
      /* Todo. Legth limit check to include null */
      if (p_rsp->p_attrs[i].name.str_len && p_rsp->p_attrs[i].name.p_str) {
@@ -4001,7 +4001,7 @@ static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg,
        osi_free_and_reset((void**)&p_rsp->p_attrs[i].name.p_str);
      }
    }
    HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb, &rc_addr, p_rsp->num_attr,
    HAL_CBACK(bt_rc_ctrl_callbacks, track_changed_cb, &rc_addr, p_rsp->num_attrs,
              p_attr);
    osi_free(p_attr);
  } else if (p_rsp->status == BTIF_RC_STS_TIMEOUT) {
@@ -4466,7 +4466,7 @@ static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg) {
        break;

      case AVRC_PDU_GET_ELEMENT_ATTR:
        handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_elem_attrs);
        handle_get_elem_attr_response(pmeta_msg, &avrc_response.get_attrs);
        break;

      case AVRC_PDU_GET_PLAY_STATUS:
+37 −103
Original line number Diff line number Diff line
@@ -445,71 +445,6 @@ static tAVRC_STS avrc_bld_inform_battery_status_rsp (UNUSED_ATTR tAVRC_RSP *p_rs
    return AVRC_STS_NO_ERROR;
}

/*******************************************************************************
**
** Function         avrc_bld_get_elem_attrs_rsp
**
** Description      This function builds the Get Element Attributes
**                  response.
**
** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
**                  Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
{
    uint8_t *p_data, *p_start, *p_len, *p_count;
    uint16_t len;
    uint8_t xx;

    AVRC_TRACE_API("%s", __func__);
    if (!p_rsp->p_attrs)
    {
        AVRC_TRACE_ERROR("%s NULL parameter", __func__);
        return AVRC_STS_BAD_PARAM;
    }

    /* get the existing length, if any, and also the num attributes */
    p_start = (uint8_t *)(p_pkt + 1) + p_pkt->offset;
    p_data = p_len = p_start + 2; /* pdu + rsvd */

    BE_STREAM_TO_UINT16(len, p_data);
    p_count = p_data;

    if (len == 0)
    {
        *p_count = 0;
        p_data++;
    }
    else
    {
        p_data = p_start + p_pkt->len;
    }

    for (xx=0; xx<p_rsp->num_attr; xx++)
    {
        if (!AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id))
        {
            AVRC_TRACE_ERROR("%s invalid attr id[%d]: %d",
                __func__, xx, p_rsp->p_attrs[xx].attr_id);
            continue;
        }
        if ( !p_rsp->p_attrs[xx].name.p_str )
        {
            p_rsp->p_attrs[xx].name.str_len = 0;
        }
        UINT32_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.charset_id);
        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.str_len);
        ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len);
        (*p_count)++;
    }
    len = p_data - p_count;
    UINT16_TO_BE_STREAM(p_len, len);
    p_pkt->len = (p_data - p_start);
    return AVRC_STS_NO_ERROR;
}

/*******************************************************************************
**
** Function         avrc_bld_get_play_status_rsp
@@ -1158,45 +1093,47 @@ static tAVRC_STS avrc_bld_change_path_rsp (tAVRC_CHG_PATH_RSP *p_rsp, BT_HDR *p_

/*******************************************************************************
**
** Function         avrc_bld_get_item_attrs_rsp
** Function         avrc_bld_get_attrs_rsp
**
** Description      This function builds the Get Item Attributes response.
** Description      This function builds the Get Item Attributes or
**                  Get Element Attributes response,
**
**                  This message goes through the Browsing channel
**                  The Get Item Attributes message goes through the
**                  Browsing channel (already specified in the |p_pkt|)
**
** Returns          AVRC_STS_NO_ERROR, if the response is built successfully
**                  AVRC_STS_INTERNAL_ERR, if the given buffer does not have enough room
**                  Otherwise, the error code.
**
*******************************************************************************/
static tAVRC_STS avrc_bld_get_item_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
static tAVRC_STS avrc_bld_get_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR *p_pkt)
{
    uint8_t   *p_data, *p_start;
    uint8_t   *p_len;
    uint16_t  len, len_left;
    uint16_t  len_left;
    uint8_t   *p_num;
    uint16_t  mtu;

    AVRC_TRACE_API("%s", __func__);
    /* calculate the buffer size needed and validate the parameters */
    if (!p_rsp || !p_rsp->p_attr_list)
    if (!p_rsp || !p_rsp->p_attrs)
    {
        AVRC_TRACE_ERROR("NULL p_attr_list");
        AVRC_TRACE_ERROR("NULL p_attrs");
        return AVRC_STS_BAD_PARAM;
    }

    /* check the length before adding the attr to the message */
    len = 2;
    for (uint8_t xx = 0; xx < p_rsp->attr_count; xx++)
    uint16_t len = 2;
    for (uint8_t xx = 0; xx < p_rsp->num_attrs; xx++)
    {
        if(p_rsp->p_attr_list[xx].name.p_str == 0 ||
            !AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attr_list[xx].attr_id))
        if(p_rsp->p_attrs[xx].name.p_str == 0 ||
            !AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id))
        {
            AVRC_TRACE_ERROR("[%d] NULL p_attr_list str or bad attr_id:%d", xx,
                p_rsp->p_attr_list[xx].attr_id);
            AVRC_TRACE_ERROR("[%d] NULL p_attrs str or bad attr_id:%d", xx,
                p_rsp->p_attrs[xx].attr_id);
            return AVRC_STS_BAD_PARAM;
        }
        len += (p_rsp->p_attr_list[xx].name.str_len + 8);
        len += (p_rsp->p_attrs[xx].name.str_len + 8);
    }
    len_left = BT_DEFAULT_BUFFER_SIZE - BT_HDR_SIZE;
    p_data = (uint8_t *)(p_pkt + 1);
@@ -1239,19 +1176,19 @@ static tAVRC_STS avrc_bld_get_item_attrs_rsp (tAVRC_GET_ATTRS_RSP *p_rsp, BT_HDR
    }


    for (uint8_t xx = 0; (xx < p_rsp->attr_count) && (len_left > 9); xx++)
    for (uint8_t xx = 0; (xx < p_rsp->num_attrs) && (len_left > 9); xx++)
    {
        (*p_num)++;
        UINT32_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].attr_id);
        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.charset_id);
        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.str_len);
        UINT32_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id);
        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.charset_id);
        UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.str_len);
        len_left -= 8;
        if (p_rsp->p_attr_list[xx].name.str_len > len_left)
            p_rsp->p_attr_list[xx].name.str_len = len_left;
        ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attr_list[xx].name.p_str,
            p_rsp->p_attr_list[xx].name.str_len);
        len_left -= p_rsp->p_attr_list[xx].name.str_len;
        len += (p_rsp->p_attr_list[xx].name.str_len + 8);
        if (p_rsp->p_attrs[xx].name.str_len > len_left)
            p_rsp->p_attrs[xx].name.str_len = len_left;
        ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str,
            p_rsp->p_attrs[xx].name.str_len);
        len_left -= p_rsp->p_attrs[xx].name.str_len;
        len += (p_rsp->p_attrs[xx].name.str_len + 8);
    }

    UINT16_TO_BE_STREAM(p_len, len);
@@ -1531,7 +1468,8 @@ tAVRC_STS AVRC_BldResponse( uint8_t handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_p
        break;

    case AVRC_PDU_GET_ELEMENT_ATTR:
        status = avrc_bld_get_elem_attrs_rsp(&p_rsp->get_elem_attrs, p_pkt);
    case AVRC_PDU_GET_ITEM_ATTRIBUTES:
        status = avrc_bld_get_attrs_rsp(&p_rsp->get_attrs, p_pkt);
        break;

    case AVRC_PDU_GET_PLAY_STATUS:
@@ -1542,19 +1480,19 @@ tAVRC_STS AVRC_BldResponse( uint8_t handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_p
        status = avrc_bld_notify_rsp(&p_rsp->reg_notif, p_pkt);
        break;

    case AVRC_PDU_REQUEST_CONTINUATION_RSP:     /*        0x40 */
    case AVRC_PDU_REQUEST_CONTINUATION_RSP:
        status = avrc_bld_next_rsp(&p_rsp->continu, p_pkt);
        break;

    case AVRC_PDU_ABORT_CONTINUATION_RSP:       /*          0x41 */
    case AVRC_PDU_ABORT_CONTINUATION_RSP:
        status = avrc_bld_next_rsp(&p_rsp->abort, p_pkt);
        break;

    case AVRC_PDU_SET_ADDRESSED_PLAYER:        /* 0x60 */
    case AVRC_PDU_SET_ADDRESSED_PLAYER:
        status = avrc_bld_set_addr_player_rsp(&p_rsp->addr_player, p_pkt);
        break;

    case AVRC_PDU_PLAY_ITEM:                   /* 0x74 */
    case AVRC_PDU_PLAY_ITEM:
        status = avrc_bld_play_item_rsp(&p_rsp->play_item, p_pkt);
        break;

@@ -1562,27 +1500,23 @@ tAVRC_STS AVRC_BldResponse( uint8_t handle, tAVRC_RESPONSE *p_rsp, BT_HDR **pp_p
        status = avrc_bld_set_absolute_volume_rsp(p_rsp->volume.volume, p_pkt);
        break;

    case AVRC_PDU_ADD_TO_NOW_PLAYING:          /* 0x90 */
    case AVRC_PDU_ADD_TO_NOW_PLAYING:
        status = avrc_bld_add_to_now_playing_rsp(&p_rsp->add_to_play, p_pkt);
        break;

    case AVRC_PDU_SET_BROWSED_PLAYER:          /* 0x70 */
    case AVRC_PDU_SET_BROWSED_PLAYER:
        status = avrc_bld_set_browsed_player_rsp(&p_rsp->br_player, p_pkt);
        break;

    case AVRC_PDU_GET_FOLDER_ITEMS:            /* 0x71 */
    case AVRC_PDU_GET_FOLDER_ITEMS:
        status = avrc_bld_get_folder_items_rsp(&p_rsp->get_items, p_pkt);
        break;

    case AVRC_PDU_CHANGE_PATH:                 /* 0x72 */
    case AVRC_PDU_CHANGE_PATH:
        status = avrc_bld_change_path_rsp(&p_rsp->chg_path, p_pkt);
        break;

    case AVRC_PDU_GET_ITEM_ATTRIBUTES:         /* 0x73 */
        status = avrc_bld_get_item_attrs_rsp(&p_rsp->get_attrs, p_pkt);
        break;

    case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS:      /* 0x75 */
    case AVRC_PDU_GET_TOTAL_NUM_OF_ITEMS:
        status = avrc_bld_get_num_of_item_rsp(&p_rsp->get_num_of_items, p_pkt);
        break;

+3 −3
Original line number Diff line number Diff line
@@ -586,11 +586,11 @@ static tAVRC_STS avrc_ctrl_pars_vendor_rsp(

        if (len <= 0)
        {
            p_result->get_elem_attrs.num_attr = 0;
            p_result->get_attrs.num_attrs = 0;
            break;
        }
        BE_STREAM_TO_UINT8(num_attrs, p);
        p_result->get_elem_attrs.num_attr = num_attrs;
        p_result->get_attrs.num_attrs = num_attrs;
        if (num_attrs)
        {
            tAVRC_ATTR_ENTRY *p_attrs =
@@ -604,7 +604,7 @@ static tAVRC_STS avrc_ctrl_pars_vendor_rsp(
                    BE_STREAM_TO_ARRAY(p, p_attrs[i].name.p_str, p_attrs[i].name.str_len);
                }
            }
            p_result->get_elem_attrs.p_attrs = p_attrs;
            p_result->get_attrs.p_attrs = p_attrs;
        }
    }
        break;
+4 −16
Original line number Diff line number Diff line
@@ -1269,16 +1269,6 @@ typedef struct
    tAVRC_APP_SETTING_TEXT   *p_attrs;
} tAVRC_GET_APP_ATTR_TXT_RSP;

/* GetElemAttrs */
typedef struct
{
    uint8_t     pdu;
    tAVRC_STS   status;
    uint8_t     opcode;         /* Op Code (copied from avrc_cmd.opcode by AVRC_BldResponse user. invalid one to generate according to pdu) */
    uint8_t     num_attr;
    tAVRC_ATTR_ENTRY   *p_attrs;
} tAVRC_GET_ELEM_ATTRS_RSP;

/* GetPlayStatus */
typedef struct
{
@@ -1374,14 +1364,14 @@ typedef struct
    uint32_t            num_items;
} tAVRC_CHG_PATH_RSP;

/* GetItemAttrs */
/* GetItemAttrs, GetElemAttrs */
typedef struct
{
    uint8_t             pdu;
    tAVRC_STS           status;
    uint8_t             opcode;         /* Op Code (copied from avrc_cmd.opcode by AVRC_BldResponse user. invalid one to generate according to pdu) */
    uint8_t             attr_count;
    tAVRC_ATTR_ENTRY    *p_attr_list;
    uint8_t             num_attrs;
    tAVRC_ATTR_ENTRY    *p_attrs;
} tAVRC_GET_ATTRS_RSP;

/* Get Total Number of Items */
@@ -1432,18 +1422,16 @@ typedef union
    tAVRC_GET_APP_ATTR_TXT_RSP      get_app_val_txt;        /* GetAppValueTxt */
    tAVRC_RSP                       inform_charset;         /* InformCharset */
    tAVRC_RSP                       inform_battery_status;  /* InformBatteryStatus */
    tAVRC_GET_ELEM_ATTRS_RSP        get_elem_attrs;         /* GetElemAttrs */
    tAVRC_GET_PLAY_STATUS_RSP       get_play_status;        /* GetPlayStatus */
    tAVRC_REG_NOTIF_RSP             reg_notif;              /* RegNotify */
    tAVRC_NEXT_RSP                  continu;                /* Continue */
    tAVRC_NEXT_RSP                  abort;                  /* Abort */

    tAVRC_RSP                       addr_player;            /* SetAddrPlayer */
    tAVRC_SET_VOLUME_RSP            volume;                 /* SetAbsVolume */
    tAVRC_SET_BR_PLAYER_RSP         br_player;              /* SetBrowsedPlayer */
    tAVRC_GET_ITEMS_RSP             get_items;              /* GetFolderItems */
    tAVRC_CHG_PATH_RSP              chg_path;               /* ChangePath */
    tAVRC_GET_ATTRS_RSP             get_attrs;              /* GetItemAttrs */
    tAVRC_GET_ATTRS_RSP             get_attrs;              /* GetItemAttrs, GetElemAttrs */
    tAVRC_GET_NUM_OF_ITEMS_RSP      get_num_of_items;       /* GetTotalNumberOfItems */
    tAVRC_SEARCH_RSP                search;                 /* Search */
    tAVRC_RSP                       play_item;              /* PlayItem */