1 /*
2 * Copyright 2022 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 <gtest/gtest.h>
18
19 #include <chrono>
20 #include <cstdint>
21 #include <memory>
22 #include <thread>
23 #include <vector>
24
25 #include "hci/address.h"
26 #include "model/controller/link_layer_controller.h"
27 #include "packets/hci_packets.h"
28 #include "packets/link_layer_packets.h"
29
30 namespace rootcanal {
31
32 using namespace bluetooth::hci;
33
34 class LeScanningFilterDuplicates : public ::testing::Test {
35 public:
LeScanningFilterDuplicates()36 LeScanningFilterDuplicates() {}
37
38 ~LeScanningFilterDuplicates() override = default;
39
SetUp()40 void SetUp() override {
41 event_listener_called_ = 0;
42 controller_.RegisterEventChannel(event_listener_);
43 controller_.RegisterRemoteChannel(remote_listener_);
44
45 auto to_mask = [](auto event) -> uint64_t {
46 return UINT64_C(1) << (static_cast<uint8_t>(event) - 1);
47 };
48
49 // Set event mask to receive (extended) Advertising Reports
50 controller_.SetEventMask(to_mask(EventCode::LE_META_EVENT));
51
52 controller_.SetLeEventMask(to_mask(SubeventCode::LE_ADVERTISING_REPORT) |
53 to_mask(SubeventCode::LE_EXTENDED_ADVERTISING_REPORT) |
54 to_mask(SubeventCode::LE_DIRECTED_ADVERTISING_REPORT));
55 }
56
StartScan(FilterDuplicates filter_duplicates)57 void StartScan(FilterDuplicates filter_duplicates) {
58 ASSERT_EQ(ErrorCode::SUCCESS,
59 controller_.LeSetScanParameters(LeScanType::ACTIVE, 0x4, 0x4,
60 OwnAddressType::PUBLIC_DEVICE_ADDRESS,
61 LeScanningFilterPolicy::ACCEPT_ALL));
62 ASSERT_EQ(ErrorCode::SUCCESS,
63 controller_.LeSetScanEnable(true, filter_duplicates == FilterDuplicates::ENABLED));
64 }
65
StopScan(void)66 void StopScan(void) { ASSERT_EQ(ErrorCode::SUCCESS, controller_.LeSetScanEnable(false, false)); }
67
StartExtendedScan(FilterDuplicates filter_duplicates,uint16_t duration=0,uint16_t period=0)68 void StartExtendedScan(FilterDuplicates filter_duplicates, uint16_t duration = 0,
69 uint16_t period = 0) {
70 bluetooth::hci::ScanningPhyParameters param;
71 param.le_scan_type_ = LeScanType::ACTIVE;
72 param.le_scan_interval_ = 0x4;
73 param.le_scan_window_ = 0x4;
74
75 ASSERT_EQ(ErrorCode::SUCCESS, controller_.LeSetExtendedScanParameters(
76 OwnAddressType::PUBLIC_DEVICE_ADDRESS,
77 LeScanningFilterPolicy::ACCEPT_ALL, 0x1, {param}));
78 ASSERT_EQ(ErrorCode::SUCCESS,
79 controller_.LeSetExtendedScanEnable(true, filter_duplicates, duration, period));
80 }
81
StopExtendedScan(void)82 void StopExtendedScan(void) {
83 ASSERT_EQ(ErrorCode::SUCCESS,
84 controller_.LeSetExtendedScanEnable(false, FilterDuplicates::DISABLED, 0, 0));
85 }
86
87 /// Helper for building ScanResponse packets
LeScanResponse(std::vector<uint8_t> const data={})88 static model::packets::LinkLayerPacketView LeScanResponse(std::vector<uint8_t> const data = {}) {
89 return FromBuilder(model::packets::LeScanResponseBuilder::Create(
90 Address::kEmpty, Address::kEmpty, model::packets::AddressType::PUBLIC, data));
91 }
92
93 /// Helper for building LeLegacyAdvertisingPdu packets
LeLegacyAdvertisingPdu(std::vector<uint8_t> const data={})94 static model::packets::LinkLayerPacketView LeLegacyAdvertisingPdu(
95 std::vector<uint8_t> const data = {}) {
96 return FromBuilder(model::packets::LeLegacyAdvertisingPduBuilder::Create(
97 Address::kEmpty, Address::kEmpty, model::packets::AddressType::PUBLIC,
98 model::packets::AddressType::PUBLIC, model::packets::LegacyAdvertisingType::ADV_IND,
99 data));
100 }
101
102 /// Helper for building LeExtendedAdvertisingPdu packets
LeExtendedAdvertisingPdu(std::vector<uint8_t> const data={})103 static model::packets::LinkLayerPacketView LeExtendedAdvertisingPdu(
104 std::vector<uint8_t> const data = {}) {
105 return FromBuilder(model::packets::LeExtendedAdvertisingPduBuilder::Create(
106 Address::kEmpty, Address::kEmpty, model::packets::AddressType::PUBLIC,
107 model::packets::AddressType::PUBLIC, 0, 1, 0, 0, 0, model::packets::PhyType::LE_1M,
108 model::packets::PhyType::LE_1M, 0, data));
109 }
110
FromBuilder(std::unique_ptr<pdl::packet::Builder> builder)111 static model::packets::LinkLayerPacketView FromBuilder(
112 std::unique_ptr<pdl::packet::Builder> builder) {
113 auto data = std::make_shared<std::vector<uint8_t>>(builder->SerializeToBytes());
114 return model::packets::LinkLayerPacketView::Create(pdl::packet::slice(data));
115 }
116
117 enum Filtered {
118 kFiltered,
119 kReported,
120 };
121
SendPacket(model::packets::LinkLayerPacketView packet)122 void SendPacket(model::packets::LinkLayerPacketView packet) {
123 controller_.IncomingPacket(packet, -90);
124 }
125
126 /// Helper for sending the provided packet to the controller then checking if
127 /// it was reported or filtered
SendPacketAndCheck(model::packets::LinkLayerPacketView packet)128 enum Filtered SendPacketAndCheck(model::packets::LinkLayerPacketView packet) {
129 unsigned const before = event_listener_called_;
130 SendPacket(packet);
131
132 if (before == event_listener_called_) {
133 return kFiltered;
134 }
135 return kReported;
136 }
137
138 protected:
139 Address address_{};
140 ControllerProperties properties_{};
141 LinkLayerController controller_{address_, properties_};
142 static unsigned event_listener_called_;
143
144 private:
event_listener_(std::shared_ptr<EventBuilder>)145 static void event_listener_(std::shared_ptr<EventBuilder> /* event */) {
146 event_listener_called_++;
147 }
148
remote_listener_(std::shared_ptr<model::packets::LinkLayerPacketBuilder>,Phy::Type,int8_t)149 static void remote_listener_(std::shared_ptr<model::packets::LinkLayerPacketBuilder> /* packet */,
150 Phy::Type /* phy */, int8_t /* tx_power */) {}
151 };
152
153 unsigned LeScanningFilterDuplicates::event_listener_called_ = 0;
154
TEST_F(LeScanningFilterDuplicates,LegacyAdvertisingPduDuringLegacyScan)155 TEST_F(LeScanningFilterDuplicates, LegacyAdvertisingPduDuringLegacyScan) {
156 StopScan();
157 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
158
159 StartScan(FilterDuplicates::DISABLED);
160 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
161 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
162
163 StopScan();
164 StartScan(FilterDuplicates::ENABLED);
165 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
166 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
167 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu({0})));
168 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu({0})));
169 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu({0, 1})));
170 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu({0, 1})));
171 }
172
TEST_F(LeScanningFilterDuplicates,LegacyAdvertisingPduDuringExtendedScan)173 TEST_F(LeScanningFilterDuplicates, LegacyAdvertisingPduDuringExtendedScan) {
174 StopExtendedScan();
175 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
176
177 StartExtendedScan(FilterDuplicates::DISABLED);
178 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
179 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
180
181 StopExtendedScan();
182 StartExtendedScan(FilterDuplicates::ENABLED);
183 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
184 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
185 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu({0})));
186 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu({0})));
187 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu({0, 1})));
188 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu({0, 1})));
189 }
190
TEST_F(LeScanningFilterDuplicates,ExtendedAdvertisingPduDuringLegacyScan)191 TEST_F(LeScanningFilterDuplicates, ExtendedAdvertisingPduDuringLegacyScan) {
192 StopScan();
193 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
194
195 StartScan(FilterDuplicates::DISABLED);
196 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
197 }
198
TEST_F(LeScanningFilterDuplicates,ExtendedAdvertisingPduDuringExtendedScan)199 TEST_F(LeScanningFilterDuplicates, ExtendedAdvertisingPduDuringExtendedScan) {
200 StopExtendedScan();
201 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
202
203 StartExtendedScan(FilterDuplicates::DISABLED);
204 ASSERT_EQ(kReported, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
205 ASSERT_EQ(kReported, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
206
207 StopExtendedScan();
208 StartExtendedScan(FilterDuplicates::ENABLED);
209 ASSERT_EQ(kReported, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
210 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
211 ASSERT_EQ(kReported, SendPacketAndCheck(LeExtendedAdvertisingPdu({0})));
212 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeExtendedAdvertisingPdu({0})));
213 ASSERT_EQ(kReported, SendPacketAndCheck(LeExtendedAdvertisingPdu({0, 1})));
214 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeExtendedAdvertisingPdu({0, 1})));
215 }
216
TEST_F(LeScanningFilterDuplicates,LeScanResponseToLegacyAdvertisingDuringLegacyScan)217 TEST_F(LeScanningFilterDuplicates, LeScanResponseToLegacyAdvertisingDuringLegacyScan) {
218 StopScan();
219 SendPacket(LeLegacyAdvertisingPdu());
220 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
221
222 StartScan(FilterDuplicates::DISABLED);
223 SendPacket(LeLegacyAdvertisingPdu());
224 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
225 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
226 SendPacket(LeLegacyAdvertisingPdu());
227 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
228 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
229
230 StopScan();
231 StartScan(FilterDuplicates::ENABLED);
232 SendPacket(LeLegacyAdvertisingPdu());
233 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
234 SendPacket(LeLegacyAdvertisingPdu()); // Duplicate
235 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
236 SendPacket(LeLegacyAdvertisingPdu({0}));
237 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse({0})));
238 SendPacket(LeLegacyAdvertisingPdu({0})); // Duplicate
239 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse({0})));
240 SendPacket(LeLegacyAdvertisingPdu({0, 1}));
241 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse({0, 1})));
242 SendPacket(LeLegacyAdvertisingPdu({0, 1})); // Duplicate
243 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse({0, 1})));
244 }
245
TEST_F(LeScanningFilterDuplicates,LeScanResponseToLegacyAdvertisingDuringExtendedScan)246 TEST_F(LeScanningFilterDuplicates, LeScanResponseToLegacyAdvertisingDuringExtendedScan) {
247 StopExtendedScan();
248 SendPacket(LeLegacyAdvertisingPdu());
249 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
250
251 StartExtendedScan(FilterDuplicates::DISABLED);
252 SendPacket(LeLegacyAdvertisingPdu());
253 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
254 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
255 SendPacket(LeLegacyAdvertisingPdu());
256 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
257 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
258
259 StopExtendedScan();
260 StartExtendedScan(FilterDuplicates::ENABLED);
261 SendPacket(LeLegacyAdvertisingPdu());
262 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
263 SendPacket(LeLegacyAdvertisingPdu()); // Duplicate
264 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
265 SendPacket(LeLegacyAdvertisingPdu({0}));
266 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse({0})));
267 SendPacket(LeLegacyAdvertisingPdu({0})); // Duplicate
268 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse({0})));
269 SendPacket(LeLegacyAdvertisingPdu({0, 1}));
270 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse({0, 1})));
271 SendPacket(LeLegacyAdvertisingPdu({0, 1})); // Duplicate
272 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse({0, 1})));
273 }
274
TEST_F(LeScanningFilterDuplicates,LeScanResponseToExtendedAdvertisingDuringLegacyScan)275 TEST_F(LeScanningFilterDuplicates, LeScanResponseToExtendedAdvertisingDuringLegacyScan) {
276 StopScan();
277 SendPacket(LeExtendedAdvertisingPdu());
278 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
279
280 StartScan(FilterDuplicates::DISABLED);
281 SendPacket(LeExtendedAdvertisingPdu());
282 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
283 SendPacket(LeExtendedAdvertisingPdu());
284 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
285 }
286
TEST_F(LeScanningFilterDuplicates,LeScanResponseToExtendedAdvertisingDuringExtendedScan)287 TEST_F(LeScanningFilterDuplicates, LeScanResponseToExtendedAdvertisingDuringExtendedScan) {
288 StopExtendedScan();
289 SendPacket(LeExtendedAdvertisingPdu());
290 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
291
292 StartExtendedScan(FilterDuplicates::DISABLED);
293 SendPacket(LeExtendedAdvertisingPdu());
294 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
295 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
296 SendPacket(LeExtendedAdvertisingPdu());
297 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
298 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
299
300 StopExtendedScan();
301 StartExtendedScan(FilterDuplicates::ENABLED);
302 SendPacket(LeExtendedAdvertisingPdu());
303 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
304 SendPacket(LeExtendedAdvertisingPdu()); // Duplicate
305 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
306 SendPacket(LeExtendedAdvertisingPdu({0}));
307 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse({0})));
308 SendPacket(LeExtendedAdvertisingPdu({0})); // Duplicate
309 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse({0})));
310 SendPacket(LeExtendedAdvertisingPdu({0, 1}));
311 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse({0, 1})));
312 SendPacket(LeExtendedAdvertisingPdu({0, 1})); // Duplicate
313 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse({0, 1})));
314 }
315
TEST_F(LeScanningFilterDuplicates,HistoryClearedBetweenLegacyScans)316 TEST_F(LeScanningFilterDuplicates, HistoryClearedBetweenLegacyScans) {
317 StopScan();
318 StartScan(FilterDuplicates::ENABLED);
319 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
320 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
321 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
322 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
323
324 StopScan();
325 StartScan(FilterDuplicates::ENABLED);
326 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
327 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
328 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
329 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
330 }
331
TEST_F(LeScanningFilterDuplicates,HistoryClearedBetweenExtendedScans)332 TEST_F(LeScanningFilterDuplicates, HistoryClearedBetweenExtendedScans) {
333 StopExtendedScan();
334 StartExtendedScan(FilterDuplicates::ENABLED);
335 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
336 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
337 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
338 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
339 ASSERT_EQ(kReported, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
340 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse({0})));
341 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
342 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse({0})));
343
344 StopExtendedScan();
345 StartExtendedScan(FilterDuplicates::ENABLED);
346 ASSERT_EQ(kReported, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
347 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse()));
348 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeLegacyAdvertisingPdu()));
349 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse()));
350 ASSERT_EQ(kReported, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
351 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse({0})));
352 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
353 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse({0})));
354 }
355
TEST_F(LeScanningFilterDuplicates,ResetHistoryAfterEachPeriod)356 TEST_F(LeScanningFilterDuplicates, ResetHistoryAfterEachPeriod) {
357 StopExtendedScan();
358 // Minimal period is 1.28 seconds
359 StartExtendedScan(FilterDuplicates::RESET_EACH_PERIOD, 100, 1);
360 ASSERT_EQ(kReported, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
361 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse({0})));
362 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
363 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse({0})));
364
365 std::this_thread::sleep_for(std::chrono::milliseconds(1300));
366 controller_.Tick();
367
368 ASSERT_EQ(kReported, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
369 ASSERT_EQ(kReported, SendPacketAndCheck(LeScanResponse({0})));
370 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeExtendedAdvertisingPdu()));
371 ASSERT_EQ(kFiltered, SendPacketAndCheck(LeScanResponse({0})));
372 }
373 } // namespace rootcanal
374