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 interface_index,
43 const BandInfo& band_info,
44 const ScanCapabilities& scan_capabilities,
45 const WiphyFeatures& wiphy_features,
46 ScanUtils* scan_utils)
49 pno_scan_started_(false),
50 interface_index_(interface_index),
51 band_info_(band_info),
52 scan_capabilities_(scan_capabilities),
53 wiphy_features_(wiphy_features),
54 scan_utils_(scan_utils),
55 scan_event_handler_(nullptr) {
56 // Subscribe one-shot scan result notification from kernel.
57 scan_utils_->SubscribeScanResultNotification(
59 std::bind(&ScannerImpl::OnScanResultsReady,
62 // Subscribe scheduled scan result notification from kernel.
63 scan_utils_->SubscribeSchedScanResultNotification(
65 std::bind(&ScannerImpl::OnSchedScanResultsReady,
70 ScannerImpl::~ScannerImpl() {
71 scan_utils_->UnsubscribeScanResultNotification(interface_index_);
72 scan_utils_->UnsubscribeSchedScanResultNotification(interface_index_);
75 bool ScannerImpl::CheckIsValid() {
77 LOG(DEBUG) << "Calling on a invalid scanner object."
78 << "Underlying client interface object was destroyed.";
83 Status ScannerImpl::getAvailable2gChannels(vector<int32_t>* out_frequencies) {
84 if (!CheckIsValid()) {
87 *out_frequencies = vector<int32_t>(band_info_.band_2g.begin(),
88 band_info_.band_2g.end());
92 Status ScannerImpl::getAvailable5gNonDFSChannels(
93 vector<int32_t>* out_frequencies) {
94 if (!CheckIsValid()) {
97 *out_frequencies = vector<int32_t>(band_info_.band_5g.begin(),
98 band_info_.band_5g.end());
102 Status ScannerImpl::getAvailableDFSChannels(vector<int32_t>* out_frequencies) {
103 if (!CheckIsValid()) {
106 *out_frequencies = vector<int32_t>(band_info_.band_dfs.begin(),
107 band_info_.band_dfs.end());
111 Status ScannerImpl::getScanResults(vector<NativeScanResult>* out_scan_results) {
112 if (!CheckIsValid()) {
115 if (!scan_utils_->GetScanResult(interface_index_, out_scan_results)) {
116 LOG(ERROR) << "Failed to get scan results via NL80211";
121 Status ScannerImpl::scan(const SingleScanSettings& scan_settings,
123 if (!CheckIsValid()) {
128 LOG(WARNING) << "Scan already started";
130 bool random_mac = wiphy_features_.supports_random_mac_oneshot_scan;
132 if (scan_settings.is_full_scan_) {
133 if (!scan_utils_->StartFullScan(interface_index_, random_mac)) {
134 *out_success = false;
137 scan_started_ = true;
141 // Initialize it with an empty ssid for a wild card scan.
142 vector<vector<uint8_t>> ssids = {{0}};
143 for (auto& network : scan_settings.hidden_networks_) {
144 if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {
145 LOG(WARNING) << "Skip scan ssid for single scan: "
146 << string(network.ssid_.begin(), network.ssid_.end());
149 ssids.push_back(network.ssid_);
152 vector<uint32_t> freqs;
153 for (auto& channel : scan_settings.channel_settings_) {
154 freqs.push_back(channel.frequency_);
157 if (!scan_utils_->Scan(interface_index_, random_mac, ssids, freqs)) {
158 *out_success = false;
161 scan_started_ = true;
166 Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,
168 if (!CheckIsValid()) {
171 if (pno_scan_started_) {
172 LOG(WARNING) << "Pno scan already started";
174 // An empty ssid for a wild card scan.
175 vector<vector<uint8_t>> scan_ssids = {{0}};
176 vector<vector<uint8_t>> match_ssids;
177 // Empty frequency list: scan all frequencies.
178 vector<uint32_t> freqs;
180 for (auto& network : pno_settings.pno_networks_) {
181 // Add hidden network ssid.
182 if (network.is_hidden_) {
183 if (scan_ssids.size() + 1 > scan_capabilities_.max_num_sched_scan_ssids) {
184 LOG(WARNING) << "Skip scan ssid for pno scan: "
185 << string(network.ssid_.begin(), network.ssid_.end());
188 scan_ssids.push_back(network.ssid_);
191 if (match_ssids.size() + 1 > scan_capabilities_.max_match_sets) {
192 LOG(WARNING) << "Skip match ssid for pno scan: "
193 << string(network.ssid_.begin(), network.ssid_.end());
196 match_ssids.push_back(network.ssid_);
199 bool random_mac = wiphy_features_.supports_random_mac_sched_scan;
201 if (!scan_utils_->StartScheduledScan(interface_index_,
202 pno_settings.interval_ms_,
203 // TODO: honor both rssi thresholds.
204 pno_settings.min_2g_rssi_,
209 *out_success = false;
210 LOG(ERROR) << "Failed to start scheduled scan";
213 pno_scan_started_ = true;
218 Status ScannerImpl::stopPnoScan(bool* out_success) {
219 if (!CheckIsValid()) {
223 if (!pno_scan_started_) {
224 LOG(WARNING) << "No pno scan started";
226 if (!scan_utils_->StopScheduledScan(interface_index_)) {
227 *out_success = false;
230 pno_scan_started_ = false;
235 Status ScannerImpl::subscribeScanEvents(const sp<IScanEvent>& handler) {
236 if (!CheckIsValid()) {
240 if (scan_event_handler_ != nullptr) {
241 LOG(ERROR) << "Found existing scan events subscriber."
242 << " This subscription request will unsubscribe it";
244 scan_event_handler_ = handler;
248 Status ScannerImpl::unsubscribeScanEvents() {
249 scan_event_handler_ = nullptr;
254 Status ScannerImpl::subscribePnoScanEvents(const sp<IPnoScanEvent>& handler) {
255 if (!CheckIsValid()) {
259 if (pno_scan_event_handler_ != nullptr) {
260 LOG(ERROR) << "Found existing pno scan events subscriber."
261 << " This subscription request will unsubscribe it";
263 pno_scan_event_handler_ = handler;
268 Status ScannerImpl::unsubscribePnoScanEvents() {
269 pno_scan_event_handler_ = nullptr;
273 void ScannerImpl::OnScanResultsReady(
274 uint32_t interface_index,
276 vector<vector<uint8_t>>& ssids,
277 vector<uint32_t>& frequencies) {
278 scan_started_ = false;
279 if (scan_event_handler_ != nullptr) {
280 // TODO: Pass other parameters back once we find framework needs them.
282 scan_event_handler_->OnScanFailed();
284 scan_event_handler_->OnScanResultReady();
289 void ScannerImpl::OnSchedScanResultsReady(uint32_t interface_index,
291 if (pno_scan_event_handler_ != nullptr) {
293 // If |pno_scan_started_| is false.
294 // This stop notification might result from our own request.
295 // See the document for NL80211_CMD_SCHED_SCAN_STOPPED in nl80211.h.
296 if (pno_scan_started_) {
297 pno_scan_event_handler_->OnPnoScanFailed();
299 pno_scan_started_ = false;
301 pno_scan_event_handler_->OnPnoNetworkFound();
306 } // namespace wificond
307 } // namespace android