2 * Copyright (C) 2016 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "wificond/scanning/scanner_impl.h"
22 #include <android-base/logging.h>
24 #include "wificond/scanning/scan_utils.h"
26 using android::binder::Status;
27 using android::net::wifi::IPnoScanEvent;
28 using android::net::wifi::IScanEvent;
30 using com::android::server::wifi::wificond::NativeScanResult;
31 using com::android::server::wifi::wificond::PnoSettings;
32 using com::android::server::wifi::wificond::SingleScanSettings;
37 using namespace std::placeholders;
42 ScannerImpl::ScannerImpl(uint32_t wiphy_index,
43 uint32_t interface_index,
44 const ScanCapabilities& scan_capabilities,
45 const WiphyFeatures& wiphy_features,
46 NetlinkUtils* netlink_utils,
47 ScanUtils* scan_utils)
50 pno_scan_started_(false),
51 wiphy_index_(wiphy_index),
52 interface_index_(interface_index),
53 scan_capabilities_(scan_capabilities),
54 wiphy_features_(wiphy_features),
55 netlink_utils_(netlink_utils),
56 scan_utils_(scan_utils),
57 scan_event_handler_(nullptr) {
58 // Subscribe one-shot scan result notification from kernel.
59 LOG(INFO) << "subscribe scan result for interface with index: "
60 << (int)interface_index_;
61 scan_utils_->SubscribeScanResultNotification(
63 std::bind(&ScannerImpl::OnScanResultsReady,
66 // Subscribe scheduled scan result notification from kernel.
67 scan_utils_->SubscribeSchedScanResultNotification(
69 std::bind(&ScannerImpl::OnSchedScanResultsReady,
74 ScannerImpl::~ScannerImpl() {
77 void ScannerImpl::Invalidate() {
78 LOG(INFO) << "Unsubscribe scan result for interface with index: "
79 << (int)interface_index_;
80 scan_utils_->UnsubscribeScanResultNotification(interface_index_);
81 scan_utils_->UnsubscribeSchedScanResultNotification(interface_index_);
84 bool ScannerImpl::CheckIsValid() {
86 LOG(DEBUG) << "Calling on a invalid scanner object."
87 << "Underlying client interface object was destroyed.";
92 Status ScannerImpl::getAvailable2gChannels(
93 std::unique_ptr<vector<int32_t>>* out_frequencies) {
94 if (!CheckIsValid()) {
98 if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
102 LOG(ERROR) << "Failed to get wiphy info from kernel";
103 *out_frequencies = nullptr;
107 **out_frequencies = vector<int32_t>(band_info.band_2g.begin(),
108 band_info.band_2g.end());
112 Status ScannerImpl::getAvailable5gNonDFSChannels(
113 std::unique_ptr<vector<int32_t>>* out_frequencies) {
114 if (!CheckIsValid()) {
118 if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
122 LOG(ERROR) << "Failed to get wiphy info from kernel";
123 *out_frequencies = nullptr;
127 **out_frequencies = vector<int32_t>(band_info.band_5g.begin(),
128 band_info.band_5g.end());
132 Status ScannerImpl::getAvailableDFSChannels(
133 std::unique_ptr<vector<int32_t>>* out_frequencies) {
134 if (!CheckIsValid()) {
138 if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
142 LOG(ERROR) << "Failed to get wiphy info from kernel";
143 *out_frequencies = nullptr;
147 **out_frequencies = vector<int32_t>(band_info.band_dfs.begin(),
148 band_info.band_dfs.end());
152 Status ScannerImpl::getScanResults(vector<NativeScanResult>* out_scan_results) {
153 if (!CheckIsValid()) {
156 if (!scan_utils_->GetScanResult(interface_index_, out_scan_results)) {
157 LOG(ERROR) << "Failed to get scan results via NL80211";
162 Status ScannerImpl::scan(const SingleScanSettings& scan_settings,
164 if (!CheckIsValid()) {
169 LOG(WARNING) << "Scan already started";
171 bool random_mac = wiphy_features_.supports_random_mac_oneshot_scan;
173 // Initialize it with an empty ssid for a wild card scan.
174 vector<vector<uint8_t>> ssids = {{}};
175 for (auto& network : scan_settings.hidden_networks_) {
176 if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {
177 LOG(WARNING) << "Skip scan ssid for single scan: "
178 << string(network.ssid_.begin(), network.ssid_.end());
181 ssids.push_back(network.ssid_);
184 vector<uint32_t> freqs;
185 for (auto& channel : scan_settings.channel_settings_) {
186 freqs.push_back(channel.frequency_);
189 if (!scan_utils_->Scan(interface_index_, random_mac, ssids, freqs)) {
190 *out_success = false;
193 scan_started_ = true;
198 Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,
200 if (!CheckIsValid()) {
203 if (pno_scan_started_) {
204 LOG(WARNING) << "Pno scan already started";
206 // An empty ssid for a wild card scan.
207 vector<vector<uint8_t>> scan_ssids = {{}};
208 vector<vector<uint8_t>> match_ssids;
209 // Empty frequency list: scan all frequencies.
210 vector<uint32_t> freqs;
212 for (auto& network : pno_settings.pno_networks_) {
213 // Add hidden network ssid.
214 if (network.is_hidden_) {
215 if (scan_ssids.size() + 1 > scan_capabilities_.max_num_sched_scan_ssids) {
216 LOG(WARNING) << "Skip scan ssid for pno scan: "
217 << string(network.ssid_.begin(), network.ssid_.end());
220 scan_ssids.push_back(network.ssid_);
223 if (match_ssids.size() + 1 > scan_capabilities_.max_match_sets) {
224 LOG(WARNING) << "Skip match ssid for pno scan: "
225 << string(network.ssid_.begin(), network.ssid_.end());
228 match_ssids.push_back(network.ssid_);
231 bool random_mac = wiphy_features_.supports_random_mac_sched_scan;
233 if (!scan_utils_->StartScheduledScan(interface_index_,
234 pno_settings.interval_ms_,
235 // TODO: honor both rssi thresholds.
236 pno_settings.min_2g_rssi_,
241 *out_success = false;
242 LOG(ERROR) << "Failed to start scheduled scan";
245 pno_scan_started_ = true;
250 Status ScannerImpl::stopPnoScan(bool* out_success) {
251 if (!CheckIsValid()) {
255 if (!pno_scan_started_) {
256 LOG(WARNING) << "No pno scan started";
258 if (!scan_utils_->StopScheduledScan(interface_index_)) {
259 *out_success = false;
262 pno_scan_started_ = false;
267 Status ScannerImpl::subscribeScanEvents(const sp<IScanEvent>& handler) {
268 if (!CheckIsValid()) {
272 if (scan_event_handler_ != nullptr) {
273 LOG(ERROR) << "Found existing scan events subscriber."
274 << " This subscription request will unsubscribe it";
276 scan_event_handler_ = handler;
280 Status ScannerImpl::unsubscribeScanEvents() {
281 scan_event_handler_ = nullptr;
286 Status ScannerImpl::subscribePnoScanEvents(const sp<IPnoScanEvent>& handler) {
287 if (!CheckIsValid()) {
291 if (pno_scan_event_handler_ != nullptr) {
292 LOG(ERROR) << "Found existing pno scan events subscriber."
293 << " This subscription request will unsubscribe it";
295 pno_scan_event_handler_ = handler;
300 Status ScannerImpl::unsubscribePnoScanEvents() {
301 pno_scan_event_handler_ = nullptr;
305 void ScannerImpl::OnScanResultsReady(
306 uint32_t interface_index,
308 vector<vector<uint8_t>>& ssids,
309 vector<uint32_t>& frequencies) {
310 LOG(INFO) << "Received scan result notification from kernel.";
311 scan_started_ = false;
312 if (scan_event_handler_ != nullptr) {
313 // TODO: Pass other parameters back once we find framework needs them.
315 LOG(WARNING) << "Scan aborted";
316 scan_event_handler_->OnScanFailed();
318 scan_event_handler_->OnScanResultReady();
321 LOG(WARNING) << "No scan event handler found.";
325 void ScannerImpl::OnSchedScanResultsReady(uint32_t interface_index,
327 if (pno_scan_event_handler_ != nullptr) {
329 // If |pno_scan_started_| is false.
330 // This stop notification might result from our own request.
331 // See the document for NL80211_CMD_SCHED_SCAN_STOPPED in nl80211.h.
332 if (pno_scan_started_) {
333 pno_scan_event_handler_->OnPnoScanFailed();
335 pno_scan_started_ = false;
337 pno_scan_event_handler_->OnPnoNetworkFound();
342 } // namespace wificond
343 } // namespace android