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