xref: /aosp_15_r20/tools/netsim/src/hci/bluetooth_facade.cc (revision cf78ab8cffb8fc9207af348f23af247fb04370a6)
1*cf78ab8cSAndroid Build Coastguard Worker // Copyright 2022 The Android Open Source Project
2*cf78ab8cSAndroid Build Coastguard Worker //
3*cf78ab8cSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*cf78ab8cSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*cf78ab8cSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*cf78ab8cSAndroid Build Coastguard Worker //
7*cf78ab8cSAndroid Build Coastguard Worker //      http://www.apache.org/licenses/LICENSE-2.0
8*cf78ab8cSAndroid Build Coastguard Worker //
9*cf78ab8cSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*cf78ab8cSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*cf78ab8cSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*cf78ab8cSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*cf78ab8cSAndroid Build Coastguard Worker // limitations under the License.
14*cf78ab8cSAndroid Build Coastguard Worker 
15*cf78ab8cSAndroid Build Coastguard Worker #include "hci/bluetooth_facade.h"
16*cf78ab8cSAndroid Build Coastguard Worker 
17*cf78ab8cSAndroid Build Coastguard Worker #include <sys/types.h>
18*cf78ab8cSAndroid Build Coastguard Worker 
19*cf78ab8cSAndroid Build Coastguard Worker #include <array>
20*cf78ab8cSAndroid Build Coastguard Worker #include <cassert>
21*cf78ab8cSAndroid Build Coastguard Worker #include <chrono>
22*cf78ab8cSAndroid Build Coastguard Worker #include <cstdint>
23*cf78ab8cSAndroid Build Coastguard Worker #include <cstring>
24*cf78ab8cSAndroid Build Coastguard Worker #include <future>
25*cf78ab8cSAndroid Build Coastguard Worker #include <iostream>
26*cf78ab8cSAndroid Build Coastguard Worker #include <memory>
27*cf78ab8cSAndroid Build Coastguard Worker #include <unordered_map>
28*cf78ab8cSAndroid Build Coastguard Worker #include <utility>
29*cf78ab8cSAndroid Build Coastguard Worker 
30*cf78ab8cSAndroid Build Coastguard Worker #include "hci/address.h"
31*cf78ab8cSAndroid Build Coastguard Worker #include "hci/hci_packet_transport.h"
32*cf78ab8cSAndroid Build Coastguard Worker #include "model/setup/async_manager.h"
33*cf78ab8cSAndroid Build Coastguard Worker #include "model/setup/test_command_handler.h"
34*cf78ab8cSAndroid Build Coastguard Worker #include "model/setup/test_model.h"
35*cf78ab8cSAndroid Build Coastguard Worker #include "netsim-daemon/src/ffi.rs.h"
36*cf78ab8cSAndroid Build Coastguard Worker #include "netsim/config.pb.h"
37*cf78ab8cSAndroid Build Coastguard Worker #include "rust/cxx.h"
38*cf78ab8cSAndroid Build Coastguard Worker #include "util/filesystem.h"
39*cf78ab8cSAndroid Build Coastguard Worker #include "util/log.h"
40*cf78ab8cSAndroid Build Coastguard Worker 
41*cf78ab8cSAndroid Build Coastguard Worker #ifndef NETSIM_ANDROID_EMULATOR
42*cf78ab8cSAndroid Build Coastguard Worker #include "net/posix/posix_async_socket_server.h"
43*cf78ab8cSAndroid Build Coastguard Worker #endif
44*cf78ab8cSAndroid Build Coastguard Worker 
45*cf78ab8cSAndroid Build Coastguard Worker namespace rootcanal::log {
46*cf78ab8cSAndroid Build Coastguard Worker void SetLogColorEnable(bool);
47*cf78ab8cSAndroid Build Coastguard Worker }
48*cf78ab8cSAndroid Build Coastguard Worker 
49*cf78ab8cSAndroid Build Coastguard Worker namespace netsim::hci::facade {
50*cf78ab8cSAndroid Build Coastguard Worker 
51*cf78ab8cSAndroid Build Coastguard Worker int8_t SimComputeRssi(int send_id, int recv_id, int8_t tx_power);
52*cf78ab8cSAndroid Build Coastguard Worker void IncrTx(uint32_t send_id, rootcanal::Phy::Type phy_type);
53*cf78ab8cSAndroid Build Coastguard Worker void IncrRx(uint32_t receive_id, rootcanal::Phy::Type phy_type);
54*cf78ab8cSAndroid Build Coastguard Worker 
55*cf78ab8cSAndroid Build Coastguard Worker using namespace std::literals;
56*cf78ab8cSAndroid Build Coastguard Worker using namespace rootcanal;
57*cf78ab8cSAndroid Build Coastguard Worker 
58*cf78ab8cSAndroid Build Coastguard Worker using rootcanal::PhyDevice;
59*cf78ab8cSAndroid Build Coastguard Worker using rootcanal::PhyLayer;
60*cf78ab8cSAndroid Build Coastguard Worker 
61*cf78ab8cSAndroid Build Coastguard Worker class SimPhyLayer : public PhyLayer {
62*cf78ab8cSAndroid Build Coastguard Worker   // for constructor inheritance
63*cf78ab8cSAndroid Build Coastguard Worker   using PhyLayer::PhyLayer;
64*cf78ab8cSAndroid Build Coastguard Worker 
65*cf78ab8cSAndroid Build Coastguard Worker   // Overrides ComputeRssi in PhyLayerFactory to provide
66*cf78ab8cSAndroid Build Coastguard Worker   // simulated RSSI information using actual spatial
67*cf78ab8cSAndroid Build Coastguard Worker   // device positions.
ComputeRssi(PhyDevice::Identifier sender_id,PhyDevice::Identifier receiver_id,int8_t tx_power)68*cf78ab8cSAndroid Build Coastguard Worker   int8_t ComputeRssi(PhyDevice::Identifier sender_id,
69*cf78ab8cSAndroid Build Coastguard Worker                      PhyDevice::Identifier receiver_id,
70*cf78ab8cSAndroid Build Coastguard Worker                      int8_t tx_power) override {
71*cf78ab8cSAndroid Build Coastguard Worker     return SimComputeRssi(sender_id, receiver_id, tx_power);
72*cf78ab8cSAndroid Build Coastguard Worker   }
73*cf78ab8cSAndroid Build Coastguard Worker 
74*cf78ab8cSAndroid Build Coastguard Worker   // Check if the device is present in the phy_devices
Contains(PhyDevice::Identifier device_id,const std::list<std::shared_ptr<rootcanal::PhyDevice>> & phy_devices)75*cf78ab8cSAndroid Build Coastguard Worker   static bool Contains(
76*cf78ab8cSAndroid Build Coastguard Worker       PhyDevice::Identifier device_id,
77*cf78ab8cSAndroid Build Coastguard Worker       const std::list<std::shared_ptr<rootcanal::PhyDevice>> &phy_devices) {
78*cf78ab8cSAndroid Build Coastguard Worker     return std::any_of(
79*cf78ab8cSAndroid Build Coastguard Worker         phy_devices.begin(), phy_devices.end(),
80*cf78ab8cSAndroid Build Coastguard Worker         [device_id](const auto &device) { return device->id == device_id; });
81*cf78ab8cSAndroid Build Coastguard Worker   }
82*cf78ab8cSAndroid Build Coastguard Worker 
83*cf78ab8cSAndroid Build Coastguard Worker   // Overrides Send in PhyLayerFactory to add Rx/Tx statistics.
Send(std::vector<uint8_t> const & packet,int8_t tx_power,PhyDevice::Identifier sender_id)84*cf78ab8cSAndroid Build Coastguard Worker   void Send(std::vector<uint8_t> const &packet, int8_t tx_power,
85*cf78ab8cSAndroid Build Coastguard Worker             PhyDevice::Identifier sender_id) override {
86*cf78ab8cSAndroid Build Coastguard Worker     // Skip if the sender's phy is in the "down" state. Prevents all outgoing
87*cf78ab8cSAndroid Build Coastguard Worker     // messages including advertisements occurring when the radio is down.
88*cf78ab8cSAndroid Build Coastguard Worker     if (!Contains(sender_id, phy_devices_)) {
89*cf78ab8cSAndroid Build Coastguard Worker       return;
90*cf78ab8cSAndroid Build Coastguard Worker     }
91*cf78ab8cSAndroid Build Coastguard Worker     IncrTx(sender_id, type);
92*cf78ab8cSAndroid Build Coastguard Worker     for (const auto &device : phy_devices_) {
93*cf78ab8cSAndroid Build Coastguard Worker       if (sender_id != device->id) {
94*cf78ab8cSAndroid Build Coastguard Worker         IncrRx(device->id, type);
95*cf78ab8cSAndroid Build Coastguard Worker         device->Receive(packet, type,
96*cf78ab8cSAndroid Build Coastguard Worker                         ComputeRssi(sender_id, device->id, tx_power));
97*cf78ab8cSAndroid Build Coastguard Worker       }
98*cf78ab8cSAndroid Build Coastguard Worker     }
99*cf78ab8cSAndroid Build Coastguard Worker   }
100*cf78ab8cSAndroid Build Coastguard Worker };
101*cf78ab8cSAndroid Build Coastguard Worker 
102*cf78ab8cSAndroid Build Coastguard Worker class SimTestModel : public rootcanal::TestModel {
103*cf78ab8cSAndroid Build Coastguard Worker   // for constructor inheritance
104*cf78ab8cSAndroid Build Coastguard Worker   using rootcanal::TestModel::TestModel;
105*cf78ab8cSAndroid Build Coastguard Worker 
CreatePhyLayer(PhyLayer::Identifier id,rootcanal::Phy::Type type)106*cf78ab8cSAndroid Build Coastguard Worker   std::unique_ptr<rootcanal::PhyLayer> CreatePhyLayer(
107*cf78ab8cSAndroid Build Coastguard Worker       PhyLayer::Identifier id, rootcanal::Phy::Type type) override {
108*cf78ab8cSAndroid Build Coastguard Worker     return std::make_unique<SimPhyLayer>(id, type);
109*cf78ab8cSAndroid Build Coastguard Worker   }
110*cf78ab8cSAndroid Build Coastguard Worker };
111*cf78ab8cSAndroid Build Coastguard Worker 
112*cf78ab8cSAndroid Build Coastguard Worker size_t phy_low_energy_index_;
113*cf78ab8cSAndroid Build Coastguard Worker size_t phy_classic_index_;
114*cf78ab8cSAndroid Build Coastguard Worker 
115*cf78ab8cSAndroid Build Coastguard Worker bool gStarted = false;
116*cf78ab8cSAndroid Build Coastguard Worker std::shared_ptr<rootcanal::AsyncManager> gAsyncManager;
117*cf78ab8cSAndroid Build Coastguard Worker rootcanal::AsyncUserId gSocketUserId{};
118*cf78ab8cSAndroid Build Coastguard Worker std::shared_ptr<SimTestModel> gTestModel;
119*cf78ab8cSAndroid Build Coastguard Worker std::shared_ptr<rootcanal::configuration::Controller> controller_proto_;
120*cf78ab8cSAndroid Build Coastguard Worker 
121*cf78ab8cSAndroid Build Coastguard Worker #ifndef NETSIM_ANDROID_EMULATOR
122*cf78ab8cSAndroid Build Coastguard Worker // test port
123*cf78ab8cSAndroid Build Coastguard Worker std::unique_ptr<rootcanal::TestCommandHandler> gTestChannel;
124*cf78ab8cSAndroid Build Coastguard Worker std::unique_ptr<rootcanal::TestChannelTransport> gTestChannelTransport;
125*cf78ab8cSAndroid Build Coastguard Worker std::shared_ptr<AsyncDataChannelServer> gTestSocketServer;
126*cf78ab8cSAndroid Build Coastguard Worker bool gTestChannelOpen{false};
127*cf78ab8cSAndroid Build Coastguard Worker constexpr int kDefaultTestPort = 7500;
128*cf78ab8cSAndroid Build Coastguard Worker #endif
129*cf78ab8cSAndroid Build Coastguard Worker 
130*cf78ab8cSAndroid Build Coastguard Worker namespace {
131*cf78ab8cSAndroid Build Coastguard Worker #ifndef NETSIM_ANDROID_EMULATOR
132*cf78ab8cSAndroid Build Coastguard Worker 
133*cf78ab8cSAndroid Build Coastguard Worker using ::android::net::PosixAsyncSocketServer;
134*cf78ab8cSAndroid Build Coastguard Worker 
SetUpTestChannel(uint16_t instance_num)135*cf78ab8cSAndroid Build Coastguard Worker void SetUpTestChannel(uint16_t instance_num) {
136*cf78ab8cSAndroid Build Coastguard Worker   gTestSocketServer = std::make_shared<PosixAsyncSocketServer>(
137*cf78ab8cSAndroid Build Coastguard Worker       kDefaultTestPort + instance_num - 1, gAsyncManager.get());
138*cf78ab8cSAndroid Build Coastguard Worker 
139*cf78ab8cSAndroid Build Coastguard Worker   gTestChannel = std::make_unique<rootcanal::TestCommandHandler>(*gTestModel);
140*cf78ab8cSAndroid Build Coastguard Worker 
141*cf78ab8cSAndroid Build Coastguard Worker   gTestChannelTransport = std::make_unique<rootcanal::TestChannelTransport>();
142*cf78ab8cSAndroid Build Coastguard Worker   gTestChannelTransport->RegisterCommandHandler(
143*cf78ab8cSAndroid Build Coastguard Worker       [](const std::string &name, const std::vector<std::string> &args) {
144*cf78ab8cSAndroid Build Coastguard Worker         gAsyncManager->ExecAsync(gSocketUserId, std::chrono::milliseconds(0),
145*cf78ab8cSAndroid Build Coastguard Worker                                  [name, args]() {
146*cf78ab8cSAndroid Build Coastguard Worker                                    std::string args_str = "";
147*cf78ab8cSAndroid Build Coastguard Worker                                    for (auto arg : args) args_str += " " + arg;
148*cf78ab8cSAndroid Build Coastguard Worker                                    if (name == "END_SIMULATION") {
149*cf78ab8cSAndroid Build Coastguard Worker                                    } else {
150*cf78ab8cSAndroid Build Coastguard Worker                                      gTestChannel->HandleCommand(name, args);
151*cf78ab8cSAndroid Build Coastguard Worker                                    }
152*cf78ab8cSAndroid Build Coastguard Worker                                  });
153*cf78ab8cSAndroid Build Coastguard Worker       });
154*cf78ab8cSAndroid Build Coastguard Worker 
155*cf78ab8cSAndroid Build Coastguard Worker   bool transport_configured = gTestChannelTransport->SetUp(
156*cf78ab8cSAndroid Build Coastguard Worker       gTestSocketServer, [](std::shared_ptr<AsyncDataChannel> conn_fd,
157*cf78ab8cSAndroid Build Coastguard Worker                             AsyncDataChannelServer *server) {
158*cf78ab8cSAndroid Build Coastguard Worker         BtsLogInfo("Test channel connection accepted.");
159*cf78ab8cSAndroid Build Coastguard Worker         server->StartListening();
160*cf78ab8cSAndroid Build Coastguard Worker         if (gTestChannelOpen) {
161*cf78ab8cSAndroid Build Coastguard Worker           BtsLogWarn("Only one connection at a time is supported");
162*cf78ab8cSAndroid Build Coastguard Worker           rootcanal::TestChannelTransport::SendResponse(
163*cf78ab8cSAndroid Build Coastguard Worker               conn_fd, "The connection is broken");
164*cf78ab8cSAndroid Build Coastguard Worker           return false;
165*cf78ab8cSAndroid Build Coastguard Worker         }
166*cf78ab8cSAndroid Build Coastguard Worker         gTestChannelOpen = true;
167*cf78ab8cSAndroid Build Coastguard Worker         gTestChannel->RegisterSendResponse(
168*cf78ab8cSAndroid Build Coastguard Worker             [conn_fd](const std::string &response) {
169*cf78ab8cSAndroid Build Coastguard Worker               rootcanal::TestChannelTransport::SendResponse(conn_fd, response);
170*cf78ab8cSAndroid Build Coastguard Worker             });
171*cf78ab8cSAndroid Build Coastguard Worker 
172*cf78ab8cSAndroid Build Coastguard Worker         conn_fd->WatchForNonBlockingRead([](AsyncDataChannel *conn_fd) {
173*cf78ab8cSAndroid Build Coastguard Worker           gTestChannelTransport->OnCommandReady(
174*cf78ab8cSAndroid Build Coastguard Worker               conn_fd, []() { gTestChannelOpen = false; });
175*cf78ab8cSAndroid Build Coastguard Worker         });
176*cf78ab8cSAndroid Build Coastguard Worker         return false;
177*cf78ab8cSAndroid Build Coastguard Worker       });
178*cf78ab8cSAndroid Build Coastguard Worker 
179*cf78ab8cSAndroid Build Coastguard Worker   gTestChannel->SetTimerPeriod({"5"});
180*cf78ab8cSAndroid Build Coastguard Worker   gTestChannel->StartTimer({});
181*cf78ab8cSAndroid Build Coastguard Worker 
182*cf78ab8cSAndroid Build Coastguard Worker   if (!transport_configured) {
183*cf78ab8cSAndroid Build Coastguard Worker     BtsLogError("Failed to set up test channel.");
184*cf78ab8cSAndroid Build Coastguard Worker     return;
185*cf78ab8cSAndroid Build Coastguard Worker   }
186*cf78ab8cSAndroid Build Coastguard Worker 
187*cf78ab8cSAndroid Build Coastguard Worker   BtsLogInfo("Set up test channel.");
188*cf78ab8cSAndroid Build Coastguard Worker }
189*cf78ab8cSAndroid Build Coastguard Worker #endif
190*cf78ab8cSAndroid Build Coastguard Worker 
191*cf78ab8cSAndroid Build Coastguard Worker }  // namespace
192*cf78ab8cSAndroid Build Coastguard Worker 
193*cf78ab8cSAndroid Build Coastguard Worker // Initialize the rootcanal library.
Start(const rust::Slice<::std::uint8_t const> proto_bytes,uint16_t instance_num)194*cf78ab8cSAndroid Build Coastguard Worker void Start(const rust::Slice<::std::uint8_t const> proto_bytes,
195*cf78ab8cSAndroid Build Coastguard Worker            uint16_t instance_num) {
196*cf78ab8cSAndroid Build Coastguard Worker   if (gStarted) return;
197*cf78ab8cSAndroid Build Coastguard Worker 
198*cf78ab8cSAndroid Build Coastguard Worker   // output is to a file, so no color wanted
199*cf78ab8cSAndroid Build Coastguard Worker   rootcanal::log::SetLogColorEnable(false);
200*cf78ab8cSAndroid Build Coastguard Worker 
201*cf78ab8cSAndroid Build Coastguard Worker   config::Bluetooth config;
202*cf78ab8cSAndroid Build Coastguard Worker   config.ParseFromArray(proto_bytes.data(), proto_bytes.size());
203*cf78ab8cSAndroid Build Coastguard Worker   controller_proto_ = std::make_shared<rootcanal::configuration::Controller>(
204*cf78ab8cSAndroid Build Coastguard Worker       config.properties());
205*cf78ab8cSAndroid Build Coastguard Worker 
206*cf78ab8cSAndroid Build Coastguard Worker   // When emulators restore from a snapshot the PacketStreamer connection to
207*cf78ab8cSAndroid Build Coastguard Worker   // netsim is recreated with a new (uninitialized) Rootcanal device. However
208*cf78ab8cSAndroid Build Coastguard Worker   // the Android Bluetooth Stack does not re-initialize the controller. Our
209*cf78ab8cSAndroid Build Coastguard Worker   // solution is for Rootcanal to recognize that it is receiving HCI commands
210*cf78ab8cSAndroid Build Coastguard Worker   // before a HCI Reset. The flag below causes a hardware error event that
211*cf78ab8cSAndroid Build Coastguard Worker   // triggers the Reset from the Bluetooth Stack.
212*cf78ab8cSAndroid Build Coastguard Worker 
213*cf78ab8cSAndroid Build Coastguard Worker   controller_proto_->mutable_quirks()->set_hardware_error_before_reset(true);
214*cf78ab8cSAndroid Build Coastguard Worker 
215*cf78ab8cSAndroid Build Coastguard Worker   gAsyncManager = std::make_shared<rootcanal::AsyncManager>();
216*cf78ab8cSAndroid Build Coastguard Worker   // Get a user ID for tasks scheduled within the test environment.
217*cf78ab8cSAndroid Build Coastguard Worker   gSocketUserId = gAsyncManager->GetNextUserId();
218*cf78ab8cSAndroid Build Coastguard Worker 
219*cf78ab8cSAndroid Build Coastguard Worker   gTestModel = std::make_unique<SimTestModel>(
220*cf78ab8cSAndroid Build Coastguard Worker       std::bind(&rootcanal::AsyncManager::GetNextUserId, gAsyncManager),
221*cf78ab8cSAndroid Build Coastguard Worker       std::bind(&rootcanal::AsyncManager::ExecAsync, gAsyncManager,
222*cf78ab8cSAndroid Build Coastguard Worker                 std::placeholders::_1, std::placeholders::_2,
223*cf78ab8cSAndroid Build Coastguard Worker                 std::placeholders::_3),
224*cf78ab8cSAndroid Build Coastguard Worker       std::bind(&rootcanal::AsyncManager::ExecAsyncPeriodically, gAsyncManager,
225*cf78ab8cSAndroid Build Coastguard Worker                 std::placeholders::_1, std::placeholders::_2,
226*cf78ab8cSAndroid Build Coastguard Worker                 std::placeholders::_3, std::placeholders::_4),
227*cf78ab8cSAndroid Build Coastguard Worker       std::bind(&rootcanal::AsyncManager::CancelAsyncTasksFromUser,
228*cf78ab8cSAndroid Build Coastguard Worker                 gAsyncManager, std::placeholders::_1),
229*cf78ab8cSAndroid Build Coastguard Worker       std::bind(&rootcanal::AsyncManager::CancelAsyncTask, gAsyncManager,
230*cf78ab8cSAndroid Build Coastguard Worker                 std::placeholders::_1),
231*cf78ab8cSAndroid Build Coastguard Worker       [](const std::string & /* server */, int /* port */,
232*cf78ab8cSAndroid Build Coastguard Worker          rootcanal::Phy::Type /* phy_type */) { return nullptr; });
233*cf78ab8cSAndroid Build Coastguard Worker 
234*cf78ab8cSAndroid Build Coastguard Worker   // Disable Address Reuse if '--disable_address_reuse' flag is true
235*cf78ab8cSAndroid Build Coastguard Worker   // Enable Address Reuse if 'address_reuse' is true
236*cf78ab8cSAndroid Build Coastguard Worker   if (config.has_disable_address_reuse()) {
237*cf78ab8cSAndroid Build Coastguard Worker     gTestModel->SetReuseDeviceAddresses(!config.disable_address_reuse());
238*cf78ab8cSAndroid Build Coastguard Worker   }
239*cf78ab8cSAndroid Build Coastguard Worker 
240*cf78ab8cSAndroid Build Coastguard Worker   // NOTE: 0:BR_EDR, 1:LOW_ENERGY. The order is used by bluetooth CTS.
241*cf78ab8cSAndroid Build Coastguard Worker   phy_classic_index_ = gTestModel->AddPhy(rootcanal::Phy::Type::BR_EDR);
242*cf78ab8cSAndroid Build Coastguard Worker   phy_low_energy_index_ = gTestModel->AddPhy(rootcanal::Phy::Type::LOW_ENERGY);
243*cf78ab8cSAndroid Build Coastguard Worker 
244*cf78ab8cSAndroid Build Coastguard Worker   // TODO: Remove test channel.
245*cf78ab8cSAndroid Build Coastguard Worker #ifdef NETSIM_ANDROID_EMULATOR
246*cf78ab8cSAndroid Build Coastguard Worker   auto testCommands = rootcanal::TestCommandHandler(*gTestModel);
247*cf78ab8cSAndroid Build Coastguard Worker   testCommands.RegisterSendResponse([](const std::string &) {});
248*cf78ab8cSAndroid Build Coastguard Worker   testCommands.SetTimerPeriod({"5"});
249*cf78ab8cSAndroid Build Coastguard Worker   testCommands.StartTimer({});
250*cf78ab8cSAndroid Build Coastguard Worker #else
251*cf78ab8cSAndroid Build Coastguard Worker   SetUpTestChannel(instance_num);
252*cf78ab8cSAndroid Build Coastguard Worker #endif
253*cf78ab8cSAndroid Build Coastguard Worker   gStarted = true;
254*cf78ab8cSAndroid Build Coastguard Worker };
255*cf78ab8cSAndroid Build Coastguard Worker 
256*cf78ab8cSAndroid Build Coastguard Worker // Resets the root canal library.
Stop()257*cf78ab8cSAndroid Build Coastguard Worker void Stop() {
258*cf78ab8cSAndroid Build Coastguard Worker   // TODO: Fix TestModel::Reset() in test_model.cc.
259*cf78ab8cSAndroid Build Coastguard Worker   // gTestModel->Reset();
260*cf78ab8cSAndroid Build Coastguard Worker   gStarted = false;
261*cf78ab8cSAndroid Build Coastguard Worker }
262*cf78ab8cSAndroid Build Coastguard Worker 
AddDeviceToPhy(uint32_t rootcanal_id,bool isLowEnergy)263*cf78ab8cSAndroid Build Coastguard Worker void AddDeviceToPhy(uint32_t rootcanal_id, bool isLowEnergy) {
264*cf78ab8cSAndroid Build Coastguard Worker   auto phy_index = (isLowEnergy) ? phy_low_energy_index_ : phy_classic_index_;
265*cf78ab8cSAndroid Build Coastguard Worker   gTestModel->AddDeviceToPhy(rootcanal_id, phy_index);
266*cf78ab8cSAndroid Build Coastguard Worker }
267*cf78ab8cSAndroid Build Coastguard Worker 
RemoveDeviceFromPhy(uint32_t rootcanal_id,bool isLowEnergy)268*cf78ab8cSAndroid Build Coastguard Worker void RemoveDeviceFromPhy(uint32_t rootcanal_id, bool isLowEnergy) {
269*cf78ab8cSAndroid Build Coastguard Worker   auto phy_index = (isLowEnergy) ? phy_low_energy_index_ : phy_classic_index_;
270*cf78ab8cSAndroid Build Coastguard Worker   gTestModel->RemoveDeviceFromPhy(rootcanal_id, phy_index);
271*cf78ab8cSAndroid Build Coastguard Worker }
272*cf78ab8cSAndroid Build Coastguard Worker 
273*cf78ab8cSAndroid Build Coastguard Worker class ChipInfo {
274*cf78ab8cSAndroid Build Coastguard Worker  public:
275*cf78ab8cSAndroid Build Coastguard Worker   uint32_t chip_id;
276*cf78ab8cSAndroid Build Coastguard Worker   std::shared_ptr<model::Chip::Bluetooth> model;
277*cf78ab8cSAndroid Build Coastguard Worker   int le_tx_count = 0;
278*cf78ab8cSAndroid Build Coastguard Worker   int classic_tx_count = 0;
279*cf78ab8cSAndroid Build Coastguard Worker   int le_rx_count = 0;
280*cf78ab8cSAndroid Build Coastguard Worker   int classic_rx_count = 0;
281*cf78ab8cSAndroid Build Coastguard Worker   std::shared_ptr<rootcanal::configuration::Controller> controller_proto;
282*cf78ab8cSAndroid Build Coastguard Worker   std::unique_ptr<rootcanal::ControllerProperties> controller_properties;
283*cf78ab8cSAndroid Build Coastguard Worker 
ChipInfo(uint32_t chip_id,std::shared_ptr<model::Chip::Bluetooth> model)284*cf78ab8cSAndroid Build Coastguard Worker   ChipInfo(uint32_t chip_id, std::shared_ptr<model::Chip::Bluetooth> model)
285*cf78ab8cSAndroid Build Coastguard Worker       : chip_id(chip_id), model(model) {}
ChipInfo(uint32_t chip_id,std::shared_ptr<model::Chip::Bluetooth> model,std::shared_ptr<rootcanal::configuration::Controller> controller_proto,std::unique_ptr<rootcanal::ControllerProperties> controller_properties)286*cf78ab8cSAndroid Build Coastguard Worker   ChipInfo(
287*cf78ab8cSAndroid Build Coastguard Worker       uint32_t chip_id, std::shared_ptr<model::Chip::Bluetooth> model,
288*cf78ab8cSAndroid Build Coastguard Worker       std::shared_ptr<rootcanal::configuration::Controller> controller_proto,
289*cf78ab8cSAndroid Build Coastguard Worker       std::unique_ptr<rootcanal::ControllerProperties> controller_properties)
290*cf78ab8cSAndroid Build Coastguard Worker       : chip_id(chip_id),
291*cf78ab8cSAndroid Build Coastguard Worker         model(model),
292*cf78ab8cSAndroid Build Coastguard Worker         controller_proto(std::move(controller_proto)),
293*cf78ab8cSAndroid Build Coastguard Worker         controller_properties(std::move(controller_properties)) {}
294*cf78ab8cSAndroid Build Coastguard Worker };
295*cf78ab8cSAndroid Build Coastguard Worker 
296*cf78ab8cSAndroid Build Coastguard Worker std::unordered_map<uint32_t, std::shared_ptr<ChipInfo>> id_to_chip_info_;
297*cf78ab8cSAndroid Build Coastguard Worker 
Get(uint32_t id)298*cf78ab8cSAndroid Build Coastguard Worker model::Chip::Bluetooth Get(uint32_t id) {
299*cf78ab8cSAndroid Build Coastguard Worker   model::Chip::Bluetooth model;
300*cf78ab8cSAndroid Build Coastguard Worker   if (id_to_chip_info_.find(id) != id_to_chip_info_.end()) {
301*cf78ab8cSAndroid Build Coastguard Worker     model.CopyFrom(*id_to_chip_info_[id]->model.get());
302*cf78ab8cSAndroid Build Coastguard Worker     auto chip_info = id_to_chip_info_[id];
303*cf78ab8cSAndroid Build Coastguard Worker     model.mutable_classic()->set_tx_count(chip_info->classic_tx_count);
304*cf78ab8cSAndroid Build Coastguard Worker     model.mutable_classic()->set_rx_count(chip_info->classic_rx_count);
305*cf78ab8cSAndroid Build Coastguard Worker     model.mutable_low_energy()->set_tx_count(chip_info->le_tx_count);
306*cf78ab8cSAndroid Build Coastguard Worker     model.mutable_low_energy()->set_rx_count(chip_info->le_rx_count);
307*cf78ab8cSAndroid Build Coastguard Worker     if (chip_info->controller_proto) {
308*cf78ab8cSAndroid Build Coastguard Worker       model.mutable_bt_properties()->CopyFrom(*chip_info->controller_proto);
309*cf78ab8cSAndroid Build Coastguard Worker     }
310*cf78ab8cSAndroid Build Coastguard Worker   }
311*cf78ab8cSAndroid Build Coastguard Worker   return model;
312*cf78ab8cSAndroid Build Coastguard Worker }
313*cf78ab8cSAndroid Build Coastguard Worker 
Reset(uint32_t id)314*cf78ab8cSAndroid Build Coastguard Worker void Reset(uint32_t id) {
315*cf78ab8cSAndroid Build Coastguard Worker   if (auto it = id_to_chip_info_.find(id); it != id_to_chip_info_.end()) {
316*cf78ab8cSAndroid Build Coastguard Worker     auto chip_info = it->second;
317*cf78ab8cSAndroid Build Coastguard Worker     chip_info->le_tx_count = 0;
318*cf78ab8cSAndroid Build Coastguard Worker     chip_info->le_rx_count = 0;
319*cf78ab8cSAndroid Build Coastguard Worker     chip_info->classic_tx_count = 0;
320*cf78ab8cSAndroid Build Coastguard Worker     chip_info->classic_rx_count = 0;
321*cf78ab8cSAndroid Build Coastguard Worker   }
322*cf78ab8cSAndroid Build Coastguard Worker   // First remove LOW_ENERGY and BR_EDR Phy
323*cf78ab8cSAndroid Build Coastguard Worker   RemoveDeviceFromPhy(id, true);
324*cf78ab8cSAndroid Build Coastguard Worker   RemoveDeviceFromPhy(id, false);
325*cf78ab8cSAndroid Build Coastguard Worker   // Add to LOW_ENERGY and BR_EDR Phy
326*cf78ab8cSAndroid Build Coastguard Worker   AddDeviceToPhy(id, true);
327*cf78ab8cSAndroid Build Coastguard Worker   AddDeviceToPhy(id, false);
328*cf78ab8cSAndroid Build Coastguard Worker }
329*cf78ab8cSAndroid Build Coastguard Worker 
Remove(uint32_t id)330*cf78ab8cSAndroid Build Coastguard Worker void Remove(uint32_t id) {
331*cf78ab8cSAndroid Build Coastguard Worker   BtsLogInfo("Removing HCI chip rootcanal_id: %d.", id);
332*cf78ab8cSAndroid Build Coastguard Worker   id_to_chip_info_.erase(id);
333*cf78ab8cSAndroid Build Coastguard Worker   // Call the transport close callback. This invokes HciDevice::Close and
334*cf78ab8cSAndroid Build Coastguard Worker   // TestModel close callback.
335*cf78ab8cSAndroid Build Coastguard Worker   gAsyncManager->ExecAsync(gSocketUserId, std::chrono::milliseconds(0), [id]() {
336*cf78ab8cSAndroid Build Coastguard Worker     // rootcanal will call HciPacketTransport::Close().
337*cf78ab8cSAndroid Build Coastguard Worker     HciPacketTransport::Remove(id);
338*cf78ab8cSAndroid Build Coastguard Worker   });
339*cf78ab8cSAndroid Build Coastguard Worker }
340*cf78ab8cSAndroid Build Coastguard Worker 
341*cf78ab8cSAndroid Build Coastguard Worker // Rename AddChip(model::Chip, device, transport)
342*cf78ab8cSAndroid Build Coastguard Worker 
Add(uint32_t chip_id,const std::string & address_string,const rust::Slice<::std::uint8_t const> controller_proto_bytes)343*cf78ab8cSAndroid Build Coastguard Worker uint32_t Add(uint32_t chip_id, const std::string &address_string,
344*cf78ab8cSAndroid Build Coastguard Worker              const rust::Slice<::std::uint8_t const> controller_proto_bytes) {
345*cf78ab8cSAndroid Build Coastguard Worker   auto transport = std::make_shared<HciPacketTransport>(chip_id, gAsyncManager);
346*cf78ab8cSAndroid Build Coastguard Worker 
347*cf78ab8cSAndroid Build Coastguard Worker   std::shared_ptr<rootcanal::configuration::Controller> controller_proto =
348*cf78ab8cSAndroid Build Coastguard Worker       controller_proto_;
349*cf78ab8cSAndroid Build Coastguard Worker   // If the Bluetooth Controller protobuf is provided, we use the provided
350*cf78ab8cSAndroid Build Coastguard Worker   if (controller_proto_bytes.size() != 0) {
351*cf78ab8cSAndroid Build Coastguard Worker     rootcanal::configuration::Controller custom_proto;
352*cf78ab8cSAndroid Build Coastguard Worker     custom_proto.ParseFromArray(controller_proto_bytes.data(),
353*cf78ab8cSAndroid Build Coastguard Worker                                 controller_proto_bytes.size());
354*cf78ab8cSAndroid Build Coastguard Worker     BtsLogInfo("chip_id: %d has rootcanal Controller configuration: %s",
355*cf78ab8cSAndroid Build Coastguard Worker                chip_id, custom_proto.ShortDebugString().c_str());
356*cf78ab8cSAndroid Build Coastguard Worker 
357*cf78ab8cSAndroid Build Coastguard Worker     // When emulators restore from a snapshot the PacketStreamer connection to
358*cf78ab8cSAndroid Build Coastguard Worker     // netsim is recreated with a new (uninitialized) Rootcanal device. However
359*cf78ab8cSAndroid Build Coastguard Worker     // the Android Bluetooth Stack does not re-initialize the controller. Our
360*cf78ab8cSAndroid Build Coastguard Worker     // solution is for Rootcanal to recognize that it is receiving HCI commands
361*cf78ab8cSAndroid Build Coastguard Worker     // before a HCI Reset. The flag below causes a hardware error event that
362*cf78ab8cSAndroid Build Coastguard Worker     // triggers the Reset from the Bluetooth Stack.
363*cf78ab8cSAndroid Build Coastguard Worker     custom_proto.mutable_quirks()->set_hardware_error_before_reset(true);
364*cf78ab8cSAndroid Build Coastguard Worker 
365*cf78ab8cSAndroid Build Coastguard Worker     controller_proto =
366*cf78ab8cSAndroid Build Coastguard Worker         std::make_shared<rootcanal::configuration::Controller>(custom_proto);
367*cf78ab8cSAndroid Build Coastguard Worker   }
368*cf78ab8cSAndroid Build Coastguard Worker   std::unique_ptr<rootcanal::ControllerProperties> controller_properties =
369*cf78ab8cSAndroid Build Coastguard Worker       std::make_unique<rootcanal::ControllerProperties>(*controller_proto);
370*cf78ab8cSAndroid Build Coastguard Worker 
371*cf78ab8cSAndroid Build Coastguard Worker   auto hci_device =
372*cf78ab8cSAndroid Build Coastguard Worker       std::make_shared<rootcanal::HciDevice>(transport, *controller_properties);
373*cf78ab8cSAndroid Build Coastguard Worker 
374*cf78ab8cSAndroid Build Coastguard Worker   // Pass netsim::hci::facade::ReportInvalidPacket signature into hci_device
375*cf78ab8cSAndroid Build Coastguard Worker   hci_device->RegisterInvalidPacketHandler(
376*cf78ab8cSAndroid Build Coastguard Worker       [](uint32_t rootcanal_id, rootcanal::InvalidPacketReason reason,
377*cf78ab8cSAndroid Build Coastguard Worker          std::string description, const std::vector<uint8_t> &packet) {
378*cf78ab8cSAndroid Build Coastguard Worker         netsim::hci::facade::ReportInvalidPacket(
379*cf78ab8cSAndroid Build Coastguard Worker             rootcanal_id, static_cast<int32_t>(reason), description, packet);
380*cf78ab8cSAndroid Build Coastguard Worker       });
381*cf78ab8cSAndroid Build Coastguard Worker 
382*cf78ab8cSAndroid Build Coastguard Worker   // Use the `AsyncManager` to ensure that the `AddHciConnection` method is
383*cf78ab8cSAndroid Build Coastguard Worker   // invoked atomically, preventing data races.
384*cf78ab8cSAndroid Build Coastguard Worker   std::promise<uint32_t> rootcanal_id_promise;
385*cf78ab8cSAndroid Build Coastguard Worker   auto rootcanal_id_future = rootcanal_id_promise.get_future();
386*cf78ab8cSAndroid Build Coastguard Worker 
387*cf78ab8cSAndroid Build Coastguard Worker   std::optional<Address> address_option;
388*cf78ab8cSAndroid Build Coastguard Worker   if (address_string != "") {
389*cf78ab8cSAndroid Build Coastguard Worker     address_option = rootcanal::Address::FromString(address_string);
390*cf78ab8cSAndroid Build Coastguard Worker   }
391*cf78ab8cSAndroid Build Coastguard Worker   gAsyncManager->ExecAsync(
392*cf78ab8cSAndroid Build Coastguard Worker       gSocketUserId, std::chrono::milliseconds(0),
393*cf78ab8cSAndroid Build Coastguard Worker       [hci_device, &rootcanal_id_promise, address_option]() {
394*cf78ab8cSAndroid Build Coastguard Worker         rootcanal_id_promise.set_value(
395*cf78ab8cSAndroid Build Coastguard Worker             gTestModel->AddHciConnection(hci_device, address_option));
396*cf78ab8cSAndroid Build Coastguard Worker       });
397*cf78ab8cSAndroid Build Coastguard Worker   auto rootcanal_id = rootcanal_id_future.get();
398*cf78ab8cSAndroid Build Coastguard Worker 
399*cf78ab8cSAndroid Build Coastguard Worker   HciPacketTransport::Add(rootcanal_id, transport);
400*cf78ab8cSAndroid Build Coastguard Worker   BtsLogInfo("Creating HCI rootcanal_id: %d for chip_id: %d", rootcanal_id,
401*cf78ab8cSAndroid Build Coastguard Worker              chip_id);
402*cf78ab8cSAndroid Build Coastguard Worker 
403*cf78ab8cSAndroid Build Coastguard Worker   auto model = std::make_shared<model::Chip::Bluetooth>();
404*cf78ab8cSAndroid Build Coastguard Worker   model->mutable_classic()->set_state(true);
405*cf78ab8cSAndroid Build Coastguard Worker   model->mutable_low_energy()->set_state(true);
406*cf78ab8cSAndroid Build Coastguard Worker 
407*cf78ab8cSAndroid Build Coastguard Worker   id_to_chip_info_.emplace(rootcanal_id, std::make_shared<ChipInfo>(
408*cf78ab8cSAndroid Build Coastguard Worker                                              chip_id, model, controller_proto,
409*cf78ab8cSAndroid Build Coastguard Worker                                              std::move(controller_properties)));
410*cf78ab8cSAndroid Build Coastguard Worker   return rootcanal_id;
411*cf78ab8cSAndroid Build Coastguard Worker }
412*cf78ab8cSAndroid Build Coastguard Worker 
RemoveRustDevice(uint32_t rootcanal_id)413*cf78ab8cSAndroid Build Coastguard Worker void RemoveRustDevice(uint32_t rootcanal_id) {
414*cf78ab8cSAndroid Build Coastguard Worker   gTestModel->RemoveDevice(rootcanal_id);
415*cf78ab8cSAndroid Build Coastguard Worker }
416*cf78ab8cSAndroid Build Coastguard Worker 
AddRustDevice(uint32_t chip_id,rust::Box<DynRustBluetoothChipCallbacks> callbacks,const std::string & type,const std::string & address)417*cf78ab8cSAndroid Build Coastguard Worker rust::Box<AddRustDeviceResult> AddRustDevice(
418*cf78ab8cSAndroid Build Coastguard Worker     uint32_t chip_id, rust::Box<DynRustBluetoothChipCallbacks> callbacks,
419*cf78ab8cSAndroid Build Coastguard Worker     const std::string &type, const std::string &address) {
420*cf78ab8cSAndroid Build Coastguard Worker   auto rust_device =
421*cf78ab8cSAndroid Build Coastguard Worker       std::make_shared<RustDevice>(std::move(callbacks), type, address);
422*cf78ab8cSAndroid Build Coastguard Worker 
423*cf78ab8cSAndroid Build Coastguard Worker   // TODO: Use the `AsyncManager` to ensure that the `AddDevice` and
424*cf78ab8cSAndroid Build Coastguard Worker   // `AddDeviceToPhy` methods are invoked atomically, preventing data races.
425*cf78ab8cSAndroid Build Coastguard Worker   // For unknown reason, use `AsyncManager` hangs.
426*cf78ab8cSAndroid Build Coastguard Worker   auto rootcanal_id = gTestModel->AddDevice(rust_device);
427*cf78ab8cSAndroid Build Coastguard Worker   gTestModel->AddDeviceToPhy(rootcanal_id, phy_low_energy_index_);
428*cf78ab8cSAndroid Build Coastguard Worker 
429*cf78ab8cSAndroid Build Coastguard Worker   auto model = std::make_shared<model::Chip::Bluetooth>();
430*cf78ab8cSAndroid Build Coastguard Worker   // Only enable ble for beacon.
431*cf78ab8cSAndroid Build Coastguard Worker   model->mutable_low_energy()->set_state(true);
432*cf78ab8cSAndroid Build Coastguard Worker   id_to_chip_info_.emplace(rootcanal_id,
433*cf78ab8cSAndroid Build Coastguard Worker                            std::make_shared<ChipInfo>(chip_id, model));
434*cf78ab8cSAndroid Build Coastguard Worker   return CreateAddRustDeviceResult(
435*cf78ab8cSAndroid Build Coastguard Worker       rootcanal_id, std::make_unique<RustBluetoothChip>(rust_device));
436*cf78ab8cSAndroid Build Coastguard Worker }
437*cf78ab8cSAndroid Build Coastguard Worker 
SetRustDeviceAddress(uint32_t rootcanal_id,std::array<uint8_t,rootcanal::Address::kLength> address)438*cf78ab8cSAndroid Build Coastguard Worker void SetRustDeviceAddress(
439*cf78ab8cSAndroid Build Coastguard Worker     uint32_t rootcanal_id,
440*cf78ab8cSAndroid Build Coastguard Worker     std::array<uint8_t, rootcanal::Address::kLength> address) {
441*cf78ab8cSAndroid Build Coastguard Worker   uint8_t addr[rootcanal::Address::kLength];
442*cf78ab8cSAndroid Build Coastguard Worker   std::memcpy(addr, address.data(), rootcanal::Address::kLength);
443*cf78ab8cSAndroid Build Coastguard Worker   gTestModel->SetDeviceAddress(rootcanal_id, rootcanal::Address(addr));
444*cf78ab8cSAndroid Build Coastguard Worker }
445*cf78ab8cSAndroid Build Coastguard Worker 
IncrTx(uint32_t id,rootcanal::Phy::Type phy_type)446*cf78ab8cSAndroid Build Coastguard Worker void IncrTx(uint32_t id, rootcanal::Phy::Type phy_type) {
447*cf78ab8cSAndroid Build Coastguard Worker   if (auto it = id_to_chip_info_.find(id); it != id_to_chip_info_.end()) {
448*cf78ab8cSAndroid Build Coastguard Worker     auto chip_info = it->second;
449*cf78ab8cSAndroid Build Coastguard Worker     if (phy_type == rootcanal::Phy::Type::LOW_ENERGY) {
450*cf78ab8cSAndroid Build Coastguard Worker       chip_info->le_tx_count++;
451*cf78ab8cSAndroid Build Coastguard Worker     } else {
452*cf78ab8cSAndroid Build Coastguard Worker       chip_info->classic_tx_count++;
453*cf78ab8cSAndroid Build Coastguard Worker     }
454*cf78ab8cSAndroid Build Coastguard Worker   }
455*cf78ab8cSAndroid Build Coastguard Worker }
456*cf78ab8cSAndroid Build Coastguard Worker 
IncrRx(uint32_t id,rootcanal::Phy::Type phy_type)457*cf78ab8cSAndroid Build Coastguard Worker void IncrRx(uint32_t id, rootcanal::Phy::Type phy_type) {
458*cf78ab8cSAndroid Build Coastguard Worker   if (auto it = id_to_chip_info_.find(id); it != id_to_chip_info_.end()) {
459*cf78ab8cSAndroid Build Coastguard Worker     auto chip_info = it->second;
460*cf78ab8cSAndroid Build Coastguard Worker     if (phy_type == rootcanal::Phy::Type::LOW_ENERGY) {
461*cf78ab8cSAndroid Build Coastguard Worker       chip_info->le_rx_count++;
462*cf78ab8cSAndroid Build Coastguard Worker     } else {
463*cf78ab8cSAndroid Build Coastguard Worker       chip_info->classic_rx_count++;
464*cf78ab8cSAndroid Build Coastguard Worker     }
465*cf78ab8cSAndroid Build Coastguard Worker   }
466*cf78ab8cSAndroid Build Coastguard Worker }
467*cf78ab8cSAndroid Build Coastguard Worker 
468*cf78ab8cSAndroid Build Coastguard Worker // TODO: Make SimComputeRssi invoke netsim::device::GetDistanceRust with dev
469*cf78ab8cSAndroid Build Coastguard Worker // flag
SimComputeRssi(int send_id,int recv_id,int8_t tx_power)470*cf78ab8cSAndroid Build Coastguard Worker int8_t SimComputeRssi(int send_id, int recv_id, int8_t tx_power) {
471*cf78ab8cSAndroid Build Coastguard Worker   if (id_to_chip_info_.find(send_id) == id_to_chip_info_.end() ||
472*cf78ab8cSAndroid Build Coastguard Worker       id_to_chip_info_.find(recv_id) == id_to_chip_info_.end()) {
473*cf78ab8cSAndroid Build Coastguard Worker #ifdef NETSIM_ANDROID_EMULATOR
474*cf78ab8cSAndroid Build Coastguard Worker     // NOTE: Ignore log messages in Cuttlefish for beacon devices created by
475*cf78ab8cSAndroid Build Coastguard Worker     // test channel.
476*cf78ab8cSAndroid Build Coastguard Worker     BtsLogWarn("Missing chip_info");
477*cf78ab8cSAndroid Build Coastguard Worker #endif
478*cf78ab8cSAndroid Build Coastguard Worker     return tx_power;
479*cf78ab8cSAndroid Build Coastguard Worker   }
480*cf78ab8cSAndroid Build Coastguard Worker   auto a = id_to_chip_info_[send_id]->chip_id;
481*cf78ab8cSAndroid Build Coastguard Worker   auto b = id_to_chip_info_[recv_id]->chip_id;
482*cf78ab8cSAndroid Build Coastguard Worker   auto distance = netsim::device::GetDistanceCxx(a, b);
483*cf78ab8cSAndroid Build Coastguard Worker   return netsim::DistanceToRssi(tx_power, distance);
484*cf78ab8cSAndroid Build Coastguard Worker }
485*cf78ab8cSAndroid Build Coastguard Worker 
GetCxx(uint32_t id)486*cf78ab8cSAndroid Build Coastguard Worker rust::Vec<::std::uint8_t> GetCxx(uint32_t id) {
487*cf78ab8cSAndroid Build Coastguard Worker   auto bluetooth = Get(id);
488*cf78ab8cSAndroid Build Coastguard Worker   std::vector<uint8_t> proto_bytes(bluetooth.ByteSizeLong());
489*cf78ab8cSAndroid Build Coastguard Worker   bluetooth.SerializeToArray(proto_bytes.data(), proto_bytes.size());
490*cf78ab8cSAndroid Build Coastguard Worker   rust::Vec<uint8_t> proto_rust_bytes;
491*cf78ab8cSAndroid Build Coastguard Worker   std::copy(proto_bytes.begin(), proto_bytes.end(),
492*cf78ab8cSAndroid Build Coastguard Worker             std::back_inserter(proto_rust_bytes));
493*cf78ab8cSAndroid Build Coastguard Worker   return proto_rust_bytes;
494*cf78ab8cSAndroid Build Coastguard Worker }
495*cf78ab8cSAndroid Build Coastguard Worker 
496*cf78ab8cSAndroid Build Coastguard Worker }  // namespace netsim::hci::facade
497