Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit de3cc5f5 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

GATT discovery refactor

Currently, when doing service discovery, we store pending discovery
content into tBTA_GATTC_ATTR_REC structure, and rewrite it into cache,
service after service during discovery.
From now on, we save discovery result directly into pending_discovery,
and at end of discovery we swap it with cache. This remove unncecessary
intermidiate step, and simplify the discovery.

Bug: 67057055
Test: GattReadTest
Change-Id: Id09026b6fb6df04eaf0a0ebefeb6e35b3d175f62
parent 9793bfc6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -700,9 +700,9 @@ void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB* p_clcb,
    /* used to reset cache in application */
    bta_gattc_cache_reset(p_clcb->p_srcb->server_bda);
  }
  if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_list) {
  if (p_clcb->p_srcb) {
    /* release pending attribute list buffer */
    osi_free_and_reset((void**)&p_clcb->p_srcb->p_srvc_list);
    p_clcb->p_srcb->pending_discovery.clear();
  }

  if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING) {
+114 −283
Original line number Diff line number Diff line
@@ -83,10 +83,7 @@ typedef struct {
/* utility functions */

/* debug function to display the server cache */
static void bta_gattc_display_cache_server(
    const std::vector<tBTA_GATTC_SERVICE>& cache) {
  LOG(ERROR) << "<================Start Server Cache =============>";

static void display_db(const std::vector<tBTA_GATTC_SERVICE>& cache) {
  for (const tBTA_GATTC_SERVICE& service : cache) {
    LOG(ERROR) << "Service: s_handle=" << loghex(service.s_handle)
               << ", e_handle=" << loghex(service.e_handle)
@@ -99,7 +96,7 @@ static void bta_gattc_display_cache_server(
    }

    for (const tBTA_GATTC_CHARACTERISTIC& c : service.characteristics) {
      LOG(ERROR) << "\t Characteristic handle=" << loghex(c.handle)
      LOG(ERROR) << "\t Characteristic value_handle=" << loghex(c.value_handle)
                 << ", uuid=" << c.uuid << ", prop=" << loghex(c.properties);

      if (c.descriptors.empty()) {
@@ -113,32 +110,22 @@ static void bta_gattc_display_cache_server(
      }
    }
  }
}

/* debug function to display the server cache */
static void bta_gattc_display_cache_server(
    const std::vector<tBTA_GATTC_SERVICE>& cache) {
  LOG(ERROR) << "<================Start Server Cache =============>";
  display_db(cache);
  LOG(ERROR) << "<================End Server Cache =============>";
  LOG(ERROR) << " ";
}

/*******************************************************************************
 *
 * Function         bta_gattc_display_explore_record
 *
 * Description      debug function to display the exploration list
 *
 * Returns          none.
 *
 ******************************************************************************/
static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC* p_rec,
                                             uint8_t num_rec) {
  uint8_t i;
  tBTA_GATTC_ATTR_REC* pp = p_rec;

/** debug function to display the exploration list */
static void bta_gattc_display_explore_record(
    const std::vector<tBTA_GATTC_SERVICE>& cache) {
  LOG(ERROR) << "<================Start Explore Queue =============>";
  for (i = 0; i < num_rec; i++, pp++) {
    LOG(ERROR) << StringPrintf(
        "\t rec[%d] uuid[%s] s_handle[%d] e_handle[%d] is_primary[%d]", i + 1,
        pp->uuid.ToString().c_str(), pp->s_handle, pp->e_handle,
        pp->is_primary);
  }
  display_db(cache);
  LOG(ERROR) << "<================ End Explore Queue =============>";
  LOG(ERROR) << " ";
}
@@ -157,15 +144,7 @@ static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC* p_rec,
tGATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb) {
  // clear reallocating
  std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->srvc_cache);

  osi_free(p_srvc_cb->p_srvc_list);
  p_srvc_cb->p_srvc_list =
      (tBTA_GATTC_ATTR_REC*)osi_malloc(BTA_GATTC_ATTR_LIST_SIZE);
  p_srvc_cb->total_srvc = 0;
  p_srvc_cb->cur_srvc_idx = 0;
  p_srvc_cb->cur_char_idx = 0;
  p_srvc_cb->next_avail_idx = 0;

  std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->pending_discovery);
  return GATT_SUCCESS;
}

@@ -221,7 +200,8 @@ static void add_characteristic_to_gatt_db(
  if (service->e_handle < value_handle) service->e_handle = value_handle;

  service->characteristics.emplace_back(
      tBTA_GATTC_CHARACTERISTIC{.value_handle = value_handle,
      tBTA_GATTC_CHARACTERISTIC{.declaration_handle = attr_handle,
                                .value_handle = value_handle,
                                .properties = property,
                                .uuid = uuid,
                                .service = service});
@@ -250,9 +230,15 @@ static void add_descriptor_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
    return;
  }

  tBTA_GATTC_CHARACTERISTIC& char_node = service->characteristics.back();
  char_node.descriptors.emplace_back(tBTA_GATTC_DESCRIPTOR{
      .handle = handle, .uuid = uuid, .characteristic = &char_node,
  tBTA_GATTC_CHARACTERISTIC* char_node = &service->characteristics.front();
  for (auto it = service->characteristics.begin();
       it != service->characteristics.end(); it++) {
    if (it->value_handle > handle) break;
    char_node = &(*it);
  }

  char_node->descriptors.emplace_back(tBTA_GATTC_DESCRIPTOR{
      .handle = handle, .uuid = uuid, .characteristic = char_node,
  });
}

@@ -288,35 +274,6 @@ static void add_incl_srvc_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
  });
}

