#include <android-base/logging.h>
+#include "wificond/client_interface_impl.h"
#include "wificond/scanning/scan_utils.h"
using android::binder::Status;
namespace android {
namespace wificond {
-ScannerImpl::ScannerImpl(uint32_t interface_index,
- const BandInfo& band_info,
+ScannerImpl::ScannerImpl(uint32_t wiphy_index,
+ uint32_t interface_index,
const ScanCapabilities& scan_capabilities,
const WiphyFeatures& wiphy_features,
+ ClientInterfaceImpl* client_interface,
+ NetlinkUtils* netlink_utils,
ScanUtils* scan_utils)
: valid_(true),
scan_started_(false),
pno_scan_started_(false),
+ wiphy_index_(wiphy_index),
interface_index_(interface_index),
- band_info_(band_info),
scan_capabilities_(scan_capabilities),
wiphy_features_(wiphy_features),
+ client_interface_(client_interface),
+ netlink_utils_(netlink_utils),
scan_utils_(scan_utils),
scan_event_handler_(nullptr) {
// Subscribe one-shot scan result notification from kernel.
}
ScannerImpl::~ScannerImpl() {
+}
+
+void ScannerImpl::Invalidate() {
LOG(INFO) << "Unsubscribe scan result for interface with index: "
<< (int)interface_index_;
scan_utils_->UnsubscribeScanResultNotification(interface_index_);
return valid_;
}
-Status ScannerImpl::getAvailable2gChannels(vector<int32_t>* out_frequencies) {
+Status ScannerImpl::getAvailable2gChannels(
+ std::unique_ptr<vector<int32_t>>* out_frequencies) {
if (!CheckIsValid()) {
return Status::ok();
}
- *out_frequencies = vector<int32_t>(band_info_.band_2g.begin(),
- band_info_.band_2g.end());
+ BandInfo band_info;
+ if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
+ &band_info,
+ &scan_capabilities_,
+ &wiphy_features_)) {
+ LOG(ERROR) << "Failed to get wiphy info from kernel";
+ out_frequencies->reset(nullptr);
+ return Status::ok();
+ }
+
+ out_frequencies->reset(new vector<int32_t>(band_info.band_2g.begin(),
+ band_info.band_2g.end()));
return Status::ok();
}
Status ScannerImpl::getAvailable5gNonDFSChannels(
- vector<int32_t>* out_frequencies) {
+ std::unique_ptr<vector<int32_t>>* out_frequencies) {
if (!CheckIsValid()) {
return Status::ok();
}
- *out_frequencies = vector<int32_t>(band_info_.band_5g.begin(),
- band_info_.band_5g.end());
+ BandInfo band_info;
+ if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
+ &band_info,
+ &scan_capabilities_,
+ &wiphy_features_)) {
+ LOG(ERROR) << "Failed to get wiphy info from kernel";
+ out_frequencies->reset(nullptr);
+ return Status::ok();
+ }
+
+ out_frequencies->reset(new vector<int32_t>(band_info.band_5g.begin(),
+ band_info.band_5g.end()));
return Status::ok();
}
-Status ScannerImpl::getAvailableDFSChannels(vector<int32_t>* out_frequencies) {
+Status ScannerImpl::getAvailableDFSChannels(
+ std::unique_ptr<vector<int32_t>>* out_frequencies) {
if (!CheckIsValid()) {
return Status::ok();
}
- *out_frequencies = vector<int32_t>(band_info_.band_dfs.begin(),
- band_info_.band_dfs.end());
+ BandInfo band_info;
+ if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
+ &band_info,
+ &scan_capabilities_,
+ &wiphy_features_)) {
+ LOG(ERROR) << "Failed to get wiphy info from kernel";
+ out_frequencies->reset(nullptr);
+ return Status::ok();
+ }
+
+ out_frequencies->reset(new vector<int32_t>(band_info.band_dfs.begin(),
+ band_info.band_dfs.end()));
return Status::ok();
}
Status ScannerImpl::scan(const SingleScanSettings& scan_settings,
bool* out_success) {
if (!CheckIsValid()) {
+ *out_success = false;
return Status::ok();
}
if (scan_started_) {
LOG(WARNING) << "Scan already started";
}
- bool random_mac = wiphy_features_.supports_random_mac_oneshot_scan;
+ // Only request MAC address randomization when station is not associated.
+ bool request_random_mac = wiphy_features_.supports_random_mac_oneshot_scan &&
+ !client_interface_->IsAssociated();
// Initialize it with an empty ssid for a wild card scan.
vector<vector<uint8_t>> ssids = {{}};
+
+ vector<vector<uint8_t>> skipped_scan_ssids;
for (auto& network : scan_settings.hidden_networks_) {
if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {
- LOG(WARNING) << "Skip scan ssid for single scan: "
- << string(network.ssid_.begin(), network.ssid_.end());
+ skipped_scan_ssids.emplace_back(network.ssid_);
continue;
}
ssids.push_back(network.ssid_);
}
+ LogSsidList(skipped_scan_ssids, "Skip scan ssid for single scan");
+
vector<uint32_t> freqs;
for (auto& channel : scan_settings.channel_settings_) {
freqs.push_back(channel.frequency_);
}
- if (!scan_utils_->Scan(interface_index_, random_mac, ssids, freqs)) {
+ if (!scan_utils_->Scan(interface_index_, request_random_mac, ssids, freqs)) {
*out_success = false;
return Status::ok();
}
Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,
bool* out_success) {
if (!CheckIsValid()) {
+ *out_success = false;
return Status::ok();
}
if (pno_scan_started_) {
// Empty frequency list: scan all frequencies.
vector<uint32_t> freqs;
+ 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) {
- LOG(WARNING) << "Skip scan ssid for pno scan: "
- << string(network.ssid_.begin(), network.ssid_.end());
+ skipped_scan_ssids.emplace_back(network.ssid_);
continue;
}
scan_ssids.push_back(network.ssid_);
}
if (match_ssids.size() + 1 > scan_capabilities_.max_match_sets) {
- LOG(WARNING) << "Skip match ssid for pno scan: "
- << string(network.ssid_.begin(), network.ssid_.end());
+ skipped_match_ssids.emplace_back(network.ssid_);
continue;
}
match_ssids.push_back(network.ssid_);
}
- bool random_mac = wiphy_features_.supports_random_mac_sched_scan;
+ LogSsidList(skipped_scan_ssids, "Skip scan ssid for pno scan");
+ LogSsidList(skipped_match_ssids, "Skip match ssid for pno scan");
+
+ // Only request MAC address randomization when station is not associated.
+ bool request_random_mac = wiphy_features_.supports_random_mac_sched_scan &&
+ !client_interface_->IsAssociated();
if (!scan_utils_->StartScheduledScan(interface_index_,
pno_settings.interval_ms_,
// TODO: honor both rssi thresholds.
- pno_settings.min_2g_rssi_,
- random_mac,
+ pno_settings.min_5g_rssi_,
+ request_random_mac,
scan_ssids,
match_ssids,
freqs)) {
*out_success = false;
- LOG(ERROR) << "Failed to start scheduled scan";
+ LOG(ERROR) << "Failed to start pno scan";
return Status::ok();
}
+ LOG(INFO) << "Pno scan started";
pno_scan_started_ = true;
*out_success = true;
return Status::ok();
Status ScannerImpl::stopPnoScan(bool* out_success) {
if (!CheckIsValid()) {
+ *out_success = false;
return Status::ok();
}
*out_success = false;
return Status::ok();
}
+ LOG(INFO) << "Pno scan stopped";
pno_scan_started_ = false;
*out_success = true;
return Status::ok();
}
+Status ScannerImpl::abortScan() {
+ if (!CheckIsValid()) {
+ return Status::ok();
+ }
+
+ if (!scan_started_) {
+ LOG(WARNING) << "Scan is not started. Ignore abort request";
+ return Status::ok();
+ }
+ if (!scan_utils_->AbortScan(interface_index_)) {
+ LOG(WARNING) << "Abort scan failed";
+ }
+ return Status::ok();
+}
+
Status ScannerImpl::subscribeScanEvents(const sp<IScanEvent>& handler) {
if (!CheckIsValid()) {
return Status::ok();
bool aborted,
vector<vector<uint8_t>>& ssids,
vector<uint32_t>& frequencies) {
- LOG(INFO) << "Received scan result notification from kernel.";
+ if (!scan_started_) {
+ LOG(INFO) << "Received external scan result notification from kernel.";
+ }
scan_started_ = false;
if (scan_event_handler_ != nullptr) {
// TODO: Pass other parameters back once we find framework needs them.
// This stop notification might result from our own request.
// See the document for NL80211_CMD_SCHED_SCAN_STOPPED in nl80211.h.
if (pno_scan_started_) {
+ LOG(WARNING) << "Unexpected pno scan stopped event";
pno_scan_event_handler_->OnPnoScanFailed();
}
pno_scan_started_ = false;
} else {
+ LOG(INFO) << "Pno scan result ready event";
pno_scan_event_handler_->OnPnoNetworkFound();
}
}
}
+void ScannerImpl::LogSsidList(vector<vector<uint8_t>>& ssid_list,
+ string prefix) {
+ if (ssid_list.empty()) {
+ return;
+ }
+ string ssid_list_string;
+ for (auto& ssid : ssid_list) {
+ ssid_list_string += string(ssid.begin(), ssid.end());
+ if (&ssid != &ssid_list.back()) {
+ ssid_list_string += ", ";
+ }
+ }
+ LOG(WARNING) << prefix << ": " << ssid_list_string;
+}
+
} // namespace wificond
} // namespace android