• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "wificond/scanning/offload/offload_scan_manager.h"
17 
18 #include <vector>
19 
20 #include <android-base/logging.h>
21 
22 #include "wificond/scanning/offload/hidl_call_util.h"
23 #include "wificond/scanning/offload/offload_scan_utils.h"
24 #include "wificond/scanning/offload/offload_service_utils.h"
25 #include "wificond/scanning/offload/scan_stats.h"
26 #include "wificond/scanning/scan_result.h"
27 
28 using android::hardware::wifi::offload::V1_0::IOffload;
29 using android::hardware::wifi::offload::V1_0::ScanResult;
30 using android::hardware::wifi::offload::V1_0::ScanFilter;
31 using android::hardware::wifi::offload::V1_0::ScanParam;
32 using android::hardware::wifi::offload::V1_0::ScanStats;
33 using android::hardware::wifi::offload::V1_0::OffloadStatus;
34 using android::hardware::wifi::offload::V1_0::OffloadStatusCode;
35 
36 using ::com::android::server::wifi::wificond::NativeScanResult;
37 using ::com::android::server::wifi::wificond::NativeScanStats;
38 using std::vector;
39 using std::weak_ptr;
40 using std::shared_ptr;
41 
42 using namespace std::placeholders;
43 
44 namespace {
45 const uint32_t kSubscriptionDelayMs = 5000;
46 }
47 
48 namespace android {
49 namespace wificond {
50 
OffloadCallbackHandlersImpl(OffloadScanManager * offload_scan_manager)51 OffloadCallbackHandlersImpl::OffloadCallbackHandlersImpl(
52     OffloadScanManager* offload_scan_manager)
53     : offload_scan_manager_(offload_scan_manager) {}
54 
~OffloadCallbackHandlersImpl()55 OffloadCallbackHandlersImpl::~OffloadCallbackHandlersImpl() {}
56 
OnScanResultHandler(const vector<ScanResult> & scanResult)57 void OffloadCallbackHandlersImpl::OnScanResultHandler(
58     const vector<ScanResult>& scanResult) {
59   if (offload_scan_manager_ != nullptr) {
60     offload_scan_manager_->ReportScanResults(scanResult);
61   }
62 }
63 
OnErrorHandler(const OffloadStatus & status)64 void OffloadCallbackHandlersImpl::OnErrorHandler(const OffloadStatus& status) {
65   if (offload_scan_manager_ != nullptr) {
66     offload_scan_manager_->ReportError(status);
67   }
68 }
69 
OffloadScanManager(weak_ptr<OffloadServiceUtils> utils,shared_ptr<OffloadScanCallbackInterface> callback)70 OffloadScanManager::OffloadScanManager(
71     weak_ptr<OffloadServiceUtils> utils,
72     shared_ptr<OffloadScanCallbackInterface> callback)
73     : wifi_offload_hal_(nullptr),
74       wifi_offload_callback_(nullptr),
75       death_recipient_(nullptr),
76       offload_status_(OffloadScanManager::kError),
77       service_available_(false),
78       offload_service_utils_(utils),
79       offload_callback_handlers_(new OffloadCallbackHandlersImpl(this)),
80       event_callback_(callback) {
81   if (InitService()) {
82     offload_status_ = OffloadScanManager::kNoError;
83   }
84 }
85 
InitService()86 bool OffloadScanManager::InitService() {
87   wifi_offload_hal_ = offload_service_utils_.lock()->GetOffloadService();
88   if (wifi_offload_hal_ == nullptr) {
89     LOG(ERROR) << "No Offload Service available";
90     return false;
91   }
92 
93   death_recipient_ = offload_service_utils_.lock()->GetOffloadDeathRecipient(
94       std::bind(&OffloadScanManager::OnObjectDeath, this, _1));
95   uint64_t cookie = reinterpret_cast<uint64_t>(wifi_offload_hal_.get());
96 
97   auto link_to_death_status =
98       wifi_offload_hal_->linkToDeath(death_recipient_, cookie);
99   if (!link_to_death_status.isOk()) {
100     LOG(ERROR) << "Unable to register death handler "
101                << link_to_death_status.description();
102     return false;
103   }
104 
105   wifi_offload_callback_ = offload_service_utils_.lock()->GetOffloadCallback(
106       offload_callback_handlers_.get());
107   if (wifi_offload_callback_ == nullptr) {
108     LOG(ERROR) << "Invalid Offload callback object";
109     return false;
110   }
111 
112   auto set_callback_status =
113       wifi_offload_hal_->setEventCallback(wifi_offload_callback_);
114   if (!set_callback_status.isOk()) {
115     LOG(ERROR) << "Unable to set event callback for Offload HAL";
116     return false;
117   }
118 
119   service_available_ = true;
120   return true;
121 }
122 
InitServiceIfNeeded()123 bool OffloadScanManager::InitServiceIfNeeded() {
124   if (!service_available_) {
125     return InitService();
126   }
127   return true;
128 }
129 
stopScan(OffloadScanManager::ReasonCode * reason_code)130 bool OffloadScanManager::stopScan(OffloadScanManager::ReasonCode* reason_code) {
131   if (!InitServiceIfNeeded() ||
132       (getOffloadStatus() != OffloadScanManager::kNoError)) {
133     *reason_code = OffloadScanManager::kNotAvailable;
134     return false;
135   }
136   const auto& res = wifi_offload_hal_->unsubscribeScanResults();
137   if (!res.isOk()) {
138     *reason_code = OffloadScanManager::kTransactionFailed;
139     LOG(WARNING) << "unsubscribeScanResults() failed " << res.description();
140     return false;
141   }
142   *reason_code = OffloadScanManager::kNone;
143   return true;
144 }
145 
GetScanStats(NativeScanStats * native_scan_stats)146 bool OffloadScanManager::GetScanStats(NativeScanStats* native_scan_stats) {
147   const auto& result = HIDL_INVOKE(wifi_offload_hal_, getScanStats);
148   const auto& offload_status_and_scan_stats = result.first;
149   bool transport_status = result.second;
150   if (!transport_status) {
151     return false;
152   }
153   OffloadStatus offload_status = offload_status_and_scan_stats.first;
154   ScanStats scan_stats = offload_status_and_scan_stats.second;
155   if (offload_status.code != OffloadStatusCode::OK) {
156     LOG(WARNING) << offload_status.description;
157     return false;
158   }
159   *native_scan_stats = OffloadScanUtils::convertToNativeScanStats(scan_stats);
160   return true;
161 }
162 
VerifyAndConvertHIDLStatus(std::pair<OffloadStatus,bool> result,OffloadScanManager::ReasonCode * reason_code)163 bool OffloadScanManager::VerifyAndConvertHIDLStatus(
164     std::pair<OffloadStatus, bool> result,
165     OffloadScanManager::ReasonCode* reason_code) {
166   const auto& offload_status = result.first;
167   bool transport_status = result.second;
168   if (!transport_status) {
169     *reason_code = OffloadScanManager::kTransactionFailed;
170     return false;
171   }
172   if (offload_status.code != OffloadStatusCode::OK) {
173     LOG(WARNING) << offload_status.description;
174     *reason_code = OffloadScanManager::kOperationFailed;
175     return false;
176   }
177   return true;
178 }
179 
startScan(uint32_t interval_ms,int32_t rssi_threshold,const vector<vector<uint8_t>> & scan_ssids,const vector<vector<uint8_t>> & match_ssids,const vector<uint8_t> & match_security,const vector<uint32_t> & freqs,OffloadScanManager::ReasonCode * reason_code)180 bool OffloadScanManager::startScan(
181     uint32_t interval_ms, int32_t rssi_threshold,
182     const vector<vector<uint8_t>>& scan_ssids,
183     const vector<vector<uint8_t>>& match_ssids,
184     const vector<uint8_t>& match_security, const vector<uint32_t>& freqs,
185     OffloadScanManager::ReasonCode* reason_code) {
186   if (!InitServiceIfNeeded() ||
187       getOffloadStatus() != OffloadScanManager::kNoError) {
188     *reason_code = OffloadScanManager::kNotAvailable;
189     LOG(WARNING) << "Offload HAL scans are not available";
190     return false;
191   }
192   ScanParam param =
193       OffloadScanUtils::createScanParam(scan_ssids, freqs, interval_ms);
194   ScanFilter filter = OffloadScanUtils::createScanFilter(
195       match_ssids, match_security, rssi_threshold);
196 
197   if (!ConfigureScans(param, filter, reason_code)) {
198     return false;
199   }
200 
201   if (!SubscribeScanResults(reason_code)) {
202     return false;
203   }
204 
205   *reason_code = OffloadScanManager::kNone;
206   return true;
207 }
208 
ConfigureScans(ScanParam param,ScanFilter filter,OffloadScanManager::ReasonCode * reason_code)209 bool OffloadScanManager::ConfigureScans(
210     ScanParam param, ScanFilter filter,
211     OffloadScanManager::ReasonCode* reason_code) {
212   const auto& result =
213       HIDL_INVOKE(wifi_offload_hal_, configureScans, param, filter);
214   if (!VerifyAndConvertHIDLStatus(result, reason_code)) {
215     return false;
216   }
217   return true;
218 }
219 
SubscribeScanResults(OffloadScanManager::ReasonCode * reason_code)220 bool OffloadScanManager::SubscribeScanResults(
221     OffloadScanManager::ReasonCode* reason_code) {
222   const auto& result = HIDL_INVOKE(wifi_offload_hal_, subscribeScanResults,
223                                    kSubscriptionDelayMs);
224   if (!VerifyAndConvertHIDLStatus(result, reason_code)) {
225     return false;
226   }
227   return true;
228 }
229 
getOffloadStatus() const230 OffloadScanManager::StatusCode OffloadScanManager::getOffloadStatus() const {
231   if (!service_available_) {
232     return OffloadScanManager::kNoService;
233   }
234   return offload_status_;
235 }
236 
getScanResults(std::vector<NativeScanResult> * out_scan_results)237 bool OffloadScanManager::getScanResults(
238     std::vector<NativeScanResult>* out_scan_results) {
239   for (const auto& scan_result : cached_scan_results_) {
240     out_scan_results->push_back(scan_result);
241   }
242   return true;
243 }
244 
getScanStats(NativeScanStats * native_scan_stats)245 bool OffloadScanManager::getScanStats(NativeScanStats* native_scan_stats) {
246   if (!InitServiceIfNeeded()) {
247     LOG(ERROR) << "Offload HAL service unavailable";
248     return false;
249   }
250   if (getOffloadStatus() != OffloadScanManager::kNoError) {
251     LOG(WARNING) << "Unable to get scan stats due to Wifi Offload HAL error";
252     return false;
253   }
254   return GetScanStats(native_scan_stats);
255 }
256 
~OffloadScanManager()257 OffloadScanManager::~OffloadScanManager() {
258   if (wifi_offload_hal_ != nullptr) {
259     wifi_offload_hal_->unlinkToDeath(death_recipient_);
260   }
261 }
262 
ReportScanResults(const vector<ScanResult> & scanResult)263 void OffloadScanManager::ReportScanResults(
264     const vector<ScanResult>& scanResult) {
265   cached_scan_results_.clear();
266   if (!OffloadScanUtils::convertToNativeScanResults(scanResult,
267                                                     &cached_scan_results_)) {
268     LOG(WARNING) << "Unable to convert scan results to native format";
269     return;
270   }
271   if (event_callback_ != nullptr) {
272     event_callback_->OnOffloadScanResult();
273   } else {
274     LOG(WARNING)
275         << "No callback to report Offload HAL's scan results to wificond";
276   }
277 }
278 
ReportError(const OffloadStatus & status)279 void OffloadScanManager::ReportError(const OffloadStatus& status) {
280   OffloadStatusCode status_code = status.code;
281   OffloadScanManager::StatusCode status_result = OffloadScanManager::kNoError;
282   switch (status_code) {
283     case OffloadStatusCode::OK:
284       status_result = OffloadScanManager::kNoError;
285       break;
286     case OffloadStatusCode::TIMEOUT:
287       status_result = OffloadScanManager::kTimeOut;
288       break;
289     case OffloadStatusCode::NO_CONNECTION:
290       status_result = OffloadScanManager::kNotConnected;
291       break;
292     case OffloadStatusCode::ERROR:
293       status_result = OffloadScanManager::kError;
294       break;
295     default:
296       LOG(WARNING) << "Invalid Offload Error reported";
297       return;
298   }
299   if (status_result != OffloadScanManager::kNoError) {
300     LOG(WARNING) << "Offload Error reported " << status.description;
301     if (event_callback_ != nullptr) {
302       event_callback_->OnOffloadError(
303           OffloadScanCallbackInterface::REMOTE_FAILURE);
304     } else {
305       LOG(WARNING) << "No callback to report Offload HAL Errors to wificond";
306     }
307   }
308   offload_status_ = status_result;
309 }
310 
OnObjectDeath(uint64_t cookie)311 void OffloadScanManager::OnObjectDeath(uint64_t cookie) {
312   if (wifi_offload_hal_ == reinterpret_cast<IOffload*>(cookie)) {
313     LOG(ERROR) << "Death Notification for Wifi Offload HAL";
314     wifi_offload_hal_.clear();
315     if (event_callback_ != nullptr) {
316       event_callback_->OnOffloadError(
317           OffloadScanCallbackInterface::BINDER_DEATH);
318     } else {
319       LOG(WARNING)
320           << "No callback to report Offload HAL Binder death to wificond";
321     }
322     service_available_ = false;
323     death_recipient_.clear();
324   }
325 }
326 
327 }  // namespace wificond
328 }  // namespace android
329