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, ¶m);
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, ¶m) != 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, ¶m);
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, ¶m);
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