From: Ted Wang Date: Mon, 18 May 2020 10:02:34 +0000 (+0800) Subject: Respond AVRCP profile descritpion list 1.4 only for some device X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=f875ec4498eb35b858fafb7737101960ef7f86c3;p=android-x86%2Fsystem-bt.git Respond AVRCP profile descritpion list 1.4 only for some device Some devices (Toyota Car Audio), will not perfomance general AVRCP initial action like get capabilities or register for any notification when receiving AVRCP profile version 1.5. Create black list for these devices so we can reply AVRCP 1.4 when we are in higher AVRCP version. Bug: 154780267 Test: manaul Change-Id: If6c9453ad1f844d255fade63afad828b185b7fdf --- diff --git a/device/include/interop.h b/device/include/interop.h index d7ca917bd..02c1a5e46 100644 --- a/device/include/interop.h +++ b/device/include/interop.h @@ -99,7 +99,10 @@ typedef enum { // The public address of these devices are same as the Random address in ADV. // Then will get name by LE_Create_connection, actually fails, // but will block pairing. - INTEROP_DISABLE_NAME_REQUEST + INTEROP_DISABLE_NAME_REQUEST, + + // Respond AVRCP profile version only 1.4 for some device. + INTEROP_AVRCP_1_4_ONLY } interop_feature_t; // Check if a given |addr| matches a known interoperability workaround as diff --git a/device/include/interop_database.h b/device/include/interop_database.h index b4b1b07d9..548395b4f 100644 --- a/device/include/interop_database.h +++ b/device/include/interop_database.h @@ -150,6 +150,9 @@ static const interop_addr_entry_t interop_addr_database[] = { // for skip name request, // because BR/EDR address and ADV random address are the same {{{0xd4, 0x7a, 0xe2, 0, 0, 0}}, 3, INTEROP_DISABLE_NAME_REQUEST}, + + // Toyota Car Audio + {{{0x00, 0x17, 0x53, 0, 0, 0}}, 3, INTEROP_AVRCP_1_4_ONLY}, }; typedef struct { diff --git a/device/src/interop.cc b/device/src/interop.cc index 9a701b1c0..74543bf94 100644 --- a/device/src/interop.cc +++ b/device/src/interop.cc @@ -132,6 +132,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) { CASE_RETURN_STR(INTEROP_DISABLE_ROLE_SWITCH) CASE_RETURN_STR(INTEROP_HID_HOST_LIMIT_SNIFF_INTERVAL) CASE_RETURN_STR(INTEROP_DISABLE_NAME_REQUEST) + CASE_RETURN_STR(INTEROP_AVRCP_1_4_ONLY) } return "UNKNOWN"; diff --git a/stack/sdp/sdp_server.cc b/stack/sdp/sdp_server.cc index 9b9ad30f9..44cc7bad5 100644 --- a/stack/sdp/sdp_server.cc +++ b/stack/sdp/sdp_server.cc @@ -29,6 +29,8 @@ #include "bt_common.h" #include "bt_types.h" +#include "avrc_defs.h" +#include "device/include/interop.h" #include "osi/include/osi.h" #include "sdp_api.h" #include "sdpint.h" @@ -548,6 +550,7 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, tSDP_RECORD* p_rec; tSDP_ATTR_SEQ attr_seq, attr_seq_sav; tSDP_ATTRIBUTE* p_attr; + tSDP_ATTRIBUTE attr_sav; bool maxxed_out = false, is_cont = false; uint8_t* p_seq_start; uint16_t seq_len, attr_len; @@ -646,6 +649,19 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, attr_seq.attr_entry[xx].end); if (p_attr) { + // Check if the attribute contain AVRCP profile description list + uint16_t avrcp_version = sdpu_is_avrcp_profile_description_list(p_attr); + if (avrcp_version > AVRC_REV_1_4 && + interop_match_addr(INTEROP_AVRCP_1_4_ONLY, + &(p_ccb->device_address))) { + SDP_TRACE_DEBUG( + "%s, device=%s is only accept AVRCP 1.4, reply AVRCP 1.4 " + "instead.", + __func__, p_ccb->device_address.ToString().c_str()); + memcpy(&attr_sav, p_attr, sizeof(tSDP_ATTRIBUTE)); + attr_sav.value_ptr[attr_sav.len - 1] = 0x04; + p_attr = &attr_sav; + } /* Check if attribute fits. Assume 3-byte value type/length */ rem_len = max_list_len - (int16_t)(p_rsp - &p_ccb->rsp_list[0]); @@ -825,5 +841,4 @@ static void process_service_search_attr_req(tCONN_CB* p_ccb, uint16_t trans_num, /* Send the buffer through L2CAP */ L2CA_DataWrite(p_ccb->connection_id, p_buf); } - #endif /* SDP_SERVER_ENABLED == TRUE */ diff --git a/stack/sdp/sdp_utils.cc b/stack/sdp/sdp_utils.cc index f66a8fd39..f8cde2c34 100644 --- a/stack/sdp/sdp_utils.cc +++ b/stack/sdp/sdp_utils.cc @@ -31,6 +31,7 @@ #include "bt_types.h" #include "btif_config.h" +#include "avrc_defs.h" #include "sdp_api.h" #include "sdpint.h" @@ -1155,3 +1156,41 @@ uint8_t* sdpu_build_partial_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr, osi_free(p_attr_buff); return p_out; } +/******************************************************************************* + * + * Function sdpu_is_avrcp_profile_description_list + * + * Description This function is to check if attirbute contain AVRCP profile + * description list + * + * p_attr: attibute to be check + * + * Returns AVRCP profile version if matched, else 0 + * + ******************************************************************************/ +uint16_t sdpu_is_avrcp_profile_description_list(tSDP_ATTRIBUTE* p_attr) { + if (p_attr->id != ATTR_ID_BT_PROFILE_DESC_LIST || p_attr->len != 8) { + return 0; + } + + uint8_t* p_uuid = p_attr->value_ptr + 3; + // Check if AVRCP profile UUID + if (p_uuid[0] != 0x11 || p_uuid[1] != 0xe) { + return 0; + } + uint8_t p_version = *(p_uuid + 4); + switch (p_version) { + case 0x0: + return AVRC_REV_1_0; + case 0x3: + return AVRC_REV_1_3; + case 0x4: + return AVRC_REV_1_4; + case 0x5: + return AVRC_REV_1_5; + case 0x6: + return AVRC_REV_1_6; + default: + return 0; + } +} diff --git a/stack/sdp/sdpint.h b/stack/sdp/sdpint.h index af9ccb824..ea6941cdb 100644 --- a/stack/sdp/sdpint.h +++ b/stack/sdp/sdpint.h @@ -235,6 +235,7 @@ extern uint16_t sdpu_get_attrib_entry_len(tSDP_ATTRIBUTE* p_attr); extern uint8_t* sdpu_build_partial_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr, uint16_t len, uint16_t* offset); +extern uint16_t sdpu_is_avrcp_profile_description_list(tSDP_ATTRIBUTE* p_attr); /* Functions provided by sdp_db.cc */