OSDN Git Service

gd: Handle scan response
authorChienyuan <chienyuanhuang@google.com>
Mon, 11 Jan 2021 14:25:11 +0000 (22:25 +0800)
committerChienyuan <chienyuanhuang@google.com>
Wed, 13 Jan 2021 08:20:55 +0000 (16:20 +0800)
Tag: #gd-refactor
Bug: 177044452
Test: gd/cert/run --host
Change-Id: Ia710365dba1901803fd8c85d3cecb27f22d25bc5

gd/hci/le_scanning_manager.cc
gd/hci/le_scanning_manager_test.cc

index c7981a0..b49430d 100644 (file)
@@ -33,6 +33,12 @@ namespace hci {
 constexpr uint16_t kDefaultLeScanWindow = 4800;
 constexpr uint16_t kDefaultLeScanInterval = 4800;
 
+constexpr uint8_t kScannableBit = 1;
+constexpr uint8_t kDirectedBit = 2;
+constexpr uint8_t kScanResponseBit = 3;
+constexpr uint8_t kLegacyBit = 4;
+constexpr uint8_t kDataStatusBits = 5;
+
 const ModuleFactory LeScanningManager::Factory = ModuleFactory([]() { return new LeScanningManager(); });
 
 enum class ScanApiType {
@@ -46,6 +52,79 @@ struct Scanner {
   bool in_use;
 };
 
+class AdvertisingCache {
+ public:
+  const std::vector<GapData>& Set(const AddressWithType& address_with_type, std::vector<GapData> data) {
+    auto it = Find(address_with_type);
+    if (it != items.end()) {
+      it->data = std::move(data);
+    }
+
+    if (items.size() > cache_max) {
+      items.pop_back();
+    }
+
+    items.emplace_front(address_with_type, std::move(data));
+    return items.front().data;
+  }
+
+  bool Exist(const AddressWithType& address_with_type) {
+    auto it = Find(address_with_type);
+    if (it == items.end()) {
+      return false;
+    }
+    return true;
+  }
+
+  const std::vector<GapData>& Append(const AddressWithType& address_with_type, std::vector<GapData> data) {
+    auto it = Find(address_with_type);
+    if (it != items.end()) {
+      it->data.insert(it->data.end(), data.begin(), data.end());
+      return it->data;
+    }
+
+    if (items.size() > cache_max) {
+      items.pop_back();
+    }
+
+    items.emplace_front(address_with_type, std::move(data));
+    return items.front().data;
+  }
+
+  /* Clear data for device |addr_type, addr| */
+  void Clear(AddressWithType address_with_type) {
+    auto it = Find(address_with_type);
+    if (it != items.end()) {
+      items.erase(it);
+    }
+  }
+
+  void ClearAll() {
+    items.clear();
+  }
+
+  struct Item {
+    AddressWithType address_with_type;
+    std::vector<GapData> data;
+
+    Item(const AddressWithType& address_with_type, std::vector<GapData> data)
+        : address_with_type(address_with_type), data(data) {}
+  };
+
+  std::list<Item>::iterator Find(const AddressWithType& address_with_type) {
+    for (auto it = items.begin(); it != items.end(); it++) {
+      if (it->address_with_type == address_with_type) {
+        return it;
+      }
+    }
+    return items.end();
+  }
+
+  /* we keep maximum 7 devices in the cache */
+  const size_t cache_max = 1000;
+  std::list<Item> items;
+};
+
 struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback {
   impl(Module* module) : module_(module), le_scanning_interface_(nullptr) {}
 
@@ -132,7 +211,6 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
       return;
     }
 
-    // TODO: handle AdvertisingCache for scan response
     for (LeAdvertisingReport report : reports) {
       uint16_t extended_event_type = 0;
       switch (report.event_type_) {
@@ -159,8 +237,8 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
           return;
       }
 
-      scanning_callbacks_->OnScanResult(
-          (uint16_t)report.event_type_,
+      process_advertising_package_content(
+          extended_event_type,
           (uint8_t)report.address_type_,
           report.address_,
           (uint8_t)PrimaryPhyType::LE_1M,
@@ -207,11 +285,11 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
       return;
     }
 
-    // TODO: handle AdvertisingCache for scan response
     for (LeExtendedAdvertisingReport report : reports) {
-      uint16_t event_type = report.connectable_ | (report.scannable_ << 1) | (report.directed_ << 2) |
-                            (report.scan_response_ << 3) | (report.legacy_ << 4) | ((uint16_t)report.data_status_ << 5);
-      scanning_callbacks_->OnScanResult(
+      uint16_t event_type = report.connectable_ | (report.scannable_ << kScannableBit) |
+                            (report.directed_ << kDirectedBit) | (report.scan_response_ << kScanResponseBit) |
+                            (report.legacy_ << kLegacyBit) | ((uint16_t)report.data_status_ << kDataStatusBits);
+      process_advertising_package_content(
           event_type,
           (uint8_t)report.address_type_,
           report.address_,
@@ -225,6 +303,54 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
     }
   }
 
+  void process_advertising_package_content(
+      uint16_t event_type,
+      uint8_t address_type,
+      Address address,
+      uint8_t primary_phy,
+      uint8_t secondary_phy,
+      uint8_t advertising_sid,
+      int8_t tx_power,
+      int8_t rssi,
+      uint16_t periodic_advertising_interval,
+      std::vector<GapData> advertising_data) {
+    bool is_scannable = event_type & (1 << kScannableBit);
+    bool is_scan_response = event_type & (1 << kScanResponseBit);
+    bool is_legacy = event_type & (1 << kLegacyBit);
+    // TODO handle anonymous advertisement (0xFF)
+    AddressWithType address_with_type(address, (AddressType)address_type);
+
+    if (is_legacy && is_scan_response && !advertising_cache_.Exist(address_with_type)) {
+      return;
+    }
+
+    bool is_start = is_legacy && is_scannable && !is_scan_response;
+
+    std::vector<GapData> const& adv_data = is_start ? advertising_cache_.Set(address_with_type, advertising_data)
+                                                    : advertising_cache_.Append(address_with_type, advertising_data);
+
+    // TODO: handle data status
+
+    if (is_scannable && !is_scan_response) {
+      // Waiting for scan response
+      return;
+    }
+
+    scanning_callbacks_->OnScanResult(
+        event_type,
+        address_type,
+        address,
+        primary_phy,
+        secondary_phy,
+        advertising_sid,
+        tx_power,
+        rssi,
+        periodic_advertising_interval,
+        adv_data);
+
+    advertising_cache_.Clear(address_with_type);
+  }
+
   void configure_scan() {
     std::vector<PhyScanParameters> parameter_vector;
     PhyScanParameters phy_scan_parameters;
@@ -389,6 +515,7 @@ struct LeScanningManager::impl : public bluetooth::hci::LeAddressManagerCallback
   bool is_scanning_ = false;
   bool scan_on_resume_ = false;
   bool paused_ = false;
+  AdvertisingCache advertising_cache_;
 
   uint32_t interval_ms_{1000};
   uint16_t window_ms_{1000};
index a39b86a..a9b3738 100644 (file)
@@ -334,7 +334,7 @@ TEST_F(LeScanningManagerTest, start_scan_test) {
   test_hci_layer_->IncomingEvent(LeSetScanEnableCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS));
 
   LeAdvertisingReport report{};
-  report.event_type_ = AdvertisingEventType::ADV_IND;
+  report.event_type_ = AdvertisingEventType::ADV_DIRECT_IND;
   report.address_type_ = AddressType::PUBLIC_DEVICE_ADDRESS;
   Address::FromString("12:34:56:78:9a:bc", report.address_);
   std::vector<GapData> gap_data{};
@@ -361,7 +361,7 @@ TEST_F(LeAndroidHciScanningManagerTest, start_scan_test) {
   test_hci_layer_->IncomingEvent(LeSetScanEnableCompleteBuilder::Create(uint8_t{1}, ErrorCode::SUCCESS));
 
   LeAdvertisingReport report{};
-  report.event_type_ = AdvertisingEventType::ADV_IND;
+  report.event_type_ = AdvertisingEventType::ADV_DIRECT_IND;
   report.address_type_ = AddressType::PUBLIC_DEVICE_ADDRESS;
   Address::FromString("12:34:56:78:9a:bc", report.address_);
   std::vector<GapData> gap_data{};
@@ -391,7 +391,7 @@ TEST_F(LeExtendedScanningManagerTest, start_scan_test) {
 
   LeExtendedAdvertisingReport report{};
   report.connectable_ = 1;
-  report.scannable_ = 1;
+  report.scannable_ = 0;
   report.address_type_ = DirectAdvertisingAddressType::PUBLIC_DEVICE_ADDRESS;
   Address::FromString("12:34:56:78:9a:bc", report.address_);
   std::vector<GapData> gap_data{};