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