• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

system/bt


Commit MetaInfo

Revision6b3a12d3ad7fafa30341edc3ac125409f944d43b (tree)
Zeit2017-05-08 17:36:03
Autorsiminy <siminy@code...>
CommiterGerrit - the friendly Code Review server

Log Message

SDP: Add logic to downgrade PBAP version for blacklisted device

As some remote devices go in bad state on parsing PBAP 1.2 SDP record.
Add them to PBAP version downgrade blacklist.Upgrade PBAP version
downgrade logic from to include name based blacklist and also remove
SDP attributes not suppported in PBAP 1.1 specifications like
GoepL2capPsm, SupportedFeatures.

CRs-Fixed: 2038030
Change-Id: I7fdb0433353ba5793470313d205a68e8eb3fb5ac

Ändern Zusammenfassung

Diff

--- a/device/include/interop.h
+++ b/device/include/interop.h
@@ -110,6 +110,11 @@ typedef enum {
110110 // Some car kits going bad state when DUT initiate profile connection in collision scenerio
111111 // Hence don't initaite profile level connections and wait for incoming connetcion
112112 INTEROP_DISABLE_CONNECTION_AFTER_COLLISION,
113+
114+ // Devices requiring this workaround do not handle Bluetooth PBAP 1.2 version correctly,
115+ // leading them to go in bad state. So for better interoperability respond with PBAP 1.1
116+ // as supported version.
117+ INTEROP_ADV_PBAP_VER_1_1,
113118 } interop_feature_t;
114119
115120 // Check if a given |addr| matches a known interoperability workaround as identified
--- a/device/include/interop_database.h
+++ b/device/include/interop_database.h
@@ -127,6 +127,13 @@ static const interop_addr_entry_t interop_addr_database[] = {
127127 {{{0x04, 0xf8, 0xc2, 0,0,0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
128128 // HONDA HFT
129129 {{{0xA0, 0x14, 0x3D, 0,0,0}}, 3, INTEROP_DISABLE_CONNECTION_AFTER_COLLISION},
130+
131+ // Land Rover Carkit(s)
132+ {{{0x00, 0x00, 0x31, 0,0,0}}, 3, INTEROP_ADV_PBAP_VER_1_1},
133+ {{{0x00, 0x00, 0x41, 0,0,0}}, 3, INTEROP_ADV_PBAP_VER_1_1},
134+ {{{0x00, 0x00, 0x6a, 0,0,0}}, 3, INTEROP_ADV_PBAP_VER_1_1},
135+ {{{0x00, 0x00, 0x7f, 0,0,0}}, 3, INTEROP_ADV_PBAP_VER_1_1},
136+ {{{0x00, 0x01, 0x0a, 0,0,0}}, 3, INTEROP_ADV_PBAP_VER_1_1},
130137 };
131138
132139 typedef struct {
@@ -167,6 +174,9 @@ static const interop_name_entry_t interop_name_database[] = {
167174 {"Motorola Keyboard KZ500", 23, INTEROP_REMOVE_HID_DIG_DESCRIPTOR},
168175 {"Motorola Keyboard KZ500 v122", 28, INTEROP_REMOVE_HID_DIG_DESCRIPTOR},
169176 {"MB Bluetooth", 12, INTEROP_ADV_AVRCP_VER_1_3},
177+
178+ // Land Rover Carkit
179+ {"Discovery Sport", 15, INTEROP_ADV_PBAP_VER_1_1},
170180 };
171181
172182 typedef struct {
--- a/device/src/interop.c
+++ b/device/src/interop.c
@@ -60,7 +60,7 @@ bool interop_match_name(const interop_feature_t feature, const char *name) {
6060 const size_t db_size = sizeof(interop_name_database) / sizeof(interop_name_entry_t);
6161 for (size_t i = 0; i != db_size; ++i) {
6262 if (feature == interop_name_database[i].feature &&
63- strlen(name) >= interop_name_database[i].length &&
63+ strlen(name) == interop_name_database[i].length &&
6464 strncmp(name, interop_name_database[i].name, interop_name_database[i].length) == 0) {
6565 LOG_WARN(LOG_TAG, "%s() Device with name: %s is a match for interop workaround %s", __func__,
6666 name, interop_feature_string_(feature));
@@ -157,6 +157,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) {
157157 CASE_RETURN_STR(INTEROP_DISABLE_LE_CONN_PREFERRED_PARAMS)
158158 CASE_RETURN_STR(INTEROP_ADV_AVRCP_VER_1_3)
159159 CASE_RETURN_STR(INTEROP_DISABLE_CONNECTION_AFTER_COLLISION)
160+ CASE_RETURN_STR(INTEROP_ADV_PBAP_VER_1_1)
160161 }
161162
162163 return "UNKNOWN";
--- a/stack/sdp/sdp_db.c
+++ b/stack/sdp/sdp_db.c
@@ -398,7 +398,7 @@ BOOLEAN SDP_AddAttribute (UINT32 handle, UINT16 attr_id, UINT8 attr_type,
398398 UINT32 attr_len, UINT8 *p_val)
399399 {
400400 #if SDP_SERVER_ENABLED == TRUE
401- UINT16 xx, yy, zz;
401+ UINT16 xx;
402402 tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0];
403403
404404 #if (BT_TRACE_VERBOSE == TRUE)
@@ -436,81 +436,84 @@ BOOLEAN SDP_AddAttribute (UINT32 handle, UINT16 attr_id, UINT8 attr_type,
436436 #endif
437437
438438 /* Find the record in the database */
439- for (zz = 0; zz < sdp_cb.server_db.num_records; zz++, p_rec++)
439+ for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++)
440440 {
441441 if (p_rec->record_handle == handle)
442- {
443- tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0];
442+ return SDP_AddAttributetoRecord (p_rec, attr_id, attr_type, attr_len, p_val);
443+ }
444+#endif
445+ return (FALSE);
446+}
444447
445- /* Found the record. Now, see if the attribute already exists */
446- for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
447- {
448- /* The attribute exists. replace it */
449- if (p_attr->id == attr_id)
450- {
451- SDP_DeleteAttribute (handle, attr_id);
452- break;
453- }
454- if (p_attr->id > attr_id)
455- break;
456- }
448+BOOLEAN SDP_AddAttributetoRecord (tSDP_RECORD *p_rec, UINT16 attr_id, UINT8 attr_type,
449+ UINT32 attr_len, UINT8 *p_val)
450+{
451+ UINT16 xx, yy;
452+ tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0];
453+ /* Found the record. Now, see if the attribute already exists */
454+ for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
455+ {
456+ /* The attribute exists. replace it */
457+ if (p_attr->id == attr_id)
458+ {
459+ SDP_DeleteAttributefromRecord (p_rec, attr_id);
460+ break;
461+ }
462+ if (p_attr->id > attr_id)
463+ break;
464+ }
457465
458- if (p_rec->num_attributes == SDP_MAX_REC_ATTR)
459- return (FALSE);
466+ if (p_rec->num_attributes == SDP_MAX_REC_ATTR)
467+ return (FALSE);
460468
461- /* If not found, see if we can allocate a new entry */
462- if (xx == p_rec->num_attributes)
463- p_attr = &p_rec->attribute[p_rec->num_attributes];
464- else
465- {
466- /* Since the attributes are kept in sorted order, insert ours here */
467- for (yy = p_rec->num_attributes; yy > xx; yy--)
468- p_rec->attribute[yy] = p_rec->attribute[yy - 1];
469- }
469+ /* If not found, see if we can allocate a new entry */
470+ if (xx == p_rec->num_attributes)
471+ p_attr = &p_rec->attribute[p_rec->num_attributes];
472+ else
473+ {
474+ /* Since the attributes are kept in sorted order, insert ours here */
475+ for (yy = p_rec->num_attributes; yy > xx; yy--)
476+ p_rec->attribute[yy] = p_rec->attribute[yy - 1];
477+ }
470478
471- p_attr->id = attr_id;
472- p_attr->type = attr_type;
473- p_attr->len = attr_len;
479+ p_attr->id = attr_id;
480+ p_attr->type = attr_type;
481+ p_attr->len = attr_len;
474482
475- if (p_rec->free_pad_ptr + attr_len >= SDP_MAX_PAD_LEN)
476- {
477- /* do truncate only for text string type descriptor */
478- if (attr_type == TEXT_STR_DESC_TYPE)
479- {
480- SDP_TRACE_WARNING("SDP_AddAttribute: attr_len:%d too long. truncate to (%d)",
481- attr_len, SDP_MAX_PAD_LEN - p_rec->free_pad_ptr );
482-
483- attr_len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr;
484- p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr] = '\0';
485- p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr+1] = '\0';
486- }
487- else
488- attr_len = 0;
489- }
483+ if (p_rec->free_pad_ptr + attr_len >= SDP_MAX_PAD_LEN)
484+ {
485+ /* do truncate only for text string type descriptor */
486+ if (attr_type == TEXT_STR_DESC_TYPE)
487+ {
488+ SDP_TRACE_WARNING("SDP_AddAttributetoRecord: attr_len:%d too long. truncate to (%d)",
489+ attr_len, SDP_MAX_PAD_LEN - p_rec->free_pad_ptr );
490490
491- if ((attr_len > 0) && (p_val != 0))
492- {
493- p_attr->len = attr_len;
494- memcpy (&p_rec->attr_pad[p_rec->free_pad_ptr], p_val, (size_t)attr_len);
495- p_attr->value_ptr = &p_rec->attr_pad[p_rec->free_pad_ptr];
496- p_rec->free_pad_ptr += attr_len;
497- }
498- else if ((attr_len == 0 && p_attr->len != 0) || /* if truncate to 0 length, simply don't add */
499- p_val == 0)
500- {
501- SDP_TRACE_ERROR("SDP_AddAttribute fail, length exceed maximum: ID %d: attr_len:%d ",
502- attr_id, attr_len );
503- p_attr->id = p_attr->type = p_attr->len = 0;
504- return (FALSE);
505- }
506- p_rec->num_attributes++;
507- return (TRUE);
491+ attr_len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr;
492+ p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr] = '\0';
493+ p_val[SDP_MAX_PAD_LEN - p_rec->free_pad_ptr+1] = '\0';
508494 }
495+ else
496+ attr_len = 0;
509497 }
510-#endif
511- return (FALSE);
512-}
513498
499+ if ((attr_len > 0) && (p_val != 0))
500+ {
501+ p_attr->len = attr_len;
502+ memcpy (&p_rec->attr_pad[p_rec->free_pad_ptr], p_val, (size_t)attr_len);
503+ p_attr->value_ptr = &p_rec->attr_pad[p_rec->free_pad_ptr];
504+ p_rec->free_pad_ptr += attr_len;
505+ }
506+ else if ((attr_len == 0 && p_attr->len != 0) || /* if truncate to 0 length, simply don't add */
507+ p_val == 0)
508+ {
509+ SDP_TRACE_ERROR("SDP_AddAttributetoRecord fail, length exceed maximum: ID %d: attr_len:%d ",
510+ attr_id, attr_len );
511+ p_attr->id = p_attr->type = p_attr->len = 0;
512+ return (FALSE);
513+ }
514+ p_rec->num_attributes++;
515+ return (TRUE);
516+}
514517
515518 /*******************************************************************************
516519 **
@@ -705,7 +708,7 @@ BOOLEAN SDP_AddAdditionProtoLists (UINT32 handle, UINT16 num_elem,
705708 *p_len = (UINT8)(p - p_len - 1);
706709 }
707710 result = SDP_AddAttribute (handle, ATTR_ID_ADDITION_PROTO_DESC_LISTS,DATA_ELE_SEQ_DESC_TYPE,
708- (UINT32) (p - p_buff), p_buff);
711+ (UINT32) (p - p_buff), p_buff);
709712 osi_free(p_buff);
710713 return result;
711714
@@ -757,6 +760,36 @@ BOOLEAN SDP_AddProfileDescriptorList (UINT32 handle, UINT16 profile_uuid,
757760 #endif
758761 }
759762
763+BOOLEAN SDP_AddProfileDescriptorListtoRecord (tSDP_RECORD *prec, UINT16 profile_uuid,
764+ UINT16 version)
765+{
766+#if SDP_SERVER_ENABLED == TRUE
767+ UINT8 *p;
768+ BOOLEAN result;
769+ UINT8 *p_buff = (UINT8 *)osi_malloc(sizeof(UINT8) * SDP_MAX_ATTR_LEN);
770+
771+ p = p_buff + 2;
772+
773+ /* First, build the profile descriptor list. This consists of a data element sequence. */
774+ /* The sequence consists of profile's UUID and version number */
775+ UINT8_TO_BE_STREAM (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
776+ UINT16_TO_BE_STREAM (p, profile_uuid);
777+
778+ UINT8_TO_BE_STREAM (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
779+ UINT16_TO_BE_STREAM (p, version);
780+
781+ /* Add in type and length fields */
782+ *p_buff = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
783+ *(p_buff+1) = (UINT8) (p - (p_buff+2));
784+
785+ result = SDP_AddAttributetoRecord (prec, ATTR_ID_BT_PROFILE_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - p_buff), p_buff);
786+ osi_free(p_buff);
787+ return result;
788+
789+#else /* SDP_SERVER_ENABLED == FALSE */
790+ return (FALSE);
791+#endif
792+}
760793
761794 /*******************************************************************************
762795 **
@@ -853,67 +886,75 @@ BOOLEAN SDP_AddServiceClassIdList (UINT32 handle, UINT16 num_services,
853886 BOOLEAN SDP_DeleteAttribute (UINT32 handle, UINT16 attr_id)
854887 {
855888 #if SDP_SERVER_ENABLED == TRUE
856- UINT16 xx, yy;
889+ UINT16 xx;
857890 tSDP_RECORD *p_rec = &sdp_cb.server_db.record[0];
858- UINT8 *pad_ptr;
859- UINT32 len; /* Number of bytes in the entry */
860891
861892 /* Find the record in the database */
862893 for (xx = 0; xx < sdp_cb.server_db.num_records; xx++, p_rec++)
863894 {
864895 if (p_rec->record_handle == handle)
865896 {
866- tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0];
867-
868897 SDP_TRACE_API("Deleting attr_id 0x%04x for handle 0x%x", attr_id, handle);
869- /* Found it. Now, find the attribute */
870- for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
898+ if (SDP_DeleteAttributefromRecord (p_rec, attr_id))
899+ return (TRUE);
900+ }
901+ }
902+#endif
903+ /* If here, not found */
904+ return (FALSE);
905+}
906+
907+BOOLEAN SDP_DeleteAttributefromRecord (tSDP_RECORD *p_rec, UINT16 attr_id)
908+{
909+ UINT16 xx, yy;
910+ tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0];
911+ UINT8 *pad_ptr;
912+ UINT32 len; /* Number of bytes in the entry */
913+
914+ /* Found it. Now, find the attribute */
915+ for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
916+ {
917+ if (p_attr->id == attr_id)
918+ {
919+ pad_ptr = p_attr->value_ptr;
920+ len = p_attr->len;
921+ if (p_rec->free_pad_ptr + p_attr->len >= SDP_MAX_PAD_LEN)
922+ {
923+ SDP_TRACE_ERROR("Deleting attr_id 0x%04x len %d exceeds 600", attr_id, len);
924+ if (p_attr->type == TEXT_STR_DESC_TYPE)
925+ len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr;
926+ else
927+ len = 0;
928+ }
929+ if (len)
871930 {
872- if (p_attr->id == attr_id)
931+ for (yy = 0; yy < p_rec->num_attributes; yy++)
873932 {
874- pad_ptr = p_attr->value_ptr;
875- len = p_attr->len;
876- if (p_rec->free_pad_ptr + p_attr->len >= SDP_MAX_PAD_LEN)
877- {
878- SDP_TRACE_ERROR("Deleting attr_id 0x%04x len %d exceeds 600", attr_id, len);
879- if (p_attr->type == TEXT_STR_DESC_TYPE)
880- len = SDP_MAX_PAD_LEN - p_rec->free_pad_ptr;
881- else
882- len = 0;
883- }
884- if (len)
885- {
886- for (yy = 0; yy < p_rec->num_attributes; yy++)
887- {
888- if( p_rec->attribute[yy].value_ptr > pad_ptr )
889- p_rec->attribute[yy].value_ptr -= len;
890- }
891- }
892-
893- /* Found it. Shift everything up one */
894- p_rec->num_attributes--;
895-
896- for (yy = xx; yy < p_rec->num_attributes; yy++, p_attr++)
897- {
898- *p_attr = *(p_attr + 1);
899- }
900-
901- /* adjust attribute values if needed */
902- if (len)
903- {
904- xx = (p_rec->free_pad_ptr - ((pad_ptr+len) -
905- &p_rec->attr_pad[0]));
906- for( yy=0; yy<xx; yy++, pad_ptr++)
907- *pad_ptr = *(pad_ptr+len);
908- p_rec->free_pad_ptr -= len;
909- }
910- return (TRUE);
933+ if( p_rec->attribute[yy].value_ptr > pad_ptr )
934+ p_rec->attribute[yy].value_ptr -= len;
911935 }
912936 }
937+
938+ /* Found it. Shift everything up one */
939+ p_rec->num_attributes--;
940+
941+ for (yy = xx; yy < p_rec->num_attributes; yy++, p_attr++)
942+ {
943+ *p_attr = *(p_attr + 1);
944+ }
945+
946+ /* adjust attribute values if needed */
947+ if (len)
948+ {
949+ xx = (p_rec->free_pad_ptr - ((pad_ptr+len) -
950+ &p_rec->attr_pad[0]));
951+ for( yy=0; yy<xx; yy++, pad_ptr++)
952+ *pad_ptr = *(pad_ptr+len);
953+ p_rec->free_pad_ptr -= len;
954+ }
955+ return (TRUE);
913956 }
914957 }
915-#endif
916- /* If here, not found */
917958 return (FALSE);
918959 }
919960
--- a/stack/sdp/sdp_server.c
+++ b/stack/sdp/sdp_server.c
@@ -59,6 +59,8 @@ extern fixed_queue_t *btu_general_alarm_queue;
5959 #define AVRCP_SUPPORTED_FEATURES_POSITION 1
6060 #define AVRCP_BROWSE_SUPPORT_BITMASK 0x40
6161 #define AVRCP_CA_SUPPORT_BITMASK 0x01
62+#define PBAP_SKIP_GOEP_L2CAP_PSM_LEN 0x06
63+#define PBAP_SKIP_SUPP_FEA_LEN 0x08
6264
6365 /********************************************************************************/
6466 /* L O C A L F U N C T I O N P R O T O T Y P E S */
@@ -75,6 +77,10 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
7577 UINT16 param_len, UINT8 *p_req,
7678 UINT8 *p_req_end);
7779
80+static BOOLEAN is_pbap_record_blacklisted (tSDP_ATTRIBUTE attr, BD_ADDR remote_address);
81+
82+static tSDP_RECORD *sdp_update_pbap_record_if_blacklisted(tSDP_RECORD *p_rec,
83+ BD_ADDR remote_address);
7884
7985 /********************************************************************************/
8086 /* E R R O R T E X T S T R I N G S */
@@ -120,6 +126,8 @@ struct blacklist_entry
120126 char addr[3];
121127 };
122128
129+static tSDP_RECORD pbap_temp_sdp_rec;
130+
123131 int sdp_get_stored_avrc_tg_version(BD_ADDR addr)
124132 {
125133 int stored_ver = AVRC_REV_INVALID;
@@ -632,6 +640,8 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
632640 return;
633641 }
634642
643+ p_rec = sdp_update_pbap_record_if_blacklisted(p_rec, p_ccb->device_address);
644+
635645 /* Free and reallocate buffer */
636646 osi_free(p_ccb->rsp_list);
637647 p_ccb->rsp_list = (UINT8 *)osi_malloc(max_list_len);
@@ -699,6 +709,7 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
699709 #endif
700710 #endif
701711 is_hfp_fallback = sdp_change_hfp_version (p_attr, p_ccb->device_address);
712+
702713 /* Check if attribute fits. Assume 3-byte value type/length */
703714 rem_len = max_list_len - (INT16) (p_rsp - &p_ccb->rsp_list[0]);
704715
@@ -922,6 +933,7 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
922933 UINT8 *p_rsp, *p_rsp_start, *p_rsp_param_len;
923934 UINT16 rsp_param_len, xx;
924935 tSDP_RECORD *p_rec;
936+ tSDP_RECORD *p_prev_rec;
925937 tSDP_ATTR_SEQ attr_seq, attr_seq_sav;
926938 tSDP_ATTRIBUTE *p_attr;
927939 BT_HDR *p_buf;
@@ -932,6 +944,7 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
932944 BOOLEAN is_avrcp_ca_bit_reset = FALSE;
933945 UINT8 *p_seq_start = NULL;
934946 UINT16 seq_len, attr_len;
947+ UINT16 blacklist_skip_len = 0;
935948 UNUSED(p_req_end);
936949
937950 /* Extract the UUID sequence to search for */
@@ -958,7 +971,6 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
958971 }
959972
960973 memcpy(&attr_seq_sav, &attr_seq, sizeof(tSDP_ATTR_SEQ)) ;
961-
962974 /* Free and reallocate buffer */
963975 osi_free(p_ccb->rsp_list);
964976 p_ccb->rsp_list = (UINT8 *)osi_malloc(max_list_len);
@@ -1010,6 +1022,34 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
10101022 for (p_rec = sdp_db_service_search (p_ccb->cont_info.prev_sdp_rec, &uid_seq); p_rec; p_rec = sdp_db_service_search (p_rec, &uid_seq))
10111023 {
10121024 p_ccb->cont_info.curr_sdp_rec = p_rec;
1025+ /* Store the actual record pointer which would be reused later */
1026+ p_prev_rec = p_rec;
1027+ p_rec = sdp_update_pbap_record_if_blacklisted(p_rec, p_ccb->device_address);
1028+ if (p_rec != p_prev_rec) {
1029+ /* Remote device is blacklisted for PBAP, calculate the reduction in length */
1030+ for (xx = p_ccb->cont_info.next_attr_index; xx < attr_seq_sav.num_attr; xx++) {
1031+ if (attr_seq_sav.attr_entry[xx].start == attr_seq_sav.attr_entry[xx].end) {
1032+ if (attr_seq_sav.attr_entry[xx].start == ATTR_ID_GOEP_L2CAP_PSM) {
1033+ blacklist_skip_len += PBAP_SKIP_GOEP_L2CAP_PSM_LEN;
1034+ SDP_TRACE_ERROR("%s: ATTR_ID_GOEP_L2CAP_PSM requested,"
1035+ " need to reduce length by %d", __func__,
1036+ blacklist_skip_len);
1037+ } else if (attr_seq_sav.attr_entry[xx].start ==
1038+ ATTR_ID_PBAP_SUPPORTED_FEATURES) {
1039+ blacklist_skip_len += PBAP_SKIP_SUPP_FEA_LEN;
1040+ SDP_TRACE_DEBUG("%s: ATTR_ID_PBAP_SUPPORTED_FEATURES requested,"
1041+ " need to reduce length by %d", __func__,
1042+ blacklist_skip_len);
1043+ }
1044+ } else {
1045+ blacklist_skip_len = PBAP_SKIP_GOEP_L2CAP_PSM_LEN +
1046+ PBAP_SKIP_SUPP_FEA_LEN;
1047+ SDP_TRACE_DEBUG("%s: All attributes requested"
1048+ " need to reduce length by %d", __func__,
1049+ blacklist_skip_len);
1050+ }
1051+ }
1052+ }
10131053 /* Allow space for attribute sequence type and length */
10141054 p_seq_start = p_rsp;
10151055 if (p_ccb->cont_info.last_attr_seq_desc_sent == FALSE)
@@ -1210,6 +1250,8 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
12101250
12111251 /* Reset the next attr index */
12121252 p_ccb->cont_info.next_attr_index = 0;
1253+ /* restore the record pointer.*/
1254+ p_rec = p_prev_rec;
12131255 p_ccb->cont_info.prev_sdp_rec = p_rec;
12141256 p_ccb->cont_info.last_attr_seq_desc_sent = FALSE;
12151257 }
@@ -1244,6 +1286,13 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
12441286 {
12451287 /* Get the total list length for requested uid and attribute sequence */
12461288 p_ccb->list_len = sdpu_get_list_len(&uid_seq, &attr_seq_sav) + 3;
1289+ if (blacklist_skip_len &&
1290+ p_ccb->list_len > blacklist_skip_len) {
1291+ p_ccb->list_len -= blacklist_skip_len;
1292+ SDP_TRACE_DEBUG("%s: reducing list_len by %d for blacklisted device",
1293+ __func__, blacklist_skip_len);
1294+ blacklist_skip_len = 0;
1295+ }
12471296 /* Put in the sequence header (2 or 3 bytes) */
12481297 if (p_ccb->list_len > 255)
12491298 {
@@ -1285,6 +1334,14 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
12851334
12861335 p_ccb->cont_offset += len_to_send;
12871336
1337+ if (blacklist_skip_len &&
1338+ p_ccb->list_len > blacklist_skip_len) {
1339+ p_ccb->list_len -= blacklist_skip_len;
1340+ SDP_TRACE_DEBUG("%s: reducing list_len by %d for blacklisted device",
1341+ __func__, blacklist_skip_len);
1342+ blacklist_skip_len = 0;
1343+ }
1344+
12881345 /* If anything left to send, continuation needed */
12891346 if (p_ccb->cont_offset < p_ccb->list_len)
12901347 {
@@ -1308,4 +1365,91 @@ static void process_service_search_attr_req (tCONN_CB *p_ccb, UINT16 trans_num,
13081365 L2CA_DataWrite (p_ccb->connection_id, p_buf);
13091366 }
13101367
1368+/*************************************************************************************
1369+**
1370+** Function is_pbap_record_blacklisted
1371+**
1372+** Description Checks if given PBAP record is for PBAP PSE and blacklisted
1373+**
1374+** Returns BOOLEAN
1375+**
1376+***************************************************************************************/
1377+static BOOLEAN is_pbap_record_blacklisted (tSDP_ATTRIBUTE attr,
1378+ BD_ADDR remote_address)
1379+{
1380+ if ((attr.id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
1381+ (((attr.value_ptr[1] << 8) | (attr.value_ptr[2])) ==
1382+ UUID_SERVCLASS_PBAP_PSE))
1383+ {
1384+ bt_bdaddr_t remote_bdaddr;
1385+ bdcpy(remote_bdaddr.address, remote_address);
1386+
1387+ bt_property_t prop_name;
1388+ bt_bdname_t bdname;
1389+
1390+ memset(&bdname, 0, sizeof(bt_bdname_t));
1391+
1392+ BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_BDNAME,
1393+ sizeof(bt_bdname_t), &bdname);
1394+ if (btif_storage_get_remote_device_property(&remote_bdaddr,
1395+ &prop_name) != BT_STATUS_SUCCESS) {
1396+ SDP_TRACE_DEBUG("%s: BT_PROPERTY_BDNAME failed", __func__);
1397+ }
1398+ if (interop_match_addr(INTEROP_ADV_PBAP_VER_1_1, &remote_bdaddr) ||
1399+ (strlen((const char *)bdname.name) != 0 &&
1400+ interop_match_name(INTEROP_ADV_PBAP_VER_1_1,
1401+ (const char *)bdname.name))) {
1402+ SDP_TRACE_DEBUG("%s: device is blacklisted for pbap version downgrade", __func__);
1403+ return TRUE;
1404+ }
1405+ }
1406+
1407+ return FALSE;
1408+}
1409+
1410+/*************************************************************************************
1411+**
1412+** Function sdp_update_pbap_record_if_blacklisted
1413+**
1414+** Description updates pbap record after checking if blacklisted
1415+**
1416+** Returns the address of updated record
1417+**
1418+***************************************************************************************/
1419+static tSDP_RECORD *sdp_update_pbap_record_if_blacklisted(tSDP_RECORD *p_rec,
1420+ BD_ADDR remote_address)
1421+{
1422+ /* Check if the given SDP record is blacklisted and requires updatiion */
1423+ if (is_pbap_record_blacklisted(p_rec->attribute[1], remote_address)) {
1424+ bool status = TRUE;
1425+ int xx;
1426+ UINT8 supported_repositories = 0x03;
1427+ UINT16 legacy_version = 0x0101;
1428+ memset(&pbap_temp_sdp_rec, 0, sizeof(tSDP_RECORD));
1429+
1430+ tSDP_ATTRIBUTE *p_attr = &p_rec->attribute[0];
1431+
1432+ /* Copying contents of the PBAP PSE record to a temporary record */
1433+ for (xx = 0; xx < p_rec->num_attributes; xx++, p_attr++)
1434+ SDP_AddAttributetoRecord (&pbap_temp_sdp_rec, p_attr->id,
1435+ p_attr->type, p_attr->len, p_attr->value_ptr);
1436+
1437+ status &= SDP_DeleteAttributefromRecord (&pbap_temp_sdp_rec,
1438+ ATTR_ID_PBAP_SUPPORTED_FEATURES);
1439+ status &= SDP_DeleteAttributefromRecord (&pbap_temp_sdp_rec,
1440+ ATTR_ID_GOEP_L2CAP_PSM);
1441+ status &= SDP_AddAttributetoRecord (&pbap_temp_sdp_rec,
1442+ ATTR_ID_SUPPORTED_REPOSITORIES, UINT_DESC_TYPE, (UINT32)1,
1443+ (UINT8*)&supported_repositories);
1444+ status &= SDP_AddProfileDescriptorListtoRecord(&pbap_temp_sdp_rec,
1445+ UUID_SERVCLASS_PHONE_ACCESS, legacy_version);
1446+ if (!status) {
1447+ SDP_TRACE_ERROR("%s() FAILED", __func__);
1448+ return p_rec;
1449+ }
1450+ return &pbap_temp_sdp_rec;
1451+ }
1452+ return p_rec;
1453+}
1454+
13111455 #endif /* SDP_SERVER_ENABLED == TRUE */
--- a/stack/sdp/sdpint.h
+++ b/stack/sdp/sdpint.h
@@ -301,6 +301,11 @@ extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8* p_uuid128);
301301 extern tSDP_RECORD *sdp_db_service_search (tSDP_RECORD *p_rec, tSDP_UUID_SEQ *p_seq);
302302 extern tSDP_RECORD *sdp_db_find_record (UINT32 handle);
303303 extern tSDP_ATTRIBUTE *sdp_db_find_attr_in_rec (tSDP_RECORD *p_rec, UINT16 start_attr, UINT16 end_attr);
304+extern BOOLEAN SDP_AddAttributetoRecord (tSDP_RECORD *p_rec, UINT16 attr_id, UINT8 attr_type,
305+ UINT32 attr_len, UINT8 *p_val);
306+extern BOOLEAN SDP_AddProfileDescriptorListtoRecord (tSDP_RECORD *p_rec, UINT16 profile_uuid,
307+ UINT16 version);
308+extern BOOLEAN SDP_DeleteAttributefromRecord (tSDP_RECORD *p_rec, UINT16 attr_id);
304309
305310
306311 /* Functions provided by sdp_server.c