1 /*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "test_model.h"
18
19 // TODO: Remove when registration works
20 #include "model/devices/beacon.h"
21 #include "model/devices/beacon_swarm.h"
22 #include "model/devices/car_kit.h"
23 #include "model/devices/classic.h"
24 #include "model/devices/keyboard.h"
25 #include "model/devices/remote_loopback_device.h"
26 #include "model/devices/scripted_beacon.h"
27 #include "model/devices/sniffer.h"
28
29 #include <memory>
30
31 #include <stdlib.h>
32 #include <iomanip>
33 #include <iostream>
34
35 #include "base/files/file_util.h"
36 #include "base/json/json_reader.h"
37 #include "base/values.h"
38
39 #include "os/log.h"
40 #include "include/phy.h"
41 #include "model/devices/hci_socket_device.h"
42 #include "model/devices/link_layer_socket_device.h"
43
44 namespace test_vendor_lib {
45
TestModel(std::function<AsyncUserId ()> get_user_id,std::function<AsyncTaskId (AsyncUserId,std::chrono::milliseconds,const TaskCallback &)> event_scheduler,std::function<AsyncTaskId (AsyncUserId,std::chrono::milliseconds,std::chrono::milliseconds,const TaskCallback &)> periodic_event_scheduler,std::function<void (AsyncUserId)> cancel_tasks_from_user,std::function<void (AsyncTaskId)> cancel,std::function<int (const std::string &,int)> connect_to_remote)46 TestModel::TestModel(
47 std::function<AsyncUserId()> get_user_id,
48 std::function<AsyncTaskId(AsyncUserId, std::chrono::milliseconds,
49 const TaskCallback&)>
50 event_scheduler,
51
52 std::function<AsyncTaskId(AsyncUserId, std::chrono::milliseconds,
53 std::chrono::milliseconds, const TaskCallback&)>
54 periodic_event_scheduler,
55
56 std::function<void(AsyncUserId)> cancel_tasks_from_user,
57 std::function<void(AsyncTaskId)> cancel,
58 std::function<int(const std::string&, int)> connect_to_remote)
59 : get_user_id_(std::move(get_user_id)),
60 schedule_task_(std::move(event_scheduler)),
61 schedule_periodic_task_(std::move(periodic_event_scheduler)),
62 cancel_task_(std::move(cancel)),
63 cancel_tasks_from_user_(std::move(cancel_tasks_from_user)),
64 connect_to_remote_(std::move(connect_to_remote)) {
65 model_user_id_ = get_user_id_();
66 // TODO: Remove when registration works!
67 example_devices_.push_back(std::make_shared<Beacon>());
68 example_devices_.push_back(std::make_shared<BeaconSwarm>());
69 example_devices_.push_back(std::make_shared<Keyboard>());
70 example_devices_.push_back(std::make_shared<CarKit>());
71 example_devices_.push_back(std::make_shared<Classic>());
72 example_devices_.push_back(std::make_shared<Sniffer>());
73 example_devices_.push_back(std::make_shared<ScriptedBeacon>());
74 example_devices_.push_back(std::make_shared<RemoteLoopbackDevice>());
75 }
76
SetTimerPeriod(std::chrono::milliseconds new_period)77 void TestModel::SetTimerPeriod(std::chrono::milliseconds new_period) {
78 timer_period_ = new_period;
79
80 if (timer_tick_task_ == kInvalidTaskId) return;
81
82 // Restart the timer with the new period
83 StopTimer();
84 StartTimer();
85 }
86
StartTimer()87 void TestModel::StartTimer() {
88 LOG_INFO("StartTimer()");
89 timer_tick_task_ = schedule_periodic_task_(
90 model_user_id_, std::chrono::milliseconds(0), timer_period_,
91 [this]() { TestModel::TimerTick(); });
92 }
93
StopTimer()94 void TestModel::StopTimer() {
95 LOG_INFO("StopTimer()");
96 cancel_task_(timer_tick_task_);
97 timer_tick_task_ = kInvalidTaskId;
98 }
99
Add(std::shared_ptr<Device> new_dev)100 size_t TestModel::Add(std::shared_ptr<Device> new_dev) {
101 devices_.push_back(std::move(new_dev));
102 return devices_.size() - 1;
103 }
104
Del(size_t dev_index)105 void TestModel::Del(size_t dev_index) {
106 if (dev_index >= devices_.size() || devices_[dev_index] == nullptr) {
107 LOG_WARN("Unknown device %zu", dev_index);
108 return;
109 }
110 schedule_task_(model_user_id_, std::chrono::milliseconds(0),
111 [this, dev_index]() {
112 devices_[dev_index]->UnregisterPhyLayers();
113 devices_[dev_index] = nullptr;
114 });
115 }
116
AddPhy(Phy::Type phy_type)117 size_t TestModel::AddPhy(Phy::Type phy_type) {
118 size_t factory_id = phys_.size();
119 phys_.emplace_back(phy_type, factory_id);
120 return factory_id;
121 }
122
DelPhy(size_t phy_index)123 void TestModel::DelPhy(size_t phy_index) {
124 if (phy_index >= phys_.size()) {
125 LOG_WARN("Unknown phy at index %zu", phy_index);
126 return;
127 }
128 schedule_task_(
129 model_user_id_, std::chrono::milliseconds(0),
130 [this, phy_index]() { phys_[phy_index].UnregisterAllPhyLayers(); });
131 }
132
AddDeviceToPhy(size_t dev_index,size_t phy_index)133 void TestModel::AddDeviceToPhy(size_t dev_index, size_t phy_index) {
134 if (dev_index >= devices_.size() || devices_[dev_index] == nullptr) {
135 LOG_WARN("Unknown device %zu", dev_index);
136 return;
137 }
138 if (phy_index >= phys_.size()) {
139 LOG_WARN("Can't find phy %zu", phy_index);
140 return;
141 }
142 auto dev = devices_[dev_index];
143 dev->RegisterPhyLayer(phys_[phy_index].GetPhyLayer(
144 [dev](model::packets::LinkLayerPacketView packet) {
145 dev->IncomingPacket(std::move(packet));
146 },
147 dev_index));
148 }
149
DelDeviceFromPhy(size_t dev_index,size_t phy_index)150 void TestModel::DelDeviceFromPhy(size_t dev_index, size_t phy_index) {
151 if (dev_index >= devices_.size() || devices_[dev_index] == nullptr) {
152 LOG_WARN("Unknown device %zu", dev_index);
153 return;
154 }
155 if (phy_index >= phys_.size()) {
156 LOG_WARN("Can't find phy %zu", phy_index);
157 return;
158 }
159 schedule_task_(model_user_id_, std::chrono::milliseconds(0),
160 [this, dev_index, phy_index]() {
161 devices_[dev_index]->UnregisterPhyLayer(
162 phys_[phy_index].GetType(),
163 phys_[phy_index].GetFactoryId());
164 });
165 }
166
AddLinkLayerConnection(int socket_fd,Phy::Type phy_type)167 void TestModel::AddLinkLayerConnection(int socket_fd, Phy::Type phy_type) {
168 std::shared_ptr<Device> dev = LinkLayerSocketDevice::Create(socket_fd, phy_type);
169 int index = Add(dev);
170 for (size_t i = 0; i < phys_.size(); i++) {
171 if (phy_type == phys_[i].GetType()) {
172 AddDeviceToPhy(index, i);
173 }
174 }
175 }
176
IncomingLinkLayerConnection(int socket_fd)177 void TestModel::IncomingLinkLayerConnection(int socket_fd) {
178 // TODO: Handle other phys
179 AddLinkLayerConnection(socket_fd, Phy::Type::BR_EDR);
180 }
181
AddRemote(const std::string & server,int port,Phy::Type phy_type)182 void TestModel::AddRemote(const std::string& server, int port, Phy::Type phy_type) {
183 int socket_fd = connect_to_remote_(server, port);
184 if (socket_fd < 0) {
185 return;
186 }
187 AddLinkLayerConnection(socket_fd, phy_type);
188 }
189
IncomingHciConnection(int socket_fd)190 void TestModel::IncomingHciConnection(int socket_fd) {
191 auto dev = HciSocketDevice::Create(socket_fd);
192 size_t index = Add(std::static_pointer_cast<Device>(dev));
193 std::string addr = "da:4c:10:de:17:"; // Da HCI dev
194 std::stringstream stream;
195 stream << std::setfill('0') << std::setw(2) << std::hex << (index % 256);
196 addr += stream.str();
197
198 dev->Initialize({"IgnoredTypeName", addr});
199 LOG_INFO("initialized %s", addr.c_str());
200 for (size_t i = 0; i < phys_.size(); i++) {
201 AddDeviceToPhy(index, i);
202 }
203 AsyncUserId user_id = get_user_id_();
204 dev->RegisterTaskScheduler([user_id, this](std::chrono::milliseconds delay,
205 TaskCallback task_callback) {
206 return schedule_task_(user_id, delay, std::move(task_callback));
207 });
208 dev->RegisterTaskCancel(cancel_task_);
209 dev->RegisterCloseCallback([this, socket_fd, index, user_id] {
210 schedule_task_(user_id, std::chrono::milliseconds(0),
211 [this, socket_fd, index, user_id]() {
212 OnHciConnectionClosed(socket_fd, index, user_id);
213 });
214 });
215 }
216
OnHciConnectionClosed(int socket_fd,size_t index,AsyncUserId user_id)217 void TestModel::OnHciConnectionClosed(int socket_fd, size_t index,
218 AsyncUserId user_id) {
219 if (index >= devices_.size() || devices_[index] == nullptr) {
220 LOG_WARN("Unknown device %zu", index);
221 return;
222 }
223 int close_result = close(socket_fd);
224 ASSERT_LOG(close_result == 0, "can't close: %s", strerror(errno));
225
226 cancel_tasks_from_user_(user_id);
227 devices_[index]->UnregisterPhyLayers();
228 devices_[index] = nullptr;
229 }
230
SetDeviceAddress(size_t index,Address address)231 void TestModel::SetDeviceAddress(size_t index, Address address) {
232 if (index >= devices_.size() || devices_[index] == nullptr) {
233 LOG_WARN("Can't find device %zu", index);
234 return;
235 }
236 devices_[index]->SetAddress(std::move(address));
237 }
238
List()239 const std::string& TestModel::List() {
240 list_string_ = "";
241 list_string_ += " Devices: \r\n";
242 for (size_t i = 0; i < devices_.size(); i++) {
243 list_string_ += " " + std::to_string(i) + ":";
244 if (devices_[i] == nullptr) {
245 list_string_ += " deleted \r\n";
246 } else {
247 list_string_ += devices_[i]->ToString() + " \r\n";
248 }
249 }
250 list_string_ += " Phys: \r\n";
251 for (size_t i = 0; i < phys_.size(); i++) {
252 list_string_ += " " + std::to_string(i) + ":";
253 list_string_ += phys_[i].ToString() + " \r\n";
254 }
255 return list_string_;
256 }
257
TimerTick()258 void TestModel::TimerTick() {
259 for (size_t i = 0; i < devices_.size(); i++) {
260 if (devices_[i] != nullptr) {
261 devices_[i]->TimerTick();
262 }
263 }
264 }
265
Reset()266 void TestModel::Reset() {
267 StopTimer();
268 schedule_task_(model_user_id_, std::chrono::milliseconds(0), [this]() {
269 LOG_INFO("Running Reset task");
270 for (size_t i = 0; i < devices_.size(); i++) {
271 if (devices_[i] != nullptr) {
272 devices_[i]->UnregisterPhyLayers();
273 }
274 }
275 devices_.clear();
276 });
277 }
278
279 } // namespace test_vendor_lib
280