OSDN Git Service

RootCanal: Add a scripted beacon for testing
authorMyles Watson <mylesgw@google.com>
Mon, 20 Apr 2020 22:57:07 +0000 (15:57 -0700)
committerSanjay Ramankandath <sanjayram@google.com>
Mon, 11 May 2020 14:16:22 +0000 (14:16 +0000)
Bug: 154491371
Tag: #feature
Test: Scan for devices
Test: gd/cert/run --host
Change-Id: I3354d621d4253d051eb7b814de8d7889dcf99f64

test/rootcanal/bluetooth_hci.cc
vendor_libs/test_vendor_lib/Android.bp
vendor_libs/test_vendor_lib/model/devices/scripted_beacon.cc [new file with mode: 0644]
vendor_libs/test_vendor_lib/model/devices/scripted_beacon.h [new file with mode: 0644]
vendor_libs/test_vendor_lib/model/setup/test_model.cc

index 2bebd9a..2363ce9 100644 (file)
@@ -190,6 +190,9 @@ Return<void> BluetoothHci::initialize_impl(
   test_channel_.AddDeviceToPhy({"2", "1"});
   test_channel_.Add({"beacon", "be:ac:10:00:00:02", "1000"});
   test_channel_.AddDeviceToPhy({"3", "1"});
+  test_channel_.Add(
+      {"scripted_beacon", "5b:ea:c1:00:00:03", "path_to_config.log"});
+  test_channel_.AddDeviceToPhy({"4", "1"});
 
   unlink_cb_ = [this, cb](sp<BluetoothDeathRecipient>& death_recipient) {
     if (death_recipient->getHasDied())
index 16662c2..70bb092 100644 (file)
@@ -28,6 +28,7 @@ cc_library_static {
         "model/devices/loopback.cc",
         "model/devices/polled_socket.cc",
         "model/devices/remote_loopback_device.cc",
+        "model/devices/scripted_beacon.cc",
         "model/devices/sniffer.cc",
         "model/setup/async_manager.cc",
         "model/setup/device_boutique.cc",
diff --git a/vendor_libs/test_vendor_lib/model/devices/scripted_beacon.cc b/vendor_libs/test_vendor_lib/model/devices/scripted_beacon.cc
new file mode 100644 (file)
index 0000000..fff377b
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "scripted_beacon.h"
+
+// #include "hci/hci_packets.h" // To use error-checking packets
+#include "model/setup/device_boutique.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+bool ScriptedBeacon::registered_ =
+    DeviceBoutique::Register("scripted_beacon", &ScriptedBeacon::Create);
+
+ScriptedBeacon::ScriptedBeacon() {
+  advertising_interval_ms_ = std::chrono::milliseconds(1280);
+  properties_.SetLeAdvertisementType(0x03 /* NON_CONNECT */);
+  properties_.SetLeAdvertisement({
+      0x18,  // Length
+      0x09 /* TYPE_NAME_CMPL */,
+      'g',
+      'D',
+      'e',
+      'v',
+      'i',
+      'c',
+      'e',
+      '-',
+      's',
+      'c',
+      'r',
+      'i',
+      'p',
+      't',
+      'e',
+      'd',
+      '-',
+      'b',
+      'e',
+      'a',
+      'c',
+      'o',
+      'n',
+      0x02,  // Length
+      0x01 /* TYPE_FLAG */,
+      0x4 /* BREDR_NOT_SPT */ | 0x2 /* GEN_DISC_FLAG */,
+  });
+
+  properties_.SetLeScanResponse({0x06,  // Length
+                                 0x07,  // TYPE_NAME_SHORT
+                                 'g', 'b', 'e', 'a'});
+}
+
+void ScriptedBeacon::Initialize(const vector<std::string>& args) {
+  if (args.size() < 2) return;
+
+  Address addr{};
+  if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
+
+  if (args.size() < 3) return;
+
+  config_file_ = args[2];
+}
+
+void ScriptedBeacon::TimerTick() {
+  if (!scanned_once_) {
+    Beacon::TimerTick();
+  } else {
+    std::shared_ptr<model::packets::LinkLayerPacketBuilder> to_send;
+    std::chrono::steady_clock::time_point now =
+        std::chrono::steady_clock::now();
+    elapsed_time_ += now - last_timer_tick_;
+    while (next_ad_.ad_time < now) {
+      auto ad = model::packets::LeAdvertisementBuilder::Create(
+          next_ad_.address, Address::kEmpty /* Destination */,
+          model::packets::AddressType::RANDOM,
+          model::packets::AdvertisementType::ADV_NONCONN_IND, next_ad_.ad);
+      to_send = std::move(ad);
+      for (auto phy : phy_layers_[Phy::Type::LOW_ENERGY]) {
+        phy->Send(to_send);
+      }
+      get_next_advertisement();
+    }
+    last_timer_tick_ = now;
+  }
+}
+
+void ScriptedBeacon::IncomingPacket(
+    model::packets::LinkLayerPacketView packet) {
+  if (!scanned_once_) {
+    if (packet.GetDestinationAddress() == properties_.GetLeAddress() &&
+        packet.GetType() == model::packets::PacketType::LE_SCAN) {
+      auto scan_response = model::packets::LeScanResponseBuilder::Create(
+          properties_.GetLeAddress(), packet.GetSourceAddress(),
+          static_cast<model::packets::AddressType>(
+              properties_.GetLeAddressType()),
+          model::packets::AdvertisementType::SCAN_RESPONSE,
+          properties_.GetLeScanResponse());
+      std::shared_ptr<model::packets::LinkLayerPacketBuilder> to_send =
+          std::move(scan_response);
+      scanned_once_ = true;
+      Address::FromString("12:34:56:78:9A:BC", next_ad_.address);
+      open_config_file();
+      for (auto phy : phy_layers_[Phy::Type::LOW_ENERGY]) {
+        phy->Send(to_send);
+      }
+    }
+  }
+}
+
+void ScriptedBeacon::get_next_advertisement() {
+  next_ad_.address.address[2]++;
+  /* For more recent versions:
+   * using bluetooth::hci::GapData;
+   * using bluetooth::hci::GapDataType;
+   * GapData flags;
+   * flags.data_type_ = GapDataType::FLAGS;
+   * flags.data_ = {0x1A};
+   * GapData service;
+   * service.data_type_ = GapDataType::COMPLETE_LIST_16_BIT_UUIDS;
+   * service.data_ = {0x6F, 0xFD}; // 0xFD6F Contact Detection Service
+   * GapData proximity_id;
+   * proximity_id.data_type = GapDataType::SERVICE_DATA_128_BIT_UUIDS;
+   * proximity_id.data_ = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+   *                       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+   *                       };
+   */
+  // For older/all versions:
+  next_ad_.ad = {
+      0x02,  // Size
+      0x01,  // Flag
+      0x1A,
+      0x03,  // Size
+      0x03,  // Complete 16-bit Service UUID
+      0x6F,
+      0xFD,
+      0x13,  // Size
+      0x16,  // Service Data - 16 bit UUID
+      0x6F,  // FD6F
+      0xFD,
+      0x00,  // ID
+      0x01,
+      next_ad_.address.address[2],  // make it different from the others
+      0x03,
+      0x04,
+      0x05,
+      0x06,
+      0x07,
+      0x08,
+      0x09,
+      0x0a,
+      0x0b,
+      0x0c,
+      0x0d,
+      0x0e,
+      0x0f,
+  };
+}
+
+void ScriptedBeacon::open_config_file() {
+  // Open the config file and read it all?
+}
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/scripted_beacon.h b/vendor_libs/test_vendor_lib/model/devices/scripted_beacon.h
new file mode 100644 (file)
index 0000000..a7c64e8
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "beacon.h"
+
+namespace test_vendor_lib {
+
+// Pretend to be a lot of beacons by advertising from a file.
+class ScriptedBeacon : public Beacon {
+ public:
+  ScriptedBeacon();
+  virtual ~ScriptedBeacon() = default;
+
+  static std::shared_ptr<Device> Create() {
+    return std::make_shared<ScriptedBeacon>();
+  }
+
+  // Return a string representation of the type of device.
+  virtual std::string GetTypeString() const override {
+    return "scripted_beacon";
+  }
+
+  virtual std::string ToString() const override {
+    return "scripted_beacon " + config_file_;
+  }
+
+  // Set the address and advertising interval from string args.
+  void Initialize(const std::vector<std::string>& args) override;
+
+  void TimerTick() override;
+
+  void IncomingPacket(model::packets::LinkLayerPacketView packet_view) override;
+
+ private:
+  static bool registered_;
+  bool scanned_once_{false};
+  std::chrono::steady_clock::duration elapsed_time_{};
+  std::chrono::steady_clock::time_point last_timer_tick_{};
+  std::string config_file_{};
+  void open_config_file();
+  struct Advertisement {
+    std::vector<uint8_t> ad;
+    Address address;
+    std::chrono::steady_clock::time_point ad_time;
+  };
+
+  void get_next_advertisement();
+
+  Advertisement next_ad_{};
+};
+
+}  // namespace test_vendor_lib
index 688b7dc..71ef77d 100644 (file)
@@ -23,6 +23,7 @@
 #include "model/devices/classic.h"
 #include "model/devices/keyboard.h"
 #include "model/devices/remote_loopback_device.h"
+#include "model/devices/scripted_beacon.h"
 #include "model/devices/sniffer.h"
 
 #include <memory>
@@ -63,6 +64,7 @@ TestModel::TestModel(
   example_devices_.push_back(std::make_shared<CarKit>());
   example_devices_.push_back(std::make_shared<Classic>());
   example_devices_.push_back(std::make_shared<Sniffer>());
+  example_devices_.push_back(std::make_shared<ScriptedBeacon>());
   example_devices_.push_back(std::make_shared<RemoteLoopbackDevice>());
 }