Loading system/bta/av/bta_av_act.cc +140 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 */ Loading Loading @@ -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 Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -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__); } Loading @@ -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; Loading @@ -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); } } Loading Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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; Loading system/bta/av/bta_av_int.h +1 −0 Original line number Diff line number Diff line Loading @@ -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) Loading system/bta/include/bta_av_api.h +11 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading system/btif/src/btif_av.cc +8 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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); Loading system/btif/src/btif_rc.cc +36 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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); } /*************************************************************************** Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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 Loading
system/bta/av/bta_av_act.cc +140 −5 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 */ Loading Loading @@ -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 Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -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__); } Loading @@ -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; Loading @@ -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); } } Loading Loading @@ -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) { Loading Loading @@ -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; Loading Loading @@ -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; Loading
system/bta/av/bta_av_int.h +1 −0 Original line number Diff line number Diff line Loading @@ -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) Loading
system/bta/include/bta_av_api.h +11 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading
system/btif/src/btif_av.cc +8 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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; Loading Loading @@ -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); Loading
system/btif/src/btif_rc.cc +36 −2 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -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; Loading @@ -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); } /*************************************************************************** Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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