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