LOCAL_PATH := $(call my-dir)
wificond_cpp_flags := -Wall -Werror -Wno-unused-parameter
+ifdef WIFI_OFFLOAD_SCANS
+wificond_cpp_flags += -DWIFI_OFFLOAD_SCANS=\"$(WIFI_OFFLOAD_SCANS)\"
+endif
wificond_parent_dir := $(LOCAL_PATH)/../
wificond_includes := \
$(wificond_parent_dir)
scanning/pno_network.cpp \
scanning/pno_settings.cpp \
scanning/scan_result.cpp \
+ scanning/offload/scan_stats.cpp \
scanning/single_scan_settings.cpp \
scanning/scan_utils.cpp \
scanning/scanner_impl.cpp \
tests/nl80211_attribute_unittest.cpp \
tests/nl80211_packet_unittest.cpp \
tests/offload_callback_test.cpp \
+ tests/offload_hal_test_constants.cpp \
tests/offload_scan_manager_test.cpp \
tests/offload_scan_utils_test.cpp \
tests/offload_test_utils.cpp \
tests/scan_result_unittest.cpp \
tests/scan_settings_unittest.cpp \
+ tests/scan_stats_unittest.cpp \
tests/scan_utils_unittest.cpp \
tests/server_unittest.cpp
LOCAL_STATIC_LIBRARIES := \
// Returns false on failure or there is no existing scheduled scan.
boolean stopPnoScan();
+ // Abort ongoing scan.
+ // Returns true on success.
+ // Returns false on failure or there is no ongoing scan.
+ boolean abortScan();
+
// TODO(nywang) add more interfaces.
}
#include "wificond/scanning/offload/offload_scan_utils.h"
#include "wificond/scanning/offload/offload_service_utils.h"
#include "wificond/scanning/scan_result.h"
+#include "wificond/scanning/offload/scan_stats.h"
using ::android::hardware::hidl_vec;
using android::hardware::wifi::offload::V1_0::IOffload;
using android::hardware::wifi::offload::V1_0::ScanResult;
+using android::hardware::wifi::offload::V1_0::ScanFilter;
+using android::hardware::wifi::offload::V1_0::ScanParam;
+using android::hardware::wifi::offload::V1_0::ScanStats;
using android::hardware::wifi::offload::V1_0::OffloadStatus;
using android::wificond::OffloadCallback;
using android::wificond::OnNativeScanResultsReadyHandler;
using ::com::android::server::wifi::wificond::NativeScanResult;
-
+using ::com::android::server::wifi::wificond::NativeScanStats;
using namespace std::placeholders;
+using std::vector;
+
+namespace {
+ const uint32_t kSubscriptionDelayMs = 5000;
+}
namespace android {
namespace wificond {
-OffloadCallbackHandlersImpl::OffloadCallbackHandlersImpl(OffloadScanManager* offload_scan_manager)
- : offload_scan_manager_(offload_scan_manager) {
+OffloadCallbackHandlersImpl::OffloadCallbackHandlersImpl(
+ OffloadScanManager* offload_scan_manager)
+ : offload_scan_manager_(offload_scan_manager) {
}
OffloadCallbackHandlersImpl::~OffloadCallbackHandlersImpl() {}
-void OffloadCallbackHandlersImpl::OnScanResultHandler(const std::vector<ScanResult>& scanResult) {
+void OffloadCallbackHandlersImpl::OnScanResultHandler(
+ const vector<ScanResult>& scanResult) {
if (offload_scan_manager_ != nullptr) {
offload_scan_manager_->ReportScanResults(scanResult);
}
OnNativeScanResultsReadyHandler handler)
: wifi_offload_hal_(nullptr),
wifi_offload_callback_(nullptr),
- scan_result_handler_(handler),
offload_status_(OffloadScanManager::kError),
- offload_callback_handlers_(new OffloadCallbackHandlersImpl(this)) {
+ subscription_enabled_(false),
+ service_available_(false),
+ offload_callback_handlers_(new OffloadCallbackHandlersImpl(this)),
+ scan_result_handler_(handler) {
if (utils == nullptr) {
LOG(ERROR) << "Invalid arguments for Offload ScanManager";
return;
}
wifi_offload_hal_ = utils->GetOffloadService();
if (wifi_offload_hal_ == nullptr) {
- LOG(WARNING) << "No Offload Service available";
- offload_status_ = OffloadScanManager::kNoService;
+ LOG(ERROR) << "No Offload Service available";
return;
}
wifi_offload_callback_ = utils->GetOffloadCallback(
offload_callback_handlers_.get());
if (wifi_offload_callback_ == nullptr) {
- offload_status_ = OffloadScanManager::kNoService;
LOG(ERROR) << "Invalid Offload callback object";
return;
}
wifi_offload_hal_->setEventCallback(wifi_offload_callback_);
+ service_available_ = true;
offload_status_ = OffloadScanManager::kNoError;
}
+bool OffloadScanManager::stopScan(OffloadScanManager::ReasonCode* reason_code) {
+ if (!subscription_enabled_) {
+ LOG(VERBOSE) << "Scans are not subscribed over Offload HAL";
+ *reason_code = OffloadScanManager::kNotSubscribed;
+ return false;
+ }
+ if (service_available_) {
+ wifi_offload_hal_->unsubscribeScanResults();
+ subscription_enabled_ = false;
+ }
+ *reason_code = OffloadScanManager::kNone;
+ return true;
+}
+
+bool OffloadScanManager::startScan(
+ uint32_t interval_ms,
+ int32_t rssi_threshold,
+ const vector<vector<uint8_t>>& scan_ssids,
+ const vector<vector<uint8_t>>& match_ssids,
+ const vector<uint8_t>& match_security,
+ const vector<uint32_t> &freqs,
+ OffloadScanManager::ReasonCode* reason_code) {
+ if (!service_available_) {
+ *reason_code = OffloadScanManager::kNotSupported;
+ LOG(WARNING) << "Offload HAL scans are not supported";
+ return false;
+ } else if (offload_status_ == OffloadScanManager::kNotConnected) {
+ LOG(WARNING) << "Offload HAL scans are not available";
+ *reason_code = OffloadScanManager::kNotAvailable;
+ return false;
+ }
+
+ ScanParam param = OffloadScanUtils::createScanParam(scan_ssids, freqs,
+ interval_ms);
+ ScanFilter filter = OffloadScanUtils::createScanFilter(match_ssids,
+ match_security, rssi_threshold);
+
+ wifi_offload_hal_->configureScans(param, filter);
+ if (!subscription_enabled_) {
+ wifi_offload_hal_->subscribeScanResults(kSubscriptionDelayMs);
+ }
+ subscription_enabled_ = true;
+ *reason_code = OffloadScanManager::kNone;
+ return true;
+}
+
+OffloadScanManager::StatusCode OffloadScanManager::getOffloadStatus() const {
+ if (!service_available_) {
+ return OffloadScanManager::kNoService;
+ }
+ return offload_status_;
+}
+
+bool OffloadScanManager::isOffloadScanSupported() const {
+ bool result = false;
+#ifdef WIFI_OFFLOAD_SCANS
+ LOG(VERBOSE) << "Offload HAL supported";
+ result = true;
+#endif
+ return result;
+}
+
+bool OffloadScanManager::getScanStats(NativeScanStats* native_scan_stats) {
+ if (getOffloadStatus() != OffloadScanManager::kNoError) {
+ LOG(WARNING) << "Unable to get scan stats due to Wifi Offload HAL error";
+ return false;
+ }
+ wifi_offload_hal_->getScanStats(
+ [&native_scan_stats] (ScanStats offload_scan_stats)-> void {
+ *native_scan_stats =
+ OffloadScanUtils::convertToNativeScanStats(offload_scan_stats);
+ });
+ return true;
+}
+
OffloadScanManager::~OffloadScanManager() {}
void OffloadScanManager::ReportScanResults(
- const std::vector<ScanResult> scanResult) {
+ const vector<ScanResult> scanResult) {
if (scan_result_handler_ != nullptr) {
- scan_result_handler_(OffloadScanUtils::convertToNativeScanResults(scanResult));
+ scan_result_handler_(
+ OffloadScanUtils::convertToNativeScanResults(scanResult));
} else {
LOG(ERROR) << "No scan result handler for Offload ScanManager";
}
}
void OffloadScanManager::ReportError(OffloadStatus status) {
- StatusCode status_result = OffloadScanManager::kNoError;
+ OffloadScanManager::StatusCode status_result = OffloadScanManager::kNoError;
switch(status) {
case OffloadStatus::OFFLOAD_STATUS_OK:
status_result = OffloadScanManager::kNoError;
offload_status_ = status_result;
}
-OffloadScanManager::StatusCode OffloadScanManager::getOffloadStatus() const {
- return offload_status_;
-}
-
} // namespace wificond
} // namespace android
namespace wificond {
class NativeScanResult;
+class NativeScanStats;
} // namespace wificond
} // namespace wifi
kError
};
+ enum ReasonCode {
+ /* Default value */
+ kNone,
+ /* Offload HAL service not available */
+ kNotSupported,
+ /* Offload HAL service is not connected */
+ kNotAvailable,
+ /* Offload HAL service is not subscribed to */
+ kNotSubscribed,
+ };
+
explicit OffloadScanManager(OffloadServiceUtils* utils,
OnNativeScanResultsReadyHandler handler);
virtual ~OffloadScanManager();
- /* Caller can use this method to obtain status of the Offload HAL service
- * before invoking methods to perform disconnected PNO scans */
+ /* Request start of offload scans with scan parameters and scan filter
+ * settings. Internally calls Offload HAL service with configureScans()
+ * and subscribeScanResults() APIs. If already subscribed, it updates
+ * the scan configuration only. Reason code is updated in failure case
+ */
+ bool startScan(
+ uint32_t /* interval_ms */,
+ int32_t /* rssi_threshold */,
+ const std::vector<std::vector<uint8_t>>& /* scan_ssids */,
+ const std::vector<std::vector<uint8_t>>& /* match_ssids */,
+ const std::vector<uint8_t>& /* match_security */,
+ const std::vector<uint32_t>& /* freqs */,
+ ReasonCode* /* failure reason */);
+ /* Request stop of offload scans, returns true if scans were subscribed
+ * to from the Offload HAL service. Otherwise, returns false. Reason code
+ * is updated in case of failure.
+ */
+ bool stopScan(ReasonCode* /* failure reason */);
+ /* Get statistics for scans performed by Offload HAL */
+ bool getScanStats(
+ ::com::android::server::wifi::wificond::NativeScanStats* /* scanStats */);
+ /* Otain status of the Offload HAL service */
StatusCode getOffloadStatus() const;
+ /* Check if Offload service is supported on this device */
+ bool isOffloadScanSupported() const;
private:
void ReportScanResults(const std::vector<ScanResult> scanResult);
android::sp<IOffload> wifi_offload_hal_;
android::sp<OffloadCallback> wifi_offload_callback_;
- OnNativeScanResultsReadyHandler scan_result_handler_;
StatusCode offload_status_;
+ bool subscription_enabled_;
+ bool service_available_;
+
const std::unique_ptr<OffloadCallbackHandlersImpl> offload_callback_handlers_;
+ OnNativeScanResultsReadyHandler scan_result_handler_;
friend class OffloadCallbackHandlersImpl;
};
* limitations under the License.
*/
#include "wificond/scanning/offload/offload_scan_utils.h"
+
+#include <android-base/logging.h>
+
#include "wificond/scanning/scan_result.h"
+#include "wificond/scanning/offload/scan_stats.h"
using ::com::android::server::wifi::wificond::NativeScanResult;
+using ::com::android::server::wifi::wificond::NativeScanStats;
using android::hardware::wifi::offload::V1_0::ScanResult;
+using android::hardware::wifi::offload::V1_0::ScanParam;
+using android::hardware::wifi::offload::V1_0::ScanFilter;
+using android::hardware::wifi::offload::V1_0::ScanStats;
+using android::hardware::wifi::offload::V1_0::NetworkInfo;
+using android::hardware::hidl_vec;
+using std::vector;
namespace android {
namespace wificond {
-std::vector<NativeScanResult> OffloadScanUtils::convertToNativeScanResults(
- const std::vector<ScanResult>& scanResult) {
- std::vector<NativeScanResult> nativeScanResult;
- nativeScanResult.reserve(scanResult.size());
- for (size_t i = 0; i < scanResult.size(); i++) {
- NativeScanResult singleScanResult;
- singleScanResult.ssid = scanResult[i].networkInfo.ssid;
- singleScanResult.bssid.assign(scanResult[i].networkInfo.ssid.begin(),
- scanResult[i].networkInfo.ssid.end());
- singleScanResult.frequency = scanResult[i].frequency;
- singleScanResult.signal_mbm = scanResult[i].rssi;
- singleScanResult.tsf = scanResult[i].tsf;
- singleScanResult.capability = scanResult[i].capability;
- singleScanResult.associated = false;
- nativeScanResult.emplace_back(singleScanResult);
+vector<NativeScanResult> OffloadScanUtils::convertToNativeScanResults(
+ const vector<ScanResult>& scan_result) {
+ vector<NativeScanResult> native_scan_result;
+ native_scan_result.reserve(scan_result.size());
+ for (size_t i = 0; i < scan_result.size(); i++) {
+ NativeScanResult single_scan_result;
+ single_scan_result.ssid = scan_result[i].networkInfo.ssid;
+ single_scan_result.bssid.assign(scan_result[i].networkInfo.ssid.begin(),
+ scan_result[i].networkInfo.ssid.end());
+ single_scan_result.frequency = scan_result[i].frequency;
+ single_scan_result.signal_mbm = scan_result[i].rssi;
+ single_scan_result.tsf = scan_result[i].tsf;
+ single_scan_result.capability = scan_result[i].capability;
+ single_scan_result.associated = false;
+ native_scan_result.emplace_back(single_scan_result);
+ }
+ return native_scan_result;
+}
+
+ScanParam OffloadScanUtils::createScanParam(
+ const vector<vector<uint8_t>>& ssid_list,
+ const vector<uint32_t>& frequency_list, uint32_t scan_interval_ms) {
+ ScanParam scan_param;
+ scan_param.disconnectedModeScanIntervalMs = scan_interval_ms;
+ scan_param.frequencyList = frequency_list;
+ vector<hidl_vec<uint8_t>> ssid_list_tmp;
+ for (const auto& ssid : ssid_list) {
+ ssid_list_tmp.push_back(ssid);
+ }
+ scan_param.ssidList = ssid_list_tmp;
+ return scan_param;
+}
+
+ScanFilter OffloadScanUtils::createScanFilter(
+ const vector<vector<uint8_t>>& ssids,
+ const vector<uint8_t>& flags, int8_t rssi_threshold) {
+ ScanFilter scan_filter;
+ vector<NetworkInfo> nw_info_list;
+ size_t i = 0;
+ scan_filter.rssiThreshold = rssi_threshold;
+ // Note that the number of ssids should match the number of security flags
+ for (const auto& ssid : ssids) {
+ NetworkInfo nw_info;
+ nw_info.ssid = ssid;
+ if (i < flags.size()) {
+ nw_info.flags = flags[i++];
+ } else {
+ continue;
+ }
+ nw_info_list.push_back(nw_info);
}
- return nativeScanResult;
+ scan_filter.preferredNetworkInfoList = nw_info_list;
+ return scan_filter;
+}
+
+NativeScanStats OffloadScanUtils::convertToNativeScanStats(
+ const ScanStats& scanStats) {
+ uint32_t num_channels_scanned = 0;
+ uint32_t scan_duration_ms = 0;
+ vector<uint8_t> histogram_channels;
+
+ for (size_t i = 0; i < scanStats.scanRecord.size(); i++) {
+ scan_duration_ms += scanStats.scanRecord[i].durationMs;
+ num_channels_scanned +=
+ scanStats.scanRecord[i].numChannelsScanned;
+ }
+ for (size_t i = 0; i < scanStats.histogramChannelsScanned.size(); i++) {
+ histogram_channels.push_back(
+ scanStats.histogramChannelsScanned[i]);
+ }
+
+ NativeScanStats native_scan_stats(scanStats.numScansRequestedByWifi,
+ scanStats.numScansServicedByWifi,
+ scanStats.subscriptionDurationMs,
+ scan_duration_ms,
+ num_channels_scanned,
+ histogram_channels);
+ return native_scan_stats;
}
-} // wificond
-} // android
+} // namespace wificond
+} // namespace android
#include <vector>
using android::hardware::wifi::offload::V1_0::ScanResult;
+using android::hardware::wifi::offload::V1_0::ScanParam;
+using android::hardware::wifi::offload::V1_0::ScanFilter;
+using android::hardware::wifi::offload::V1_0::ScanStats;
namespace com {
namespace android {
namespace wificond {
class NativeScanResult;
+class NativeScanStats;
} // namespace wificond
} // namespace wifi
public:
static std::vector<::com::android::server::wifi::wificond::NativeScanResult>
convertToNativeScanResults(const std::vector<ScanResult>&);
+ static ScanParam createScanParam(
+ const std::vector<std::vector<uint8_t>>& ssid_list,
+ const std::vector<uint32_t>& frequency_list, uint32_t scan_interval_ms);
+ /* Creates ScanFilter using ssids, security flags and rssi_threshold
+ * The caller must ensure that the number of ssids match the number of security
+ * flags, also there must be ordering maintained among the two lists. For eg:
+ * (ssid[0], flags[0]) describe the SSID and security settings of one network
+ */
+ static ScanFilter createScanFilter(
+ const std::vector<std::vector<uint8_t>>& ssids,
+ const std::vector<uint8_t>& flags, int8_t rssi_threshold);
+ static ::com::android::server::wifi::wificond::NativeScanStats
+ convertToNativeScanStats(const ScanStats& /* scanStats */);
};
} // namespace wificond
--- /dev/null
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wificond/scanning/offload/scan_stats.h"
+
+#include <android-base/logging.h>
+
+#include "wificond/parcelable_utils.h"
+
+using android::status_t;
+
+namespace com {
+namespace android {
+namespace server {
+namespace wifi {
+namespace wificond {
+
+NativeScanStats::NativeScanStats(uint32_t num_scans_requested_by_wifi,
+ uint32_t num_scans_serviced_by_wifi,
+ uint32_t subscription_duration_ms,
+ uint32_t scan_duration_ms,
+ uint32_t num_channels_scanned,
+ std::vector<uint8_t> histogram_channels)
+ : num_scans_requested_by_wifi_(num_scans_requested_by_wifi),
+ num_scans_serviced_by_wifi_(num_scans_serviced_by_wifi),
+ subscription_duration_ms_(subscription_duration_ms),
+ scan_duration_ms_(scan_duration_ms),
+ num_channels_scanned_(num_channels_scanned),
+ time_stamp_(0),
+ histogram_channels_(histogram_channels) {
+}
+
+NativeScanStats::NativeScanStats()
+ : num_scans_requested_by_wifi_(0),
+ num_scans_serviced_by_wifi_(0),
+ subscription_duration_ms_(0),
+ num_channels_scanned_(0),
+ time_stamp_(0) {
+}
+
+bool NativeScanStats::operator==(const NativeScanStats& rhs) const {
+ bool result = true;
+ if ((rhs.num_scans_requested_by_wifi_ != num_scans_requested_by_wifi_) ||
+ (rhs.num_scans_serviced_by_wifi_ != num_scans_serviced_by_wifi_) ||
+ (rhs.scan_duration_ms_ != scan_duration_ms_) ||
+ (rhs.num_channels_scanned_ != num_channels_scanned_)) {
+ result = false;
+ }
+ if (rhs.histogram_channels_.size() != histogram_channels_.size()) {
+ return false;
+ }
+ for (size_t i = 0; i < histogram_channels_.size(); i++) {
+ if (rhs.histogram_channels_[i] != histogram_channels_[i]) {
+ result = false;
+ }
+ }
+ return result;
+}
+
+status_t NativeScanStats::writeToParcel(::android::Parcel* parcel) const {
+ RETURN_IF_FAILED(parcel->writeUint32(num_scans_requested_by_wifi_));
+ RETURN_IF_FAILED(parcel->writeUint32(num_scans_serviced_by_wifi_));
+ RETURN_IF_FAILED(parcel->writeUint32(subscription_duration_ms_));
+ RETURN_IF_FAILED(parcel->writeUint32(scan_duration_ms_));
+ RETURN_IF_FAILED(parcel->writeUint32(num_channels_scanned_));
+ RETURN_IF_FAILED(parcel->writeByteVector(histogram_channels_));
+ return ::android::OK;
+}
+
+status_t NativeScanStats::readFromParcel(const ::android::Parcel* parcel) {
+ RETURN_IF_FAILED(parcel->readUint32(&num_scans_requested_by_wifi_));
+ RETURN_IF_FAILED(parcel->readUint32(&num_scans_serviced_by_wifi_));
+ RETURN_IF_FAILED(parcel->readUint32(&subscription_duration_ms_));
+ RETURN_IF_FAILED(parcel->readUint32(&scan_duration_ms_));
+ RETURN_IF_FAILED(parcel->readUint32(&num_channels_scanned_));
+ RETURN_IF_FAILED(parcel->readByteVector(&histogram_channels_));
+ return ::android::OK;
+}
+
+
+} // namespace wificond
+} // namespace wifi
+} // namespace server
+} // namespace android
+} // namespace com
--- /dev/null
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WIFICOND_SCAN_STATS_H
+#define WIFICOND_SCAN_STATS_H
+
+#include <vector>
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+
+namespace com {
+namespace android {
+namespace server {
+namespace wifi {
+namespace wificond {
+
+class NativeScanStats : public ::android::Parcelable {
+ public:
+ NativeScanStats();
+ NativeScanStats(uint32_t num_scans_requested_by_wifi,
+ uint32_t num_scans_serviced_by_wifi,
+ uint32_t subscription_duration_ms,
+ uint32_t scan_duration_ms,
+ uint32_t num_channels_scanned,
+ std::vector<uint8_t> histogram_channels);
+
+ bool operator==(const NativeScanStats&) const;
+ ::android::status_t writeToParcel(::android::Parcel* parcel) const override;
+ ::android::status_t readFromParcel(const ::android::Parcel* parcel) override;
+
+ uint32_t num_scans_requested_by_wifi_;
+ uint32_t num_scans_serviced_by_wifi_;
+ uint32_t subscription_duration_ms_;
+ uint32_t scan_duration_ms_;
+ uint32_t num_channels_scanned_;
+ uint32_t time_stamp_;
+ std::vector<uint8_t> histogram_channels_;
+};
+
+} // namespace wificond
+} // namespace wifi
+} // namespace server
+} // namespace android
+} // namespace com
+#endif // WIFICOND_SCAN_STATS_H
+
vector<uint8_t> ssid;
if (!GetSSIDFromInfoElement(ie, &ssid)) {
// Skip BSS without SSID IE.
- // It might be from a hidden network. Framework doesn't need it.
- return false;
- }
- if (ssid.empty() ||
- std::all_of(ssid.begin(), ssid.end(), [](uint8_t c) {return c == 0;})) {
- // Skip BSS with empty or all-zero SSID.
- // It might be from a hidden network. Framework doesn't need it.
+ // These scan results are considered as malformed.
return false;
}
uint64_t tsf;
return true;
}
+bool ScanUtils::AbortScan(uint32_t interface_index) {
+ NL80211Packet abort_scan(
+ netlink_manager_->GetFamilyId(),
+ NL80211_CMD_ABORT_SCAN,
+ netlink_manager_->GetSequenceNumber(),
+ getpid());
+
+ // Force an ACK response upon success.
+ abort_scan.AddFlag(NLM_F_ACK);
+ abort_scan.AddAttribute(
+ NL80211Attr<uint32_t>(NL80211_ATTR_IFINDEX, interface_index));
+
+ if (!netlink_manager_->SendMessageAndGetAck(abort_scan)) {
+ LOG(ERROR) << "NL80211_CMD_ABORT_SCAN failed";
+ return false;
+ }
+ return true;
+}
+
bool ScanUtils::StartScheduledScan(
uint32_t interface_index,
uint32_t interval_ms,
// Returns false on error or when there is no scheduled scan running.
virtual bool StopScheduledScan(uint32_t interface_index);
+ // Abort ongoing single scan on interface with index |interface_index|.
+ // Returns true on success.
+ virtual bool AbortScan(uint32_t interface_index);
+
// Sign up to be notified when new scan results are available.
// |handler| will be called when the kernel signals to wificond that a scan
// has been completed on the given |interface_index|. See the declaration of
: valid_(true),
scan_started_(false),
pno_scan_started_(false),
+ offload_scan_supported_(false),
wiphy_index_(wiphy_index),
interface_index_(interface_index),
scan_capabilities_(scan_capabilities),
new OffloadScanManager(new OffloadServiceUtils(),
std::bind(&ScannerImpl::OnOffloadScanResult,
this, _1)));
+ offload_scan_supported_ = offload_scan_manager_->isOffloadScanSupported();
}
ScannerImpl::~ScannerImpl() {
Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,
bool* out_success) {
- if (!CheckIsValid()) {
- *out_success = false;
- return Status::ok();
- }
- if (pno_scan_started_) {
- LOG(WARNING) << "Pno scan already started";
+ if (!offload_scan_supported_ || !StartPnoScanOffload(pno_settings)) {
+ *out_success = StartPnoScanDefault(pno_settings);
+ } else {
+ // scanning over offload succeeded
+ *out_success = true;
}
- // An empty ssid for a wild card scan.
- vector<vector<uint8_t>> scan_ssids = {{}};
+ return Status::ok();
+}
+
+bool ScannerImpl::StartPnoScanOffload(const PnoSettings& pno_settings) {
+ OffloadScanManager::ReasonCode reason_code;
+ vector<vector<uint8_t>> scan_ssids;
vector<vector<uint8_t>> match_ssids;
+ vector<uint8_t> match_security;
// Empty frequency list: scan all frequencies.
vector<uint32_t> freqs;
+ ParsePnoSettings(pno_settings, &scan_ssids, &match_ssids, &freqs, &match_security);
+
+ bool success = offload_scan_manager_->startScan(
+ pno_settings.interval_ms_,
+ // TODO: honor both rssi thresholds.
+ pno_settings.min_5g_rssi_,
+ scan_ssids,
+ match_ssids,
+ match_security,
+ freqs,
+ &reason_code);
+ return success;
+}
+
+void ScannerImpl::ParsePnoSettings(const PnoSettings& pno_settings,
+ vector<vector<uint8_t>>* scan_ssids,
+ vector<vector<uint8_t>>* match_ssids,
+ vector<uint32_t>* freqs,
+ vector<uint8_t>* match_security) {
+ // TODO provide actionable security match parameters
+ const uint8_t kNetworkFlagsDefault = 0;
vector<vector<uint8_t>> skipped_scan_ssids;
vector<vector<uint8_t>> skipped_match_ssids;
for (auto& network : pno_settings.pno_networks_) {
// Add hidden network ssid.
if (network.is_hidden_) {
- if (scan_ssids.size() + 1 > scan_capabilities_.max_num_sched_scan_ssids) {
+ // TODO remove pruning for Offload Scans
+ if (scan_ssids->size() + 1 > scan_capabilities_.max_num_sched_scan_ssids) {
skipped_scan_ssids.emplace_back(network.ssid_);
continue;
}
- scan_ssids.push_back(network.ssid_);
+ scan_ssids->push_back(network.ssid_);
}
- if (match_ssids.size() + 1 > scan_capabilities_.max_match_sets) {
+ if (match_ssids->size() + 1 > scan_capabilities_.max_match_sets) {
skipped_match_ssids.emplace_back(network.ssid_);
continue;
}
- match_ssids.push_back(network.ssid_);
+ match_ssids->push_back(network.ssid_);
+ match_security->push_back(kNetworkFlagsDefault);
}
LogSsidList(skipped_scan_ssids, "Skip scan ssid for pno scan");
LogSsidList(skipped_match_ssids, "Skip match ssid for pno scan");
+}
+
+bool ScannerImpl::StartPnoScanDefault(const PnoSettings& pno_settings) {
+ if (!CheckIsValid()) {
+ return false;
+ }
+ if (pno_scan_started_) {
+ LOG(WARNING) << "Pno scan already started";
+ }
+ // An empty ssid for a wild card scan.
+ vector<vector<uint8_t>> scan_ssids = {{}};
+ vector<vector<uint8_t>> match_ssids;
+ vector<uint8_t> unused;
+ // Empty frequency list: scan all frequencies.
+ vector<uint32_t> freqs;
+ ParsePnoSettings(pno_settings, &scan_ssids, &match_ssids, &freqs, &unused);
// Only request MAC address randomization when station is not associated.
bool request_random_mac = wiphy_features_.supports_random_mac_sched_scan &&
!client_interface_->IsAssociated();
scan_ssids,
match_ssids,
freqs)) {
- *out_success = false;
LOG(ERROR) << "Failed to start pno scan";
- return Status::ok();
+ return false;
}
LOG(INFO) << "Pno scan started";
pno_scan_started_ = true;
- *out_success = true;
- return Status::ok();
+ return true;
}
Status ScannerImpl::stopPnoScan(bool* out_success) {
+ if (!offload_scan_supported_ || !StopPnoScanOffload()) {
+ *out_success = StopPnoScanDefault();
+ } else {
+ // Pno scans over offload stopped successfully
+ *out_success = true;
+ }
+ return Status::ok();
+}
+
+bool ScannerImpl::StopPnoScanOffload() {
+ OffloadScanManager::ReasonCode reason_code;
+ return(offload_scan_manager_->stopScan(&reason_code));
+}
+
+bool ScannerImpl::StopPnoScanDefault() {
if (!CheckIsValid()) {
- *out_success = false;
- return Status::ok();
+ return false;
}
if (!pno_scan_started_) {
LOG(WARNING) << "No pno scan started";
}
if (!scan_utils_->StopScheduledScan(interface_index_)) {
- *out_success = false;
- return Status::ok();
+ return false;
}
LOG(INFO) << "Pno scan stopped";
pno_scan_started_ = false;
- *out_success = true;
+ return true;
+}
+
+Status ScannerImpl::abortScan(bool* out_success) {
+ *out_success = false;
+ if (!CheckIsValid()) {
+ return Status::ok();
+ }
+
+ if (!scan_started_) {
+ LOG(WARNING) << "Scan is not started. Ignore abort request";
+ } else if (scan_utils_->AbortScan(interface_index_)) {
+ *out_success = true;
+ }
return Status::ok();
}
void ScannerImpl::OnOffloadScanResult(
std::vector<NativeScanResult> scanResult) {
- // TODO: Process scan result
- if (scan_event_handler_ != nullptr) {
- scan_event_handler_->OnScanResultReady();
+ LOG(INFO) << "Offload Scan results received";
+ if (pno_scan_event_handler_ != nullptr) {
+ pno_scan_event_handler_->OnPnoNetworkFound();
} else {
LOG(WARNING) << "No scan event handler Offload Scan result";
}
const ::com::android::server::wifi::wificond::PnoSettings& pno_settings,
bool* out_success) override;
::android::binder::Status stopPnoScan(bool* out_success) override;
+ ::android::binder::Status abortScan(bool* out_success) override;
::android::binder::Status subscribeScanEvents(
const ::android::sp<::android::net::wifi::IScanEvent>& handler) override;
void OnSchedScanResultsReady(uint32_t interface_index, bool scan_stopped);
void LogSsidList(std::vector<std::vector<uint8_t>>& ssid_list,
std::string prefix);
-
+ bool StartPnoScanDefault(
+ const ::com::android::server::wifi::wificond::PnoSettings& pno_settings);
+ bool StartPnoScanOffload(
+ const ::com::android::server::wifi::wificond::PnoSettings& pno_settings);
+ bool StopPnoScanDefault();
+ bool StopPnoScanOffload();
+ void ParsePnoSettings(
+ const ::com::android::server::wifi::wificond::PnoSettings& pno_settings,
+ std::vector<std::vector<uint8_t>>* scan_ssids,
+ std::vector<std::vector<uint8_t>>* match_ssids,
+ std::vector<uint32_t>* freqs,
+ std::vector<uint8_t>* match_security);
// Boolean variables describing current scanner status.
bool valid_;
bool scan_started_;
bool pno_scan_started_;
+ bool offload_scan_supported_;
const uint32_t wiphy_index_;
const uint32_t interface_index_;
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "offload_hal_test_constants.h"
+
+namespace android {
+namespace wificond {
+namespace offload_hal_test_constants {
+
+const uint8_t kSsid1[] = { 'G', 'o', 'o', 'g', 'l', 'e' };
+const size_t kSsid1_size = sizeof(kSsid1);
+const uint8_t kSsid2[] = { 'X', 'f', 'i', 'n', 'i', 't', 'y' };
+const size_t kSsid2_size = sizeof(kSsid2);
+const uint8_t kBssid [6] = { 0x12, 0xef, 0xa1, 0x2c, 0x97, 0x8b };
+const int16_t kRssi = -60;
+const int16_t kRssiThreshold = -76;
+const uint32_t kFrequency1 = 2412;
+const uint32_t kFrequency2 = 2437;
+const uint8_t kBssidSize = 6;
+const uint64_t kTsf = 0;
+const uint16_t kCapability = 0;
+const uint8_t kNetworkFlags = 0;
+const uint32_t kDisconnectedModeScanIntervalMs = 5000;
+const uint64_t kSubscriptionDurationMs = 10000;
+const uint64_t kScanDurationMs[2] = { 2000, 500 };
+const uint32_t kNumChannelsScanned[2] = { 14, 6 };
+const uint8_t kDefaultNumTimesAChannelsIsScanned = 1;
+const uint8_t kChannelNotScanned = 0;
+const uint32_t kDefaultNumScansRequestedByWifi = 2;
+const uint32_t kDefaultNumScansServicedByWifi = 2;
+const uint64_t kScanDurationTotalMs = 2000;
+const uint32_t kNumChannelsTotalScanned = 20;
+
+} // namespace offload_hal_test_constants
+} // namespace wificond
+} // namespace android
+
--- /dev/null
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WIFICOND_OFFLOAD_HAL_TEST_CONSTANTS_H_
+#define WIFICOND_OFFLOAD_HAL_TEST_CONSTANTS_H_
+
+#include <cstdint>
+
+namespace android {
+namespace wificond {
+namespace offload_hal_test_constants {
+
+extern const uint8_t kSsid1[];
+extern const size_t kSsid1_size;
+extern const uint8_t kSsid2[];
+extern const size_t kSsid2_size;
+extern const uint8_t kBssid [6];
+extern const int16_t kRssi;
+extern const int16_t kRssiThreshold;
+extern const uint32_t kFrequency1;
+extern const uint32_t kFrequency2;
+extern const uint8_t kBssidSize;
+extern const uint64_t kTsf;
+extern const uint16_t kCapability;
+extern const uint8_t kNetworkFlags;
+extern const uint32_t kDisconnectedModeScanIntervalMs;
+extern const uint64_t kSubscriptionDurationMs;
+extern const uint64_t kScanDurationMs[2];
+extern const uint32_t kNumChannelsScanned[2];
+extern const uint8_t kDefaultNumTimesAChannelsIsScanned;
+extern const uint8_t kChannelNotScanned;
+extern const uint32_t kDefaultNumScansRequestedByWifi;
+extern const uint32_t kDefaultNumScansServicedByWifi;
+extern const uint64_t kScanDurationTotalMs;
+extern const uint32_t kNumChannelsTotalScanned;
+
+} // namespace offload_hal_test_constants
+} // namespace wificond
+} // namespace android
+
+#endif // WIFICOND_OFFLOAD_HAL_TEST_CONSTANTS_H_
#include <gtest/gtest.h>
#include <android/hardware/wifi/offload/1.0/IOffload.h>
+#include "wificond/tests/offload_hal_test_constants.h"
+#include "wificond/tests/offload_test_utils.h"
#include "wificond/tests/mock_offload.h"
#include "wificond/tests/mock_offload_service_utils.h"
-#include "wificond/tests/offload_test_utils.h"
#include "wificond/scanning/scan_result.h"
#include "wificond/scanning/offload/offload_callback.h"
using android::hardware::wifi::offload::V1_0::ScanResult;
using android::hardware::wifi::offload::V1_0::OffloadStatus;
+using android::hardware::wifi::offload::V1_0::ScanParam;
+using android::hardware::wifi::offload::V1_0::ScanFilter;
using com::android::server::wifi::wificond::NativeScanResult;
+using com::android::server::wifi::wificond::NativeScanStats;
using testing::NiceMock;
using testing::_;
using testing::Invoke;
using std::bind;
using namespace std::placeholders;
+using namespace android::wificond::offload_hal_test_constants;
namespace android {
namespace wificond {
unique_ptr<NiceMock<MockOffloadServiceUtils>> mock_offload_service_utils_{
new NiceMock<MockOffloadServiceUtils>()};
unique_ptr<OffloadScanManager> offload_scan_manager_;
+ vector<vector<uint8_t>> scan_ssids { kSsid1, kSsid2};
+ vector<vector<uint8_t>> match_ssids { kSsid1, kSsid2 };
+ vector<uint8_t> security_flags { kNetworkFlags, kNetworkFlags };
+ vector<uint32_t> frequencies { kFrequency1, kFrequency2 };
};
/**
*/
TEST_F(OffloadScanManagerTest, ServiceUtilsNotAvailableTest) {
offload_scan_manager_.reset(new OffloadScanManager(nullptr, nullptr));
- EXPECT_EQ(OffloadScanManager::kError, offload_scan_manager_->getOffloadStatus());
+ EXPECT_EQ(OffloadScanManager::kNoService,
+ offload_scan_manager_->getOffloadStatus());
}
/**
TEST_F(OffloadScanManagerTest, ServiceNotAvailableTest) {
ON_CALL(*mock_offload_service_utils_, GetOffloadService())
.WillByDefault(testing::Return(nullptr));
- offload_scan_manager_.reset(new OffloadScanManager(mock_offload_service_utils_.get(),
- [] (std::vector<NativeScanResult> scanResult) -> void {}));
- EXPECT_EQ(OffloadScanManager::kNoService, offload_scan_manager_->getOffloadStatus());
+ offload_scan_manager_.reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ EXPECT_EQ(OffloadScanManager::kNoService,
+ offload_scan_manager_->getOffloadStatus());
}
/**
EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
ON_CALL(*mock_offload_service_utils_, GetOffloadService())
.WillByDefault(testing::Return(mock_offload_));
- offload_scan_manager_ .reset(new OffloadScanManager(mock_offload_service_utils_.get(),
- [] (vector<NativeScanResult> scanResult) -> void {}));
- EXPECT_EQ(OffloadScanManager::kNoError, offload_scan_manager_->getOffloadStatus());
+ offload_scan_manager_ .reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ EXPECT_EQ(OffloadScanManager::kNoError,
+ offload_scan_manager_->getOffloadStatus());
}
/**
EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
ON_CALL(*mock_offload_service_utils_, GetOffloadService())
.WillByDefault(testing::Return(mock_offload_));
- offload_scan_manager_.reset(new OffloadScanManager(mock_offload_service_utils_.get(),
- [&callback_invoked] (vector<NativeScanResult> scanResult) -> void {
+ offload_scan_manager_.reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [&callback_invoked] (vector<NativeScanResult> scanResult) -> void {
callback_invoked = true;
- }));
- vector<ScanResult> dummy_scan_results_ = OffloadTestUtils::createOffloadScanResults();
+ }));
+ vector<ScanResult> dummy_scan_results_ =
+ OffloadTestUtils::createOffloadScanResults();
offload_callback_->onScanResult(dummy_scan_results_);
EXPECT_EQ(true, callback_invoked);
}
EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
ON_CALL(*mock_offload_service_utils_, GetOffloadService())
.WillByDefault(testing::Return(mock_offload_));
- offload_scan_manager_.reset(new OffloadScanManager(mock_offload_service_utils_.get(),
- [this] (std::vector<NativeScanResult> scanResult) -> void {}));
+ offload_scan_manager_.reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [this] (vector<NativeScanResult> scanResult) -> void {}));
offload_callback_->onError(OffloadStatus::OFFLOAD_STATUS_ERROR);
- EXPECT_EQ(offload_scan_manager_->getOffloadStatus(), OffloadScanManager::kError);
+ EXPECT_EQ(offload_scan_manager_->getOffloadStatus(),
+ OffloadScanManager::kError);
+}
+
+/**
+ * Testing OffloadScanManager for subscribing to the scan results from
+ * Offload HAL when service is running without errors
+ */
+TEST_F(OffloadScanManagerTest, StartScanTestWhenServiceIsOk) {
+ EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
+ ON_CALL(*mock_offload_service_utils_, GetOffloadService())
+ .WillByDefault(testing::Return(mock_offload_));
+ offload_scan_manager_ .reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ EXPECT_CALL(*mock_offload_, subscribeScanResults(_));
+ EXPECT_CALL(*mock_offload_, configureScans(_, _));
+ OffloadScanManager::ReasonCode reason_code = OffloadScanManager::kNone;
+ bool result = offload_scan_manager_->startScan(
+ kDisconnectedModeScanIntervalMs,
+ kRssiThreshold,
+ scan_ssids,
+ match_ssids,
+ security_flags,
+ frequencies,
+ &reason_code);
+ EXPECT_EQ(result, true);
+}
+
+/**
+ * Testing OffloadScanManager for subscribing to the scan results from
+ * Offload HAL when service is not available
+ */
+TEST_F(OffloadScanManagerTest, StartScanTestWhenServiceIsNotAvailable) {
+ EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
+ ON_CALL(*mock_offload_service_utils_, GetOffloadService())
+ .WillByDefault(testing::Return(nullptr));
+ offload_scan_manager_ .reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ OffloadScanManager::ReasonCode reason_code = OffloadScanManager::kNone;
+ bool result = offload_scan_manager_->startScan(
+ kDisconnectedModeScanIntervalMs,
+ kRssiThreshold,
+ scan_ssids,
+ match_ssids,
+ security_flags,
+ frequencies,
+ &reason_code);
+ EXPECT_EQ(result, false);
+ EXPECT_EQ(reason_code, OffloadScanManager::kNotSupported);
+}
+
+/**
+ * Testing OffloadScanManager for subscribing to the scan results from
+ * Offload HAL when service is not working correctly
+ */
+TEST_F(OffloadScanManagerTest, StartScanTestWhenServiceIsNotConnected) {
+ EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
+ ON_CALL(*mock_offload_service_utils_, GetOffloadService())
+ .WillByDefault(testing::Return(mock_offload_));
+ offload_scan_manager_ .reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ offload_callback_->onError(OffloadStatus::OFFLOAD_STATUS_NO_CONNECTION);
+ OffloadScanManager::ReasonCode reason_code = OffloadScanManager::kNone;
+ bool result = offload_scan_manager_->startScan(
+ kDisconnectedModeScanIntervalMs,
+ kRssiThreshold,
+ scan_ssids,
+ match_ssids,
+ security_flags,
+ frequencies,
+ &reason_code);
+ EXPECT_EQ(result, false);
+ EXPECT_EQ(reason_code, OffloadScanManager::kNotAvailable);
+}
+
+/**
+ * Testing OffloadScanManager for subscribing to the scan results from
+ * Offload HAL twice when service is okay
+ */
+TEST_F(OffloadScanManagerTest, StartScanTwiceTestWhenServiceIsOk) {
+ EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
+ ON_CALL(*mock_offload_service_utils_, GetOffloadService())
+ .WillByDefault(testing::Return(mock_offload_));
+ offload_scan_manager_ .reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ EXPECT_CALL(*mock_offload_, subscribeScanResults(_)).Times(1);
+ EXPECT_CALL(*mock_offload_, configureScans(_, _)).Times(2);
+ OffloadScanManager::ReasonCode reason_code = OffloadScanManager::kNone;
+ bool result = offload_scan_manager_->startScan(
+ kDisconnectedModeScanIntervalMs,
+ kRssiThreshold,
+ scan_ssids,
+ match_ssids,
+ security_flags,
+ frequencies,
+ &reason_code);
+ EXPECT_EQ(result, true);
+ result = offload_scan_manager_->startScan(
+ kDisconnectedModeScanIntervalMs,
+ kRssiThreshold,
+ scan_ssids,
+ match_ssids,
+ security_flags,
+ frequencies,
+ &reason_code);
+ EXPECT_EQ(result, true);
+}
+
+/**
+ * Testing OffloadScanManager for unsubscribing to the scan results from
+ * Offload HAL when service is ok
+ */
+TEST_F(OffloadScanManagerTest, StopScanTestWhenServiceIsOk) {
+ EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
+ ON_CALL(*mock_offload_service_utils_, GetOffloadService())
+ .WillByDefault(testing::Return(mock_offload_));
+ offload_scan_manager_ .reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ EXPECT_CALL(*mock_offload_, subscribeScanResults(_));
+ EXPECT_CALL(*mock_offload_, configureScans(_, _));
+ EXPECT_CALL(*mock_offload_, unsubscribeScanResults());
+ OffloadScanManager::ReasonCode reason_code = OffloadScanManager::kNone;
+ bool result = offload_scan_manager_->startScan(
+ kDisconnectedModeScanIntervalMs,
+ kRssiThreshold,
+ scan_ssids,
+ match_ssids,
+ security_flags,
+ frequencies,
+ &reason_code);
+ EXPECT_EQ(result, true);
+ result = offload_scan_manager_->stopScan(&reason_code);
+ EXPECT_EQ(result, true);
+}
+
+/**
+ * Testing OffloadScanManager for unsubscribing to the scan results from
+ * Offload HAL without first subscribing
+ */
+TEST_F(OffloadScanManagerTest, StopScanTestWithoutStartWhenServiceIsOk) {
+ EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
+ ON_CALL(*mock_offload_service_utils_, GetOffloadService())
+ .WillByDefault(testing::Return(mock_offload_));
+ offload_scan_manager_ .reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ OffloadScanManager::ReasonCode reason_code = OffloadScanManager::kNone;
+ bool result = offload_scan_manager_->stopScan(&reason_code);
+ EXPECT_EQ(result, false);
+ EXPECT_EQ(reason_code, OffloadScanManager::kNotSubscribed);
+}
+
+/**
+ * Testing OffloadScanManager for unsubscribing to the scan results from
+ * Offload HAL without first subscribing when service is not working correctly
+ */
+TEST_F(OffloadScanManagerTest, StopScanTestWhenServiceIsNotConnectedAnymore) {
+ EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
+ ON_CALL(*mock_offload_service_utils_, GetOffloadService())
+ .WillByDefault(testing::Return(mock_offload_));
+ offload_scan_manager_ .reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ EXPECT_CALL(*mock_offload_, subscribeScanResults(_));
+ EXPECT_CALL(*mock_offload_, configureScans(_, _));
+ EXPECT_CALL(*mock_offload_, unsubscribeScanResults());
+ OffloadScanManager::ReasonCode reason_code = OffloadScanManager::kNone;
+ bool result = offload_scan_manager_->startScan(
+ kDisconnectedModeScanIntervalMs,
+ kRssiThreshold,
+ scan_ssids,
+ match_ssids,
+ security_flags,
+ frequencies,
+ &reason_code);
+ EXPECT_EQ(result, true);
+ offload_callback_->onError(OffloadStatus::OFFLOAD_STATUS_NO_CONNECTION);
+ result = offload_scan_manager_->stopScan(&reason_code);
+ EXPECT_EQ(result, true);
+}
+
+/**
+ * Testing OffloadScanManager for getting scan statistics when the
+ * Offload HAL service is running without errors
+ */
+TEST_F(OffloadScanManagerTest, getScanStatsTestWhenServiceIsOk) {
+ EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
+ ON_CALL(*mock_offload_service_utils_, GetOffloadService())
+ .WillByDefault(testing::Return(mock_offload_));
+ offload_scan_manager_ .reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ EXPECT_CALL(*mock_offload_, getScanStats(_));
+ NativeScanStats stats;
+ bool result = offload_scan_manager_->getScanStats(&stats);
+ EXPECT_EQ(result, true);
+}
+
+/**
+ * Testing OffloadScanManager for getting scan statistics when the
+ * Offload HAL service is not connected
+ */
+TEST_F(OffloadScanManagerTest, getScanStatsTestWhenServiceIsNotOk) {
+ EXPECT_CALL(*mock_offload_service_utils_, GetOffloadService());
+ ON_CALL(*mock_offload_service_utils_, GetOffloadService())
+ .WillByDefault(testing::Return(mock_offload_));
+ offload_scan_manager_ .reset(new OffloadScanManager(
+ mock_offload_service_utils_.get(),
+ [] (vector<NativeScanResult> scanResult) -> void {}));
+ offload_callback_->onError(OffloadStatus::OFFLOAD_STATUS_NO_CONNECTION);
+ EXPECT_CALL(*mock_offload_, getScanStats(_)).Times(0);
+ NativeScanStats stats;
+ bool result = offload_scan_manager_->getScanStats(&stats);
+ EXPECT_EQ(result, false);
}
} // namespace wificond
} // namespace android
+
#include <gtest/gtest.h>
#include "wificond/tests/offload_test_utils.h"
-
+#include <android-base/logging.h>
#include "wificond/scanning/scan_result.h"
#include "wificond/scanning/offload/offload_scan_utils.h"
+#include "wificond/tests/offload_hal_test_constants.h"
using android::hardware::wifi::offload::V1_0::ScanResult;
+using android::hardware::wifi::offload::V1_0::ScanParam;
+using android::hardware::wifi::offload::V1_0::ScanFilter;
+using android::hardware::wifi::offload::V1_0::NetworkInfo;
+using android::hardware::wifi::offload::V1_0::ScanRecord;
+using android::hardware::wifi::offload::V1_0::ScanStats;
using ::com::android::server::wifi::wificond::NativeScanResult;
+using ::com::android::server::wifi::wificond::NativeScanStats;
+using std::vector;
+
+using namespace android::wificond::offload_hal_test_constants;
namespace android {
namespace wificond {
dummy_scan_results_.clear();
}
- std::vector<ScanResult> dummy_scan_results_;
+ vector<ScanResult> dummy_scan_results_;
};
TEST_F(OffloadScanUtilsTest, verifyConversion) {
- std::vector<NativeScanResult> native_scan_results =
+ vector<NativeScanResult> native_scan_results =
OffloadScanUtils::convertToNativeScanResults(dummy_scan_results_);
EXPECT_EQ(native_scan_results.size(), dummy_scan_results_.size());
for (size_t i = 0; i < native_scan_results.size(); i++) {
EXPECT_EQ(native_scan_results[i].frequency, dummy_scan_results_[i].frequency);
EXPECT_EQ(native_scan_results[i].tsf, dummy_scan_results_[i].tsf);
EXPECT_EQ(native_scan_results[i].signal_mbm, dummy_scan_results_[i].rssi);
- EXPECT_EQ(native_scan_results[i].ssid.size(), dummy_scan_results_[i].networkInfo.ssid.size());
- EXPECT_EQ(native_scan_results[i].bssid.size(), dummy_scan_results_[i].bssid.elementCount());
+ EXPECT_EQ(native_scan_results[i].ssid.size(),
+ dummy_scan_results_[i].networkInfo.ssid.size());
+ EXPECT_EQ(native_scan_results[i].bssid.size(),
+ dummy_scan_results_[i].bssid.elementCount());
EXPECT_EQ(native_scan_results[i].capability, dummy_scan_results_[i].capability);
}
}
+TEST_F(OffloadScanUtilsTest, verifyScanParam) {
+ vector<vector<uint8_t>> scan_ssids { kSsid1, kSsid2};
+ vector<uint32_t> frequencies { kFrequency1, kFrequency2 };
+ ScanParam scanParam = OffloadScanUtils::createScanParam(scan_ssids, frequencies,
+ kDisconnectedModeScanIntervalMs);
+ EXPECT_EQ(scanParam.disconnectedModeScanIntervalMs,
+ kDisconnectedModeScanIntervalMs);
+ for (size_t i = 0; i < frequencies.size(); i++) {
+ EXPECT_EQ(scanParam.frequencyList[i], frequencies[i]);
+ }
+ for (size_t j = 0; j < scan_ssids.size(); j++) {
+ vector<uint8_t> ssid_result = scanParam.ssidList[j];
+ vector<uint8_t> ssid_input = scan_ssids[j];
+ for (size_t k = 0; k < ssid_result.size(); k++) {
+ EXPECT_EQ(ssid_result[k], ssid_input[k]);
+ }
+ }
+}
+
+TEST_F(OffloadScanUtilsTest, verifyScanFilter) {
+ vector<vector<uint8_t>> match_ssids { kSsid1, kSsid2 };
+ vector<uint8_t> security_flags { kNetworkFlags, kNetworkFlags };
+ ScanFilter scanFilter = OffloadScanUtils::createScanFilter(match_ssids,
+ security_flags, kRssiThreshold);
+ EXPECT_EQ(kRssiThreshold, scanFilter.rssiThreshold);
+ EXPECT_FALSE(scanFilter.preferredNetworkInfoList.size() == 0);
+ for (size_t i = 0; i < security_flags.size(); ++i) {
+ NetworkInfo nwInfo = scanFilter.preferredNetworkInfoList[i];
+ vector<uint8_t> ssid = nwInfo.ssid;
+ vector<uint8_t> match_ssid = match_ssids[i];
+ EXPECT_EQ(nwInfo.flags, security_flags[i]);
+ for (size_t j = 0; j < ssid.size(); j++) {
+ EXPECT_EQ(ssid[j], match_ssid[j]);
+ }
+ }
+}
+
+TEST_F(OffloadScanUtilsTest, verifyScanStats) {
+ NativeScanStats stats_expected;
+ ScanStats offload_scan_stats = OffloadTestUtils::createScanStats(&stats_expected);
+ NativeScanStats stats_returned = OffloadScanUtils::convertToNativeScanStats(
+ offload_scan_stats);
+ EXPECT_TRUE(stats_expected == stats_returned);
+}
+
} // namespace wificond
} // namespace android
#include <vector>
#include "wificond/tests/offload_test_utils.h"
+#include "wificond/tests/offload_hal_test_constants.h"
using android::hardware::wifi::offload::V1_0::ScanResult;
+using android::hardware::wifi::offload::V1_0::ScanStats;
+using android::hardware::wifi::offload::V1_0::ScanRecord;
+using namespace android::wificond::offload_hal_test_constants;
namespace android {
namespace wificond {
-namespace {
- const uint8_t kSsid[] = { 'G', 'o', 'o', 'g', 'l', 'e' };
- const uint8_t kBssid [6] = { 0x12, 0xef, 0xa1, 0x2c, 0x97, 0x8b };
- const int16_t kRssi = -60;
- const uint32_t kFrequency = 2412;
- const uint8_t kBssidSize = 6;
- const uint64_t kTsf = 0;
- const uint16_t kCapability = 0;
- const uint8_t kNetworkFlags = 0;
-} // namespace
-
std::vector<ScanResult> OffloadTestUtils::createOffloadScanResults() {
std::vector<ScanResult> scanResults;
ScanResult scanResult;
- std::vector<uint8_t> ssid(kSsid, kSsid + sizeof(kSsid));
+ std::vector<uint8_t> ssid(kSsid1, kSsid1 + kSsid1_size);
scanResult.tsf = kTsf;
scanResult.rssi = kRssi;
- scanResult.frequency = kFrequency;
+ scanResult.frequency = kFrequency1;
scanResult.capability = kCapability;
memcpy(&scanResult.bssid[0], &kBssid[0], kBssidSize);
scanResult.networkInfo.ssid = ssid;
return scanResults;
}
+ScanStats OffloadTestUtils::createScanStats(NativeScanStats* nativeScanStats) {
+ std::vector<ScanRecord> scan_records;
+ std::vector<uint8_t> histogram_channels;
+ uint32_t scan_duration_ms = 0;
+ uint32_t num_channels_scanned = 0;
+ ScanStats scan_stats;
+ int numEntriesInScanRecord =
+ sizeof(kNumChannelsScanned)/sizeof(kNumChannelsScanned[0]);
+ for (int i = 0; i < numEntriesInScanRecord; i++) {
+ ScanRecord scan_record;
+ scan_record.durationMs = kScanDurationMs[i];
+ scan_duration_ms += kScanDurationMs[i];
+ scan_record.numChannelsScanned = kNumChannelsScanned[i];
+ num_channels_scanned += kNumChannelsScanned[i];
+ scan_record.numEntriesAggregated = 1;
+ scan_records.push_back(scan_record);
+ }
+ scan_stats.scanRecord = scan_records;
+ scan_stats.numScansRequestedByWifi = kDefaultNumScansRequestedByWifi;
+ scan_stats.numScansServicedByWifi = kDefaultNumScansServicedByWifi;
+ scan_stats.subscriptionDurationMs = kSubscriptionDurationMs;
+ uint32_t skip_tmp = 256/num_channels_scanned;
+ for(size_t i = 0; i < 256; i++) {
+ if (i % skip_tmp == 0) {
+ scan_stats.histogramChannelsScanned[i] = kDefaultNumTimesAChannelsIsScanned;
+ histogram_channels.push_back(kDefaultNumTimesAChannelsIsScanned);
+ } else {
+ scan_stats.histogramChannelsScanned[i] = kChannelNotScanned;
+ histogram_channels.push_back(kChannelNotScanned);
+ }
+ }
+ NativeScanStats native_scan_stats(kDefaultNumScansRequestedByWifi,
+ kDefaultNumScansServicedByWifi,
+ kSubscriptionDurationMs,
+ scan_duration_ms,
+ num_channels_scanned,
+ histogram_channels);
+ *nativeScanStats = native_scan_stats;
+ return scan_stats;
+}
+
} // namespace wificond
} // namespace android
#include <android/hardware/wifi/offload/1.0/IOffload.h>
#include <vector>
+
+#include "wificond/scanning/offload/scan_stats.h"
+
using android::hardware::wifi::offload::V1_0::ScanResult;
+using android::hardware::wifi::offload::V1_0::ScanStats;
+using ::com::android::server::wifi::wificond::NativeScanStats;
+
namespace android {
namespace wificond {
class OffloadTestUtils {
public:
static std::vector<ScanResult> createOffloadScanResults();
+ static ScanStats createScanStats(NativeScanStats* /* nativeScanStats */);
};
} // namespace wificond
--- /dev/null
+/*
+ * Copyright (C) 2017, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include "wificond/scanning/offload/scan_stats.h"
+#include "wificond/tests/offload_hal_test_constants.h"
+
+using ::com::android::server::wifi::wificond::NativeScanStats;
+using namespace android::wificond::offload_hal_test_constants;
+
+namespace android {
+namespace wificond {
+
+class ScanStatsTest : public ::testing::Test {
+};
+
+TEST_F(ScanStatsTest, ParcelableTest) {
+ std::vector<uint8_t> histogram_channels;
+ for(size_t i = 0; i < 256; i++) {
+ histogram_channels.push_back(255 - i);
+ }
+ NativeScanStats scan_stats_in(kDefaultNumScansRequestedByWifi,
+ kDefaultNumScansServicedByWifi,
+ kScanDurationTotalMs,
+ kSubscriptionDurationMs,
+ kNumChannelsTotalScanned,
+ histogram_channels);
+ Parcel parcel;
+ EXPECT_EQ(::android::OK, scan_stats_in.writeToParcel(&parcel));
+ NativeScanStats scan_stats_out;
+ parcel.setDataPosition(0);
+ EXPECT_EQ(::android::OK, scan_stats_out.readFromParcel(&parcel));
+ EXPECT_TRUE(scan_stats_in == scan_stats_out);
+}
+
+} // namespace wificond
+} // namespace android