1 /*
2 * Copyright (C) 2021-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_napi_event.h"
17 #include <uv.h>
18 #include "accesstoken_kit.h"
19 #include "ipc_skeleton.h"
20 #include "wifi_device.h"
21 #include "wifi_logger.h"
22 #include "wifi_napi_utils.h"
23 #include "wifi_scan.h"
24 #include "wifi_napi_errcode.h"
25
26 namespace OHOS {
27 namespace Wifi {
28 DEFINE_WIFILOG_LABEL("WifiNAPIEvent");
29 constexpr uint32_t INVALID_REF_COUNT = 0xff;
30 std::shared_ptr<WifiDevice> g_wifiStaPtr = WifiDevice::GetInstance(WIFI_DEVICE_ABILITY_ID);
31 std::shared_ptr<WifiScan> g_wifiScanPtr = WifiScan::GetInstance(WIFI_SCAN_ABILITY_ID);
32 std::shared_ptr<WifiHotspot> g_wifiHotspotPtr = WifiHotspot::GetInstance(WIFI_HOTSPOT_ABILITY_ID);
33 std::shared_ptr<WifiP2p> g_wifiP2pPtr = WifiP2p::GetInstance(WIFI_P2P_ABILITY_ID);
34
35 static std::set<std::string> g_supportEventList = {
36 EVENT_STA_POWER_STATE_CHANGE,
37 EVENT_STA_CONN_STATE_CHANGE,
38 EVENT_STA_SCAN_STATE_CHANGE,
39 EVENT_STA_RSSI_STATE_CHANGE,
40 EVENT_STA_DEVICE_CONFIG_CHANGE,
41 EVENT_STREAM_CHANGE,
42 EVENT_HOTSPOT_STATE_CHANGE,
43 EVENT_HOTSPOT_STA_JOIN,
44 EVENT_HOTSPOT_STA_LEAVE,
45 EVENT_P2P_STATE_CHANGE,
46 EVENT_P2P_CONN_STATE_CHANGE,
47 EVENT_P2P_DEVICE_STATE_CHANGE,
48 EVENT_P2P_PERSISTENT_GROUP_CHANGE,
49 EVENT_P2P_PEER_DEVICE_CHANGE,
50 EVENT_P2P_DISCOVERY_CHANGE,
51 };
52
53 std::map<std::string, std::int32_t> g_EventSysCapMap = {
54 { EVENT_STA_POWER_STATE_CHANGE, SYSCAP_WIFI_STA },
55 { EVENT_STA_CONN_STATE_CHANGE, SYSCAP_WIFI_STA },
56 { EVENT_STA_SCAN_STATE_CHANGE, SYSCAP_WIFI_STA },
57 { EVENT_STA_RSSI_STATE_CHANGE, SYSCAP_WIFI_STA },
58 { EVENT_STA_DEVICE_CONFIG_CHANGE, SYSCAP_WIFI_STA },
59 { EVENT_STREAM_CHANGE, SYSCAP_WIFI_STA },
60 { EVENT_HOTSPOT_STATE_CHANGE, SYSCAP_WIFI_AP_CORE },
61 { EVENT_HOTSPOT_STA_JOIN, SYSCAP_WIFI_AP_CORE },
62 { EVENT_HOTSPOT_STA_LEAVE, SYSCAP_WIFI_AP_CORE },
63 { EVENT_P2P_STATE_CHANGE, SYSCAP_WIFI_P2P },
64 { EVENT_P2P_CONN_STATE_CHANGE, SYSCAP_WIFI_P2P },
65 { EVENT_P2P_DEVICE_STATE_CHANGE, SYSCAP_WIFI_P2P },
66 { EVENT_P2P_PERSISTENT_GROUP_CHANGE, SYSCAP_WIFI_P2P },
67 { EVENT_P2P_PEER_DEVICE_CHANGE, SYSCAP_WIFI_P2P },
68 { EVENT_P2P_DISCOVERY_CHANGE, SYSCAP_WIFI_P2P },
69 };
70
EventNotify(AsyncEventData * asyncEvent)71 void NapiEvent::EventNotify(AsyncEventData *asyncEvent)
72 {
73 if (asyncEvent == nullptr) {
74 WIFI_LOGE("asyncEvent is null!");
75 return;
76 }
77 WIFI_LOGD("Enter wifi event notify, eventType: %{public}s", asyncEvent->eventType.c_str());
78
79 auto task = [asyncEvent]() {
80 napi_value handler = nullptr;
81 napi_handle_scope scope = nullptr;
82 napi_value jsEvent = nullptr;
83 uint32_t refCount = INVALID_REF_COUNT;
84 napi_status res;
85 bool unrefRef = false;
86 {
87 bool find = false;
88 std::shared_lock<std::shared_mutex> guard(g_regInfoMutex);
89 auto it = g_eventRegisterInfo.find(asyncEvent->eventType);
90 napi_open_handle_scope(asyncEvent->env, &scope);
91 if (scope == nullptr) {
92 WIFI_LOGE("napi_send_event, scope is nullptr");
93 goto EXIT;
94 }
95 if (it == g_eventRegisterInfo.end()) {
96 WIFI_LOGW("napi_send_event, event has been unregistered.");
97 goto EXIT;
98 }
99 for (auto& each : it->second) {
100 if (each.m_regEnv == asyncEvent->env && each.m_regHanderRef == asyncEvent->callbackRef) {
101 find = true;
102 break;
103 }
104 }
105 if (find == false) {
106 WIFI_LOGW("napi_send_event, NOT find the event.");
107 goto EXIT;
108 }
109 }
110 res = napi_reference_ref(asyncEvent->env, asyncEvent->callbackRef, &refCount);
111 WIFI_LOGI("napi_send_event, res: %{public}d, callbackRef: %{private}p, refCount: %{public}d",
112 res, asyncEvent->callbackRef, refCount);
113 if (res != napi_ok || refCount <= 1) {
114 WIFI_LOGE("napi_send_event, do NOT call back, res: %{public}d!", res);
115 goto EXIT;
116 }
117 unrefRef = true;
118 res = napi_get_reference_value(asyncEvent->env, asyncEvent->callbackRef, &handler);
119 if (res != napi_ok || handler == nullptr) {
120 WIFI_LOGE("napi_send_event, handler is nullptr or res: %{public}d!", res);
121 goto EXIT;
122 }
123 napi_value undefine;
124 napi_get_undefined(asyncEvent->env, &undefine);
125 jsEvent = asyncEvent->packResult();
126 if (napi_call_function(asyncEvent->env, nullptr, handler, 1, &jsEvent, &undefine) != napi_ok) {
127 WIFI_LOGE("napi_send_event, Report event to Js failed");
128 }
129
130 EXIT:
131 napi_close_handle_scope(asyncEvent->env, scope);
132 if (unrefRef) {
133 res = napi_reference_unref(asyncEvent->env, asyncEvent->callbackRef, &refCount);
134 WIFI_LOGD("napi_send_event, unref, res: %{public}d, refCount: %{public}d", res, refCount);
135 }
136 delete asyncEvent;
137 };
138 if (napi_status::napi_ok != napi_send_event(asyncEvent->env, task, napi_eprio_immediate)) {
139 WIFI_LOGE("napi_send_event: Failed to SendEvent");
140 delete asyncEvent;
141 } else {
142 WIFI_LOGD("napi_send_event: Successed to SendEvent");
143 }
144 }
145
CreateResult(const napi_env & env,int value)146 napi_value NapiEvent::CreateResult(const napi_env& env, int value)
147 {
148 napi_value result;
149 napi_create_int32(env, value, &result);
150 return result;
151 }
152
CreateResult(const napi_env & env,const StationInfo & info)153 napi_value NapiEvent::CreateResult(const napi_env& env, const StationInfo& info)
154 {
155 napi_value result;
156 napi_create_object(env, &result);
157 SetValueUtf8String(env, "name", info.deviceName, result);
158 SetValueUtf8String(env, "macAddress", info.bssid, result);
159 SetValueInt32(env, "macAddressType", info.bssidType, result);
160 SetValueUtf8String(env, "ipAddress", info.ipAddr, result);
161 return result;
162 }
163
CreateResult(const napi_env & env,const WifiP2pDevice & device)164 napi_value NapiEvent::CreateResult(const napi_env& env, const WifiP2pDevice& device)
165 {
166 napi_value result;
167 napi_create_object(env, &result);
168 SetValueUtf8String(env, "deviceName", device.GetDeviceName(), result);
169 SetValueUtf8String(env, "deviceAddress", device.GetDeviceAddress(), result);
170 SetValueInt32(env, "deviceAddressType", device.GetDeviceAddressType(), result);
171 SetValueUtf8String(env, "primaryDeviceType", device.GetPrimaryDeviceType(), result);
172 SetValueInt32(env, "deviceStatus", static_cast<int>(device.GetP2pDeviceStatus()), result);
173 SetValueInt32(env, "groupCapabilities", device.GetGroupCapabilitys(), result);
174 return result;
175 }
176
CreateResult(const napi_env & env,const std::vector<WifiP2pDevice> & devices)177 napi_value NapiEvent::CreateResult(const napi_env& env, const std::vector<WifiP2pDevice>& devices)
178 {
179 uint32_t idx = 0;
180 napi_value arrayResult;
181 napi_create_array_with_length(env, devices.size(), &arrayResult);
182 for (auto& each : devices) {
183 if (napi_set_element(env, arrayResult, idx++, CreateResult(env, each)) != napi_ok) {
184 WIFI_LOGE("Array result set element error, idx: %{public}u", idx - 1);
185 }
186 }
187 return arrayResult;
188 }
189
CreateResult(const napi_env & env,const WifiP2pLinkedInfo & info)190 napi_value NapiEvent::CreateResult(const napi_env& env, const WifiP2pLinkedInfo& info)
191 {
192 napi_value result;
193 napi_create_object(env, &result);
194 SetValueInt32(env, "connectState", static_cast<int>(info.GetConnectState()), result);
195 SetValueBool(env, "isGroupOwner", info.IsGroupOwner(), result);
196 SetValueUtf8String(env, "groupOwnerAddr", info.GetGroupOwnerAddress(), result);
197 return result;
198 }
199
CreateResult(const napi_env & env,napi_value placehoders)200 napi_value NapiEvent::NapiEvent::CreateResult(const napi_env& env, napi_value placehoders)
201 {
202 return placehoders == nullptr ? UndefinedNapiValue(env) : placehoders;
203 }
204
205 class WifiNapiDeviceEventCallback : public IWifiDeviceCallBack, public NapiEvent {
206 public:
WifiNapiDeviceEventCallback()207 WifiNapiDeviceEventCallback() {
208 }
209
~WifiNapiDeviceEventCallback()210 virtual ~WifiNapiDeviceEventCallback() {
211 }
212
213 public:
OnWifiStateChanged(int state)214 void OnWifiStateChanged(int state) override {
215 WIFI_LOGI("OnWifiStateChanged event: %{public}d [0:DISABLING, 1:DISABLED, 2:ENABLING, 3:ENABLED]",
216 state);
217 if (m_wifiStateConvertMap.find(state) == m_wifiStateConvertMap.end()) {
218 WIFI_LOGW("not find state.");
219 return;
220 }
221 CheckAndNotify(EVENT_STA_POWER_STATE_CHANGE, m_wifiStateConvertMap[state]);
222 }
223
OnWifiConnectionChanged(int state,const WifiLinkedInfo & info)224 void OnWifiConnectionChanged(int state, const WifiLinkedInfo &info) override {
225 WIFI_LOGI("OnWifiConnectionChanged event: %{public}d [4:CONNECTED, 6:DISCONNECTED, 7:SPECIAL_CONNECT]", state);
226 if (m_connectStateConvertMap.find(state) == m_connectStateConvertMap.end()) {
227 WIFI_LOGW("not find connect state.");
228 return;
229 }
230 CheckAndNotify(EVENT_STA_CONN_STATE_CHANGE, m_connectStateConvertMap[state]);
231 }
232
OnWifiRssiChanged(int rssi)233 void OnWifiRssiChanged(int rssi) override {
234 WIFI_LOGI("OnWifiRssiChanged event: %{public}d", rssi);
235 CheckAndNotify(EVENT_STA_RSSI_STATE_CHANGE, rssi);
236 }
237
OnWifiWpsStateChanged(int state,const std::string & pinCode)238 void OnWifiWpsStateChanged(int state, const std::string &pinCode) override {
239 }
240
OnStreamChanged(int direction)241 void OnStreamChanged(int direction) override
242 {
243 WIFI_LOGD("OnStreamChanged event: %{public}d [0:DATA_NONE, 1:DATA_IN, 2:DATA_OUT, 3:DATA_INOUT]",
244 direction);
245 if (m_streamDirectionConvertMap.find(direction) == m_streamDirectionConvertMap.end()) {
246 WIFI_LOGW("not find stream state.");
247 return;
248 }
249 CheckAndNotify(EVENT_STREAM_CHANGE, m_streamDirectionConvertMap[direction]);
250 }
251
OnDeviceConfigChanged(ConfigChange value)252 void OnDeviceConfigChanged(ConfigChange value) override {
253 WIFI_LOGI("OnDeviceConfigChanged event: %{public}d", static_cast<int>(value));
254 CheckAndNotify(EVENT_STA_DEVICE_CONFIG_CHANGE, static_cast<int>(value));
255 }
256
AsObject()257 OHOS::sptr<OHOS::IRemoteObject> AsObject() override {
258 return nullptr;
259 }
260
261 private:
262 enum class JsLayerWifiState {
263 DISABLED = 0,
264 ENABLED = 1,
265 ENABLING = 2,
266 DISABLING = 3
267 };
268
269 enum class JsLayerConnectStatus {
270 DISCONNECTED = 0,
271 CONNECTED = 1,
272 SPECIAL_CONNECT = 2,
273 };
274
275 enum class JsLayerStreamDirection {
276 STREAM_DIRECTION_NONE = 0,
277 STREAM_DIRECTION_DOWN = 1,
278 STREAM_DIRECTION_UP = 2,
279 STREAM_DIRECTION_UPDOWN = 3
280 };
281
282 std::map<int, int> m_wifiStateConvertMap = {
283 { static_cast<int>(WifiState::DISABLING), static_cast<int>(JsLayerWifiState::DISABLING) },
284 { static_cast<int>(WifiState::DISABLED), static_cast<int>(JsLayerWifiState::DISABLED) },
285 { static_cast<int>(WifiState::ENABLING), static_cast<int>(JsLayerWifiState::ENABLING) },
286 { static_cast<int>(WifiState::ENABLED), static_cast<int>(JsLayerWifiState::ENABLED) },
287 };
288
289 std::map<int, int> m_connectStateConvertMap = {
290 { static_cast<int>(ConnState::CONNECTED), static_cast<int>(JsLayerConnectStatus::CONNECTED) },
291 { static_cast<int>(ConnState::DISCONNECTED), static_cast<int>(JsLayerConnectStatus::DISCONNECTED) },
292 { static_cast<int>(ConnState::SPECIAL_CONNECT), static_cast<int>(JsLayerConnectStatus::SPECIAL_CONNECT) },
293 };
294
295 std::map<int, int> m_streamDirectionConvertMap = {
296 { static_cast<int>(StreamDirection::STREAM_DIRECTION_NONE),
297 static_cast<int>(JsLayerStreamDirection::STREAM_DIRECTION_NONE) },
298 { static_cast<int>(StreamDirection::STREAM_DIRECTION_DOWN),
299 static_cast<int>(JsLayerStreamDirection::STREAM_DIRECTION_DOWN) },
300 { static_cast<int>(StreamDirection::STREAM_DIRECTION_UP),
301 static_cast<int>(JsLayerStreamDirection::STREAM_DIRECTION_UP) },
302 { static_cast<int>(StreamDirection::STREAM_DIRECTION_UPDOWN),
303 static_cast<int>(JsLayerStreamDirection::STREAM_DIRECTION_UPDOWN) },
304 };
305 };
306
307 class WifiNapiScanEventCallback : public IWifiScanCallback, public NapiEvent {
308 public:
WifiNapiScanEventCallback()309 WifiNapiScanEventCallback() {
310 }
311
~WifiNapiScanEventCallback()312 virtual ~WifiNapiScanEventCallback() {
313 }
314
315 public:
OnWifiScanStateChanged(int state)316 void OnWifiScanStateChanged(int state) override {
317 WIFI_LOGI("scan received state changed event: %{public}d", state);
318 CheckAndNotify(EVENT_STA_SCAN_STATE_CHANGE, state);
319 }
320
AsObject()321 OHOS::sptr<OHOS::IRemoteObject> AsObject() override {
322 return nullptr;
323 }
324 };
325
326 class WifiNapiHotspotEventCallback : public IWifiHotspotCallback, public NapiEvent {
327 public:
WifiNapiHotspotEventCallback()328 WifiNapiHotspotEventCallback() {
329 }
330
~WifiNapiHotspotEventCallback()331 virtual ~WifiNapiHotspotEventCallback() {
332 }
333
334 public:
OnHotspotStateChanged(int state)335 void OnHotspotStateChanged(int state) override {
336 WIFI_LOGI("Hotspot received state changed event: %{public}d", state);
337 if (m_apStateConvertMap.find(state) == m_apStateConvertMap.end()) {
338 return;
339 }
340
341 CheckAndNotify(EVENT_HOTSPOT_STATE_CHANGE, m_apStateConvertMap[state]);
342 }
343
OnHotspotStaJoin(const StationInfo & info)344 void OnHotspotStaJoin(const StationInfo &info) override {
345 WIFI_LOGI("Hotspot received sta join event");
346 CheckAndNotify(EVENT_HOTSPOT_STA_JOIN, info);
347 }
348
OnHotspotStaLeave(const StationInfo & info)349 void OnHotspotStaLeave(const StationInfo &info) override {
350 WIFI_LOGI("Hotspot received sta leave event");
351 CheckAndNotify(EVENT_HOTSPOT_STA_LEAVE, info);
352 }
353
AsObject()354 OHOS::sptr<OHOS::IRemoteObject> AsObject() override {
355 return nullptr;
356 }
357
358 private:
359 enum class JsLayerApState {
360 DISABLED = 0,
361 ENABLED = 1,
362 ENABLING = 2,
363 DISABLING = 3
364 };
365
366 std::map<int, int> m_apStateConvertMap = {
367 { static_cast<int>(ApState::AP_STATE_STARTING), static_cast<int>(JsLayerApState::ENABLING) },
368 { static_cast<int>(ApState::AP_STATE_STARTED), static_cast<int>(JsLayerApState::ENABLED) },
369 { static_cast<int>(ApState::AP_STATE_CLOSING), static_cast<int>(JsLayerApState::DISABLING) },
370 { static_cast<int>(ApState::AP_STATE_CLOSED), static_cast<int>(JsLayerApState::DISABLED) },
371 };
372 };
373
374 class WifiNapiP2pEventCallback : public IWifiP2pCallback, public NapiEvent {
375 public:
WifiNapiP2pEventCallback()376 WifiNapiP2pEventCallback() {
377 }
378
~WifiNapiP2pEventCallback()379 virtual ~WifiNapiP2pEventCallback() {
380 }
381
382 public:
OnP2pStateChanged(int state)383 void OnP2pStateChanged(int state) override {
384 WIFI_LOGI("received p2p state changed event: %{public}d", state);
385 CheckAndNotify(EVENT_P2P_STATE_CHANGE, state);
386 }
387
OnP2pPersistentGroupsChanged(void)388 void OnP2pPersistentGroupsChanged(void) override {
389 WIFI_LOGI("received persistent group changed event");
390 CheckAndNotify(EVENT_P2P_PERSISTENT_GROUP_CHANGE, nullptr);
391 }
392
OnP2pThisDeviceChanged(const WifiP2pDevice & device)393 void OnP2pThisDeviceChanged(const WifiP2pDevice& device) override {
394 WIFI_LOGI("received this device changed event");
395 CheckAndNotify(EVENT_P2P_DEVICE_STATE_CHANGE, device);
396 }
397
OnP2pPeersChanged(const std::vector<WifiP2pDevice> & devices)398 void OnP2pPeersChanged(const std::vector<WifiP2pDevice>& devices) override {
399 WIFI_LOGI("received p2p peers changed event, devices count: %{public}d", static_cast<int>(devices.size()));
400 CheckAndNotify(EVENT_P2P_PEER_DEVICE_CHANGE, devices);
401 }
402
OnP2pServicesChanged(const std::vector<WifiP2pServiceInfo> & srvInfo)403 void OnP2pServicesChanged(const std::vector<WifiP2pServiceInfo>& srvInfo) override {
404 }
405
OnP2pConnectionChanged(const WifiP2pLinkedInfo & info)406 void OnP2pConnectionChanged(const WifiP2pLinkedInfo& info) override {
407 WIFI_LOGI("received p2p connection changed event, state: %{public}d",
408 static_cast<int>(info.GetConnectState()));
409 CheckAndNotify(EVENT_P2P_CONN_STATE_CHANGE, info);
410 }
411
OnP2pDiscoveryChanged(bool isChange)412 void OnP2pDiscoveryChanged(bool isChange) override {
413 WIFI_LOGI("received discovery state changed event");
414 CheckAndNotify(EVENT_P2P_DISCOVERY_CHANGE, (int)isChange);
415 }
416
OnP2pActionResult(P2pActionCallback action,ErrCode code)417 void OnP2pActionResult(P2pActionCallback action, ErrCode code) override {
418 }
419
OnConfigChanged(CfgType type,char * data,int dataLen)420 void OnConfigChanged(CfgType type, char* data, int dataLen) override {
421 }
422
OnP2pGcJoinGroup(const OHOS::Wifi::GcInfo & info)423 void OnP2pGcJoinGroup(const OHOS::Wifi::GcInfo &info) override
424 {
425 WIFI_LOGI("received OnP2pGcJoinGroup event");
426 }
427
OnP2pGcLeaveGroup(const OHOS::Wifi::GcInfo & info)428 void OnP2pGcLeaveGroup(const OHOS::Wifi::GcInfo &info) override
429 {
430 WIFI_LOGI("received OnP2pGcLeave event");
431 }
432
OnP2pPrivatePeersChanged(const std::string & priWfdInfo)433 void OnP2pPrivatePeersChanged(const std::string &priWfdInfo) override
434 {
435 WIFI_LOGI("received OnP2pPrivatePeersChanged event");
436 }
437
OnP2pChrErrCodeReport(const int errCode)438 void OnP2pChrErrCodeReport(const int errCode) override
439 {
440 WIFI_LOGI("received OnP2pChrErrCodeReport event");
441 }
442
AsObject()443 OHOS::sptr<OHOS::IRemoteObject> AsObject() override {
444 return nullptr;
445 }
446 };
447
On(napi_env env,napi_callback_info cbinfo)448 napi_value On(napi_env env, napi_callback_info cbinfo) {
449 TRACE_FUNC_CALL;
450 size_t requireArgc = 2;
451 size_t argc = 2;
452 napi_value argv[2] = {0};
453 napi_value thisVar = 0;
454 napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
455 if (requireArgc > argc) {
456 WIFI_LOGI("requireArgc:%{public}zu, argc:%{public}zu", requireArgc, argc);
457 WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
458 }
459
460 napi_valuetype eventName = napi_undefined;
461 napi_typeof(env, argv[0], &eventName);
462 if (eventName != napi_string) {
463 WIFI_LOGI("first argv != napi_string");
464 WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
465 }
466
467 napi_valuetype handler = napi_undefined;
468 napi_typeof(env, argv[1], &handler);
469 if (handler != napi_function) {
470 WIFI_LOGI("second argv != napi_function");
471 WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
472 }
473
474 char type[64] = {0};
475 size_t typeLen = 0;
476 napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &typeLen);
477 EventRegister::GetInstance().Register(env, type, argv[1]);
478 napi_value result = nullptr;
479 napi_get_undefined(env, &result);
480 return result;
481 }
482
Off(napi_env env,napi_callback_info cbinfo)483 napi_value Off(napi_env env, napi_callback_info cbinfo) {
484 TRACE_FUNC_CALL;
485 size_t requireArgc = 1;
486 size_t requireArgcWithCb = 2;
487 size_t argc = 2;
488 napi_value argv[2] = {0};
489 napi_value thisVar = 0;
490 napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
491 if (requireArgc > argc) {
492 WIFI_LOGI("requireArgc:%{public}zu, argc:%{public}zu", requireArgc, argc);
493 WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
494 }
495
496 napi_valuetype eventName = napi_undefined;
497 napi_typeof(env, argv[0], &eventName);
498 if (eventName != napi_string) {
499 WIFI_LOGI("first argv != napi_string");
500 WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
501 }
502
503 napi_valuetype handler = napi_undefined;
504 if (argc >= requireArgcWithCb) {
505 napi_typeof(env, argv[1], &handler);
506 if (handler != napi_function && handler != napi_null) {
507 WIFI_LOGI("second argv != napi_function");
508 WIFI_NAPI_RETURN(env, false, WIFI_OPT_INVALID_PARAM, 0);
509 }
510 }
511
512 char type[64] = {0};
513 size_t typeLen = 0;
514 napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &typeLen);
515 if (argc >= requireArgcWithCb && handler != napi_null) {
516 EventRegister::GetInstance().Unregister(env, type, argv[1]);
517 } else {
518 EventRegister::GetInstance().Unregister(env, type, nullptr);
519 }
520 napi_value result = nullptr;
521 napi_get_undefined(env, &result);
522 return result;
523 }
524
findSysCap(const std::string & type)525 static int32_t findSysCap(const std::string& type)
526 {
527 int32_t sysCap = SYSCAP_WIFI_STA;
528 auto iter = g_EventSysCapMap.find(type);
529 if (iter == g_EventSysCapMap.end()) {
530 WIFI_LOGI("findSysCap, type:%{public}s, DO NOT find sysCap.", type.c_str());
531 return sysCap;
532 }
533 sysCap = iter->second;
534 return sysCap;
535 }
536
537 sptr<WifiNapiDeviceEventCallback> wifiDeviceCallback =
538 sptr<WifiNapiDeviceEventCallback>(new (std::nothrow) WifiNapiDeviceEventCallback());
539
540 sptr<WifiNapiScanEventCallback> wifiScanCallback =
541 sptr<WifiNapiScanEventCallback>(new (std::nothrow) WifiNapiScanEventCallback());
542
543 sptr<WifiNapiHotspotEventCallback> wifiHotspotCallback =
544 sptr<WifiNapiHotspotEventCallback>(new (std::nothrow) WifiNapiHotspotEventCallback());
545
546 sptr<WifiNapiP2pEventCallback> wifiP2pCallback =
547 sptr<WifiNapiP2pEventCallback>(new (std::nothrow) WifiNapiP2pEventCallback());
548
RegisterDeviceEvents(const std::vector<std::string> & event)549 ErrCode EventRegister::RegisterDeviceEvents(const std::vector<std::string> &event)
550 {
551 if (event.empty()) {
552 WIFI_LOGE("Register sta event is empty!");
553 return WIFI_OPT_FAILED;
554 }
555 if (g_wifiStaPtr == nullptr) {
556 WIFI_LOGE("Register sta event get instance failed!");
557 return WIFI_OPT_FAILED;
558 }
559 ErrCode ret = g_wifiStaPtr->RegisterCallBack(wifiDeviceCallback, event);
560 if (ret != WIFI_OPT_SUCCESS) {
561 WIFI_LOGE("Register sta event failed!");
562 return ret;
563 }
564 return WIFI_OPT_SUCCESS;
565 }
566
RegisterScanEvents(const std::vector<std::string> & event)567 ErrCode EventRegister::RegisterScanEvents(const std::vector<std::string> &event)
568 {
569 if (event.empty()) {
570 WIFI_LOGE("Register scan event is empty!");
571 return WIFI_OPT_FAILED;
572 }
573 if (g_wifiScanPtr == nullptr) {
574 WIFI_LOGE("Register scan event get instance failed!");
575 return WIFI_OPT_FAILED;
576 }
577 ErrCode ret = g_wifiScanPtr->RegisterCallBack(wifiScanCallback, event);
578 if (ret != WIFI_OPT_SUCCESS) {
579 WIFI_LOGE("Register scan event failed!");
580 return ret;
581 }
582 return WIFI_OPT_SUCCESS;
583 }
584
RegisterHotspotEvents(const std::vector<std::string> & event)585 ErrCode EventRegister::RegisterHotspotEvents(const std::vector<std::string> &event)
586 {
587 if (event.empty()) {
588 WIFI_LOGE("Register hotspot event is empty!");
589 return WIFI_OPT_FAILED;
590 }
591 if (g_wifiHotspotPtr == nullptr) {
592 WIFI_LOGE("Register hotspot event get instance failed!");
593 return WIFI_OPT_FAILED;
594 }
595 ErrCode ret = g_wifiHotspotPtr->RegisterCallBack(wifiHotspotCallback, event);
596 if (ret != WIFI_OPT_SUCCESS) {
597 WIFI_LOGE("Register hotspot event failed!");
598 return ret;
599 }
600 return WIFI_OPT_SUCCESS;
601 }
602
RegisterP2PEvents(const std::vector<std::string> & event)603 ErrCode EventRegister::RegisterP2PEvents(const std::vector<std::string> &event)
604 {
605 if (event.empty()) {
606 WIFI_LOGE("Register p2p event is empty!");
607 return WIFI_OPT_FAILED;
608 }
609 if (g_wifiP2pPtr == nullptr) {
610 WIFI_LOGE("Register p2p event get instance failed!");
611 return WIFI_OPT_FAILED;
612 }
613 ErrCode ret = g_wifiP2pPtr->RegisterCallBack(wifiP2pCallback, event);
614 if (ret != WIFI_OPT_SUCCESS) {
615 WIFI_LOGE("Register p2p event failed!");
616 return ret;
617 }
618 return WIFI_OPT_SUCCESS;
619 }
620
RegisterWifiEvents(int32_t sysCap,const std::string & type)621 NO_SANITIZE("cfi") ErrCode EventRegister::RegisterWifiEvents(int32_t sysCap, const std::string& type)
622 {
623 std::vector<std::string> event = {type};
624 if (sysCap == SYSCAP_WIFI_STA) {
625 ErrCode ret = RegisterDeviceEvents(event);
626 if (ret != WIFI_OPT_SUCCESS) {
627 return ret;
628 }
629 return RegisterScanEvents(event);
630 }
631
632 if (sysCap == SYSCAP_WIFI_AP_CORE) {
633 return RegisterHotspotEvents(event);
634 }
635
636 if (sysCap == SYSCAP_WIFI_P2P) {
637 return RegisterP2PEvents(event);
638 }
639
640 WIFI_LOGE("RegisterWifiEvents, invalid sysCap: %{public}d!", static_cast<int>(sysCap));
641 return WIFI_OPT_FAILED;
642 }
643
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)644 void WifiNapiAbilityStatusChange::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
645 {
646 WIFI_LOGI("OnAddSystemAbility systemAbilityId:%{public}d", systemAbilityId);
647 std::vector<std::string> event;
648 switch (systemAbilityId) {
649 case WIFI_DEVICE_ABILITY_ID: {
650 std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
651 for (auto &iter : g_eventRegisterInfo) {
652 if (findSysCap(iter.first) == SYSCAP_WIFI_STA) {
653 event.emplace_back(iter.first);
654 }
655 }
656 EventRegister::GetInstance().RegisterDeviceEvents(event);
657 break;
658 }
659 case WIFI_SCAN_ABILITY_ID: {
660 std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
661 for (auto &iter : g_eventRegisterInfo) {
662 if (findSysCap(iter.first) == SYSCAP_WIFI_STA) {
663 event.emplace_back(iter.first);
664 }
665 }
666 EventRegister::GetInstance().RegisterScanEvents(event);
667 break;
668 }
669 case WIFI_HOTSPOT_ABILITY_ID: {
670 std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
671 for (auto &iter : g_eventRegisterInfo) {
672 if (findSysCap(iter.first) == SYSCAP_WIFI_AP_CORE) {
673 event.emplace_back(iter.first);
674 }
675 }
676 EventRegister::GetInstance().RegisterHotspotEvents(event);
677 break;
678 }
679 case WIFI_P2P_ABILITY_ID: {
680 std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
681 for (auto &iter : g_eventRegisterInfo) {
682 if (findSysCap(iter.first) == SYSCAP_WIFI_P2P) {
683 event.emplace_back(iter.first);
684 }
685 }
686 EventRegister::GetInstance().RegisterP2PEvents(event);
687 break;
688 }
689 default:
690 WIFI_LOGI("OnAddSystemAbility unhandled sysabilityId:%{public}d", systemAbilityId);
691 return;
692 }
693 }
694
GetInstance()695 EventRegister& EventRegister::GetInstance()
696 {
697 static EventRegister inst;
698 return inst;
699 }
700
IsEventSupport(const std::string & type)701 bool EventRegister::IsEventSupport(const std::string& type)
702 {
703 return g_supportEventList.find(type) != g_supportEventList.end();
704 }
705
Register(const napi_env & env,const std::string & type,napi_value handler)706 void EventRegister::Register(const napi_env& env, const std::string& type, napi_value handler)
707 {
708 int32_t sysCap = findSysCap(type);
709 WIFI_LOGI("Register event: %{public}s, env: %{private}p, %{public}d.",
710 type.c_str(), env, static_cast<int>(sysCap));
711 if (!IsEventSupport(type)) {
712 WIFI_LOGE("Register type error or not support!");
713 #ifdef ENABLE_NAPI_WIFI_MANAGER
714 HandleSyncErrCode(env, WIFI_OPT_NOT_SUPPORTED, sysCap);
715 #endif
716 return;
717 }
718 std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
719 ErrCode ret = RegisterWifiEvents(sysCap, type);
720 if (ret != WIFI_OPT_SUCCESS) {
721 #ifdef ENABLE_NAPI_WIFI_MANAGER
722 HandleSyncErrCode(env, ret, sysCap);
723 #endif
724 return;
725 }
726
727 napi_ref handlerRef = nullptr;
728 napi_create_reference(env, handler, 1, &handlerRef);
729 RegObj regObj(env, handlerRef);
730 auto iter = g_eventRegisterInfo.find(type);
731 if (iter == g_eventRegisterInfo.end()) {
732 if (g_eventRegisterInfo.size() > REGISTERINFO_MAX_NUM) {
733 WIFI_LOGE("RegisterInfo Exceeding the maximum value!");
734 return;
735 }
736 g_eventRegisterInfo[type] = std::vector<RegObj>{regObj};
737 } else {
738 iter->second.emplace_back(regObj);
739 }
740 }
741
DeleteRegisterObj(const napi_env & env,std::vector<RegObj> & vecRegObjs,napi_value & handler)742 void EventRegister::DeleteRegisterObj(const napi_env& env, std::vector<RegObj>& vecRegObjs, napi_value& handler)
743 {
744 auto iter = vecRegObjs.begin();
745 for (; iter != vecRegObjs.end();) {
746 if (env == iter->m_regEnv) {
747 napi_value handlerTemp = nullptr;
748 napi_get_reference_value(iter->m_regEnv, iter->m_regHanderRef, &handlerTemp);
749 bool isEqual = false;
750 napi_strict_equals(iter->m_regEnv, handlerTemp, handler, &isEqual);
751 if (isEqual) {
752 uint32_t refCount = INVALID_REF_COUNT;
753 napi_reference_unref(iter->m_regEnv, iter->m_regHanderRef, &refCount);
754 WIFI_LOGI("delete ref, m_regEnv: %{private}p, m_regHanderRef: %{private}p, refCount: %{public}d",
755 iter->m_regEnv, iter->m_regHanderRef, refCount);
756 if (refCount == 0) {
757 napi_delete_reference(iter->m_regEnv, iter->m_regHanderRef);
758 }
759 WIFI_LOGI("Delete register object ref.");
760 iter = vecRegObjs.erase(iter);
761 } else {
762 ++iter;
763 }
764 } else {
765 WIFI_LOGI("Unregister event, env is not equal %{private}p, : %{private}p", env, iter->m_regEnv);
766 ++iter;
767 }
768 }
769 }
770
DeleteAllRegisterObj(const napi_env & env,std::vector<RegObj> & vecRegObjs)771 void EventRegister::DeleteAllRegisterObj(const napi_env& env, std::vector<RegObj>& vecRegObjs)
772 {
773 auto iter = vecRegObjs.begin();
774 for (; iter != vecRegObjs.end();) {
775 if (env == iter->m_regEnv) {
776 uint32_t refCount = INVALID_REF_COUNT;
777 napi_reference_unref(iter->m_regEnv, iter->m_regHanderRef, &refCount);
778 WIFI_LOGI("delete all ref, m_regEnv: %{private}p, m_regHanderRef: %{private}p, refCount: %{public}d",
779 iter->m_regEnv, iter->m_regHanderRef, refCount);
780 if (refCount == 0) {
781 napi_delete_reference(iter->m_regEnv, iter->m_regHanderRef);
782 }
783 iter = vecRegObjs.erase(iter);
784 } else {
785 WIFI_LOGI("Unregister all event, env is not equal %{private}p, : %{private}p", env, iter->m_regEnv);
786 ++iter;
787 }
788 }
789 }
790
Unregister(const napi_env & env,const std::string & type,napi_value handler)791 void EventRegister::Unregister(const napi_env& env, const std::string& type, napi_value handler)
792 {
793 int32_t sysCap = findSysCap(type);
794 WIFI_LOGI("Unregister event: %{public}s, env: %{private}p, sysCap:%{public}d",
795 type.c_str(), env, (int)sysCap);
796 if (!IsEventSupport(type)) {
797 WIFI_LOGE("Unregister type error or not support!");
798 #ifdef ENABLE_NAPI_WIFI_MANAGER
799 HandleSyncErrCode(env, WIFI_OPT_NOT_SUPPORTED, sysCap);
800 #endif
801 return;
802 }
803 std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
804 auto iter = g_eventRegisterInfo.find(type);
805 if (iter == g_eventRegisterInfo.end()) {
806 WIFI_LOGE("Unregister type not registered!");
807 #ifdef ENABLE_NAPI_WIFI_MANAGER
808 HandleSyncErrCode(env, WIFI_OPT_INVALID_CONFIG, sysCap);
809 #endif
810 return;
811 }
812 if (handler != nullptr) {
813 DeleteRegisterObj(env, iter->second, handler);
814 } else {
815 WIFI_LOGW("Unregister all relevant subscribe for: %{public}s", type.c_str());
816 DeleteAllRegisterObj(env, iter->second);
817 }
818 if (iter->second.empty()) {
819 g_eventRegisterInfo.erase(iter);
820 }
821 }
822
CleanUp(void * data)823 void EventRegister::CleanUp(void *data)
824 {
825 std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
826 auto env = *(reinterpret_cast<napi_env*>(data));
827 for (auto &event : g_eventRegisterInfo) {
828 auto &vecRegObjs = event.second;
829 auto iter = vecRegObjs.begin();
830 for (; iter != vecRegObjs.end();) {
831 if (env == iter->m_regEnv) {
832 napi_delete_reference(iter->m_regEnv, iter->m_regHanderRef);
833 iter = vecRegObjs.erase(iter);
834 } else {
835 ++iter;
836 }
837 }
838 }
839 delete reinterpret_cast<napi_env*>(data);
840 data = nullptr;
841 }
842 } // namespace Wifi
843 } // namespace OHOS
844