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