system/bt
Revision | a776d907a9b3a3b87f461587ea6096479b236d5a (tree) |
---|---|
Zeit | 2017-05-27 09:02:01 |
Autor | Myles Watson <mylesgw@goog...> |
Commiter | Myles Watson |
GATT: Interop fix for service changed indications
The Pixel C Keyboard disconnects if it receives an indication
for which it hasn't registered.
Test: Add a GATT service with Pixel C connected
Bug: 34352677
Change-Id: I1f717db40b2ba9ec21feac5fd9e339c09f140d51
(cherry picked from commit 43c7f9f4775e589d8fd0604ef4717996696a0321)
@@ -69,7 +69,11 @@ typedef enum { | ||
69 | 69 | |
70 | 70 | // Do not use supervision timeout value received from preferred connection |
71 | 71 | // parameters, use 3s instead. Use with HID only. |
72 | - INTEROP_HID_PREF_CONN_SUP_TIMEOUT_3S | |
72 | + INTEROP_HID_PREF_CONN_SUP_TIMEOUT_3S, | |
73 | + | |
74 | + // Do not send service changed indications (GATT client). | |
75 | + // This should be removed after the characteristic is implmeented b/62088395. | |
76 | + INTEROP_GATTC_NO_SERVICE_CHANGED_IND, | |
73 | 77 | } interop_feature_t; |
74 | 78 | |
75 | 79 | // Check if a given |addr| matches a known interoperability workaround as |
@@ -128,4 +128,7 @@ static const interop_name_entry_t interop_name_database[] = { | ||
128 | 128 | |
129 | 129 | // Subaru car kits ("CAR M_MEDIA") |
130 | 130 | {"CAR", 3, INTEROP_DISABLE_AUTO_PAIRING}, |
131 | + | |
132 | + // Pixel C Keyboard doesn't respond to service changed indications. | |
133 | + {"Pixel C Keyboard", 16, INTEROP_GATTC_NO_SERVICE_CHANGED_IND}, | |
131 | 134 | }; |
@@ -125,6 +125,7 @@ static const char* interop_feature_string_(const interop_feature_t feature) { | ||
125 | 125 | CASE_RETURN_STR(INTEROP_KEYBOARD_REQUIRES_FIXED_PIN) |
126 | 126 | CASE_RETURN_STR(INTEROP_2MBPS_LINK_ONLY) |
127 | 127 | CASE_RETURN_STR(INTEROP_HID_PREF_CONN_SUP_TIMEOUT_3S) |
128 | + CASE_RETURN_STR(INTEROP_GATTC_NO_SERVICE_CHANGED_IND) | |
128 | 129 | } |
129 | 130 | |
130 | 131 | return "UNKNOWN"; |
@@ -26,8 +26,10 @@ | ||
26 | 26 | |
27 | 27 | #include "bt_common.h" |
28 | 28 | #include "bt_utils.h" |
29 | +#include "btif_storage.h" | |
29 | 30 | #include "btm_ble_int.h" |
30 | 31 | #include "btm_int.h" |
32 | +#include "device/include/interop.h" | |
31 | 33 | #include "gatt_int.h" |
32 | 34 | #include "l2c_api.h" |
33 | 35 | #include "osi/include/osi.h" |
@@ -267,7 +269,8 @@ bool gatt_update_app_hold_link_status(tGATT_IF gatt_if, tGATT_TCB* p_tcb, | ||
267 | 269 | bool is_add) { |
268 | 270 | for (int i = 0; i < GATT_MAX_APPS; i++) { |
269 | 271 | if (p_tcb->app_hold_link[i] == gatt_if && is_add) { |
270 | - GATT_TRACE_DEBUG("%s: gatt_if %d already exists at idx %d", __func__, gatt_if, i); | |
272 | + GATT_TRACE_DEBUG("%s: gatt_if %d already exists at idx %d", __func__, | |
273 | + gatt_if, i); | |
271 | 274 | return true; |
272 | 275 | } |
273 | 276 | } |
@@ -1100,6 +1103,20 @@ void gatt_init_srv_chg(void) { | ||
1100 | 1103 | } |
1101 | 1104 | } |
1102 | 1105 | |
1106 | +// Get the name of a device from btif for interop database matching. | |
1107 | +static bool get_stored_remote_name(BD_ADDR bda, char* name) { | |
1108 | + bt_bdaddr_t bd_addr; | |
1109 | + for (int i = 0; i < 6; i++) bd_addr.address[i] = bda[i]; | |
1110 | + | |
1111 | + bt_property_t property; | |
1112 | + property.type = BT_PROPERTY_BDNAME; | |
1113 | + property.len = BTM_MAX_REM_BD_NAME_LEN; | |
1114 | + property.val = name; | |
1115 | + | |
1116 | + return (btif_storage_get_remote_device_property(&bd_addr, &property) == | |
1117 | + BT_STATUS_SUCCESS); | |
1118 | +} | |
1119 | + | |
1103 | 1120 | /******************************************************************************* |
1104 | 1121 | * |
1105 | 1122 | * Function gatt_proc_srv_chg |
@@ -1112,7 +1129,6 @@ void gatt_init_srv_chg(void) { | ||
1112 | 1129 | void gatt_proc_srv_chg(void) { |
1113 | 1130 | uint8_t start_idx, found_idx; |
1114 | 1131 | BD_ADDR bda; |
1115 | - bool srv_chg_ind_pending = false; | |
1116 | 1132 | tGATT_TCB* p_tcb; |
1117 | 1133 | tBT_TRANSPORT transport; |
1118 | 1134 |
@@ -1124,14 +1140,26 @@ void gatt_proc_srv_chg(void) { | ||
1124 | 1140 | while ( |
1125 | 1141 | gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) { |
1126 | 1142 | p_tcb = &gatt_cb.tcb[found_idx]; |
1127 | - ; | |
1128 | - srv_chg_ind_pending = gatt_is_srv_chg_ind_pending(p_tcb); | |
1129 | 1143 | |
1130 | - if (!srv_chg_ind_pending) { | |
1131 | - gatt_send_srv_chg_ind(bda); | |
1132 | - } else { | |
1144 | + bool send_indication = true; | |
1145 | + | |
1146 | + if (gatt_is_srv_chg_ind_pending(p_tcb)) { | |
1147 | + send_indication = false; | |
1133 | 1148 | GATT_TRACE_DEBUG("discard srv chg - already has one in the queue"); |
1134 | 1149 | } |
1150 | + | |
1151 | + // Some LE GATT clients don't respond to service changed indications. | |
1152 | + char remote_name[BTM_MAX_REM_BD_NAME_LEN] = ""; | |
1153 | + if (send_indication && get_stored_remote_name(bda, remote_name)) { | |
1154 | + if (interop_match_name(INTEROP_GATTC_NO_SERVICE_CHANGED_IND, | |
1155 | + remote_name)) { | |
1156 | + GATT_TRACE_DEBUG("discard srv chg - interop matched %s", remote_name); | |
1157 | + send_indication = false; | |
1158 | + } | |
1159 | + } | |
1160 | + | |
1161 | + if (send_indication) gatt_send_srv_chg_ind(bda); | |
1162 | + | |
1135 | 1163 | start_idx = ++found_idx; |
1136 | 1164 | } |
1137 | 1165 | } |