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