1 /*
2 * Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development 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 "nfc_napi_controller_event.h"
17 #include <uv.h>
18 #include "iservice_registry.h"
19 #include "loghelper.h"
20 #include "nfc_controller.h"
21 #include "nfc_sdk_common.h"
22 
23 namespace OHOS {
24 namespace NFC {
25 namespace KITS {
26 const std::string EVENT_NFC_STATE_CHANGE = "nfcStateChange";
27 
28 static std::set<std::string> g_supportEventList = {
29     EVENT_NFC_STATE_CHANGE,
30 };
31 
32 bool EventRegister::isEventRegistered = false;
33 
34 constexpr uint32_t INVALID_REF_COUNT = 0xFF;
35 
36 static std::shared_mutex g_regInfoMutex;
37 static std::map<std::string, std::vector<RegObj>> g_eventRegisterInfo;
38 
39 class NapiEvent {
40 public:
41     napi_value CreateResult(const napi_env& env, int value);
42     bool CheckIsRegister(const std::string& type);
43     void EventNotify(AsyncEventData *asyncEvent);
44 
45     template<typename T>
CheckAndNotify(const std::string & type,const T & obj)46     void CheckAndNotify(const std::string& type, const T& obj)
47     {
48         std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
49         if (!CheckIsRegister(type)) {
50             return;
51         }
52 
53         std::vector<RegObj>& vecObj = g_eventRegisterInfo[type];
54         for (const auto& each : vecObj) {
55             auto result = [this, env = each.m_regEnv, obj] () -> napi_value {
56                 return CreateResult(env, obj);
57             };
58             AsyncEventData *asyncEvent =
59                 new (std::nothrow)AsyncEventData(each.m_regEnv, each.m_regHanderRef, result);
60             if (asyncEvent == nullptr) {
61                 return;
62             }
63             EventNotify(asyncEvent);
64         }
65     }
66 };
67 
after_work_cb(uv_work_t * work,int status)68 static void after_work_cb(uv_work_t *work, int status)
69 {
70     AsyncEventData *asyncData = static_cast<AsyncEventData *>(work->data);
71     InfoLog("Napi event uv_queue_work, env: %{private}p, status: %{public}d", asyncData->env, status);
72 
73     napi_handle_scope scope = nullptr;
74     uint32_t refCount = INVALID_REF_COUNT;
75     napi_open_handle_scope(asyncData->env, &scope);
76     napi_value handler = nullptr;
77     napi_value jsEvent = nullptr;
78     if (scope == nullptr) {
79         ErrorLog("scope is nullptr");
80         goto EXIT;
81     }
82 
83     napi_get_reference_value(asyncData->env, asyncData->callbackRef, &handler);
84     if (handler == nullptr) {
85         ErrorLog("handler is nullptr");
86         goto EXIT;
87     }
88     napi_value undefine;
89     napi_get_undefined(asyncData->env, &undefine);
90     jsEvent = asyncData->packResult();
91     if (napi_call_function(asyncData->env, nullptr, handler, 1, &jsEvent, &undefine) != napi_ok) {
92         DebugLog("Report event to Js failed");
93     }
94 
95 EXIT:
96     napi_close_handle_scope(asyncData->env, scope);
97     napi_reference_unref(asyncData->env, asyncData->callbackRef, &refCount);
98     InfoLog("after_work_cb unref, env: %{private}p, callbackRef: %{private}p, refCount: %{public}d",
99         asyncData->env, asyncData->callbackRef, refCount);
100     if (refCount == 0) {
101         napi_delete_reference(asyncData->env, asyncData->callbackRef);
102     }
103     delete asyncData;
104     delete work;
105     asyncData = nullptr;
106     work = nullptr;
107 }
108 
EventNotify(AsyncEventData * asyncEvent)109 void NapiEvent::EventNotify(AsyncEventData *asyncEvent)
110 {
111     DebugLog("Enter nfc event notify");
112     if (asyncEvent == nullptr) {
113         DebugLog("asyncEvent is null.");
114         return;
115     }
116     uv_loop_s* loop = nullptr;
117     napi_get_uv_event_loop(asyncEvent->env, &loop);
118 
119     uv_work_t* work = new uv_work_t;
120     if (work == nullptr) {
121         DebugLog("uv_work_t work is null.");
122         delete asyncEvent;
123         asyncEvent = nullptr;
124         return;
125     }
126 
127     uint32_t refCount = INVALID_REF_COUNT;
128     napi_reference_ref(asyncEvent->env, asyncEvent->callbackRef, &refCount);
129     work->data = asyncEvent;
130     uv_after_work_cb tmp_after_work_cb = after_work_cb;
131     int ret = uv_queue_work(
132         loop,
133         work,
134         [](uv_work_t* work) {},
135         tmp_after_work_cb);
136     if (ret != 0) {
137         ErrorLog("uv_queue_work failed.");
138         delete asyncEvent;
139         delete work;
140     }
141 }
142 
CreateResult(const napi_env & env,int value)143 napi_value NapiEvent::CreateResult(const napi_env& env, int value)
144 {
145     napi_value result;
146     napi_create_int32(env, value, &result);
147     return result;
148 }
149 
CheckIsRegister(const std::string & type)150 bool NapiEvent::CheckIsRegister(const std::string& type)
151 {
152     return g_eventRegisterInfo.find(type) != g_eventRegisterInfo.end();
153 }
154 
155 class NfcStateListenerEvent : public INfcControllerCallback, public NapiEvent {
156 public:
NfcStateListenerEvent()157     NfcStateListenerEvent() {
158     }
159 
~NfcStateListenerEvent()160     virtual ~NfcStateListenerEvent() {
161     }
162 
163 public:
OnNfcStateChanged(int nfcState)164     void OnNfcStateChanged(int nfcState) override
165     {
166         InfoLog("OnNotify rcvd nfcRfState: %{public}d", nfcState);
167         CheckAndNotify(EVENT_NFC_STATE_CHANGE, nfcState);
168     }
169 
AsObject()170     OHOS::sptr<OHOS::IRemoteObject> AsObject() override
171     {
172         return nullptr;
173     }
174 };
175 
176 sptr<NfcStateListenerEvent> nfcStateListenerEvent =
177     sptr<NfcStateListenerEvent>(new (std::nothrow) NfcStateListenerEvent());
178 
On(napi_env env,napi_callback_info cbinfo)179 napi_value On(napi_env env, napi_callback_info cbinfo)
180 {
181     size_t requireArgc = 2;
182     size_t argc = 2;
183     napi_value argv[2] = {0};
184     napi_value thisVar = 0;
185     napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
186     NAPI_ASSERT(env, argc >= requireArgc, "requires 2 parameter");
187 
188     napi_valuetype eventName = napi_undefined;
189     napi_typeof(env, argv[0], &eventName);
190     NAPI_ASSERT(env, eventName == napi_string, "type mismatch for parameter 1");
191 
192     napi_valuetype handler = napi_undefined;
193     napi_typeof(env, argv[1], &handler);
194     NAPI_ASSERT(env, handler == napi_function, "type mismatch for parameter 2");
195 
196     char type[64] = {0};
197     size_t typeLen = 0;
198     napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &typeLen);
199     EventRegister::GetInstance().Register(env, type, argv[1]);
200     napi_value result = nullptr;
201     napi_get_undefined(env, &result);
202     return result;
203 }
204 
205 
Off(napi_env env,napi_callback_info cbinfo)206 napi_value Off(napi_env env, napi_callback_info cbinfo)
207 {
208     size_t requireArgc = 1;
209     size_t requireArgcWithCb = 2;
210     size_t argc = 2;
211     napi_value argv[2] = {0};
212     napi_value thisVar = 0;
213     napi_get_cb_info(env, cbinfo, &argc, argv, &thisVar, nullptr);
214     NAPI_ASSERT(env, argc >= requireArgc, "requires at least 1 parameter");
215 
216     napi_valuetype eventName = napi_undefined;
217     napi_typeof(env, argv[0], &eventName);
218     NAPI_ASSERT(env, eventName == napi_string, "type mismatch for parameter 1");
219 
220     if (argc >= requireArgcWithCb) {
221         napi_valuetype handler = napi_undefined;
222         napi_typeof(env, argv[1], &handler);
223         if (handler == napi_null || handler == napi_undefined) {
224             argc -= 1;
225             DebugLog("argv[1] is null or undefined, handle as no argv[1] input");
226         } else {
227             NAPI_ASSERT(env, handler == napi_function, "type mismatch for parameter 2");
228         }
229     }
230 
231     char type[64] = {0};
232     size_t typeLen = 0;
233     napi_get_value_string_utf8(env, argv[0], type, sizeof(type), &typeLen);
234     EventRegister::GetInstance().Unregister(env, type, argc >= requireArgcWithCb ? argv[1] : nullptr);
235     napi_value result = nullptr;
236     napi_get_undefined(env, &result);
237     return result;
238 }
239 
RegisterNfcStateChangedEvents(const std::string & type)240 ErrorCode EventRegister::RegisterNfcStateChangedEvents(const std::string& type)
241 {
242     NfcController nfcCtrl = NfcController::GetInstance();
243     ErrorCode ret = nfcCtrl.RegListener(nfcStateListenerEvent, type);
244     if (ret != KITS::ERR_NONE) {
245         ErrorLog("RegisterNfcStateChangedEvents nfcListenerEvent failed!");
246         return ret;
247     }
248     return ret;
249 }
250 
UnRegisterNfcEvents(const std::string & type)251 ErrorCode EventRegister::UnRegisterNfcEvents(const std::string& type)
252 {
253     NfcController nfcCtrl = OHOS::NFC::KITS::NfcController::GetInstance();
254     ErrorCode ret = nfcCtrl.UnregListener(type);
255     if (ret != KITS::ERR_NONE) {
256         ErrorLog("UnRegisterNfcEvents nfcListenerEvent failed!");
257         return ret;
258     }
259     return ret;
260 }
261 
GetInstance()262 EventRegister& EventRegister::GetInstance()
263 {
264     static EventRegister inst;
265     return inst;
266 }
267 
IsEventSupport(const std::string & type)268 bool EventRegister::IsEventSupport(const std::string& type)
269 {
270     return g_supportEventList.find(type) != g_supportEventList.end();
271 }
272 
Register(const napi_env & env,const std::string & type,napi_value handler)273 void EventRegister::Register(const napi_env& env, const std::string& type, napi_value handler)
274 {
275     InfoLog("Register event: %{public}s", type.c_str());
276     if (!IsEventSupport(type)) {
277         ErrorLog("Register type error or not support!");
278         return;
279     }
280     std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
281     RegisterNfcStateChangedEvents(type);
282     if (isEventRegistered) {
283         InfoLog("event %{public}s already registered.", type.c_str());
284         return;
285     }
286     napi_ref handlerRef = nullptr;
287     napi_create_reference(env, handler, 1, &handlerRef);
288     RegObj regObj(env, handlerRef);
289     auto iter = g_eventRegisterInfo.find(type);
290     if (iter == g_eventRegisterInfo.end()) {
291         g_eventRegisterInfo[type] = std::vector<RegObj> {regObj};
292         isEventRegistered = true;
293         InfoLog("Register, add new type.");
294         return;
295     }
296     auto miter = iter->second.begin();
297     for (; miter != iter->second.end();) {
298         if (env == miter->m_regEnv) {
299             napi_value handlerTemp = nullptr;
300             napi_get_reference_value(miter->m_regEnv, miter->m_regHanderRef, &handlerTemp);
301             bool isEqual = false;
302             napi_strict_equals(miter->m_regEnv, handlerTemp, handler, &isEqual);
303             if (isEqual) {
304                 WarnLog("handler function is same");
305                 ++miter;
306             } else {
307                 iter->second.emplace_back(regObj);
308                 break;
309             }
310         } else {
311             iter->second.emplace_back(regObj);
312             break;
313         }
314     }
315 }
316 
DeleteRegisterObj(const napi_env & env,std::vector<RegObj> & vecRegObjs,napi_value & handler)317 void EventRegister::DeleteRegisterObj(const napi_env& env, std::vector<RegObj>& vecRegObjs, napi_value& handler)
318 {
319     auto iter = vecRegObjs.begin();
320     for (; iter != vecRegObjs.end();) {
321         if (env == iter->m_regEnv) {
322             napi_value handlerTemp = nullptr;
323             napi_get_reference_value(iter->m_regEnv, iter->m_regHanderRef, &handlerTemp);
324             bool isEqual = false;
325             if (handlerTemp == nullptr) {
326                 DebugLog("handlerTemp is null");
327             }
328             if (handler == nullptr) {
329                 DebugLog("handler is null");
330             }
331             napi_strict_equals(iter->m_regEnv, handlerTemp, handler, &isEqual);
332             DebugLog("Delete register isEqual = %{public}d", isEqual);
333             if (isEqual) {
334                 uint32_t refCount = INVALID_REF_COUNT;
335                 napi_reference_unref(iter->m_regEnv, iter->m_regHanderRef, &refCount);
336                 InfoLog("delete ref, m_regEnv: %{private}p, m_regHanderRef: %{private}p, refCount: %{public}d",
337                     iter->m_regEnv, iter->m_regHanderRef, refCount);
338                 if (refCount == 0) {
339                     napi_delete_reference(iter->m_regEnv, iter->m_regHanderRef);
340                 }
341                 DebugLog("Delete register object ref.");
342                 iter = vecRegObjs.erase(iter);
343             } else {
344                 ++iter;
345             }
346         } else {
347             DebugLog("Unregister event, env is not equal %{private}p, : %{private}p", env, iter->m_regEnv);
348             ++iter;
349         }
350     }
351 }
352 
DeleteAllRegisterObj(const napi_env & env,std::vector<RegObj> & vecRegObjs)353 void EventRegister::DeleteAllRegisterObj(const napi_env& env, std::vector<RegObj>& vecRegObjs)
354 {
355     auto iter = vecRegObjs.begin();
356     for (; iter != vecRegObjs.end();) {
357         if (env == iter->m_regEnv) {
358             uint32_t refCount = INVALID_REF_COUNT;
359             napi_reference_unref(iter->m_regEnv, iter->m_regHanderRef, &refCount);
360             InfoLog("delete all ref, m_regEnv: %{private}p, m_regHanderRef: %{private}p, refCount: %{public}d",
361                 iter->m_regEnv, iter->m_regHanderRef, refCount);
362             if (refCount == 0) {
363                 napi_delete_reference(iter->m_regEnv, iter->m_regHanderRef);
364             }
365             iter = vecRegObjs.erase(iter);
366         } else {
367             DebugLog("Unregister all event, env is not equal %{private}p, : %{private}p", env, iter->m_regEnv);
368             ++iter;
369         }
370     }
371 }
372 
Unregister(const napi_env & env,const std::string & type,napi_value handler)373 void EventRegister::Unregister(const napi_env& env, const std::string& type, napi_value handler)
374 {
375     InfoLog("Unregister event: %{public}s", type.c_str());
376     if (!IsEventSupport(type)) {
377         ErrorLog("Unregister type error or not support!");
378         return;
379     }
380     std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
381     auto iter = g_eventRegisterInfo.find(type);
382     if (iter == g_eventRegisterInfo.end()) {
383         WarnLog("Unregister type not registered!");
384         if (UnRegisterNfcEvents(type) != KITS::ERR_NONE) {
385             ErrorLog("UnRegisterNfcEvents failed.");
386         }
387         return;
388     }
389     if (handler != nullptr) {
390         DeleteRegisterObj(env, iter->second, handler);
391     } else {
392         InfoLog("All callback is unsubscribe for event: %{public}s", type.c_str());
393         DeleteAllRegisterObj(env, iter->second);
394     }
395     if (iter->second.empty()) {
396         g_eventRegisterInfo.erase(iter);
397         if (UnRegisterNfcEvents(type) != KITS::ERR_NONE) {
398             ErrorLog("UnRegisterNfcEvents failed.");
399         }
400         isEventRegistered = false;
401     }
402 }
403 
OnAddSystemAbility(int32_t systemAbilityId,const std::string & deviceId)404 void NfcNapiAbilityStatusChange::OnAddSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
405 {
406     std::unique_lock<std::shared_mutex> guard(g_regInfoMutex);
407     if (g_eventRegisterInfo.find(EVENT_NFC_STATE_CHANGE) != g_eventRegisterInfo.end()) {
408         InfoLog("%{public}s g_eventRegisterInfo is not null, systemAbilityId = %{public}d", __func__, systemAbilityId);
409         EventRegister::GetInstance().RegisterNfcStateChangedEvents(EVENT_NFC_STATE_CHANGE);
410     } else {
411         WarnLog("%{public}s g_eventRegisterInfo is null", __func__);
412     }
413 }
414 
OnRemoveSystemAbility(int32_t systemAbilityId,const std::string & deviceId)415 void NfcNapiAbilityStatusChange::OnRemoveSystemAbility(int32_t systemAbilityId, const std::string& deviceId)
416 {
417     InfoLog("%{public}s, systemAbilityId = %{public}d", __func__, systemAbilityId);
418 }
419 
Init(int32_t systemAbilityId)420 void NfcNapiAbilityStatusChange::Init(int32_t systemAbilityId)
421 {
422     sptr<ISystemAbilityManager> samgrProxy = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager();
423     int32_t ret = samgrProxy->SubscribeSystemAbility(systemAbilityId, this);
424     InfoLog("SubscribeSystemAbility, systemAbilityId = %{public}d, ret = %{public}d", systemAbilityId, ret);
425 }
426 }  // namespace KITS
427 }  // namespace NFC
428 }  // namespace OHOS
429