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