OSDN Git Service

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