/*******************************************************************************
 *
 * Function         bta_gattc_get_disc_range
 *
 * Description      get discovery stating and ending handle range.
 *
 * Returns          None.
 *
 ******************************************************************************/
void bta_gattc_get_disc_range(tBTA_GATTC_SERV* p_srvc_cb, uint16_t* p_s_hdl,
                              uint16_t* p_e_hdl, bool is_srvc) {
  tBTA_GATTC_ATTR_REC* p_rec = NULL;

  if (is_srvc) {
    p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
    *p_s_hdl = p_rec->s_handle;
  } else {
    p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
    *p_s_hdl = p_rec->s_handle + 1;
  }

  *p_e_hdl = p_rec->e_handle;
#if (BTA_GATT_DEBUG == TRUE)
  VLOG(1) << StringPrintf("discover range [%d ~ %d]", p_rec->s_handle,
                          p_rec->e_handle);
#endif
  return;
}

/** Start primary service discovery */
tGATT_STATUS bta_gattc_discover_pri_service(uint16_t conn_id,
                                            tBTA_GATTC_SERV* p_server_cb,
@@ -324,83 +281,65 @@ tGATT_STATUS bta_gattc_discover_pri_service(uint16_t conn_id,
  tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
  if (!p_clcb) return GATT_ERROR;

  if (p_clcb->transport == BTA_TRANSPORT_LE)
    return bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);

  return bta_gattc_sdp_service_disc(conn_id, p_server_cb);
  if (p_clcb->transport == BTA_TRANSPORT_LE) {
    tGATT_DISC_PARAM param{.s_handle = 0x0001, .e_handle = 0xFFFF};
    return GATTC_Discover(conn_id, disc_type, &param);
  }

/*******************************************************************************
 *
 * Function         bta_gattc_discover_procedure
 *
 * Description      Start a particular type of discovery procedure on server.
 *
 * Returns          status of the operation.
 *
 ******************************************************************************/
tGATT_STATUS bta_gattc_discover_procedure(uint16_t conn_id,
                                          tBTA_GATTC_SERV* p_server_cb,
                                          uint8_t disc_type) {
  tGATT_DISC_PARAM param;
  bool is_service = true;

  memset(&param, 0, sizeof(tGATT_DISC_PARAM));

  if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID) {
    param.s_handle = 1;
    param.e_handle = 0xFFFF;
  } else {
    if (disc_type == GATT_DISC_CHAR_DSCPT) is_service = false;

    bta_gattc_get_disc_range(p_server_cb, &param.s_handle, &param.e_handle,
                             is_service);

    if (param.s_handle > param.e_handle) {
      return GATT_ERROR;
    }
  }
  return GATTC_Discover(conn_id, disc_type, &param);
  return bta_gattc_sdp_service_disc(conn_id, p_server_cb);
}

