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