• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 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 "hci/le_scanning_reassembler.h"
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 using ::testing::_;
23 using ::testing::Eq;
24 
25 using namespace bluetooth;
26 using namespace std::chrono_literals;
27 
28 namespace bluetooth::hci {
29 
30 // Event type fields.
31 static constexpr uint16_t kScannable = 0x2;
32 static constexpr uint16_t kScanResponse = 0x8;
33 static constexpr uint16_t kLegacy = 0x10;
34 static constexpr uint8_t kComplete = 0x0;
35 static constexpr uint8_t kContinuation = 0x20;
36 static constexpr uint8_t kTruncated = 0x40;
37 
38 // Defaults for other fields.
39 static constexpr uint8_t kSidNotPresent = 0xff;
40 
41 // Test addresses.
42 static const Address kTestAddress = Address({0, 1, 2, 3, 4, 5});
43 
44 class LeScanningReassemblerTest : public ::testing::Test {
45  public:
46   LeScanningReassembler reassembler_;
47 };
48 
TEST_F(LeScanningReassemblerTest,trim_advertising_data)49 TEST_F(LeScanningReassemblerTest, trim_advertising_data) {
50   // TrimAdvertisingData should filter out empty entries.
51   ASSERT_EQ(
52       LeScanningReassembler::TrimAdvertisingData({0x1, 0x2, 0x0, 0x0, 0x3, 0x4, 0x5, 0x6}),
53       std::vector<uint8_t>({0x1, 0x2, 0x3, 0x4, 0x5, 0x6}));
54 
55   // TrimAdvertisingData should remove trailing zeros.
56   ASSERT_EQ(
57       LeScanningReassembler::TrimAdvertisingData({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x0, 0x0}),
58       std::vector<uint8_t>({0x1, 0x2, 0x3, 0x4, 0x5, 0x6}));
59 
60   // TrimAdvertisingData should remove overflowing entries.
61   ASSERT_EQ(
62       LeScanningReassembler::TrimAdvertisingData({0x1, 0x2, 0x3, 0x4, 0x5}),
63       std::vector<uint8_t>({0x1, 0x2}));
64 }
65 
TEST_F(LeScanningReassemblerTest,non_scannable_legacy_advertising)66 TEST_F(LeScanningReassemblerTest, non_scannable_legacy_advertising) {
67   // Test non scannable legacy advertising.
68   ASSERT_EQ(
69       reassembler_.ProcessAdvertisingReport(
70           kLegacy | kComplete,
71           (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
72           kTestAddress,
73           kSidNotPresent,
74           {0x1, 0x2}),
75       std::vector<uint8_t>({0x1, 0x2}));
76 }
77 
TEST_F(LeScanningReassemblerTest,scannable_legacy_advertising)78 TEST_F(LeScanningReassemblerTest, scannable_legacy_advertising) {
79   // Test scannable legacy advertising with well formed advertising and
80   // scan response payload.
81   ASSERT_FALSE(reassembler_
82                    .ProcessAdvertisingReport(
83                        kLegacy | kScannable | kComplete,
84                        (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
85                        kTestAddress,
86                        kSidNotPresent,
87                        {0x1, 0x2})
88                    .has_value());
89 
90   ASSERT_EQ(
91       reassembler_.ProcessAdvertisingReport(
92           kLegacy | kScannable | kScanResponse | kComplete,
93           (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
94           kTestAddress,
95           kSidNotPresent,
96           {0x3, 0x4, 0x5, 0x6}),
97       std::vector<uint8_t>({0x1, 0x2, 0x3, 0x4, 0x5, 0x6}));
98 
99   // Test scannable legacy advertising with padding after the
100   // advertising and scan response data.
101   ASSERT_FALSE(reassembler_
102                    .ProcessAdvertisingReport(
103                        kLegacy | kScannable | kComplete,
104                        (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
105                        kTestAddress,
106                        kSidNotPresent,
107                        {0x1, 0x2, 0x0, 0x0})
108                    .has_value());
109 
110   ASSERT_EQ(
111       reassembler_.ProcessAdvertisingReport(
112           kLegacy | kScannable | kScanResponse | kComplete,
113           (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
114           kTestAddress,
115           kSidNotPresent,
116           {0x3, 0x4, 0x5, 0x6, 0x0, 0x0}),
117       std::vector<uint8_t>({0x1, 0x2, 0x3, 0x4, 0x5, 0x6}));
118 }
119 
TEST_F(LeScanningReassemblerTest,non_scannable_extended_advertising)120 TEST_F(LeScanningReassemblerTest, non_scannable_extended_advertising) {
121   // Test fragmented non scannable extended advertising.
122   // The split may occur in the middle of a GAP entry.
123   ASSERT_FALSE(reassembler_
124                    .ProcessAdvertisingReport(
125                        kContinuation,
126                        (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
127                        kTestAddress,
128                        kSidNotPresent,
129                        {0x1, 0x2, 0x3})
130                    .has_value());
131 
132   ASSERT_EQ(
133       reassembler_.ProcessAdvertisingReport(
134           kComplete,
135           (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
136           kTestAddress,
137           kSidNotPresent,
138           {0x4, 0x5, 0x6}),
139       std::vector<uint8_t>({0x1, 0x2, 0x3, 0x4, 0x5, 0x6}));
140 
141   // Test fragmented and truncated non scannable extended advertising.
142   // The split may occur in the middle of a GAP entry.
143   ASSERT_FALSE(reassembler_
144                    .ProcessAdvertisingReport(
145                        kContinuation,
146                        (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
147                        kTestAddress,
148                        kSidNotPresent,
149                        {0x1, 0x2, 0x3})
150                    .has_value());
151 
152   ASSERT_EQ(
153       reassembler_.ProcessAdvertisingReport(
154           kTruncated,
155           (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
156           kTestAddress,
157           kSidNotPresent,
158           {0x4, 0x5, 0x6, 0x7}),
159       std::vector<uint8_t>({0x1, 0x2, 0x3, 0x4, 0x5, 0x6}));
160 
161   // Test fragmented and truncated anonymous, non scannable
162   // extended advertising. The split may occur in the middle of a GAP entry.
163   ASSERT_FALSE(reassembler_
164                    .ProcessAdvertisingReport(
165                        kContinuation,
166                        (uint8_t)DirectAdvertisingAddressType::NO_ADDRESS_PROVIDED,
167                        Address::kEmpty,
168                        kSidNotPresent,
169                        {0x1, 0x2, 0x3})
170                    .has_value());
171 
172   ASSERT_EQ(
173       reassembler_.ProcessAdvertisingReport(
174           kTruncated,
175           (uint8_t)DirectAdvertisingAddressType::NO_ADDRESS_PROVIDED,
176           Address::kEmpty,
177           kSidNotPresent,
178           {0x4, 0x5, 0x6, 0x7}),
179       std::vector<uint8_t>({0x1, 0x2, 0x3, 0x4, 0x5, 0x6}));
180 }
181 
TEST_F(LeScanningReassemblerTest,scannable_extended_advertising)182 TEST_F(LeScanningReassemblerTest, scannable_extended_advertising) {
183   // Test fragmented scannable extended advertising.
184   // The split may occur in the middle of a GAP entry.
185   // Padding may occur at the end of the advertising data.
186   ASSERT_FALSE(reassembler_
187                    .ProcessAdvertisingReport(
188                        kScannable | kContinuation,
189                        (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
190                        kTestAddress,
191                        kSidNotPresent,
192                        {0x1, 0x2, 0x3})
193                    .has_value());
194 
195   ASSERT_FALSE(reassembler_
196                    .ProcessAdvertisingReport(
197                        kScannable | kComplete,
198                        (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
199                        kTestAddress,
200                        kSidNotPresent,
201                        {0x4, 0x5, 0x6, 0x0, 0x0})
202                    .has_value());
203 
204   ASSERT_FALSE(reassembler_
205                    .ProcessAdvertisingReport(
206                        kContinuation,
207                        (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
208                        kTestAddress,
209                        kSidNotPresent,
210                        {0x7, 0x8, 0x9, 0xa})
211                    .has_value());
212 
213   ASSERT_EQ(
214       reassembler_.ProcessAdvertisingReport(
215           kTruncated,
216           (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
217           kTestAddress,
218           kSidNotPresent,
219           {0xb, 0xc, 0xd, 0xe, 0x0}),
220       std::vector<uint8_t>({0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe}));
221 }
222 
TEST_F(LeScanningReassemblerTest,ignore_scan_responses)223 TEST_F(LeScanningReassemblerTest, ignore_scan_responses) {
224   // Scan response without advertising data are ignored.
225   ASSERT_FALSE(reassembler_
226                    .ProcessAdvertisingReport(
227                        kScannable | kScanResponse | kComplete,
228                        (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
229                        kTestAddress,
230                        kSidNotPresent,
231                        {0x1, 0x2})
232                    .has_value());
233 
234   ASSERT_EQ(
235       reassembler_.ProcessAdvertisingReport(
236           kComplete,
237           (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
238           kTestAddress,
239           kSidNotPresent,
240           {0x1, 0x2}),
241       std::vector<uint8_t>({0x1, 0x2}));
242 
243   // The option ignore_scan_responses forces scan responses to be dropped.
244   reassembler_.SetIgnoreScanResponses(true);
245   ASSERT_EQ(
246       reassembler_.ProcessAdvertisingReport(
247           kScannable | kComplete,
248           (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
249           kTestAddress,
250           kSidNotPresent,
251           {0x1, 0x2}),
252       std::vector<uint8_t>({0x1, 0x2}));
253 }
254 
TEST_F(LeScanningReassemblerTest,interleaved_advertising)255 TEST_F(LeScanningReassemblerTest, interleaved_advertising) {
256   // The reassembler must disambiguate advertising events by address,
257   // address type, and SID.
258   ASSERT_FALSE(reassembler_
259                    .ProcessAdvertisingReport(
260                        kContinuation,
261                        (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
262                        kTestAddress,
263                        kSidNotPresent,
264                        {0x2, 0x0})
265                    .has_value());
266 
267   ASSERT_FALSE(reassembler_
268                    .ProcessAdvertisingReport(
269                        kContinuation,
270                        (uint8_t)AddressType::RANDOM_DEVICE_ADDRESS,
271                        kTestAddress,
272                        kSidNotPresent,
273                        {0x2, 0x1})
274                    .has_value());
275 
276   ASSERT_FALSE(reassembler_
277                    .ProcessAdvertisingReport(
278                        kContinuation,
279                        (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
280                        kTestAddress,
281                        0x1,
282                        {0x2, 0x2})
283                    .has_value());
284 
285   ASSERT_FALSE(reassembler_
286                    .ProcessAdvertisingReport(
287                        kContinuation,
288                        (uint8_t)DirectAdvertisingAddressType::NO_ADDRESS_PROVIDED,
289                        Address::kEmpty,
290                        0x1,
291                        {0x2, 0x3})
292                    .has_value());
293 
294   ASSERT_EQ(
295       reassembler_.ProcessAdvertisingReport(
296           kComplete,
297           (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS,
298           kTestAddress,
299           kSidNotPresent,
300           {0x0}),
301       std::vector<uint8_t>({0x2, 0x0, 0x0}));
302 
303   ASSERT_EQ(
304       reassembler_.ProcessAdvertisingReport(
305           kComplete,
306           (uint8_t)AddressType::RANDOM_DEVICE_ADDRESS,
307           kTestAddress,
308           kSidNotPresent,
309           {0x1}),
310       std::vector<uint8_t>({0x2, 0x1, 0x1}));
311 
312   ASSERT_EQ(
313       reassembler_.ProcessAdvertisingReport(
314           kComplete, (uint8_t)AddressType::PUBLIC_DEVICE_ADDRESS, kTestAddress, 0x1, {0x2}),
315       std::vector<uint8_t>({0x2, 0x2, 0x2}));
316 
317   ASSERT_EQ(
318       reassembler_.ProcessAdvertisingReport(
319           kComplete,
320           (uint8_t)DirectAdvertisingAddressType::NO_ADDRESS_PROVIDED,
321           Address::kEmpty,
322           0x1,
323           {0x3}),
324       std::vector<uint8_t>({0x2, 0x3, 0x3}));
325 }
326 
327 }  // namespace bluetooth::hci
328