/** Start discovery for characteristic descriptor */
void bta_gattc_start_disc_char_dscp(uint16_t conn_id,
                                    tBTA_GATTC_SERV* p_srvc_cb) {
  VLOG(1) << "starting discover characteristics descriptor";
  auto& characteristic = p_srvc_cb->pending_char;

  uint16_t end_handle = 0xFFFF;
  // if there are more characteristics in the service
  if (std::next(p_srvc_cb->pending_char) !=
      p_srvc_cb->pending_service->characteristics.end()) {
    // end at beginning of next characteristic
    end_handle = std::next(p_srvc_cb->pending_char)->declaration_handle - 1;
  } else {
    // end at the end of current service
    end_handle = p_srvc_cb->pending_service->e_handle;
  }

  if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) !=
      0)
  tGATT_DISC_PARAM param{
      .s_handle = (uint16_t)(characteristic->value_handle + 1),
      .e_handle = end_handle};
  if (GATTC_Discover(conn_id, GATT_DISC_CHAR_DSCPT, &param) != 0) {
    bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
  }
}

/** process the service discovery complete event */
static void bta_gattc_explore_srvc(uint16_t conn_id,
                                   tBTA_GATTC_SERV* p_srvc_cb) {
  tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
  if (!p_clcb) {
    LOG(ERROR) << "unknown connection ID";
    LOG(ERROR) << "unknown conn_id=" << +conn_id;
    return;
  }

  /* start expore a service if there is service not been explored */
  if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc) {
    tBTA_GATTC_ATTR_REC* p_rec =
        p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
    VLOG(1) << "Start service discovery: srvc_idx:" << +p_srvc_cb->cur_srvc_idx;

    p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;

    /* add the first service into cache */
    add_service_to_gatt_db(p_srvc_cb->srvc_cache, p_rec->s_handle,
                           p_rec->e_handle, p_rec->uuid, p_rec->is_primary);
  if (p_srvc_cb->pending_service != p_srvc_cb->pending_discovery.end()) {
    auto& service = *p_srvc_cb->pending_service;
    VLOG(1) << "Start service discovery";

    /* start discovering included services */
    bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
    tGATT_DISC_PARAM param = {.s_handle = service.s_handle,
                              .e_handle = service.e_handle};
    GATTC_Discover(conn_id, GATT_DISC_INC_SRVC, &param);
    return;
  }

  /* no service found at all, the end of server discovery*/
  LOG_WARN(LOG_TAG, "%s no more services found", __func__);
  LOG(INFO) << __func__ << ": no more services found";

  p_srvc_cb->srvc_cache.swap(p_srvc_cb->pending_discovery);
  std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->pending_discovery);

#if (BTA_GATT_DEBUG == TRUE)
  bta_gattc_display_cache_server(p_srvc_cb->srvc_cache);
@@ -415,70 +354,26 @@ static void bta_gattc_explore_srvc(uint16_t conn_id,
  bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
}

/*******************************************************************************
 *
 * Function         bta_gattc_char_disc_cmpl
 *
 * Description      process the characteristic discovery complete event
 *
 * Returns          status
 *
 ******************************************************************************/
