OSDN Git Service

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