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

Commit dd3914c5 authored by Sal Savage's avatar Sal Savage Committed by Automerger Merge Worker
Browse files

Merge "AVCRP Controller support Get Item Attributes" into rvc-dev am: f6655f2b

Change-Id: I38e422ed3001cde8351e12ca6ff569aa70aa3a80
parents 04c8df0e f6655f2b
Loading
Loading
Loading
Loading
+122 −95
Original line number Diff line number Diff line
@@ -295,7 +295,7 @@ static void handle_set_addressed_player_response(tBTA_AV_META_MSG* pmeta_msg,
                                                 tAVRC_RSP* p_rsp);
static void cleanup_btrc_folder_items(btrc_folder_items_t* btrc_items,
                                      uint8_t item_count);
static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg,
static void handle_get_metadata_attr_response(tBTA_AV_META_MSG* pmeta_msg,
                                          tAVRC_GET_ATTRS_RSP* p_rsp);
static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg,
                                             tAVRC_RSP* p_rsp);
@@ -307,9 +307,16 @@ static bt_status_t get_player_app_setting_value_text_cmd(
static bt_status_t register_notification_cmd(uint8_t label, uint8_t event_id,
                                             uint32_t event_value,
                                             btif_rc_device_cb_t* p_dev);
static bt_status_t get_metadata_attribute_cmd(uint8_t num_attribute,
                                              const uint32_t* p_attr_ids,
                                              btif_rc_device_cb_t* p_dev);
static bt_status_t get_element_attribute_cmd(uint8_t num_attribute,
                                             const uint32_t* p_attr_ids,
                                             btif_rc_device_cb_t* p_dev);
static bt_status_t get_item_attribute_cmd(uint64_t uid, int scope,
                                           uint8_t num_attribute,
                                           const uint32_t* p_attr_ids,
                                           btif_rc_device_cb_t* p_dev);
static bt_status_t getcapabilities_cmd(uint8_t cap_id,
                                       btif_rc_device_cb_t* p_dev);
static bt_status_t list_player_app_setting_attrib_cmd(
@@ -1840,7 +1847,7 @@ static void rc_ctrl_procedure_complete(btif_rc_device_cb_t* p_dev) {
  p_dev->rc_procedure_complete = true;
  const uint32_t* attr_list = get_requested_attributes_list(p_dev);
  const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
  get_element_attribute_cmd(attr_list_size, attr_list, p_dev);
  get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
}

/***************************************************************************
@@ -2920,7 +2927,7 @@ static void btif_rc_status_cmd_timeout_handler(UNUSED_ATTR uint16_t event,

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

    case AVRC_PDU_GET_PLAY_STATUS:
@@ -3096,6 +3103,44 @@ bt_status_t build_and_send_vendor_cmd(tAVRC_COMMAND* avrc_cmd,
  return (bt_status_t)status;
}

/***************************************************************************
 *
 * Function         send_browsing_command
 *
 * Description      Send a command to a device on the browsing channel
 *
 * Parameters       avrc_cmd: The command you're sending
 *                  p_dev: Device control block
 *
 * Returns          BT_STATUS_SUCCESS if command is issued successfully
 *                  otherwise BT_STATUS_FAIL
 *
 **************************************************************************/
static bt_status_t build_and_send_browsing_cmd(tAVRC_COMMAND* avrc_cmd,
                                         btif_rc_device_cb_t* p_dev) {
  BT_HDR* p_msg = NULL;
  tAVRC_STS status = AVRC_BldCommand(avrc_cmd, &p_msg);
  if (status != AVRC_STS_NO_ERROR) {
    BTIF_TRACE_ERROR("%s: failed to build command status %d", __func__, status);
    return BT_STATUS_FAIL;
  }

  rc_transaction_t* p_transaction = NULL;
  bt_status_t tran_status = get_transaction(&p_transaction);

  if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
    osi_free(p_msg);
    BTIF_TRACE_ERROR("%s: failed to obtain txn details. status: 0x%02x",
                     __func__, tran_status);
    return BT_STATUS_FAIL;
  }

  BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__,
                   p_transaction->lbl);
  BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
  return BT_STATUS_SUCCESS;
}

