1 /*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17 #include "wificond/scanning/scanner_impl.h"
18
19 #include <string>
20 #include <vector>
21
22 #include <android-base/logging.h>
23
24 #include "wificond/client_interface_impl.h"
25 #include "wificond/scanning/offload/offload_scan_manager.h"
26 #include "wificond/scanning/offload/offload_service_utils.h"
27 #include "wificond/scanning/scan_utils.h"
28
29 using android::binder::Status;
30 using android::net::wifi::IPnoScanEvent;
31 using android::net::wifi::IScanEvent;
32 using android::hardware::wifi::offload::V1_0::IOffload;
33 using android::sp;
34 using com::android::server::wifi::wificond::NativeScanResult;
35 using com::android::server::wifi::wificond::PnoSettings;
36 using com::android::server::wifi::wificond::SingleScanSettings;
37
38 using std::pair;
39 using std::string;
40 using std::vector;
41 using std::weak_ptr;
42 using std::shared_ptr;
43
44 using namespace std::placeholders;
45
46 namespace android {
47 namespace wificond {
48
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,weak_ptr<OffloadServiceUtils> offload_service_utils)49 ScannerImpl::ScannerImpl(uint32_t wiphy_index, uint32_t interface_index,
50 const ScanCapabilities& scan_capabilities,
51 const WiphyFeatures& wiphy_features,
52 ClientInterfaceImpl* client_interface,
53 NetlinkUtils* netlink_utils, ScanUtils* scan_utils,
54 weak_ptr<OffloadServiceUtils> offload_service_utils)
55 : valid_(true),
56 scan_started_(false),
57 pno_scan_started_(false),
58 offload_scan_supported_(false),
59 pno_scan_running_over_offload_(false),
60 pno_scan_results_from_offload_(false),
61 wiphy_index_(wiphy_index),
62 interface_index_(interface_index),
63 scan_capabilities_(scan_capabilities),
64 wiphy_features_(wiphy_features),
65 client_interface_(client_interface),
66 netlink_utils_(netlink_utils),
67 scan_utils_(scan_utils),
68 scan_event_handler_(nullptr) {
69 // Subscribe one-shot scan result notification from kernel.
70 LOG(INFO) << "subscribe scan result for interface with index: "
71 << (int)interface_index_;
72 scan_utils_->SubscribeScanResultNotification(
73 interface_index_,
74 std::bind(&ScannerImpl::OnScanResultsReady, this, _1, _2, _3, _4));
75 // Subscribe scheduled scan result notification from kernel.
76 scan_utils_->SubscribeSchedScanResultNotification(
77 interface_index_,
78 std::bind(&ScannerImpl::OnSchedScanResultsReady,
79 this,
80 _1, _2));
81 std::shared_ptr<OffloadScanCallbackInterfaceImpl>
82 offload_scan_callback_interface =
83 offload_service_utils.lock()->GetOffloadScanCallbackInterface(this);
84 offload_scan_manager_ = offload_service_utils.lock()->GetOffloadScanManager(
85 offload_service_utils, offload_scan_callback_interface);
86 offload_scan_supported_ = offload_service_utils.lock()->IsOffloadScanSupported();
87 }
88
~ScannerImpl()89 ScannerImpl::~ScannerImpl() {}
90
Invalidate()91 void ScannerImpl::Invalidate() {
92 LOG(INFO) << "Unsubscribe scan result for interface with index: "
93 << (int)interface_index_;
94 scan_utils_->UnsubscribeScanResultNotification(interface_index_);
95 scan_utils_->UnsubscribeSchedScanResultNotification(interface_index_);
96 valid_ = false;
97 }
98
CheckIsValid()99 bool ScannerImpl::CheckIsValid() {
100 if (!valid_) {
101 LOG(DEBUG) << "Calling on a invalid scanner object."
102 << "Underlying client interface object was destroyed.";
103 }
104 return valid_;
105 }
106
getAvailable2gChannels(std::unique_ptr<vector<int32_t>> * out_frequencies)107 Status ScannerImpl::getAvailable2gChannels(
108 std::unique_ptr<vector<int32_t>>* out_frequencies) {
109 if (!CheckIsValid()) {
110 return Status::ok();
111 }
112 BandInfo band_info;
113 if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
114 &scan_capabilities_, &wiphy_features_)) {
115 LOG(ERROR) << "Failed to get wiphy info from kernel";
116 out_frequencies->reset(nullptr);
117 return Status::ok();
118 }
119
120 out_frequencies->reset(
121 new vector<int32_t>(band_info.band_2g.begin(), band_info.band_2g.end()));
122 return Status::ok();
123 }
124
getAvailable5gNonDFSChannels(std::unique_ptr<vector<int32_t>> * out_frequencies)125 Status ScannerImpl::getAvailable5gNonDFSChannels(
126 std::unique_ptr<vector<int32_t>>* out_frequencies) {
127 if (!CheckIsValid()) {
128 return Status::ok();
129 }
130 BandInfo band_info;
131 if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
132 &scan_capabilities_, &wiphy_features_)) {
133 LOG(ERROR) << "Failed to get wiphy info from kernel";
134 out_frequencies->reset(nullptr);
135 return Status::ok();
136 }
137
138 out_frequencies->reset(
139 new vector<int32_t>(band_info.band_5g.begin(), band_info.band_5g.end()));
140 return Status::ok();
141 }
142
getAvailableDFSChannels(std::unique_ptr<vector<int32_t>> * out_frequencies)143 Status ScannerImpl::getAvailableDFSChannels(
144 std::unique_ptr<vector<int32_t>>* out_frequencies) {
145 if (!CheckIsValid()) {
146 return Status::ok();
147 }
148 BandInfo band_info;
149 if (!netlink_utils_->GetWiphyInfo(wiphy_index_, &band_info,
150 &scan_capabilities_, &wiphy_features_)) {
151 LOG(ERROR) << "Failed to get wiphy info from kernel";
152 out_frequencies->reset(nullptr);
153 return Status::ok();
154 }
155
156 out_frequencies->reset(new vector<int32_t>(band_info.band_dfs.begin(),
157 band_info.band_dfs.end()));
158 return Status::ok();
159 }
160
getScanResults(vector<NativeScanResult> * out_scan_results)161 Status ScannerImpl::getScanResults(vector<NativeScanResult>* out_scan_results) {
162 if (!CheckIsValid()) {
163 return Status::ok();
164 }
165 if (!scan_utils_->GetScanResult(interface_index_, out_scan_results)) {
166 LOG(ERROR) << "Failed to get scan results via NL80211";
167 }
168 return Status::ok();
169 }
170
getPnoScanResults(vector<NativeScanResult> * out_scan_results)171 Status ScannerImpl::getPnoScanResults(
172 vector<NativeScanResult>* out_scan_results) {
173 if (!CheckIsValid()) {
174 return Status::ok();
175 }
176 if (pno_scan_results_from_offload_) {
177 if (!offload_scan_manager_->getScanResults(out_scan_results)) {
178 LOG(ERROR) << "Failed to get scan results via Offload HAL";
179 }
180 } else {
181 if (!scan_utils_->GetScanResult(interface_index_, out_scan_results)) {
182 LOG(ERROR) << "Failed to get scan results via NL80211";
183 }
184 }
185 return Status::ok();
186 }
187
scan(const SingleScanSettings & scan_settings,bool * out_success)188 Status ScannerImpl::scan(const SingleScanSettings& scan_settings,
189 bool* out_success) {
190 if (!CheckIsValid()) {
191 *out_success = false;
192 return Status::ok();
193 }
194
195 if (scan_started_) {
196 LOG(WARNING) << "Scan already started";
197 }
198 // Only request MAC address randomization when station is not associated.
199 bool request_random_mac = wiphy_features_.supports_random_mac_oneshot_scan &&
200 !client_interface_->IsAssociated();
201
202 // Initialize it with an empty ssid for a wild card scan.
203 vector<vector<uint8_t>> ssids = {{}};
204
205 vector<vector<uint8_t>> skipped_scan_ssids;
206 for (auto& network : scan_settings.hidden_networks_) {
207 if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {
208 skipped_scan_ssids.emplace_back(network.ssid_);
209 continue;
210 }
211 ssids.push_back(network.ssid_);
212 }
213
214 LogSsidList(skipped_scan_ssids, "Skip scan ssid for single scan");
215
216 vector<uint32_t> freqs;
217 for (auto& channel : scan_settings.channel_settings_) {
218 freqs.push_back(channel.frequency_);
219 }
220
221 int error_code = 0;
222 if (!scan_utils_->Scan(interface_index_, request_random_mac, ssids, freqs,
223 &error_code)) {
224 CHECK(error_code != ENODEV) << "Driver is in a bad state, restarting wificond";
225 *out_success = false;
226 return Status::ok();
227 }
228 scan_started_ = true;
229 *out_success = true;
230 return Status::ok();
231 }
232
startPnoScan(const PnoSettings & pno_settings,bool * out_success)233 Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,
234 bool* out_success) {
235 pno_settings_ = pno_settings;
236 pno_scan_results_from_offload_ = false;
237 LOG(VERBOSE) << "startPnoScan";
238 if (offload_scan_supported_ && StartPnoScanOffload(pno_settings)) {
239 // scanning over offload succeeded
240 *out_success = true;
241 } else {
242 *out_success = StartPnoScanDefault(pno_settings);
243 }
244 return Status::ok();
245 }
246
StartPnoScanOffload(const PnoSettings & pno_settings)247 bool ScannerImpl::StartPnoScanOffload(const PnoSettings& pno_settings) {
248 OffloadScanManager::ReasonCode reason_code;
249 vector<vector<uint8_t>> scan_ssids;
250 vector<vector<uint8_t>> match_ssids;
251 vector<uint8_t> match_security;
252 // Empty frequency list: scan all frequencies.
253 vector<uint32_t> freqs;
254
255 ParsePnoSettings(pno_settings, &scan_ssids, &match_ssids, &freqs,
256 &match_security);
257 pno_scan_running_over_offload_ = offload_scan_manager_->startScan(
258 pno_settings.interval_ms_,
259 // TODO: honor both rssi thresholds.
260 pno_settings.min_5g_rssi_, scan_ssids, match_ssids, match_security, freqs,
261 &reason_code);
262 if (pno_scan_running_over_offload_) {
263 LOG(VERBOSE) << "Pno scans requested over Offload HAL";
264 if (pno_scan_event_handler_ != nullptr) {
265 pno_scan_event_handler_->OnPnoScanOverOffloadStarted();
266 }
267 }
268 return pno_scan_running_over_offload_;
269 }
270
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)271 void ScannerImpl::ParsePnoSettings(const PnoSettings& pno_settings,
272 vector<vector<uint8_t>>* scan_ssids,
273 vector<vector<uint8_t>>* match_ssids,
274 vector<uint32_t>* freqs,
275 vector<uint8_t>* match_security) {
276 // TODO provide actionable security match parameters
277 const uint8_t kNetworkFlagsDefault = 0;
278 vector<vector<uint8_t>> skipped_scan_ssids;
279 vector<vector<uint8_t>> skipped_match_ssids;
280 for (auto& network : pno_settings.pno_networks_) {
281 // Add hidden network ssid.
282 if (network.is_hidden_) {
283 // TODO remove pruning for Offload Scans
284 if (scan_ssids->size() + 1 >
285 scan_capabilities_.max_num_sched_scan_ssids) {
286 skipped_scan_ssids.emplace_back(network.ssid_);
287 continue;
288 }
289 scan_ssids->push_back(network.ssid_);
290 }
291
292 if (match_ssids->size() + 1 > scan_capabilities_.max_match_sets) {
293 skipped_match_ssids.emplace_back(network.ssid_);
294 continue;
295 }
296 match_ssids->push_back(network.ssid_);
297 match_security->push_back(kNetworkFlagsDefault);
298 }
299
300 LogSsidList(skipped_scan_ssids, "Skip scan ssid for pno scan");
301 LogSsidList(skipped_match_ssids, "Skip match ssid for pno scan");
302 }
303
StartPnoScanDefault(const PnoSettings & pno_settings)304 bool ScannerImpl::StartPnoScanDefault(const PnoSettings& pno_settings) {
305 if (!CheckIsValid()) {
306 return false;
307 }
308 if (pno_scan_started_) {
309 LOG(WARNING) << "Pno scan already started";
310 }
311 // An empty ssid for a wild card scan.
312 vector<vector<uint8_t>> scan_ssids = {{}};
313 vector<vector<uint8_t>> match_ssids;
314 vector<uint8_t> unused;
315 // Empty frequency list: scan all frequencies.
316 vector<uint32_t> freqs;
317
318 ParsePnoSettings(pno_settings, &scan_ssids, &match_ssids, &freqs, &unused);
319 // Only request MAC address randomization when station is not associated.
320 bool request_random_mac = wiphy_features_.supports_random_mac_sched_scan &&
321 !client_interface_->IsAssociated();
322
323 int error_code = 0;
324 if (!scan_utils_->StartScheduledScan(interface_index_,
325 GenerateIntervalSetting(pno_settings),
326 // TODO: honor both rssi thresholds.
327 pno_settings.min_5g_rssi_,
328 request_random_mac,
329 scan_ssids,
330 match_ssids,
331 freqs,
332 &error_code)) {
333 LOG(ERROR) << "Failed to start pno scan";
334 CHECK(error_code != ENODEV) << "Driver is in a bad state, restarting wificond";
335 return false;
336 }
337 LOG(INFO) << "Pno scan started";
338 pno_scan_started_ = true;
339 return true;
340 }
341
stopPnoScan(bool * out_success)342 Status ScannerImpl::stopPnoScan(bool* out_success) {
343 if (offload_scan_supported_ && StopPnoScanOffload()) {
344 // Pno scans over offload stopped successfully
345 *out_success = true;
346 } else {
347 // Pno scans were not requested over offload
348 *out_success = StopPnoScanDefault();
349 }
350 return Status::ok();
351 }
352
StopPnoScanOffload()353 bool ScannerImpl::StopPnoScanOffload() {
354 OffloadScanManager::ReasonCode reason_code;
355 if (!pno_scan_running_over_offload_) {
356 return false;
357 }
358 if (!offload_scan_manager_->stopScan(&reason_code)) {
359 LOG(WARNING) << "Unable to unsubscribe to Offload scan results";
360 }
361 pno_scan_running_over_offload_ = false;
362 LOG(VERBOSE) << "Pno scans over Offload stopped";
363 return true;
364 }
365
StopPnoScanDefault()366 bool ScannerImpl::StopPnoScanDefault() {
367 if (!CheckIsValid()) {
368 return false;
369 }
370
371 if (!pno_scan_started_) {
372 LOG(WARNING) << "No pno scan started";
373 }
374 if (!scan_utils_->StopScheduledScan(interface_index_)) {
375 return false;
376 }
377 LOG(INFO) << "Pno scan stopped";
378 pno_scan_started_ = false;
379 return true;
380 }
381
abortScan()382 Status ScannerImpl::abortScan() {
383 if (!CheckIsValid()) {
384 return Status::ok();
385 }
386
387 if (!scan_started_) {
388 LOG(WARNING) << "Scan is not started. Ignore abort request";
389 return Status::ok();
390 }
391 if (!scan_utils_->AbortScan(interface_index_)) {
392 LOG(WARNING) << "Abort scan failed";
393 }
394 return Status::ok();
395 }
396
subscribeScanEvents(const sp<IScanEvent> & handler)397 Status ScannerImpl::subscribeScanEvents(const sp<IScanEvent>& handler) {
398 if (!CheckIsValid()) {
399 return Status::ok();
400 }
401
402 if (scan_event_handler_ != nullptr) {
403 LOG(ERROR) << "Found existing scan events subscriber."
404 << " This subscription request will unsubscribe it";
405 }
406 scan_event_handler_ = handler;
407 return Status::ok();
408 }
409
unsubscribeScanEvents()410 Status ScannerImpl::unsubscribeScanEvents() {
411 scan_event_handler_ = nullptr;
412 return Status::ok();
413 }
414
subscribePnoScanEvents(const sp<IPnoScanEvent> & handler)415 Status ScannerImpl::subscribePnoScanEvents(const sp<IPnoScanEvent>& handler) {
416 if (!CheckIsValid()) {
417 return Status::ok();
418 }
419
420 if (pno_scan_event_handler_ != nullptr) {
421 LOG(ERROR) << "Found existing pno scan events subscriber."
422 << " This subscription request will unsubscribe it";
423 }
424 pno_scan_event_handler_ = handler;
425
426 return Status::ok();
427 }
428
unsubscribePnoScanEvents()429 Status ScannerImpl::unsubscribePnoScanEvents() {
430 pno_scan_event_handler_ = nullptr;
431 return Status::ok();
432 }
433
OnScanResultsReady(uint32_t interface_index,bool aborted,vector<vector<uint8_t>> & ssids,vector<uint32_t> & frequencies)434 void ScannerImpl::OnScanResultsReady(uint32_t interface_index, bool aborted,
435 vector<vector<uint8_t>>& ssids,
436 vector<uint32_t>& frequencies) {
437 if (!scan_started_) {
438 LOG(INFO) << "Received external scan result notification from kernel.";
439 }
440 scan_started_ = false;
441 if (scan_event_handler_ != nullptr) {
442 // TODO: Pass other parameters back once we find framework needs them.
443 if (aborted) {
444 LOG(WARNING) << "Scan aborted";
445 scan_event_handler_->OnScanFailed();
446 } else {
447 scan_event_handler_->OnScanResultReady();
448 }
449 } else {
450 LOG(WARNING) << "No scan event handler found.";
451 }
452 }
453
OnSchedScanResultsReady(uint32_t interface_index,bool scan_stopped)454 void ScannerImpl::OnSchedScanResultsReady(uint32_t interface_index,
455 bool scan_stopped) {
456 if (pno_scan_event_handler_ != nullptr) {
457 if (scan_stopped) {
458 // If |pno_scan_started_| is false.
459 // This stop notification might result from our own request.
460 // See the document for NL80211_CMD_SCHED_SCAN_STOPPED in nl80211.h.
461 if (pno_scan_started_) {
462 LOG(WARNING) << "Unexpected pno scan stopped event";
463 pno_scan_event_handler_->OnPnoScanFailed();
464 }
465 pno_scan_started_ = false;
466 } else {
467 LOG(INFO) << "Pno scan result ready event";
468 pno_scan_results_from_offload_ = false;
469 pno_scan_event_handler_->OnPnoNetworkFound();
470 }
471 }
472 }
473
GenerateIntervalSetting(const::com::android::server::wifi::wificond::PnoSettings & pno_settings) const474 SchedScanIntervalSetting ScannerImpl::GenerateIntervalSetting(
475 const ::com::android::server::wifi::wificond::PnoSettings&
476 pno_settings) const {
477 bool support_num_scan_plans = scan_capabilities_.max_num_scan_plans >= 2;
478 bool support_scan_plan_interval =
479 scan_capabilities_.max_scan_plan_interval * 1000 >=
480 pno_settings.interval_ms_ * PnoSettings::kSlowScanIntervalMultiplier;
481 bool support_scan_plan_iterations =
482 scan_capabilities_.max_scan_plan_iterations >=
483 PnoSettings::kFastScanIterations;
484
485 uint32_t fast_scan_interval =
486 static_cast<uint32_t>(pno_settings.interval_ms_);
487 if (support_num_scan_plans && support_scan_plan_interval &&
488 support_scan_plan_iterations) {
489 return SchedScanIntervalSetting{
490 {{fast_scan_interval, PnoSettings::kFastScanIterations}},
491 fast_scan_interval * PnoSettings::kSlowScanIntervalMultiplier};
492 } else {
493 // Device doesn't support the provided scan plans.
494 // Specify single interval instead.
495 // In this case, the driver/firmware is expected to implement back off
496 // logic internally using |pno_settings.interval_ms_| as "fast scan"
497 // interval.
498 return SchedScanIntervalSetting{{}, fast_scan_interval};
499 }
500 }
501
OnOffloadScanResult()502 void ScannerImpl::OnOffloadScanResult() {
503 if (!pno_scan_running_over_offload_) {
504 LOG(WARNING) << "Scan results from Offload HAL but scan not requested over "
505 "this interface";
506 return;
507 }
508 LOG(INFO) << "Offload Scan results received";
509 pno_scan_results_from_offload_ = true;
510 if (pno_scan_event_handler_ != nullptr) {
511 pno_scan_event_handler_->OnPnoNetworkFound();
512 } else {
513 LOG(WARNING) << "No scan event handler Offload Scan result";
514 }
515 }
516
OnOffloadError(OffloadScanCallbackInterface::AsyncErrorReason error_code)517 void ScannerImpl::OnOffloadError(
518 OffloadScanCallbackInterface::AsyncErrorReason error_code) {
519 if (!pno_scan_running_over_offload_) {
520 // Ignore irrelevant error notifications
521 LOG(WARNING) << "Offload HAL Async Error occured but Offload HAL is not "
522 "subscribed to";
523 return;
524 }
525 LOG(ERROR) << "Offload Service Async Failure error_code=" << error_code;
526 switch (error_code) {
527 case OffloadScanCallbackInterface::AsyncErrorReason::BINDER_DEATH:
528 LOG(ERROR) << "Binder death";
529 if (pno_scan_event_handler_ != nullptr) {
530 pno_scan_event_handler_->OnPnoScanOverOffloadFailed(
531 net::wifi::IPnoScanEvent::PNO_SCAN_OVER_OFFLOAD_BINDER_FAILURE);
532 }
533 break;
534 case OffloadScanCallbackInterface::AsyncErrorReason::REMOTE_FAILURE:
535 LOG(ERROR) << "Remote failure";
536 if (pno_scan_event_handler_ != nullptr) {
537 pno_scan_event_handler_->OnPnoScanOverOffloadFailed(
538 net::wifi::IPnoScanEvent::PNO_SCAN_OVER_OFFLOAD_REMOTE_FAILURE);
539 }
540 break;
541 default:
542 LOG(WARNING) << "Invalid Error code";
543 break;
544 }
545 bool success = false;
546 // Stop scans over Offload HAL and request them over netlink
547 stopPnoScan(&success);
548 if (success) {
549 LOG(INFO) << "Pno scans stopped";
550 }
551 // Restart PNO scans over netlink interface
552 success = StartPnoScanDefault(pno_settings_);
553 if (success) {
554 LOG(INFO) << "Pno scans restarted";
555 } else {
556 LOG(ERROR) << "Unable to fall back to netlink pno scan";
557 pno_scan_event_handler_->OnPnoScanFailed();
558 }
559 }
560
LogSsidList(vector<vector<uint8_t>> & ssid_list,string prefix)561 void ScannerImpl::LogSsidList(vector<vector<uint8_t>>& ssid_list,
562 string prefix) {
563 if (ssid_list.empty()) {
564 return;
565 }
566 string ssid_list_string;
567 for (auto& ssid : ssid_list) {
568 ssid_list_string += string(ssid.begin(), ssid.end());
569 if (&ssid != &ssid_list.back()) {
570 ssid_list_string += ", ";
571 }
572 }
573 LOG(WARNING) << prefix << ": " << ssid_list_string;
574 }
575
576 } // namespace wificond
577 } // namespace android
578