OSDN Git Service

Enforce wificond scanner capability checks
[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   if (scan_settings.is_full_scan_) {
133     if (!scan_utils_->StartFullScan(interface_index_, random_mac)) {
134       *out_success = false;
135       return Status::ok();
136     }
137     scan_started_ = true;
138     return Status::ok();
139   }
140
141   // Initialize it with an empty ssid for a wild card scan.
142   vector<vector<uint8_t>> ssids = {{0}};
143   for (auto& network : scan_settings.hidden_networks_) {
144     if (ssids.size() + 1 > scan_capabilities_.max_num_scan_ssids) {
145       LOG(WARNING) << "Skip scan ssid for single scan: "
146                    << string(network.ssid_.begin(), network.ssid_.end());
147       continue;
148     }
149     ssids.push_back(network.ssid_);
150   }
151
152   vector<uint32_t> freqs;
153   for (auto& channel : scan_settings.channel_settings_) {
154     freqs.push_back(channel.frequency_);
155   }
156
157   if (!scan_utils_->Scan(interface_index_, random_mac, ssids, freqs)) {
158     *out_success = false;
159     return Status::ok();
160   }
161   scan_started_ = true;
162   *out_success = true;
163   return Status::ok();
164 }
165
166 Status ScannerImpl::startPnoScan(const PnoSettings& pno_settings,
167                                  bool* out_success) {
168   if (!CheckIsValid()) {
169     return Status::ok();
170   }
171   if (pno_scan_started_) {
172     LOG(WARNING) << "Pno scan already started";
173   }
174   // An empty ssid for a wild card scan.
175   vector<vector<uint8_t>> scan_ssids = {{0}};
176   vector<vector<uint8_t>> match_ssids;
177   // Empty frequency list: scan all frequencies.
178   vector<uint32_t> freqs;
179
180   for (auto& network : pno_settings.pno_networks_) {
181     // Add hidden network ssid.
182     if (network.is_hidden_) {
183       if (scan_ssids.size() + 1 > scan_capabilities_.max_num_sched_scan_ssids) {
184         LOG(WARNING) << "Skip scan ssid for pno scan: "
185                      << string(network.ssid_.begin(), network.ssid_.end());
186         continue;
187       }
188       scan_ssids.push_back(network.ssid_);
189     }
190
191     if (match_ssids.size() + 1 > scan_capabilities_.max_match_sets) {
192       LOG(WARNING) << "Skip match ssid for pno scan: "
193                    << string(network.ssid_.begin(), network.ssid_.end());
194       continue;
195     }
196     match_ssids.push_back(network.ssid_);
197   }
198
199   bool random_mac = wiphy_features_.supports_random_mac_sched_scan;
200
201   if (!scan_utils_->StartScheduledScan(interface_index_,
202                                        pno_settings.interval_ms_,
203                                        // TODO: honor both rssi thresholds.
204                                        pno_settings.min_2g_rssi_,
205                                        random_mac,
206                                        scan_ssids,
207                                        match_ssids,
208                                        freqs)) {
209     *out_success = false;
210     LOG(ERROR) << "Failed to start scheduled scan";
211     return Status::ok();
212   }
213   pno_scan_started_ = true;
214   *out_success = true;
215   return Status::ok();
216 }
217
218 Status ScannerImpl::stopPnoScan(bool* out_success) {
219   if (!CheckIsValid()) {
220     return Status::ok();
221   }
222
223   if (!pno_scan_started_) {
224     LOG(WARNING) << "No pno scan started";
225   }
226   if (!scan_utils_->StopScheduledScan(interface_index_)) {
227     *out_success = false;
228     return Status::ok();
229   }
230   pno_scan_started_ = false;
231   *out_success = true;
232   return Status::ok();
233 }
234
235 Status ScannerImpl::subscribeScanEvents(const sp<IScanEvent>& handler) {
236   if (!CheckIsValid()) {
237     return Status::ok();
238   }
239
240   if (scan_event_handler_ != nullptr) {
241     LOG(ERROR) << "Found existing scan events subscriber."
242                << " This subscription request will unsubscribe it";
243   }
244   scan_event_handler_ = handler;
245   return Status::ok();
246 }
247
248 Status ScannerImpl::unsubscribeScanEvents() {
249   scan_event_handler_ = nullptr;
250   return Status::ok();
251 }
252
253
254 Status ScannerImpl::subscribePnoScanEvents(const sp<IPnoScanEvent>& handler) {
255   if (!CheckIsValid()) {
256     return Status::ok();
257   }
258
259   if (pno_scan_event_handler_ != nullptr) {
260     LOG(ERROR) << "Found existing pno scan events subscriber."
261                << " This subscription request will unsubscribe it";
262   }
263   pno_scan_event_handler_ = handler;
264
265   return Status::ok();
266 }
267
268 Status ScannerImpl::unsubscribePnoScanEvents() {
269   pno_scan_event_handler_ = nullptr;
270   return Status::ok();
271 }
272
273 void ScannerImpl::OnScanResultsReady(
274     uint32_t interface_index,
275     bool aborted,
276     vector<vector<uint8_t>>& ssids,
277     vector<uint32_t>& frequencies) {
278   scan_started_ = false;
279   if (scan_event_handler_ != nullptr) {
280     // TODO: Pass other parameters back once we find framework needs them.
281     if (aborted) {
282       scan_event_handler_->OnScanFailed();
283     } else {
284       scan_event_handler_->OnScanResultReady();
285     }
286   }
287 }
288
289 void ScannerImpl::OnSchedScanResultsReady(uint32_t interface_index,
290                                           bool scan_stopped) {
291   if (pno_scan_event_handler_ != nullptr) {
292     if (scan_stopped) {
293       // If |pno_scan_started_| is false.
294       // This stop notification might result from our own request.
295       // See the document for NL80211_CMD_SCHED_SCAN_STOPPED in nl80211.h.
296       if (pno_scan_started_) {
297         pno_scan_event_handler_->OnPnoScanFailed();
298       }
299       pno_scan_started_ = false;
300     } else {
301       pno_scan_event_handler_->OnPnoNetworkFound();
302     }
303   }
304 }
305
306 }  // namespace wificond
307 }  // namespace android