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

Commit 132c5179 authored by Chen Chen's avatar Chen Chen
Browse files

Bluetooth Metrics: Init and Close MetricIdAllocator and use its APIs

Test: Manually pair device and cat config file
Bug: 142563377
Change-Id: I4492dc9b4c9d810e7919e97ef36ea151b76b2dbc
Merged-In: I4492dc9b4c9d810e7919e97ef36ea151b76b2dbc
(cherry picked from commit f6a356ead8e711e3b94e0e915a5b94cfac978ffa)
parent ccf28543
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -29,9 +29,11 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <functional>
#include <mutex>
#include <sstream>
#include <string>
#include <unordered_map>

#include "bt_types.h"
#include "btcore/include/module.h"
@@ -41,6 +43,7 @@
//#include "btif_keystore.h"
#include "btif_util.h"
#include "common/address_obfuscator.h"
#include "common/metric_id_allocator.h"
#include "main/shim/config.h"
#include "main/shim/shim.h"
#include "osi/include/alarm.h"
@@ -50,6 +53,7 @@
#include "osi/include/log.h"
#include "osi/include/osi.h"
#include "osi/include/properties.h"
#include "raw_address.h"

#define BT_CONFIG_SOURCE_TAG_NUM 1010001

@@ -68,8 +72,11 @@ static const char* TIME_STRING_FORMAT = "%Y-%m-%d %H:%M:%S";

#define BT_CONFIG_METRICS_SECTION "Metrics"
#define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
#define BT_CONFIG_METRICS_ID_KEY "MetricsId"

// using bluetooth::BtifKeystore;
using bluetooth::common::AddressObfuscator;
using bluetooth::common::MetricIdAllocator;

// TODO(armansito): Find a better way than searching by a hardcoded path.
#if defined(OS_GENERIC)
@@ -192,6 +199,63 @@ static void read_or_set_metrics_salt() {
  AddressObfuscator::GetInstance()->Initialize(metrics_salt);
}

/**
 * Initialize metric id allocator by reading metric_id from config by mac
 * address. If there is no metric id for a mac address, then allocate it a new
 * metric id.
 */
static void init_metric_id_allocator() {
  std::unordered_map<RawAddress, int> paired_device_map;

  // When user update the system, there will be devices paired with older
  // version of android without a metric id.
  std::vector<RawAddress> addresses_without_id;

  for (auto& section : btif_config_sections()) {
    auto& section_name = section.name;
    RawAddress mac_address;
    if (!RawAddress::FromString(section_name, mac_address)) {
      continue;
    }
    // if the section name is a mac address
    bool is_valid_id_found = false;
    if (btif_config_exist(section_name, BT_CONFIG_METRICS_ID_KEY)) {
      // there is one metric id under this mac_address
      int id = 0;
      btif_config_get_int(section_name, BT_CONFIG_METRICS_ID_KEY, &id);
      if (MetricIdAllocator::IsValidId(id)) {
        paired_device_map[mac_address] = id;
        is_valid_id_found = true;
      }
    }
    if (!is_valid_id_found) {
      addresses_without_id.push_back(mac_address);
    }
  }

  // Initialize MetricIdAllocator
  MetricIdAllocator::Callback save_device_callback =
      [](const RawAddress& address, const int id) {
        return btif_config_set_int(address.ToString(), BT_CONFIG_METRICS_ID_KEY,
                                   id);
      };
  MetricIdAllocator::Callback forget_device_callback =
      [](const RawAddress& address, const int id) {
        return btif_config_remove(address.ToString(), BT_CONFIG_METRICS_ID_KEY);
      };
  if (!MetricIdAllocator::GetInstance().Init(
          paired_device_map, std::move(save_device_callback),
          std::move(forget_device_callback))) {
    LOG(FATAL) << __func__ << "Failed to initialize MetricIdAllocator";
  }

  // Add device_without_id
  for (auto& address : addresses_without_id) {
    MetricIdAllocator::GetInstance().AllocateId(address);
    MetricIdAllocator::GetInstance().SaveDevice(address);
  }
}

