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