From d6a0d7fb70aaae34462315019753a20f16781756 Mon Sep 17 00:00:00 2001
From: David Duarte <licorne@google.com>
Date: Mon, 28 Mar 2022 11:36:59 +0000
Subject: [PATCH] RootCanal: Handle args in DeviceBoutique instead of the
 Device

Test: Run root-canal and add a sniffer
Change-Id: I51a1ecabf77ed54fc9e3f8d1aabe2bd10493a2d2
---
 system/test/rootcanal/bluetooth_hci.cc        |  8 ++++-
 .../model/controller/dual_mode_controller.cc  | 11 -------
 .../model/controller/dual_mode_controller.h   |  2 --
 tools/rootcanal/model/devices/beacon.cc       | 22 ++++++-------
 tools/rootcanal/model/devices/beacon.h        |  8 ++---
 tools/rootcanal/model/devices/beacon_swarm.cc | 13 +-------
 tools/rootcanal/model/devices/beacon_swarm.h  |  9 ++----
 tools/rootcanal/model/devices/broken_adv.cc   | 16 +++++-----
 tools/rootcanal/model/devices/broken_adv.h    |  8 ++---
 tools/rootcanal/model/devices/car_kit.cc      | 20 ++++++------
 tools/rootcanal/model/devices/car_kit.h       |  8 ++---
 tools/rootcanal/model/devices/classic.cc      | 18 +++++------
 tools/rootcanal/model/devices/classic.h       |  8 ++---
 tools/rootcanal/model/devices/device.h        |  3 --
 tools/rootcanal/model/devices/keyboard.cc     | 13 +-------
 tools/rootcanal/model/devices/keyboard.h      |  9 ++----
 .../model/devices/link_layer_socket_device.h  |  2 --
 tools/rootcanal/model/devices/loopback.cc     | 22 ++++++-------
 tools/rootcanal/model/devices/loopback.h      |  8 ++---
 .../model/devices/remote_loopback_device.cc   |  7 ----
 .../model/devices/remote_loopback_device.h    |  4 +--
 .../model/devices/scripted_beacon.cc          | 32 +++++++------------
 .../rootcanal/model/devices/scripted_beacon.h |  9 ++----
 tools/rootcanal/model/devices/sniffer.cc      | 14 +++-----
 tools/rootcanal/model/devices/sniffer.h       |  9 ++----
 .../rootcanal/model/setup/device_boutique.cc  | 21 ++++++------
 tools/rootcanal/model/setup/device_boutique.h | 10 +++---
 tools/rootcanal/model/setup/test_model.cc     | 11 +++----
 28 files changed, 126 insertions(+), 199 deletions(-)