static std::recursive_mutex config_lock;  // protects operations on |config|.
static std::unique_ptr<config_t> config;
static alarm_t* config_timer;
@@ -265,6 +329,9 @@ static future_t* init(void) {
  // Read or set metrics 256 bit hashing salt
  read_or_set_metrics_salt();

  // Initialize MetricIdAllocator
  init_metric_id_allocator();

  // TODO(sharvil): use a non-wake alarm for this once we have
  // API support for it. There's no need to wake the system to
  // write back to disk.
@@ -329,6 +396,7 @@ static future_t* clean_up(void) {
  config_timer = NULL;

  std::unique_lock<std::recursive_mutex> lock(config_lock);
  MetricIdAllocator::GetInstance().Close();
  config.reset();
  return future_new_immediate(FUTURE_SUCCESS);
}
+11 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@
#include "btif_storage.h"
#include "btif_util.h"
#include "btu.h"
#include "common/metric_id_allocator.h"
#include "common/metrics.h"
#include "device/include/controller.h"
#include "device/include/interop.h"
@@ -72,6 +73,7 @@
#include "stack_config.h"

using bluetooth::Uuid;
using bluetooth::common::MetricIdAllocator;
/******************************************************************************
 *  Constants & Macros
 *****************************************************************************/
@@ -505,6 +507,15 @@ static void bond_state_changed(bt_status_t status, const RawAddress& bd_addr,
  BTIF_TRACE_DEBUG("%s: state=%d, prev_state=%d, sdp_attempts = %d", __func__,
                   state, pairing_cb.state, pairing_cb.sdp_attempts);

  if (state == BT_BOND_STATE_NONE) {
    MetricIdAllocator::GetInstance().ForgetDevice(bd_addr);
  } else if (state == BT_BOND_STATE_BONDED) {
    MetricIdAllocator::GetInstance().AllocateId(bd_addr);
    if (!MetricIdAllocator::GetInstance().SaveDevice(bd_addr)) {
      LOG(FATAL) << __func__ << ": Fail to save metric id for device "
                 << bd_addr;
    }
  }
  auto tmp = bd_addr;
  HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, &tmp, state);

+18 −11
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@ namespace common {

const std::string MetricIdAllocator::LOGGING_TAG = "BluetoothMetricIdAllocator";
const size_t MetricIdAllocator::kMaxNumUnpairedDevicesInMemory = 200;
const size_t MetricIdAllocator::kMaxNumPairedDevicesInMemory = 400;
const size_t MetricIdAllocator::kMaxNumPairedDevicesInMemory = 65000;
const int MetricIdAllocator::kMinId = 1;
const int MetricIdAllocator::kMaxId = 65534;  // 2^16 - 2

@@ -43,13 +43,12 @@ static_assert((MetricIdAllocator::kMaxNumUnpairedDevicesInMemory +

MetricIdAllocator::MetricIdAllocator()
    : paired_device_cache_(kMaxNumPairedDevicesInMemory, LOGGING_TAG,
                           [this](RawAddress dummy, int to_remove) {
                             this->id_set_.erase(to_remove);
                           [this](RawAddress mac_address, int id) {
                             ForgetDevicePostprocess(mac_address, id);
                           }),
      temporary_device_cache_(kMaxNumUnpairedDevicesInMemory, LOGGING_TAG,
                              [this](RawAddress dummy, int to_remove) {
                                this->id_set_.erase(to_remove);
                              }) {}
      temporary_device_cache_(
          kMaxNumUnpairedDevicesInMemory, LOGGING_TAG,
          [this](RawAddress dummy, int id) { this->id_set_.erase(id); }) {}

bool MetricIdAllocator::Init(
    const std::unordered_map<RawAddress, int>& paired_device_map,
@@ -157,16 +156,24 @@ bool MetricIdAllocator::SaveDevice(const RawAddress& mac_address) {
}

// call this function when a device is forgotten
bool MetricIdAllocator::ForgetDevice(const RawAddress& mac_address) {
void MetricIdAllocator::ForgetDevice(const RawAddress& mac_address) {
  std::lock_guard<std::mutex> lock(id_allocator_mutex_);
  int id = 0;
  bool success = paired_device_cache_.Get(mac_address, &id);
  success &= paired_device_cache_.Remove(mac_address);
  if (success) {
    id_set_.erase(id);
    success = forget_device_callback_(mac_address, id);
    ForgetDevicePostprocess(mac_address, id);
  }
  return success;
}

bool MetricIdAllocator::IsValidId(const int id) {
  return id >= kMinId && id <= kMaxId;
}

void MetricIdAllocator::ForgetDevicePostprocess(const RawAddress& mac_address,
                                                const int id) {
  id_set_.erase(id);
  forget_device_callback_(mac_address, id);
}

}  // namespace common
+12 −1
Original line number Diff line number Diff line
@@ -98,9 +98,18 @@ class MetricIdAllocator {
   * Delete the id for a device to be forgotten
   *
   * @param mac_address mac address of Bluetooth device
   */
  void ForgetDevice(const RawAddress& mac_address);

  /**
   * Check if an id is valid.
   * The id should be less than or equal to kMaxId and bigger than or equal to
   * kMinId
   *
   * @param mac_address mac address of Bluetooth device
   * @return true if delete successfully
   */
  bool ForgetDevice(const RawAddress& mac_address);
  static bool IsValidId(const int id);

 protected:
  // Singleton
@@ -119,6 +128,8 @@ class MetricIdAllocator {
  Callback save_id_callback_;
  Callback forget_device_callback_;

  void ForgetDevicePostprocess(const RawAddress& mac_address, const int id);

  // delete copy constructor for singleton
  MetricIdAllocator(MetricIdAllocator const&) = delete;
  MetricIdAllocator& operator=(MetricIdAllocator const&) = delete;
+31 −28
Original line number Diff line number Diff line
@@ -170,9 +170,9 @@ TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorMainTest1) {
  EXPECT_EQ(dummy, 176);

  // forget
  EXPECT_FALSE(allocator.ForgetDevice(RawAddress({0, 0, 0, 0, 0, 1})));
  allocator.ForgetDevice(RawAddress({0, 0, 0, 0, 0, 1}));
  EXPECT_EQ(dummy, 176);
  EXPECT_TRUE(allocator.ForgetDevice(RawAddress({0, 0, 0, 0, 0, 2})));
  allocator.ForgetDevice(RawAddress({0, 0, 0, 0, 0, 2}));
  EXPECT_EQ(dummy, 88);

  EXPECT_TRUE(allocator.Close());
@@ -183,7 +183,7 @@ TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorFullPairedMap) {
  // preset a full map
  std::unordered_map<RawAddress, int> paired_device_map =
      generateAddresses(MetricIdAllocator::kMaxNumPairedDevicesInMemory);
  int dummy = 22;
  int dummy = 243;
  int* pointer = &dummy;
  MetricIdAllocator::Callback save_callback = [pointer](const RawAddress&,
                                                        const int) {
@@ -192,7 +192,7 @@ TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorFullPairedMap) {
  };
  MetricIdAllocator::Callback forget_callback = [pointer](const RawAddress&,
                                                          const int) {
    *pointer = *pointer / 2;
    *pointer = *pointer / 3;
    return true;
  };

@@ -222,7 +222,8 @@ TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorFullPairedMap) {

  // save it and make sure the callback is called
  EXPECT_TRUE(allocator.SaveDevice(kthAddress(key)));
  EXPECT_EQ(dummy, 44);
  EXPECT_EQ(dummy, 162);  // one key is evicted, another key is saved so *2/3

  // paired: 1, 2 ... 199, 200,
  // scanned:

@@ -233,13 +234,13 @@ TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorFullPairedMap) {
  // key == 200
  // should fail, since id of device is not allocated
  EXPECT_FALSE(allocator.SaveDevice(kthAddress(key + 1)));
  EXPECT_EQ(dummy, 44);
  EXPECT_EQ(dummy, 162);
  // paired: 1, 2 ... 199, 200,
  // scanned: 0

  EXPECT_EQ(allocator.AllocateId(kthAddress(key + 1)), id++);
  EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 1)));
  EXPECT_EQ(dummy, 88);
  EXPECT_EQ(dummy, 108);  // one key is evicted, another key is saved so *2/3,
  // paired: 2 ... 199, 200, 201
  // scanned: 0

@@ -253,23 +254,24 @@ TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorFullPairedMap) {
  // paired: 2 ... 199, 200, 201,
  // scanned: 0, 1, 202, 203

  dummy = 44;
  dummy = 9;
  EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 2)));
  EXPECT_EQ(dummy, 88);
  EXPECT_EQ(dummy, 6);  // one key is evicted, another key is saved so *2/3,
  EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 3)));
  EXPECT_EQ(dummy, 176);
  EXPECT_EQ(dummy, 4);  // one key is evicted, another key is saved so *2/3,
  // paired: 4 ... 199, 200, 201, 202, 203
  // scanned: 0, 1

  // should fail, since id had been saved
  EXPECT_FALSE(allocator.SaveDevice(kthAddress(key + 2)));
  EXPECT_EQ(dummy, 176);
  EXPECT_EQ(dummy, 4);

  dummy = 27;
  // forget
  EXPECT_FALSE(allocator.ForgetDevice(kthAddress(key + 200)));
  EXPECT_EQ(dummy, 176);
  EXPECT_TRUE(allocator.ForgetDevice(kthAddress(key + 2)));
  EXPECT_EQ(dummy, 88);
  allocator.ForgetDevice(kthAddress(key + 200));
  EXPECT_EQ(dummy, 27);  // should fail, no such a key
  allocator.ForgetDevice(kthAddress(key + 2));
  EXPECT_EQ(dummy, 9);
  // paired: 4 ... 199, 200, 201, 203
  // scanned: 0, 1

