summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNingyuan Wang <nywang@google.com>2017-07-19 10:58:36 -0700
committerNingyuan Wang <nywang@google.com>2017-08-01 17:55:19 -0700
commitdfbe7e4e12824527fac840391f31d2b4a4578e3e (patch)
treeb62a5c015c05198c9fbb0f7cdfdd6a4e9525cce5
parent514a184b8ee7df61e656d76e9f2dd822524e887a (diff)
downloadwificond-dfbe7e4e12824527fac840391f31d2b4a4578e3e.tar.gz
Support scan plan attribute for scheduled scanoreo-dr1-dev
This adds the support of the scan plan attribute. With kernel updates, driver can no longer diffrentiate interval attribute from single scan plan attribute, so driver's pno scan back off logic cannot be triggered in that case. To solve the PNO back-off problem, this CL allows wificond to explicitly specify scan plans (if the driver supports it). With explicit scan plans, the driver will have the information it needs to back-off PNO scans. Bug: 63837760 Test: compile, unit tests Test: Manually test that pno scan works on multiple devices Test: Integration sanity test Change-Id: Ic7e38caa482a2d72f45bf3c8177fa656e534db08
-rw-r--r--scanning/pno_settings.cpp3
-rw-r--r--scanning/pno_settings.h3
-rw-r--r--scanning/scan_utils.cpp32
-rw-r--r--scanning/scan_utils.h13
-rw-r--r--scanning/scanner_impl.cpp31
-rw-r--r--scanning/scanner_impl.h5
-rw-r--r--tests/mock_scan_utils.h2
-rw-r--r--tests/scan_utils_unittest.cpp51
-rw-r--r--tests/scanner_unittest.cpp81
9 files changed, 211 insertions, 10 deletions
diff --git a/scanning/pno_settings.cpp b/scanning/pno_settings.cpp
index c8b5ff6..be051dd 100644
--- a/scanning/pno_settings.cpp
+++ b/scanning/pno_settings.cpp
@@ -28,6 +28,9 @@ namespace server {
namespace wifi {
namespace wificond {
+const uint32_t PnoSettings::kFastScanIterations = 3;
+const uint32_t PnoSettings::kSlowScanIntervalMultiplier = 3;
+
status_t PnoSettings::writeToParcel(::android::Parcel* parcel) const {
RETURN_IF_FAILED(parcel->writeInt32(interval_ms_));
RETURN_IF_FAILED(parcel->writeInt32(min_2g_rssi_));
diff --git a/scanning/pno_settings.h b/scanning/pno_settings.h
index e236ec8..a606b0f 100644
--- a/scanning/pno_settings.h
+++ b/scanning/pno_settings.h
@@ -32,6 +32,9 @@ namespace wificond {
class PnoSettings : public ::android::Parcelable {
public:
+ static const uint32_t kFastScanIterations;
+ static const uint32_t kSlowScanIntervalMultiplier;
+
PnoSettings()
: interval_ms_(0),
min_2g_rssi_(0),
diff --git a/scanning/scan_utils.cpp b/scanning/scan_utils.cpp
index 5f0a6e3..dfd051c 100644
--- a/scanning/scan_utils.cpp
+++ b/scanning/scan_utils.cpp
@@ -36,6 +36,7 @@ namespace wificond {
namespace {
constexpr uint8_t kElemIdSsid = 0;
+constexpr unsigned int kMsecPerSec = 1000;
} // namespace
@@ -348,7 +349,7 @@ bool ScanUtils::AbortScan(uint32_t interface_index) {
bool ScanUtils::StartScheduledScan(
uint32_t interface_index,
- uint32_t interval_ms,
+ const SchedScanIntervalSetting& interval_setting,
int32_t rssi_threshold,
bool request_random_mac,
const std::vector<std::vector<uint8_t>>& scan_ssids,
@@ -385,6 +386,7 @@ bool ScanUtils::StartScheduledScan(
NL80211Attr<int32_t>(NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, rssi_threshold));
scan_match_attr.AddAttribute(match_group);
}
+ start_sched_scan.AddAttribute(scan_match_attr);
// Append all attributes to the NL80211_CMD_START_SCHED_SCAN packet.
start_sched_scan.AddAttribute(
@@ -395,9 +397,31 @@ bool ScanUtils::StartScheduledScan(
if (!freqs.empty()) {
start_sched_scan.AddAttribute(freqs_attr);
}
- start_sched_scan.AddAttribute(
- NL80211Attr<uint32_t>(NL80211_ATTR_SCHED_SCAN_INTERVAL, interval_ms));
- start_sched_scan.AddAttribute(scan_match_attr);
+
+ if (!interval_setting.plans.empty()) {
+ NL80211NestedAttr scan_plans(NL80211_ATTR_SCHED_SCAN_PLANS);
+ for (unsigned int i = 0; i < interval_setting.plans.size(); i++) {
+ NL80211NestedAttr scan_plan(i + 1);
+ scan_plan.AddAttribute(
+ NL80211Attr<uint32_t>(NL80211_SCHED_SCAN_PLAN_INTERVAL,
+ interval_setting.plans[i].interval_ms / kMsecPerSec));
+ scan_plan.AddAttribute(
+ NL80211Attr<uint32_t>(NL80211_SCHED_SCAN_PLAN_ITERATIONS,
+ interval_setting.plans[i].n_iterations));
+ scan_plans.AddAttribute(scan_plan);
+ }
+ NL80211NestedAttr last_scan_plan(interval_setting.plans.size() + 1);
+ last_scan_plan.AddAttribute(
+ NL80211Attr<uint32_t>(NL80211_SCHED_SCAN_PLAN_INTERVAL,
+ interval_setting.final_interval_ms / kMsecPerSec));
+ scan_plans.AddAttribute(last_scan_plan);
+ start_sched_scan.AddAttribute(scan_plans);
+ } else {
+ start_sched_scan.AddAttribute(
+ NL80211Attr<uint32_t>(NL80211_ATTR_SCHED_SCAN_INTERVAL,
+ interval_setting.final_interval_ms));
+ }
+
if (request_random_mac) {
start_sched_scan.AddAttribute(
NL80211Attr<uint32_t>(NL80211_ATTR_SCAN_FLAGS,
diff --git a/scanning/scan_utils.h b/scanning/scan_utils.h
index dbc2556..87df13a 100644
--- a/scanning/scan_utils.h
+++ b/scanning/scan_utils.h
@@ -44,6 +44,17 @@ namespace wificond {
class NL80211NestedAttr;
class NL80211Packet;
+struct SchedScanIntervalSetting {
+ struct ScanPlan {
+ uint32_t interval_ms;
+ uint32_t n_iterations;
+ };
+ std::vector<ScanPlan> plans;
+ // After |plans| has been exhausted, scan at every
+ // |final_interval_ms|.
+ uint32_t final_interval_ms{0};
+};
+
// Provides scanning helper functions.
class ScanUtils {
public:
@@ -98,7 +109,7 @@ class ScanUtils {
// Returns true on success.
virtual bool StartScheduledScan(
uint32_t interface_index,
- uint32_t interval_ms,
+ const SchedScanIntervalSetting& interval_setting,
int32_t rssi_threshold,
bool request_random_mac,
const std::vector<std::vector<uint8_t>>& scan_ssids,
diff --git a/scanning/scanner_impl.cpp b/scanning/scanner_impl.cpp
index a1ea261..9bf13b3 100644
--- a/scanning/scanner_impl.cpp
+++ b/scanning/scanner_impl.cpp
@@ -35,6 +35,7 @@ using com::android::server::wifi::wificond::NativeScanResult;
using com::android::server::wifi::wificond::PnoSettings;
using com::android::server::wifi::wificond::SingleScanSettings;
+using std::pair;
using std::string;
using std::vector;
using std::weak_ptr;
@@ -305,7 +306,7 @@ bool ScannerImpl::StartPnoScanDefault(const PnoSettings& pno_settings) {
int error_code = 0;
if (!scan_utils_->StartScheduledScan(interface_index_,
- pno_settings.interval_ms_,
+ GenerateIntervalSetting(pno_settings),
// TODO: honor both rssi thresholds.
pno_settings.min_5g_rssi_,
request_random_mac,
@@ -447,6 +448,34 @@ void ScannerImpl::OnSchedScanResultsReady(uint32_t interface_index,
}
}
+SchedScanIntervalSetting ScannerImpl::GenerateIntervalSetting(
+ const ::com::android::server::wifi::wificond::PnoSettings&
+ pno_settings) const {
+ bool support_num_scan_plans = scan_capabilities_.max_num_scan_plans >= 2;
+ bool support_scan_plan_interval =
+ scan_capabilities_.max_scan_plan_interval * 1000 >=
+ pno_settings.interval_ms_ * PnoSettings::kSlowScanIntervalMultiplier;
+ bool support_scan_plan_iterations =
+ scan_capabilities_.max_scan_plan_iterations >=
+ PnoSettings::kFastScanIterations;
+
+ uint32_t fast_scan_interval =
+ static_cast<uint32_t>(pno_settings.interval_ms_);
+ if (support_num_scan_plans && support_scan_plan_interval &&
+ support_scan_plan_iterations) {
+ return SchedScanIntervalSetting{
+ {{fast_scan_interval, PnoSettings::kFastScanIterations}},
+ fast_scan_interval * PnoSettings::kSlowScanIntervalMultiplier};
+ } else {
+ // Device doesn't support the provided scan plans.
+ // Specify single interval instead.
+ // In this case, the driver/firmware is expected to implement back off
+ // logic internally using |pno_settings.interval_ms_| as "fast scan"
+ // interval.
+ return SchedScanIntervalSetting{{}, fast_scan_interval};
+ }
+}
+
void ScannerImpl::LogSsidList(vector<vector<uint8_t>>& ssid_list,
string prefix) {
if (ssid_list.empty()) {
diff --git a/scanning/scanner_impl.h b/scanning/scanner_impl.h
index fe66f17..2bb9262 100644
--- a/scanning/scanner_impl.h
+++ b/scanning/scanner_impl.h
@@ -25,13 +25,13 @@
#include "android/net/wifi/BnWifiScannerImpl.h"
#include "wificond/net/netlink_utils.h"
#include "wificond/scanning/offload/offload_scan_manager.h"
+#include "wificond/scanning/scan_utils.h"
namespace android {
namespace wificond {
class ClientInterfaceImpl;
class OffloadServiceUtils;
-class ScanUtils;
class ScannerImpl : public android::net::wifi::BnWifiScannerImpl {
public:
@@ -99,6 +99,9 @@ class ScannerImpl : public android::net::wifi::BnWifiScannerImpl {
std::vector<std::vector<uint8_t>>* match_ssids,
std::vector<uint32_t>* freqs,
std::vector<uint8_t>* match_security);
+ SchedScanIntervalSetting GenerateIntervalSetting(
+ const ::com::android::server::wifi::wificond::PnoSettings& pno_settings) const;
+
// Boolean variables describing current scanner status.
bool valid_;
bool scan_started_;
diff --git a/tests/mock_scan_utils.h b/tests/mock_scan_utils.h
index f3e1777..3e5cc7f 100644
--- a/tests/mock_scan_utils.h
+++ b/tests/mock_scan_utils.h
@@ -50,7 +50,7 @@ class MockScanUtils : public ScanUtils {
MOCK_METHOD8(StartScheduledScan, bool(
uint32_t interface_index,
- uint32_t interval_ms,
+ const SchedScanIntervalSetting& interval_setting,
int32_t rssi_threshold,
bool request_random_mac,
const std::vector<std::vector<uint8_t>>& scan_ssids,
diff --git a/tests/scan_utils_unittest.cpp b/tests/scan_utils_unittest.cpp
index 9e36ab2..28ea283 100644
--- a/tests/scan_utils_unittest.cpp
+++ b/tests/scan_utils_unittest.cpp
@@ -32,8 +32,10 @@ using std::placeholders::_1;
using std::placeholders::_2;
using std::unique_ptr;
using std::vector;
+using testing::AllOf;
using testing::Invoke;
using testing::NiceMock;
+using testing::Not;
using testing::Return;
using testing::_;
@@ -106,6 +108,11 @@ MATCHER_P(DoesNL80211PacketMatchCommand, command,
return arg.GetCommand() == command;
}
+MATCHER_P(DoesNL80211PacketHaveAttribute, attr,
+ "Check if the netlink packet has atttribute |attr|") {
+ return arg.HasAttribute(attr);
+}
+
TEST_F(ScanUtilsTest, CanGetScanResult) {
vector<NativeScanResult> scan_results;
EXPECT_CALL(
@@ -162,7 +169,7 @@ TEST_F(ScanUtilsTest, CanSendSchedScanRequest) {
int errno_ignored;
EXPECT_TRUE(scan_utils_.StartScheduledScan(
kFakeInterfaceIndex,
- kFakeScheduledScanIntervalMs,
+ SchedScanIntervalSetting(),
kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &errno_ignored));
// TODO(b/34231420): Add validation of requested scan ssids, threshold,
// and frequencies.
@@ -179,11 +186,51 @@ TEST_F(ScanUtilsTest, CanHandleSchedScanRequestFailure) {
int error_code;
EXPECT_FALSE(scan_utils_.StartScheduledScan(
kFakeInterfaceIndex,
- kFakeScheduledScanIntervalMs,
+ SchedScanIntervalSetting(),
kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &error_code));
EXPECT_EQ(kFakeErrorCode, error_code);
}
+TEST_F(ScanUtilsTest, CanSpecifyScanPlansForSchedScanRequest) {
+ EXPECT_CALL(
+ netlink_manager_,
+ SendMessageAndGetResponses(
+ AllOf(
+ DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN),
+ DoesNL80211PacketHaveAttribute(NL80211_ATTR_SCHED_SCAN_PLANS),
+ Not(DoesNL80211PacketHaveAttribute(
+ NL80211_ATTR_SCHED_SCAN_INTERVAL))),
+ _));
+ int errno_ignored;
+ SchedScanIntervalSetting interval_setting{
+ {{kFakeScheduledScanIntervalMs, 10 /* repeated times */}},
+ kFakeScheduledScanIntervalMs * 3 /* interval for infinite scans */};
+
+ scan_utils_.StartScheduledScan(
+ kFakeInterfaceIndex,
+ interval_setting,
+ kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &errno_ignored);
+}
+
+TEST_F(ScanUtilsTest, CanSpecifySingleIntervalForSchedScanRequest) {
+ EXPECT_CALL(
+ netlink_manager_,
+ SendMessageAndGetResponses(
+ AllOf(
+ DoesNL80211PacketMatchCommand(NL80211_CMD_START_SCHED_SCAN),
+ DoesNL80211PacketHaveAttribute(NL80211_ATTR_SCHED_SCAN_INTERVAL),
+ Not(DoesNL80211PacketHaveAttribute(
+ NL80211_ATTR_SCHED_SCAN_PLANS))),
+ _));
+ int errno_ignored;
+ SchedScanIntervalSetting interval_setting{{}, kFakeScheduledScanIntervalMs};
+
+ scan_utils_.StartScheduledScan(
+ kFakeInterfaceIndex,
+ interval_setting,
+ kFakeRssiThreshold, kFakeUseRandomMAC, {}, {}, {}, &errno_ignored);
+}
+
TEST_F(ScanUtilsTest, CanPrioritizeLastSeenSinceBootNetlinkAttribute) {
constexpr uint64_t kLastSeenTimestampNanoSeconds = 123456;
constexpr uint64_t kBssTsfTimestampMicroSeconds = 654321;
diff --git a/tests/scanner_unittest.cpp b/tests/scanner_unittest.cpp
index 85f6330..bbaeffd 100644
--- a/tests/scanner_unittest.cpp
+++ b/tests/scanner_unittest.cpp
@@ -51,6 +51,7 @@ namespace {
constexpr uint32_t kFakeInterfaceIndex = 12;
constexpr uint32_t kFakeWiphyIndex = 5;
+constexpr uint32_t kFakeScanIntervalMs = 10000;
// This is a helper function to mock the behavior of ScanUtils::Scan()
// when we expect a error code.
@@ -69,6 +70,20 @@ bool ReturnErrorCodeForScanRequest(
return false;
}
+bool CaptureSchedScanIntervalSetting(
+ uint32_t /* interface_index */,
+ const SchedScanIntervalSetting& interval_setting,
+ int32_t /* rssi_threshold */,
+ bool /* request_random_mac */,
+ const std::vector<std::vector<uint8_t>>& /* scan_ssids */,
+ const std::vector<std::vector<uint8_t>>& /* match_ssids */,
+ const std::vector<uint32_t>& /* freqs */,
+ int* /* error_code */,
+ SchedScanIntervalSetting* out_interval_setting) {
+ *out_interval_setting = interval_setting;
+ return true;
+}
+
} // namespace
class ScannerTest : public ::testing::Test {
@@ -168,5 +183,71 @@ TEST_F(ScannerTest, TestStopPnoScanViaNetlink) {
EXPECT_TRUE(success);
}
+TEST_F(ScannerTest, TestGenerateScanPlansIfDeviceSupports) {
+ ScanCapabilities scan_capabilities_scan_plan_supported(
+ 0 /* max_num_scan_ssids */,
+ 0 /* max_num_sched_scan_ssids */,
+ 0 /* max_match_sets */,
+ // Parameters above are not related to this test.
+ 2 /* 1 plan for finite repeated scan and 1 plan for ininfite scan loop */,
+ kFakeScanIntervalMs * PnoSettings::kSlowScanIntervalMultiplier / 1000,
+ PnoSettings::kFastScanIterations);
+ ScannerImpl scanner(
+ kFakeWiphyIndex, kFakeInterfaceIndex,
+ scan_capabilities_scan_plan_supported, wiphy_features_,
+ &client_interface_impl_,
+ &netlink_utils_, &scan_utils_, offload_service_utils_);
+
+ PnoSettings pno_settings;
+ pno_settings.interval_ms_ = kFakeScanIntervalMs;
+
+ SchedScanIntervalSetting interval_setting;
+ EXPECT_CALL(
+ scan_utils_,
+ StartScheduledScan(_, _, _, _, _, _, _, _)).
+ WillOnce(Invoke(bind(
+ CaptureSchedScanIntervalSetting,
+ _1, _2, _3, _4, _5, _6, _7, _8, &interval_setting)));
+
+ bool success_ignored = 0;
+ EXPECT_TRUE(scanner.startPnoScan(pno_settings, &success_ignored).isOk());
+ /* 1 plan for finite repeated scan */
+ EXPECT_EQ(1U, interval_setting.plans.size());
+ EXPECT_EQ(kFakeScanIntervalMs * PnoSettings::kSlowScanIntervalMultiplier,
+ interval_setting.final_interval_ms);
+}
+
+TEST_F(ScannerTest, TestGenerateSingleIntervalIfDeviceDoesNotSupportScanPlan) {
+ ScanCapabilities scan_capabilities_no_scan_plan_support(
+ 0 /* max_num_scan_ssids */,
+ 0 /* max_num_sched_scan_ssids */,
+ 0 /* max_match_sets */,
+ // Parameters above are not related to this test.
+ 0 /* max_num_scan_plans */,
+ 0 /* max_scan_plan_interval */,
+ 0 /* max_scan_plan_iterations */);
+ ScannerImpl scanner(
+ kFakeWiphyIndex, kFakeInterfaceIndex,
+ scan_capabilities_no_scan_plan_support, wiphy_features_,
+ &client_interface_impl_,
+ &netlink_utils_, &scan_utils_, offload_service_utils_);
+ PnoSettings pno_settings;
+ pno_settings.interval_ms_ = kFakeScanIntervalMs;
+
+ SchedScanIntervalSetting interval_setting;
+ EXPECT_CALL(
+ scan_utils_,
+ StartScheduledScan(_, _, _, _, _, _, _, _)).
+ WillOnce(Invoke(bind(
+ CaptureSchedScanIntervalSetting,
+ _1, _2, _3, _4, _5, _6, _7, _8, &interval_setting)));
+
+ bool success_ignored = 0;
+ EXPECT_TRUE(scanner.startPnoScan(pno_settings, &success_ignored).isOk());
+
+ EXPECT_EQ(0U, interval_setting.plans.size());
+ EXPECT_EQ(kFakeScanIntervalMs, interval_setting.final_interval_ms);
+}
+
} // namespace wificond
} // namespace android