diff --git a/system/test/rootcanal/bluetooth_hci.cc b/system/test/rootcanal/bluetooth_hci.cc
index 7ceff6720c1..f8f2f371bd3 100644
--- a/system/test/rootcanal/bluetooth_hci.cc
+++ b/system/test/rootcanal/bluetooth_hci.cc
@@ -35,6 +35,7 @@ namespace V1_1 {
 namespace sim {
 
 using android::hardware::hidl_vec;
+using ::bluetooth::hci::Address;
 using rootcanal::AsyncTaskId;
 using rootcanal::DualModeController;
 using rootcanal::HciSocketDevice;
@@ -107,7 +108,12 @@ Return<void> BluetoothHci::initialize_impl(
   char mac_property[PROPERTY_VALUE_MAX] = "";
   property_get("vendor.bt.rootcanal_mac_address", mac_property,
                "3C:5A:B4:01:02:03");
-  controller_->Initialize({"dmc", std::string(mac_property)});
+  auto addr = Address::FromString(std::string(mac_property));
+  if (addr) {
+    controller_->SetAddress(*addr);
+  } else {
+    LOG_ALWAYS_FATAL("Invalid address: %s", mac_property);
+  }
 
   controller_->RegisterEventChannel(
       [this, cb](std::shared_ptr<std::vector<uint8_t>> packet) {
diff --git a/tools/rootcanal/model/controller/dual_mode_controller.cc b/tools/rootcanal/model/controller/dual_mode_controller.cc
index acd413b3681..dffc069be19 100644
--- a/tools/rootcanal/model/controller/dual_mode_controller.cc
+++ b/tools/rootcanal/model/controller/dual_mode_controller.cc
@@ -38,17 +38,6 @@ constexpr uint16_t kLeMaximumDataLength = 64;
 constexpr uint16_t kLeMaximumDataTime = 0x148;
 
 // Device methods.
-void DualModeController::Initialize(const std::vector<std::string>& args) {
-  if (args.size() < 2) return;
-
-  Address addr{};
-  if (Address::FromString(args[1], addr)) {
-    properties_.SetAddress(addr);
-  } else {
-    LOG_ALWAYS_FATAL("Invalid address: %s", args[1].c_str());
-  }
-};
-
 std::string DualModeController::GetTypeString() const {
   return "Simulated Bluetooth Controller";
 }
diff --git a/tools/rootcanal/model/controller/dual_mode_controller.h b/tools/rootcanal/model/controller/dual_mode_controller.h
index f9a4d282b6e..8ef3cf33a91 100644
--- a/tools/rootcanal/model/controller/dual_mode_controller.h
+++ b/tools/rootcanal/model/controller/dual_mode_controller.h
@@ -62,8 +62,6 @@ class DualModeController : public Device {
   ~DualModeController() = default;
 
   // Device methods.
-  virtual void Initialize(const std::vector<std::string>& args) override;
-
   virtual std::string GetTypeString() const override;
 
   virtual void IncomingPacket(
diff --git a/tools/rootcanal/model/devices/beacon.cc b/tools/rootcanal/model/devices/beacon.cc
index e18a091821e..00a6983b5b2 100644
--- a/tools/rootcanal/model/devices/beacon.cc
+++ b/tools/rootcanal/model/devices/beacon.cc
@@ -40,6 +40,17 @@ Beacon::Beacon() {
                                  'c'});
 }
 
+Beacon::Beacon(const vector<std::string>& args) : Beacon() {
+  if (args.size() >= 2) {
+    Address addr{};
+    if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
+  }
+
+  if (args.size() >= 3) {
+    SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+  }
+}
+
 std::string Beacon::GetTypeString() const { return "beacon"; }
 
 std::string Beacon::ToString() const {
@@ -49,17 +60,6 @@ std::string Beacon::ToString() const {
   return dev;
 }
 
-void Beacon::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;
-
-  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
-}
-
 void Beacon::TimerTick() {
   if (IsAdvertisementAvailable()) {
     last_advertisement_ = std::chrono::steady_clock::now();
diff --git a/tools/rootcanal/model/devices/beacon.h b/tools/rootcanal/model/devices/beacon.h
index c0fc4ed1dcf..fc6af5c6902 100644
--- a/tools/rootcanal/model/devices/beacon.h
+++ b/tools/rootcanal/model/devices/beacon.h
@@ -27,9 +27,12 @@ namespace rootcanal {
 class Beacon : public Device {
  public:
   Beacon();
+  Beacon(const std::vector<std::string>& args);
   virtual ~Beacon() = default;
 
-  static std::shared_ptr<Device> Create() { return std::make_shared<Beacon>(); }
+  static std::shared_ptr<Device> Create(const std::vector<std::string>& args) {
+    return std::make_shared<Beacon>(args);
+  }
 
   // Return a string representation of the type of device.
   virtual std::string GetTypeString() const override;
@@ -37,9 +40,6 @@ class Beacon : public Device {
   // Return a string representation of the device.
   virtual std::string ToString() const override;
 
-  // Set the address and advertising interval from string args.
-  virtual void Initialize(const std::vector<std::string>& args) override;
-
   virtual void IncomingPacket(
       model::packets::LinkLayerPacketView packet) override;
 
diff --git a/tools/rootcanal/model/devices/beacon_swarm.cc b/tools/rootcanal/model/devices/beacon_swarm.cc
index ac2cea61e83..f47df40aab7 100644
--- a/tools/rootcanal/model/devices/beacon_swarm.cc
+++ b/tools/rootcanal/model/devices/beacon_swarm.cc
@@ -24,7 +24,7 @@ namespace rootcanal {
 bool BeaconSwarm::registered_ =
     DeviceBoutique::Register("beacon_swarm", &BeaconSwarm::Create);
 
-BeaconSwarm::BeaconSwarm() {
+BeaconSwarm::BeaconSwarm(const vector<std::string>& args) : Beacon(args) {
   advertising_interval_ms_ = std::chrono::milliseconds(1280);
   properties_.SetLeAdvertisementType(0x03 /* NON_CONNECT */);
   properties_.SetLeAdvertisement({
@@ -60,17 +60,6 @@ BeaconSwarm::BeaconSwarm() {
                                  'c'});
 }
 
-void BeaconSwarm::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;
-
-  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
-}
-
 void BeaconSwarm::TimerTick() {
   Address beacon_addr = properties_.GetLeAddress();
   uint8_t* low_order_byte = (uint8_t*)(&beacon_addr);
diff --git a/tools/rootcanal/model/devices/beacon_swarm.h b/tools/rootcanal/model/devices/beacon_swarm.h
index 118e047c6c0..775aa7c0669 100644
--- a/tools/rootcanal/model/devices/beacon_swarm.h
+++ b/tools/rootcanal/model/devices/beacon_swarm.h
@@ -26,19 +26,16 @@ namespace rootcanal {
 // Pretend to be a lot of beacons by changing the advertising address.
 class BeaconSwarm : public Beacon {
  public:
-  BeaconSwarm();
+  BeaconSwarm(const std::vector<std::string>& args);
   virtual ~BeaconSwarm() = default;
 
-  static std::shared_ptr<Device> Create() {
-    return std::make_shared<BeaconSwarm>();
+  static std::shared_ptr<Device> Create(const std::vector<std::string>& args) {
+    return std::make_shared<BeaconSwarm>(args);
   }
 
   // Return a string representation of the type of device.
   virtual std::string GetTypeString() const override { return "beacon_swarm"; }
 
-  // Set the address and advertising interval from string args.
-  virtual void Initialize(const std::vector<std::string>& args) override;
-
   virtual void TimerTick() override;
 
  private:
diff --git a/tools/rootcanal/model/devices/broken_adv.cc b/tools/rootcanal/model/devices/broken_adv.cc
index 2de20170676..5190f999690 100644
--- a/tools/rootcanal/model/devices/broken_adv.cc
+++ b/tools/rootcanal/model/devices/broken_adv.cc
@@ -51,15 +51,15 @@ BrokenAdv::BrokenAdv() {
   page_scan_delay_ms_ = std::chrono::milliseconds(600);
 }
 
-void BrokenAdv::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;
+BrokenAdv::BrokenAdv(const vector<std::string>& args) : BrokenAdv() {
+  if (args.size() >= 2) {
+    Address addr{};
+    if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
+  }
 
-  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+  if (args.size() >= 3) {
+    SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+  }
 }
 
 // Mostly return the correct length
diff --git a/tools/rootcanal/model/devices/broken_adv.h b/tools/rootcanal/model/devices/broken_adv.h
index 34c736900f7..e551ea27c7d 100644
--- a/tools/rootcanal/model/devices/broken_adv.h
+++ b/tools/rootcanal/model/devices/broken_adv.h
@@ -26,15 +26,13 @@ namespace rootcanal {
 class BrokenAdv : public Device {
  public:
   BrokenAdv();
+  BrokenAdv(const std::vector<std::string>& args);
   ~BrokenAdv() = default;
 
-  static std::shared_ptr<Device> Create() {
-    return std::make_shared<BrokenAdv>();
+  static std::shared_ptr<Device> Create(const std::vector<std::string>& args) {
+    return std::make_shared<BrokenAdv>(args);
   }
 
-  // Initialize the device based on the values of |args|.
-  virtual void Initialize(const std::vector<std::string>& args) override;
-
   // Return a string representation of the type of device.
   virtual std::string GetTypeString() const override { return "broken_adv"; }
 
diff --git a/tools/rootcanal/model/devices/car_kit.cc b/tools/rootcanal/model/devices/car_kit.cc
index ba2c43e07d3..ef929805351 100644
--- a/tools/rootcanal/model/devices/car_kit.cc
+++ b/tools/rootcanal/model/devices/car_kit.cc
@@ -81,16 +81,16 @@ CarKit::CarKit() : Device(kCarKitPropertiesFile) {
   });
 }
 
-void CarKit::Initialize(const vector<std::string>& args) {
-  if (args.size() < 2) return;
-
-  Address addr{};
-  if (Address::FromString(args[1], addr)) properties_.SetAddress(addr);
-  LOG_INFO("%s SetAddress %s", ToString().c_str(), addr.ToString().c_str());
-
-  if (args.size() < 3) return;
-
-  properties_.SetClockOffset(std::stoi(args[2]));
+CarKit::CarKit(const vector<std::string>& args) : CarKit() {
+  if (args.size() >= 2) {
+    Address addr{};
+    if (Address::FromString(args[1], addr)) properties_.SetAddress(addr);
+    LOG_INFO("%s SetAddress %s", ToString().c_str(), addr.ToString().c_str());
+  }
+
+  if (args.size() >= 3) {
+    properties_.SetClockOffset(std::stoi(args[2]));
+  }
 }
 
 void CarKit::TimerTick() { link_layer_controller_.TimerTick(); }
diff --git a/tools/rootcanal/model/devices/car_kit.h b/tools/rootcanal/model/devices/car_kit.h
index 8b4295dc8d7..f793e49a3e5 100644
--- a/tools/rootcanal/model/devices/car_kit.h
+++ b/tools/rootcanal/model/devices/car_kit.h
@@ -28,12 +28,12 @@ namespace rootcanal {
 class CarKit : public Device {
  public:
   CarKit();
+  CarKit(const std::vector<std::string>& args);
   ~CarKit() = default;
 
-  static std::shared_ptr<CarKit> Create() { return std::make_shared<CarKit>(); }
-
-  // Initialize the device based on the values of |args|.
-  virtual void Initialize(const std::vector<std::string>& args) override;
+  static std::shared_ptr<CarKit> Create(const std::vector<std::string>& args) {
+    return std::make_shared<CarKit>(args);
+  }
 
   // Return a string representation of the type of device.
   virtual std::string GetTypeString() const override { return "car_kit"; }
diff --git a/tools/rootcanal/model/devices/classic.cc b/tools/rootcanal/model/devices/classic.cc
index 732a8266f72..60866c953b3 100644
--- a/tools/rootcanal/model/devices/classic.cc
+++ b/tools/rootcanal/model/devices/classic.cc
@@ -40,15 +40,15 @@ Classic::Classic() {
   page_scan_delay_ms_ = std::chrono::milliseconds(600);
 }
 
-void Classic::Initialize(const vector<std::string>& args) {
-  if (args.size() < 2) return;
-
-  Address addr{};
-  if (Address::FromString(args[1], addr)) properties_.SetAddress(addr);
-
-  if (args.size() < 3) return;
-
-  properties_.SetClockOffset(std::stoi(args[2]));
+Classic::Classic(const vector<std::string>& args) : Classic() {
+  if (args.size() >= 2) {
+    Address addr{};
+    if (Address::FromString(args[1], addr)) properties_.SetAddress(addr);
+  }
+
+  if (args.size() >= 3) {
+    properties_.SetClockOffset(std::stoi(args[2]));
+  }
 }
 
 }  // namespace rootcanal
diff --git a/tools/rootcanal/model/devices/classic.h b/tools/rootcanal/model/devices/classic.h
index 861c7cf8e40..b3f6b65497a 100644
--- a/tools/rootcanal/model/devices/classic.h
+++ b/tools/rootcanal/model/devices/classic.h
@@ -26,15 +26,13 @@ namespace rootcanal {
 class Classic : public Device {
  public:
   Classic();
+  Classic(const std::vector<std::string>& args);
   ~Classic() = default;
 
-  static std::shared_ptr<Device> Create() {
-    return std::make_shared<Classic>();
+  static std::shared_ptr<Device> Create(const std::vector<std::string>& args) {
+    return std::make_shared<Classic>(args);
   }
 
-  // Initialize the device based on the values of |args|.
-  virtual void Initialize(const std::vector<std::string>& args) override;
-
   // Return a string representation of the type of device.
   virtual std::string GetTypeString() const override { return "classic"; }
 
diff --git a/tools/rootcanal/model/devices/device.h b/tools/rootcanal/model/devices/device.h
index f57f11f9a43..25d10247dde 100644
--- a/tools/rootcanal/model/devices/device.h
+++ b/tools/rootcanal/model/devices/device.h
@@ -40,9 +40,6 @@ class Device {
         properties_(properties_filename) {}
   virtual ~Device() = default;
 
-  // Initialize the device based on the values of |args|.
-  virtual void Initialize(const std::vector<std::string>& args) = 0;
-
   // Return a string representation of the type of device.
   virtual std::string GetTypeString() const = 0;
 
diff --git a/tools/rootcanal/model/devices/keyboard.cc b/tools/rootcanal/model/devices/keyboard.cc
index 5c818a02779..9d219deab98 100644
--- a/tools/rootcanal/model/devices/keyboard.cc
+++ b/tools/rootcanal/model/devices/keyboard.cc
@@ -24,7 +24,7 @@ namespace rootcanal {
 bool Keyboard::registered_ =
     DeviceBoutique::Register("keyboard", &Keyboard::Create);
 
-Keyboard::Keyboard() {
+Keyboard::Keyboard(const vector<std::string>& args) : Beacon(args) {
   properties_.SetLeAdvertisementType(0x00 /* CONNECTABLE */);
   properties_.SetLeAdvertisement(
       {0x11,  // Length
@@ -63,17 +63,6 @@ Keyboard::Keyboard() {
 
 std::string Keyboard::GetTypeString() const { return "keyboard"; }
 
-void Keyboard::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;
-
-  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
-}
-
 void Keyboard::TimerTick() {
   if (!connected_) {
     Beacon::TimerTick();
diff --git a/tools/rootcanal/model/devices/keyboard.h b/tools/rootcanal/model/devices/keyboard.h
index a97e3f976bc..65620f33929 100644
--- a/tools/rootcanal/model/devices/keyboard.h
+++ b/tools/rootcanal/model/devices/keyboard.h
@@ -26,19 +26,16 @@ namespace rootcanal {
 
 class Keyboard : public Beacon {
  public:
-  Keyboard();
+  Keyboard(const std::vector<std::string>& args);
   virtual ~Keyboard() = default;
 
-  static std::shared_ptr<Device> Create() {
-    return std::make_shared<Keyboard>();
+  static std::shared_ptr<Device> Create(const std::vector<std::string>& args) {
+    return std::make_shared<Keyboard>(args);
   }
 
   // Return a string representation of the type of device.
   virtual std::string GetTypeString() const override;
 
-  // Initialize the device based on the values of |args|.
-  virtual void Initialize(const std::vector<std::string>& args) override;
-
   virtual void IncomingPacket(
       model::packets::LinkLayerPacketView packet) override;
 
diff --git a/tools/rootcanal/model/devices/link_layer_socket_device.h b/tools/rootcanal/model/devices/link_layer_socket_device.h
index 8ad89bd8008..d887760df1d 100644
--- a/tools/rootcanal/model/devices/link_layer_socket_device.h
+++ b/tools/rootcanal/model/devices/link_layer_socket_device.h
@@ -48,8 +48,6 @@ class LinkLayerSocketDevice : public Device {
     return "link_layer_socket_device";
   }
 
-  virtual void Initialize(const std::vector<std::string>&) override {}
-
   virtual void IncomingPacket(
       model::packets::LinkLayerPacketView packet) override;
 
diff --git a/tools/rootcanal/model/devices/loopback.cc b/tools/rootcanal/model/devices/loopback.cc
index bd4ecdf8200..59c09597a20 100644
--- a/tools/rootcanal/model/devices/loopback.cc
+++ b/tools/rootcanal/model/devices/loopback.cc
@@ -44,6 +44,17 @@ Loopback::Loopback() {
                                  'l', 'o', 'o', 'p'});
 }
 
+Loopback::Loopback(const vector<std::string>& args) : Loopback() {
+  if (args.size() >= 2) {
+    Address addr{};
+    if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
+  }
+
+  if (args.size() >= 3) {
+    SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+  }
+}
+
 std::string Loopback::GetTypeString() const { return "loopback"; }
 
 std::string Loopback::ToString() const {
@@ -53,17 +64,6 @@ std::string Loopback::ToString() const {
   return dev;
 }
 
-void Loopback::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;
-
-  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
-}
-
 void Loopback::TimerTick() {}
 
 void Loopback::IncomingPacket(model::packets::LinkLayerPacketView packet) {
diff --git a/tools/rootcanal/model/devices/loopback.h b/tools/rootcanal/model/devices/loopback.h
index 866a81d5bad..d6af78d0668 100644
--- a/tools/rootcanal/model/devices/loopback.h
+++ b/tools/rootcanal/model/devices/loopback.h
@@ -27,10 +27,11 @@ namespace rootcanal {
 class Loopback : public Device {
  public:
   Loopback();
+  Loopback(const std::vector<std::string>& args);
   virtual ~Loopback() = default;
 
-  static std::shared_ptr<Device> Create() {
-    return std::make_shared<Loopback>();
+  static std::shared_ptr<Device> Create(const std::vector<std::string>& args) {
+    return std::make_shared<Loopback>(args);
   }
 
   // Return a string representation of the type of device.
@@ -39,9 +40,6 @@ class Loopback : public Device {
   // Return a string representation of the device.
   virtual std::string ToString() const override;
 
-  // Set the address and advertising interval from string args.
-  virtual void Initialize(const std::vector<std::string>& args) override;
-
   virtual void IncomingPacket(
       model::packets::LinkLayerPacketView packet) override;
 
diff --git a/tools/rootcanal/model/devices/remote_loopback_device.cc b/tools/rootcanal/model/devices/remote_loopback_device.cc
index 3d5ceff0297..afe27541a6b 100644
--- a/tools/rootcanal/model/devices/remote_loopback_device.cc
+++ b/tools/rootcanal/model/devices/remote_loopback_device.cc
@@ -35,13 +35,6 @@ std::string RemoteLoopbackDevice::ToString() const {
   return GetTypeString() + " (no address)";
 }
 
-void RemoteLoopbackDevice::Initialize(const std::vector<std::string>& args) {
-  if (args.size() < 2) return;
-
-  Address addr{};
-  if (Address::FromString(args[1], addr)) properties_.SetAddress(addr);
-}
-
 void RemoteLoopbackDevice::IncomingPacket(
     model::packets::LinkLayerPacketView packet) {
   // TODO: Check sender?
diff --git a/tools/rootcanal/model/devices/remote_loopback_device.h b/tools/rootcanal/model/devices/remote_loopback_device.h
index 78c1ffbcb09..496093b7bbd 100644
--- a/tools/rootcanal/model/devices/remote_loopback_device.h
+++ b/tools/rootcanal/model/devices/remote_loopback_device.h
@@ -28,7 +28,7 @@ class RemoteLoopbackDevice : public Device {
   RemoteLoopbackDevice();
   virtual ~RemoteLoopbackDevice() = default;
 
-  static std::shared_ptr<Device> Create() {
+  static std::shared_ptr<Device> Create(const std::vector<std::string>&) {
     return std::make_shared<RemoteLoopbackDevice>();
   }
 
@@ -38,8 +38,6 @@ class RemoteLoopbackDevice : public Device {
 
   virtual std::string ToString() const override;
 
-  virtual void Initialize(const std::vector<std::string>& args) override;
-
   virtual void IncomingPacket(
       model::packets::LinkLayerPacketView packet) override;
 
diff --git a/tools/rootcanal/model/devices/scripted_beacon.cc b/tools/rootcanal/model/devices/scripted_beacon.cc
index b13c5691d4d..9c04be789d0 100644
--- a/tools/rootcanal/model/devices/scripted_beacon.cc
+++ b/tools/rootcanal/model/devices/scripted_beacon.cc
@@ -37,7 +37,8 @@ using std::chrono::system_clock;
 namespace rootcanal {
 bool ScriptedBeacon::registered_ =
     DeviceBoutique::Register("scripted_beacon", &ScriptedBeacon::Create);
-ScriptedBeacon::ScriptedBeacon() {
+
+ScriptedBeacon::ScriptedBeacon(const vector<std::string>& args) : Beacon(args) {
   advertising_interval_ms_ = std::chrono::milliseconds(1280);
   properties_.SetLeAdvertisementType(0x02 /* SCANNABLE */);
   properties_.SetLeAdvertisement({
@@ -75,31 +76,20 @@ ScriptedBeacon::ScriptedBeacon() {
                                  0x08,  // TYPE_NAME_SHORT
                                  'g', 'b', 'e', 'a'});
   LOG_INFO("Scripted_beacon registered %s", registered_ ? "true" : "false");
-}
-
-bool has_time_elapsed(steady_clock::time_point time_point) {
-  return steady_clock::now() > time_point;
-}
 
-void ScriptedBeacon::Initialize(const vector<std::string>& args) {
-  if (args.size() < 2) {
-    LOG_ERROR(
-        "Initialization failed, need mac address, playback and playback events "
-        "file arguments");
-    return;
-  }
-
-  Address addr{};
-  if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
-
-  if (args.size() < 4) {
+  if (args.size() >= 4) {
+    config_file_ = args[2];
+    events_file_ = args[3];
+    set_state(PlaybackEvent::INITIALIZED);
+  } else {
     LOG_ERROR(
         "Initialization failed, need playback and playback events file "
         "arguments");
   }
-  config_file_ = args[2];
-  events_file_ = args[3];
-  set_state(PlaybackEvent::INITIALIZED);
+}
+
+bool has_time_elapsed(steady_clock::time_point time_point) {
+  return steady_clock::now() > time_point;
 }
 
 void ScriptedBeacon::populate_event(PlaybackEvent* event,
diff --git a/tools/rootcanal/model/devices/scripted_beacon.h b/tools/rootcanal/model/devices/scripted_beacon.h
index 333480a42a7..a5ea22aa250 100644
--- a/tools/rootcanal/model/devices/scripted_beacon.h
+++ b/tools/rootcanal/model/devices/scripted_beacon.h
@@ -30,11 +30,11 @@ namespace rootcanal {
 // Pretend to be a lot of beacons by advertising from a file.
 class ScriptedBeacon : public Beacon {
  public:
-  ScriptedBeacon();
+  ScriptedBeacon(const std::vector<std::string>& args);
   virtual ~ScriptedBeacon() = default;
 
-  static std::shared_ptr<Device> Create() {
-    return std::make_shared<ScriptedBeacon>();
+  static std::shared_ptr<Device> Create(const std::vector<std::string>& args) {
+    return std::make_shared<ScriptedBeacon>(args);
   }
 
   // Return a string representation of the type of device.
@@ -46,9 +46,6 @@ class ScriptedBeacon : public Beacon {
     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;
diff --git a/tools/rootcanal/model/devices/sniffer.cc b/tools/rootcanal/model/devices/sniffer.cc
index b57acd17c28..a38607b3855 100644
--- a/tools/rootcanal/model/devices/sniffer.cc
+++ b/tools/rootcanal/model/devices/sniffer.cc
@@ -26,16 +26,12 @@ namespace rootcanal {
 bool Sniffer::registered_ =
     DeviceBoutique::Register("sniffer", &Sniffer::Create);
 
-Sniffer::Sniffer() {}
-
-void Sniffer::Initialize(const vector<std::string>& args) {
-  if (args.size() < 2) return;
-
-  if (Address::FromString(args[1], device_to_sniff_)) {
-    properties_.SetAddress(device_to_sniff_);
+Sniffer::Sniffer(const vector<std::string>& args) {
+  if (args.size() >= 2) {
+    if (Address::FromString(args[1], device_to_sniff_)) {
+      properties_.SetAddress(device_to_sniff_);
+    }
   }
-
-  if (args.size() < 3) return;
 }
 
 void Sniffer::TimerTick() {}
diff --git a/tools/rootcanal/model/devices/sniffer.h b/tools/rootcanal/model/devices/sniffer.h
index f72b4f7d198..268865593b8 100644
--- a/tools/rootcanal/model/devices/sniffer.h
+++ b/tools/rootcanal/model/devices/sniffer.h
@@ -29,16 +29,13 @@ using ::bluetooth::hci::Address;
 
 class Sniffer : public Device {
  public:
-  Sniffer();
+  Sniffer(const std::vector<std::string>& args);
   ~Sniffer() = default;
 
-  static std::shared_ptr<Sniffer> Create() {
-    return std::make_shared<Sniffer>();
+  static std::shared_ptr<Sniffer> Create(const std::vector<std::string>& args) {
+    return std::make_shared<Sniffer>(args);
   }
 
-  // Initialize the device based on the values of |args|.
-  virtual void Initialize(const std::vector<std::string>& args) override;
-
   // Return a string representation of the type of device.
   virtual std::string GetTypeString() const override { return "sniffer"; }
 
diff --git a/tools/rootcanal/model/setup/device_boutique.cc b/tools/rootcanal/model/setup/device_boutique.cc
index d95fe9d55ef..3acb5b5a010 100644
--- a/tools/rootcanal/model/setup/device_boutique.cc
+++ b/tools/rootcanal/model/setup/device_boutique.cc
@@ -22,10 +22,11 @@ using std::vector;
 
 namespace rootcanal {
 
-std::unordered_map<std::string, std::function<std::shared_ptr<Device>()>>&
+std::unordered_map<std::string, std::function<std::shared_ptr<Device>(
+                                    const vector<std::string>&)>>&
 DeviceBoutique::GetMap() {
-  static std::unordered_map<std::string,
-                            std::function<std::shared_ptr<Device>()>>
+  static std::unordered_map<std::string, std::function<std::shared_ptr<Device>(
+                                             const vector<std::string>&)>>
       impl;
   return impl;
 }
@@ -33,9 +34,10 @@ DeviceBoutique::GetMap() {
 // Register a constructor for a device type.
 bool DeviceBoutique::Register(
     const std::string& device_type,
-    const std::function<std::shared_ptr<Device>()> device_constructor) {
+    const std::function<std::shared_ptr<Device>(const vector<std::string>&)>
+        method) {
   LOG_INFO("Registering %s", device_type.c_str());
-  GetMap()[device_type] = device_constructor;
+  GetMap()[device_type] = method;
   return true;
 }
 
@@ -43,15 +45,14 @@ std::shared_ptr<Device> DeviceBoutique::Create(
     const vector<std::string>& args) {
   ASSERT(!args.empty());
 
-  if (GetMap().find(args[0]) == GetMap().end()) {
+  auto device = GetMap().find(args[0]);
+
+  if (device == GetMap().end()) {
     LOG_WARN("No constructor registered for %s", args[0].c_str());
     return std::shared_ptr<Device>(nullptr);
   }
 
-  std::shared_ptr<Device> new_device = GetMap()[args[0]]();
-  if (new_device != nullptr) new_device->Initialize(args);
-
-  return new_device;
+  return device->second(args);
 }
 
 }  // namespace rootcanal
diff --git a/tools/rootcanal/model/setup/device_boutique.h b/tools/rootcanal/model/setup/device_boutique.h
index a07b48c5e04..562003c7373 100644
--- a/tools/rootcanal/model/setup/device_boutique.h
+++ b/tools/rootcanal/model/setup/device_boutique.h
@@ -34,14 +34,16 @@ class DeviceBoutique {
 
   // Register a constructor for a device type.
   static bool Register(const std::string& device_type,
-                       const std::function<std::shared_ptr<Device>()> method);
+                       const std::function<std::shared_ptr<Device>(
+                           const std::vector<std::string>&)>
+                           method);
 
-  // Call the constructor that matches arg[0], then call dev->Initialize(args).
+  // Call the function that matches arg[0] with args
   static std::shared_ptr<Device> Create(const std::vector<std::string>& args);
 
  private:
-  static std::unordered_map<std::string,
-                            std::function<std::shared_ptr<Device>()>>&
+  static std::unordered_map<std::string, std::function<std::shared_ptr<Device>(
+                                             const std::vector<std::string>&)>>&
   GetMap();
 };
 
diff --git a/tools/rootcanal/model/setup/test_model.cc b/tools/rootcanal/model/setup/test_model.cc
index 3b993b43606..feedb9c3793 100644
--- a/tools/rootcanal/model/setup/test_model.cc
+++ b/tools/rootcanal/model/setup/test_model.cc
@@ -173,13 +173,12 @@ void TestModel::AddRemote(const std::string& server, int port,
 
 void TestModel::AddHciConnection(std::shared_ptr<HciSocketDevice> dev) {
   size_t index = Add(std::static_pointer_cast<Device>(dev));
-  std::string addr = "da:4c:10:de:17:";  // Da HCI dev
-  std::stringstream stream;
-  stream << std::setfill('0') << std::setw(2) << std::hex << (index % 256);
-  addr += stream.str();
 
-  dev->Initialize({"IgnoredTypeName", addr});
-  LOG_INFO("initialized %s", addr.c_str());
+  uint8_t raw[] = {0xda, 0x4c, 0x10, 0xde, 0x17, uint8_t(index)};  // Da HCI dev
+  auto addr = Address{{raw[5], raw[4], raw[3], raw[2], raw[1], raw[0]}};
+  dev->SetAddress(addr);
+
+  LOG_INFO("initialized %s", addr.ToString().c_str());
   for (size_t i = 0; i < phys_.size(); i++) {
     AddDeviceToPhy(index, i);
   }
-- 
GitLab