OSDN Git Service

Merge "Wildcard ssid should be zero-length" am: 5a2e243cf3 am: 2604bf902e
[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/scanning/scan_utils.h"
25
26 using android::binder::Status;
27 using android::net::wifi::IPnoScanEvent;
28 using android::net::wifi::IScanEvent;
29 using android::sp;
30 using com::android::server::wifi::wificond::NativeScanResult;
31 using com::android::server::wifi::wificond::PnoSettings;
32 using com::android::server::wifi::wificond::SingleScanSettings;
33
34 using std::string;
35 using std::vector;
36
37 using namespace std::placeholders;
38
39 namespace android {
40 namespace wificond {
41
42 ScannerImpl::ScannerImpl(uint32_t interface_index,
43                          const BandInfo& band_info,
44                          const ScanCapabilities& scan_capabilities,
45                          const WiphyFeatures& wiphy_features,
46                          ScanUtils* scan_utils)
47     : valid_(true),
48       scan_started_(false),
49       pno_scan_started_(false),
50       interface_index_(interface_index),
51       band_info_(band_info),
52       scan_capabilities_(scan_capabilities),
53       wiphy_features_(wiphy_features),
54       scan_utils_(scan_utils),
55       scan_event_handler_(nullptr) {
56   // Subscribe one-shot scan result notification from kernel.
57   scan_utils_->SubscribeScanResultNotification(
58       interface_index_,
59       std::bind(&ScannerImpl::OnScanResultsReady,
60                 this,
61                 _1, _2, _3, _4));
62   // Subscribe scheduled scan result notification from kernel.
63   scan_utils_->SubscribeSchedScanResultNotification(
64       interface_index_,
65       std::bind(&ScannerImpl::OnSchedScanResultsReady,
66                 this,
67                 _1, _2));
68 }
69
70 ScannerImpl::~ScannerImpl() {
71   scan_utils_->UnsubscribeScanResultNotification(interface_index_);
72   scan_utils_->UnsubscribeSchedScanResultNotification(interface_index_);
73 }
74
75 bool ScannerImpl::CheckIsValid() {
76   if (!valid_) {
77     LOG(DEBUG) << "Calling on a invalid scanner object."
78                << "Underlying client interface object was destroyed.";
79   }
80   return valid_;
81 }
82
83 Status ScannerImpl::getAvailable2gChannels(vector<int32_t>* out_frequencies) {
84   if (!CheckIsValid()) {
85     return Status::ok();
86   }
87   *out_frequencies = vector<int32_t>(band_info_.band_2g.begin(),
88                                      band_info_.band_2g.end());
89   return Status::ok();
90 }
91
92 Status ScannerImpl::getAvailable5gNonDFSChannels(
93     vector<int32_t>* out_frequencies) {
94   if (!CheckIsValid()) {
95     return Status::ok();
96   }
97   *out_frequencies = vector<int32_t>(band_info_.band_5g.begin(),
98                                      band_info_.band_5g.end());
99   return Status::ok();
100 }
101
102 Status ScannerImpl::getAvailableDFSChannels(vector<int32_t>* out_frequencies) {
103   if (!CheckIsValid()) {
104     return Status::ok();
105   }
106   *out_frequencies = vector<int32_t>(band_info_.band_dfs.begin(),
107                                      band_info_.band_dfs.end());
108   return Status::ok();
109 }
110
111 Status ScannerImpl::getScanResults(vector<NativeScanResult>* out_scan_results) {
112   if (!CheckIsValid()) {
113     return Status::ok();
114   }
115   if (!scan_utils_->GetScanResult(interface_index_, out_scan_results)) {
116     LOG(ERROR) << "Failed to get scan results via NL80211";
117   }
118   return Status::ok();
119 }
120
121 Status ScannerImpl::scan(const SingleScanSettings& scan_settings,
122                          bool* out_success) {
123   if (!CheckIsValid()) {
124     return Status::ok();
125   }
126
127   if (scan_started_) {
128     LOG(WARNING) << "Scan already started";
129   }
130   bool random_mac =  wiphy_features_.supports_random_mac_oneshot_scan;
131
132   // Initialize it with an empty ssid for a wild card scan.
133   vector<vector<uint8_t>> ssids = {{}};
134   for (auto& network : scan_settings.hidden_networks_) {
135     if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {
136       LOG(WARNING) << "Skip scan ssid for single scan: "
137                    << string(network.ssid_.begin(), network.ssid_.end());
138       continue;
139     }
140     ssids.push_back(network.ssid_);
141   }
142
143   vector<uint32_t> freqs;
144   for (auto& channel : scan_settings.channel_settings_) {
145     freqs.push_back(channel.frequency_);
146   }
147
148   if (!scan_utils_->Scan(interface_index_, random_mac, ssids, freqs)) {
149     *out_success = false;
150     return Status::ok();
151   }
152   scan_started_ = true;
153   *out_success = true;
154   return Status::ok();
155 }
156
157 Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,
158                                  bool* out_success) {
159   if (!CheckIsValid()) {
160     return Status::ok();
161   }
162   if (pno_scan_started_) {
163     LOG(WARNING) << "Pno scan already started";
164   }
165   // An empty ssid for a wild card scan.
166   vector<vector<uint8_t>> scan_ssids = {{}};
167   vector<vector<uint8_t>> match_ssids;
168   // Empty frequency list: scan all frequencies.
169   vector<uint32_t> freqs;
170
171   for (auto& network : pno_settings.pno_networks_) {
172     // Add hidden network ssid.
173     if (network.is_hidden_) {
174       if (scan_ssids.size() + 1 > scan_capabilities_.max_num_sched_scan_ssids) {
175         LOG(WARNING) << "Skip scan ssid for pno scan: "
176                      << string(network.ssid_.begin(), network.ssid_.end());
177         continue;
178       }
179       scan_ssids.push_back(network.ssid_);
180     }
181
182     if (match_ssids.size() + 1 > scan_capabilities_.max_match_sets) {
183       LOG(WARNING) << "Skip match ssid for pno scan: "
184                    << string(network.ssid_.begin(), network.ssid_.end());
185       continue;
186     }
187     match_ssids.push_back(network.ssid_);
188   }
189
190   bool random_mac = wiphy_features_.supports_random_mac_sched_scan;
191
192   if (!scan_utils_->StartScheduledScan(interface_index_,
193                                        pno_settings.interval_ms_,
194                                        // TODO: honor both rssi thresholds.
195                                        pno_settings.min_2g_rssi_,
196                                        random_mac,
197                                        scan_ssids,
198                                        match_ssids,
199                                        freqs)) {
200     *out_success = false;
201     LOG(ERROR) << "Failed to start scheduled scan";
202     return Status::ok();
203   }
204   pno_scan_started_ = true;
205   *out_success = true;
206   return Status::ok();
207 }
208
209 Status ScannerImpl::stopPnoScan(bool* out_success) {
210   if (!CheckIsValid()) {
211     return Status::ok();
212   }
213
214   if (!pno_scan_started_) {
215     LOG(WARNING) << "No pno scan started";
216   }
217   if (!scan_utils_->StopScheduledScan(interface_index_)) {
218     *out_success = false;
219     return Status::ok();
220   }
221   pno_scan_started_ = false;
222   *out_success = true;
223   return Status::ok();
224 }
225
226 Status ScannerImpl::subscribeScanEvents(const sp<IScanEvent>& handler) {
227   if (!CheckIsValid()) {
228     return Status::ok();
229   }
230
231   if (scan_event_handler_ != nullptr) {
232     LOG(ERROR) << "Found existing scan events subscriber."
233                << " This subscription request will unsubscribe it";
234   }
235   scan_event_handler_ = handler;
236   return Status::ok();
237 }
238
239 Status ScannerImpl::unsubscribeScanEvents() {
240   scan_event_handler_ = nullptr;
241   return Status::ok();
242 }
243
244
245 Status ScannerImpl::subscribePnoScanEvents(const sp<IPnoScanEvent>& handler) {
246   if (!CheckIsValid()) {
247     return Status::ok();
248   }
249
250   if (pno_scan_event_handler_ != nullptr) {
251     LOG(ERROR) << "Found existing pno scan events subscriber."
252                << " This subscription request will unsubscribe it";
253   }
254   pno_scan_event_handler_ = handler;
255
256   return Status::ok();
257 }
258
259 Status ScannerImpl::unsubscribePnoScanEvents() {
260   pno_scan_event_handler_ = nullptr;
261   return Status::ok();
262 }
263
264 void ScannerImpl::OnScanResultsReady(
265     uint32_t interface_index,
266     bool aborted,
267     vector<vector<uint8_t>>& ssids,
268     vector<uint32_t>& frequencies) {
269   scan_started_ = false;
270   if (scan_event_handler_ != nullptr) {
271     // TODO: Pass other parameters back once we find framework needs them.
272     if (aborted) {
273       scan_event_handler_->OnScanFailed();
274     } else {
275       scan_event_handler_->OnScanResultReady();
276     }
277   }
278 }
279
280 void ScannerImpl::OnSchedScanResultsReady(uint32_t interface_index,
281                                           bool scan_stopped) {
282   if (pno_scan_event_handler_ != nullptr) {
283     if (scan_stopped) {
284       // If |pno_scan_started_| is false.
285       // This stop notification might result from our own request.
286       // See the document for NL80211_CMD_SCHED_SCAN_STOPPED in nl80211.h.
287       if (pno_scan_started_) {
288         pno_scan_event_handler_->OnPnoScanFailed();
289       }
290       pno_scan_started_ = false;
291     } else {
292       pno_scan_event_handler_->OnPnoNetworkFound();
293     }
294   }
295 }
296
297 }  // namespace wificond
298 }  // namespace android