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

Commit dab612be 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
parent d3424eff
Loading
Loading
Loading
Loading
+68 −0
Original line number Original line Diff line number Diff line
@@ -29,9 +29,11 @@
#include <string.h>
#include <string.h>
#include <time.h>
#include <time.h>
#include <unistd.h>
#include <unistd.h>
#include <functional>
#include <mutex>
#include <mutex>
#include <sstream>
#include <sstream>
#include <string>
#include <string>
#include <unordered_map>


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


#define BT_CONFIG_SOURCE_TAG_NUM 1010001
#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_SECTION "Metrics"
#define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
#define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
#define BT_CONFIG_METRICS_ID_KEY "MetricsId"

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


// TODO(armansito): Find a better way than searching by a hardcoded path.
// TODO(armansito): Find a better way than searching by a hardcoded path.
#if defined(OS_GENERIC)
#if defined(OS_GENERIC)
@@ -191,6 +198,63 @@ static void read_or_set_metrics_salt() {
  AddressObfuscator::GetInstance()->Initialize(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::recursive_mutex config_lock;  // protects operations on |config|.
static std::unique_ptr<config_t> config;
static std::unique_ptr<config_t> config;
static alarm_t* config_timer;
static alarm_t* config_timer;
@@ -262,6 +326,9 @@ static future_t* init(void) {
  // Read or set metrics 256 bit hashing salt
  // Read or set metrics 256 bit hashing salt
  read_or_set_metrics_salt();
  read_or_set_metrics_salt();


  // Initialize MetricIdAllocator
  init_metric_id_allocator();

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


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


using bluetooth::Uuid;
using bluetooth::Uuid;
using bluetooth::common::MetricIdAllocator;
/******************************************************************************
/******************************************************************************
 *  Constants & Macros
 *  Constants & Macros
 *****************************************************************************/
 *****************************************************************************/
@@ -293,6 +295,15 @@ static void btif_dm_data_free(uint16_t event, tBTA_DM_SEC* dm_sec) {
static void btif_dm_send_bond_state_changed(RawAddress address, bt_bond_state_t bond_state) {
static void btif_dm_send_bond_state_changed(RawAddress address, bt_bond_state_t bond_state) {
  do_in_jni_thread(FROM_HERE, base::BindOnce([](RawAddress address, bt_bond_state_t bond_state) {
  do_in_jni_thread(FROM_HERE, base::BindOnce([](RawAddress address, bt_bond_state_t bond_state) {
    btif_stats_add_bond_event(address, BTIF_DM_FUNC_BOND_STATE_CHANGED, bond_state);
    btif_stats_add_bond_event(address, BTIF_DM_FUNC_BOND_STATE_CHANGED, bond_state);
    if (bond_state == BT_BOND_STATE_NONE) {
      MetricIdAllocator::GetInstance().ForgetDevice(address);
    } else if (bond_state == BT_BOND_STATE_BONDED) {
      MetricIdAllocator::GetInstance().AllocateId(address);
      if (!MetricIdAllocator::GetInstance().SaveDevice(address)) {
        LOG(FATAL) << __func__ << ": Fail to save metric id for device "
                   << address;
      }
    }
    HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, BT_STATUS_SUCCESS, &address, bond_state);
    HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, BT_STATUS_SUCCESS, &address, bond_state);
  }, address, bond_state));
  }, address, bond_state));
}
}
@@ -545,6 +556,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__,
  BTIF_TRACE_DEBUG("%s: state=%d, prev_state=%d, sdp_attempts = %d", __func__,
                   state, pairing_cb.state, pairing_cb.sdp_attempts);
                   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;
  auto tmp = bd_addr;
  HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, &tmp, state);
  HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, &tmp, state);


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


const std::string MetricIdAllocator::LOGGING_TAG = "BluetoothMetricIdAllocator";
const std::string MetricIdAllocator::LOGGING_TAG = "BluetoothMetricIdAllocator";
const size_t MetricIdAllocator::kMaxNumUnpairedDevicesInMemory = 200;
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::kMinId = 1;
const int MetricIdAllocator::kMaxId = 65534;  // 2^16 - 2
const int MetricIdAllocator::kMaxId = 65534;  // 2^16 - 2


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


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


bool MetricIdAllocator::Init(
bool MetricIdAllocator::Init(
    const std::unordered_map<RawAddress, int>& paired_device_map,
    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
// 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_);
  std::lock_guard<std::mutex> lock(id_allocator_mutex_);
  int id = 0;
  int id = 0;
  bool success = paired_device_cache_.Get(mac_address, &id);
  bool success = paired_device_cache_.Get(mac_address, &id);
  success &= paired_device_cache_.Remove(mac_address);
  success &= paired_device_cache_.Remove(mac_address);
  if (success) {
  if (success) {
    id_set_.erase(id);
    ForgetDevicePostprocess(mac_address, id);
    success = forget_device_callback_(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
}  // namespace common
+12 −1
Original line number Original line Diff line number Diff line
@@ -98,9 +98,18 @@ class MetricIdAllocator {
   * Delete the id for a device to be forgotten
   * Delete the id for a device to be forgotten
   *
   *
   * @param mac_address mac address of Bluetooth device
   * @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
   * @return true if delete successfully
   */
   */
  bool ForgetDevice(const RawAddress& mac_address);
  static bool IsValidId(const int id);


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


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

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


  // forget
  // 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_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_EQ(dummy, 88);


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


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


  // save it and make sure the callback is called
  // save it and make sure the callback is called
  EXPECT_TRUE(allocator.SaveDevice(kthAddress(key)));
  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,
  // paired: 1, 2 ... 199, 200,
  // scanned:
  // scanned:


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


  EXPECT_EQ(allocator.AllocateId(kthAddress(key + 1)), id++);
  EXPECT_EQ(allocator.AllocateId(kthAddress(key + 1)), id++);
  EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 1)));
  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
  // paired: 2 ... 199, 200, 201
  // scanned: 0
  // scanned: 0


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


  dummy = 44;
  dummy = 9;
  EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 2)));
  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_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
  // paired: 4 ... 199, 200, 201, 202, 203
  // scanned: 0, 1
  // scanned: 0, 1


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


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


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


  EXPECT_TRUE(allocator.SaveDevice(kthAddress(key + 2)));
  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_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_TRUE(allocator.SaveDevice(kthAddress(key + 4)));
  EXPECT_EQ(dummy, 352);
  EXPECT_EQ(dummy, 12);  // one key is evicted, another key is saved so *2/3,
  // paired: 6 ... 199, 200, 201, 203, 202, 204
  // paired: 5 6 ... 199, 200, 201, 203, 202, 204
  // scanned: 0, 1, 205
  // scanned: 0, 1, 205


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


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