• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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