OSDN Git Service

Merge changes from topic 'WIFI_OFFLOAD_HAL_MASTER'
[android-x86/system-connectivity-wificond.git] / scanning / scanner_impl.cpp
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/scan_utils.h"
26 #include "wificond/scanning/offload/offload_service_utils.h"
27 #include "wificond/scanning/offload/offload_scan_manager.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::string;
39 using std::vector;
40
41 using namespace std::placeholders;
42
43 namespace android {
44 namespace wificond {
45
46 ScannerImpl::ScannerImpl(uint32_t wiphy_index,
47                          uint32_t interface_index,
48                          const ScanCapabilities& scan_capabilities,
49                          const WiphyFeatures& wiphy_features,
50                          ClientInterfaceImpl* client_interface,
51                          NetlinkUtils* netlink_utils,
52                          ScanUtils* scan_utils)
53     : valid_(true),
54       scan_started_(false),
55       pno_scan_started_(false),
56       wiphy_index_(wiphy_index),
57       interface_index_(interface_index),
58       scan_capabilities_(scan_capabilities),
59       wiphy_features_(wiphy_features),
60       client_interface_(client_interface),
61       netlink_utils_(netlink_utils),
62       scan_utils_(scan_utils),
63       scan_event_handler_(nullptr) {
64   // Subscribe one-shot scan result notification from kernel.
65   LOG(INFO) << "subscribe scan result for interface with index: "
66             << (int)interface_index_;
67   scan_utils_->SubscribeScanResultNotification(
68       interface_index_,
69       std::bind(&ScannerImpl::OnScanResultsReady,
70                 this,
71                 _1, _2, _3, _4));
72   // Subscribe scheduled scan result notification from kernel.
73   scan_utils_->SubscribeSchedScanResultNotification(
74       interface_index_,
75       std::bind(&ScannerImpl::OnSchedScanResultsReady,
76                 this,
77                 _1, _2));
78   offload_scan_manager_.reset(
79       new OffloadScanManager(new OffloadServiceUtils(),
80           std::bind(&ScannerImpl::OnOffloadScanResult,
81               this, _1)));
82 }
83
84 ScannerImpl::~ScannerImpl() {
85 }
86
87 void ScannerImpl::Invalidate() {
88   LOG(INFO) << "Unsubscribe scan result for interface with index: "
89             << (int)interface_index_;
90   scan_utils_->UnsubscribeScanResultNotification(interface_index_);
91   scan_utils_->UnsubscribeSchedScanResultNotification(interface_index_);
92 }
93
94 bool ScannerImpl::CheckIsValid() {
95   if (!valid_) {
96     LOG(DEBUG) << "Calling on a invalid scanner object."
97                << "Underlying client interface object was destroyed.";
98   }
99   return valid_;
100 }
101
102 Status ScannerImpl::getAvailable2gChannels(
103     std::unique_ptr<vector<int32_t>>* out_frequencies) {
104   if (!CheckIsValid()) {
105     return Status::ok();
106   }
107   BandInfo band_info;
108   if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
109                                &band_info,
110                                &scan_capabilities_,
111                                &wiphy_features_)) {
112     LOG(ERROR) << "Failed to get wiphy info from kernel";
113     out_frequencies->reset(nullptr);
114     return Status::ok();
115   }
116
117   out_frequencies->reset(new vector<int32_t>(band_info.band_2g.begin(),
118                                              band_info.band_2g.end()));
119   return Status::ok();
120 }
121
122 Status ScannerImpl::getAvailable5gNonDFSChannels(
123     std::unique_ptr<vector<int32_t>>* out_frequencies) {
124   if (!CheckIsValid()) {
125     return Status::ok();
126   }
127   BandInfo band_info;
128   if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
129                                &band_info,
130                                &scan_capabilities_,
131                                &wiphy_features_)) {
132     LOG(ERROR) << "Failed to get wiphy info from kernel";
133     out_frequencies->reset(nullptr);
134     return Status::ok();
135   }
136
137   out_frequencies->reset(new vector<int32_t>(band_info.band_5g.begin(),
138                                              band_info.band_5g.end()));
139   return Status::ok();
140 }
141
142 Status ScannerImpl::getAvailableDFSChannels(
143     std::unique_ptr<vector<int32_t>>* out_frequencies) {
144   if (!CheckIsValid()) {
145     return Status::ok();
146   }
147   BandInfo band_info;
148   if (!netlink_utils_->GetWiphyInfo(wiphy_index_,
149                                &band_info,
150                                &scan_capabilities_,
151                                &wiphy_features_)) {
152     LOG(ERROR) << "Failed to get wiphy info from kernel";
153     out_frequencies->reset(nullptr);
154     return Status::ok();
155   }
156
157   out_frequencies->reset(new vector<int32_t>(band_info.band_dfs.begin(),
158                                              band_info.band_dfs.end()));
159   return Status::ok();
160 }
161
162 Status ScannerImpl::getScanResults(vector<NativeScanResult>* out_scan_results) {
163   if (!CheckIsValid()) {
164     return Status::ok();
165   }
166   if (!scan_utils_->GetScanResult(interface_index_, out_scan_results)) {
167     LOG(ERROR) << "Failed to get scan results via NL80211";
168   }
169   return Status::ok();
170 }
171
172 Status ScannerImpl::scan(const SingleScanSettings& scan_settings,
173                          bool* out_success) {
174   if (!CheckIsValid()) {
175     *out_success = false;
176     return Status::ok();
177   }
178
179   if (scan_started_) {
180     LOG(WARNING) << "Scan already started";
181   }
182   // Only request MAC address randomization when station is not associated.
183   bool request_random_mac =  wiphy_features_.supports_random_mac_oneshot_scan &&
184       !client_interface_->IsAssociated();
185
186   // Initialize it with an empty ssid for a wild card scan.
187   vector<vector<uint8_t>> ssids = {{}};
188
189   vector<vector<uint8_t>> skipped_scan_ssids;
190   for (auto& network : scan_settings.hidden_networks_) {
191     if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {
192       skipped_scan_ssids.emplace_back(network.ssid_);
193       continue;
194     }
195     ssids.push_back(network.ssid_);
196   }
197
198   LogSsidList(skipped_scan_ssids, "Skip scan ssid for single scan");
199
200   vector<uint32_t> freqs;
201   for (auto& channel : scan_settings.channel_settings_) {
202     freqs.push_back(channel.frequency_);
203   }
204
205   if (!scan_utils_->Scan(interface_index_, request_random_mac, ssids, freqs)) {
206     *out_success = false;
207     return Status::ok();
208   }
209   scan_started_ = true;
210   *out_success = true;
211   return Status::ok();
212 }
213
214 Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,
215                                  bool* out_success) {
216   if (!CheckIsValid()) {
217     *out_success = false;
218     return Status::ok();
219   }
220   if (pno_scan_started_) {
221     LOG(WARNING) << "Pno scan already started";
222   }
223   // An empty ssid for a wild card scan.
224   vector<vector<uint8_t>> scan_ssids = {{}};
225   vector<vector<uint8_t>> match_ssids;
226   // Empty frequency list: scan all frequencies.
227   vector<uint32_t> freqs;
228
229   vector<vector<uint8_t>> skipped_scan_ssids;
230   vector<vector<uint8_t>> skipped_match_ssids;
231   for (auto& network : pno_settings.pno_networks_) {
232     // Add hidden network ssid.
233     if (network.is_hidden_) {
234       if (scan_ssids.size() + 1 > scan_capabilities_.max_num_sched_scan_ssids) {
235         skipped_scan_ssids.emplace_back(network.ssid_);
236         continue;
237       }
238       scan_ssids.push_back(network.ssid_);
239     }
240
241     if (match_ssids.size() + 1 > scan_capabilities_.max_match_sets) {
242       skipped_match_ssids.emplace_back(network.ssid_);
243       continue;
244     }
245     match_ssids.push_back(network.ssid_);
246   }
247
248   LogSsidList(skipped_scan_ssids, "Skip scan ssid for pno scan");
249   LogSsidList(skipped_match_ssids, "Skip match ssid for pno scan");
250
251   // Only request MAC address randomization when station is not associated.
252   bool request_random_mac = wiphy_features_.supports_random_mac_sched_scan &&
253       !client_interface_->IsAssociated();
254
255   if (!scan_utils_->StartScheduledScan(interface_index_,
256                                        pno_settings.interval_ms_,
257                                        // TODO: honor both rssi thresholds.
258                                        pno_settings.min_5g_rssi_,
259                                        request_random_mac,
260                                        scan_ssids,
261                                        match_ssids,
262                                        freqs)) {
263     *out_success = false;
264     LOG(ERROR) << "Failed to start pno scan";
265     return Status::ok();
266   }
267   LOG(INFO) << "Pno scan started";
268   pno_scan_started_ = true;
269   *out_success = true;
270   return Status::ok();
271 }
272
273 Status ScannerImpl::stopPnoScan(bool* out_success) {
274   if (!CheckIsValid()) {
275     *out_success = false;
276     return Status::ok();
277   }
278
279   if (!pno_scan_started_) {
280     LOG(WARNING) << "No pno scan started";
281   }
282   if (!scan_utils_->StopScheduledScan(interface_index_)) {
283     *out_success = false;
284     return Status::ok();
285   }
286   LOG(INFO) << "Pno scan stopped";
287   pno_scan_started_ = false;
288   *out_success = true;
289   return Status::ok();
290 }
291
292 Status ScannerImpl::subscribeScanEvents(const sp<IScanEvent>& handler) {
293   if (!CheckIsValid()) {
294     return Status::ok();
295   }
296
297   if (scan_event_handler_ != nullptr) {
298     LOG(ERROR) << "Found existing scan events subscriber."
299                << " This subscription request will unsubscribe it";
300   }
301   scan_event_handler_ = handler;
302   return Status::ok();
303 }
304
305 Status ScannerImpl::unsubscribeScanEvents() {
306   scan_event_handler_ = nullptr;
307   return Status::ok();
308 }
309
310
311 Status ScannerImpl::subscribePnoScanEvents(const sp<IPnoScanEvent>& handler) {
312   if (!CheckIsValid()) {
313     return Status::ok();
314   }
315
316   if (pno_scan_event_handler_ != nullptr) {
317     LOG(ERROR) << "Found existing pno scan events subscriber."
318                << " This subscription request will unsubscribe it";
319   }
320   pno_scan_event_handler_ = handler;
321
322   return Status::ok();
323 }
324
325 Status ScannerImpl::unsubscribePnoScanEvents() {
326   pno_scan_event_handler_ = nullptr;
327   return Status::ok();
328 }
329
330 void ScannerImpl::OnScanResultsReady(
331     uint32_t interface_index,
332     bool aborted,
333     vector<vector<uint8_t>>& ssids,
334     vector<uint32_t>& frequencies) {
335   if (!scan_started_) {
336     LOG(INFO) << "Received external scan result notification from kernel.";
337   }
338   scan_started_ = false;
339   if (scan_event_handler_ != nullptr) {
340     // TODO: Pass other parameters back once we find framework needs them.
341     if (aborted) {
342       LOG(WARNING) << "Scan aborted";
343       scan_event_handler_->OnScanFailed();
344     } else {
345       scan_event_handler_->OnScanResultReady();
346     }
347   } else {
348     LOG(WARNING) << "No scan event handler found.";
349   }
350 }
351
352 void ScannerImpl::OnSchedScanResultsReady(uint32_t interface_index,
353                                           bool scan_stopped) {
354   if (pno_scan_event_handler_ != nullptr) {
355     if (scan_stopped) {
356       // If |pno_scan_started_| is false.
357       // This stop notification might result from our own request.
358       // See the document for NL80211_CMD_SCHED_SCAN_STOPPED in nl80211.h.
359       if (pno_scan_started_) {
360         LOG(WARNING) << "Unexpected pno scan stopped event";
361         pno_scan_event_handler_->OnPnoScanFailed();
362       }
363       pno_scan_started_ = false;
364     } else {
365       LOG(INFO) << "Pno scan result ready event";
366       pno_scan_event_handler_->OnPnoNetworkFound();
367     }
368   }
369 }
370
371 void ScannerImpl::LogSsidList(vector<vector<uint8_t>>& ssid_list,
372                               string prefix) {
373   if (ssid_list.empty()) {
374     return;
375   }
376   string ssid_list_string;
377   for (auto& ssid : ssid_list) {
378     ssid_list_string += string(ssid.begin(), ssid.end());
379     if (&ssid != &ssid_list.back()) {
380       ssid_list_string += ", ";
381     }
382   }
383   LOG(WARNING) << prefix << ": " << ssid_list_string;
384 }
385
386 void ScannerImpl::OnOffloadScanResult(
387     std::vector<NativeScanResult> scanResult) {
388   // TODO: Process scan result
389   if (scan_event_handler_ != nullptr) {
390     scan_event_handler_->OnScanResultReady();
391   } else {
392     LOG(WARNING) << "No scan event handler Offload Scan result";
393   }
394 }
395
396 }  // namespace wificond
397 }  // namespace android