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 // Initialize it with an empty ssid for a wild card scan.
133 vector<vector<uint8_t>> ssids = {{}};
134 for (auto& network : scan_settings.hidden_networks_) {
135 if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {
136 LOG(WARNING) << "Skip scan ssid for single scan: "
137 << string(network.ssid_.begin(), network.ssid_.end());
140 ssids.push_back(network.ssid_);
143 vector<uint32_t> freqs;
144 for (auto& channel : scan_settings.channel_settings_) {
145 freqs.push_back(channel.frequency_);
148 if (!scan_utils_->Scan(interface_index_, random_mac, ssids, freqs)) {
149 *out_success = false;
152 scan_started_ = true;
157 Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,
159 if (!CheckIsValid()) {
162 if (pno_scan_started_) {
163 LOG(WARNING) << "Pno scan already started";
165 // An empty ssid for a wild card scan.
166 vector<vector<uint8_t>> scan_ssids = {{}};
167 vector<vector<uint8_t>> match_ssids;
168 // Empty frequency list: scan all frequencies.
169 vector<uint32_t> freqs;
171 for (auto& network : pno_settings.pno_networks_) {
172 // Add hidden network ssid.
173 if (network.is_hidden_) {
174 if (scan_ssids.size() + 1 > scan_capabilities_.max_num_sched_scan_ssids) {
175 LOG(WARNING) << "Skip scan ssid for pno scan: "
176 << string(network.ssid_.begin(), network.ssid_.end());
179 scan_ssids.push_back(network.ssid_);
182 if (match_ssids.size() + 1 > scan_capabilities_.max_match_sets) {
183 LOG(WARNING) << "Skip match ssid for pno scan: "
184 << string(network.ssid_.begin(), network.ssid_.end());
187 match_ssids.push_back(network.ssid_);
190 bool random_mac = wiphy_features_.supports_random_mac_sched_scan;
192 if (!scan_utils_->StartScheduledScan(interface_index_,
193 pno_settings.interval_ms_,
194 // TODO: honor both rssi thresholds.
195 pno_settings.min_2g_rssi_,
200 *out_success = false;
201 LOG(ERROR) << "Failed to start scheduled scan";
204 pno_scan_started_ = true;
209 Status ScannerImpl::stopPnoScan(bool* out_success) {
210 if (!CheckIsValid()) {
214 if (!pno_scan_started_) {
215 LOG(WARNING) << "No pno scan started";
217 if (!scan_utils_->StopScheduledScan(interface_index_)) {
218 *out_success = false;
221 pno_scan_started_ = false;
226 Status ScannerImpl::subscribeScanEvents(const sp<IScanEvent>& handler) {
227 if (!CheckIsValid()) {
231 if (scan_event_handler_ != nullptr) {
232 LOG(ERROR) << "Found existing scan events subscriber."
233 << " This subscription request will unsubscribe it";
235 scan_event_handler_ = handler;
239 Status ScannerImpl::unsubscribeScanEvents() {
240 scan_event_handler_ = nullptr;
245 Status ScannerImpl::subscribePnoScanEvents(const sp<IPnoScanEvent>& handler) {
246 if (!CheckIsValid()) {
250 if (pno_scan_event_handler_ != nullptr) {
251 LOG(ERROR) << "Found existing pno scan events subscriber."
252 << " This subscription request will unsubscribe it";
254 pno_scan_event_handler_ = handler;
259 Status ScannerImpl::unsubscribePnoScanEvents() {
260 pno_scan_event_handler_ = nullptr;
264 void ScannerImpl::OnScanResultsReady(
265 uint32_t interface_index,
267 vector<vector<uint8_t>>& ssids,
268 vector<uint32_t>& frequencies) {
269 scan_started_ = false;
270 if (scan_event_handler_ != nullptr) {
271 // TODO: Pass other parameters back once we find framework needs them.
273 scan_event_handler_->OnScanFailed();
275 scan_event_handler_->OnScanResultReady();
280 void ScannerImpl::OnSchedScanResultsReady(uint32_t interface_index,
282 if (pno_scan_event_handler_ != nullptr) {
284 // If |pno_scan_started_| is false.
285 // This stop notification might result from our own request.
286 // See the document for NL80211_CMD_SCHED_SCAN_STOPPED in nl80211.h.
287 if (pno_scan_started_) {
288 pno_scan_event_handler_->OnPnoScanFailed();
290 pno_scan_started_ = false;
292 pno_scan_event_handler_->OnPnoNetworkFound();
297 } // namespace wificond
298 } // namespace android