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