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

Commit 347b6c93 authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Jakub Pawłowski
Browse files

Wait for remote version information, before deciding Robust Cache support

Currently, GATT service discovery is scheduled immediately after
connection to new LE device.

Depending on timing of Link Layer, we might not read remote version
information before checking for Robust Caching support. In this case, we
would assume device doesn't support it.

After this patch, we would wait for "remote version information" command
to finish, and go back to schedulsed service discovery. This way, we
would alawys use Robust Cache when newly connected device supports it.

Test: Bond with a set of devices, where both of them have same GATT
    database hash. Verify service discovery is triggered only once in snoop
    log.
Bug: 293249869
Change-Id: Id87ce6f8aa4a4f23a33d963dbbc28ef0891a6d75
parent 318a22f8
Loading
Loading
Loading
Loading
+68 −16
Original line number Diff line number Diff line
@@ -808,6 +808,10 @@ void bta_gattc_start_discover_internal(tBTA_GATTC_CLCB* p_clcb) {
    p_clcb->disc_active = true;
}

static void bta_gattc_continue_with_version_and_cache_known(
    tBTA_GATTC_CLCB* p_clcb, RobustCachingSupport cache_support,
    bool is_svc_chg);

/** Start a discovery on server */
void bta_gattc_start_discover(tBTA_GATTC_CLCB* p_clcb,
                              UNUSED_ATTR const tBTA_GATTC_DATA* p_data) {
@@ -839,9 +843,65 @@ void bta_gattc_start_discover(tBTA_GATTC_CLCB* p_clcb,
    p_clcb->p_srcb->srvc_hdl_chg = false;
    p_clcb->p_srcb->update_count = 0;
    p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC_ACT;
    p_clcb->p_srcb->disc_blocked_waiting_on_version = false;

    auto cache_support =
        GetRobustCachingSupport(p_clcb, p_clcb->p_srcb->gatt_database);
    if (cache_support == RobustCachingSupport::W4_REMOTE_VERSION) {
      LOG_INFO(
          "Pausing service discovery till remote version is read conn_id:%d",
          p_clcb->bta_conn_id);
      p_clcb->p_srcb->disc_blocked_waiting_on_version = true;
      p_clcb->p_srcb->blocked_conn_id = p_clcb->bta_conn_id;
      return;
    }

    bta_gattc_continue_with_version_and_cache_known(p_clcb, cache_support,
                                                    is_svc_chg);
  }
  /* pending operation, wait until it finishes */
  else {
    p_clcb->auto_update = BTA_GATTC_DISC_WAITING;

    if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
      p_clcb->state = BTA_GATTC_CONN_ST; /* set clcb state */
  }
}

void bta_gattc_continue_discovery_if_needed(const RawAddress& bd_addr,
                                            uint16_t acl_handle) {
  tBTA_GATTC_SERV* p_srcb = bta_gattc_find_srvr_cache(bd_addr);
  if (!p_srcb || !p_srcb->disc_blocked_waiting_on_version) {
    return;
  }

  uint16_t conn_id = p_srcb->blocked_conn_id;

  p_srcb->disc_blocked_waiting_on_version = false;
  p_srcb->blocked_conn_id = 0;

  LOG_INFO("Received remote version, continue service discovery for %s",
           ADDRESS_TO_LOGGABLE_CSTR(bd_addr));

    if (GetRobustCachingSupport(p_clcb, p_clcb->p_srcb->gatt_database) ==
        RobustCachingSupport::UNSUPPORTED) {
  tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);

  if (!p_clcb) {
    LOG_ERROR("Can't find CLCB to continue service discovery, id:%d", conn_id);
    return;
  }

  bool is_svc_chg = p_clcb->p_srcb->srvc_hdl_chg;

  auto cache_support =
      GetRobustCachingSupport(p_clcb, p_clcb->p_srcb->gatt_database);
  bta_gattc_continue_with_version_and_cache_known(p_clcb, cache_support,
                                                  is_svc_chg);
}

void bta_gattc_continue_with_version_and_cache_known(
    tBTA_GATTC_CLCB* p_clcb, RobustCachingSupport cache_support,
    bool is_svc_chg) {
  if (cache_support == RobustCachingSupport::UNSUPPORTED) {
    // Skip initial DB hash read if we have strong reason (due to interop,
    // or a prior discovery) to believe that it is unsupported.
    p_clcb->p_srcb->srvc_hdl_db_hash = false;
@@ -852,21 +912,13 @@ void bta_gattc_start_discover(tBTA_GATTC_CLCB* p_clcb,
      p_clcb->p_srcb->srvc_hdl_db_hash &&
      bta_gattc_read_db_hash(p_clcb, is_svc_chg)) {
    LOG(INFO) << __func__
                << ": pending service discovery, read db hash first";
              << ": pending service discovery, read db hash first conn_id:"
              << loghex(p_clcb->bta_conn_id);
    p_clcb->p_srcb->srvc_hdl_db_hash = false;
    return;
  }

  bta_gattc_start_discover_internal(p_clcb);
}
  /* pending operation, wait until it finishes */
  else {
    p_clcb->auto_update = BTA_GATTC_DISC_WAITING;

    if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
      p_clcb->state = BTA_GATTC_CONN_ST; /* set clcb state */
  }
}

/** discovery on server is finished */
void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB* p_clcb,
+6 −0
Original line number Diff line number Diff line
@@ -164,6 +164,12 @@ RobustCachingSupport GetRobustCachingSupport(const tBTA_GATTC_CLCB* p_clcb,
    return RobustCachingSupport::UNSUPPORTED;
  }

  if (p_clcb->transport == BT_TRANSPORT_LE &&
      !BTM_IsRemoteVersionReceived(p_clcb->bda)) {
    LOG_INFO("version info is not ready yet");
    return RobustCachingSupport::W4_REMOTE_VERSION;
  }

  // This is workaround for the embedded devices being already on the market
  // and having a serious problem with handle Read By Type with
  // GATT_UUID_DATABASE_HASH. With this workaround, Android will assume that
+4 −0
Original line number Diff line number Diff line
@@ -232,6 +232,9 @@ typedef struct {
  uint16_t attr_index;  /* cahce NV saving/loading attribute index */

  uint16_t mtu;

  bool disc_blocked_waiting_on_version;
  uint16_t blocked_conn_id;
} tBTA_GATTC_SERV;

#ifndef BTA_GATTC_NOTIF_REG_MAX
@@ -480,6 +483,7 @@ enum class RobustCachingSupport {
  UNSUPPORTED,
  SUPPORTED,
  UNKNOWN,
  W4_REMOTE_VERSION
};
RobustCachingSupport GetRobustCachingSupport(const tBTA_GATTC_CLCB* p_clcb,
                                             const gatt::Database& db);
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include "types/raw_address.h"

void tACL_CONN::Reset() {
  remote_version_received = false;
  memset(peer_le_features, 0, sizeof(peer_le_features));
  peer_le_features_valid = false;
  memset(peer_lmp_feature_pages, 0, sizeof(peer_lmp_feature_pages));
+3 −0
Original line number Diff line number Diff line
@@ -180,6 +180,9 @@ struct tACL_CONN {
  BD_FEATURES peer_lmp_feature_pages[HCI_EXT_FEATURES_PAGE_MAX + 1];
  bool peer_lmp_feature_valid[HCI_EXT_FEATURES_PAGE_MAX + 1];

  /* Whether "Read Remote Version Information Complete" was received */
  bool remote_version_received{false};

  RawAddress active_remote_addr;
  tBLE_ADDR_TYPE active_remote_addr_type;

Loading