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

Commit 0079ae1f authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge changes from topic "bt-avrcp-controller-cover-art" am: c0c80a62 am:...

Merge changes from topic "bt-avrcp-controller-cover-art" am: c0c80a62 am: f43862e9 am: 48563148

Change-Id: If2a29c2290e88a842a70096e6f313ca903293d22
parents cb6998d0 48563148
Loading
Loading
Loading
Loading
+140 −5
Original line number Diff line number Diff line
@@ -362,6 +362,7 @@ uint8_t bta_av_rc_create(tBTA_AV_CB* p_cb, uint8_t role, uint8_t shdl,
  p_rcb->shdl = shdl;
  p_rcb->lidx = lidx;
  p_rcb->peer_features = 0;
  p_rcb->cover_art_psm = 0;
  if (lidx == (BTA_AV_NUM_LINKS + 1)) {
    /* this LIDX is reserved for the AVRCP ACP connection */
    p_cb->rc_acp_handle = p_rcb->handle;
@@ -560,9 +561,11 @@ void bta_av_rc_opened(tBTA_AV_CB* p_cb, tBTA_AV_DATA* p_data) {

  rc_open.peer_addr = p_data->rc_conn_chg.peer_addr;
  rc_open.peer_features = p_cb->rcb[i].peer_features;
  rc_open.cover_art_psm = p_cb->rcb[i].cover_art_psm;
  rc_open.status = BTA_AV_SUCCESS;
  APPL_TRACE_DEBUG("%s: local features:x%x peer_features:x%x", __func__,
                   p_cb->features, rc_open.peer_features);
  APPL_TRACE_DEBUG("%s: cover art psm:x%x", __func__, rc_open.cover_art_psm);
  if (rc_open.peer_features == 0) {
    /* we have not done SDP on peer RC capabilities.
     * peer must have initiated the RC connection */
@@ -1755,6 +1758,108 @@ tBTA_AV_FEAT bta_avk_check_peer_features(uint16_t service_uuid) {
  return peer_features;
}

/******************************************************************************
 *
 * Function         bta_avk_get_cover_art_psm
 *
 * Description      Get the PSM associated with the AVRCP Target cover art
 *                  feature
 *
 * Returns          uint16_t PSM value used to get cover artwork, or 0x0000 if
 *                  one does not exist.
 *
 *****************************************************************************/
uint16_t bta_avk_get_cover_art_psm() {
  APPL_TRACE_DEBUG("%s: searching for cover art psm", __func__);
  /* Cover Art L2CAP PSM is only available on a target device */
  tBTA_AV_CB* p_cb = &bta_av_cb;
  tSDP_DISC_REC* p_rec =
      SDP_FindServiceInDb(p_cb->p_disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET,
          NULL);
  while (p_rec) {
    tSDP_DISC_ATTR* p_attr =
        (SDP_FindAttributeInRec(p_rec, ATTR_ID_ADDITION_PROTO_DESC_LISTS));
    /*
     * If we have the Additional Protocol Description Lists attribute then we
     * specifically want the list that is an L2CAP protocol leading to OBEX.
     * Because the is a case where cover art is supported and browsing isn't
     * we need to check each list for the one we want.
     *
     * This means we need to do drop down into the protocol list and do a
     * "for each protocol, for each protocol element, for each protocol element
     * list parameter, if the parameter is L2CAP then find the PSM associated
     * with it, then make sure we see OBEX in that same protocol"
     */
    if (p_attr != NULL && SDP_DISC_ATTR_TYPE(p_attr->attr_len_type)
        == DATA_ELE_SEQ_DESC_TYPE) {
      // Point to first in List of protocols (i.e [(L2CAP -> AVCTP),
      // (L2CAP -> OBEX)])
      tSDP_DISC_ATTR* p_protocol_list = p_attr->attr_value.v.p_sub_attr;
      while (p_protocol_list != NULL) {
        if (SDP_DISC_ATTR_TYPE(p_protocol_list->attr_len_type)
            == DATA_ELE_SEQ_DESC_TYPE) {
          // Point to fist in list of protocol elements (i.e. [L2CAP, AVCTP])
          tSDP_DISC_ATTR* p_protocol =
              p_protocol_list->attr_value.v.p_sub_attr;
          bool protocol_has_obex = false;
          bool protocol_has_l2cap = false;
          uint16_t psm = 0x0000;
          while (p_protocol) {
            if (SDP_DISC_ATTR_TYPE(p_protocol->attr_len_type)
                == DATA_ELE_SEQ_DESC_TYPE) {
              // Point to first item protocol parameters list (i.e [UUID=L2CAP,
              // PSM=0x1234])
              tSDP_DISC_ATTR* p_protocol_param =
                  p_protocol->attr_value.v.p_sub_attr;
              /*
               * Currently there's only ever one UUID and one parameter. L2cap
               * has a single PSM, AVCTP has a version and OBEX has nothing.
               * Change this if that ever changes.
               */
              uint16_t protocol_uuid = 0;
              uint16_t protocol_param = 0;
              while (p_protocol_param) {
                uint16_t param_type =
                    SDP_DISC_ATTR_TYPE(p_protocol_param->attr_len_type);
                uint16_t param_len =
                    SDP_DISC_ATTR_LEN(p_protocol_param->attr_len_type);
                if (param_type == UUID_DESC_TYPE) {
                  protocol_uuid = p_protocol_param->attr_value.v.u16;
                } else if (param_type == UINT_DESC_TYPE) {
                    protocol_param = (param_len == 2)
                      ? p_protocol_param->attr_value.v.u16
                      : p_protocol_param->attr_value.v.u8;
                } /* else dont care */
                p_protocol_param = p_protocol_param->p_next_attr;  // next
              }
              // If we've found L2CAP then the parameter is a PSM
              if (protocol_uuid == UUID_PROTOCOL_L2CAP) {
                protocol_has_l2cap = true;
                psm = protocol_param;
              } else if (protocol_uuid == UUID_PROTOCOL_OBEX) {
                protocol_has_obex = true;
              }
            }
            // If this protocol has l2cap and obex then we're found the BIP PSM
            if (protocol_has_l2cap && protocol_has_obex) {
              APPL_TRACE_DEBUG("%s: found psm 0x%x", __func__, psm);
              return psm;
            }
            p_protocol = p_protocol->p_next_attr;  // next protocol element
          }
        }
        p_protocol_list = p_protocol_list->p_next_attr;  // next protocol
      }
    }
    /* get next record; if none found, we're done */
    p_rec = SDP_FindServiceInDb(p_cb->p_disc_db,
        UUID_SERVCLASS_AV_REM_CTRL_TARGET, p_rec);
  }
  /* L2CAP PSM range is 0x1000-0xFFFF so 0x0000 is safe default invalid */
  APPL_TRACE_DEBUG("%s: could not find a BIP psm", __func__);
  return 0x0000;
}

/*******************************************************************************
 *
 * Function         bta_av_rc_disc_done
@@ -1771,6 +1876,7 @@ void bta_av_rc_disc_done(UNUSED_ATTR tBTA_AV_DATA* p_data) {
  tBTA_AV_LCB* p_lcb;
  uint8_t rc_handle;
  tBTA_AV_FEAT peer_features = 0; /* peer features mask */
  uint16_t cover_art_psm = 0x0000;

  APPL_TRACE_DEBUG("%s: bta_av_rc_disc_done disc:x%x", __func__, p_cb->disc);
  if (!p_cb->disc) {
@@ -1804,6 +1910,12 @@ void bta_av_rc_disc_done(UNUSED_ATTR tBTA_AV_DATA* p_data) {
    if (BTA_AV_FEAT_ADV_CTRL &
        bta_avk_check_peer_features(UUID_SERVCLASS_AV_REMOTE_CONTROL))
      peer_features |= (BTA_AV_FEAT_ADV_CTRL | BTA_AV_FEAT_RCCT);

    if (peer_features & BTA_AV_FEAT_COVER_ARTWORK)
      cover_art_psm = bta_avk_get_cover_art_psm();

    APPL_TRACE_DEBUG("%s: populating rem ctrl target bip psm 0x%x", __func__,
                     cover_art_psm);
  } else
#endif
      if (p_cb->sdp_a2dp_handle) {
@@ -1856,6 +1968,7 @@ void bta_av_rc_disc_done(UNUSED_ATTR tBTA_AV_DATA* p_data) {
          rc_handle = bta_av_rc_create(p_cb, AVCT_INT,
                                       (uint8_t)(p_scb->hdi + 1), p_lcb->lidx);
          p_cb->rcb[rc_handle].peer_features = peer_features;
          p_cb->rcb[rc_handle].cover_art_psm = cover_art_psm;
        } else {
          APPL_TRACE_ERROR("%s: can not find LCB!!", __func__);
        }
@@ -1865,6 +1978,7 @@ void bta_av_rc_disc_done(UNUSED_ATTR tBTA_AV_DATA* p_data) {
        tBTA_AV_RC_OPEN rc_open;
        rc_open.peer_addr = p_scb->PeerAddress();
        rc_open.peer_features = 0;
        rc_open.cover_art_psm = 0;
        rc_open.status = BTA_AV_FAIL_SDP;
        tBTA_AV bta_av_data;
        bta_av_data.rc_open = rc_open;
@@ -1886,9 +2000,28 @@ void bta_av_rc_disc_done(UNUSED_ATTR tBTA_AV_DATA* p_data) {
    } else {
      rc_feat.peer_addr = p_scb->PeerAddress();
    }
    tBTA_AV bta_av_data;
    bta_av_data.rc_feat = rc_feat;
    (*p_cb->p_cback)(BTA_AV_RC_FEAT_EVT, &bta_av_data);

    tBTA_AV bta_av_feat;
    bta_av_feat.rc_feat = rc_feat;
    (*p_cb->p_cback)(BTA_AV_RC_FEAT_EVT, &bta_av_feat);

    // Send PSM data
    APPL_TRACE_DEBUG("%s: Send PSM data", __func__);
    tBTA_AV_RC_PSM rc_psm;
    p_cb->rcb[rc_handle].cover_art_psm = cover_art_psm;
    rc_psm.rc_handle = rc_handle;
    rc_psm.cover_art_psm = cover_art_psm;
    if (p_scb == NULL) {
      rc_psm.peer_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx - 1].addr;
    } else {
      rc_psm.peer_addr = p_scb->PeerAddress();
    }

    APPL_TRACE_DEBUG("%s: rc_psm = 0x%x", __func__, rc_psm.cover_art_psm);

    tBTA_AV bta_av_psm;
    bta_av_psm.rc_cover_art_psm = rc_psm;
    (*p_cb->p_cback)(BTA_AV_RC_PSM_EVT, &bta_av_psm);
  }
}

@@ -1922,6 +2055,7 @@ void bta_av_rc_closed(tBTA_AV_DATA* p_data) {
      rc_close.rc_handle = i;
      p_rcb->status &= ~BTA_AV_RC_CONN_MASK;
      p_rcb->peer_features = 0;
      p_rcb->cover_art_psm = 0;
      APPL_TRACE_DEBUG("%s: shdl:%d, lidx:%d", __func__, p_rcb->shdl,
                       p_rcb->lidx);
      if (p_rcb->shdl) {
@@ -2044,7 +2178,8 @@ void bta_av_rc_disc(uint8_t disc) {
  tAVRC_SDP_DB_PARAMS db_params;
  uint16_t attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
                          ATTR_ID_BT_PROFILE_DESC_LIST,
                          ATTR_ID_SUPPORTED_FEATURES};
                          ATTR_ID_SUPPORTED_FEATURES,
                          ATTR_ID_ADDITION_PROTO_DESC_LISTS};
  uint8_t hdi;
  tBTA_AV_SCB* p_scb;
  RawAddress peer_addr = RawAddress::kEmpty;
@@ -2077,7 +2212,7 @@ void bta_av_rc_disc(uint8_t disc) {

    /* set up parameters */
    db_params.db_len = BTA_AV_DISC_BUF_SIZE;
    db_params.num_attr = 3;
    db_params.num_attr = sizeof(attr_list) / sizeof(uint16_t);
    db_params.p_db = p_cb->p_disc_db;
    db_params.p_attrs = attr_list;

+1 −0
Original line number Diff line number Diff line
@@ -571,6 +571,7 @@ typedef struct {
  uint8_t shdl;               /* stream handle (hdi + 1) */
  uint8_t lidx;               /* (index+1) to LCB */
  tBTA_AV_FEAT peer_features; /* peer features mask */
  uint16_t cover_art_psm;     /* BIP PSM for cover art feature */
} tBTA_AV_RCB;
#define BTA_AV_NUM_RCB (BTA_AV_NUM_STRS + 2)

+11 −1
Original line number Diff line number Diff line
@@ -145,8 +145,9 @@ typedef uint8_t tBTA_AV_ERR;
#define BTA_AV_OFFLOAD_START_RSP_EVT 22 /* a2dp offload start response */
#define BTA_AV_RC_BROWSE_OPEN_EVT 23    /* remote control channel open */
#define BTA_AV_RC_BROWSE_CLOSE_EVT 24   /* remote control channel closed */
#define BTA_AV_RC_PSM_EVT 25            /* cover art psm update */
/* Max BTA event */
#define BTA_AV_MAX_EVT 25
#define BTA_AV_MAX_EVT 26

typedef uint8_t tBTA_AV_EVT;

@@ -235,6 +236,7 @@ typedef struct {
/* data associated with BTA_AV_RC_OPEN_EVT */
typedef struct {
  uint8_t rc_handle;
  uint16_t cover_art_psm;
  tBTA_AV_FEAT peer_features;
  RawAddress peer_addr;
  tBTA_AV_STATUS status;
@@ -266,6 +268,13 @@ typedef struct {
  RawAddress peer_addr;
} tBTA_AV_RC_FEAT;

/* data associated with BTA_AV_RC_PSM_EVT */
typedef struct {
  uint8_t rc_handle;
  uint16_t cover_art_psm;
  RawAddress peer_addr;
} tBTA_AV_RC_PSM;

/* data associated with BTA_AV_REMOTE_CMD_EVT */
typedef struct {
  uint8_t rc_handle;
@@ -343,6 +352,7 @@ typedef union {
  tBTA_AV_META_MSG meta_msg;
  tBTA_AV_REJECT reject;
  tBTA_AV_RC_FEAT rc_feat;
  tBTA_AV_RC_PSM rc_cover_art_psm;
  tBTA_AV_STATUS status;
} tBTA_AV;

+8 −0
Original line number Diff line number Diff line
@@ -656,6 +656,7 @@ static BtifAvSink btif_av_sink;
  case BTA_AV_VENDOR_CMD_EVT:      \
  case BTA_AV_META_MSG_EVT:        \
  case BTA_AV_RC_FEAT_EVT:         \
  case BTA_AV_RC_PSM_EVT:          \
  case BTA_AV_REMOTE_RSP_EVT: {    \
    btif_rc_handler(e, d);         \
  } break;
@@ -729,6 +730,7 @@ const char* dump_av_sm_event_name(btif_av_sm_event_t event) {
    CASE_RETURN_STR(BTA_AV_META_MSG_EVT)
    CASE_RETURN_STR(BTA_AV_REJECT_EVT)
    CASE_RETURN_STR(BTA_AV_RC_FEAT_EVT)
    CASE_RETURN_STR(BTA_AV_RC_PSM_EVT)
    CASE_RETURN_STR(BTA_AV_OFFLOAD_START_RSP_EVT)
    CASE_RETURN_STR(BTIF_AV_CONNECT_REQ_EVT)
    CASE_RETURN_STR(BTIF_AV_DISCONNECT_REQ_EVT)
@@ -1543,6 +1545,7 @@ bool BtifAvStateMachine::StateIdle::ProcessEvent(uint32_t event, void* p_data) {
    case BTA_AV_VENDOR_CMD_EVT:
    case BTA_AV_META_MSG_EVT:
    case BTA_AV_RC_FEAT_EVT:
    case BTA_AV_RC_PSM_EVT:
    case BTA_AV_REMOTE_RSP_EVT:
      btif_rc_handler(event, (tBTA_AV*)p_data);
      break;
@@ -2571,6 +2574,11 @@ static void btif_av_handle_bta_av_event(uint8_t peer_sep,
      peer_address = rc_feat.peer_addr;
      break;
    }
    case BTA_AV_RC_PSM_EVT: {
      const tBTA_AV_RC_PSM& rc_psm = p_data->rc_cover_art_psm;
      peer_address = rc_psm.peer_addr;
      break;
    }
  }
  BTIF_TRACE_DEBUG("%s: peer_address=%s bta_handle=0x%x", __func__,
                   peer_address.ToString().c_str(), bta_handle);
+36 −2
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ typedef struct {
  bool br_connected;  // Browsing channel.
  uint8_t rc_handle;
  tBTA_AV_FEAT rc_features;
  uint16_t rc_cover_art_psm;  // AVRCP-BIP psm
  btrc_connection_state_t rc_state;
  RawAddress rc_addr;
  uint16_t rc_pending_play;
@@ -527,6 +528,15 @@ void handle_rc_ctrl_features(btif_rc_device_cb_t* p_dev) {
                                         p_dev->rc_addr, rc_features));
}

void handle_rc_ctrl_psm(btif_rc_device_cb_t* p_dev) {
  uint16_t cover_art_psm = p_dev->rc_cover_art_psm;
  BTIF_TRACE_DEBUG("%s: Update rc cover art psm to CTRL: %d", __func__,
      cover_art_psm);
  do_in_jni_thread(FROM_HERE, base::Bind(
      bt_rc_ctrl_callbacks->get_cover_art_psm_cb,
      p_dev->rc_addr, cover_art_psm));
}

void handle_rc_features(btif_rc_device_cb_t* p_dev) {

  CHECK(bt_rc_callbacks);
@@ -668,6 +678,9 @@ void handle_rc_connect(tBTA_AV_RC_OPEN* p_rc_open) {
  p_dev->rc_features = p_rc_open->peer_features;
  BTIF_TRACE_DEBUG("%s: handle_rc_connect in features: 0x%x out features 0x%x",
                   __func__, p_rc_open->peer_features, p_dev->rc_features);
  p_dev->rc_cover_art_psm = p_rc_open->cover_art_psm;
  BTIF_TRACE_DEBUG("%s: cover art psm: 0x%x",
                   __func__, p_dev->rc_cover_art_psm);
  p_dev->rc_vol_label = MAX_LABEL;
  p_dev->rc_volume = MAX_VOLUME;

@@ -688,6 +701,9 @@ void handle_rc_connect(tBTA_AV_RC_OPEN* p_rc_open) {
  }
  /* report connection state if remote device is AVRCP target */
  handle_rc_ctrl_features(p_dev);

  /* report psm if remote device is AVRCP target */
  handle_rc_ctrl_psm(p_dev);
}

/***************************************************************************
@@ -738,6 +754,7 @@ void handle_rc_disconnect(tBTA_AV_RC_CLOSE* p_rc_close) {
    memset(p_dev->rc_notif, 0, sizeof(p_dev->rc_notif));

    p_dev->rc_features = 0;
    p_dev->rc_cover_art_psm = 0;
    p_dev->rc_vol_label = MAX_LABEL;
    p_dev->rc_volume = MAX_VOLUME;

@@ -1011,8 +1028,9 @@ void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data) {
  btif_rc_device_cb_t* p_dev = NULL;
  switch (event) {
    case BTA_AV_RC_OPEN_EVT: {
      BTIF_TRACE_DEBUG("%s: Peer_features: %x", __func__,
                       p_data->rc_open.peer_features);
      BTIF_TRACE_DEBUG("%s: Peer_features: 0x%x Cover Art PSM: 0x%x", __func__,
                       p_data->rc_open.peer_features,
                       p_data->rc_open.cover_art_psm);
      handle_rc_connect(&(p_data->rc_open));
    } break;

@@ -1073,6 +1091,22 @@ void btif_rc_handler(tBTA_AV_EVT event, tBTA_AV* p_data) {
      }
    } break;

    case BTA_AV_RC_PSM_EVT: {
      BTIF_TRACE_DEBUG("%s: Peer cover art PSM: %x", __func__,
                       p_data->rc_cover_art_psm.cover_art_psm);
      p_dev = btif_rc_get_device_by_handle(p_data->rc_cover_art_psm.rc_handle);
      if (p_dev == NULL) {
        BTIF_TRACE_ERROR("%s: RC PSM event for Invalid rc handle",
                         __func__);
        break;
      }

      p_dev->rc_cover_art_psm = p_data->rc_cover_art_psm.cover_art_psm;
      if ((p_dev->rc_connected) && (bt_rc_ctrl_callbacks != NULL)) {
        handle_rc_ctrl_psm(p_dev);
      }
    } break;

    case BTA_AV_META_MSG_EVT: {
      if (bt_rc_callbacks != NULL) {
        BTIF_TRACE_DEBUG("%s: BTA_AV_META_MSG_EVT code: %d label: %d", __func__,
Loading