Home | History | Annotate | Download | only in gatt
      1 /******************************************************************************
      2  *
      3  *  Copyright 2003-2012 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  *  This file contains the GATT client discovery procedures and cache
     22  *  related functions.
     23  *
     24  ******************************************************************************/
     25 
     26 #define LOG_TAG "bt_bta_gattc"
     27 
     28 #include "bt_target.h"
     29 
     30 #include <errno.h>
     31 #include <stdio.h>
     32 #include <string.h>
     33 #include <unistd.h>
     34 
     35 #include "bt_common.h"
     36 #include "bta_gattc_int.h"
     37 #include "bta_sys.h"
     38 #include "btm_api.h"
     39 #include "btm_ble_api.h"
     40 #include "btm_int.h"
     41 #include "osi/include/log.h"
     42 #include "osi/include/osi.h"
     43 #include "sdp_api.h"
     44 #include "sdpdefs.h"
     45 #include "utl.h"
     46 
     47 using bluetooth::Uuid;
     48 using base::StringPrintf;
     49 
     50 static void bta_gattc_cache_write(const RawAddress& server_bda,
     51                                   uint16_t num_attr, tBTA_GATTC_NV_ATTR* attr);
     52 static void bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,
     53                                            tBTA_GATTC_SERV* p_srvc_cb);
     54 static tGATT_STATUS bta_gattc_sdp_service_disc(uint16_t conn_id,
     55                                                tBTA_GATTC_SERV* p_server_cb);
     56 const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(
     57     tBTA_GATTC_SERV* p_srcb, uint16_t handle);
     58 tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(
     59     tBTA_GATTC_SERV* p_srcb, uint16_t handle);
     60 
     61 #define BTA_GATT_SDP_DB_SIZE 4096
     62 
     63 #define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_"
     64 #define GATT_CACHE_VERSION 4
     65 
     66 static void bta_gattc_generate_cache_file_name(char* buffer, size_t buffer_len,
     67                                                const RawAddress& bda) {
     68   snprintf(buffer, buffer_len, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX,
     69            bda.address[0], bda.address[1], bda.address[2], bda.address[3],
     70            bda.address[4], bda.address[5]);
     71 }
     72 
     73 /*****************************************************************************
     74  *  Constants and data types
     75  ****************************************************************************/
     76 
     77 typedef struct {
     78   tSDP_DISCOVERY_DB* p_sdp_db;
     79   uint16_t sdp_conn_id;
     80 } tBTA_GATTC_CB_DATA;
     81 
     82 #if (BTA_GATT_DEBUG == TRUE)
     83 /* utility functions */
     84 
     85 /* debug function to display the server cache */
     86 static void display_db(const std::vector<tBTA_GATTC_SERVICE>& cache) {
     87   for (const tBTA_GATTC_SERVICE& service : cache) {
     88     LOG(ERROR) << "Service: s_handle=" << loghex(service.s_handle)
     89                << ", e_handle=" << loghex(service.e_handle)
     90                << ", inst=" << loghex(service.handle)
     91                << ", uuid=" << service.uuid;
     92 
     93     if (service.characteristics.empty()) {
     94       LOG(ERROR) << "\t No characteristics";
     95       continue;
     96     }
     97 
     98     for (const tBTA_GATTC_CHARACTERISTIC& c : service.characteristics) {
     99       LOG(ERROR) << "\t Characteristic value_handle=" << loghex(c.value_handle)
    100                  << ", uuid=" << c.uuid << ", prop=" << loghex(c.properties);
    101 
    102       if (c.descriptors.empty()) {
    103         LOG(ERROR) << "\t\t No descriptors";
    104         continue;
    105       }
    106 
    107       for (const tBTA_GATTC_DESCRIPTOR& d : c.descriptors) {
    108         LOG(ERROR) << "\t\t Descriptor handle=" << loghex(d.handle)
    109                    << ", uuid=" << d.uuid;
    110       }
    111     }
    112   }
    113 }
    114 
    115 /* debug function to display the server cache */
    116 static void bta_gattc_display_cache_server(
    117     const std::vector<tBTA_GATTC_SERVICE>& cache) {
    118   LOG(ERROR) << "<================Start Server Cache =============>";
    119   display_db(cache);
    120   LOG(ERROR) << "<================End Server Cache =============>";
    121   LOG(ERROR) << " ";
    122 }
    123 
    124 /** debug function to display the exploration list */
    125 static void bta_gattc_display_explore_record(
    126     const std::vector<tBTA_GATTC_SERVICE>& cache) {
    127   LOG(ERROR) << "<================Start Explore Queue =============>";
    128   display_db(cache);
    129   LOG(ERROR) << "<================ End Explore Queue =============>";
    130   LOG(ERROR) << " ";
    131 }
    132 #endif /* BTA_GATT_DEBUG == TRUE */
    133 
    134 /*******************************************************************************
    135  *
    136  * Function         bta_gattc_init_cache
    137  *
    138  * Description      Initialize the database cache and discovery related
    139  *                  resources.
    140  *
    141  * Returns          status
    142  *
    143  ******************************************************************************/
    144 tGATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb) {
    145   // clear reallocating
    146   std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->srvc_cache);
    147   std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->pending_discovery);
    148   return GATT_SUCCESS;
    149 }
    150 
    151 tBTA_GATTC_SERVICE* bta_gattc_find_matching_service(
    152     std::vector<tBTA_GATTC_SERVICE>& services, uint16_t handle) {
    153   for (tBTA_GATTC_SERVICE& service : services) {
    154     if (handle >= service.s_handle && handle <= service.e_handle)
    155       return &service;
    156   }
    157 
    158   return nullptr;
    159 }
    160 
    161 /** Add a service into GATT database */
    162 static void add_service_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
    163                                    uint16_t s_handle, uint16_t e_handle,
    164                                    const Uuid& uuid, bool is_primary) {
    165 #if (BTA_GATT_DEBUG == TRUE)
    166   VLOG(1) << "Add a service into GATT DB";
    167 #endif
    168 
    169   gatt_db.emplace_back(tBTA_GATTC_SERVICE{
    170       .s_handle = s_handle,
    171       .e_handle = e_handle,
    172       .is_primary = is_primary,
    173       .uuid = uuid,
    174       .handle = s_handle,
    175   });
    176 }
    177 
    178 /** Add a characteristic into GATT database */
    179 static void add_characteristic_to_gatt_db(
    180     std::vector<tBTA_GATTC_SERVICE>& gatt_db, uint16_t attr_handle,
    181     uint16_t value_handle, const Uuid& uuid, uint8_t property) {
    182 #if (BTA_GATT_DEBUG == TRUE)
    183   VLOG(1) << __func__
    184           << ": Add a characteristic into service. handle:" << +value_handle
    185           << " uuid:" << uuid << " property=0x" << std::hex << +property;
    186 #endif
    187 
    188   tBTA_GATTC_SERVICE* service =
    189       bta_gattc_find_matching_service(gatt_db, attr_handle);
    190   if (!service) {
    191     LOG(ERROR) << "Illegal action to add char/descr/incl srvc for non-existing "
    192                   "service!";
    193     return;
    194   }
    195 
    196   /* TODO(jpawlowski): We should use attribute handle, not value handle to refer
    197      to characteristic.
    198      This is just a temporary workaround.
    199   */
    200   if (service->e_handle < value_handle) service->e_handle = value_handle;
    201 
    202   service->characteristics.emplace_back(
    203       tBTA_GATTC_CHARACTERISTIC{.declaration_handle = attr_handle,
    204                                 .value_handle = value_handle,
    205                                 .properties = property,
    206                                 .uuid = uuid});
    207   return;
    208 }
    209 
    210 /* Add an descriptor into database cache buffer */
    211 static void add_descriptor_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
    212                                       uint16_t handle, const Uuid& uuid) {
    213 #if (BTA_GATT_DEBUG == TRUE)
    214   VLOG(1) << __func__ << ": add descriptor, handle=" << loghex(handle)
    215           << ", uuid=" << uuid;
    216 #endif
    217 
    218   tBTA_GATTC_SERVICE* service =
    219       bta_gattc_find_matching_service(gatt_db, handle);
    220   if (!service) {
    221     LOG(ERROR) << "Illegal action to add descriptor for non-existing service!";
    222     return;
    223   }
    224 
    225   if (service->characteristics.empty()) {
    226     LOG(ERROR) << __func__
    227                << ": Illegal action to add descriptor before adding a "
    228                   "characteristic!";
    229     return;
    230   }
    231 
    232   tBTA_GATTC_CHARACTERISTIC* char_node = &service->characteristics.front();
    233   for (auto it = service->characteristics.begin();
    234        it != service->characteristics.end(); it++) {
    235     if (it->value_handle > handle) break;
    236     char_node = &(*it);
    237   }
    238 
    239   char_node->descriptors.emplace_back(
    240       tBTA_GATTC_DESCRIPTOR{.handle = handle, .uuid = uuid});
    241 }
    242 
    243 /* Add an attribute into database cache buffer */
    244 static void add_incl_srvc_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
    245                                      uint16_t handle, const Uuid& uuid,
    246                                      uint16_t incl_srvc_s_handle) {
    247 #if (BTA_GATT_DEBUG == TRUE)
    248   VLOG(1) << __func__ << ": add included service, handle=" << loghex(handle)
    249           << ", uuid=" << uuid;
    250 #endif
    251 
    252   tBTA_GATTC_SERVICE* service =
    253       bta_gattc_find_matching_service(gatt_db, handle);
    254   if (!service) {
    255     LOG(ERROR) << "Illegal action to add incl srvc for non-existing service!";
    256     return;
    257   }
    258 
    259   tBTA_GATTC_SERVICE* included_service =
    260       bta_gattc_find_matching_service(gatt_db, incl_srvc_s_handle);
    261   if (!included_service) {
    262     LOG(ERROR) << __func__
    263                << ": Illegal action to add non-existing included service!";
    264     return;
    265   }
    266 
    267   service->included_svc.emplace_back(tBTA_GATTC_INCLUDED_SVC{
    268       .handle = handle,
    269       .uuid = uuid,
    270       .owning_service = service,
    271       .included_service = included_service,
    272   });
    273 }
    274 
    275 /** Start primary service discovery */
    276 tGATT_STATUS bta_gattc_discover_pri_service(uint16_t conn_id,
    277                                             tBTA_GATTC_SERV* p_server_cb,
    278                                             uint8_t disc_type) {
    279   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    280   if (!p_clcb) return GATT_ERROR;
    281 
    282   if (p_clcb->transport == BTA_TRANSPORT_LE) {
    283     tGATT_DISC_PARAM param{.s_handle = 0x0001, .e_handle = 0xFFFF};
    284     return GATTC_Discover(conn_id, disc_type, &param);
    285   }
    286 
    287   return bta_gattc_sdp_service_disc(conn_id, p_server_cb);
    288 }
    289 
    290 /** Start discovery for characteristic descriptor */
    291 void bta_gattc_start_disc_char_dscp(uint16_t conn_id,
    292                                     tBTA_GATTC_SERV* p_srvc_cb) {
    293   VLOG(1) << "starting discover characteristics descriptor";
    294   auto& characteristic = p_srvc_cb->pending_char;
    295 
    296   uint16_t end_handle = 0xFFFF;
    297   // if there are more characteristics in the service
    298   if (std::next(p_srvc_cb->pending_char) !=
    299       p_srvc_cb->pending_service->characteristics.end()) {
    300     // end at beginning of next characteristic
    301     end_handle = std::next(p_srvc_cb->pending_char)->declaration_handle - 1;
    302   } else {
    303     // end at the end of current service
    304     end_handle = p_srvc_cb->pending_service->e_handle;
    305   }
    306 
    307   tGATT_DISC_PARAM param{
    308       .s_handle = (uint16_t)(characteristic->value_handle + 1),
    309       .e_handle = end_handle};
    310   if (GATTC_Discover(conn_id, GATT_DISC_CHAR_DSCPT, &param) != 0) {
    311     bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
    312   }
    313 }
    314 
    315 /** process the service discovery complete event */
    316 static void bta_gattc_explore_srvc(uint16_t conn_id,
    317                                    tBTA_GATTC_SERV* p_srvc_cb) {
    318   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    319   if (!p_clcb) {
    320     LOG(ERROR) << "unknown conn_id=" << +conn_id;
    321     return;
    322   }
    323 
    324   /* start expore a service if there is service not been explored */
    325   if (p_srvc_cb->pending_service != p_srvc_cb->pending_discovery.end()) {
    326     auto& service = *p_srvc_cb->pending_service;
    327     VLOG(1) << "Start service discovery";
    328 
    329     /* start discovering included services */
    330     tGATT_DISC_PARAM param = {.s_handle = service.s_handle,
    331                               .e_handle = service.e_handle};
    332     GATTC_Discover(conn_id, GATT_DISC_INC_SRVC, &param);
    333     return;
    334   }
    335 
    336   /* no service found at all, the end of server discovery*/
    337   LOG(INFO) << __func__ << ": no more services found";
    338 
    339   p_srvc_cb->srvc_cache.swap(p_srvc_cb->pending_discovery);
    340   std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->pending_discovery);
    341 
    342 #if (BTA_GATT_DEBUG == TRUE)
    343   bta_gattc_display_cache_server(p_srvc_cb->srvc_cache);
    344 #endif
    345   /* save cache to NV */
    346   p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
    347 
    348   if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) {
    349     bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id);
    350   }
    351 
    352   bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
    353 }
    354 
    355 /** process the char descriptor discovery complete event */
    356 static void bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,
    357                                            tBTA_GATTC_SERV* p_srvc_cb) {
    358   ++p_srvc_cb->pending_char;
    359   if (p_srvc_cb->pending_char !=
    360       p_srvc_cb->pending_service->characteristics.end()) {
    361     /* start discoverying next characteristic for char descriptor */
    362     bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
    363     return;
    364   }
    365 
    366   /* all characteristic has been explored, start with next service if any */
    367 #if (BTA_GATT_DEBUG == TRUE)
    368   LOG(ERROR) << "all char has been explored";
    369 #endif
    370   p_srvc_cb->pending_service++;
    371   bta_gattc_explore_srvc(conn_id, p_srvc_cb);
    372 }
    373 
    374 static bool bta_gattc_srvc_in_list(std::vector<tBTA_GATTC_SERVICE>& services,
    375                                    uint16_t s_handle, uint16_t e_handle, Uuid) {
    376   if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle)) {
    377     LOG(ERROR) << "invalid included service s_handle=" << loghex(s_handle)
    378                << ", e_handle=" << loghex(e_handle);
    379     return true;
    380   }
    381 
    382   for (tBTA_GATTC_SERVICE& service : services) {
    383     if (service.s_handle == s_handle || service.e_handle == e_handle)
    384       return true;
    385   }
    386 
    387   return false;
    388 }
    389 
    390 /*******************************************************************************
    391  *
    392  * Function         bta_gattc_sdp_callback
    393  *
    394  * Description      Process the discovery result from sdp
    395  *
    396  * Returns          void
    397  *
    398  ******************************************************************************/
    399 void bta_gattc_sdp_callback(uint16_t sdp_status, void* user_data) {
    400   tBTA_GATTC_CB_DATA* cb_data = (tBTA_GATTC_CB_DATA*)user_data;
    401   tBTA_GATTC_SERV* p_srvc_cb = bta_gattc_find_scb_by_cid(cb_data->sdp_conn_id);
    402 
    403   if (p_srvc_cb == nullptr) {
    404     LOG(ERROR) << "GATT service discovery is done on unknown connection";
    405   } else {
    406     bool no_pending_disc = p_srvc_cb->pending_discovery.empty();
    407 
    408     if ((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) {
    409       tSDP_DISC_REC* p_sdp_rec = NULL;
    410       do {
    411         /* find a service record, report it */
    412         p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
    413         if (p_sdp_rec) {
    414           Uuid service_uuid;
    415           if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) {
    416             tSDP_PROTOCOL_ELEM pe;
    417             if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT,
    418                                               &pe)) {
    419               uint16_t start_handle = (uint16_t)pe.params[0];
    420               uint16_t end_handle = (uint16_t)pe.params[1];
    421 
    422 #if (BTA_GATT_DEBUG == TRUE)
    423               VLOG(1) << "Found ATT service uuid=" << service_uuid
    424                       << ", s_handle=" << loghex(start_handle)
    425                       << ", e_handle=" << loghex(end_handle);
    426 #endif
    427 
    428               if (GATT_HANDLE_IS_VALID(start_handle) &&
    429                   GATT_HANDLE_IS_VALID(end_handle) && p_srvc_cb != NULL) {
    430                 /* discover services result, add services into a service list */
    431                 add_service_to_gatt_db(p_srvc_cb->pending_discovery,
    432                                        start_handle, end_handle, service_uuid,
    433                                        true);
    434               } else {
    435                 LOG(ERROR) << "invalid start_handle=" << loghex(start_handle)
    436                            << ", end_handle=" << loghex(end_handle);
    437               }
    438             }
    439           }
    440         }
    441       } while (p_sdp_rec);
    442     }
    443 
    444     if (no_pending_disc) {
    445       p_srvc_cb->pending_service = p_srvc_cb->pending_discovery.begin();
    446     }
    447 
    448     /* start discover primary service */
    449     bta_gattc_explore_srvc(cb_data->sdp_conn_id, p_srvc_cb);
    450   }
    451 
    452   /* both were allocated in bta_gattc_sdp_service_disc */
    453   osi_free(cb_data->p_sdp_db);
    454   osi_free(cb_data);
    455 }
    456 /*******************************************************************************
    457  *
    458  * Function         bta_gattc_sdp_service_disc
    459  *
    460  * Description      Start DSP Service Discovert
    461  *
    462  * Returns          void
    463  *
    464  ******************************************************************************/
    465 static tGATT_STATUS bta_gattc_sdp_service_disc(uint16_t conn_id,
    466                                                tBTA_GATTC_SERV* p_server_cb) {
    467   uint16_t num_attrs = 2;
    468   uint16_t attr_list[2];
    469 
    470   /*
    471    * On success, cb_data will be freed inside bta_gattc_sdp_callback,
    472    * otherwise it will be freed within this function.
    473    */
    474   tBTA_GATTC_CB_DATA* cb_data =
    475       (tBTA_GATTC_CB_DATA*)osi_malloc(sizeof(tBTA_GATTC_CB_DATA));
    476 
    477   cb_data->p_sdp_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_GATT_SDP_DB_SIZE);
    478   attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
    479   attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
    480 
    481   Uuid uuid = Uuid::From16Bit(UUID_PROTOCOL_ATT);
    482   SDP_InitDiscoveryDb(cb_data->p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1, &uuid,
    483                       num_attrs, attr_list);
    484 
    485   if (!SDP_ServiceSearchAttributeRequest2(p_server_cb->server_bda,
    486                                           cb_data->p_sdp_db,
    487                                           &bta_gattc_sdp_callback, cb_data)) {
    488     osi_free(cb_data->p_sdp_db);
    489     osi_free(cb_data);
    490     return GATT_ERROR;
    491   }
    492 
    493   cb_data->sdp_conn_id = conn_id;
    494   return GATT_SUCCESS;
    495 }
    496 
    497 /** callback function to GATT client stack */
    498 void bta_gattc_disc_res_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
    499                               tGATT_DISC_RES* p_data) {
    500   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    501   tBTA_GATTC_SERV* p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
    502 
    503   if (!p_srvc_cb || !p_clcb || p_clcb->state != BTA_GATTC_DISCOVER_ST) return;
    504 
    505   switch (disc_type) {
    506     case GATT_DISC_SRVC_ALL:
    507     case GATT_DISC_SRVC_BY_UUID:
    508       /* discover services result, add services into a service list */
    509       add_service_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
    510                              p_data->value.group_value.e_handle,
    511                              p_data->value.group_value.service_type, true);
    512       break;
    513 
    514     case GATT_DISC_INC_SRVC:
    515       /* add included service into service list if it's secondary or it never
    516          showed up in the primary service search */
    517       if (!bta_gattc_srvc_in_list(p_srvc_cb->pending_discovery,
    518                                   p_data->value.incl_service.s_handle,
    519                                   p_data->value.incl_service.e_handle,
    520                                   p_data->value.incl_service.service_type)) {
    521         add_service_to_gatt_db(p_srvc_cb->pending_discovery,
    522                                p_data->value.incl_service.s_handle,
    523                                p_data->value.incl_service.e_handle,
    524                                p_data->value.incl_service.service_type, false);
    525       }
    526 
    527       /* add into database */
    528       add_incl_srvc_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
    529                                p_data->value.incl_service.service_type,
    530                                p_data->value.incl_service.s_handle);
    531       break;
    532 
    533     case GATT_DISC_CHAR:
    534       /* add char value into database */
    535       add_characteristic_to_gatt_db(p_srvc_cb->pending_discovery,
    536                                     p_data->handle,
    537                                     p_data->value.dclr_value.val_handle,
    538                                     p_data->value.dclr_value.char_uuid,
    539                                     p_data->value.dclr_value.char_prop);
    540       break;
    541 
    542     case GATT_DISC_CHAR_DSCPT:
    543       add_descriptor_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
    544                                 p_data->type);
    545       break;
    546   }
    547 }
    548 
    549 void bta_gattc_disc_cmpl_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
    550                                tGATT_STATUS status) {
    551   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    552 
    553   if (p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS)) {
    554     if (status == GATT_SUCCESS) p_clcb->status = status;
    555     bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
    556     return;
    557   }
    558 
    559   tBTA_GATTC_SERV* p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
    560   if (!p_srvc_cb) return;
    561 
    562   switch (disc_type) {
    563     case GATT_DISC_SRVC_ALL:
    564     case GATT_DISC_SRVC_BY_UUID:
    565 // definition of all services are discovered, now it's time to discover
    566 // their content
    567 #if (BTA_GATT_DEBUG == TRUE)
    568       bta_gattc_display_explore_record(p_srvc_cb->pending_discovery);
    569 #endif
    570       p_srvc_cb->pending_service = p_srvc_cb->pending_discovery.begin();
    571       bta_gattc_explore_srvc(conn_id, p_srvc_cb);
    572       break;
    573 
    574     case GATT_DISC_INC_SRVC: {
    575       auto& service = *p_srvc_cb->pending_service;
    576 
    577       /* start discoverying characteristic */
    578 
    579       tGATT_DISC_PARAM param = {.s_handle = service.s_handle,
    580                                 .e_handle = service.e_handle};
    581       GATTC_Discover(conn_id, GATT_DISC_CHAR, &param);
    582       break;
    583     }
    584 
    585     case GATT_DISC_CHAR: {
    586 #if (BTA_GATT_DEBUG == TRUE)
    587       bta_gattc_display_explore_record(p_srvc_cb->pending_discovery);
    588 #endif
    589       auto& service = *p_srvc_cb->pending_service;
    590       if (!service.characteristics.empty()) {
    591         /* discover descriptors */
    592         p_srvc_cb->pending_char = service.characteristics.begin();
    593         bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
    594         return;
    595       }
    596       /* start next service */
    597       ++p_srvc_cb->pending_service;
    598       bta_gattc_explore_srvc(conn_id, p_srvc_cb);
    599       break;
    600     }
    601 
    602     case GATT_DISC_CHAR_DSCPT:
    603       bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
    604       break;
    605   }
    606 }
    607 
    608 /** search local cache for matching service record */
    609 void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb, Uuid* p_uuid) {
    610   for (const tBTA_GATTC_SERVICE& service : p_clcb->p_srcb->srvc_cache) {
    611     if (p_uuid && *p_uuid != service.uuid) continue;
    612 
    613 #if (BTA_GATT_DEBUG == TRUE)
    614     VLOG(1) << __func__ << "found service " << service.uuid
    615             << ", inst:" << +service.handle << " handle:" << +service.s_handle;
    616 #endif
    617     if (!p_clcb->p_rcb->p_cback) continue;
    618 
    619     tBTA_GATTC cb_data;
    620     memset(&cb_data, 0, sizeof(tBTA_GATTC));
    621     cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
    622     cb_data.srvc_res.service_uuid.inst_id = service.handle;
    623     cb_data.srvc_res.service_uuid.uuid = service.uuid;
    624 
    625     (*p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
    626   }
    627 }
    628 
    629 std::vector<tBTA_GATTC_SERVICE>* bta_gattc_get_services_srcb(
    630     tBTA_GATTC_SERV* p_srcb) {
    631   if (!p_srcb || p_srcb->srvc_cache.empty()) return NULL;
    632 
    633   return &p_srcb->srvc_cache;
    634 }
    635 
    636 std::vector<tBTA_GATTC_SERVICE>* bta_gattc_get_services(uint16_t conn_id) {
    637   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    638 
    639   if (p_clcb == NULL) return NULL;
    640 
    641   tBTA_GATTC_SERV* p_srcb = p_clcb->p_srcb;
    642 
    643   return bta_gattc_get_services_srcb(p_srcb);
    644 }
    645 
    646 tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle_srcb(
    647     tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
    648   std::vector<tBTA_GATTC_SERVICE>* services =
    649       bta_gattc_get_services_srcb(p_srcb);
    650   if (services == NULL) return NULL;
    651   return bta_gattc_find_matching_service(*services, handle);
    652 }
    653 
    654 const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle(uint16_t conn_id,
    655                                                            uint16_t handle) {
    656   std::vector<tBTA_GATTC_SERVICE>* services = bta_gattc_get_services(conn_id);
    657   if (services == NULL) return NULL;
    658 
    659   return bta_gattc_find_matching_service(*services, handle);
    660 }
    661 
    662 tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(
    663     tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
    664   tBTA_GATTC_SERVICE* service =
    665       bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
    666 
    667   if (!service) return NULL;
    668 
    669   for (tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
    670     if (handle == charac.value_handle) return &charac;
    671   }
    672 
    673   return NULL;
    674 }
    675 
    676 tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic(uint16_t conn_id,
    677                                                         uint16_t handle) {
    678   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    679 
    680   if (p_clcb == NULL) return NULL;
    681 
    682   tBTA_GATTC_SERV* p_srcb = p_clcb->p_srcb;
    683   return bta_gattc_get_characteristic_srcb(p_srcb, handle);
    684 }
    685 
    686 const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(
    687     tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
    688   const tBTA_GATTC_SERVICE* service =
    689       bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
    690 
    691   if (!service) {
    692     return NULL;
    693   }
    694 
    695   for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
    696     for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
    697       if (handle == desc.handle) return &desc;
    698     }
    699   }
    700 
    701   return NULL;
    702 }
    703 
    704 const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(uint16_t conn_id,
    705                                                       uint16_t handle) {
    706   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    707 
    708   if (p_clcb == NULL) return NULL;
    709 
    710   tBTA_GATTC_SERV* p_srcb = p_clcb->p_srcb;
    711   return bta_gattc_get_descriptor_srcb(p_srcb, handle);
    712 }
    713 
    714 tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_owning_characteristic_srcb(
    715     tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
    716   tBTA_GATTC_SERVICE* service =
    717       bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
    718 
    719   if (!service) return NULL;
    720 
    721   for (tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
    722     for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
    723       if (handle == desc.handle) return &charac;
    724     }
    725   }
    726 
    727   return NULL;
    728 }
    729 
    730 const tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_owning_characteristic(
    731     uint16_t conn_id, uint16_t handle) {
    732   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    733   if (!p_clcb) return NULL;
    734 
    735   return bta_gattc_get_owning_characteristic_srcb(p_clcb->p_srcb, handle);
    736 }
    737 
    738 /*******************************************************************************
    739  *
    740  * Function         bta_gattc_fill_gatt_db_el
    741  *
    742  * Description      fill a btgatt_db_element_t value
    743  *
    744  * Returns          None.
    745  *
    746  ******************************************************************************/
    747 void bta_gattc_fill_gatt_db_el(btgatt_db_element_t* p_attr,
    748                                bt_gatt_db_attribute_type_t type,
    749                                uint16_t att_handle, uint16_t s_handle,
    750                                uint16_t e_handle, uint16_t id, const Uuid& uuid,
    751                                uint8_t prop) {
    752   p_attr->type = type;
    753   p_attr->attribute_handle = att_handle;
    754   p_attr->start_handle = s_handle;
    755   p_attr->end_handle = e_handle;
    756   p_attr->id = id;
    757   p_attr->properties = prop;
    758 
    759   // Permissions are not discoverable using the attribute protocol.
    760   // Core 5.0, Part F, 3.2.5 Attribute Permissions
    761   p_attr->permissions = 0;
    762   p_attr->uuid = uuid;
    763 }
    764 
    765 /*******************************************************************************
    766  * Returns          number of elements inside db from start_handle to end_handle
    767  ******************************************************************************/
    768 static size_t bta_gattc_get_db_size(
    769     const std::vector<tBTA_GATTC_SERVICE>& services, uint16_t start_handle,
    770     uint16_t end_handle) {
    771   if (services.empty()) return 0;
    772 
    773   size_t db_size = 0;
    774 
    775   for (const tBTA_GATTC_SERVICE& service : services) {
    776     if (service.s_handle < start_handle) continue;
    777 
    778     if (service.e_handle > end_handle) break;
    779 
    780     db_size++;
    781 
    782     for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
    783       db_size++;
    784 
    785       db_size += charac.descriptors.size();
    786     }
    787 
    788     db_size += service.included_svc.size();
    789   }
    790 
    791   return db_size;
    792 }
    793 
    794 /*******************************************************************************
    795  *
    796  * Function         bta_gattc_get_gatt_db_impl
    797  *
    798  * Description      copy the server GATT database into db parameter.
    799  *
    800  * Parameters       p_srvc_cb: server.
    801  *                  db: output parameter which will contain GATT database copy.
    802  *                      Caller is responsible for freeing it.
    803  *                  count: output parameter which will contain number of
    804  *                  elements in database.
    805  *
    806  * Returns          None.
    807  *
    808  ******************************************************************************/
    809 static void bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV* p_srvc_cb,
    810                                        uint16_t start_handle,
    811                                        uint16_t end_handle,
    812                                        btgatt_db_element_t** db, int* count) {
    813   VLOG(1) << __func__
    814           << StringPrintf(": start_handle 0x%04x, end_handle 0x%04x",
    815                           start_handle, end_handle);
    816 
    817   if (p_srvc_cb->srvc_cache.empty()) {
    818     *count = 0;
    819     *db = NULL;
    820     return;
    821   }
    822 
    823   size_t db_size =
    824       bta_gattc_get_db_size(p_srvc_cb->srvc_cache, start_handle, end_handle);
    825 
    826   void* buffer = osi_malloc(db_size * sizeof(btgatt_db_element_t));
    827   btgatt_db_element_t* curr_db_attr = (btgatt_db_element_t*)buffer;
    828 
    829   for (const tBTA_GATTC_SERVICE& service : p_srvc_cb->srvc_cache) {
    830     if (service.s_handle < start_handle) continue;
    831 
    832     if (service.e_handle > end_handle) break;
    833 
    834     bta_gattc_fill_gatt_db_el(curr_db_attr,
    835                               service.is_primary ? BTGATT_DB_PRIMARY_SERVICE
    836                                                  : BTGATT_DB_SECONDARY_SERVICE,
    837                               0 /* att_handle */, service.s_handle,
    838                               service.e_handle, service.s_handle, service.uuid,
    839                               0 /* prop */);
    840     curr_db_attr++;
    841 
    842     for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
    843       bta_gattc_fill_gatt_db_el(curr_db_attr, BTGATT_DB_CHARACTERISTIC,
    844                                 charac.value_handle, 0 /* s_handle */,
    845                                 0 /* e_handle */, charac.value_handle,
    846                                 charac.uuid, charac.properties);
    847       curr_db_attr++;
    848 
    849       for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
    850         bta_gattc_fill_gatt_db_el(
    851             curr_db_attr, BTGATT_DB_DESCRIPTOR, desc.handle, 0 /* s_handle */,
    852             0 /* e_handle */, desc.handle, desc.uuid, 0 /* property */);
    853         curr_db_attr++;
    854       }
    855     }
    856 
    857     for (const tBTA_GATTC_INCLUDED_SVC& p_isvc : service.included_svc) {
    858       bta_gattc_fill_gatt_db_el(
    859           curr_db_attr, BTGATT_DB_INCLUDED_SERVICE, p_isvc.handle,
    860           p_isvc.included_service ? p_isvc.included_service->s_handle : 0,
    861           0 /* e_handle */, p_isvc.handle, p_isvc.uuid, 0 /* property */);
    862       curr_db_attr++;
    863     }
    864   }
    865 
    866   *db = (btgatt_db_element_t*)buffer;
    867   *count = db_size;
    868 }
    869 
    870 /*******************************************************************************
    871  *
    872  * Function         bta_gattc_get_gatt_db
    873  *
    874  * Description      copy the server GATT database into db parameter.
    875  *
    876  * Parameters       conn_id: connection ID which identify the server.
    877  *                  db: output parameter which will contain GATT database copy.
    878  *                      Caller is responsible for freeing it.
    879  *                  count: number of elements in database.
    880  *
    881  * Returns          None.
    882  *
    883  ******************************************************************************/
    884 void bta_gattc_get_gatt_db(uint16_t conn_id, uint16_t start_handle,
    885                            uint16_t end_handle, btgatt_db_element_t** db,
    886                            int* count) {
    887   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
    888 
    889   LOG_DEBUG(LOG_TAG, "%s", __func__);
    890   if (p_clcb == NULL) {
    891     LOG(ERROR) << "Unknown conn_id=" << loghex(conn_id);
    892     return;
    893   }
    894 
    895   if (p_clcb->state != BTA_GATTC_CONN_ST) {
    896     LOG(ERROR) << "server cache not available, CLCB state=" << +p_clcb->state;
    897     return;
    898   }
    899 
    900   if (!p_clcb->p_srcb ||
    901       !p_clcb->p_srcb->pending_discovery.empty() || /* no active discovery */
    902       p_clcb->p_srcb->srvc_cache.empty()) {
    903     LOG(ERROR) << "No server cache available";
    904     return;
    905   }
    906 
    907   bta_gattc_get_gatt_db_impl(p_clcb->p_srcb, start_handle, end_handle, db,
    908                              count);
    909 }
    910 
    911 /* rebuild server cache from NV cache */
    912 void bta_gattc_rebuild_cache(tBTA_GATTC_SERV* p_srvc_cb, uint16_t num_attr,
    913                              tBTA_GATTC_NV_ATTR* p_attr) {
    914   /* first attribute loading, initialize buffer */
    915   LOG(INFO) << __func__ << " " << num_attr;
    916 
    917   // clear reallocating
    918   std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->srvc_cache);
    919 
    920   while (num_attr > 0 && p_attr != NULL) {
    921     switch (p_attr->attr_type) {
    922       case BTA_GATTC_ATTR_TYPE_SRVC:
    923         add_service_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
    924                                p_attr->e_handle, p_attr->uuid,
    925                                p_attr->is_primary);
    926         break;
    927 
    928       case BTA_GATTC_ATTR_TYPE_CHAR:
    929         add_characteristic_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
    930                                       p_attr->s_handle, p_attr->uuid,
    931                                       p_attr->prop);
    932         break;
    933 
    934       case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
    935         add_descriptor_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
    936                                   p_attr->uuid);
    937         break;
    938       case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
    939         add_incl_srvc_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
    940                                  p_attr->uuid, p_attr->incl_srvc_handle);
    941         break;
    942     }
    943     p_attr++;
    944     num_attr--;
    945   }
    946 }
    947 
    948 /*******************************************************************************
    949  *
    950  * Function         bta_gattc_fill_nv_attr
    951  *
    952  * Description      fill a NV attribute entry value
    953  *
    954  * Returns          None.
    955  *
    956  ******************************************************************************/
    957 void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR* p_attr, uint8_t type,
    958                             uint16_t s_handle, uint16_t e_handle, Uuid uuid,
    959                             uint8_t prop, uint16_t incl_srvc_handle,
    960                             bool is_primary) {
    961   p_attr->s_handle = s_handle;
    962   p_attr->e_handle = e_handle;
    963   p_attr->attr_type = type;
    964   p_attr->is_primary = is_primary;
    965   p_attr->id = 0;
    966   p_attr->prop = prop;
    967   p_attr->incl_srvc_handle = incl_srvc_handle;
    968   p_attr->uuid = uuid;
    969 }
    970 
    971 /*******************************************************************************
    972  *
    973  * Function         bta_gattc_cache_save
    974  *
    975  * Description      save the server cache into NV
    976  *
    977  * Returns          None.
    978  *
    979  ******************************************************************************/
    980 void bta_gattc_cache_save(tBTA_GATTC_SERV* p_srvc_cb, uint16_t conn_id) {
    981   if (p_srvc_cb->srvc_cache.empty()) return;
    982 
    983   int i = 0;
    984   size_t db_size = bta_gattc_get_db_size(p_srvc_cb->srvc_cache, 0x0000, 0xFFFF);
    985   tBTA_GATTC_NV_ATTR* nv_attr =
    986       (tBTA_GATTC_NV_ATTR*)osi_malloc(db_size * sizeof(tBTA_GATTC_NV_ATTR));
    987 
    988   for (const tBTA_GATTC_SERVICE& service : p_srvc_cb->srvc_cache) {
    989     bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_SRVC,
    990                            service.s_handle, service.e_handle, service.uuid,
    991                            0 /* properties */, 0 /* incl_srvc_handle */,
    992                            service.is_primary);
    993   }
    994 
    995   for (const tBTA_GATTC_SERVICE& service : p_srvc_cb->srvc_cache) {
    996     for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
    997       bta_gattc_fill_nv_attr(
    998           &nv_attr[i++], BTA_GATTC_ATTR_TYPE_CHAR, charac.value_handle, 0,
    999           charac.uuid, charac.properties, 0 /* incl_srvc_handle */, false);
   1000 
   1001       for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
   1002         bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
   1003                                desc.handle, 0, desc.uuid, 0 /* properties */,
   1004                                0 /* incl_srvc_handle */, false);
   1005       }
   1006     }
   1007 
   1008     for (const tBTA_GATTC_INCLUDED_SVC& p_isvc : service.included_svc) {
   1009       bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_INCL_SRVC,
   1010                              p_isvc.handle, 0, p_isvc.uuid, 0 /* properties */,
   1011                              p_isvc.included_service->s_handle, false);
   1012     }
   1013   }
   1014 
   1015   bta_gattc_cache_write(p_srvc_cb->server_bda, db_size, nv_attr);
   1016   osi_free(nv_attr);
   1017 }
   1018 
   1019 /*******************************************************************************
   1020  *
   1021  * Function         bta_gattc_cache_load
   1022  *
   1023  * Description      Load GATT cache from storage for server.
   1024  *
   1025  * Parameter        p_clcb: pointer to server clcb, that will
   1026  *                          be filled from storage
   1027  * Returns          true on success, false otherwise
   1028  *
   1029  ******************************************************************************/
   1030 bool bta_gattc_cache_load(tBTA_GATTC_CLCB* p_clcb) {
   1031   char fname[255] = {0};
   1032   bta_gattc_generate_cache_file_name(fname, sizeof(fname),
   1033                                      p_clcb->p_srcb->server_bda);
   1034 
   1035   FILE* fd = fopen(fname, "rb");
   1036   if (!fd) {
   1037     LOG(ERROR) << __func__ << ": can't open GATT cache file " << fname
   1038                << " for reading, error: " << strerror(errno);
   1039     return false;
   1040   }
   1041 
   1042   uint16_t cache_ver = 0;
   1043   tBTA_GATTC_NV_ATTR* attr = NULL;
   1044   bool success = false;
   1045   uint16_t num_attr = 0;
   1046 
   1047   if (fread(&cache_ver, sizeof(uint16_t), 1, fd) != 1) {
   1048     LOG(ERROR) << __func__ << ": can't read GATT cache version from: " << fname;
   1049     goto done;
   1050   }
   1051 
   1052   if (cache_ver != GATT_CACHE_VERSION) {
   1053     LOG(ERROR) << __func__ << ": wrong GATT cache version: " << fname;
   1054     goto done;
   1055   }
   1056 
   1057   if (fread(&num_attr, sizeof(uint16_t), 1, fd) != 1) {
   1058     LOG(ERROR) << __func__
   1059                << ": can't read number of GATT attributes: " << fname;
   1060     goto done;
   1061   }
   1062 
   1063   attr = (tBTA_GATTC_NV_ATTR*)osi_malloc(sizeof(tBTA_GATTC_NV_ATTR) * num_attr);
   1064 
   1065   if (fread(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) {
   1066     LOG(ERROR) << __func__ << "s: can't read GATT attributes: " << fname;
   1067     goto done;
   1068   }
   1069 
   1070   bta_gattc_rebuild_cache(p_clcb->p_srcb, num_attr, attr);
   1071 
   1072   success = true;
   1073 
   1074 done:
   1075   osi_free(attr);
   1076   fclose(fd);
   1077   return success;
   1078 }
   1079 
   1080 /*******************************************************************************
   1081  *
   1082  * Function         bta_gattc_cache_write
   1083  *
   1084  * Description      This callout function is executed by GATT when a server
   1085  *                  cache is available to save.
   1086  *
   1087  * Parameter        server_bda: server bd address of this cache belongs to
   1088  *                  num_attr: number of attribute to be save.
   1089  *                  attr: pointer to the list of attributes to save.
   1090  * Returns
   1091  *
   1092  ******************************************************************************/
   1093 static void bta_gattc_cache_write(const RawAddress& server_bda,
   1094                                   uint16_t num_attr, tBTA_GATTC_NV_ATTR* attr) {
   1095   char fname[255] = {0};
   1096   bta_gattc_generate_cache_file_name(fname, sizeof(fname), server_bda);
   1097 
   1098   FILE* fd = fopen(fname, "wb");
   1099   if (!fd) {
   1100     LOG(ERROR) << __func__
   1101                << ": can't open GATT cache file for writing: " << fname;
   1102     return;
   1103   }
   1104 
   1105   uint16_t cache_ver = GATT_CACHE_VERSION;
   1106   if (fwrite(&cache_ver, sizeof(uint16_t), 1, fd) != 1) {
   1107     LOG(ERROR) << __func__ << ": can't write GATT cache version: " << fname;
   1108     fclose(fd);
   1109     return;
   1110   }
   1111 
   1112   if (fwrite(&num_attr, sizeof(uint16_t), 1, fd) != 1) {
   1113     LOG(ERROR) << __func__
   1114                << ": can't write GATT cache attribute count: " << fname;
   1115     fclose(fd);
   1116     return;
   1117   }
   1118 
   1119   if (fwrite(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) {
   1120     LOG(ERROR) << __func__ << ": can't write GATT cache attributes: " << fname;
   1121     fclose(fd);
   1122     return;
   1123   }
   1124 
   1125   fclose(fd);
   1126 }
   1127 
   1128 /*******************************************************************************
   1129  *
   1130  * Function         bta_gattc_cache_reset
   1131  *
   1132  * Description      This callout function is executed by GATTC to reset cache in
   1133  *                  application
   1134  *
   1135  * Parameter        server_bda: server bd address of this cache belongs to
   1136  *
   1137  * Returns          void.
   1138  *
   1139  ******************************************************************************/
   1140 void bta_gattc_cache_reset(const RawAddress& server_bda) {
   1141   VLOG(1) << __func__;
   1142   char fname[255] = {0};
   1143   bta_gattc_generate_cache_file_name(fname, sizeof(fname), server_bda);
   1144   unlink(fname);
   1145 }
   1146