static void bta_gattc_char_disc_cmpl(uint16_t conn_id,
                                     tBTA_GATTC_SERV* p_srvc_cb) {
  tBTA_GATTC_ATTR_REC* p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;

  /* if there are characteristic needs to be explored */
  if (p_srvc_cb->total_char > 0) {
    /* add the first characteristic into cache */
    add_characteristic_to_gatt_db(p_srvc_cb->srvc_cache,
                                  p_rec->char_decl_handle, p_rec->s_handle,
                                  p_rec->uuid, p_rec->property);

    /* start discoverying characteristic descriptor , if failed, disc for next
     * char*/
    bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
  } else /* otherwise start with next service */
  {
    p_srvc_cb->cur_srvc_idx++;

    bta_gattc_explore_srvc(conn_id, p_srvc_cb);
  }
}
/*******************************************************************************
 *
 * Function         bta_gattc_char_dscpt_disc_cmpl
 *
 * Description      process the char descriptor discovery complete event
 *
 * Returns          status
 *
 ******************************************************************************/
/** process the char descriptor discovery complete event */
static void bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,
                                           tBTA_GATTC_SERV* p_srvc_cb) {
  tBTA_GATTC_ATTR_REC* p_rec = NULL;

  if (--p_srvc_cb->total_char > 0) {
    p_rec = p_srvc_cb->p_srvc_list + (++p_srvc_cb->cur_char_idx);
    /* add the next characteristic into cache */
    add_characteristic_to_gatt_db(p_srvc_cb->srvc_cache,
                                  p_rec->char_decl_handle, p_rec->s_handle,
                                  p_rec->uuid, p_rec->property);

  ++p_srvc_cb->pending_char;
  if (p_srvc_cb->pending_char !=
      p_srvc_cb->pending_service->characteristics.end()) {
    /* start discoverying next characteristic for char descriptor */
    bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
  } else
    return;
  }

  /* all characteristic has been explored, start with next service if any */
  {
#if (BTA_GATT_DEBUG == TRUE)
  LOG(ERROR) << "all char has been explored";
#endif
    p_srvc_cb->cur_srvc_idx++;
  p_srvc_cb->pending_service++;
  bta_gattc_explore_srvc(conn_id, p_srvc_cb);
}
}

static bool bta_gattc_srvc_in_list(tBTA_GATTC_SERV* p_srvc_cb,
static bool bta_gattc_srvc_in_list(std::vector<tBTA_GATTC_SERVICE>& services,
                                   uint16_t s_handle, uint16_t e_handle, Uuid) {
  if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle)) {
    LOG(ERROR) << "invalid included service s_handle=" << loghex(s_handle)
@@ -486,80 +381,14 @@ static bool bta_gattc_srvc_in_list(tBTA_GATTC_SERV* p_srvc_cb,
    return true;
  }

  for (uint8_t i = 0; i < p_srvc_cb->next_avail_idx; i++) {
    tBTA_GATTC_ATTR_REC* p_rec = p_srvc_cb->p_srvc_list + i;

    /* new service should not have any overlap with other service */
    if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle) {
  for (tBTA_GATTC_SERVICE& service : services) {
    if (service.s_handle == s_handle || service.e_handle == e_handle)
      return true;
  }
  }

  return false;
}

/** Add a service into explore pending list */
static void bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV* p_srvc_cb,
                                       uint16_t s_handle, uint16_t e_handle,
                                       const Uuid& uuid, bool is_primary) {
  if (!p_srvc_cb->p_srvc_list ||
      p_srvc_cb->next_avail_idx >= BTA_GATTC_MAX_CACHE_CHAR) {
    /* allocate bigger buffer ?? */
    LOG(ERROR) << "service not added, no resources or wrong state";
    return;
  }

  tBTA_GATTC_ATTR_REC* p_rec =
      p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;

  VLOG(1) << __func__ << "handle:" << loghex(s_handle)
          << " service type=" << uuid;

  p_rec->s_handle = s_handle;
  p_rec->e_handle = e_handle;
  p_rec->is_primary = is_primary;
  p_rec->uuid = uuid;

  p_srvc_cb->total_srvc++;
  p_srvc_cb->next_avail_idx++;
}

