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

Commit fcea285a authored by Qasim Javed's avatar Qasim Javed Committed by Jack He
Browse files

Cache EIR UUIDs per Bluetooth address outside the pairing_cb_t

Currently, EIR UUIDs are cached inside the pairing control block. This
means EIR UUIDs belonging to device A can overwrite the EIR UUIDs
belonging to device B. Subsequently, if SDP fails for device A, we would
happily fetch the EIR UUIDs we know of (Device B's) and report it to the
Java layer. This is clearly incorrect.

Fix this by storing the EIR UUIDs per bdaddr. Upon failure of SDP, send
the EIR UUIDs belonging to the device for which SDP failed to Java and
then clear those EIR UUIDs so that we do not store them in memory for
longer than desired.

We are now using an LRU Cache to store the EIR UUIDs corresponding to
each discovered bdaddr. The cache can have EIR UUIDs for upto 128
devices.

1 BD_ADDR = 6 bytes
1 set of, say 6, 128-bit UUIDs = 96 bytes
=========================================
128 entries = 128*(6+96) = 13,056 bytes ~ 13KB of memory usage

If pairing is never done for certain devices after discovery, then
entries for these previously seen devices will always stay there in the
cache until the cache fills up with 128 entries at which point the
oldest entry will be replaced with the newest one.

Therefore, this CL adds a permanent memory footprint of about 13KB.

Bug: 242350646
Tag: #refactor
Test: tested it manually by forcing only EIR UUIDs to propagate to the
Java layer and also tested the case where zero EIR UUIDs exist and an
empty UUID is sent to the Java layer

Ignore-AOSP-First: Cherry-pick

Change-Id: Id3c4f7efd44c724a9451f31388d96d8f6119c1ba
(cherry-picked from commit 17db20332ef500ee0ad2d0b659002ba9a5182bc6)
parent 1e376a18
Loading
Loading
Loading
Loading
+34 −26
Original line number Diff line number Diff line
@@ -78,6 +78,7 @@
#include "common/metrics.h"
#include "device/include/controller.h"
#include "device/include/interop.h"
#include "gd/common/lru_cache.h"
#include "internal_include/stack_config.h"
#include "main/shim/dumpsys.h"
#include "main/shim/shim.h"
@@ -164,9 +165,6 @@ typedef struct {
  bool is_le_nc; /* LE Numeric comparison */
  btif_dm_ble_cb_t ble;
  uint8_t fail_reason;
  Uuid::UUID128Bit eir_uuids[32];
  uint8_t num_eir_uuids;
  std::set<Uuid::UUID128Bit> uuids;
} btif_dm_pairing_cb_t;

// TODO(jpawlowski): unify ?
@@ -214,6 +212,11 @@ typedef struct {

#define MAX_BTIF_BOND_EVENT_ENTRIES 15

#define MAX_NUM_DEVICES_IN_EIR_UUID_CACHE 128

static bluetooth::common::LruCache<RawAddress, std::set<Uuid>> eir_uuids_cache(
    MAX_NUM_DEVICES_IN_EIR_UUID_CACHE);

static skip_sdp_entry_t sdp_rejectlist[] = {{76}};  // Apple Mouse and Keyboard

/* This flag will be true if HCI_Inquiry is in progress */
@@ -1302,13 +1305,16 @@ static void btif_dm_search_devices_evt(tBTA_DM_SEARCH_EVT event,
        /* Cache EIR queried services */
        if (num_uuids > 0) {
          uint16_t* p_uuid16 = (uint16_t*)uuid_list;
          pairing_cb.num_eir_uuids = 0;
          LOG_INFO("EIR UUIDS:");
          auto uuid_iter = eir_uuids_cache.find(bdaddr);
          if (uuid_iter == eir_uuids_cache.end()) {
            auto triple = eir_uuids_cache.try_emplace(bdaddr, std::set<Uuid>{});
            uuid_iter = std::get<0>(triple);
          }
          LOG_INFO("EIR UUIDs for %s:", bdaddr.ToString().c_str());
          for (int i = 0; i < num_uuids; ++i) {
            Uuid uuid = Uuid::From16Bit(p_uuid16[i]);
            LOG_INFO("        %s", uuid.ToString().c_str());
            pairing_cb.eir_uuids[i] = uuid.To128BitBE();
            pairing_cb.num_eir_uuids++;
            uuid_iter->second.insert(uuid);
          }
        }

@@ -1438,6 +1444,8 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event,
      /* onUuidChanged requires getBondedDevices to be populated.
      ** bond_state_changed needs to be sent prior to remote_device_property
      */
      auto num_eir_uuids = 0;
      Uuid uuid = {};
      if (pairing_cb.state == BT_BOND_STATE_BONDED && pairing_cb.sdp_attempts &&
          (p_data->disc_res.bd_addr == pairing_cb.bd_addr ||
           p_data->disc_res.bd_addr == pairing_cb.static_bdaddr)) {
@@ -1448,33 +1456,33 @@ static void btif_dm_search_services_evt(tBTA_DM_SEARCH_EVT event,
        // when SDP failed or no UUID is discovered
        if (p_data->disc_res.result != BTA_SUCCESS ||
            p_data->disc_res.num_uuids == 0) {
          auto uuids_iter = eir_uuids_cache.find(bd_addr);
          if (uuids_iter != eir_uuids_cache.end()) {
            num_eir_uuids = static_cast<int>(uuids_iter->second.size());
            LOG_INFO("SDP failed, send %d EIR UUIDs to unblock bonding %s",
                   pairing_cb.num_eir_uuids, bd_addr.ToString().c_str());
          bt_property_t prop_uuids;
          Uuid uuid = {};
          prop_uuids.type = BT_PROPERTY_UUIDS;
          if (pairing_cb.num_eir_uuids > 0) {
            prop_uuids.val = pairing_cb.eir_uuids;
            prop_uuids.len = pairing_cb.num_eir_uuids * Uuid::kNumBytes128;
                     num_eir_uuids, bd_addr.ToString().c_str());
            for (auto eir_uuid : uuids_iter->second) {
              auto uuid_128bit = eir_uuid.To128BitBE();
              property_value.insert(property_value.end(), uuid_128bit.begin(),
                                    uuid_128bit.end());
            }
          }
          if (num_eir_uuids > 0) {
            prop.val = (void*)property_value.data();
            prop.len = num_eir_uuids * Uuid::kNumBytes128;
          } else {
            prop_uuids.val = &uuid;
            prop_uuids.len = Uuid::kNumBytes128;
            LOG_WARN("SDP failed and we have no EIR UUIDs to report either");
            prop.val = &uuid;
            prop.len = Uuid::kNumBytes128;
          }

          /* Send the event to the BTIF
           * prop_uuids will be deep copied by this call
           */
          invoke_remote_device_properties_cb(BT_STATUS_SUCCESS, bd_addr, 1,
                                             &prop_uuids);
          pairing_cb = {};
          break;
          eir_uuids_cache.erase(uuids_iter);
        }
        // Both SDP and bonding are done, clear pairing control block in case
        // it is not already cleared
        pairing_cb = {};
      }

      if (p_data->disc_res.num_uuids != 0) {
      if (p_data->disc_res.num_uuids != 0 || num_eir_uuids != 0) {
        /* Also write this to the NVRAM */
        ret = btif_storage_set_remote_device_property(&bd_addr, &prop);
        ASSERTC(ret == BT_STATUS_SUCCESS, "storing remote services failed",