OSDN Git Service

Bluetooth Metrics: Init and Close MetricIdAllocator and use its APIs
authorChen Chen <cncn@google.com>
Sat, 14 Mar 2020 00:00:24 +0000 (17:00 -0700)
committerChen Chen <cncn@google.com>
Fri, 20 Mar 2020 18:13:53 +0000 (18:13 +0000)
Test: Manually pair device and cat config file
Bug: 142563377
Change-Id: I4492dc9b4c9d810e7919e97ef36ea151b76b2dbc
Merged-In: I4492dc9b4c9d810e7919e97ef36ea151b76b2dbc
(cherry picked from commit f6a356ead8e711e3b94e0e915a5b94cfac978ffa)

btif/src/btif_config.cc
btif/src/btif_dm.cc
common/metric_id_allocator.cc
common/metric_id_allocator.h
common/metric_id_allocator_unittest.cc

index 8012745..d0f36cc 100644 (file)
 #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);
 }
index 59954ad..f2fcee8 100644 (file)
@@ -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);
 
index 92a5822..652803b 100644 (file)
@@ -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
index bbef02e..63236e4 100644 (file)
@@ -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;
index 416b671..eae2ffe 100644 (file)
@@ -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: 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) {