bta_gattc_cache.cc revision 0bdae6a1c108f8a699bfeeb362023de848750a65
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
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);
56const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(
57    tBTA_GATTC_SERV* p_srcb, uint16_t handle);
58tBTA_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
66static 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
77typedef 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 */
86static 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 */
116static 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 */
125static 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 ******************************************************************************/
144tGATT_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
151tBTA_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 */
162static 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 */
179static 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 */
211static 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 */
244static 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 */
276tGATT_STATUS bta_gattc_discover_pri_service(uint16_t conn_id,
277                                            tBTA_GATTC_SERV* p_server_cb,
278                                            uint8_t disc_type) {
279  tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
280  if (!p_clcb) return GATT_ERROR;
281
282  if (p_clcb->transport == BTA_TRANSPORT_LE) {
283    tGATT_DISC_PARAM param{.s_handle = 0x0001, .e_handle = 0xFFFF};
284    return GATTC_Discover(conn_id, disc_type, &param);
285  }
286
287  return bta_gattc_sdp_service_disc(conn_id, p_server_cb);
288}
289
290/** Start discovery for characteristic descriptor */
291void bta_gattc_start_disc_char_dscp(uint16_t conn_id,
292                                    tBTA_GATTC_SERV* p_srvc_cb) {
293  VLOG(1) << "starting discover characteristics descriptor";
294  auto& characteristic = p_srvc_cb->pending_char;
295
296  uint16_t end_handle = 0xFFFF;
297  // if there are more characteristics in the service
298  if (std::next(p_srvc_cb->pending_char) !=
299      p_srvc_cb->pending_service->characteristics.end()) {
300    // end at beginning of next characteristic
301    end_handle = std::next(p_srvc_cb->pending_char)->declaration_handle - 1;
302  } else {
303    // end at the end of current service
304    end_handle = p_srvc_cb->pending_service->e_handle;
305  }
306
307  tGATT_DISC_PARAM param{
308      .s_handle = (uint16_t)(characteristic->value_handle + 1),
309      .e_handle = end_handle};
310  if (GATTC_Discover(conn_id, GATT_DISC_CHAR_DSCPT, &param) != 0) {
311    bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
312  }
313}
314
315/** process the service discovery complete event */
316static void bta_gattc_explore_srvc(uint16_t conn_id,
317                                   tBTA_GATTC_SERV* p_srvc_cb) {
318  tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
319  if (!p_clcb) {
320    LOG(ERROR) << "unknown conn_id=" << +conn_id;
321    return;
322  }
323
324  /* start expore a service if there is service not been explored */
325  if (p_srvc_cb->pending_service != p_srvc_cb->pending_discovery.end()) {
326    auto& service = *p_srvc_cb->pending_service;
327    VLOG(1) << "Start service discovery";
328
329    /* start discovering included services */
330    tGATT_DISC_PARAM param = {.s_handle = service.s_handle,
331                              .e_handle = service.e_handle};
332    GATTC_Discover(conn_id, GATT_DISC_INC_SRVC, &param);
333    return;
334  }
335
336  /* no service found at all, the end of server discovery*/
337  LOG(INFO) << __func__ << ": no more services found";
338
339  p_srvc_cb->srvc_cache.swap(p_srvc_cb->pending_discovery);
340  std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->pending_discovery);
341
342#if (BTA_GATT_DEBUG == TRUE)
343  bta_gattc_display_cache_server(p_srvc_cb->srvc_cache);
344#endif
345  /* save cache to NV */
346  p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
347
348  if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) {
349    bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id);
350  }
351
352  bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
353}
354
355/** process the char descriptor discovery complete event */
356static 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
374static 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 ******************************************************************************/
399void 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  bool no_pending_disc = p_srvc_cb->pending_discovery.empty();
404
405  if (((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) &&
406      p_srvc_cb != NULL) {
407    tSDP_DISC_REC* p_sdp_rec = NULL;
408    do {
409      /* find a service record, report it */
410      p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
411      if (p_sdp_rec) {
412        Uuid service_uuid;
413        if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) {
414          tSDP_PROTOCOL_ELEM pe;
415          if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT,
416                                            &pe)) {
417            uint16_t start_handle = (uint16_t)pe.params[0];
418            uint16_t end_handle = (uint16_t)pe.params[1];
419
420#if (BTA_GATT_DEBUG == TRUE)
421            VLOG(1) << "Found ATT service uuid=" << service_uuid
422                    << ", s_handle=" << loghex(start_handle)
423                    << ", e_handle=" << loghex(end_handle);
424#endif
425
426            if (GATT_HANDLE_IS_VALID(start_handle) &&
427                GATT_HANDLE_IS_VALID(end_handle) && p_srvc_cb != NULL) {
428              /* discover services result, add services into a service list */
429              add_service_to_gatt_db(p_srvc_cb->pending_discovery, start_handle,
430                                     end_handle, service_uuid, true);
431            } else {
432              LOG(ERROR) << "invalid start_handle=" << loghex(start_handle)
433                         << ", end_handle=" << loghex(end_handle);
434            }
435          }
436        }
437      }
438    } while (p_sdp_rec);
439  }
440
441  if (p_srvc_cb != NULL) {
442    if (no_pending_disc) {
443      p_srvc_cb->pending_service = p_srvc_cb->pending_discovery.begin();
444    }
445
446    /* start discover primary service */
447    bta_gattc_explore_srvc(cb_data->sdp_conn_id, p_srvc_cb);
448  } else {
449    LOG(ERROR) << "GATT service discovery is done on unknown connection";
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 ******************************************************************************/
465static 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 */
498void 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
549void bta_gattc_disc_cmpl_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
550                               tGATT_STATUS status) {
551  tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
552
553  if (p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS)) {
554    if (status == GATT_SUCCESS) p_clcb->status = status;
555    bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
556    return;
557  }
558
559  tBTA_GATTC_SERV* p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
560  if (!p_srvc_cb) return;
561
562  switch (disc_type) {
563    case GATT_DISC_SRVC_ALL:
564    case GATT_DISC_SRVC_BY_UUID:
565// definition of all services are discovered, now it's time to discover
566// their content
567#if (BTA_GATT_DEBUG == TRUE)
568      bta_gattc_display_explore_record(p_srvc_cb->pending_discovery);
569#endif
570      p_srvc_cb->pending_service = p_srvc_cb->pending_discovery.begin();
571      bta_gattc_explore_srvc(conn_id, p_srvc_cb);
572      break;
573
574    case GATT_DISC_INC_SRVC: {
575      auto& service = *p_srvc_cb->pending_service;
576
577      /* start discoverying characteristic */
578
579      tGATT_DISC_PARAM param = {.s_handle = service.s_handle,
580                                .e_handle = service.e_handle};
581      GATTC_Discover(conn_id, GATT_DISC_CHAR, &param);
582      break;
583    }
584
585    case GATT_DISC_CHAR: {
586#if (BTA_GATT_DEBUG == TRUE)
587      bta_gattc_display_explore_record(p_srvc_cb->pending_discovery);
588#endif
589      auto& service = *p_srvc_cb->pending_service;
590      if (!service.characteristics.empty()) {
591        /* discover descriptors */
592        p_srvc_cb->pending_char = service.characteristics.begin();
593        bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
594        return;
595      }
596      /* start next service */
597      ++p_srvc_cb->pending_service;
598      bta_gattc_explore_srvc(conn_id, p_srvc_cb);
599      break;
600    }
601
602    case GATT_DISC_CHAR_DSCPT:
603      bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
604      break;
605  }
606}
607
608/** search local cache for matching service record */
609void 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
629std::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
636std::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
646tBTA_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
654const 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
662tBTA_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
676tBTA_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
686const 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
704const 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
714tBTA_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
730const 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 ******************************************************************************/
747void 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 ******************************************************************************/
768static 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 ******************************************************************************/
809static 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 ******************************************************************************/
884void 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 */
912void 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 ******************************************************************************/
957void 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 ******************************************************************************/
980void 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 ******************************************************************************/
1030bool 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
1074done:
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 ******************************************************************************/
1093static 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 ******************************************************************************/
1140void 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