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