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_command_handler.h"
18 #include "device_boutique.h"
19 #include "phy.h"
20
21 #include <memory>
22
23 #include <stdlib.h>
24
25 #include "base/files/file_util.h"
26 #include "base/json/json_reader.h"
27 #include "base/strings/string_split.h"
28 #include "base/values.h"
29
30 #include "os/log.h"
31 #include "osi/include/osi.h"
32
33 using std::vector;
34
35 namespace test_vendor_lib {
36
TestCommandHandler(TestModel & test_model)37 TestCommandHandler::TestCommandHandler(TestModel& test_model) : model_(test_model) {
38 #define SET_HANDLER(command_name, method) \
39 active_commands_[command_name] = [this](const vector<std::string>& param) { method(param); };
40 SET_HANDLER("add", Add);
41 SET_HANDLER("add_remote", AddRemote);
42 SET_HANDLER("del", Del);
43 SET_HANDLER("add_phy", AddPhy);
44 SET_HANDLER("del_phy", DelPhy);
45 SET_HANDLER("add_device_to_phy", AddDeviceToPhy);
46 SET_HANDLER("del_device_from_phy", DelDeviceFromPhy);
47 SET_HANDLER("list", List);
48 SET_HANDLER("set_device_address", SetDeviceAddress);
49 SET_HANDLER("set_timer_period", SetTimerPeriod);
50 SET_HANDLER("start_timer", StartTimer);
51 SET_HANDLER("stop_timer", StopTimer);
52 SET_HANDLER("reset", Reset);
53 #undef SET_HANDLER
54 }
55
AddDefaults()56 void TestCommandHandler::AddDefaults() {
57 // Add a phy for LE and one for BR/EDR
58 AddPhy({"LOW_ENERGY"});
59 AddPhy({"BR_EDR"});
60
61 // Add the controller to the Phys
62 AddDeviceToPhy({"1", "1"});
63 AddDeviceToPhy({"1", "2"});
64
65 // Add default test devices and add the devices to the phys
66 // Add({"beacon", "be:ac:10:00:00:01", "1000"});
67 // AddDeviceToPhy({"2", "1"});
68
69 // Add({"keyboard", "cc:1c:eb:0a:12:d1", "500"});
70 // AddDeviceToPhy({"3", "1"});
71
72 // Add({"classic", "c1:a5:51:c0:00:01", "22"});
73 // AddDeviceToPhy({"4", "2"});
74
75 // Add({"car_kit", "ca:12:1c:17:00:01", "238"});
76 // AddDeviceToPhy({"5", "2"});
77
78 // Add({"sniffer", "ca:12:1c:17:00:01"});
79 // AddDeviceToPhy({"6", "2"});
80
81 // Add({"sniffer", "3c:5a:b4:04:05:06"});
82 // AddDeviceToPhy({"7", "2"});
83 // Add({"remote_loopback_device", "10:0d:00:ba:c1:06"});
84 // AddDeviceToPhy({"8", "2"});
85 List({});
86
87 SetTimerPeriod({"10"});
88 StartTimer({});
89 }
90
HandleCommand(const std::string & name,const vector<std::string> & args)91 void TestCommandHandler::HandleCommand(const std::string& name, const vector<std::string>& args) {
92 if (active_commands_.count(name) == 0) {
93 response_string_ = "Unhandled command: " + name;
94 send_response_(response_string_);
95 return;
96 }
97 active_commands_[name](args);
98 }
99
FromFile(const std::string & file_name)100 void TestCommandHandler::FromFile(const std::string& file_name) {
101 if (file_name.size() == 0) {
102 return;
103 }
104
105 std::string commands_raw;
106 if (!base::ReadFileToString(base::FilePath(file_name), &commands_raw)) {
107 LOG_ERROR("Error reading commands from file.");
108 return;
109 }
110
111 base::StringPairs command_pairs;
112 base::SplitStringIntoKeyValuePairs(commands_raw, ' ', '\n', &command_pairs);
113 for (const std::pair<std::string, std::string>& p : command_pairs) {
114 auto params = base::SplitString(p.second, " ", base::TRIM_WHITESPACE,
115 base::SPLIT_WANT_NONEMPTY);
116 HandleCommand(p.first, params);
117 }
118 }
119
RegisterSendResponse(const std::function<void (const std::string &)> callback)120 void TestCommandHandler::RegisterSendResponse(const std::function<void(const std::string&)> callback) {
121 send_response_ = callback;
122 send_response_("RegisterSendResponse called");
123 }
124
Add(const vector<std::string> & args)125 void TestCommandHandler::Add(const vector<std::string>& args) {
126 if (args.size() < 1) {
127 response_string_ = "TestCommandHandler 'add' takes an argument";
128 send_response_(response_string_);
129 return;
130 }
131 std::shared_ptr<Device> new_dev = DeviceBoutique::Create(args);
132
133 if (new_dev == NULL) {
134 response_string_ = "TestCommandHandler 'add' " + args[0] + " failed!";
135 send_response_(response_string_);
136 LOG_WARN("%s", response_string_.c_str());
137 return;
138 }
139
140 LOG_INFO("Add %s", new_dev->ToString().c_str());
141 size_t dev_index = model_.Add(new_dev);
142 response_string_ = std::to_string(dev_index) + std::string(":") + new_dev->ToString();
143 send_response_(response_string_);
144 }
145
AddRemote(const vector<std::string> & args)146 void TestCommandHandler::AddRemote(const vector<std::string>& args) {
147 if (args.size() < 3) {
148 response_string_ = "TestCommandHandler usage: add_remote host port phy_type";
149 send_response_(response_string_);
150 return;
151 }
152
153 size_t port = std::stoi(args[1]);
154 Phy::Type phy_type = Phy::Type::BR_EDR;
155 if ("LOW_ENERGY" == args[2]) {
156 phy_type = Phy::Type::LOW_ENERGY;
157 }
158 if (port == 0 || port > 0xffff || args[0].size() < 2) {
159 response_string_ = "TestCommandHandler bad arguments to 'add_remote': ";
160 response_string_ += args[0];
161 response_string_ += "@";
162 response_string_ += args[1];
163 send_response_(response_string_);
164 return;
165 }
166
167 model_.AddRemote(args[0], port, phy_type);
168
169 response_string_ = args[0] + std::string("@") + std::to_string(port);
170 send_response_(response_string_);
171 }
172
Del(const vector<std::string> & args)173 void TestCommandHandler::Del(const vector<std::string>& args) {
174 size_t dev_index = std::stoi(args[0]);
175
176 model_.Del(dev_index);
177 response_string_ = "TestCommandHandler 'del' called with device at index " + std::to_string(dev_index);
178 send_response_(response_string_);
179 }
180
AddPhy(const vector<std::string> & args)181 void TestCommandHandler::AddPhy(const vector<std::string>& args) {
182 if (args[0] == "LOW_ENERGY") {
183 model_.AddPhy(Phy::Type::LOW_ENERGY);
184 } else if (args[0] == "BR_EDR") {
185 model_.AddPhy(Phy::Type::BR_EDR);
186 } else {
187 response_string_ = "TestCommandHandler 'add_phy' with unrecognized type " + args[0];
188 send_response_(response_string_);
189 }
190 }
191
DelPhy(const vector<std::string> & args)192 void TestCommandHandler::DelPhy(const vector<std::string>& args) {
193 size_t phy_index = std::stoi(args[0]);
194
195 model_.DelPhy(phy_index);
196 response_string_ = "TestCommandHandler 'del_phy' called with phy at index " + std::to_string(phy_index);
197 send_response_(response_string_);
198 }
199
AddDeviceToPhy(const vector<std::string> & args)200 void TestCommandHandler::AddDeviceToPhy(const vector<std::string>& args) {
201 if (args.size() != 2) {
202 response_string_ = "TestCommandHandler 'add_device_to_phy' takes two arguments";
203 send_response_(response_string_);
204 return;
205 }
206 size_t dev_index = std::stoi(args[0]);
207 size_t phy_index = std::stoi(args[1]);
208 model_.AddDeviceToPhy(dev_index, phy_index);
209 response_string_ = "TestCommandHandler 'add_device_to_phy' called with device " + std::to_string(dev_index) +
210 " and phy " + std::to_string(phy_index);
211 send_response_(response_string_);
212 return;
213 }
214
DelDeviceFromPhy(const vector<std::string> & args)215 void TestCommandHandler::DelDeviceFromPhy(const vector<std::string>& args) {
216 if (args.size() != 2) {
217 response_string_ = "TestCommandHandler 'del_device_from_phy' takes two arguments";
218 send_response_(response_string_);
219 return;
220 }
221 size_t dev_index = std::stoi(args[0]);
222 size_t phy_index = std::stoi(args[1]);
223 model_.DelDeviceFromPhy(dev_index, phy_index);
224 response_string_ = "TestCommandHandler 'del_device_from_phy' called with device " + std::to_string(dev_index) +
225 " and phy " + std::to_string(phy_index);
226 send_response_(response_string_);
227 return;
228 }
229
List(const vector<std::string> & args)230 void TestCommandHandler::List(const vector<std::string>& args) {
231 if (args.size() > 0) {
232 LOG_INFO("Unused args: arg[0] = %s", args[0].c_str());
233 return;
234 }
235 send_response_(model_.List());
236 }
237
SetDeviceAddress(const vector<std::string> & args)238 void TestCommandHandler::SetDeviceAddress(const vector<std::string>& args) {
239 if (args.size() != 2) {
240 response_string_ = "TestCommandHandler 'set_device_address' takes two arguments";
241 send_response_(response_string_);
242 return;
243 }
244 size_t device_id = std::stoi(args[0]);
245 Address device_address{};
246 Address::FromString(args[1], device_address);
247 model_.SetDeviceAddress(device_id, device_address);
248 response_string_ = "set_device_address " + args[0];
249 response_string_ += " ";
250 response_string_ += args[1];
251 send_response_(response_string_);
252 }
253
SetTimerPeriod(const vector<std::string> & args)254 void TestCommandHandler::SetTimerPeriod(const vector<std::string>& args) {
255 if (args.size() != 1) {
256 LOG_INFO("SetTimerPeriod takes 1 argument");
257 }
258 size_t period = std::stoi(args[0]);
259 if (period != 0) {
260 response_string_ = "set timer period to ";
261 response_string_ += args[0];
262 model_.SetTimerPeriod(std::chrono::milliseconds(period));
263 } else {
264 response_string_ = "invalid timer period ";
265 response_string_ += args[0];
266 }
267 send_response_(response_string_);
268 }
269
StartTimer(const vector<std::string> & args)270 void TestCommandHandler::StartTimer(const vector<std::string>& args) {
271 if (args.size() > 0) {
272 LOG_INFO("Unused args: arg[0] = %s", args[0].c_str());
273 }
274 model_.StartTimer();
275 response_string_ = "timer started";
276 send_response_(response_string_);
277 }
278
StopTimer(const vector<std::string> & args)279 void TestCommandHandler::StopTimer(const vector<std::string>& args) {
280 if (args.size() > 0) {
281 LOG_INFO("Unused args: arg[0] = %s", args[0].c_str());
282 }
283 model_.StopTimer();
284 response_string_ = "timer stopped";
285 send_response_(response_string_);
286 }
287
Reset(const std::vector<std::string> & args)288 void TestCommandHandler::Reset(const std::vector<std::string>& args) {
289 if (args.size() > 0) {
290 LOG_INFO("Unused args: arg[0] = %s", args[0].c_str());
291 }
292 model_.Reset();
293 response_string_ = "model reset";
294 send_response_(response_string_);
295 }
296
297 } // namespace test_vendor_lib
298