/***************************************************************************
 *
 * Function         handle_get_capability_response
@@ -3229,7 +3274,7 @@ static void handle_notification_response(tBTA_AV_META_MSG* pmeta_msg,
          uint8_t* p_data = p_rsp->param.track;
          BE_STREAM_TO_UINT64(p_dev->rc_playing_uid, p_data);
          get_play_status_cmd(p_dev);
          get_element_attribute_cmd(attr_list_size, attr_list,
          get_metadata_attribute_cmd(attr_list_size, attr_list,
                                    p_dev);
        }
        break;
@@ -3331,7 +3376,7 @@ static void handle_notification_response(tBTA_AV_META_MSG* pmeta_msg,
         * if the play state is playing.
         */
        if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING) {
          get_element_attribute_cmd(attr_list_size, attr_list,
          get_metadata_attribute_cmd(attr_list_size, attr_list,
                                    p_dev);
        }
        do_in_jni_thread(
@@ -3346,7 +3391,7 @@ static void handle_notification_response(tBTA_AV_META_MSG* pmeta_msg,
        if (rc_is_track_id_valid(p_rsp->param.track) != true) {
          break;
        }
        get_element_attribute_cmd(attr_list_size, attr_list, p_dev);
        get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
        break;

      case AVRC_EVT_APP_SETTING_CHANGE: {
@@ -3814,14 +3859,14 @@ static void handle_set_app_attr_val_response(tBTA_AV_META_MSG* pmeta_msg,

/***************************************************************************
 *
 * Function         handle_get_elem_attr_response
 * Function         handle_get_metadata_attr_response
 *
 * Description      handles the the element attributes response, calls
 *                  HAL callback to update track change information.
 * Returns          None
 *
 **************************************************************************/
static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg,
static void handle_get_metadata_attr_response(tBTA_AV_META_MSG* pmeta_msg,
                                          tAVRC_GET_ATTRS_RSP* p_rsp) {
  btif_rc_device_cb_t* p_dev =
      btif_rc_get_device_by_handle(pmeta_msg->rc_handle);
@@ -3856,7 +3901,7 @@ static void handle_get_elem_attr_response(tBTA_AV_META_MSG* pmeta_msg,
     */
    const uint32_t* attr_list = get_requested_attributes_list(p_dev);
    const uint8_t attr_list_size = get_requested_attributes_list_size(p_dev);
    get_element_attribute_cmd(attr_list_size, attr_list, p_dev);
    get_metadata_attribute_cmd(attr_list_size, attr_list, p_dev);
  } else {
    BTIF_TRACE_ERROR("%s: Error in get element attr procedure: %d", __func__,
                     p_rsp->status);
@@ -4346,7 +4391,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_attrs);
        handle_get_metadata_attr_response(pmeta_msg, &avrc_response.get_attrs);
        break;

      case AVRC_PDU_GET_PLAY_STATUS:
@@ -4371,6 +4416,9 @@ static void handle_avk_rc_metamsg_rsp(tBTA_AV_META_MSG* pmeta_msg) {
      case AVRC_PDU_SET_BROWSED_PLAYER:
        handle_set_browsed_player_response(pmeta_msg, &avrc_response.br_player);
        break;
      case AVRC_PDU_GET_ITEM_ATTRIBUTES:
        handle_get_metadata_attr_response(pmeta_msg, &avrc_response.get_attrs);
        break;
      default:
        BTIF_TRACE_ERROR("%s cannot handle browse pdu %d", __func__,
                         pmeta_msg->p_msg->hdr.opcode);
@@ -4624,6 +4672,35 @@ static bt_status_t get_now_playing_list_cmd(const RawAddress& bd_addr,
                              end_item);
}

/***************************************************************************
 *
 * Function         get_item_attribute_cmd
 *
 * Description      Fetch the item attributes for a given uid.
 *
 * Parameters       uid: Track UID you want attributes for
 *                  scope: Constant representing which scope you're querying
 *                         (i.e AVRC_SCOPE_FILE_SYSTEM)
 *                  p_dev: Device control block
 *
 * Returns          BT_STATUS_SUCCESS if command is issued successfully
 *                  otherwise BT_STATUS_FAIL
 *
 **************************************************************************/
static bt_status_t get_item_attribute_cmd(uint64_t uid, int scope,
                                           uint8_t num_attribute,
                                           const uint32_t* p_attr_ids,
                                           btif_rc_device_cb_t* p_dev) {
  tAVRC_COMMAND avrc_cmd = {0};
  avrc_cmd.pdu = AVRC_PDU_GET_ITEM_ATTRIBUTES;
  avrc_cmd.get_attrs.scope = scope;
  memcpy(avrc_cmd.get_attrs.uid, &uid, 8);
  avrc_cmd.get_attrs.uid_counter = 0;
  avrc_cmd.get_attrs.attr_count = 0;

  return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
}

/***************************************************************************
 *
 * Function         get_folder_list_cmd
@@ -4697,26 +4774,7 @@ static bt_status_t change_folder_path_cmd(const RawAddress& bd_addr,
  memset(avrc_cmd.chg_path.folder_uid, 0, AVRC_UID_SIZE * sizeof(uint8_t));
  memcpy(avrc_cmd.chg_path.folder_uid, uid, AVRC_UID_SIZE * sizeof(uint8_t));

  BT_HDR* p_msg = NULL;
  tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg);
  if (status != AVRC_STS_NO_ERROR) {
    BTIF_TRACE_ERROR("%s failed to build command status %d", __func__, status);
    return BT_STATUS_FAIL;
  }

  rc_transaction_t* p_transaction = NULL;
  bt_status_t tran_status = get_transaction(&p_transaction);
  if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
    osi_free(p_msg);
    BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
                     __func__, tran_status);
    return BT_STATUS_FAIL;
  }

  BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__,
                   p_transaction->lbl);
  BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
  return BT_STATUS_SUCCESS;
  return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
}

/***************************************************************************
@@ -4738,33 +4796,13 @@ static bt_status_t set_browsed_player_cmd(const RawAddress& bd_addr,
  CHECK_RC_CONNECTED(p_dev);
  CHECK_BR_CONNECTED(p_dev);

  rc_transaction_t* p_transaction = NULL;

  tAVRC_COMMAND avrc_cmd = {0};
  avrc_cmd.br_player.pdu = AVRC_PDU_SET_BROWSED_PLAYER;
  avrc_cmd.br_player.status = AVRC_STS_NO_ERROR;
  // TODO(sanketa): Improve for database aware clients.
  avrc_cmd.br_player.player_id = id;

  BT_HDR* p_msg = NULL;
  tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg);
  if (status != AVRC_STS_NO_ERROR) {
    BTIF_TRACE_ERROR("%s failed to build command status %d", __func__, status);
    return BT_STATUS_FAIL;
  }

  bt_status_t tran_status = get_transaction(&p_transaction);
  if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
    osi_free(p_msg);
    BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
                     __func__, tran_status);
    return BT_STATUS_FAIL;
  }

  BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__,
                   p_transaction->lbl);
  BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
  return BT_STATUS_SUCCESS;
  return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
}

/***************************************************************************
@@ -4788,33 +4826,12 @@ static bt_status_t set_addressed_player_cmd(const RawAddress& bd_addr,
  CHECK_BR_CONNECTED(p_dev);

  tAVRC_COMMAND avrc_cmd = {0};
  BT_HDR* p_msg = NULL;

  avrc_cmd.addr_player.pdu = AVRC_PDU_SET_ADDRESSED_PLAYER;
  avrc_cmd.addr_player.status = AVRC_STS_NO_ERROR;
  // TODO(sanketa): Improve for database aware clients.
  avrc_cmd.addr_player.player_id = id;

  tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg);
  if (status != AVRC_STS_NO_ERROR) {
    BTIF_TRACE_ERROR("%s: failed to build command status %d", __func__, status);
    return BT_STATUS_FAIL;
  }

  rc_transaction_t* p_transaction = NULL;
  bt_status_t tran_status = get_transaction(&p_transaction);

  if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
    osi_free(p_msg);
    BTIF_TRACE_ERROR("%s: failed to obtain txn details. status: 0x%02x",
                     __func__, tran_status);
    return BT_STATUS_FAIL;
  }

  BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__,
                   p_transaction->lbl);
  BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
  return BT_STATUS_SUCCESS;
  return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
}

/***************************************************************************
@@ -4854,26 +4871,7 @@ static bt_status_t get_folder_items_cmd(const RawAddress& bd_addr,
  avrc_cmd.get_items.end_item = end_item;
  avrc_cmd.get_items.attr_count = 0; /* p_attr_list does not matter hence */

  BT_HDR* p_msg = NULL;
  tAVRC_STS status = AVRC_BldCommand(&avrc_cmd, &p_msg);
  if (status != AVRC_STS_NO_ERROR) {
    BTIF_TRACE_ERROR("%s failed to build command status %d", __func__, status);
    return BT_STATUS_FAIL;
  }

  rc_transaction_t* p_transaction = NULL;
  bt_status_t tran_status = get_transaction(&p_transaction);
  if (tran_status != BT_STATUS_SUCCESS || p_transaction == NULL) {
    osi_free(p_msg);
    BTIF_TRACE_ERROR("%s: failed to obtain transaction details. status: 0x%02x",
                     __func__, tran_status);
    return BT_STATUS_FAIL;
  }

  BTIF_TRACE_DEBUG("%s msgreq being sent out with label %d", __func__,
                   p_transaction->lbl);
  BTA_AvMetaCmd(p_dev->rc_handle, p_transaction->lbl, AVRC_CMD_CTRL, p_msg);
  return BT_STATUS_SUCCESS;
  return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
}

/***************************************************************************
@@ -4934,7 +4932,8 @@ static bt_status_t play_item_cmd(const RawAddress& bd_addr, uint8_t scope,
  memcpy(avrc_cmd.play_item.uid, uid, AVRC_UID_SIZE);
  avrc_cmd.play_item.uid_counter = uid_counter;

  return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_CTRL, p_dev);
  return build_and_send_browsing_cmd(&avrc_cmd, p_dev);
  // return build_and_send_vendor_cmd(&avrc_cmd, AVRC_CMD_CTRL, p_dev);
}

/***************************************************************************
@@ -5031,6 +5030,35 @@ static bt_status_t register_notification_cmd(uint8_t label, uint8_t event_id,
  return (bt_status_t)status;
}

/***************************************************************************
 *
 * Function         get_metadata_attribute_cmd
 *
 * Description      Get metadata attributes for attributeIds. This function
 *                  will make the right determination of whether to use the
 *                  control or browsing channel for the request
 *
 * Returns          BT_STATUS_SUCCESS if the command is successfully issued
 *                  otherwise BT_STATUS_FAIL
 *
 **************************************************************************/
static bt_status_t get_metadata_attribute_cmd(uint8_t num_attribute,
                                              const uint32_t* p_attr_ids,
                                              btif_rc_device_cb_t* p_dev) {
  BTIF_TRACE_DEBUG("%s: num_attribute: %d attribute_id: %d", __func__,
                   num_attribute, p_attr_ids[0]);

  // If browsing is connected then send the command out that channel
  if (p_dev->br_connected) {
    return get_item_attribute_cmd(p_dev->rc_playing_uid,
                                   AVRC_SCOPE_NOW_PLAYING, num_attribute,
                                   p_attr_ids, p_dev);
  }

  // Otherwise, default to the control channel
  return get_element_attribute_cmd(num_attribute, p_attr_ids, p_dev);
}

/***************************************************************************
 *
 * Function         get_element_attribute_cmd
@@ -5046,7 +5074,6 @@ static bt_status_t get_element_attribute_cmd(uint8_t num_attribute,
  BTIF_TRACE_DEBUG("%s: num_attribute: %d attribute_id: %d", __func__,
                   num_attribute, p_attr_ids[0]);
  CHECK_RC_CONNECTED(p_dev);

  tAVRC_COMMAND avrc_cmd = {0};
  avrc_cmd.get_elem_attrs.opcode = AVRC_OP_VENDOR;
  avrc_cmd.get_elem_attrs.status = AVRC_STS_NO_ERROR;
+21 −1
Original line number Diff line number Diff line
@@ -431,7 +431,24 @@ static tAVRC_STS avrc_bld_change_folder_cmd(BT_HDR* p_pkt,
  p_pkt->len = (p_data - p_start);
  return AVRC_STS_NO_ERROR;
}

static tAVRC_STS avrc_bld_get_item_attributes_cmd(
    BT_HDR* p_pkt, const tAVRC_GET_ATTRS_CMD* cmd) {
  AVRC_TRACE_API("%s", __func__);
  uint8_t* p_start = (uint8_t*)(p_pkt + 1) + p_pkt->offset;
  /* This is where the PDU specific for AVRC starts
   * AVRCP Spec 1.4 section 22.19 */
  uint8_t* p_data = p_start + 1; /* pdu */
  UINT16_TO_BE_STREAM(p_data, 12 + 4 * cmd->attr_count);
  UINT8_TO_BE_STREAM(p_data, cmd->scope);
  uint64_t uid;
  memcpy(&uid, cmd->uid, 8);
  UINT64_TO_BE_STREAM(p_data, uid);
  UINT16_TO_BE_STREAM(p_data, cmd->uid_counter);
  UINT8_TO_BE_STREAM(p_data, cmd->attr_count);
  ARRAY_TO_BE_STREAM(p_data, cmd->p_attr_list, 4 * cmd->attr_count);
  p_pkt->len = (p_data - p_start);
  return AVRC_STS_NO_ERROR;
}
/*******************************************************************************
 *
 * Function         avrc_bld_set_browsed_player_cmd
@@ -645,6 +662,9 @@ tAVRC_STS AVRC_BldCommand(tAVRC_COMMAND* p_cmd, BT_HDR** pp_pkt) {
    case AVRC_PDU_CHANGE_PATH:
      status = avrc_bld_change_folder_cmd(p_pkt, &(p_cmd->chg_path));
      break;
    case AVRC_PDU_GET_ITEM_ATTRIBUTES:
      status = avrc_bld_get_item_attributes_cmd(p_pkt, &(p_cmd->get_attrs));
      break;
    case AVRC_PDU_SET_BROWSED_PLAYER:
      status = avrc_bld_set_browsed_player_cmd(p_pkt, &(p_cmd->br_player));
      break;
+24 −0
Original line number Diff line number Diff line
@@ -425,6 +425,30 @@ static tAVRC_STS avrc_pars_browse_rsp(tAVRC_MSG_BROWSE* p_msg,
      break;
    }

    case AVRC_PDU_GET_ITEM_ATTRIBUTES: {
      tAVRC_GET_ATTRS_RSP* get_attr_rsp = &(p_rsp->get_attrs);
      get_attr_rsp->pdu = pdu;
      BE_STREAM_TO_UINT8(get_attr_rsp->status, p)
      BE_STREAM_TO_UINT8(get_attr_rsp->num_attrs, p);
      get_attr_rsp->p_attrs = (tAVRC_ATTR_ENTRY*)osi_malloc(
          get_attr_rsp->num_attrs * sizeof(tAVRC_ATTR_ENTRY));
      for (int i = 0; i < get_attr_rsp->num_attrs; i++) {
        tAVRC_ATTR_ENTRY* attr_entry = &(get_attr_rsp->p_attrs[i]);
        BE_STREAM_TO_UINT32(attr_entry->attr_id, p);
        BE_STREAM_TO_UINT16(attr_entry->name.charset_id, p);
        BE_STREAM_TO_UINT16(attr_entry->name.str_len, p);
        min_len += attr_entry->name.str_len;
        if (pkt_len < min_len) goto browse_length_error;
        attr_entry->name.p_str =
            (uint8_t*)osi_malloc(attr_entry->name.str_len * sizeof(uint8_t));
        BE_STREAM_TO_ARRAY(p, attr_entry->name.p_str, attr_entry->name.str_len);
        AVRC_TRACE_DEBUG("%s media attr id %d cs %d name len %d", __func__,
                         attr_entry->attr_id, attr_entry->name.charset_id,
                         attr_entry->name.str_len);
      }

      break;
    }
    case AVRC_PDU_SET_BROWSED_PLAYER: {
      tAVRC_SET_BR_PLAYER_RSP* set_br_pl_rsp = &(p_rsp->br_player);
      /* Copyback the PDU */