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

Commit eda4a0d2 authored by Jakub Pawłowski's avatar Jakub Pawłowski Committed by Automerger Merge Worker
Browse files

Merge changes I0a7655b3,I60d0b82b am: c159afca

parents 653a07fc c159afca
Loading
Loading
Loading
Loading
+18 −2
Original line number Original line Diff line number Diff line
@@ -501,13 +501,23 @@ void bta_gattc_conn(tBTA_GATTC_CLCB* p_clcb, const tBTA_GATTC_DATA* p_data) {
      p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE) {
      p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE) {
    if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) {
    if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) {
      p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD;
      p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD;
      // Consider the case that if GATT Server is changed, but no service
      // changed indication is received, the database might be out of date. So
      // if robust caching is enabled, any time when connection is established,
      // always check the db hash first, not just load the stored database.
      gatt::Database db = bta_gattc_cache_load(p_clcb->p_srcb->server_bda);
      gatt::Database db = bta_gattc_cache_load(p_clcb->p_srcb->server_bda);
      if (!db.IsEmpty()) {
      if (!bta_gattc_is_robust_caching_enabled() && !db.IsEmpty()) {
        p_clcb->p_srcb->gatt_database = db;
        p_clcb->p_srcb->gatt_database = db;
        p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
        p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
        bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
        bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
      } else {
      } else {
        p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
        p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;

        /* set true to read database hash before service discovery */
        if (bta_gattc_is_robust_caching_enabled()) {
          p_clcb->p_srcb->srvc_hdl_db_hash = true;
        }

        /* cache load failure, start discovery */
        /* cache load failure, start discovery */
        bta_gattc_start_discover(p_clcb, NULL);
        bta_gattc_start_discover(p_clcb, NULL);
      }
      }
@@ -707,6 +717,11 @@ void bta_gattc_start_discover(tBTA_GATTC_CLCB* p_clcb,
      /* set all srcb related clcb into discovery ST */
      /* set all srcb related clcb into discovery ST */
      bta_gattc_set_discover_st(p_clcb->p_srcb);
      bta_gattc_set_discover_st(p_clcb->p_srcb);


      // Before clear mask, set is_svc_chg to
      // 1. true, invoked by service changed indication
      // 2. false, invoked by connect API
      bool is_svc_chg = p_clcb->p_srcb->srvc_hdl_chg;

      /* clear the service change mask */
      /* clear the service change mask */
      p_clcb->p_srcb->srvc_hdl_chg = false;
      p_clcb->p_srcb->srvc_hdl_chg = false;
      p_clcb->p_srcb->update_count = 0;
      p_clcb->p_srcb->update_count = 0;
@@ -714,7 +729,8 @@ void bta_gattc_start_discover(tBTA_GATTC_CLCB* p_clcb,


      /* read db hash if db hash characteristic exists */
      /* read db hash if db hash characteristic exists */
      if (bta_gattc_is_robust_caching_enabled() &&
      if (bta_gattc_is_robust_caching_enabled() &&
          p_clcb->p_srcb->srvc_hdl_db_hash && bta_gattc_read_db_hash(p_clcb)) {
          p_clcb->p_srcb->srvc_hdl_db_hash &&
          bta_gattc_read_db_hash(p_clcb, is_svc_chg)) {
        LOG(INFO) << __func__
        LOG(INFO) << __func__
                  << ": pending service discovery, read db hash first";
                  << ": pending service discovery, read db hash first";
        p_clcb->p_srcb->srvc_hdl_db_hash = false;
        p_clcb->p_srcb->srvc_hdl_db_hash = false;
+85 −21
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@
#define LOG_TAG "bt_bta_gattc"
#define LOG_TAG "bt_bta_gattc"


#include <base/logging.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>
#include <base/strings/stringprintf.h>


#include <cstdint>
#include <cstdint>
@@ -61,7 +62,8 @@ static void bta_gattc_explore_srvc_finished(uint16_t conn_id,
                                            tBTA_GATTC_SERV* p_srvc_cb);
                                            tBTA_GATTC_SERV* p_srvc_cb);


static void bta_gattc_read_db_hash_cmpl(tBTA_GATTC_CLCB* p_clcb,
static void bta_gattc_read_db_hash_cmpl(tBTA_GATTC_CLCB* p_clcb,
                                        const tBTA_GATTC_OP_CMPL* p_data);
                                        const tBTA_GATTC_OP_CMPL* p_data,
                                        bool is_svc_chg);


static void bta_gattc_read_ext_prop_desc_cmpl(tBTA_GATTC_CLCB* p_clcb,
static void bta_gattc_read_ext_prop_desc_cmpl(tBTA_GATTC_CLCB* p_clcb,
                                              const tBTA_GATTC_OP_CMPL* p_data);
                                              const tBTA_GATTC_OP_CMPL* p_data);
@@ -216,16 +218,25 @@ static void bta_gattc_explore_srvc_finished(uint16_t conn_id,
  /* save cache to NV */
  /* save cache to NV */
  p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
  p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;


  // If robust caching is not enabled, use original design
  if (!bta_gattc_is_robust_caching_enabled()) {
    if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) {
    if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) {
      bta_gattc_cache_write(p_clcb->p_srcb->server_bda,
      bta_gattc_cache_write(p_clcb->p_srcb->server_bda,
                            p_clcb->p_srcb->gatt_database);
                            p_clcb->p_srcb->gatt_database);
    }
    }
  } else {
    // If robust caching is enabled, do something optimized
    Octet16 hash = p_clcb->p_srcb->gatt_database.Hash();
    bool success = bta_gattc_hash_write(hash, p_clcb->p_srcb->gatt_database);

    // If the device is trusted, link the addr file to hash file
    if (success && btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) {
      bta_gattc_cache_link(p_clcb->p_srcb->server_bda, hash);
    }


    // After success, reset the count.
    // After success, reset the count.
  if (bta_gattc_is_robust_caching_enabled()) {
    LOG_DEBUG("service discovery succeed, reset count to zero, conn_id=0x%04x",
    LOG(INFO) << __func__
              conn_id);
              << ": service discovery succeed, reset count to zero, conn_id="
              << loghex(conn_id);
    p_srvc_cb->srvc_disc_count = 0;
    p_srvc_cb->srvc_disc_count = 0;
  }
  }


@@ -366,8 +377,11 @@ void bta_gattc_op_cmpl_during_discovery(tBTA_GATTC_CLCB* p_clcb,
      bta_gattc_read_ext_prop_desc_cmpl(p_clcb, &p_data->op_cmpl);
      bta_gattc_read_ext_prop_desc_cmpl(p_clcb, &p_data->op_cmpl);
      break;
      break;
    case BTA_GATTC_DISCOVER_REQ_READ_DB_HASH:
    case BTA_GATTC_DISCOVER_REQ_READ_DB_HASH:
    case BTA_GATTC_DISCOVER_REQ_READ_DB_HASH_FOR_SVC_CHG:
      if (bta_gattc_is_robust_caching_enabled()) {
      if (bta_gattc_is_robust_caching_enabled()) {
        bta_gattc_read_db_hash_cmpl(p_clcb, &p_data->op_cmpl);
        bool is_svc_chg = (p_clcb->request_during_discovery ==
                           BTA_GATTC_DISCOVER_REQ_READ_DB_HASH_FOR_SVC_CHG);
        bta_gattc_read_db_hash_cmpl(p_clcb, &p_data->op_cmpl, is_svc_chg);
      } else {
      } else {
        // it is not possible here if flag is off, but just in case
        // it is not possible here if flag is off, but just in case
        p_clcb->request_during_discovery = BTA_GATTC_DISCOVER_REQ_NONE;
        p_clcb->request_during_discovery = BTA_GATTC_DISCOVER_REQ_NONE;
@@ -614,7 +628,7 @@ const Characteristic* bta_gattc_get_owning_characteristic(uint16_t conn_id,
}
}


/* request reading database hash */
/* request reading database hash */
bool bta_gattc_read_db_hash(tBTA_GATTC_CLCB* p_clcb) {
bool bta_gattc_read_db_hash(tBTA_GATTC_CLCB* p_clcb, bool is_svc_chg) {
  tGATT_READ_PARAM read_param;
  tGATT_READ_PARAM read_param;
  memset(&read_param, 0, sizeof(tGATT_READ_BY_TYPE));
  memset(&read_param, 0, sizeof(tGATT_READ_BY_TYPE));


@@ -626,14 +640,21 @@ bool bta_gattc_read_db_hash(tBTA_GATTC_CLCB* p_clcb) {
      GATTC_Read(p_clcb->bta_conn_id, GATT_READ_BY_TYPE, &read_param);
      GATTC_Read(p_clcb->bta_conn_id, GATT_READ_BY_TYPE, &read_param);


  if (status != GATT_SUCCESS) return false;
  if (status != GATT_SUCCESS) return false;

  if (is_svc_chg) {
    p_clcb->request_during_discovery =
        BTA_GATTC_DISCOVER_REQ_READ_DB_HASH_FOR_SVC_CHG;
  } else {
    p_clcb->request_during_discovery = BTA_GATTC_DISCOVER_REQ_READ_DB_HASH;
    p_clcb->request_during_discovery = BTA_GATTC_DISCOVER_REQ_READ_DB_HASH;
  }


  return true;
  return true;
}
}


/* handle response of reading database hash */
/* handle response of reading database hash */
static void bta_gattc_read_db_hash_cmpl(tBTA_GATTC_CLCB* p_clcb,
static void bta_gattc_read_db_hash_cmpl(tBTA_GATTC_CLCB* p_clcb,
                                        const tBTA_GATTC_OP_CMPL* p_data) {
                                        const tBTA_GATTC_OP_CMPL* p_data,
                                        bool is_svc_chg) {
  uint8_t op = (uint8_t)p_data->op_code;
  uint8_t op = (uint8_t)p_data->op_code;
  if (op != GATTC_OPTYPE_READ) {
  if (op != GATTC_OPTYPE_READ) {
    VLOG(1) << __func__ << ": op = " << +p_data->hdr.layer_specific;
    VLOG(1) << __func__ << ": op = " << +p_data->hdr.layer_specific;
@@ -643,31 +664,74 @@ static void bta_gattc_read_db_hash_cmpl(tBTA_GATTC_CLCB* p_clcb,


  // run match flow only if the status is success
  // run match flow only if the status is success
  bool matched = false;
  bool matched = false;
  bool found = false;
  if (p_data->status == GATT_SUCCESS) {
  if (p_data->status == GATT_SUCCESS) {
    // start to compare local hash and remote hash
    // start to compare local hash and remote hash
    uint16_t len = p_data->p_cmpl->att_value.len;
    uint16_t len = p_data->p_cmpl->att_value.len;
    uint8_t* data = p_data->p_cmpl->att_value.value;
    uint8_t* data = p_data->p_cmpl->att_value.value;


    Octet16 remote_hash;
    Octet16 remote_hash;
    if (len == remote_hash.size()) {
    if (len == remote_hash.max_size()) {
      uint8_t idx = 0;
      std::copy(data, data + len, remote_hash.begin());
      auto it = remote_hash.begin();
      for (; idx < len; idx++, data++, it++) *it = *data;


      Octet16 local_hash = p_clcb->p_srcb->gatt_database.Hash();
      Octet16 local_hash = p_clcb->p_srcb->gatt_database.Hash();
      matched = (local_hash == remote_hash);
      matched = (local_hash == remote_hash);

      LOG_DEBUG("lhash=%s",
                base::HexEncode(local_hash.data(), local_hash.size()).c_str());
      LOG_DEBUG(
          "rhash=%s",
          base::HexEncode(remote_hash.data(), remote_hash.size()).c_str());

      if (!matched) {
        gatt::Database db = bta_gattc_hash_load(remote_hash);
        if (!db.IsEmpty()) {
          p_clcb->p_srcb->gatt_database = db;
          found = true;
        }
        // If the device is trusted, link addr file to correct hash file
        if (found && (btm_sec_is_a_bonded_dev(p_clcb->p_srcb->server_bda))) {
          bta_gattc_cache_link(p_clcb->p_srcb->server_bda, remote_hash);
        }
      }
    }
  } else {
    // Only load cache for trusted device if no database hash on server side.
    // If is_svc_chg is true, do not read the existing cache.
    bool is_a_bonded_dev = btm_sec_is_a_bonded_dev(p_clcb->p_srcb->server_bda);
    if (!is_svc_chg && is_a_bonded_dev) {
      gatt::Database db = bta_gattc_cache_load(p_clcb->p_srcb->server_bda);
      if (!db.IsEmpty()) {
        p_clcb->p_srcb->gatt_database = db;
        found = true;
      }
      LOG_DEBUG("load cache directly, result=%d", found);
    } else {
      LOG_DEBUG("skip read cache, is_svc_chg=%d, is_a_bonded_dev=%d",
                is_svc_chg, is_a_bonded_dev);
    }
    }
  }
  }


  if (matched) {
  if (matched) {
    LOG(INFO) << __func__ << ": hash is the same, skip service discovery";
    LOG_DEBUG("hash is the same, skip service discovery");
    p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
    bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
  } else {
    if (found) {
      LOG_DEBUG("hash found in cache, skip service discovery");

#if (BTA_GATT_DEBUG == TRUE)
      bta_gattc_display_cache_server(p_clcb->p_srcb->gatt_database);
#endif

      p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
      p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
      bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
      bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
    } else {
    } else {
    LOG(INFO) << __func__ << ": hash is not the same, start service discovery";
      LOG_DEBUG("hash is not the same, start service discovery");
      bta_gattc_start_discover_internal(p_clcb);
      bta_gattc_start_discover_internal(p_clcb);
    }
    }
  }
  }
}


/* handle response of reading extended properties descriptor */
/* handle response of reading extended properties descriptor */
static void bta_gattc_read_ext_prop_desc_cmpl(
static void bta_gattc_read_ext_prop_desc_cmpl(
+189 −3
Original line number Original line Diff line number Diff line
@@ -16,16 +16,36 @@
 *
 *
 ******************************************************************************/
 ******************************************************************************/


#define LOG_TAG "bt_bta_gattc"

#include <base/logging.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <dirent.h>
#include <sys/stat.h>

#include <string>
#include <vector>


#include "bta/gatt/bta_gattc_int.h"
#include "bta/gatt/bta_gattc_int.h"
#include "osi/include/log.h"
#include "osi/include/log.h"


using gatt::StoredAttribute;
using gatt::StoredAttribute;
using std::string;
using std::vector;


#define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_"
#define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_"
#define GATT_CACHE_VERSION 6
#define GATT_CACHE_VERSION 6


#define GATT_HASH_MAX_SIZE 30
#define GATT_HASH_PATH_PREFIX "/data/misc/bluetooth/gatt_hash_"
#define GATT_HASH_PATH "/data/misc/bluetooth"
#define GATT_HASH_FILE_PREFIX "gatt_hash_"

// Default expired time is 7 days
#define GATT_HASH_EXPIRED_TIME 604800

static void bta_gattc_hash_remove_least_recently_used_if_possible();

static void bta_gattc_generate_cache_file_name(char* buffer, size_t buffer_len,
static void bta_gattc_generate_cache_file_name(char* buffer, size_t buffer_len,
                                               const RawAddress& bda) {
                                               const RawAddress& bda) {
  snprintf(buffer, buffer_len, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX,
  snprintf(buffer, buffer_len, "%s%02x%02x%02x%02x%02x%02x", GATT_CACHE_PREFIX,
@@ -33,6 +53,12 @@ static void bta_gattc_generate_cache_file_name(char* buffer, size_t buffer_len,
           bda.address[4], bda.address[5]);
           bda.address[4], bda.address[5]);
}
}


static void bta_gattc_generate_hash_file_name(char* buffer, size_t buffer_len,
                                              const Octet16& hash) {
  snprintf(buffer, buffer_len, "%s%s", GATT_HASH_PATH_PREFIX,
           base::HexEncode(hash.data(), 16).c_str());
}

static gatt::Database EMPTY_DB;
static gatt::Database EMPTY_DB;


/*******************************************************************************
/*******************************************************************************
@@ -111,6 +137,24 @@ gatt::Database bta_gattc_cache_load(const RawAddress& server_bda) {
  return bta_gattc_load_db(fname);
  return bta_gattc_load_db(fname);
}
}


/*******************************************************************************
 *
 * Function         bta_gattc_hash_load
 *
 * Description      Load GATT cache from storage for server.
 *
 * Parameter        hash: 16-byte value
 *
 * Returns          non-empty GATT database on success, empty GATT database
 *                  otherwise
 *
 ******************************************************************************/
gatt::Database bta_gattc_hash_load(const Octet16& hash) {
  char fname[255] = {0};
  bta_gattc_generate_hash_file_name(fname, sizeof(fname), hash);
  return bta_gattc_load_db(fname);
}

/*******************************************************************************
/*******************************************************************************
 *
 *
 * Function         bta_gattc_store_db
 * Function         bta_gattc_store_db
@@ -162,7 +206,9 @@ static bool bta_gattc_store_db(const char* fname,
 * Function         bta_gattc_cache_write
 * Function         bta_gattc_cache_write
 *
 *
 * Description      This callout function is executed by GATT when a server
 * Description      This callout function is executed by GATT when a server
 *                  cache is available to save.
 *                  cache is available to save. Before calling this API, make
 *                  sure the device is bonded. Otherwise you might get lots of
 *                  address caches for unbonded devices.
 *
 *
 * Parameter        server_bda: server bd address of this cache belongs to
 * Parameter        server_bda: server bd address of this cache belongs to
 *                  database: attributes to save.
 *                  database: attributes to save.
@@ -171,9 +217,61 @@ static bool bta_gattc_store_db(const char* fname,
 ******************************************************************************/
 ******************************************************************************/
void bta_gattc_cache_write(const RawAddress& server_bda,
void bta_gattc_cache_write(const RawAddress& server_bda,
                           const gatt::Database& database) {
                           const gatt::Database& database) {
  char addr_file[255] = {0};
  char hash_file[255] = {0};
  Octet16 hash = database.Hash();
  bta_gattc_generate_cache_file_name(addr_file, sizeof(addr_file), server_bda);
  bta_gattc_generate_hash_file_name(hash_file, sizeof(hash_file), hash);

  bool result = bta_gattc_hash_write(hash, database);
  // Only link addr_file to hash file when hash_file is created successfully.
  if (result) {
    bta_gattc_cache_link(server_bda, hash);
  }
}

/*******************************************************************************
 *
 * Function         bta_gattc_cache_link
 *
 * Description      Link address-database file to hash-database file
 *
 * Parameter        server_bda: server bd address of this cache belongs to
 *                  hash: 16-byte value
 *
 * Returns          true on success, false otherwise
 *
 ******************************************************************************/
void bta_gattc_cache_link(const RawAddress& server_bda, const Octet16& hash) {
  char addr_file[255] = {0};
  char hash_file[255] = {0};
  bta_gattc_generate_cache_file_name(addr_file, sizeof(addr_file), server_bda);
  bta_gattc_generate_hash_file_name(hash_file, sizeof(hash_file), hash);

  unlink(addr_file);  // remove addr file first if the file exists
  if (link(hash_file, addr_file) == -1) {
    LOG_ERROR("link %s to %s, errno=%d", addr_file, hash_file, errno);
  }
}

/*******************************************************************************
 *
 * Function         bta_gattc_hash_write
 *
 * Description      This callout function is executed by GATT when a server
 *                  cache is available to save for specific hash.
 *
 * Parameter        hash: 16-byte value
 *                  database: gatt::Database instance.
 *
 * Returns          true on success, false otherwise
 *
 ******************************************************************************/
bool bta_gattc_hash_write(const Octet16& hash, const gatt::Database& database) {
  char fname[255] = {0};
  char fname[255] = {0};
  bta_gattc_generate_cache_file_name(fname, sizeof(fname), server_bda);
  bta_gattc_generate_hash_file_name(fname, sizeof(fname), hash);
  bta_gattc_store_db(fname, database.Serialize());
  bta_gattc_hash_remove_least_recently_used_if_possible();
  return bta_gattc_store_db(fname, database.Serialize());
}
}


/*******************************************************************************
/*******************************************************************************
@@ -194,3 +292,91 @@ void bta_gattc_cache_reset(const RawAddress& server_bda) {
  bta_gattc_generate_cache_file_name(fname, sizeof(fname), server_bda);
  bta_gattc_generate_cache_file_name(fname, sizeof(fname), server_bda);
  unlink(fname);
  unlink(fname);
}
}

/*******************************************************************************
 *
 * Function         bta_gattc_hash_remove_least_recently_used_if_possible
 *
 * Description      When the max size reaches, find the oldest item and remove
 *                  it if possible
 *
 * Parameter
 *
 * Returns          void
 *
 ******************************************************************************/
static void bta_gattc_hash_remove_least_recently_used_if_possible() {
  std::unique_ptr<DIR, decltype(&closedir)> dirp(opendir(GATT_HASH_PATH),
                                                 &closedir);
  if (dirp == nullptr) {
    LOG_ERROR("open dir error, dir=%s", GATT_HASH_PATH);
    return;
  }

  time_t current_time = time(NULL);
  time_t lru_time = current_time;
  size_t count = 0;
  string candidate_item;
  vector<string> expired_items;

  LOG_DEBUG("<-----------Start Local Hash Cache---------->");
  dirent* dp;
  while ((dp = readdir(dirp.get())) != nullptr) {
    if (strncmp(".", dp->d_name, 1) == 0 || strncmp("..", dp->d_name, 2) == 0) {
      continue;
    }

    // pattern match: gatt_hash_
    size_t fname_len = strlen(dp->d_name);
    size_t pattern_len = strlen(GATT_HASH_FILE_PREFIX);
    if (pattern_len > fname_len) {
      continue;
    }

    // check if the file name has gatt_hash_ as prefix
    char tmp[255] = {0};
    strncpy(tmp, dp->d_name, pattern_len);
    if (strncmp(tmp, GATT_HASH_FILE_PREFIX, pattern_len) != 0) {
      continue;
    }

    // increase hash file count
    count++;

    // generate the full path, in order to get the state of the file
    snprintf(tmp, 255, "%s/%s", GATT_HASH_PATH, dp->d_name);

    struct stat buf;
    int result = lstat(tmp, &buf);
    LOG_DEBUG("name=%s, result=%d, linknum=%lu, mtime=%lu", dp->d_name, result,
              (unsigned long)buf.st_nlink, (unsigned long)buf.st_mtime);

    // if hard link count of the file is 1, it means no trusted device links to
    // the inode. It is safe to be a candidate to be removed
    if (buf.st_nlink == 1) {
      if (buf.st_mtime < lru_time) {
        lru_time = buf.st_mtime;
        // Find the LRU candidate during for-loop itreation.
        candidate_item.assign(tmp);
      }

      if (buf.st_mtime + GATT_HASH_EXPIRED_TIME < current_time) {
        // Add expired item.
        expired_items.emplace_back(tmp);
      }
    }
  }
  LOG_DEBUG("<-----------End Local Hash Cache------------>");

  // if the number of hash files exceeds the limit, remove the cadidate item.
  if (count > GATT_HASH_MAX_SIZE && !candidate_item.empty()) {
    unlink(candidate_item.c_str());
    LOG_DEBUG("delete hash file (size), name=%s", candidate_item.c_str());
  }

  // If there is any file expired, also delete it.
  for (string expired_item : expired_items) {
    unlink(expired_item.c_str());
    LOG_DEBUG("delete hash file (expired), name=%s", expired_item.c_str());
  }
}
+10 −2
Original line number Original line Diff line number Diff line
@@ -258,6 +258,7 @@ typedef struct {
#define BTA_GATTC_DISCOVER_REQ_NONE 0
#define BTA_GATTC_DISCOVER_REQ_NONE 0
#define BTA_GATTC_DISCOVER_REQ_READ_EXT_PROP_DESC 1
#define BTA_GATTC_DISCOVER_REQ_READ_EXT_PROP_DESC 1
#define BTA_GATTC_DISCOVER_REQ_READ_DB_HASH 2
#define BTA_GATTC_DISCOVER_REQ_READ_DB_HASH 2
#define BTA_GATTC_DISCOVER_REQ_READ_DB_HASH_FOR_SVC_CHG 3


  uint8_t request_during_discovery; /* request during discover state */
  uint8_t request_during_discovery; /* request during discover state */


@@ -476,11 +477,18 @@ extern tBTA_GATTC_CONN* bta_gattc_conn_find(const RawAddress& remote_bda);
extern tBTA_GATTC_CONN* bta_gattc_conn_find_alloc(const RawAddress& remote_bda);
extern tBTA_GATTC_CONN* bta_gattc_conn_find_alloc(const RawAddress& remote_bda);
extern bool bta_gattc_conn_dealloc(const RawAddress& remote_bda);
extern bool bta_gattc_conn_dealloc(const RawAddress& remote_bda);


/* bta_gattc_cache */
extern bool bta_gattc_read_db_hash(tBTA_GATTC_CLCB* p_clcb, bool is_svc_chg);

/* bta_gattc_db_storage */
extern gatt::Database bta_gattc_hash_load(const Octet16& hash);
extern bool bta_gattc_hash_write(const Octet16& hash,
                                 const gatt::Database& database);
extern gatt::Database bta_gattc_cache_load(const RawAddress& server_bda);
extern gatt::Database bta_gattc_cache_load(const RawAddress& server_bda);
extern void bta_gattc_cache_write(const RawAddress& server_bda,
extern void bta_gattc_cache_write(const RawAddress& server_bda,
                                  const gatt::Database& database);
                                  const gatt::Database& database);
extern void bta_gattc_cache_link(const RawAddress& server_bda,
                                 const Octet16& hash);
extern void bta_gattc_cache_reset(const RawAddress& server_bda);
extern void bta_gattc_cache_reset(const RawAddress& server_bda);


extern bool bta_gattc_read_db_hash(tBTA_GATTC_CLCB* p_clcb);

#endif /* BTA_GATTC_INT_H */
#endif /* BTA_GATTC_INT_H */