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