OSDN Git Service

Respond AVRCP profile descritpion list 1.4 only for some device
authorTed Wang <tedwang@google.com>
Mon, 18 May 2020 10:02:34 +0000 (18:02 +0800)
committerTed Wang <tedwang@google.com>
Tue, 19 May 2020 09:28:36 +0000 (09:28 +0000)
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

device/include/interop.h
device/include/interop_database.h
device/src/interop.cc
stack/sdp/sdp_server.cc
stack/sdp/sdp_utils.cc
stack/sdp/sdpint.h

index d7ca917..02c1a5e 100644 (file)
@@ -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
index b4b1b07..548395b 100644 (file)
@@ -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 {
index 9a701b1..74543bf 100644 (file)
@@ -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";
index 9b9ad30..44cc7ba 100644 (file)
@@ -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 */
index f66a8fd..f8cde2c 100644 (file)
@@ -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;
+  }
+}
index af9ccb8..ea6941c 100644 (file)
@@ -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
  */