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