@@ -281,25 +283,25 @@ TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorFullPairedMap) {
  // scanned: 0, 1, 202, 204, 205

  EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 2)));
  EXPECT_EQ(dummy, 176);
  EXPECT_EQ(dummy, 18);  // no key is evicted, a key is saved so *2,
  EXPECT_FALSE(allocator.SaveDevice(kthAddress(key + 3)));
  EXPECT_EQ(dummy, 176);
  EXPECT_EQ(dummy, 18);  // no such a key in scanned
  EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 4)));
  EXPECT_EQ(dummy, 352);
  // paired: 6 ... 199, 200, 201, 203, 202, 204
  EXPECT_EQ(dummy, 12);  // one key is evicted, another key is saved so *2/3,
  // paired: 5 6 ... 199, 200, 201, 203, 202, 204
  // scanned: 0, 1, 205

  // verify paired:
  for (key = 6; key <= 199; key++) {
    dummy = 10;
    EXPECT_TRUE(allocator.ForgetDevice(kthAddress(key)));
    EXPECT_EQ(dummy, 5);
  for (key = 5; key <= 199; key++) {
    dummy = 3;
    allocator.ForgetDevice(kthAddress(key));
    EXPECT_EQ(dummy, 1);
  }
  for (size_t k = MetricIdAllocator::kMaxNumPairedDevicesInMemory;
       k <= MetricIdAllocator::kMaxNumPairedDevicesInMemory + 4; k++) {
    dummy = 10;
    EXPECT_TRUE(allocator.ForgetDevice(kthAddress(k)));
    EXPECT_EQ(dummy, 5);
    dummy = 3;
    allocator.ForgetDevice(kthAddress(k));
    EXPECT_EQ(dummy, 1);
  }

  // verify scanned
@@ -397,14 +399,15 @@ TEST(BluetoothMetricIdAllocatorTest, MetricIdAllocatorMultiThreadPressureTest) {
  // make sure no deadlock
  std::vector<std::thread> workers;
  for (int key = 0;
       key < static_cast<int>(MetricIdAllocator::kMaxNumPairedDevicesInMemory);
       key <
       static_cast<int>(MetricIdAllocator::kMaxNumUnpairedDevicesInMemory);
       key++) {
    workers.push_back(std::thread([key]() {
      auto& allocator = MetricIdAllocator::GetInstance();
      RawAddress fake_mac_address = kthAddress(key);
      allocator.AllocateId(fake_mac_address);
      EXPECT_TRUE(allocator.SaveDevice(fake_mac_address));
      EXPECT_TRUE(allocator.ForgetDevice(fake_mac_address));
      allocator.ForgetDevice(fake_mac_address);
    }));
  }
  for (auto& worker : workers) {