1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "wifi_scan_proxy.h"
17 #include "define.h"
18 #include "wifi_manager_service_ipc_interface_code.h"
19 #include "ipc_skeleton.h"
20 #include "rpc_errno.h"
21 #include "serializer.h"
22 #include "samgr_lite.h"
23 #include "wifi_ipc_lite_adapter.h"
24 #include "wifi_logger.h"
25 #include "wifi_scan_callback_stub.h"
26
27 DEFINE_WIFILOG_SCAN_LABEL("WifiScanProxyLite");
28 namespace OHOS {
29 namespace Wifi {
30 static SvcIdentity g_sid;
31 static IpcObjectStub g_objStub;
32 static WifiScanCallbackStub g_wifiScanCallbackStub;
33
ParseScanInfos(IpcIo * reply,std::vector<WifiScanInfo> & infos)34 static ErrCode ParseScanInfos(IpcIo *reply, std::vector<WifiScanInfo> &infos)
35 {
36 constexpr int MAX_SIZE = 4096;
37 int tmpsize = 0;
38 (void)ReadInt32(reply, &tmpsize);
39 if (tmpsize > MAX_SIZE) {
40 WIFI_LOGE("Scan info size exceeds maximum allowed size: %{public}d", tmpsize);
41 return WIFI_OPT_FAILED;
42 }
43
44 size_t readLen;
45 for (int i = 0; i < tmpsize; ++i) {
46 WifiScanInfo info;
47 info.bssid = (char *)ReadString(reply, &readLen);
48 info.ssid = (char *)ReadString(reply, &readLen);
49 info.capabilities = (char *)ReadString(reply, &readLen);
50 (void)ReadInt32(reply, &info.frequency);
51 (void)ReadInt32(reply, &info.rssi);
52 int64_t timestamp = 0;
53 (void)ReadInt64(reply, ×tamp);
54 info.timestamp = timestamp;
55 (void)ReadInt32(reply, &info.band);
56 int securityType = 0;
57 (void)ReadInt32(reply, &securityType);
58 info.securityType = static_cast<WifiSecurity>(securityType);
59 int channelWidth = 0;
60 (void)ReadInt32(reply, &channelWidth);
61 info.channelWidth = static_cast<WifiChannelWidth>(channelWidth);
62 (void)ReadInt32(reply, &info.centerFrequency0);
63 (void)ReadInt32(reply, &info.centerFrequency1);
64 int64_t features = 0;
65 (void)ReadInt64(reply, &features);
66 info.features = features;
67
68 constexpr int IE_SIZE_MAX = 256;
69 int ieSize = 0;
70 (void)ReadInt32(reply, &ieSize);
71 if (ieSize > IE_SIZE_MAX) {
72 WIFI_LOGE("ie size error: %{public}d", ieSize);
73 return WIFI_OPT_FAILED;
74 }
75 for (int m = 0; m < ieSize; ++m) {
76 WifiInfoElem tempWifiInfoElem;
77 (void)ReadUint32(reply, &tempWifiInfoElem.id);
78 int contentSize = 0;
79 (void)ReadInt32(reply, &contentSize);
80 int8_t tmpInt8 = 0;
81 for (int n = 0; n < contentSize; n++) {
82 (void)ReadInt8(reply, &tmpInt8);
83 char tempChar = static_cast<char>(tmpInt8);
84 tempWifiInfoElem.content.emplace_back(tempChar);
85 }
86 info.infoElems.emplace_back(tempWifiInfoElem);
87 }
88 infos.emplace_back(info);
89 }
90 return WIFI_OPT_SUCCESS;
91 }
92
IpcCallback(void * owner,int code,IpcIo * reply)93 static int IpcCallback(void *owner, int code, IpcIo *reply)
94 {
95 if (code != 0 || owner == nullptr || reply == nullptr) {
96 WIFI_LOGE("Callback error, code:%{public}d, owner:%{public}d, reply:%{public}d",
97 code, owner == nullptr, reply == nullptr);
98 return ERR_FAILED;
99 }
100
101 struct IpcOwner *data = (struct IpcOwner *)owner;
102 (void)ReadInt32(reply, &data->exception);
103 (void)ReadInt32(reply, &data->retCode);
104 if (data->exception != 0 || data->retCode != WIFI_OPT_SUCCESS || data->variable == nullptr) {
105 return ERR_NONE;
106 }
107
108 switch (data->funcId) {
109 case static_cast<uint32_t>(ScanInterfaceCode::WIFI_SVR_CMD_IS_SCAN_ALWAYS_ACTIVE): {
110 (void)ReadBool(reply, (bool *)data->variable);
111 break;
112 }
113 case static_cast<uint32_t>(DevInterfaceCode::WIFI_SVR_CMD_GET_SUPPORTED_FEATURES): {
114 int64_t features = 0;
115 (void)ReadInt64(reply, &features);
116 *((long *)data->variable) = features;
117 break;
118 }
119 case static_cast<uint32_t>(ScanInterfaceCode::WIFI_SVR_CMD_GET_SCAN_INFO_LIST): {
120 data->retCode = ParseScanInfos(reply, *((std::vector<WifiScanInfo> *)data->variable));
121 break;
122 }
123 default:
124 break;
125 }
126 return ERR_NONE;
127 }
128
AsyncCallback(uint32_t code,IpcIo * data,IpcIo * reply,MessageOption option)129 static int AsyncCallback(uint32_t code, IpcIo *data, IpcIo *reply, MessageOption option)
130 {
131 if (data == nullptr) {
132 WIFI_LOGE("AsyncCallback error, data is null");
133 return ERR_FAILED;
134 }
135 return g_wifiScanCallbackStub.OnRemoteRequest(code, data);
136 }
137
OnRemoteSrvDied(void * arg)138 static void OnRemoteSrvDied(void *arg)
139 {
140 WIFI_LOGE("%{public}s called.", __func__);
141 WifiScanProxy *client = WifiScanProxy::GetInstance();
142 if (client != nullptr) {
143 client->OnRemoteDied();
144 }
145 return;
146 }
147
148 WifiScanProxy *WifiScanProxy::g_instance = nullptr;
WifiScanProxy()149 WifiScanProxy::WifiScanProxy() : remote_(nullptr), remoteDied_(false)
150 {}
151
~WifiScanProxy()152 WifiScanProxy::~WifiScanProxy()
153 {}
154
GetInstance(void)155 WifiScanProxy *WifiScanProxy::GetInstance(void)
156 {
157 if (g_instance != nullptr) {
158 return g_instance;
159 }
160
161 WifiScanProxy *tempInstance = new(std::nothrow) WifiScanProxy();
162 g_instance = tempInstance;
163 return g_instance;
164 }
165
ReleaseInstance(void)166 void WifiScanProxy::ReleaseInstance(void)
167 {
168 if (g_instance != nullptr) {
169 delete g_instance;
170 g_instance = nullptr;
171 }
172 }
173
Init(void)174 ErrCode WifiScanProxy::Init(void)
175 {
176 IUnknown *iUnknown = SAMGR_GetInstance()->GetFeatureApi(WIFI_SERVICE_LITE, WIFI_FEATRUE_SCAN);
177 if (iUnknown == nullptr) {
178 WIFI_LOGE("GetFeatureApi failed.");
179 return WIFI_OPT_FAILED;
180 }
181 IClientProxy *proxy = nullptr;
182 int result = iUnknown->QueryInterface(iUnknown, CLIENT_PROXY_VER, reinterpret_cast<void **>(&proxy));
183 if (result != 0) {
184 WIFI_LOGE("QueryInterface failed.");
185 return WIFI_OPT_FAILED;
186 }
187 remote_ = proxy;
188
189 // Register SA Death Callback
190 uint32_t deadId = 0;
191 svcIdentity_ = SAMGR_GetRemoteIdentity(WIFI_SERVICE_LITE, WIFI_FEATRUE_SCAN);
192 result = AddDeathRecipient(svcIdentity_, OnRemoteSrvDied, nullptr, &deadId);
193 if (result != 0) {
194 WIFI_LOGE("Register SA Death Callback failed, errorCode[%d]", result);
195 }
196 return WIFI_OPT_SUCCESS;
197 }
198
SetScanControlInfo(const ScanControlInfo & info)199 ErrCode WifiScanProxy::SetScanControlInfo(const ScanControlInfo &info)
200 {
201 if (remoteDied_ || remote_ == nullptr) {
202 WIFI_LOGE("failed to %{public}s, remoteDied_: %{public}d, remote_: %{public}d",
203 __func__, remoteDied_, remote_ == nullptr);
204 return WIFI_OPT_FAILED;
205 }
206
207 IpcIo request;
208 char data[IPC_DATA_SIZE_BIG];
209 struct IpcOwner owner = {.exception = -1, .retCode = 0, .variable = nullptr};
210
211 IpcIoInit(&request, data, IPC_DATA_SIZE_BIG, MAX_IPC_OBJ_COUNT);
212 if (!WriteInterfaceToken(&request, DECLARE_INTERFACE_DESCRIPTOR_L1, DECLARE_INTERFACE_DESCRIPTOR_L1_LENGTH)) {
213 WIFI_LOGE("Write interface token error: %{public}s", __func__);
214 return WIFI_OPT_FAILED;
215 }
216 (void)WriteInt32(&request, 0);
217 (void)WriteInt32(&request, info.scanForbidList.size());
218 for (auto iter = info.scanForbidList.begin(); iter != info.scanForbidList.end(); iter++) {
219 (void)WriteInt32(&request, iter->scanScene);
220 (void)WriteInt32(&request, static_cast<int>(iter->scanMode));
221 (void)WriteInt32(&request, iter->forbidTime);
222 (void)WriteInt32(&request, iter->forbidCount);
223 }
224
225 (void)WriteInt32(&request, info.scanIntervalList.size());
226 for (auto iter2 = info.scanIntervalList.begin(); iter2 != info.scanIntervalList.end(); iter2++) {
227 (void)WriteInt32(&request, iter2->scanScene);
228 (void)WriteInt32(&request, static_cast<int>(iter2->scanMode));
229 (void)WriteBool(&request, iter2->isSingle);
230 (void)WriteInt32(&request, static_cast<int>(iter2->intervalMode));
231 (void)WriteInt32(&request, iter2->interval);
232 (void)WriteInt32(&request, iter2->count);
233 }
234
235 owner.funcId = static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_SET_SCAN_CONTROL_INFO);
236 int error = remote_->Invoke(remote_, static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_SET_SCAN_CONTROL_INFO),
237 &request, &owner, IpcCallback);
238 if (error != EC_SUCCESS) {
239 WIFI_LOGW("Set Attr(%{public}d) failed",
240 static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_SET_SCAN_CONTROL_INFO));
241 return WIFI_OPT_FAILED;
242 }
243
244 if (owner.exception) {
245 return WIFI_OPT_FAILED;
246 }
247 return ErrCode(owner.retCode);
248 }
249
Scan(bool compatible)250 ErrCode WifiScanProxy::Scan(bool compatible)
251 {
252 if (remoteDied_ || remote_ == nullptr) {
253 WIFI_LOGE("failed to %{public}s, remoteDied_: %{public}d, remote_: %{public}d",
254 __func__, remoteDied_, remote_ == nullptr);
255 return WIFI_OPT_FAILED;
256 }
257
258 IpcIo request;
259 char data[IPC_DATA_SIZE_SMALL];
260 struct IpcOwner owner = {.exception = -1, .retCode = 0, .variable = nullptr};
261
262 IpcIoInit(&request, data, IPC_DATA_SIZE_SMALL, MAX_IPC_OBJ_COUNT);
263 if (!WriteInterfaceToken(&request, DECLARE_INTERFACE_DESCRIPTOR_L1, DECLARE_INTERFACE_DESCRIPTOR_L1_LENGTH)) {
264 WIFI_LOGE("Write interface token error: %{public}s", __func__);
265 return WIFI_OPT_FAILED;
266 }
267 (void)WriteInt32(&request, 0);
268
269 owner.funcId = static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_FULL_SCAN);
270 int error = remote_->Invoke(remote_, static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_FULL_SCAN),
271 &request, &owner, IpcCallback);
272 if (error != EC_SUCCESS) {
273 WIFI_LOGW("Set Attr(%{public}d) failed", static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_FULL_SCAN));
274 return WIFI_OPT_FAILED;
275 }
276
277 if (owner.exception) {
278 return WIFI_OPT_FAILED;
279 }
280 return ErrCode(owner.retCode);
281 }
282
AdvanceScan(const WifiScanParams & params)283 ErrCode WifiScanProxy::AdvanceScan(const WifiScanParams ¶ms)
284 {
285 if (remoteDied_ || remote_ == nullptr) {
286 WIFI_LOGE("failed to %{public}s, remoteDied_: %{public}d, remote_: %{public}d",
287 __func__, remoteDied_, remote_ == nullptr);
288 return WIFI_OPT_FAILED;
289 }
290
291 IpcIo request;
292 char data[IPC_DATA_SIZE_MID];
293 struct IpcOwner owner = {.exception = -1, .retCode = 0, .variable = nullptr};
294
295 IpcIoInit(&request, data, IPC_DATA_SIZE_MID, MAX_IPC_OBJ_COUNT);
296 if (!WriteInterfaceToken(&request, DECLARE_INTERFACE_DESCRIPTOR_L1, DECLARE_INTERFACE_DESCRIPTOR_L1_LENGTH)) {
297 WIFI_LOGE("Write interface token error: %{public}s", __func__);
298 return WIFI_OPT_FAILED;
299 }
300 (void)WriteInt32(&request, 0);
301 (void)WriteString(&request, params.ssid.c_str());
302 (void)WriteString(&request, params.bssid.c_str());
303 (void)WriteInt32(&request, params.freqs.size());
304 for (std::size_t i = 0; i < params.freqs.size(); i++) {
305 (void)WriteInt32(&request, params.freqs[i]);
306 }
307 (void)WriteUint32(&request, params.band);
308
309 owner.funcId = static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_SPECIFIED_PARAMS_SCAN);
310 int error = remote_->Invoke(remote_, static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_SPECIFIED_PARAMS_SCAN),
311 &request, &owner, IpcCallback);
312 if (error != EC_SUCCESS) {
313 WIFI_LOGW("Set Attr(%{public}d) failed",
314 static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_SPECIFIED_PARAMS_SCAN));
315 return WIFI_OPT_FAILED;
316 }
317
318 if (owner.exception) {
319 return WIFI_OPT_FAILED;
320 }
321
322 return ErrCode(owner.retCode);
323 }
324
IsWifiClosedScan(bool & bOpen)325 ErrCode WifiScanProxy::IsWifiClosedScan(bool &bOpen)
326 {
327 if (remoteDied_ || remote_ == nullptr) {
328 WIFI_LOGE("failed to %{public}s, remoteDied_: %{public}d, remote_: %{public}d",
329 __func__, remoteDied_, remote_ == nullptr);
330 return WIFI_OPT_FAILED;
331 }
332
333 IpcIo request;
334 char data[IPC_DATA_SIZE_SMALL];
335 struct IpcOwner owner = {.exception = -1, .retCode = 0, .variable = nullptr};
336
337 IpcIoInit(&request, data, IPC_DATA_SIZE_SMALL, MAX_IPC_OBJ_COUNT);
338 if (!WriteInterfaceToken(&request, DECLARE_INTERFACE_DESCRIPTOR_L1, DECLARE_INTERFACE_DESCRIPTOR_L1_LENGTH)) {
339 WIFI_LOGE("Write interface token error: %{public}s", __func__);
340 return WIFI_OPT_FAILED;
341 }
342 (void)WriteInt32(&request, 0);
343 owner.variable = &bOpen;
344 owner.funcId = static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_IS_SCAN_ALWAYS_ACTIVE);
345 int error = remote_->Invoke(remote_, static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_IS_SCAN_ALWAYS_ACTIVE),
346 &request, &owner, IpcCallback);
347 if (error != EC_SUCCESS) {
348 WIFI_LOGW("Set Attr(%{public}d) failed",
349 static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_IS_SCAN_ALWAYS_ACTIVE));
350 return WIFI_OPT_FAILED;
351 }
352
353 if (owner.exception) {
354 return WIFI_OPT_FAILED;
355 }
356 return ErrCode(owner.retCode);
357 }
358
GetScanInfoList(std::vector<WifiScanInfo> & result,bool compatible)359 ErrCode WifiScanProxy::GetScanInfoList(std::vector<WifiScanInfo> &result, bool compatible)
360 {
361 if (remoteDied_ || remote_ == nullptr) {
362 WIFI_LOGE("failed to %{public}s, remoteDied_: %{public}d, remote_: %{public}d",
363 __func__, remoteDied_, remote_ == nullptr);
364 return WIFI_OPT_FAILED;
365 }
366
367 IpcIo request;
368 char data[IPC_DATA_SIZE_SMALL];
369 struct IpcOwner owner = {.exception = -1, .retCode = 0, .variable = nullptr};
370
371 IpcIoInit(&request, data, IPC_DATA_SIZE_SMALL, MAX_IPC_OBJ_COUNT);
372 if (!WriteInterfaceToken(&request, DECLARE_INTERFACE_DESCRIPTOR_L1, DECLARE_INTERFACE_DESCRIPTOR_L1_LENGTH)) {
373 WIFI_LOGE("Write interface token error: %{public}s", __func__);
374 return WIFI_OPT_FAILED;
375 }
376 (void)WriteInt32(&request, 0);
377 owner.variable = &result;
378 owner.funcId = static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_GET_SCAN_INFO_LIST);
379 int error = remote_->Invoke(remote_, static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_GET_SCAN_INFO_LIST),
380 &request, &owner, IpcCallback);
381 if (error != EC_SUCCESS) {
382 WIFI_LOGW("Set Attr(%{public}d) failed",
383 static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_GET_SCAN_INFO_LIST));
384 return WIFI_OPT_FAILED;
385 }
386
387 if (owner.exception) {
388 return WIFI_OPT_FAILED;
389 }
390 return ErrCode(owner.retCode);
391 }
392
RegisterCallBack(const std::shared_ptr<IWifiScanCallback> & callback,const std::vector<std::string> & event)393 ErrCode WifiScanProxy::RegisterCallBack(const std::shared_ptr<IWifiScanCallback> &callback,
394 const std::vector<std::string> &event)
395 {
396 if (remoteDied_ || remote_ == nullptr) {
397 WIFI_LOGE("failed to %{public}s, remoteDied_: %{public}d, remote_: %{public}d",
398 __func__, remoteDied_, remote_ == nullptr);
399 return WIFI_OPT_FAILED;
400 }
401 WIFI_LOGD("RegisterCallBack start!");
402 g_objStub.func = AsyncCallback;
403 g_objStub.args = nullptr;
404 g_objStub.isRemote = false;
405
406 g_sid.handle = IPC_INVALID_HANDLE;
407 g_sid.token = SERVICE_TYPE_ANONYMOUS;
408 g_sid.cookie = (uintptr_t)&g_objStub;
409
410 IpcIo request;
411 char data[IPC_DATA_SIZE_SMALL];
412 struct IpcOwner owner = {.exception = -1, .retCode = 0, .variable = nullptr};
413
414 IpcIoInit(&request, data, IPC_DATA_SIZE_SMALL, MAX_IPC_OBJ_COUNT);
415 if (!WriteInterfaceToken(&request, DECLARE_INTERFACE_DESCRIPTOR_L1, DECLARE_INTERFACE_DESCRIPTOR_L1_LENGTH)) {
416 WIFI_LOGE("Write interface token error: %{public}s", __func__);
417 return WIFI_OPT_FAILED;
418 }
419 (void)WriteInt32(&request, 0);
420 (void)WriteRemoteObject(&request, &g_sid);
421 int eventNum = event.size();
422 (void)WriteInt32(&request, eventNum);
423 if (eventNum > 0) {
424 for (auto &eventName : event) {
425 (void)WriteString(&request, eventName.c_str());
426 }
427 }
428 owner.funcId = static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_REGISTER_SCAN_CALLBACK);
429 int error = remote_->Invoke(remote_, static_cast<int32_t>(ScanInterfaceCode::WIFI_SVR_CMD_REGISTER_SCAN_CALLBACK),
430 &request, &owner, IpcCallback);
431 if (error != EC_SUCCESS) {
432 WIFI_LOGE("RegisterCallBack failed, error code is %{public}d", error);
433 return WIFI_OPT_FAILED;
434 }
435 WIFI_LOGD("RegisterCallBack is finished: result=%{public}d", owner.exception);
436 if (owner.exception) {
437 return WIFI_OPT_FAILED;
438 }
439 g_wifiScanCallbackStub.RegisterCallBack(callback);
440 return WIFI_OPT_SUCCESS;
441 }
442
GetSupportedFeatures(long & features)443 ErrCode WifiScanProxy::GetSupportedFeatures(long &features)
444 {
445 if (remoteDied_ || remote_ == nullptr) {
446 WIFI_LOGE("failed to %{public}s, remoteDied_: %{public}d, remote_: %{public}d",
447 __func__, remoteDied_, remote_ == nullptr);
448 return WIFI_OPT_FAILED;
449 }
450
451 IpcIo request;
452 char data[IPC_DATA_SIZE_SMALL];
453 struct IpcOwner owner = {.exception = -1, .retCode = 0, .variable = nullptr};
454
455 IpcIoInit(&request, data, IPC_DATA_SIZE_SMALL, MAX_IPC_OBJ_COUNT);
456 if (!WriteInterfaceToken(&request, DECLARE_INTERFACE_DESCRIPTOR_L1, DECLARE_INTERFACE_DESCRIPTOR_L1_LENGTH)) {
457 WIFI_LOGE("Write interface token error: %{public}s", __func__);
458 return WIFI_OPT_FAILED;
459 }
460 (void)WriteInt32(&request, 0);
461 owner.variable = &features;
462 owner.funcId = static_cast<int32_t>(DevInterfaceCode::WIFI_SVR_CMD_GET_SUPPORTED_FEATURES);
463 int error = remote_->Invoke(remote_, static_cast<int32_t>(DevInterfaceCode::WIFI_SVR_CMD_GET_SUPPORTED_FEATURES),
464 &request, &owner, IpcCallback);
465 if (error != EC_SUCCESS) {
466 WIFI_LOGE("Set Attr(%{public}d) failed,error code is %{public}d",
467 static_cast<int32_t>(DevInterfaceCode::WIFI_SVR_CMD_GET_SUPPORTED_FEATURES), error);
468 return ErrCode(error);
469 }
470
471 if (owner.exception) {
472 return WIFI_OPT_FAILED;
473 }
474 return ErrCode(owner.retCode);
475 }
476
OnRemoteDied(void)477 void WifiScanProxy::OnRemoteDied(void)
478 {
479 WIFI_LOGW("Remote service is died!");
480 remoteDied_ = true;
481 g_wifiScanCallbackStub.SetRemoteDied(true);
482 }
483 } // namespace Wifi
484 } // namespace OHOS
485