1 /*
2 * Copyright (C) 2016, 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 <functional>
18 #include <memory>
19 #include <vector>
20
21 #include <linux/netlink.h>
22
23 #include <gtest/gtest.h>
24
25 #include "android/net/wifi/IWifiScannerImpl.h"
26 #include "wificond/net/kernel-header-latest/nl80211.h"
27 #include "wificond/scanning/scan_result.h"
28 #include "wificond/scanning/scan_utils.h"
29 #include "wificond/tests/mock_netlink_manager.h"
30
31 using std::bind;
32 using std::placeholders::_1;
33 using std::placeholders::_2;
34 using std::unique_ptr;
35 using std::vector;
36 using testing::AllOf;
37 using testing::Invoke;
38 using testing::NiceMock;
39 using testing::Not;
40 using testing::Return;
41 using testing::_;
42
43 using android::net::wifi::IWifiScannerImpl;
44 using com::android::server::wifi::wificond::NativeScanResult;
45
46 namespace android {
47 namespace wificond {
48
49 namespace {
50
51 constexpr uint32_t kFakeInterfaceIndex = 12;
52 constexpr uint32_t kFakeScheduledScanIntervalMs = 20000;
53 constexpr uint32_t kFakeSequenceNumber = 1984;
54 constexpr int kFakeErrorCode = EIO;
55 constexpr int32_t kFake2gRssiThreshold = -80;
56 constexpr int32_t kFake5gRssiThreshold = -77;
57 constexpr bool kFakeUseRandomMAC = true;
58 constexpr bool kFakeRequestLowPower = true;
59 constexpr int kFakeScanType = IWifiScannerImpl::SCAN_TYPE_LOW_SPAN;
60
61 // Currently, control messages are only created by the kernel and sent to us.
62 // Therefore NL80211Packet doesn't have corresponding constructor.
63 // For test we manually create control messages using this helper function.
CreateControlMessageError(int error_code)64 NL80211Packet CreateControlMessageError(int error_code) {
65 vector<uint8_t> data;
66 data.resize(NLMSG_HDRLEN + NLA_ALIGN(sizeof(int)), 0);
67 // Initialize length field.
68 nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data.data());
69 nl_header->nlmsg_len = data.size();
70 nl_header->nlmsg_type = NLMSG_ERROR;
71 nl_header->nlmsg_seq = kFakeSequenceNumber;
72 nl_header->nlmsg_pid = getpid();
73 int* error_field = reinterpret_cast<int*>(data.data() + NLMSG_HDRLEN);
74 *error_field = -error_code;
75
76 return NL80211Packet(data);
77 }
78
CreateControlMessageAck()79 NL80211Packet CreateControlMessageAck() {
80 return CreateControlMessageError(0);
81 }
82
83 // This is a helper function to mock the behavior of NetlinkManager::
84 // SendMessageAndGetResponses() when we expect a single packet response.
85 // |request_message| and |response| are mapped to existing parameters of
86 // SendMessageAndGetResponses().
87 // |mock_response| and |mock_return value| are additional parameters used
88 // for specifying expected results,
AppendMessageAndReturn(NL80211Packet & mock_response,bool mock_return_value,const NL80211Packet & request_message,vector<std::unique_ptr<const NL80211Packet>> * response)89 bool AppendMessageAndReturn(
90 NL80211Packet& mock_response,
91 bool mock_return_value,
92 const NL80211Packet& request_message,
93 vector<std::unique_ptr<const NL80211Packet>>* response) {
94 response->push_back(std::make_unique<NL80211Packet>(mock_response));
95 return mock_return_value;
96 }
97
98 } // namespace
99
100 class ScanUtilsTest : public ::testing::Test {
101 protected:
SetUp()102 virtual void SetUp() {
103 ON_CALL(netlink_manager_,
104 SendMessageAndGetResponses(_, _)).WillByDefault(Return(true));
105 }
106
107 NiceMock<MockNetlinkManager> netlink_manager_;
108 ScanUtils scan_utils_{&netlink_manager_};
109 };
110
111 MATCHER_P(DoesNL80211PacketMatchCommand, command,
112 "Check if the netlink packet matches |command|") {
113 return arg.GetCommand() == command;
114 }
115
116 MATCHER_P(DoesNL80211PacketHaveAttribute, attr,
117 "Check if the netlink packet has atttribute |attr|") {
118 return arg.HasAttribute(attr);
119 }
120
121 MATCHER_P2(DoesNL80211PacketHaveAttributeWithUint32Value, attr, expected_value,
122 "Check if the netlink packet has atttribute |attr| with "
123 "|expected_value|") {
124 uint32_t actual_value;
125 if (!arg.GetAttributeValue(attr, &actual_value)) {
126 return false;
127 }
128 return actual_value == expected_value;
129 }
130
TEST_F(ScanUtilsTest,CanGetScanResult)131 TEST_F(ScanUtilsTest, CanGetScanResult) {
132 vector<NativeScanResult> scan_results;
133 EXPECT_CALL(
134 netlink_manager_,
135 SendMessageAndGetResponses(
136 DoesNL80211PacketMatchCommand(NL80211_CMD_GET_SCAN), _));
137
138 // We don't use EXPECT_TRUE here because we need to mock a complete
139 // response for NL80211_CMD_GET_SCAN to satisfy the parsing code called
140 // by GetScanResult.
141 // TODO(b/34231002): Mock response for NL80211_CMD_GET_SCAN.
142 // TODO(b/34231420): Add validation of interface index.
143 scan_utils_.GetScanResult(kFakeInterfaceIndex, &scan_results);
144 }
145
TEST_F(ScanUtilsTest,CanSendScanRequest)146 TEST_F(ScanUtilsTest, CanSendScanRequest) {
147 NL80211Packet response = CreateControlMessageAck();
148 EXPECT_CALL(
149 netlink_manager_,
150 SendMessageAndGetResponses(
151 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)).
152 WillOnce(Invoke(bind(
153 AppendMessageAndReturn, response, true, _1, _2)));
154
155 int errno_ignored;
156 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC,
157 kFakeScanType, {}, {}, &errno_ignored));
158 // TODO(b/34231420): Add validation of requested scan ssids, threshold,
159 // and frequencies.
160 }
161
TEST_F(ScanUtilsTest,CanSendScanRequestWithRandomAddr)162 TEST_F(ScanUtilsTest, CanSendScanRequestWithRandomAddr) {
163 NL80211Packet response = CreateControlMessageAck();
164 EXPECT_CALL(
165 netlink_manager_,
166 SendMessageAndGetResponses(
167 AllOf(
168 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN),
169 DoesNL80211PacketHaveAttributeWithUint32Value(
170 NL80211_ATTR_SCAN_FLAGS, NL80211_SCAN_FLAG_RANDOM_ADDR)),
171 _)).
172 WillOnce(Invoke(bind(AppendMessageAndReturn, response, true, _1, _2)));
173
174 int errno_ignored;
175 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, true,
176 IWifiScannerImpl::SCAN_TYPE_DEFAULT,
177 {}, {}, &errno_ignored));
178 }
179
TEST_F(ScanUtilsTest,CanSendScanRequestForLowSpanScan)180 TEST_F(ScanUtilsTest, CanSendScanRequestForLowSpanScan) {
181 NL80211Packet response = CreateControlMessageAck();
182 EXPECT_CALL(
183 netlink_manager_,
184 SendMessageAndGetResponses(
185 AllOf(
186 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN),
187 DoesNL80211PacketHaveAttributeWithUint32Value(
188 NL80211_ATTR_SCAN_FLAGS, NL80211_SCAN_FLAG_LOW_SPAN)),
189 _)).
190 WillOnce(Invoke(bind(AppendMessageAndReturn, response, true, _1, _2)));
191
192 int errno_ignored;
193 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, false,
194 IWifiScannerImpl::SCAN_TYPE_LOW_SPAN,
195 {}, {}, &errno_ignored));
196 }
197
TEST_F(ScanUtilsTest,CanSendScanRequestForLowPowerScan)198 TEST_F(ScanUtilsTest, CanSendScanRequestForLowPowerScan) {
199 NL80211Packet response = CreateControlMessageAck();
200 EXPECT_CALL(
201 netlink_manager_,
202 SendMessageAndGetResponses(
203 AllOf(
204 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN),
205 DoesNL80211PacketHaveAttributeWithUint32Value(
206 NL80211_ATTR_SCAN_FLAGS, NL80211_SCAN_FLAG_LOW_POWER)),
207 _)).
208 WillOnce(Invoke(bind(AppendMessageAndReturn, response, true, _1, _2)));
209
210 int errno_ignored;
211 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, false,
212 IWifiScannerImpl::SCAN_TYPE_LOW_POWER,
213 {}, {}, &errno_ignored));
214 }
215
TEST_F(ScanUtilsTest,CanSendScanRequestForHighAccuracyScan)216 TEST_F(ScanUtilsTest, CanSendScanRequestForHighAccuracyScan) {
217 NL80211Packet response = CreateControlMessageAck();
218 EXPECT_CALL(
219 netlink_manager_,
220 SendMessageAndGetResponses(
221 AllOf(
222 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN),
223 DoesNL80211PacketHaveAttributeWithUint32Value(
224 NL80211_ATTR_SCAN_FLAGS, NL80211_SCAN_FLAG_HIGH_ACCURACY)),
225 _)).
226 WillOnce(Invoke(bind(AppendMessageAndReturn, response, true, _1, _2)));
227
228 int errno_ignored;
229 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, false,
230 IWifiScannerImpl::SCAN_TYPE_HIGH_ACCURACY,
231 {}, {}, &errno_ignored));
232 }
233
TEST_F(ScanUtilsTest,CanSendScanRequestForHighAccuracyScanWithRandomAddr)234 TEST_F(ScanUtilsTest, CanSendScanRequestForHighAccuracyScanWithRandomAddr) {
235 NL80211Packet response = CreateControlMessageAck();
236 EXPECT_CALL(
237 netlink_manager_,
238 SendMessageAndGetResponses(
239 AllOf(
240 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN),
241 DoesNL80211PacketHaveAttributeWithUint32Value(
242 NL80211_ATTR_SCAN_FLAGS,
243 static_cast<uint32_t>(NL80211_SCAN_FLAG_RANDOM_ADDR |
244 NL80211_SCAN_FLAG_HIGH_ACCURACY))),
245 _)).
246 WillOnce(Invoke(bind(AppendMessageAndReturn, response, true, _1, _2)));
247
248 int errno_ignored;
249 EXPECT_TRUE(scan_utils_.Scan(kFakeInterfaceIndex, true,
250 IWifiScannerImpl::SCAN_TYPE_HIGH_ACCURACY,
251 {}, {}, &errno_ignored));
252 }
253
TEST_F(ScanUtilsTest,CanHandleScanRequestFailure)254 TEST_F(ScanUtilsTest, CanHandleScanRequestFailure) {
255 NL80211Packet response = CreateControlMessageError(kFakeErrorCode);
256 EXPECT_CALL(
257 netlink_manager_,
258 SendMessageAndGetResponses(
259 DoesNL80211PacketMatchCommand(NL80211_CMD_TRIGGER_SCAN), _)).
260 WillOnce(Invoke(bind(
261 AppendMessageAndReturn, response, true, _1, _2)));
262 int error_code;
263 EXPECT_FALSE(scan_utils_.Scan(kFakeInterfaceIndex, kFakeUseRandomMAC,
264 kFakeScanType, {}, {}, &error_code));
265 EXPECT_EQ(kFakeErrorCode, error_code);
266 }
267
TEST_F(ScanUtilsTest,CanSendSchedScanRequest)268 TEST_F(ScanUtilsTest, CanSendSchedScanRequest) {
269 NL80211Packet response = CreateControlMessageAck();
270 EXPECT_CALL(
271 netlink_manager_,
272 SendMessageAndGetResponses(
273 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)).
274 WillOnce(Invoke(bind(
275 AppendMessageAndReturn, response, true, _1, _2)));
276 int errno_ignored;
277 EXPECT_TRUE(scan_utils_.StartScheduledScan(
278 kFakeInterfaceIndex,
279 SchedScanIntervalSetting(),
280 kFake2gRssiThreshold, kFake5gRssiThreshold,
281 kFakeUseRandomMAC, kFakeRequestLowPower, {}, {}, {}, &errno_ignored));
282 // TODO(b/34231420): Add validation of requested scan ssids, threshold,
283 // and frequencies.
284 }
285
TEST_F(ScanUtilsTest,CanHandleSchedScanRequestFailure)286 TEST_F(ScanUtilsTest, CanHandleSchedScanRequestFailure) {
287 NL80211Packet response = CreateControlMessageError(kFakeErrorCode);
288 EXPECT_CALL(
289 netlink_manager_,
290 SendMessageAndGetResponses(
291 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN), _)).
292 WillOnce(Invoke(bind(
293 AppendMessageAndReturn, response, true, _1, _2)));
294 int error_code;
295 EXPECT_FALSE(scan_utils_.StartScheduledScan(
296 kFakeInterfaceIndex,
297 SchedScanIntervalSetting(),
298 kFake2gRssiThreshold, kFake5gRssiThreshold,
299 kFakeUseRandomMAC, kFakeRequestLowPower, {}, {}, {}, &error_code));
300 EXPECT_EQ(kFakeErrorCode, error_code);
301 }
302
TEST_F(ScanUtilsTest,CanSendSchedScanRequestForLowPowerScan)303 TEST_F(ScanUtilsTest, CanSendSchedScanRequestForLowPowerScan) {
304 NL80211Packet response = CreateControlMessageAck();
305 EXPECT_CALL(
306 netlink_manager_,
307 SendMessageAndGetResponses(
308 AllOf(
309 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN),
310 DoesNL80211PacketHaveAttributeWithUint32Value(
311 NL80211_ATTR_SCAN_FLAGS, NL80211_SCAN_FLAG_LOW_POWER)),
312 _));
313 int errno_ignored;
314 scan_utils_.StartScheduledScan(
315 kFakeInterfaceIndex,
316 SchedScanIntervalSetting(),
317 kFake2gRssiThreshold, kFake5gRssiThreshold,
318 false, true, {}, {}, {}, &errno_ignored);
319 }
320
TEST_F(ScanUtilsTest,CanSpecifyScanPlansForSchedScanRequest)321 TEST_F(ScanUtilsTest, CanSpecifyScanPlansForSchedScanRequest) {
322 EXPECT_CALL(
323 netlink_manager_,
324 SendMessageAndGetResponses(
325 AllOf(
326 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN),
327 DoesNL80211PacketHaveAttribute(NL80211_ATTR_SCHED_SCAN_PLANS),
328 Not(DoesNL80211PacketHaveAttribute(
329 NL80211_ATTR_SCHED_SCAN_INTERVAL))),
330 _));
331 int errno_ignored;
332 SchedScanIntervalSetting interval_setting{
333 {{kFakeScheduledScanIntervalMs, 10 /* repeated times */}},
334 kFakeScheduledScanIntervalMs * 3 /* interval for infinite scans */};
335
336 scan_utils_.StartScheduledScan(
337 kFakeInterfaceIndex,
338 interval_setting,
339 kFake2gRssiThreshold, kFake5gRssiThreshold,
340 kFakeUseRandomMAC, kFakeRequestLowPower, {}, {}, {}, &errno_ignored);
341 }
342
TEST_F(ScanUtilsTest,CanSpecifySingleIntervalForSchedScanRequest)343 TEST_F(ScanUtilsTest, CanSpecifySingleIntervalForSchedScanRequest) {
344 EXPECT_CALL(
345 netlink_manager_,
346 SendMessageAndGetResponses(
347 AllOf(
348 DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN),
349 DoesNL80211PacketHaveAttribute(NL80211_ATTR_SCHED_SCAN_INTERVAL),
350 Not(DoesNL80211PacketHaveAttribute(
351 NL80211_ATTR_SCHED_SCAN_PLANS))),
352 _));
353 int errno_ignored;
354 SchedScanIntervalSetting interval_setting{{}, kFakeScheduledScanIntervalMs};
355
356 scan_utils_.StartScheduledScan(
357 kFakeInterfaceIndex,
358 interval_setting,
359 kFake2gRssiThreshold, kFake5gRssiThreshold,
360 kFakeUseRandomMAC, kFakeRequestLowPower, {}, {}, {}, &errno_ignored);
361 }
362
TEST_F(ScanUtilsTest,CanPrioritizeLastSeenSinceBootNetlinkAttribute)363 TEST_F(ScanUtilsTest, CanPrioritizeLastSeenSinceBootNetlinkAttribute) {
364 constexpr uint64_t kLastSeenTimestampNanoSeconds = 123456;
365 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321;
366 NL80211NestedAttr bss(NL80211_ATTR_BSS);
367 bss.AddAttribute(
368 NL80211Attr<uint64_t>(NL80211_BSS_LAST_SEEN_BOOTTIME,
369 kLastSeenTimestampNanoSeconds));
370 bss.AddAttribute(
371 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
372 uint64_t timestamp_microseconds;
373 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
374 bss, ×tamp_microseconds));
375 EXPECT_EQ(kLastSeenTimestampNanoSeconds/1000, timestamp_microseconds);
376 }
377
TEST_F(ScanUtilsTest,CanHandleMissingLastSeenSinceBootNetlinkAttribute)378 TEST_F(ScanUtilsTest, CanHandleMissingLastSeenSinceBootNetlinkAttribute) {
379 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321;
380 NL80211NestedAttr bss(NL80211_ATTR_BSS);
381 bss.AddAttribute(
382 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
383 uint64_t timestamp_microseconds;
384 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
385 bss, ×tamp_microseconds));
386 EXPECT_EQ(kBssTsfTimestampMicroSeconds, timestamp_microseconds);
387 }
388
389 // Probe TSF is newer.
TEST_F(ScanUtilsTest,CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon1)390 TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon1) {
391 constexpr uint64_t kBssBeaconTsfTimestampMicroSeconds = 654321;
392 constexpr uint64_t kBssTsfTimestampMicroSeconds =
393 kBssBeaconTsfTimestampMicroSeconds + 2000;
394 NL80211NestedAttr bss(NL80211_ATTR_BSS);
395 bss.AddAttribute(
396 NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF,
397 kBssBeaconTsfTimestampMicroSeconds));
398 bss.AddAttribute(
399 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
400 uint64_t timestamp_microseconds;
401 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
402 bss, ×tamp_microseconds));
403 EXPECT_EQ(kBssTsfTimestampMicroSeconds, timestamp_microseconds);
404 }
405
406 // Beacon TSF is newer.
TEST_F(ScanUtilsTest,CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon2)407 TEST_F(ScanUtilsTest, CanPickMostRecentTimestampBetweenBetweenProbeAndBeacon2) {
408 constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321;
409 constexpr uint64_t kBssBeaconTsfTimestampMicroSeconds =
410 kBssTsfTimestampMicroSeconds + 2000;
411 NL80211NestedAttr bss(NL80211_ATTR_BSS);
412 bss.AddAttribute(
413 NL80211Attr<uint64_t>(NL80211_BSS_BEACON_TSF,
414 kBssBeaconTsfTimestampMicroSeconds));
415 bss.AddAttribute(
416 NL80211Attr<uint64_t>(NL80211_BSS_TSF, kBssTsfTimestampMicroSeconds));
417 uint64_t timestamp_microseconds;
418 EXPECT_TRUE(scan_utils_.GetBssTimestampForTesting(
419 bss, ×tamp_microseconds));
420 EXPECT_EQ(kBssBeaconTsfTimestampMicroSeconds, timestamp_microseconds);
421 }
422
423 } // namespace wificond
424 } // namespace android
425