/** Add a characteristic into explore pending list */
static void bta_gattc_add_char_to_list(tBTA_GATTC_SERV* p_srvc_cb,
                                       uint16_t decl_handle,
                                       uint16_t value_handle, const Uuid& uuid,
                                       uint8_t property) {
  if (!p_srvc_cb->p_srvc_list) {
    LOG(ERROR) << "No service available, unexpected char discovery result";
    return;
  }

  if (p_srvc_cb->next_avail_idx >= BTA_GATTC_MAX_CACHE_CHAR) {
    LOG(ERROR) << "char not added, no resources";
    /* allocate bigger buffer ?? */
    return;
  }

  tBTA_GATTC_ATTR_REC* p_rec =
      p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;

  p_srvc_cb->total_char++;

  p_rec->s_handle = value_handle;
  p_rec->char_decl_handle = decl_handle;
  p_rec->property = property;
  p_rec->e_handle =
      (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
  p_rec->uuid = uuid;

  /* update the endind handle of pervious characteristic if available */
  if (p_srvc_cb->total_char > 1) {
    p_rec -= 1;
    p_rec->e_handle = decl_handle - 1;
  }
  p_srvc_cb->next_avail_idx++;
}

/*******************************************************************************
 *
 * Function         bta_gattc_sdp_callback
@@ -597,8 +426,8 @@ void bta_gattc_sdp_callback(uint16_t sdp_status, void* user_data) {
            if (GATT_HANDLE_IS_VALID(start_handle) &&
                GATT_HANDLE_IS_VALID(end_handle) && p_srvc_cb != NULL) {
              /* discover services result, add services into a service list */
              bta_gattc_add_srvc_to_list(p_srvc_cb, start_handle, end_handle,
                                         service_uuid, true);
              add_service_to_gatt_db(p_srvc_cb->pending_discovery, start_handle,
                                     end_handle, service_uuid, true);
            } else {
              LOG(ERROR) << "invalid start_handle=" << loghex(start_handle)
                         << ", end_handle=" << loghex(end_handle);
@@ -671,14 +500,9 @@ void bta_gattc_disc_res_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,

  switch (disc_type) {
    case GATT_DISC_SRVC_ALL:
      /* discover services result, add services into a service list */
      bta_gattc_add_srvc_to_list(p_srvc_cb, p_data->handle,
                                 p_data->value.group_value.e_handle,
                                 p_data->value.group_value.service_type, true);

      break;
    case GATT_DISC_SRVC_BY_UUID:
      bta_gattc_add_srvc_to_list(p_srvc_cb, p_data->handle,
      /* discover services result, add services into a service list */
      add_service_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
                             p_data->value.group_value.e_handle,
                             p_data->value.group_value.service_type, true);
      break;
@@ -686,32 +510,33 @@ void bta_gattc_disc_res_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
    case GATT_DISC_INC_SRVC:
      /* add included service into service list if it's secondary or it never
         showed up in the primary service search */
      if (!bta_gattc_srvc_in_list(p_srvc_cb,
      if (!bta_gattc_srvc_in_list(p_srvc_cb->pending_discovery,
                                  p_data->value.incl_service.s_handle,
                                  p_data->value.incl_service.e_handle,
                                  p_data->value.incl_service.service_type)) {
        bta_gattc_add_srvc_to_list(
            p_srvc_cb, p_data->value.incl_service.s_handle,
        add_service_to_gatt_db(p_srvc_cb->pending_discovery,
                               p_data->value.incl_service.s_handle,
                               p_data->value.incl_service.e_handle,
                               p_data->value.incl_service.service_type, false);
      }

      /* add into database */
      add_incl_srvc_to_gatt_db(p_srvc_cb->srvc_cache, p_data->handle,
      add_incl_srvc_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
                               p_data->value.incl_service.service_type,
                               p_data->value.incl_service.s_handle);
      break;

    case GATT_DISC_CHAR:
      /* add char value into database */
      bta_gattc_add_char_to_list(p_srvc_cb, p_data->handle,
      add_characteristic_to_gatt_db(p_srvc_cb->pending_discovery,
                                    p_data->handle,
                                    p_data->value.dclr_value.val_handle,
                                    p_data->value.dclr_value.char_uuid,
                                    p_data->value.dclr_value.char_prop);
      break;

    case GATT_DISC_CHAR_DSCPT:
      add_descriptor_to_gatt_db(p_srvc_cb->srvc_cache, p_data->handle,
      add_descriptor_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
                                p_data->type);
      break;
  }
@@ -733,27 +558,42 @@ void bta_gattc_disc_cmpl_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
  switch (disc_type) {
    case GATT_DISC_SRVC_ALL:
    case GATT_DISC_SRVC_BY_UUID:
// definition of all services are discovered, now it's time to discover
// their content
#if (BTA_GATT_DEBUG == TRUE)
      bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list,
                                       p_srvc_cb->next_avail_idx);
      bta_gattc_display_explore_record(p_srvc_cb->pending_discovery);
#endif
      p_srvc_cb->pending_service = p_srvc_cb->pending_discovery.begin();
      bta_gattc_explore_srvc(conn_id, p_srvc_cb);
      break;

    case GATT_DISC_INC_SRVC:
    case GATT_DISC_INC_SRVC: {
      auto& service = *p_srvc_cb->pending_service;

      /* start discoverying characteristic */
      p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
      p_srvc_cb->total_char = 0;
      bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);

      tGATT_DISC_PARAM param = {.s_handle = service.s_handle,
                                .e_handle = service.e_handle};
      GATTC_Discover(conn_id, GATT_DISC_CHAR, &param);
      break;
    }

    case GATT_DISC_CHAR:
    case GATT_DISC_CHAR: {
#if (BTA_GATT_DEBUG == TRUE)
      bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list,
                                       p_srvc_cb->next_avail_idx);
      bta_gattc_display_explore_record(p_srvc_cb->pending_discovery);
#endif
      bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
      auto& service = *p_srvc_cb->pending_service;
      if (!service.characteristics.empty()) {
        /* discover descriptors */
        p_srvc_cb->pending_char = service.characteristics.begin();
        bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
        return;
      }
      /* start next service */
      ++p_srvc_cb->pending_service;
      bta_gattc_explore_srvc(conn_id, p_srvc_cb);
      break;
    }

    case GATT_DISC_CHAR_DSCPT:
      bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
@@ -761,15 +601,7 @@ void bta_gattc_disc_cmpl_cback(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
  }
}

/*******************************************************************************
 *
 * Function         bta_gattc_search_service
 *
 * Description      search local cache for matching service record.
 *
 * Returns          false if map can not be found.
 *
 ******************************************************************************/
/** search local cache for matching service record */
void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb, Uuid* p_uuid) {
  for (const tBTA_GATTC_SERVICE& service : p_clcb->p_srcb->srvc_cache) {
    if (p_uuid && *p_uuid != service.uuid) continue;
@@ -1038,7 +870,7 @@ void bta_gattc_get_gatt_db(uint16_t conn_id, uint16_t start_handle,
  }

  if (!p_clcb->p_srcb ||
      p_clcb->p_srcb->p_srvc_list || /* no active discovery */
      !p_clcb->p_srcb->pending_discovery.empty() || /* no active discovery */
      p_clcb->p_srcb->srvc_cache.empty()) {
    LOG(ERROR) << "No server cache available";
    return;
@@ -1076,7 +908,6 @@ void bta_gattc_rebuild_cache(tBTA_GATTC_SERV* p_srvc_cb, uint16_t num_attr,
        break;

      case BTA_GATTC_ATTR_TYPE_CHAR:
        // TODO(jpawlowski): store decl_handle properly.
        add_characteristic_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
                                      p_attr->s_handle, p_attr->uuid,
                                      p_attr->prop);
+3 −29
Original line number Diff line number Diff line
@@ -185,26 +185,6 @@ typedef union {
  tBTA_GATTC_INT_CONN int_conn;
} tBTA_GATTC_DATA;

/* GATT server cache on the client */

typedef struct {
  bluetooth::Uuid uuid;
  uint16_t s_handle;
  uint16_t e_handle;
  // this field is set only for characteristic
  uint16_t char_decl_handle;
  bool is_primary;
  tGATT_CHAR_PROP property;
} tBTA_GATTC_ATTR_REC;

#define BTA_GATTC_MAX_CACHE_CHAR 40
#define BTA_GATTC_ATTR_LIST_SIZE \
  (BTA_GATTC_MAX_CACHE_CHAR * sizeof(tBTA_GATTC_ATTR_REC))

#ifndef BTA_GATTC_CACHE_SRVR_SIZE
#define BTA_GATTC_CACHE_SRVR_SIZE 600
#endif

enum {
  BTA_GATTC_IDLE_ST = 0, /* Idle  */
  BTA_GATTC_W4_CONN_ST,  /* Wait for connection -  (optional) */
@@ -230,12 +210,9 @@ typedef struct {
  uint8_t update_count; /* indication received */
  uint8_t num_clcb;     /* number of associated CLCB */

  tBTA_GATTC_ATTR_REC* p_srvc_list;
  uint8_t cur_srvc_idx;
  uint8_t cur_char_idx;
  uint8_t next_avail_idx;
  uint8_t total_srvc;
  uint8_t total_char;
  std::vector<tBTA_GATTC_SERVICE> pending_discovery;
  std::vector<tBTA_GATTC_SERVICE>::iterator pending_service;
  std::vector<tBTA_GATTC_CHARACTERISTIC>::iterator pending_char;

  uint8_t srvc_hdl_chg; /* service handle change indication pending */
  uint16_t attr_index;  /* cahce NV saving/loading attribute index */
@@ -445,9 +422,6 @@ extern void bta_gattc_disc_res_cback(uint16_t conn_id,
extern void bta_gattc_disc_cmpl_cback(uint16_t conn_id,
                                      tGATT_DISC_TYPE disc_type,
                                      tGATT_STATUS status);
extern tGATT_STATUS bta_gattc_discover_procedure(uint16_t conn_id,
                                                 tBTA_GATTC_SERV* p_server_cb,
                                                 uint8_t disc_type);
extern tGATT_STATUS bta_gattc_discover_pri_service(uint16_t conn_id,
                                                   tBTA_GATTC_SERV* p_server_cb,
                                                   uint8_t disc_type);
+2 −3
Original line number Diff line number Diff line
@@ -129,7 +129,7 @@ tBTA_GATTC_CLCB* bta_gattc_clcb_alloc(tGATT_IF client_if,
  for (i_clcb = 0; i_clcb < BTA_GATTC_CLCB_MAX; i_clcb++) {
    if (!bta_gattc_cb.clcb[i_clcb].in_use) {
#if (BTA_GATT_DEBUG == TRUE)
      VLOG(1) << __func__ << ": found clcb:" << +i_clcb << " available", ;
      VLOG(1) << __func__ << ": found clcb:" << +i_clcb << " available";
#endif
      p_clcb = &bta_gattc_cb.clcb[i_clcb];
      p_clcb->in_use = true;
@@ -297,8 +297,7 @@ tBTA_GATTC_SERV* bta_gattc_srcb_alloc(const RawAddress& bda) {
  if (p_tcb != NULL) {
    // clear reallocating
    std::vector<tBTA_GATTC_SERVICE>().swap(p_tcb->srvc_cache);

    osi_free_and_reset((void**)&p_tcb->p_srvc_list);
    std::vector<tBTA_GATTC_SERVICE>().swap(p_tcb->pending_discovery);
    *p_tcb = tBTA_GATTC_SERV();

    p_tcb->in_use = true;
+2 −0
Original line number Diff line number Diff line
@@ -390,6 +390,8 @@ typedef struct {

struct tBTA_GATTC_CHARACTERISTIC {
  bluetooth::Uuid uuid;
  // this is used only during discovery, and not persisted in cache
  uint16_t declaration_handle;
  uint16_t value_handle;
  tGATT_CHAR_PROP properties;
  tBTA_GATTC_SERVICE* service; /* owning service*/