From 66b2807dcc2619cc4ad72cea629f0660df8ec553 Mon Sep 17 00:00:00 2001 From: Sumit Bajpai Date: Tue, 14 Jun 2016 15:25:37 +0530 Subject: [PATCH] Misc AV changes in stack 1) Update UI on remote's browsing support. 2) Avoid sending get capability request if Avrcp TG. 3) Use Interop database for Abs vol. 4) Add 30msec uinput delay upon creation. 5) Role switch failure handling. 6) Misc A2dp/Avrcp handling. CRs-Fixed: 1029888 Change-Id: I2e86285da9e9a0b7c5180fbefeb7665f62ac77cd --- bta/av/bta_av_act.c | 4 ---- bta/av/bta_av_cfg.c | 2 ++ bta/av/bta_av_main.c | 21 ++++++++++++++---- btif/src/btif_av.c | 8 ++++--- btif/src/btif_rc.c | 30 +++++++++++++------------ stack/avct/avct_l2c.c | 8 +++---- stack/avrc/avrc_api.c | 58 +++++++++++++++++++++++++++++++++++++++--------- stack/avrc/avrc_bld_tg.c | 8 +++---- 8 files changed, 95 insertions(+), 44 deletions(-) diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c index 6138bc9f4..d80128d10 100644 --- a/bta/av/bta_av_act.c +++ b/bta/av/bta_av_act.c @@ -2279,10 +2279,6 @@ void bta_av_rc_closed(tBTA_AV_DATA *p_data) { /* AVCT CCB is still there. dealloc */ bta_av_del_rc(p_rcb); - - /* if the AVRCP is no longer listening, create the listening channel */ - if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE && bta_av_cb.features & BTA_AV_FEAT_RCTG) - bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1); } } else if ((p_rcb->handle != BTA_AV_RC_HANDLE_NONE) && (p_rcb->status & BTA_AV_RC_CONN_MASK)) diff --git a/bta/av/bta_av_cfg.c b/bta/av/bta_av_cfg.c index fcfebad08..0c3011b1c 100644 --- a/bta/av/bta_av_cfg.c +++ b/bta/av/bta_av_cfg.c @@ -41,6 +41,8 @@ const UINT32 bta_av_meta_caps_co_ids[] = { /* AVRCP cupported categories */ #if (AVRC_CTLR_INCLUDED == TRUE) +#define BTA_AV_RC_SUPF_CT (AVRC_SUPF_CT_CAT1 | AVRC_SUPF_CT_CAT2) +#else #define BTA_AV_RC_SUPF_CT (AVRC_SUPF_CT_CAT2) #endif diff --git a/bta/av/bta_av_main.c b/bta/av/bta_av_main.c index c37271f1d..3fafca729 100644 --- a/bta/av/bta_av_main.c +++ b/bta/av/bta_av_main.c @@ -1139,6 +1139,7 @@ BOOLEAN bta_av_switch_if_needed(tBTA_AV_SCB *p_scb) UINT8 role; BOOLEAN needed = FALSE; tBTA_AV_SCB *p_scbi; + tBTM_STATUS ret; int i; UINT8 mask; @@ -1156,7 +1157,11 @@ BOOLEAN bta_av_switch_if_needed(tBTA_AV_SCB *p_scb) { if (bta_av_cb.features & BTA_AV_FEAT_MASTER) bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scbi->peer_addr); - if (BTM_CMD_STARTED != BTM_SwitchRole(p_scbi->peer_addr, BTM_ROLE_MASTER, NULL)) + ret = BTM_SwitchRole(p_scbi->peer_addr, BTM_ROLE_MASTER, NULL); + if (ret == BTM_REPEATED_ATTEMPTS) + return FALSE; + + if (BTM_CMD_STARTED != ret) { /* can not switch role on SCBI * start the timer on SCB - because this function is ONLY called when SCB gets API_OPEN */ @@ -1188,18 +1193,26 @@ BOOLEAN bta_av_link_role_ok(tBTA_AV_SCB *p_scb, UINT8 bits) { UINT8 role; BOOLEAN is_ok = TRUE; + tBTM_STATUS ret; if (BTM_GetRole(p_scb->peer_addr, &role) == BTM_SUCCESS) { - LOG_INFO(LOG_TAG, "%s hndl:x%x role:%d conn_audio:x%x bits:%d features:x%x", + LOG_INFO("%s hndl:x%x role:%d conn_audio:x%x bits:%d features:x%x", __func__, p_scb->hndl, role, bta_av_cb.conn_audio, bits, bta_av_cb.features); if (BTM_ROLE_MASTER != role && (A2D_BitsSet(bta_av_cb.conn_audio) > bits || (bta_av_cb.features & BTA_AV_FEAT_MASTER))) { if (bta_av_cb.features & BTA_AV_FEAT_MASTER) bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scb->peer_addr); - - if (BTM_CMD_STARTED != BTM_SwitchRole(p_scb->peer_addr, BTM_ROLE_MASTER, NULL)) + ret = BTM_SwitchRole(p_scb->peer_addr, BTM_ROLE_MASTER, NULL); + /* We have already reached maximum attempts, + * If we try again it will anyways fail + * return from here + * */ + if (ret == BTM_REPEATED_ATTEMPTS) + return TRUE; + + if (BTM_CMD_STARTED != ret) { /* can not switch role on SCB - start the timer on SCB */ } diff --git a/btif/src/btif_av.c b/btif/src/btif_av.c index 437a2ba4c..1f526d24c 100644 --- a/btif/src/btif_av.c +++ b/btif/src/btif_av.c @@ -599,6 +599,8 @@ static BOOLEAN btif_av_state_idle_handler(btif_sm_event_t event, void *p_data, i else if ((btif_av_cb[index].peer_sep == AVDT_TSEP_SRC) && (p_bta_data->open.status == BTA_AV_SUCCESS)) { + /* if queued PLAY command, send it now */ + btif_rc_check_handle_pending_play(p_bta_data->open.bd_addr, FALSE); /* Bring up AVRCP connection too */ BTA_AvOpenRc(btif_av_cb[index].bta_handle); } @@ -1652,13 +1654,13 @@ static void btif_av_handle_event(UINT16 event, char* p_param) switch (event) { case BTIF_AV_INIT_REQ_EVT: - BTIF_TRACE_DEBUG("%s: BTIF_AV_INIT_REQ_EVT", __FUNCTION__); + BTIF_TRACE_IMP("%s: BTIF_AV_INIT_REQ_EVT", __FUNCTION__); if(btif_a2dp_start_media_task()) btif_a2dp_on_init(); break; /*events from Upper layer and Media Task*/ case BTIF_AV_CLEANUP_REQ_EVT: /*Clean up to be called on default index*/ - BTIF_TRACE_DEBUG("%s: BTIF_AV_CLEANUP_REQ_EVT", __FUNCTION__); + BTIF_TRACE_IMP("%s: BTIF_AV_CLEANUP_REQ_EVT", __FUNCTION__); uuid = (int)*p_param; if (uuid == BTA_A2DP_SOURCE_SERVICE_ID) { @@ -2457,7 +2459,7 @@ static bt_status_t disconnect(bt_bdaddr_t *bd_addr) static void cleanup(int service_uuid) { int i; - BTIF_TRACE_EVENT("%s", __FUNCTION__); + BTIF_TRACE_IMP("AV %s", __FUNCTION__); btif_transfer_context(btif_av_handle_event, BTIF_AV_CLEANUP_REQ_EVT, (char*)&service_uuid, sizeof(int), NULL); diff --git a/btif/src/btif_rc.c b/btif/src/btif_rc.c index b33f84309..83eae059c 100644 --- a/btif/src/btif_rc.c +++ b/btif/src/btif_rc.c @@ -366,8 +366,10 @@ static void rc_start_play_status_timer(void); static bool absolute_volume_disabled(void); static void btif_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND* p_param, UINT8 ctype, UINT8 label, int index); +#if (AVRC_ADV_CTRL_INCLUDED == TRUE) static void btif_rc_upstreams_rsp_evt(UINT16 event, tAVRC_RESPONSE *pavrc_resp, UINT8 ctype, UINT8 label, int index); +#endif static bt_status_t set_addrplayer_rsp(btrc_status_t status_code, bt_bdaddr_t *bd_addr); static int btif_rc_get_idx_by_addr(BD_ADDR address); @@ -394,7 +396,6 @@ static UINT8 btif_rc_get_idx_by_rc_handle(UINT8 rc_handle); ******************************************************************************/ extern BOOLEAN btif_hf_call_terminated_recently(); extern BOOLEAN check_cod(const bt_bdaddr_t *remote_bdaddr, uint32_t cod); - extern void btif_get_latest_playing_device(BD_ADDR address); //get the Playing device address extern BOOLEAN btif_av_is_playing(); extern BOOLEAN btif_av_is_device_connected(BD_ADDR address); @@ -503,6 +504,8 @@ int uinput_create(char *name) close(fd); return -1; } + BTIF_TRACE_IMP("AVRCP: input device opened.. Delay 30 ms"); + sleep_ms(30); return fd; } @@ -604,9 +607,9 @@ void handle_rc_features(int index) bdaddr_to_string(&avdtp_addr, addr1, sizeof(bdstr_t)), bdaddr_to_string(&rc_addr, addr2, sizeof(bdstr_t)) ); - //if (interop_match(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr) - if (absolute_volume_disabled() - || bdcmp(avdtp_addr.address, rc_addr.address)) + if (interop_match_addr(INTEROP_DISABLE_ABSOLUTE_VOLUME, &rc_addr) + || absolute_volume_disabled() + || bdcmp(avdtp_addr.address, rc_addr.address)) btif_rc_cb[index].rc_features &= ~BTA_AV_FEAT_ADV_CTRL; if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_BROWSE) @@ -621,22 +624,20 @@ void handle_rc_features(int index) if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_METADATA) { rc_features |= BTRC_FEAT_METADATA; - /* Mark rc features processed to avoid repeating - * the AVRCP procedure every time on receiving this - * update. - */ - btif_rc_cb[index].rc_features_processed = TRUE; - getcapabilities_cmd (AVRC_CAP_COMPANY_ID); } - BTIF_TRACE_DEBUG("%s: rc_features=0x%x", __FUNCTION__, rc_features); + if (btif_rc_cb[index].rc_features & BTA_AV_FEAT_AVRC_UI_UPDATE) + { + rc_features |= BTRC_FEAT_AVRC_UI_UPDATE; + } + BTIF_TRACE_IMP("%s: rc_features=0x%x", __FUNCTION__, rc_features); if (btif_rc_cb[index].rc_connected) { - BTIF_TRACE_DEBUG("%s: update App on supported features", __FUNCTION__); + BTIF_TRACE_IMP("%s: update App on supported features", __FUNCTION__); HAL_CBACK(bt_rc_callbacks, remote_features_cb, &rc_addr, rc_features) } else { - BTIF_TRACE_DEBUG("%s: skipping feature update to App", __FUNCTION__); + BTIF_TRACE_IMP("%s: skipping feature update to App", __FUNCTION__); } #if (AVRC_ADV_CTRL_INCLUDED == TRUE) BTIF_TRACE_DEBUG("Checking for feature flags in btif_rc_handler with label %d", @@ -3555,6 +3556,7 @@ static bt_status_t get_itemattr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p UINT32 i; tAVRC_ATTR_ENTRY element_attrs[MAX_ELEM_ATTR_SIZE]; int valid_attr, rc_index = btif_rc_get_idx_by_addr(bd_addr->address); + CHECK_RC_CONNECTED valid_attr = 0; if (rc_index == btif_max_rc_clients) @@ -3563,7 +3565,7 @@ static bt_status_t get_itemattr_rsp(uint8_t num_attr, btrc_element_attr_val_t *p return BT_STATUS_FAIL; } BTIF_TRACE_DEBUG("- %s on index = %d", __FUNCTION__, rc_index); - CHECK_RC_CONNECTED + memset(element_attrs, 0, sizeof(tAVRC_ATTR_ENTRY) * num_attr); if (num_attr == 0) diff --git a/stack/avct/avct_l2c.c b/stack/avct/avct_l2c.c index 674500d8f..231039013 100644 --- a/stack/avct/avct_l2c.c +++ b/stack/avct/avct_l2c.c @@ -288,10 +288,10 @@ void avct_l2c_br_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UIN p_bcb->ch_lcid = lcid; /*Updadate LCID so that on config associated bcb could be found*/ ertm_info.preferred_mode = L2CAP_FCR_ERTM_MODE; ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM; - ertm_info.user_rx_buf_size = 4096;//AVCT_BR_USER_RX_BUF_SIZE; - ertm_info.user_tx_buf_size = 4096;//AVCT_BR_USER_TX_BUF_SIZE; - ertm_info.fcr_rx_buf_size = 4096;//AVCT_BR_FCR_RX_BUF_SIZE; - ertm_info.fcr_tx_buf_size = 4096;//AVCT_BR_FCR_TX_BUF_SIZE; + ertm_info.user_rx_buf_size = AVCT_BR_USER_RX_BUF_SIZE; + ertm_info.user_tx_buf_size = AVCT_BR_USER_TX_BUF_SIZE; + ertm_info.fcr_rx_buf_size = AVCT_BR_FCR_RX_BUF_SIZE; + ertm_info.fcr_tx_buf_size = AVCT_BR_FCR_TX_BUF_SIZE; p_ertm_info = &ertm_info; L2CA_ErtmConnectRsp (bd_addr, id, lcid, result, L2CAP_CONN_OK, p_ertm_info); } diff --git a/stack/avrc/avrc_api.c b/stack/avrc/avrc_api.c index 7838823f4..ade3b855a 100644 --- a/stack/avrc/avrc_api.c +++ b/stack/avrc/avrc_api.c @@ -106,6 +106,29 @@ static UINT8 * avrc_get_data_ptr(BT_HDR *p_pkt) /****************************************************************************** ** +** Function avrc_get_packet_type +** +** Description Gets a packet type for fragmanted packet. +** +** Returns Type of fragmenatation packet. +** +******************************************************************************/ +static UINT8 avrc_get_packet_type(BT_HDR *pp_pkt) +{ + BT_HDR *p_pkt = pp_pkt; + UINT8 *p_data; + UINT8 pkt_type; + p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset; + /* Skip over vendor header (ctype, subunit*, opcode, CO_ID) */ + p_data += AVRC_VENDOR_HDR_SIZE; + + pkt_type = *(p_data + 1) & AVRC_PKT_TYPE_MASK; + + return pkt_type; +} + +/****************************************************************************** +** ** Function avrc_copy_packet ** ** Description Copies an AVRC packet to a new buffer. In the new buffer, @@ -236,6 +259,7 @@ static BT_HDR * avrc_proc_vendor_command(UINT8 handle, UINT8 label, UINT8 *p_data; UINT8 *p_begin; UINT8 pkt_type; + UINT8 *p_rsp_data; BOOLEAN abort_frag = FALSE; tAVRC_STS status = AVRC_STS_NO_ERROR; tAVRC_FRAG_CB *p_fcb; @@ -316,15 +340,15 @@ static BT_HDR * avrc_proc_vendor_command(UINT8 handle, UINT8 label, if (status != AVRC_STS_NO_ERROR) { - /* use the current GKI buffer to build/send the reject message */ - p_data = (UINT8 *)(p_pkt+1) + p_pkt->offset; - *p_data++ = AVRC_RSP_REJ; - p_data += AVRC_VENDOR_HDR_SIZE; /* pdu */ - *p_data++ = 0; /* pkt_type */ - UINT16_TO_BE_STREAM(p_data, 1); /* len */ - *p_data++ = status; /* error code */ - p_pkt->len = AVRC_VENDOR_HDR_SIZE + 5; - p_rsp = p_pkt; + /* check for buffer size before modifing it */ + p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_REJ_MSG_LEN); + p_rsp_data = avrc_get_data_ptr(p_rsp); + *p_rsp_data++ = AVRC_RSP_REJ; + p_rsp_data += AVRC_VENDOR_HDR_SIZE; /* pdu 1 byte*/ + *p_rsp_data++ = 0; /* pkt_type 1 byte*/ + UINT16_TO_BE_STREAM(p_rsp_data, 1); /* len 2 byte */ + *p_rsp_data++ = status; /* error code 1 byte*/ + p_rsp->len = AVRC_VENDOR_HDR_SIZE + 5; } return p_rsp; @@ -579,7 +603,7 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr, msg.hdr.subunit_id = p_data[1] & AVRC_SUBID_MASK; opcode = p_data[2]; } - + AVRC_TRACE_DEBUG("opcode %d",opcode); if ( ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD)) || ((avrc_cb.ccb[handle].control & AVRC_CT_CONTROL) && (cr == AVCT_RSP)) ) { @@ -672,6 +696,18 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr, #if (AVRC_METADATA_INCLUDED == TRUE) UINT8 drop_code = 0; + if (p_msg->vendor_len > AVRC_META_CMD_BUF_SIZE) + { + int packet_type = avrc_get_packet_type(p_pkt); + AVRC_TRACE_DEBUG("packet_type %d", packet_type); + //single packet size is greater then MTU size, reject it + if (packet_type == AVRC_PKT_SINGLE) + { + AVRC_TRACE_ERROR("Incorrect lenght for single packet"); + reject = TRUE; + break; + } + } drop_code = avrc_proc_far_msg(handle, label, cr, &p_pkt, p_msg); if (drop_code > 0) drop = TRUE; @@ -786,7 +822,7 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr, opcode = p_data[0]; AVRC_TRACE_DEBUG("opcode:%x, length:%x",opcode, p_pkt->len); /*Do sanity Check here*/ - if (cr == AVCT_CMD) + if ((avrc_cb.ccb[handle].control & AVRC_CT_TARGET) && (cr == AVCT_CMD)) { opcode = AVRC_OP_BROWSE; msg.browse.browse_len = p_pkt->len; diff --git a/stack/avrc/avrc_bld_tg.c b/stack/avrc/avrc_bld_tg.c index 60a4cd3a7..5c184e75a 100644 --- a/stack/avrc/avrc_bld_tg.c +++ b/stack/avrc/avrc_bld_tg.c @@ -649,9 +649,6 @@ static tAVRC_STS avrc_bld_notify_rsp (tAVRC_REG_NOTIF_RSP *p_rsp, BT_HDR *p_pkt) status = AVRC_STS_BAD_PARAM; break; - case AVRC_EVT_VOLUME_CHANGE: - len = 2; - UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_rsp->param.volume)); case AVRC_EVT_AVAL_PLAYERS_CHANGE: len = EVT_AVAIL_PLAYER_CHANGE_RSP_LENGTH; break; @@ -665,7 +662,10 @@ static tAVRC_STS avrc_bld_notify_rsp (tAVRC_REG_NOTIF_RSP *p_rsp, BT_HDR *p_pkt) case AVRC_EVT_NOW_PLAYING_CHANGE: len = EVT_NOW_PLAYING_CHANGE_RSP_LENGTH; break; - + case AVRC_EVT_VOLUME_CHANGE: + len = 2; + UINT8_TO_BE_STREAM(p_data, (AVRC_MAX_VOLUME & p_rsp->param.volume)); + break; default: status = AVRC_STS_BAD_PARAM; AVRC_TRACE_ERROR("%s unknown event_id", __func__); -- 2.11.0