• 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/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, &timestamp_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, &timestamp_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, &timestamp_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, &timestamp_microseconds));
420   EXPECT_EQ(kBssBeaconTsfTimestampMicroSeconds, timestamp_microseconds);
421 }
422 
423 }  // namespace wificond
424 }  // namespace android
425