• 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::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