OSDN Git Service

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