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