• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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