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