• 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 <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