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
31using std::bind;
32using std::placeholders::_1;
33using std::placeholders::_2;
34using std::unique_ptr;
35using std::vector;
36using testing::AllOf;
37using testing::Invoke;
38using testing::NiceMock;
39using testing::Not;
40using testing::Return;
41using testing::_;
42
43using android::net::wifi::IWifiScannerImpl;
44using com::android::server::wifi::wificond::NativeScanResult;
45
46namespace android {
47namespace wificond {
48
49namespace {
50
51constexpr uint32_t kFakeInterfaceIndex = 12;
52constexpr uint32_t kFakeScheduledScanIntervalMs = 20000;
53constexpr uint32_t kFakeSequenceNumber = 1984;
54constexpr int kFakeErrorCode = EIO;
55constexpr int32_t kFake2gRssiThreshold = -80;
56constexpr int32_t kFake5gRssiThreshold = -77;
57constexpr bool kFakeUseRandomMAC = true;
58constexpr bool kFakeRequestLowPower = true;
59constexpr 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.
64NL80211Packet 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
79NL80211Packet 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,
89bool 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
100class ScanUtilsTest : public ::testing::Test {
101 protected:
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
111MATCHER_P(DoesNL80211PacketMatchCommand, command,
112          "Check if the netlink packet matches |command|") {
113  return arg.GetCommand() == command;
114}
115
116MATCHER_P(DoesNL80211PacketHaveAttribute, attr,
117          "Check if the netlink packet has atttribute |attr|") {
118  return arg.HasAttribute(attr);
119}
120
121MATCHER_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
131TEST_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
146TEST_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
162TEST_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
180TEST_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
198TEST_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
216TEST_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
234TEST_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
254TEST_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
268TEST_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
286TEST_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
303TEST_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
321TEST_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
343TEST_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
363TEST_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
378TEST_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.
390TEST_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.
407TEST_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