• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  *  Copyright 2009-2014 Broadcom Corporation
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at:
8  *
9  *  http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  ******************************************************************************/
18 
19 /*******************************************************************************
20  *
21  *  Filename:      btif_gatt_client.c
22  *
23  *  Description:   GATT client implementation
24  *
25  ******************************************************************************/
26 
27 #define LOG_TAG "bt_btif_gattc"
28 
29 #include <base/at_exit.h>
30 #include <base/bind.h>
31 #include <base/logging.h>
32 #include <base/threading/thread.h>
33 #include <errno.h>
34 #include <hardware/bluetooth.h>
35 #include <hardware/bt_gatt.h>
36 
37 #include <string>
38 
39 #include "bta_api.h"
40 #include "bta_gatt_api.h"
41 #include "btif_common.h"
42 #include "btif_config.h"
43 #include "btif_dm.h"
44 #include "btif_gatt.h"
45 #include "btif_gatt_util.h"
46 #include "btif_storage.h"
47 #include "btif_util.h"
48 #include "device/include/controller.h"
49 #include "osi/include/allocator.h"
50 #include "osi/include/log.h"
51 #include "stack/include/acl_api.h"
52 #include "stack/include/acl_api_types.h"
53 #include "stack/include/btu.h"
54 #include "types/bluetooth/uuid.h"
55 #include "types/bt_transport.h"
56 #include "types/raw_address.h"
57 #include "vendor_api.h"
58 
59 using base::Bind;
60 using base::Owned;
61 using bluetooth::Uuid;
62 using std::vector;
63 
64 extern bool btif_get_address_type(const RawAddress& bda,
65                                   tBLE_ADDR_TYPE* p_addr_type);
66 extern bool btif_get_device_type(const RawAddress& bda, int* p_device_type);
67 
68 extern bt_status_t btif_gattc_test_command_impl(
69     int command, const btgatt_test_params_t* params);
70 extern const btgatt_callbacks_t* bt_gatt_callbacks;
71 
72 /*******************************************************************************
73  *  Constants & Macros
74  ******************************************************************************/
75 #define CLI_CBACK_WRAP_IN_JNI(P_CBACK, P_CBACK_WRAP)                 \
76   do {                                                               \
77     if (bt_gatt_callbacks && bt_gatt_callbacks->client->P_CBACK) {   \
78       BTIF_TRACE_API("HAL bt_gatt_callbacks->client->%s", #P_CBACK); \
79       do_in_jni_thread(P_CBACK_WRAP);                                \
80     } else {                                                         \
81       ASSERTC(0, "Callback is NULL", 0);                             \
82     }                                                                \
83   } while (0)
84 
85 #define CLI_CBACK_IN_JNI(P_CBACK, ...)                                         \
86   do {                                                                         \
87     if (bt_gatt_callbacks && bt_gatt_callbacks->client->P_CBACK) {             \
88       BTIF_TRACE_API("HAL bt_gatt_callbacks->client->%s", #P_CBACK);           \
89       do_in_jni_thread(Bind(bt_gatt_callbacks->client->P_CBACK, __VA_ARGS__)); \
90     } else {                                                                   \
91       ASSERTC(0, "Callback is NULL", 0);                                       \
92     }                                                                          \
93   } while (0)
94 
95 #define CHECK_BTGATT_INIT()                             \
96   do {                                                  \
97     if (bt_gatt_callbacks == NULL) {                    \
98       LOG_WARN("%s: BTGATT not initialized", __func__); \
99       return BT_STATUS_NOT_READY;                       \
100     } else {                                            \
101       LOG_DEBUG("%s", __func__);                        \
102     }                                                   \
103   } while (0)
104 
105 namespace {
106 
107 uint8_t rssi_request_client_if;
108 
bta_gattc_event_text(const tBTA_GATTC_EVT & event)109 std::string bta_gattc_event_text(const tBTA_GATTC_EVT& event) {
110   switch (event) {
111     case BTA_GATTC_DEREG_EVT:
112       return std::string("GATT client deregistered");
113     case BTA_GATTC_OPEN_EVT:
114       return std::string("GATTC open request status");
115     case BTA_GATTC_CLOSE_EVT:
116       return std::string("GATTC close request status");
117     case BTA_GATTC_SEARCH_CMPL_EVT:
118       return std::string("GATT discovery complete");
119     case BTA_GATTC_SEARCH_RES_EVT:
120       return std::string("GATT discovery result");
121     case BTA_GATTC_SRVC_DISC_DONE_EVT:
122       return std::string("GATT service discovery done");
123     case BTA_GATTC_NOTIF_EVT:
124       return std::string("GATT attribute notification");
125     case BTA_GATTC_EXEC_EVT:
126       return std::string("execute write complete");
127     case BTA_GATTC_ACL_EVT:
128       return std::string("ACL up");
129     case BTA_GATTC_CANCEL_OPEN_EVT:
130       return std::string("cancel open");
131     case BTA_GATTC_SRVC_CHG_EVT:
132       return std::string("service change");
133     case BTA_GATTC_ENC_CMPL_CB_EVT:
134       return std::string("encryption complete callback");
135     case BTA_GATTC_CFG_MTU_EVT:
136       return std::string("configure MTU complete");
137     case BTA_GATTC_CONGEST_EVT:
138       return std::string("congestion");
139     case BTA_GATTC_PHY_UPDATE_EVT:
140       return std::string("PHY change");
141     case BTA_GATTC_CONN_UPDATE_EVT:
142       return std::string("connection parameters update");
143   }
144 }
145 
btif_gattc_upstreams_evt(uint16_t event,char * p_param)146 static void btif_gattc_upstreams_evt(uint16_t event, char* p_param) {
147   LOG_DEBUG("Event %s [%d]",
148             bta_gattc_event_text(static_cast<tBTA_GATTC_EVT>(event)).c_str(),
149             event);
150 
151   tBTA_GATTC* p_data = (tBTA_GATTC*)p_param;
152   switch (event) {
153     case BTA_GATTC_EXEC_EVT: {
154       HAL_CBACK(bt_gatt_callbacks, client->execute_write_cb,
155                 p_data->exec_cmpl.conn_id, p_data->exec_cmpl.status);
156       break;
157     }
158 
159     case BTA_GATTC_SEARCH_CMPL_EVT: {
160       HAL_CBACK(bt_gatt_callbacks, client->search_complete_cb,
161                 p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
162       break;
163     }
164 
165     case BTA_GATTC_NOTIF_EVT: {
166       btgatt_notify_params_t data;
167 
168       data.bda = p_data->notify.bda;
169       memcpy(data.value, p_data->notify.value, p_data->notify.len);
170 
171       data.handle = p_data->notify.handle;
172       data.is_notify = p_data->notify.is_notify;
173       data.len = p_data->notify.len;
174 
175       HAL_CBACK(bt_gatt_callbacks, client->notify_cb, p_data->notify.conn_id,
176                 data);
177 
178       if (!p_data->notify.is_notify)
179         BTA_GATTC_SendIndConfirm(p_data->notify.conn_id, p_data->notify.cid);
180 
181       break;
182     }
183 
184     case BTA_GATTC_OPEN_EVT: {
185       LOG_DEBUG("BTA_GATTC_OPEN_EVT %s",
186                 p_data->open.remote_bda.ToString().c_str());
187       HAL_CBACK(bt_gatt_callbacks, client->open_cb, p_data->open.conn_id,
188                 p_data->open.status, p_data->open.client_if,
189                 p_data->open.remote_bda);
190 
191       if (GATT_DEF_BLE_MTU_SIZE != p_data->open.mtu && p_data->open.mtu) {
192         HAL_CBACK(bt_gatt_callbacks, client->configure_mtu_cb,
193                   p_data->open.conn_id, p_data->open.status, p_data->open.mtu);
194       }
195 
196       if (p_data->open.status == GATT_SUCCESS)
197         btif_gatt_check_encrypted_link(p_data->open.remote_bda,
198                                        p_data->open.transport);
199       break;
200     }
201 
202     case BTA_GATTC_CLOSE_EVT: {
203       HAL_CBACK(bt_gatt_callbacks, client->close_cb, p_data->close.conn_id,
204                 p_data->close.status, p_data->close.client_if,
205                 p_data->close.remote_bda);
206       break;
207     }
208 
209     case BTA_GATTC_ACL_EVT:
210     case BTA_GATTC_DEREG_EVT:
211     case BTA_GATTC_SEARCH_RES_EVT:
212     case BTA_GATTC_CANCEL_OPEN_EVT:
213     case BTA_GATTC_SRVC_DISC_DONE_EVT:
214       LOG_DEBUG("Ignoring event (%d)", event);
215       break;
216 
217     case BTA_GATTC_CFG_MTU_EVT: {
218       HAL_CBACK(bt_gatt_callbacks, client->configure_mtu_cb,
219                 p_data->cfg_mtu.conn_id, p_data->cfg_mtu.status,
220                 p_data->cfg_mtu.mtu);
221       break;
222     }
223 
224     case BTA_GATTC_CONGEST_EVT:
225       HAL_CBACK(bt_gatt_callbacks, client->congestion_cb,
226                 p_data->congest.conn_id, p_data->congest.congested);
227       break;
228 
229     case BTA_GATTC_PHY_UPDATE_EVT:
230       HAL_CBACK(bt_gatt_callbacks, client->phy_updated_cb,
231                 p_data->phy_update.conn_id, p_data->phy_update.tx_phy,
232                 p_data->phy_update.rx_phy, p_data->phy_update.status);
233       break;
234 
235     case BTA_GATTC_CONN_UPDATE_EVT:
236       HAL_CBACK(bt_gatt_callbacks, client->conn_updated_cb,
237                 p_data->conn_update.conn_id, p_data->conn_update.interval,
238                 p_data->conn_update.latency, p_data->conn_update.timeout,
239                 p_data->conn_update.status);
240       break;
241 
242     case BTA_GATTC_SRVC_CHG_EVT:
243       HAL_CBACK(bt_gatt_callbacks, client->service_changed_cb,
244                 p_data->service_changed.conn_id);
245       break;
246 
247     default:
248       LOG_ERROR("Unhandled event (%d)!", event);
249       break;
250   }
251 }
252 
bta_gattc_cback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)253 static void bta_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
254   LOG_DEBUG(" gatt client callback event:%s [%d]",
255             gatt_client_event_text(event).c_str(), event);
256   bt_status_t status =
257       btif_transfer_context(btif_gattc_upstreams_evt, (uint16_t)event,
258                             (char*)p_data, sizeof(tBTA_GATTC), NULL);
259   ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
260 }
261 
btm_read_rssi_cb(void * p_void)262 void btm_read_rssi_cb(void* p_void) {
263   tBTM_RSSI_RESULT* p_result = (tBTM_RSSI_RESULT*)p_void;
264 
265   if (!p_result) return;
266 
267   CLI_CBACK_IN_JNI(read_remote_rssi_cb, rssi_request_client_if,
268                    p_result->rem_bda, p_result->rssi, p_result->status);
269 }
270 
271 /*******************************************************************************
272  *  Client API Functions
273  ******************************************************************************/
274 
btif_gattc_register_app(const Uuid & uuid,bool eatt_support)275 static bt_status_t btif_gattc_register_app(const Uuid& uuid,
276                                            bool eatt_support) {
277   CHECK_BTGATT_INIT();
278 
279   return do_in_jni_thread(Bind(
280       [](const Uuid& uuid, bool eatt_support) {
281         BTA_GATTC_AppRegister(
282             bta_gattc_cback,
283             base::Bind(
284                 [](const Uuid& uuid, uint8_t client_id, uint8_t status) {
285                   do_in_jni_thread(Bind(
286                       [](const Uuid& uuid, uint8_t client_id, uint8_t status) {
287                         HAL_CBACK(bt_gatt_callbacks, client->register_client_cb,
288                                   status, client_id, uuid);
289                       },
290                       uuid, client_id, status));
291                 },
292                 uuid),
293             eatt_support);
294       },
295       uuid, eatt_support));
296 }
297 
btif_gattc_unregister_app_impl(int client_if)298 static void btif_gattc_unregister_app_impl(int client_if) {
299   BTA_GATTC_AppDeregister(client_if);
300 }
301 
btif_gattc_unregister_app(int client_if)302 static bt_status_t btif_gattc_unregister_app(int client_if) {
303   CHECK_BTGATT_INIT();
304   return do_in_jni_thread(Bind(&btif_gattc_unregister_app_impl, client_if));
305 }
306 
btif_gattc_open_impl(int client_if,RawAddress address,bool is_direct,int transport_p,bool opportunistic,int initiating_phys)307 void btif_gattc_open_impl(int client_if, RawAddress address, bool is_direct,
308                           int transport_p, bool opportunistic,
309                           int initiating_phys) {
310   // Ensure device is in inquiry database
311   tBLE_ADDR_TYPE addr_type = BLE_ADDR_PUBLIC;
312   int device_type = 0;
313   tBT_TRANSPORT transport = (tBT_TRANSPORT)BT_TRANSPORT_LE;
314 
315   if (btif_get_address_type(address, &addr_type) &&
316       btif_get_device_type(address, &device_type) &&
317       device_type != BT_DEVICE_TYPE_BREDR) {
318     BTA_DmAddBleDevice(address, addr_type, device_type);
319   }
320 
321   // Check for background connections
322   if (!is_direct) {
323     // Check for privacy 1.0 and 1.1 controller and do not start background
324     // connection if RPA offloading is not supported, since it will not
325     // connect after change of random address
326     if (!controller_get_interface()->supports_ble_privacy() &&
327         (addr_type == BLE_ADDR_RANDOM) && BTM_BLE_IS_RESOLVE_BDA(address)) {
328       tBTM_BLE_VSC_CB vnd_capabilities;
329       BTM_BleGetVendorCapabilities(&vnd_capabilities);
330       if (!vnd_capabilities.rpa_offloading) {
331         HAL_CBACK(bt_gatt_callbacks, client->open_cb, 0, BT_STATUS_UNSUPPORTED,
332                   client_if, address);
333         return;
334       }
335     }
336   }
337 
338   // Determine transport
339   if (transport_p != BT_TRANSPORT_AUTO) {
340     transport = transport_p;
341   } else {
342     switch (device_type) {
343       case BT_DEVICE_TYPE_BREDR:
344         transport = BT_TRANSPORT_BR_EDR;
345         break;
346 
347       case BT_DEVICE_TYPE_BLE:
348         transport = BT_TRANSPORT_LE;
349         break;
350 
351       case BT_DEVICE_TYPE_DUMO:
352         if (addr_type == BLE_ADDR_RANDOM)
353           transport = BT_TRANSPORT_LE;
354         else
355           transport = BT_TRANSPORT_BR_EDR;
356         break;
357       default:
358         LOG_ERROR("Unknown device type %d", +device_type);
359         break;
360     }
361   }
362 
363   // Connect!
364   LOG_INFO("Transport=%d, device type=%d, address type =%d, phy=%d", transport,
365            device_type, addr_type, initiating_phys);
366   tBTM_BLE_CONN_TYPE type =
367       is_direct ? BTM_BLE_DIRECT_CONNECTION : BTM_BLE_BKG_CONNECT_ALLOW_LIST;
368   BTA_GATTC_Open(client_if, address, type, transport, opportunistic,
369                  initiating_phys);
370 }
371 
btif_gattc_open(int client_if,const RawAddress & bd_addr,bool is_direct,int transport,bool opportunistic,int initiating_phys)372 static bt_status_t btif_gattc_open(int client_if, const RawAddress& bd_addr,
373                                    bool is_direct, int transport,
374                                    bool opportunistic, int initiating_phys) {
375   CHECK_BTGATT_INIT();
376   // Closure will own this value and free it.
377   return do_in_jni_thread(Bind(&btif_gattc_open_impl, client_if, bd_addr,
378                                is_direct, transport, opportunistic,
379                                initiating_phys));
380 }
381 
btif_gattc_close_impl(int client_if,RawAddress address,int conn_id)382 void btif_gattc_close_impl(int client_if, RawAddress address, int conn_id) {
383   LOG_INFO("client_if=%d, conn_id=%d, address=%s", client_if, conn_id,
384            PRIVATE_ADDRESS(address));
385   // Disconnect established connections
386   if (conn_id != 0) {
387     BTA_GATTC_Close(conn_id);
388   } else {
389     BTA_GATTC_CancelOpen(client_if, address, true);
390   }
391 
392   // Cancel pending background connections (remove from acceptlist)
393   BTA_GATTC_CancelOpen(client_if, address, false);
394 }
395 
btif_gattc_close(int client_if,const RawAddress & bd_addr,int conn_id)396 static bt_status_t btif_gattc_close(int client_if, const RawAddress& bd_addr,
397                                     int conn_id) {
398   CHECK_BTGATT_INIT();
399   return do_in_jni_thread(
400       Bind(&btif_gattc_close_impl, client_if, bd_addr, conn_id));
401 }
402 
btif_gattc_refresh(int client_if,const RawAddress & bd_addr)403 static bt_status_t btif_gattc_refresh(int client_if,
404                                       const RawAddress& bd_addr) {
405   CHECK_BTGATT_INIT();
406   return do_in_jni_thread(Bind(&BTA_GATTC_Refresh, bd_addr));
407 }
408 
btif_gattc_search_service(int conn_id,const Uuid * filter_uuid)409 static bt_status_t btif_gattc_search_service(int conn_id,
410                                              const Uuid* filter_uuid) {
411   CHECK_BTGATT_INIT();
412 
413   if (filter_uuid) {
414     Uuid* uuid = new Uuid(*filter_uuid);
415     return do_in_jni_thread(
416         Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, base::Owned(uuid)));
417   } else {
418     return do_in_jni_thread(
419         Bind(&BTA_GATTC_ServiceSearchRequest, conn_id, nullptr));
420   }
421 }
422 
btif_gattc_discover_service_by_uuid(int conn_id,const Uuid & uuid)423 static void btif_gattc_discover_service_by_uuid(int conn_id, const Uuid& uuid) {
424   do_in_jni_thread(Bind(&BTA_GATTC_DiscoverServiceByUuid, conn_id, uuid));
425 }
426 
btif_gattc_get_gatt_db_impl(int conn_id)427 void btif_gattc_get_gatt_db_impl(int conn_id) {
428   btgatt_db_element_t* db = NULL;
429   int count = 0;
430   BTA_GATTC_GetGattDb(conn_id, 0x0000, 0xFFFF, &db, &count);
431 
432   HAL_CBACK(bt_gatt_callbacks, client->get_gatt_db_cb, conn_id, db, count);
433   osi_free(db);
434 }
435 
btif_gattc_get_gatt_db(int conn_id)436 static bt_status_t btif_gattc_get_gatt_db(int conn_id) {
437   CHECK_BTGATT_INIT();
438   return do_in_jni_thread(Bind(&btif_gattc_get_gatt_db_impl, conn_id));
439 }
440 
read_char_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)441 void read_char_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
442                   uint16_t len, uint8_t* value, void* data) {
443   btgatt_read_params_t* params = new btgatt_read_params_t;
444   params->value_type = 0x00 /* GATTC_READ_VALUE_TYPE_VALUE */;
445   params->status = status;
446   params->handle = handle;
447   params->value.len = len;
448   CHECK(len <= BTGATT_MAX_ATTR_LEN);
449   if (len > 0) memcpy(params->value.value, value, len);
450 
451   // clang-tidy analyzer complains about |params| is leaked.  It doesn't know
452   // that |param| will be freed by the callback function.
453   CLI_CBACK_IN_JNI(read_characteristic_cb, conn_id, status, /* NOLINT */
454                    base::Owned(params));
455 }
456 
btif_gattc_read_char(int conn_id,uint16_t handle,int auth_req)457 static bt_status_t btif_gattc_read_char(int conn_id, uint16_t handle,
458                                         int auth_req) {
459   CHECK_BTGATT_INIT();
460   return do_in_jni_thread(Bind(&BTA_GATTC_ReadCharacteristic, conn_id, handle,
461                                auth_req, read_char_cb, nullptr));
462 }
463 
read_using_char_uuid_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)464 void read_using_char_uuid_cb(uint16_t conn_id, tGATT_STATUS status,
465                              uint16_t handle, uint16_t len, uint8_t* value,
466                              void* data) {
467   btgatt_read_params_t* params = new btgatt_read_params_t;
468   params->value_type = 0x00 /* GATTC_READ_VALUE_TYPE_VALUE */;
469   params->status = status;
470   params->handle = handle;
471   params->value.len = len;
472   CHECK(len <= BTGATT_MAX_ATTR_LEN);
473   if (len > 0) memcpy(params->value.value, value, len);
474 
475   // clang-tidy analyzer complains about |params| is leaked.  It doesn't know
476   // that |param| will be freed by the callback function.
477   CLI_CBACK_IN_JNI(read_characteristic_cb, conn_id, status, /* NOLINT */
478                    base::Owned(params));
479 }
480 
btif_gattc_read_using_char_uuid(int conn_id,const Uuid & uuid,uint16_t s_handle,uint16_t e_handle,int auth_req)481 static bt_status_t btif_gattc_read_using_char_uuid(int conn_id,
482                                                    const Uuid& uuid,
483                                                    uint16_t s_handle,
484                                                    uint16_t e_handle,
485                                                    int auth_req) {
486   CHECK_BTGATT_INIT();
487   return do_in_jni_thread(Bind(&BTA_GATTC_ReadUsingCharUuid, conn_id, uuid,
488                                s_handle, e_handle, auth_req,
489                                read_using_char_uuid_cb, nullptr));
490 }
491 
read_desc_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,uint8_t * value,void * data)492 void read_desc_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
493                   uint16_t len, uint8_t* value, void* data) {
494   btgatt_read_params_t params;
495   params.value_type = 0x00 /* GATTC_READ_VALUE_TYPE_VALUE */;
496   params.status = status;
497   params.handle = handle;
498   params.value.len = len;
499   CHECK(len <= BTGATT_MAX_ATTR_LEN);
500   if (len > 0) memcpy(params.value.value, value, len);
501 
502   CLI_CBACK_IN_JNI(read_descriptor_cb, conn_id, status, params);
503 }
504 
btif_gattc_read_char_descr(int conn_id,uint16_t handle,int auth_req)505 static bt_status_t btif_gattc_read_char_descr(int conn_id, uint16_t handle,
506                                               int auth_req) {
507   CHECK_BTGATT_INIT();
508   return do_in_jni_thread(Bind(&BTA_GATTC_ReadCharDescr, conn_id, handle,
509                                auth_req, read_desc_cb, nullptr));
510 }
511 
write_char_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,void * data)512 void write_char_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
513                    uint16_t len, const uint8_t* value, void* data) {
514   std::vector<uint8_t> val(value, value + len);
515   CLI_CBACK_WRAP_IN_JNI(
516       write_characteristic_cb,
517       base::BindOnce(
518           [](write_characteristic_callback cb, uint16_t conn_id,
519              tGATT_STATUS status, uint16_t handle,
520              std::vector<uint8_t> moved_value) {
521             cb(conn_id, status, handle, moved_value.size(), moved_value.data());
522           },
523           bt_gatt_callbacks->client->write_characteristic_cb, conn_id, status,
524           handle, std::move(val)));
525 }
526 
btif_gattc_write_char(int conn_id,uint16_t handle,int write_type,int auth_req,const uint8_t * val,size_t len)527 static bt_status_t btif_gattc_write_char(int conn_id, uint16_t handle,
528                                          int write_type, int auth_req,
529                                          const uint8_t* val, size_t len) {
530   CHECK_BTGATT_INIT();
531 
532   std::vector<uint8_t> value(val, val + len);
533 
534   if (value.size() > BTGATT_MAX_ATTR_LEN) value.resize(BTGATT_MAX_ATTR_LEN);
535 
536   return do_in_jni_thread(Bind(&BTA_GATTC_WriteCharValue, conn_id, handle,
537                                write_type, std::move(value), auth_req,
538                                write_char_cb, nullptr));
539 }
540 
write_descr_cb(uint16_t conn_id,tGATT_STATUS status,uint16_t handle,uint16_t len,const uint8_t * value,void * data)541 void write_descr_cb(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
542                     uint16_t len, const uint8_t* value, void* data) {
543   std::vector<uint8_t> val(value, value + len);
544 
545   CLI_CBACK_WRAP_IN_JNI(
546       write_descriptor_cb,
547       base::BindOnce(
548           [](write_descriptor_callback cb, uint16_t conn_id,
549              tGATT_STATUS status, uint16_t handle,
550              std::vector<uint8_t> moved_value) {
551             cb(conn_id, status, handle, moved_value.size(), moved_value.data());
552           },
553           bt_gatt_callbacks->client->write_descriptor_cb, conn_id, status,
554           handle, std::move(val)));
555 }
556 
btif_gattc_write_char_descr(int conn_id,uint16_t handle,int auth_req,const uint8_t * val,size_t len)557 static bt_status_t btif_gattc_write_char_descr(int conn_id, uint16_t handle,
558                                                int auth_req, const uint8_t* val,
559                                                size_t len) {
560   CHECK_BTGATT_INIT();
561 
562   std::vector<uint8_t> value(val, val + len);
563 
564   if (value.size() > BTGATT_MAX_ATTR_LEN) value.resize(BTGATT_MAX_ATTR_LEN);
565 
566   return do_in_jni_thread(Bind(&BTA_GATTC_WriteCharDescr, conn_id, handle,
567                                std::move(value), auth_req, write_descr_cb,
568                                nullptr));
569 }
570 
btif_gattc_execute_write(int conn_id,int execute)571 static bt_status_t btif_gattc_execute_write(int conn_id, int execute) {
572   CHECK_BTGATT_INIT();
573   return do_in_jni_thread(
574       Bind(&BTA_GATTC_ExecuteWrite, conn_id, (uint8_t)execute));
575 }
576 
btif_gattc_reg_for_notification_impl(tGATT_IF client_if,const RawAddress & bda,uint16_t handle)577 static void btif_gattc_reg_for_notification_impl(tGATT_IF client_if,
578                                                  const RawAddress& bda,
579                                                  uint16_t handle) {
580   tGATT_STATUS status =
581       BTA_GATTC_RegisterForNotifications(client_if, bda, handle);
582 
583   // TODO(jpawlowski): conn_id is currently unused
584   HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb,
585             /* conn_id */ 0, 1, status, handle);
586 }
587 
btif_gattc_reg_for_notification(int client_if,const RawAddress & bd_addr,uint16_t handle)588 bt_status_t btif_gattc_reg_for_notification(int client_if,
589                                             const RawAddress& bd_addr,
590                                             uint16_t handle) {
591   CHECK_BTGATT_INIT();
592 
593   return do_in_jni_thread(
594       Bind(base::IgnoreResult(&btif_gattc_reg_for_notification_impl), client_if,
595            bd_addr, handle));
596 }
597 
btif_gattc_dereg_for_notification_impl(tGATT_IF client_if,const RawAddress & bda,uint16_t handle)598 static void btif_gattc_dereg_for_notification_impl(tGATT_IF client_if,
599                                                    const RawAddress& bda,
600                                                    uint16_t handle) {
601   tGATT_STATUS status =
602       BTA_GATTC_DeregisterForNotifications(client_if, bda, handle);
603 
604   // TODO(jpawlowski): conn_id is currently unused
605   HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb,
606             /* conn_id */ 0, 0, status, handle);
607 }
608 
btif_gattc_dereg_for_notification(int client_if,const RawAddress & bd_addr,uint16_t handle)609 bt_status_t btif_gattc_dereg_for_notification(int client_if,
610                                               const RawAddress& bd_addr,
611                                               uint16_t handle) {
612   CHECK_BTGATT_INIT();
613 
614   return do_in_jni_thread(
615       Bind(base::IgnoreResult(&btif_gattc_dereg_for_notification_impl),
616            client_if, bd_addr, handle));
617 }
618 
btif_gattc_read_remote_rssi(int client_if,const RawAddress & bd_addr)619 static bt_status_t btif_gattc_read_remote_rssi(int client_if,
620                                                const RawAddress& bd_addr) {
621   CHECK_BTGATT_INIT();
622   rssi_request_client_if = client_if;
623 
624   return do_in_jni_thread(
625       Bind(base::IgnoreResult(&BTM_ReadRSSI), bd_addr, btm_read_rssi_cb));
626 }
627 
btif_gattc_configure_mtu(int conn_id,int mtu)628 static bt_status_t btif_gattc_configure_mtu(int conn_id, int mtu) {
629   CHECK_BTGATT_INIT();
630   return do_in_jni_thread(
631       Bind(base::IgnoreResult(
632         static_cast<void (*)(uint16_t,uint16_t)>(&BTA_GATTC_ConfigureMTU)),
633         conn_id, mtu));
634 }
635 
btif_gattc_conn_parameter_update_impl(RawAddress addr,int min_interval,int max_interval,int latency,int timeout,uint16_t min_ce_len,uint16_t max_ce_len)636 static void btif_gattc_conn_parameter_update_impl(
637     RawAddress addr, int min_interval, int max_interval, int latency,
638     int timeout, uint16_t min_ce_len, uint16_t max_ce_len) {
639   if (BTA_DmGetConnectionState(addr))
640     BTA_DmBleUpdateConnectionParams(addr, min_interval, max_interval, latency,
641                                     timeout, min_ce_len, max_ce_len);
642   else
643     BTA_DmSetBlePrefConnParams(addr, min_interval, max_interval, latency,
644                                timeout);
645 }
646 
btif_gattc_conn_parameter_update(const RawAddress & bd_addr,int min_interval,int max_interval,int latency,int timeout,uint16_t min_ce_len,uint16_t max_ce_len)647 bt_status_t btif_gattc_conn_parameter_update(const RawAddress& bd_addr,
648                                              int min_interval, int max_interval,
649                                              int latency, int timeout,
650                                              uint16_t min_ce_len,
651                                              uint16_t max_ce_len) {
652   CHECK_BTGATT_INIT();
653   return do_in_jni_thread(Bind(
654       base::IgnoreResult(&btif_gattc_conn_parameter_update_impl), bd_addr,
655       min_interval, max_interval, latency, timeout, min_ce_len, max_ce_len));
656 }
657 
btif_gattc_set_preferred_phy(const RawAddress & bd_addr,uint8_t tx_phy,uint8_t rx_phy,uint16_t phy_options)658 static bt_status_t btif_gattc_set_preferred_phy(const RawAddress& bd_addr,
659                                                 uint8_t tx_phy, uint8_t rx_phy,
660                                                 uint16_t phy_options) {
661   CHECK_BTGATT_INIT();
662   do_in_main_thread(FROM_HERE,
663                     Bind(&BTM_BleSetPhy, bd_addr, tx_phy, rx_phy, phy_options));
664   return BT_STATUS_SUCCESS;
665 }
666 
btif_gattc_read_phy(const RawAddress & bd_addr,base::Callback<void (uint8_t tx_phy,uint8_t rx_phy,uint8_t status)> cb)667 static bt_status_t btif_gattc_read_phy(
668     const RawAddress& bd_addr,
669     base::Callback<void(uint8_t tx_phy, uint8_t rx_phy, uint8_t status)> cb) {
670   CHECK_BTGATT_INIT();
671   do_in_main_thread(FROM_HERE, Bind(&BTM_BleReadPhy, bd_addr,
672                                     jni_thread_wrapper(FROM_HERE, cb)));
673   return BT_STATUS_SUCCESS;
674 }
675 
btif_gattc_get_device_type(const RawAddress & bd_addr)676 static int btif_gattc_get_device_type(const RawAddress& bd_addr) {
677   int device_type = 0;
678 
679   if (btif_config_get_int(bd_addr.ToString().c_str(), "DevType", &device_type))
680     return device_type;
681   return 0;
682 }
683 
btif_gattc_test_command(int command,const btgatt_test_params_t & params)684 static bt_status_t btif_gattc_test_command(int command,
685                                            const btgatt_test_params_t& params) {
686   return btif_gattc_test_command_impl(command, &params);
687 }
688 
689 }  // namespace
690 
691 const btgatt_client_interface_t btgattClientInterface = {
692     btif_gattc_register_app,
693     btif_gattc_unregister_app,
694     btif_gattc_open,
695     btif_gattc_close,
696     btif_gattc_refresh,
697     btif_gattc_search_service,
698     btif_gattc_discover_service_by_uuid,
699     btif_gattc_read_char,
700     btif_gattc_read_using_char_uuid,
701     btif_gattc_write_char,
702     btif_gattc_read_char_descr,
703     btif_gattc_write_char_descr,
704     btif_gattc_execute_write,
705     btif_gattc_reg_for_notification,
706     btif_gattc_dereg_for_notification,
707     btif_gattc_read_remote_rssi,
708     btif_gattc_get_device_type,
709     btif_gattc_configure_mtu,
710     btif_gattc_conn_parameter_update,
711     btif_gattc_set_preferred_phy,
712     btif_gattc_read_phy,
713     btif_gattc_test_command,
714     btif_gattc_get_gatt_db};
715