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