• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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