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 
bta_gattc_generate_cache_file_name(char * buffer,size_t buffer_len,const RawAddress & bda)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 */
display_db(const std::vector<tBTA_GATTC_SERVICE> & 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 */
bta_gattc_display_cache_server(const std::vector<tBTA_GATTC_SERVICE> & 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 */
bta_gattc_display_explore_record(const std::vector<tBTA_GATTC_SERVICE> & cache)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  ******************************************************************************/
bta_gattc_init_cache(tBTA_GATTC_SERV * p_srvc_cb)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 
bta_gattc_find_matching_service(std::vector<tBTA_GATTC_SERVICE> & services,uint16_t handle)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 */
add_service_to_gatt_db(std::vector<tBTA_GATTC_SERVICE> & gatt_db,uint16_t s_handle,uint16_t e_handle,const Uuid & uuid,bool is_primary)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 */
add_characteristic_to_gatt_db(std::vector<tBTA_GATTC_SERVICE> & gatt_db,uint16_t attr_handle,uint16_t value_handle,const Uuid & uuid,uint8_t property)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 */
add_descriptor_to_gatt_db(std::vector<tBTA_GATTC_SERVICE> & gatt_db,uint16_t handle,const Uuid & uuid)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 */
add_incl_srvc_to_gatt_db(std::vector<tBTA_GATTC_SERVICE> & gatt_db,uint16_t handle,const Uuid & uuid,uint16_t incl_srvc_s_handle)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 */
bta_gattc_discover_pri_service(uint16_t conn_id,tBTA_GATTC_SERV * p_server_cb,uint8_t disc_type)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 */
bta_gattc_start_disc_char_dscp(uint16_t conn_id,tBTA_GATTC_SERV * p_srvc_cb)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 */
bta_gattc_explore_srvc(uint16_t conn_id,tBTA_GATTC_SERV * p_srvc_cb)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 */
bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,tBTA_GATTC_SERV * p_srvc_cb)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 
bta_gattc_srvc_in_list(std::vector<tBTA_GATTC_SERVICE> & services,uint16_t s_handle,uint16_t e_handle,Uuid)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  ******************************************************************************/
bta_gattc_sdp_callback(uint16_t sdp_status,void * user_data)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  ******************************************************************************/
bta_gattc_sdp_service_disc(uint16_t conn_id,tBTA_GATTC_SERV * p_server_cb)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 */
bta_gattc_disc_res_cback(uint16_t conn_id,tGATT_DISC_TYPE disc_type,tGATT_DISC_RES * p_data)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 
bta_gattc_disc_cmpl_cback(uint16_t conn_id,tGATT_DISC_TYPE disc_type,tGATT_STATUS status)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 */
bta_gattc_search_service(tBTA_GATTC_CLCB * p_clcb,Uuid * p_uuid)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 
bta_gattc_get_services_srcb(tBTA_GATTC_SERV * p_srcb)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 
bta_gattc_get_services(uint16_t conn_id)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 
bta_gattc_get_service_for_handle_srcb(tBTA_GATTC_SERV * p_srcb,uint16_t handle)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 
bta_gattc_get_service_for_handle(uint16_t conn_id,uint16_t handle)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 
bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV * p_srcb,uint16_t handle)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 
bta_gattc_get_characteristic(uint16_t conn_id,uint16_t handle)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 
bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV * p_srcb,uint16_t handle)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 
bta_gattc_get_descriptor(uint16_t conn_id,uint16_t handle)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 
bta_gattc_get_owning_characteristic_srcb(tBTA_GATTC_SERV * p_srcb,uint16_t handle)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 
bta_gattc_get_owning_characteristic(uint16_t conn_id,uint16_t handle)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  ******************************************************************************/
bta_gattc_fill_gatt_db_el(btgatt_db_element_t * p_attr,bt_gatt_db_attribute_type_t type,uint16_t att_handle,uint16_t s_handle,uint16_t e_handle,uint16_t id,const Uuid & uuid,uint8_t prop)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  ******************************************************************************/
bta_gattc_get_db_size(const std::vector<tBTA_GATTC_SERVICE> & services,uint16_t start_handle,uint16_t end_handle)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  ******************************************************************************/
bta_gattc_get_gatt_db_impl(tBTA_GATTC_SERV * p_srvc_cb,uint16_t start_handle,uint16_t end_handle,btgatt_db_element_t ** db,int * count)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  ******************************************************************************/
bta_gattc_get_gatt_db(uint16_t conn_id,uint16_t start_handle,uint16_t end_handle,btgatt_db_element_t ** db,int * count)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 */
bta_gattc_rebuild_cache(tBTA_GATTC_SERV * p_srvc_cb,uint16_t num_attr,tBTA_GATTC_NV_ATTR * p_attr)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  ******************************************************************************/
bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR * p_attr,uint8_t type,uint16_t s_handle,uint16_t e_handle,Uuid uuid,uint8_t prop,uint16_t incl_srvc_handle,bool is_primary)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  ******************************************************************************/
bta_gattc_cache_save(tBTA_GATTC_SERV * p_srvc_cb,uint16_t conn_id)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  ******************************************************************************/
bta_gattc_cache_load(tBTA_GATTC_CLCB * p_clcb)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  ******************************************************************************/
bta_gattc_cache_write(const RawAddress & server_bda,uint16_t num_attr,tBTA_GATTC_NV_ATTR * attr)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  ******************************************************************************/
bta_gattc_cache_reset(const RawAddress & server_bda)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