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