1  /*
2   * Copyright (c) 2021-2024 Huawei Device 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 "subscribe.h"
17  #include "ans_inner_errors.h"
18  #include "inner_event.h"
19  #include <mutex>
20  #include <uv.h>
21  
22  namespace OHOS {
23  namespace NotificationNapi {
24  const int32_t SUBSRIBE_MAX_PARA = 3;
25  const int32_t NO_DELETE_REASON = -1;
26  
27  const std::string CONSUME = "onConsume";
28  const std::string CANCEL = "onCancel";
29  const std::string UPDATE = "onUpdate";
30  const std::string CONNECTED = "onConnect";
31  const std::string DIS_CONNECTED = "onDisconnect";
32  const std::string DIE = "onDestroy";
33  const std::string DISTURB_MODE_CHANGE = "onDisturbModeChange";
34  const std::string DISTURB_DATE_CHANGE = "onDoNotDisturbDateChange";
35  const std::string DISTURB_CHANGED = "onDoNotDisturbChanged";
36  const std::string ENABLE_NOTIFICATION_CHANGED = "OnEnabledNotificationChanged";
37  const std::string BADGE_CHANGED = "OnBadgeChanged";
38  const std::string BADGE_ENABLED_CHANGED = "OnBadgeEnabledChanged";
39  const std::string BATCH_CANCEL = "onBatchCancel";
40  
41  enum class Type {
42      UNKNOWN,
43      CANCEL,
44      BATCH_CANCEL,
45      CONSUME,
46      UPDATE,
47      CONNECTED,
48      DIS_CONNECTED,
49      DIE,
50      DISTURB_DATE_CHANGE,
51      DISTURB_CHANGED,
52      ENABLE_NOTIFICATION_CHANGED,
53      BADGE_CHANGED,
54      BADGE_ENABLED_CHANGED
55  };
56  
57  struct NotificationReceiveDataWorker {
58      napi_env env = nullptr;
59      napi_ref ref = nullptr;
60      std::shared_ptr<OHOS::Notification::Notification> request;
61      std::vector<std::shared_ptr<OHOS::Notification::Notification>> requestList;
62      std::shared_ptr<NotificationSortingMap> sortingMap;
63      NotificationDoNotDisturbDate date;
64      EnabledNotificationCallbackData callbackData;
65      BadgeNumberCallbackData badge;
66      int32_t deleteReason = 0;
67      int32_t result = 0;
68      int32_t disturbMode = 0;
69      std::shared_ptr<SubscriberInstance> subscriber = nullptr;
70      Type type;
71  };
72  
SetSubscribeCallbackData(const napi_env & env,const std::shared_ptr<OHOS::Notification::Notification> & request,const std::shared_ptr<NotificationSortingMap> & sortingMap,int32_t deleteReason,napi_value & result)73  napi_value SetSubscribeCallbackData(const napi_env &env,
74      const std::shared_ptr<OHOS::Notification::Notification> &request,
75      const std::shared_ptr<NotificationSortingMap> &sortingMap, int32_t deleteReason, napi_value &result)
76  {
77      ANS_LOGD("enter");
78      if (request == nullptr) {
79          ANS_LOGE("request is null");
80          return Common::NapiGetBoolean(env, false);
81      }
82  
83      if (sortingMap == nullptr) {
84          ANS_LOGE("sortingMap is null");
85          return Common::NapiGetBoolean(env, false);
86      }
87  
88      // request: NotificationRequest
89      napi_value requestResult = nullptr;
90      napi_create_object(env, &requestResult);
91      if (!Common::SetNotification(env, request.get(), requestResult)) {
92          ANS_LOGE("SetNotification call failed");
93          return Common::NapiGetBoolean(env, false);
94      }
95      napi_set_named_property(env, result, "request", requestResult);
96  
97      // sortingMap?: NotificationSortingMap
98      napi_value sortingMapResult = nullptr;
99      napi_create_object(env, &sortingMapResult);
100      if (!Common::SetNotificationSortingMap(env, sortingMap, sortingMapResult)) {
101          ANS_LOGE("SetNotificationSortingMap call failed");
102          return Common::NapiGetBoolean(env, false);
103      }
104      napi_set_named_property(env, result, "sortingMap", sortingMapResult);
105  
106      // reason?: number
107      if (deleteReason != NO_DELETE_REASON) {
108          napi_value value = nullptr;
109          int32_t outReason = 0;
110          if (!AnsEnumUtil::ReasonCToJS(deleteReason, outReason)) {
111              return Common::NapiGetBoolean(env, false);
112          }
113          napi_create_int32(env, outReason, &value);
114          napi_set_named_property(env, result, "reason", value);
115      }
116  
117      // sound?: string
118      napi_value soundResult = nullptr;
119      std::string sound;
120      if (request->EnableSound()) {
121          sound = request->GetSound().ToString();
122      }
123      napi_create_string_utf8(env, sound.c_str(), NAPI_AUTO_LENGTH, &soundResult);
124      napi_set_named_property(env, result, "sound", soundResult);
125  
126      // vibrationValues?: Array<number>
127      napi_value arr = nullptr;
128      napi_create_array(env, &arr);
129      if (request->EnableVibrate()) {
130          uint32_t count = 0;
131          for (auto vec : request->GetVibrationStyle()) {
132              napi_value nVibrationValue = nullptr;
133              napi_create_int64(env, vec, &nVibrationValue);
134              napi_set_element(env, arr, count, nVibrationValue);
135              count++;
136          }
137      }
138      napi_set_named_property(env, result, "vibrationValues", arr);
139  
140      return Common::NapiGetBoolean(env, true);
141  }
142  
SubscriberInstance()143  SubscriberInstance::SubscriberInstance()
144  {}
145  
~SubscriberInstance()146  SubscriberInstance::~SubscriberInstance()
147  {
148      if (tsfn_ != nullptr) {
149          napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
150      }
151      if (canceCallbackInfo_.ref != nullptr) {
152          napi_delete_reference(canceCallbackInfo_.env, canceCallbackInfo_.ref);
153      }
154      if (consumeCallbackInfo_.ref != nullptr) {
155          napi_delete_reference(consumeCallbackInfo_.env, consumeCallbackInfo_.ref);
156      }
157      if (updateCallbackInfo_.ref != nullptr) {
158          napi_delete_reference(updateCallbackInfo_.env, updateCallbackInfo_.ref);
159      }
160      if (subscribeCallbackInfo_.ref != nullptr) {
161          napi_delete_reference(subscribeCallbackInfo_.env, subscribeCallbackInfo_.ref);
162      }
163      if (unsubscribeCallbackInfo_.ref != nullptr) {
164          napi_delete_reference(unsubscribeCallbackInfo_.env, unsubscribeCallbackInfo_.ref);
165      }
166      if (dieCallbackInfo_.ref != nullptr) {
167          napi_delete_reference(dieCallbackInfo_.env, dieCallbackInfo_.ref);
168      }
169      if (disturbModeCallbackInfo_.ref != nullptr) {
170          napi_delete_reference(disturbModeCallbackInfo_.env, disturbModeCallbackInfo_.ref);
171      }
172      if (enabledNotificationCallbackInfo_.ref != nullptr) {
173          napi_delete_reference(enabledNotificationCallbackInfo_.env, enabledNotificationCallbackInfo_.ref);
174      }
175      if (batchCancelCallbackInfo_.ref != nullptr) {
176          napi_delete_reference(batchCancelCallbackInfo_.env, batchCancelCallbackInfo_.ref);
177      }
178  }
179  
ThreadSafeOnCancel(napi_env env,napi_value jsCallback,void * context,void * data)180  void ThreadSafeOnCancel(napi_env env, napi_value jsCallback, void* context, void* data)
181  {
182      ANS_LOGI("OnCanceled thread safe start");
183  
184      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
185      if (dataWorkerData == nullptr) {
186          ANS_LOGE("Create dataWorkerData failed.");
187          return;
188      }
189  
190      napi_value result = nullptr;
191      napi_handle_scope scope;
192      napi_open_handle_scope(dataWorkerData->env, &scope);
193      if (scope == nullptr) {
194          ANS_LOGE("Scope is null");
195          return;
196      }
197      napi_create_object(dataWorkerData->env, &result);
198      if (!SetSubscribeCallbackData(dataWorkerData->env,
199          dataWorkerData->request,
200          dataWorkerData->sortingMap,
201          dataWorkerData->deleteReason,
202          result)) {
203          ANS_LOGE("Failed to convert data to JS");
204      } else {
205          Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
206      }
207      napi_close_handle_scope(dataWorkerData->env, scope);
208  
209      delete dataWorkerData;
210      dataWorkerData = nullptr;
211  }
212  
OnCanceled(const std::shared_ptr<OHOS::Notification::Notification> & request,const std::shared_ptr<NotificationSortingMap> & sortingMap,int32_t deleteReason)213  void SubscriberInstance::OnCanceled(const std::shared_ptr<OHOS::Notification::Notification> &request,
214      const std::shared_ptr<NotificationSortingMap> &sortingMap, int32_t deleteReason)
215  {
216      ANS_LOGD("enter");
217  
218      if (canceCallbackInfo_.ref == nullptr || canceCallbackInfo_.env == nullptr) {
219          ANS_LOGI("cancel callback or env unset");
220          return;
221      }
222  
223      if (request == nullptr) {
224          ANS_LOGE("request is null");
225          return;
226      }
227  
228      if (sortingMap == nullptr) {
229          ANS_LOGE("sortingMap is null");
230          return;
231      }
232      ANS_LOGI("OnCanceled NotificationKey = %{public}s. sortingMap size = %{public}zu. deleteReason = %{public}d",
233          request->GetKey().c_str(), sortingMap->GetKey().size(), deleteReason);
234  
235      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
236      if (dataWorker == nullptr) {
237          ANS_LOGE("DataWorker is nullptr.");
238          return;
239      }
240  
241      dataWorker->request = request;
242      dataWorker->sortingMap = sortingMap;
243      dataWorker->deleteReason = deleteReason;
244      dataWorker->env = canceCallbackInfo_.env;
245      dataWorker->ref = canceCallbackInfo_.ref;
246      dataWorker->type = Type::CANCEL;
247  
248      napi_acquire_threadsafe_function(tsfn_);
249      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
250      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
251  }
252  
ThreadSafeOnBatchCancel(napi_env env,napi_value jsCallback,void * context,void * data)253  void ThreadSafeOnBatchCancel(napi_env env, napi_value jsCallback, void* context, void* data)
254  {
255      ANS_LOGI("OnBatchCancel thread safe start");
256  
257      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
258      if (dataWorkerData == nullptr) {
259          ANS_LOGE("Create dataWorkerData failed.");
260          return;
261      }
262  
263      napi_value resultArray = nullptr;
264      napi_handle_scope scope;
265      napi_open_handle_scope(dataWorkerData->env, &scope);
266      if (scope == nullptr) {
267          ANS_LOGE("Scope is null");
268          return;
269      }
270      napi_create_array(dataWorkerData->env, &resultArray);
271      int index = 0;
272      for (auto request : dataWorkerData->requestList) {
273          napi_value result = nullptr;
274          napi_create_object(dataWorkerData->env, &result);
275          if (SetSubscribeCallbackData(dataWorkerData->env, request,
276              dataWorkerData->sortingMap, dataWorkerData->deleteReason, result)) {
277              napi_set_element(dataWorkerData->env, resultArray, index, result);
278              index++;
279          }
280      }
281      uint32_t elementCount = 0;
282      napi_get_array_length(dataWorkerData->env, resultArray, &elementCount);
283      ANS_LOGI("notification array length: %{public}d ", elementCount);
284      if (elementCount > 0) {
285          Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, resultArray);
286      }
287  
288      napi_close_handle_scope(dataWorkerData->env, scope);
289  
290      delete dataWorkerData;
291      dataWorkerData = nullptr;
292  }
293  
OnBatchCanceled(const std::vector<std::shared_ptr<OHOS::Notification::Notification>> & requestList,const std::shared_ptr<NotificationSortingMap> & sortingMap,int32_t deleteReason)294  void SubscriberInstance::OnBatchCanceled(const std::vector<std::shared_ptr<OHOS::Notification::Notification>>
295      &requestList, const std::shared_ptr<NotificationSortingMap> &sortingMap, int32_t deleteReason)
296  {
297      ANS_LOGI("OnBatchCancel");
298      if (batchCancelCallbackInfo_.ref == nullptr || batchCancelCallbackInfo_.env == nullptr) {
299          ANS_LOGI("batchCancelCallbackInfo_ callback or env unset");
300          return;
301      }
302      if (requestList.empty()) {
303          ANS_LOGE("requestList is empty");
304          return;
305      }
306      if (sortingMap == nullptr) {
307          ANS_LOGE("sortingMap is null");
308          return;
309      }
310      ANS_LOGI("OnBatchCancel sortingMap size = %{public}zu", sortingMap->GetKey().size());
311      ANS_LOGI("OnBatchCancel deleteReason = %{public}d", deleteReason);
312      std::string notificationKeys = "";
313      for (auto notification : requestList) {
314          notificationKeys.append(notification->GetKey()).append("-");
315      }
316      ANS_LOGI("OnBatchCancel. cancel keys = %{public}s", notificationKeys.c_str());
317  
318      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
319      if (dataWorker == nullptr) {
320          ANS_LOGE("DataWorker is nullptr.");
321          return;
322      }
323      dataWorker->requestList = requestList;
324      dataWorker->sortingMap = sortingMap;
325      dataWorker->deleteReason = deleteReason;
326      dataWorker->env = batchCancelCallbackInfo_.env;
327      dataWorker->ref = batchCancelCallbackInfo_.ref;
328      dataWorker->type = Type::BATCH_CANCEL;
329  
330      napi_acquire_threadsafe_function(tsfn_);
331      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
332      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
333      return;
334  }
335  
HasOnBatchCancelCallback()336  bool SubscriberInstance::HasOnBatchCancelCallback()
337  {
338      if (batchCancelCallbackInfo_.ref == nullptr) {
339          ANS_LOGI("batchCancelCallbackInfo_ callback unset");
340          return false;
341      }
342      return true;
343  }
344  
ThreadSafeOnConsumed(napi_env env,napi_value jsCallback,void * context,void * data)345  void ThreadSafeOnConsumed(napi_env env, napi_value jsCallback, void* context, void* data)
346  {
347      ANS_LOGI("OnConsumed thread safe start");
348  
349      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
350      if (dataWorkerData == nullptr) {
351          ANS_LOGD("dataWorkerData is null.");
352          return;
353      }
354      napi_value result = nullptr;
355      napi_handle_scope scope;
356      napi_open_handle_scope(dataWorkerData->env, &scope);
357      if (scope == nullptr) {
358          ANS_LOGE("Scope is null");
359          return;
360      }
361      napi_create_object(dataWorkerData->env, &result);
362      if (!SetSubscribeCallbackData(dataWorkerData->env,
363          dataWorkerData->request,
364          dataWorkerData->sortingMap,
365          NO_DELETE_REASON,
366          result)) {
367          ANS_LOGE("Convert data to JS fail.");
368      } else {
369          Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
370      }
371      napi_close_handle_scope(dataWorkerData->env, scope);
372  
373      delete dataWorkerData;
374      dataWorkerData = nullptr;
375  }
376  
OnConsumed(const std::shared_ptr<OHOS::Notification::Notification> & request,const std::shared_ptr<NotificationSortingMap> & sortingMap)377  void SubscriberInstance::OnConsumed(const std::shared_ptr<OHOS::Notification::Notification> &request,
378      const std::shared_ptr<NotificationSortingMap> &sortingMap)
379  {
380      ANS_LOGD("enter");
381  
382      if (consumeCallbackInfo_.ref == nullptr || consumeCallbackInfo_.env == nullptr) {
383          ANS_LOGI("consume callback or env unset");
384          return;
385      }
386  
387      if (tsfn_ == nullptr) {
388          ANS_LOGI("consume tsfn is null");
389          return;
390      }
391  
392      if (request == nullptr) {
393          ANS_LOGE("request is nullptr.");
394          return;
395      }
396  
397      if (sortingMap == nullptr) {
398          ANS_LOGE("sortingMap is nullptr.");
399          return;
400      }
401      auto notificationFlags = request->GetNotificationRequest().GetFlags();
402      ANS_LOGI("OnConsumed Notification key = %{public}s, sortingMap size = %{public}zu, notificationFlag = %{public}s",
403          request->GetKey().c_str(), sortingMap->GetKey().size(),
404          notificationFlags == nullptr ? "null" : notificationFlags->Dump().c_str());
405      ANS_LOGD("OnConsumed Notification info is %{public}s", request->GetNotificationRequest().Dump().c_str());
406  
407      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
408      if (dataWorker == nullptr) {
409          ANS_LOGE("new dataWorker failed");
410          return;
411      }
412  
413      dataWorker->request = request;
414      dataWorker->sortingMap = sortingMap;
415      dataWorker->env = consumeCallbackInfo_.env;
416      dataWorker->ref = consumeCallbackInfo_.ref;
417      dataWorker->type = Type::CONSUME;
418      napi_acquire_threadsafe_function(tsfn_);
419      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
420      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
421  }
422  
ThreadSafeOnUpdate(napi_env env,napi_value jsCallback,void * context,void * data)423  void ThreadSafeOnUpdate(napi_env env, napi_value jsCallback, void* context, void* data)
424  {
425      ANS_LOGI("OnUpdate thread safe start");
426  
427      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
428      if (dataWorkerData == nullptr) {
429          ANS_LOGE("dataWorkerData is nullptr");
430          return;
431      }
432      napi_value result = nullptr;
433      napi_handle_scope scope;
434      napi_open_handle_scope(dataWorkerData->env, &scope);
435      if (scope == nullptr) {
436          ANS_LOGE("Scope is null");
437          return;
438      }
439      napi_create_object(dataWorkerData->env, &result);
440      if (!Common::SetNotificationSortingMap(dataWorkerData->env, dataWorkerData->sortingMap, result)) {
441          ANS_LOGE("Failed to convert data to JS");
442      } else {
443          Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
444      }
445      napi_close_handle_scope(dataWorkerData->env, scope);
446  
447      delete dataWorkerData;
448      dataWorkerData = nullptr;
449  }
450  
OnUpdate(const std::shared_ptr<NotificationSortingMap> & sortingMap)451  void SubscriberInstance::OnUpdate(const std::shared_ptr<NotificationSortingMap> &sortingMap)
452  {
453      ANS_LOGD("enter");
454  
455      if (updateCallbackInfo_.ref == nullptr || updateCallbackInfo_.env == nullptr) {
456          ANS_LOGI("update callback or env unset");
457          return;
458      }
459  
460      if (sortingMap == nullptr) {
461          ANS_LOGE("sortingMap is null");
462          return;
463      }
464      ANS_LOGI("OnUpdate sortingMap size = %{public}zu", sortingMap->GetKey().size());
465  
466      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
467      if (dataWorker == nullptr) {
468          ANS_LOGE("new dataWorker failed");
469          return;
470      }
471  
472      dataWorker->sortingMap = sortingMap;
473      dataWorker->env = updateCallbackInfo_.env;
474      dataWorker->ref = updateCallbackInfo_.ref;
475      dataWorker->type = Type::UPDATE;
476  
477      napi_acquire_threadsafe_function(tsfn_);
478      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
479      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
480  }
481  
ThreadSafeOnConnected(napi_env env,napi_value jsCallback,void * context,void * data)482  void ThreadSafeOnConnected(napi_env env, napi_value jsCallback, void* context, void* data)
483  {
484      ANS_LOGD("OnConnected thread safe start");
485      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
486      if (dataWorkerData == nullptr) {
487          ANS_LOGE("dataWorkerData is nullptr.");
488          return;
489      }
490  
491      Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, Common::NapiGetNull(dataWorkerData->env));
492  
493      delete dataWorkerData;
494      dataWorkerData = nullptr;
495  }
496  
OnConnected()497  void SubscriberInstance::OnConnected()
498  {
499      ANS_LOGD("enter");
500  
501      if (subscribeCallbackInfo_.ref == nullptr || subscribeCallbackInfo_.env == nullptr) {
502          ANS_LOGI("subscribe callback or env unset");
503          return;
504      }
505  
506      if (tsfn_ == nullptr) {
507          ANS_LOGI("subscribe tsfn is null");
508          return;
509      }
510  
511      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
512      if (dataWorker == nullptr) {
513          ANS_LOGE("new dataWorker failed");
514          return;
515      }
516  
517      dataWorker->env = subscribeCallbackInfo_.env;
518      dataWorker->ref = subscribeCallbackInfo_.ref;
519      dataWorker->type = Type::CONNECTED;
520  
521      napi_acquire_threadsafe_function(tsfn_);
522      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
523      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
524  }
525  
ThreadSafeOnDisconnected(napi_env env,napi_value jsCallback,void * context,void * data)526  void ThreadSafeOnDisconnected(napi_env env, napi_value jsCallback, void* context, void* data)
527  {
528      ANS_LOGI("OnDisconnected thread safe start");
529  
530      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
531      if (dataWorkerData == nullptr) {
532          ANS_LOGE("Failed to create dataWorkerData.");
533          return;
534      }
535  
536      Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, Common::NapiGetNull(dataWorkerData->env));
537      DelSubscriberInstancesInfo(dataWorkerData->env, dataWorkerData->subscriber);
538      delete dataWorkerData;
539      dataWorkerData = nullptr;
540  }
541  
OnDisconnected()542  void SubscriberInstance::OnDisconnected()
543  {
544      ANS_LOGD("enter");
545  
546      if (unsubscribeCallbackInfo_.ref == nullptr) {
547          ANS_LOGI("unsubscribe callback unset");
548          return;
549      }
550  
551      if (tsfn_ == nullptr) {
552          ANS_LOGI("unsubscribe tsfn is null");
553          return;
554      }
555  
556      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
557      if (dataWorker == nullptr) {
558          ANS_LOGE("new dataWorker failed");
559          return;
560      }
561  
562      dataWorker->env = unsubscribeCallbackInfo_.env;
563      dataWorker->ref = unsubscribeCallbackInfo_.ref;
564      dataWorker->subscriber = std::static_pointer_cast<SubscriberInstance>(shared_from_this());
565      dataWorker->type = Type::DIS_CONNECTED;
566  
567      napi_acquire_threadsafe_function(tsfn_);
568      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
569      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
570  }
571  
ThreadSafeOnDestroy(napi_env env,napi_value jsCallback,void * context,void * data)572  void ThreadSafeOnDestroy(napi_env env, napi_value jsCallback, void* context, void* data)
573  {
574      ANS_LOGI("OnDied thread safe start");
575  
576      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
577      if (dataWorkerData == nullptr) {
578          ANS_LOGE("dataWorkerData is null");
579          return;
580      }
581  
582      Common::SetCallback(
583          dataWorkerData->env, dataWorkerData->ref, Common::NapiGetNull(dataWorkerData->env));
584  
585      delete dataWorkerData;
586      dataWorkerData = nullptr;
587  }
588  
OnDied()589  void SubscriberInstance::OnDied()
590  {
591      ANS_LOGD("enter");
592  
593      if (dieCallbackInfo_.ref == nullptr) {
594          ANS_LOGE("die callback unset");
595          return;
596      }
597  
598      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
599      if (dataWorker == nullptr) {
600          ANS_LOGE("new dataWorker failed");
601          return;
602      }
603  
604      dataWorker->env = dieCallbackInfo_.env;
605      dataWorker->ref = dieCallbackInfo_.ref;
606      dataWorker->type = Type::DIE;
607  
608      napi_acquire_threadsafe_function(tsfn_);
609      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
610      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
611  }
612  
ThreadSafeOnDoNotDisturbDateChange(napi_env env,napi_value jsCallback,void * context,void * data)613  void ThreadSafeOnDoNotDisturbDateChange(napi_env env, napi_value jsCallback, void* context, void* data)
614  {
615      ANS_LOGI("OnDoNotDisturbDateChange thread safe start");
616  
617      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
618      if (dataWorkerData == nullptr) {
619          ANS_LOGE("Data worker data is null.");
620          return;
621      }
622  
623      napi_value result = nullptr;
624      napi_handle_scope scope;
625      napi_open_handle_scope(dataWorkerData->env, &scope);
626      if (scope == nullptr) {
627          ANS_LOGE("Scope is null");
628          return;
629      }
630      napi_create_object(dataWorkerData->env, &result);
631  
632      if (!Common::SetDoNotDisturbDate(dataWorkerData->env, dataWorkerData->date, result)) {
633          result = Common::NapiGetNull(dataWorkerData->env);
634      }
635  
636      Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
637      napi_close_handle_scope(dataWorkerData->env, scope);
638  
639      delete dataWorkerData;
640      dataWorkerData = nullptr;
641  }
642  
OnDoNotDisturbDateChange(const std::shared_ptr<NotificationDoNotDisturbDate> & date)643  void SubscriberInstance::OnDoNotDisturbDateChange(const std::shared_ptr<NotificationDoNotDisturbDate> &date)
644  {
645      ANS_LOGD("enter");
646  
647      onDoNotDisturbChanged(date);
648  
649      if (disturbDateCallbackInfo_.ref == nullptr || disturbDateCallbackInfo_.env == nullptr) {
650          ANS_LOGI("disturbDateCallbackInfo_ callback or env unset");
651          return;
652      }
653  
654      if (date == nullptr) {
655          ANS_LOGE("date is null");
656          return;
657      }
658  
659      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
660      if (dataWorker == nullptr) {
661          ANS_LOGE("new dataWorker failed");
662          return;
663      }
664  
665      dataWorker->date = *date;
666      dataWorker->env = disturbDateCallbackInfo_.env;
667      dataWorker->ref = disturbDateCallbackInfo_.ref;
668      dataWorker->type = Type::DISTURB_DATE_CHANGE;
669  
670      napi_acquire_threadsafe_function(tsfn_);
671      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
672      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
673  }
674  
675  
ThreadSafeOnDoNotDisturbChanged(napi_env env,napi_value jsCallback,void * context,void * data)676  void ThreadSafeOnDoNotDisturbChanged(napi_env env, napi_value jsCallback, void* context, void* data)
677  {
678      ANS_LOGI("OnDoNotDisturbChanged thread safe start");
679  
680      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
681      if (dataWorkerData == nullptr) {
682          ANS_LOGE("Data worker data is null.");
683          return;
684      }
685  
686      napi_value result = nullptr;
687      napi_handle_scope scope;
688      napi_open_handle_scope(dataWorkerData->env, &scope);
689      napi_create_object(dataWorkerData->env, &result);
690  
691      if (!Common::SetDoNotDisturbDate(dataWorkerData->env, dataWorkerData->date, result)) {
692          result = Common::NapiGetNull(dataWorkerData->env);
693      }
694  
695      Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
696      napi_close_handle_scope(dataWorkerData->env, scope);
697  
698      delete dataWorkerData;
699      dataWorkerData = nullptr;
700  }
701  
onDoNotDisturbChanged(const std::shared_ptr<NotificationDoNotDisturbDate> & date)702  void SubscriberInstance::onDoNotDisturbChanged(const std::shared_ptr<NotificationDoNotDisturbDate>& date)
703  {
704      ANS_LOGD("enter");
705  
706      if (disturbChangedCallbackInfo_.ref == nullptr || disturbChangedCallbackInfo_.env == nullptr) {
707          ANS_LOGE("disturbChangedCallbackInfo_ callback or env unset");
708          return;
709      }
710  
711      if (date == nullptr) {
712          ANS_LOGE("date is null");
713          return;
714      }
715  
716      NotificationReceiveDataWorker* dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
717      if (dataWorker == nullptr) {
718          ANS_LOGE("new dataWorker failed");
719          return;
720      }
721  
722      dataWorker->date = *date;
723      dataWorker->env = disturbChangedCallbackInfo_.env;
724      dataWorker->ref = disturbChangedCallbackInfo_.ref;
725      dataWorker->type = Type::DISTURB_CHANGED;
726  
727      napi_acquire_threadsafe_function(tsfn_);
728      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
729      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
730  }
731  
ThreadSafeOnEnabledNotificationChanged(napi_env env,napi_value jsCallback,void * context,void * data)732  void ThreadSafeOnEnabledNotificationChanged(napi_env env, napi_value jsCallback, void* context, void* data)
733  {
734      ANS_LOGI("OnEnabledNotificationChanged thread safe start");
735  
736      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
737      if (dataWorkerData == nullptr) {
738          ANS_LOGE("Data worker data is null.");
739          return;
740      }
741  
742      napi_value result = nullptr;
743      napi_handle_scope scope;
744      napi_open_handle_scope(dataWorkerData->env, &scope);
745      if (scope == nullptr) {
746          ANS_LOGE("Scope is null");
747          return;
748      }
749      napi_create_object(dataWorkerData->env, &result);
750  
751      if (!Common::SetEnabledNotificationCallbackData(dataWorkerData->env, dataWorkerData->callbackData, result)) {
752          result = Common::NapiGetNull(dataWorkerData->env);
753      }
754  
755      Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
756      napi_close_handle_scope(dataWorkerData->env, scope);
757  
758      delete dataWorkerData;
759      dataWorkerData = nullptr;
760  }
761  
OnEnabledNotificationChanged(const std::shared_ptr<EnabledNotificationCallbackData> & callbackData)762  void SubscriberInstance::OnEnabledNotificationChanged(
763      const std::shared_ptr<EnabledNotificationCallbackData> &callbackData)
764  {
765      ANS_LOGD("enter");
766  
767      if (enabledNotificationCallbackInfo_.ref == nullptr || enabledNotificationCallbackInfo_.env == nullptr) {
768          ANS_LOGI("enabledNotificationCallbackInfo_ callback or env unset");
769          return;
770      }
771  
772      if (callbackData == nullptr) {
773          ANS_LOGE("callbackData is null");
774          return;
775      }
776  
777      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
778      if (dataWorker == nullptr) {
779          ANS_LOGE("new dataWorker failed");
780          return;
781      }
782  
783      dataWorker->callbackData = *callbackData;
784      dataWorker->env = enabledNotificationCallbackInfo_.env;
785      dataWorker->ref = enabledNotificationCallbackInfo_.ref;
786      dataWorker->type = Type::ENABLE_NOTIFICATION_CHANGED;
787  
788      napi_acquire_threadsafe_function(tsfn_);
789      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
790      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
791  }
792  
ThreadSafeOnBadgeChanged(napi_env env,napi_value jsCallback,void * context,void * data)793  void ThreadSafeOnBadgeChanged(napi_env env, napi_value jsCallback, void* context, void* data)
794  {
795      ANS_LOGI("OnBadgeChanged thread safe start");
796  
797      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
798      if (dataWorkerData == nullptr) {
799          ANS_LOGE("dataWorkerData is null");
800          return;
801      }
802  
803      napi_value result = nullptr;
804      napi_handle_scope scope;
805      napi_open_handle_scope(dataWorkerData->env, &scope);
806      if (scope == nullptr) {
807          ANS_LOGE("Scope is null");
808          return;
809      }
810      napi_create_object(dataWorkerData->env, &result);
811  
812      if (!Common::SetBadgeCallbackData(dataWorkerData->env, dataWorkerData->badge, result)) {
813          result = Common::NapiGetNull(dataWorkerData->env);
814      }
815  
816      Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
817      napi_close_handle_scope(dataWorkerData->env, scope);
818  
819      delete dataWorkerData;
820      dataWorkerData = nullptr;
821  }
822  
OnBadgeChanged(const std::shared_ptr<BadgeNumberCallbackData> & badgeData)823  void SubscriberInstance::OnBadgeChanged(
824      const std::shared_ptr<BadgeNumberCallbackData> &badgeData)
825  {
826      ANS_LOGD("enter");
827  
828      if (setBadgeCallbackInfo_.ref == nullptr || setBadgeCallbackInfo_.env == nullptr) {
829          return;
830      }
831  
832      if (badgeData == nullptr) {
833          ANS_LOGE("badgeData is null");
834          return;
835      }
836  
837      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
838      if (dataWorker == nullptr) {
839          ANS_LOGE("new dataWorker failed");
840          return;
841      }
842  
843      dataWorker->badge = *badgeData;
844      dataWorker->env = setBadgeCallbackInfo_.env;
845      dataWorker->ref = setBadgeCallbackInfo_.ref;
846      dataWorker->type = Type::BADGE_CHANGED;
847  
848      napi_acquire_threadsafe_function(tsfn_);
849      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
850      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
851  }
852  
ThreadSafeOnBadgeEnabledChanged(napi_env env,napi_value jsCallback,void * context,void * data)853  void ThreadSafeOnBadgeEnabledChanged(napi_env env, napi_value jsCallback, void* context, void* data)
854  {
855      ANS_LOGI("OnBadgeEnabledChanged thread safe start.");
856  
857      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
858      if (dataWorkerData == nullptr) {
859          ANS_LOGE("Data worker is null.");
860          return;
861      }
862  
863      napi_value result = nullptr;
864      napi_handle_scope scope;
865      napi_open_handle_scope(dataWorkerData->env, &scope);
866      if (scope == nullptr) {
867          ANS_LOGE("Scope is null");
868          return;
869      }
870      napi_create_object(dataWorkerData->env, &result);
871      if (!Common::SetEnabledNotificationCallbackData(dataWorkerData->env, dataWorkerData->callbackData, result)) {
872          result = Common::NapiGetNull(dataWorkerData->env);
873      }
874  
875      Common::SetCallback(dataWorkerData->env, dataWorkerData->ref, result);
876      napi_close_handle_scope(dataWorkerData->env, scope);
877  
878      delete dataWorkerData;
879      dataWorkerData = nullptr;
880  }
881  
OnBadgeEnabledChanged(const sptr<EnabledNotificationCallbackData> & callbackData)882  void SubscriberInstance::OnBadgeEnabledChanged(
883      const sptr<EnabledNotificationCallbackData> &callbackData)
884  {
885      if (setBadgeEnabledCallbackInfo_.ref == nullptr) {
886          ANS_LOGE("Set badge enabled callback info is null.");
887          return;
888      }
889      if (callbackData == nullptr) {
890          ANS_LOGE("Callback data is null.");
891          return;
892      }
893  
894      NotificationReceiveDataWorker *dataWorker = new (std::nothrow) NotificationReceiveDataWorker();
895      if (dataWorker == nullptr) {
896          ANS_LOGE("Create new data worker failed.");
897          return;
898      }
899  
900      dataWorker->callbackData = *callbackData;
901      dataWorker->env = setBadgeEnabledCallbackInfo_.env;
902      dataWorker->ref = setBadgeEnabledCallbackInfo_.ref;
903      dataWorker->type = Type::BADGE_ENABLED_CHANGED;
904  
905      napi_acquire_threadsafe_function(tsfn_);
906      napi_call_threadsafe_function(tsfn_, dataWorker, napi_tsfn_nonblocking);
907      napi_release_threadsafe_function(tsfn_, napi_tsfn_release);
908  }
909  
SetThreadSafeFunction(const napi_threadsafe_function & tsfn)910  void SubscriberInstance::SetThreadSafeFunction(const napi_threadsafe_function &tsfn)
911  {
912      tsfn_ = tsfn;
913  }
914  
SetCancelCallbackInfo(const napi_env & env,const napi_ref & ref)915  void SubscriberInstance::SetCancelCallbackInfo(const napi_env &env, const napi_ref &ref)
916  {
917      canceCallbackInfo_.env = env;
918      canceCallbackInfo_.ref = ref;
919  }
920  
SetConsumeCallbackInfo(const napi_env & env,const napi_ref & ref)921  void SubscriberInstance::SetConsumeCallbackInfo(const napi_env &env, const napi_ref &ref)
922  {
923      consumeCallbackInfo_.env = env;
924      consumeCallbackInfo_.ref = ref;
925  }
926  
SetUpdateCallbackInfo(const napi_env & env,const napi_ref & ref)927  void SubscriberInstance::SetUpdateCallbackInfo(const napi_env &env, const napi_ref &ref)
928  {
929      updateCallbackInfo_.env = env;
930      updateCallbackInfo_.ref = ref;
931  }
932  
SetSubscribeCallbackInfo(const napi_env & env,const napi_ref & ref)933  void SubscriberInstance::SetSubscribeCallbackInfo(const napi_env &env, const napi_ref &ref)
934  {
935      subscribeCallbackInfo_.env = env;
936      subscribeCallbackInfo_.ref = ref;
937  }
938  
SetUnsubscribeCallbackInfo(const napi_env & env,const napi_ref & ref)939  void SubscriberInstance::SetUnsubscribeCallbackInfo(const napi_env &env, const napi_ref &ref)
940  {
941      unsubscribeCallbackInfo_.env = env;
942      unsubscribeCallbackInfo_.ref = ref;
943  }
944  
SetDieCallbackInfo(const napi_env & env,const napi_ref & ref)945  void SubscriberInstance::SetDieCallbackInfo(const napi_env &env, const napi_ref &ref)
946  {
947      dieCallbackInfo_.env = env;
948      dieCallbackInfo_.ref = ref;
949  }
950  
SetDisturbModeCallbackInfo(const napi_env & env,const napi_ref & ref)951  void SubscriberInstance::SetDisturbModeCallbackInfo(const napi_env &env, const napi_ref &ref)
952  {
953      disturbModeCallbackInfo_.env = env;
954      disturbModeCallbackInfo_.ref = ref;
955  }
956  
SetEnabledNotificationCallbackInfo(const napi_env & env,const napi_ref & ref)957  void SubscriberInstance::SetEnabledNotificationCallbackInfo(const napi_env &env, const napi_ref &ref)
958  {
959      enabledNotificationCallbackInfo_.env = env;
960      enabledNotificationCallbackInfo_.ref = ref;
961  }
962  
SetDisturbDateCallbackInfo(const napi_env & env,const napi_ref & ref)963  void SubscriberInstance::SetDisturbDateCallbackInfo(const napi_env &env, const napi_ref &ref)
964  {
965      disturbDateCallbackInfo_.env = env;
966      disturbDateCallbackInfo_.ref = ref;
967  }
968  
SetDisturbChangedCallbackInfo(const napi_env & env,const napi_ref & ref)969  void SubscriberInstance::SetDisturbChangedCallbackInfo(const napi_env &env, const napi_ref &ref)
970  {
971      disturbChangedCallbackInfo_.env = env;
972      disturbChangedCallbackInfo_.ref = ref;
973  }
974  
SetBadgeCallbackInfo(const napi_env & env,const napi_ref & ref)975  void SubscriberInstance::SetBadgeCallbackInfo(const napi_env &env, const napi_ref &ref)
976  {
977      setBadgeCallbackInfo_.env = env;
978      setBadgeCallbackInfo_.ref = ref;
979  }
980  
981  
SetBadgeEnabledCallbackInfo(const napi_env & env,const napi_ref & ref)982  void SubscriberInstance::SetBadgeEnabledCallbackInfo(const napi_env &env, const napi_ref &ref)
983  {
984      setBadgeEnabledCallbackInfo_.env = env;
985      setBadgeEnabledCallbackInfo_.ref = ref;
986  }
987  
SetBatchCancelCallbackInfo(const napi_env & env,const napi_ref & ref)988  void SubscriberInstance::SetBatchCancelCallbackInfo(const napi_env &env, const napi_ref &ref)
989  {
990      batchCancelCallbackInfo_.env = env;
991      batchCancelCallbackInfo_.ref = ref;
992  }
993  
SetCallbackInfo(const napi_env & env,const std::string & type,const napi_ref & ref)994  void SubscriberInstance::SetCallbackInfo(const napi_env &env, const std::string &type, const napi_ref &ref)
995  {
996      if (type == CONSUME) {
997          SetConsumeCallbackInfo(env, ref);
998      } else if (type == CANCEL) {
999          SetCancelCallbackInfo(env, ref);
1000      } else if (type == UPDATE) {
1001          SetUpdateCallbackInfo(env, ref);
1002      } else if (type == CONNECTED) {
1003          SetSubscribeCallbackInfo(env, ref);
1004      } else if (type == DIS_CONNECTED) {
1005          SetUnsubscribeCallbackInfo(env, ref);
1006      } else if (type == DIE) {
1007          SetDieCallbackInfo(env, ref);
1008      } else if (type == DISTURB_MODE_CHANGE) {
1009          SetDisturbModeCallbackInfo(env, ref);
1010      } else if (type == DISTURB_DATE_CHANGE) {
1011          SetDisturbDateCallbackInfo(env, ref);
1012      } else if (type == DISTURB_CHANGED) {
1013          SetDisturbChangedCallbackInfo(env, ref);
1014      } else if (type == ENABLE_NOTIFICATION_CHANGED) {
1015          SetEnabledNotificationCallbackInfo(env, ref);
1016      } else if (type == BADGE_CHANGED) {
1017          SetBadgeCallbackInfo(env, ref);
1018      } else if (type == BADGE_ENABLED_CHANGED) {
1019          SetBadgeEnabledCallbackInfo(env, ref);
1020      } else if (type == BATCH_CANCEL) {
1021          SetBatchCancelCallbackInfo(env, ref);
1022      } else {
1023          ANS_LOGW("type is error");
1024      }
1025  }
1026  
HasNotificationSubscriber(const napi_env & env,const napi_value & value,SubscriberInstancesInfo & subscriberInfo)1027  bool HasNotificationSubscriber(const napi_env &env, const napi_value &value, SubscriberInstancesInfo &subscriberInfo)
1028  {
1029      std::lock_guard<std::mutex> lock(mutex_);
1030      for (auto vec : subscriberInstances_) {
1031          napi_value callback = nullptr;
1032          napi_get_reference_value(env, vec.ref, &callback);
1033          bool isEquals = false;
1034          napi_strict_equals(env, value, callback, &isEquals);
1035          if (isEquals) {
1036              subscriberInfo = vec;
1037              return true;
1038          }
1039      }
1040      return false;
1041  }
1042  
1043  void ThreadFinished(napi_env env, void* data, [[maybe_unused]] void* context)
1044  {
1045      ANS_LOGD("ThreadFinished");
1046  }
1047  
ThreadSafeCommon(napi_env env,napi_value jsCallback,void * context,void * data)1048  void ThreadSafeCommon(napi_env env, napi_value jsCallback, void* context, void* data)
1049  {
1050      ANS_LOGI("common thread safe start");
1051      auto dataWorkerData = reinterpret_cast<NotificationReceiveDataWorker *>(data);
1052      switch (dataWorkerData->type) {
1053          case Type::CANCEL:
1054              ThreadSafeOnCancel(env, jsCallback, context, data);
1055              break;
1056          case Type::BATCH_CANCEL:
1057              ThreadSafeOnBatchCancel(env, jsCallback, context, data);
1058              break;
1059          case Type::CONSUME:
1060              ThreadSafeOnConsumed(env, jsCallback, context, data);
1061              break;
1062          case Type::UPDATE:
1063              ThreadSafeOnUpdate(env, jsCallback, context, data);
1064              break;
1065          case Type::CONNECTED:
1066              ThreadSafeOnConnected(env, jsCallback, context, data);
1067              break;
1068          case Type::DIS_CONNECTED:
1069              ThreadSafeOnDisconnected(env, jsCallback, context, data);
1070              break;
1071          case Type::DIE:
1072              ThreadSafeOnDestroy(env, jsCallback, context, data);
1073              break;
1074          case Type::DISTURB_DATE_CHANGE:
1075              ThreadSafeOnDoNotDisturbDateChange(env, jsCallback, context, data);
1076              break;
1077          case Type::DISTURB_CHANGED:
1078              ThreadSafeOnDoNotDisturbChanged(env, jsCallback, context, data);
1079              break;
1080          case Type::ENABLE_NOTIFICATION_CHANGED:
1081              ThreadSafeOnEnabledNotificationChanged(env, jsCallback, context, data);
1082              break;
1083          case Type::BADGE_CHANGED:
1084              ThreadSafeOnBadgeChanged(env, jsCallback, context, data);
1085              break;
1086          case Type::BADGE_ENABLED_CHANGED:
1087              ThreadSafeOnBadgeEnabledChanged(env, jsCallback, context, data);
1088              break;
1089          default:
1090              break;
1091      }
1092  }
1093  
GetNotificationSubscriber(const napi_env & env,const napi_value & value,SubscriberInstancesInfo & subscriberInfo)1094  napi_value GetNotificationSubscriber(
1095      const napi_env &env, const napi_value &value, SubscriberInstancesInfo &subscriberInfo)
1096  {
1097      ANS_LOGD("enter");
1098      bool hasProperty = false;
1099      napi_valuetype valuetype = napi_undefined;
1100      napi_ref result = nullptr;
1101  
1102      subscriberInfo.subscriber = std::make_shared<SubscriberInstance>();
1103      if (subscriberInfo.subscriber == nullptr) {
1104          ANS_LOGE("subscriber is null");
1105          std::string msg = "Mandatory parameters are left unspecified. subscriber is null";
1106          Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1107          return nullptr;
1108      }
1109  
1110      napi_create_reference(env, value, 1, &subscriberInfo.ref);
1111  
1112      napi_value resourceName = nullptr;
1113      napi_create_string_latin1(env, "tsfn", NAPI_AUTO_LENGTH, &resourceName);
1114      napi_threadsafe_function tsfn = nullptr;
1115      napi_create_threadsafe_function(env, nullptr, nullptr, resourceName, 0, 1, subscriberInfo.ref,
1116          ThreadFinished, nullptr, ThreadSafeCommon, &tsfn);
1117      subscriberInfo.subscriber->SetThreadSafeFunction(tsfn);
1118  
1119      // onConsume?:(data: SubscribeCallbackData) => void
1120      NAPI_CALL(env, napi_has_named_property(env, value, "onConsume", &hasProperty));
1121      if (hasProperty) {
1122          napi_value nOnConsumed = nullptr;
1123          napi_get_named_property(env, value, "onConsume", &nOnConsumed);
1124          NAPI_CALL(env, napi_typeof(env, nOnConsumed, &valuetype));
1125          if (valuetype != napi_function) {
1126              ANS_LOGE("Wrong argument type. Function expected.");
1127              std::string msg = "Incorrect parameter types.The type of param must be function.";
1128              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1129              return nullptr;
1130          }
1131          napi_create_reference(env, nOnConsumed, 1, &result);
1132          subscriberInfo.subscriber->SetCallbackInfo(env, CONSUME, result);
1133      }
1134      // onCancel?:(data: SubscribeCallbackData) => void
1135      NAPI_CALL(env, napi_has_named_property(env, value, "onCancel", &hasProperty));
1136      if (hasProperty) {
1137          napi_value nOnCanceled = nullptr;
1138          napi_get_named_property(env, value, "onCancel", &nOnCanceled);
1139          NAPI_CALL(env, napi_typeof(env, nOnCanceled, &valuetype));
1140          if (valuetype != napi_function) {
1141              ANS_LOGE("Wrong argument type. Function expected.");
1142              std::string msg = "Incorrect parameter types.The type of param must be function.";
1143              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1144              return nullptr;
1145          }
1146          napi_create_reference(env, nOnCanceled, 1, &result);
1147          subscriberInfo.subscriber->SetCallbackInfo(env, CANCEL, result);
1148      }
1149      // onUpdate?:(data: NotificationSortingMap) => void
1150      NAPI_CALL(env, napi_has_named_property(env, value, "onUpdate", &hasProperty));
1151      if (hasProperty) {
1152          napi_value nOnUpdate = nullptr;
1153          napi_get_named_property(env, value, "onUpdate", &nOnUpdate);
1154          NAPI_CALL(env, napi_typeof(env, nOnUpdate, &valuetype));
1155          if (valuetype != napi_function) {
1156              ANS_LOGE("Wrong argument type. Function expected.");
1157              std::string msg = "Incorrect parameter types.The type of param must be function.";
1158              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1159              return nullptr;
1160          }
1161          napi_create_reference(env, nOnUpdate, 1, &result);
1162          subscriberInfo.subscriber->SetCallbackInfo(env, UPDATE, result);
1163      }
1164      // onConnect?:() => void
1165      NAPI_CALL(env, napi_has_named_property(env, value, "onConnect", &hasProperty));
1166      if (hasProperty) {
1167          napi_value nOnConnected = nullptr;
1168          napi_get_named_property(env, value, "onConnect", &nOnConnected);
1169          NAPI_CALL(env, napi_typeof(env, nOnConnected, &valuetype));
1170          if (valuetype != napi_function) {
1171              ANS_LOGE("Wrong argument type. Function expected.");
1172              std::string msg = "Incorrect parameter types.The type of param must be function.";
1173              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1174              return nullptr;
1175          }
1176          napi_create_reference(env, nOnConnected, 1, &result);
1177          subscriberInfo.subscriber->SetCallbackInfo(env, CONNECTED, result);
1178      }
1179      // onDisconnect?:() => void
1180      NAPI_CALL(env, napi_has_named_property(env, value, "onDisconnect", &hasProperty));
1181      if (hasProperty) {
1182          napi_value nOnDisConnect = nullptr;
1183          napi_get_named_property(env, value, "onDisconnect", &nOnDisConnect);
1184          NAPI_CALL(env, napi_typeof(env, nOnDisConnect, &valuetype));
1185          if (valuetype != napi_function) {
1186              ANS_LOGE("Wrong argument type. Function expected.");
1187              std::string msg = "Incorrect parameter types.The type of param must be function.";
1188              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1189              return nullptr;
1190          }
1191          napi_create_reference(env, nOnDisConnect, 1, &result);
1192          subscriberInfo.subscriber->SetCallbackInfo(env, DIS_CONNECTED, result);
1193      }
1194      // onDestroy?:() => void
1195      NAPI_CALL(env, napi_has_named_property(env, value, "onDestroy", &hasProperty));
1196      if (hasProperty) {
1197          napi_value nOnDied = nullptr;
1198          napi_get_named_property(env, value, "onDestroy", &nOnDied);
1199          NAPI_CALL(env, napi_typeof(env, nOnDied, &valuetype));
1200          if (valuetype != napi_function) {
1201              ANS_LOGE("Wrong argument type. Function expected.");
1202              std::string msg = "Incorrect parameter types.The type of param must be function.";
1203              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1204              return nullptr;
1205          }
1206          napi_create_reference(env, nOnDied, 1, &result);
1207          subscriberInfo.subscriber->SetCallbackInfo(env, DIE, result);
1208      }
1209      // onDisturbModeChange?:(mode: notification.DoNotDisturbMode) => void
1210      NAPI_CALL(env, napi_has_named_property(env, value, "onDisturbModeChange", &hasProperty));
1211      if (hasProperty) {
1212          napi_value nOnDisturbModeChanged = nullptr;
1213          napi_get_named_property(env, value, "onDisturbModeChange", &nOnDisturbModeChanged);
1214          NAPI_CALL(env, napi_typeof(env, nOnDisturbModeChanged, &valuetype));
1215          if (valuetype != napi_function) {
1216              ANS_LOGE("Wrong argument type. Function expected.");
1217              std::string msg = "Incorrect parameter types.The type of param must be function.";
1218              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1219              return nullptr;
1220          }
1221          napi_create_reference(env, nOnDisturbModeChanged, 1, &result);
1222          subscriberInfo.subscriber->SetCallbackInfo(env, DISTURB_MODE_CHANGE, result);
1223      }
1224  
1225      // onDoNotDisturbDateChange?:(mode: notification.DoNotDisturbDate) => void
1226      NAPI_CALL(env, napi_has_named_property(env, value, "onDoNotDisturbDateChange", &hasProperty));
1227      if (hasProperty) {
1228          napi_value nOnDisturbDateChanged = nullptr;
1229          napi_get_named_property(env, value, "onDoNotDisturbDateChange", &nOnDisturbDateChanged);
1230          NAPI_CALL(env, napi_typeof(env, nOnDisturbDateChanged, &valuetype));
1231          if (valuetype != napi_function) {
1232              ANS_LOGE("Wrong argument type. Function expected.");
1233              std::string msg = "Incorrect parameter types.The type of param must be function.";
1234              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1235              return nullptr;
1236          }
1237          napi_create_reference(env, nOnDisturbDateChanged, 1, &result);
1238          subscriberInfo.subscriber->SetCallbackInfo(env, DISTURB_DATE_CHANGE, result);
1239      }
1240  
1241      // onDoNotDisturbChanged?:(mode: notificationManager.DoNotDisturbDate) => void
1242      NAPI_CALL(env, napi_has_named_property(env, value, "onDoNotDisturbChanged", &hasProperty));
1243      if (hasProperty) {
1244          napi_value nOnDoNotDisturbChanged = nullptr;
1245          napi_get_named_property(env, value, "onDoNotDisturbChanged", &nOnDoNotDisturbChanged);
1246          NAPI_CALL(env, napi_typeof(env, nOnDoNotDisturbChanged, &valuetype));
1247          if (valuetype != napi_function) {
1248              ANS_LOGE("Wrong argument type. Function expected.");
1249              std::string msg = "Incorrect parameter types.The type of param must be function.";
1250              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1251              return nullptr;
1252          }
1253          napi_create_reference(env, nOnDoNotDisturbChanged, 1, &result);
1254          subscriberInfo.subscriber->SetCallbackInfo(env, DISTURB_CHANGED, result);
1255      }
1256  
1257      // onEnabledNotificationChanged?:(data: notification.EnabledNotificationCallbackData) => void
1258      NAPI_CALL(env, napi_has_named_property(env, value, "onEnabledNotificationChanged", &hasProperty));
1259      if (hasProperty) {
1260          napi_value nOnEnabledNotificationChanged = nullptr;
1261          napi_get_named_property(env, value, "onEnabledNotificationChanged", &nOnEnabledNotificationChanged);
1262          NAPI_CALL(env, napi_typeof(env, nOnEnabledNotificationChanged, &valuetype));
1263          if (valuetype != napi_function) {
1264              ANS_LOGE("Wrong argument type. Function expected.");
1265              std::string msg = "Incorrect parameter types.The type of param must be function.";
1266              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1267              return nullptr;
1268          }
1269          napi_create_reference(env, nOnEnabledNotificationChanged, 1, &result);
1270          subscriberInfo.subscriber->SetCallbackInfo(env, ENABLE_NOTIFICATION_CHANGED, result);
1271      }
1272  
1273      // onBadgeChanged?:(data: BadgeNumberCallbackData) => void
1274      NAPI_CALL(env, napi_has_named_property(env, value, "onBadgeChanged", &hasProperty));
1275      if (hasProperty) {
1276          napi_value nOnBadgeChanged = nullptr;
1277          napi_get_named_property(env, value, "onBadgeChanged", &nOnBadgeChanged);
1278          NAPI_CALL(env, napi_typeof(env, nOnBadgeChanged, &valuetype));
1279          if (valuetype != napi_function) {
1280              ANS_LOGE("Wrong argument type. Function expected.");
1281              std::string msg = "Incorrect parameter types.The type of param must be function.";
1282              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1283              return nullptr;
1284          }
1285          napi_create_reference(env, nOnBadgeChanged, 1, &result);
1286          subscriberInfo.subscriber->SetCallbackInfo(env, BADGE_CHANGED, result);
1287      }
1288  
1289      // onBadgeEnabledChanged?:(data: EnabledNotificationCallbackData) => void
1290      NAPI_CALL(env, napi_has_named_property(env, value, "onBadgeEnabledChanged", &hasProperty));
1291      if (hasProperty) {
1292          napi_value nOnBadgeEnabledChanged = nullptr;
1293          napi_get_named_property(env, value, "onBadgeEnabledChanged", &nOnBadgeEnabledChanged);
1294          NAPI_CALL(env, napi_typeof(env, nOnBadgeEnabledChanged, &valuetype));
1295          if (valuetype != napi_function) {
1296              ANS_LOGE("Wrong argument type. Function expected.");
1297              std::string msg = "Incorrect parameter types.The type of param must be function.";
1298              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1299              return nullptr;
1300          }
1301          napi_create_reference(env, nOnBadgeEnabledChanged, 1, &result);
1302          subscriberInfo.subscriber->SetCallbackInfo(env, BADGE_ENABLED_CHANGED, result);
1303      }
1304  
1305      // onBatchCancel?:(data: Array<SubscribeCallbackData>) => void
1306      NAPI_CALL(env, napi_has_named_property(env, value, "onBatchCancel", &hasProperty));
1307      if (hasProperty) {
1308          napi_value onBatchCancel = nullptr;
1309          napi_get_named_property(env, value, "onBatchCancel", &onBatchCancel);
1310          NAPI_CALL(env, napi_typeof(env, onBatchCancel, &valuetype));
1311          if (valuetype != napi_function) {
1312              ANS_LOGE("Wrong argument type. Function expected.");
1313              std::string msg = "Incorrect parameter types.The type of param must be function.";
1314              Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1315              return nullptr;
1316          }
1317          napi_create_reference(env, onBatchCancel, 1, &result);
1318          subscriberInfo.subscriber->SetCallbackInfo(env, BATCH_CANCEL, result);
1319      }
1320  
1321      return Common::NapiGetNull(env);
1322  }
1323  
AddSubscriberInstancesInfo(const napi_env & env,const SubscriberInstancesInfo & subscriberInfo)1324  bool AddSubscriberInstancesInfo(const napi_env &env, const SubscriberInstancesInfo &subscriberInfo)
1325  {
1326      ANS_LOGD("enter");
1327      if (subscriberInfo.ref == nullptr) {
1328          ANS_LOGE("subscriberInfo.ref is null");
1329          return false;
1330      }
1331      if (subscriberInfo.subscriber == nullptr) {
1332          ANS_LOGE("subscriberInfo.subscriber is null");
1333          return false;
1334      }
1335      std::lock_guard<std::mutex> lock(mutex_);
1336      subscriberInstances_.emplace_back(subscriberInfo);
1337  
1338      return true;
1339  }
1340  
DelSubscriberInstancesInfo(const napi_env & env,const std::shared_ptr<SubscriberInstance> subscriber)1341  bool DelSubscriberInstancesInfo(const napi_env &env, const std::shared_ptr<SubscriberInstance> subscriber)
1342  {
1343      ANS_LOGD("enter");
1344      if (subscriber == nullptr) {
1345          ANS_LOGE("subscriber is null");
1346          return false;
1347      }
1348      std::lock_guard<std::mutex> lock(delMutex_);
1349      auto iter = std::find(DeletingSubscriber.begin(), DeletingSubscriber.end(), subscriber);
1350      if (iter != DeletingSubscriber.end()) {
1351          DeletingSubscriber.erase(iter);
1352          std::lock_guard<std::mutex> lock(mutex_);
1353          for (auto it = subscriberInstances_.begin(); it != subscriberInstances_.end(); ++it) {
1354              if ((*it).subscriber == subscriber) {
1355                  if ((*it).ref != nullptr) {
1356                      napi_delete_reference(env, (*it).ref);
1357                  }
1358                  subscriberInstances_.erase(it);
1359                  return true;
1360              }
1361          }
1362      }
1363      return false;
1364  }
1365  
ParseParameters(const napi_env & env,const napi_callback_info & info,NotificationSubscribeInfo & subscriberInfo,std::shared_ptr<SubscriberInstance> & subscriber,napi_ref & callback)1366  napi_value ParseParameters(const napi_env &env, const napi_callback_info &info,
1367      NotificationSubscribeInfo &subscriberInfo, std::shared_ptr<SubscriberInstance> &subscriber, napi_ref &callback)
1368  {
1369      ANS_LOGD("enter");
1370  
1371      size_t argc = SUBSRIBE_MAX_PARA;
1372      napi_value argv[SUBSRIBE_MAX_PARA] = {nullptr};
1373      napi_value thisVar = nullptr;
1374      NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, NULL));
1375      if (argc < 1) {
1376          ANS_LOGE("Wrong number of arguments");
1377          Common::NapiThrow(env, ERROR_PARAM_INVALID, MANDATORY_PARAMETER_ARE_LEFT_UNSPECIFIED);
1378          return nullptr;
1379      }
1380  
1381      napi_valuetype valuetype = napi_undefined;
1382  
1383      // argv[0]:subscriber
1384      NAPI_CALL(env, napi_typeof(env, argv[PARAM0], &valuetype));
1385      if (valuetype != napi_object) {
1386          ANS_LOGE("Wrong argument type for arg0. NotificationSubscriber object expected.");
1387          std::string msg = "Incorrect parameter types.The type of param must be NotificationSubscriber.";
1388          Common::NapiThrow(env, ERROR_PARAM_INVALID, msg);
1389          return nullptr;
1390      }
1391  
1392      SubscriberInstancesInfo subscriberInstancesInfo;
1393      if (!HasNotificationSubscriber(env, argv[PARAM0], subscriberInstancesInfo)) {
1394          if (GetNotificationSubscriber(env, argv[PARAM0], subscriberInstancesInfo) == nullptr) {
1395              ANS_LOGE("NotificationSubscriber parse failed");
1396              return nullptr;
1397          }
1398          if (!AddSubscriberInstancesInfo(env, subscriberInstancesInfo)) {
1399              ANS_LOGE("AddSubscriberInstancesInfo add failed");
1400              return nullptr;
1401          }
1402      }
1403      subscriber = subscriberInstancesInfo.subscriber;
1404  
1405      // argv[1]:callback or NotificationSubscribeInfo
1406      if (argc >= SUBSRIBE_MAX_PARA - 1) {
1407          NAPI_CALL(env, napi_typeof(env, argv[PARAM1], &valuetype));
1408          if ((valuetype != napi_function) && (valuetype != napi_object)) {
1409              ANS_LOGE("Wrong argument type for arg1."
1410                  "Function or NotificationSubscribeInfo object expected. Excute promise");
1411              return Common::NapiGetNull(env);
1412          }
1413          if (valuetype == napi_function) {
1414              napi_create_reference(env, argv[PARAM1], 1, &callback);
1415          } else {
1416              if (Common::GetNotificationSubscriberInfo(env, argv[PARAM1], subscriberInfo) == nullptr) {
1417                  ANS_LOGE("NotificationSubscribeInfo parse failed");
1418                  return nullptr;
1419              }
1420          }
1421      }
1422  
1423      // argv[2]:callback
1424      if (argc >= SUBSRIBE_MAX_PARA) {
1425          NAPI_CALL(env, napi_typeof(env, argv[PARAM2], &valuetype));
1426          if (valuetype != napi_function) {
1427              ANS_LOGE("Callback is not function enforce promise.");
1428              return Common::NapiGetNull(env);
1429          }
1430          napi_create_reference(env, argv[PARAM2], 1, &callback);
1431      }
1432  
1433      return Common::NapiGetNull(env);
1434  }
1435  
Subscribe(napi_env env,napi_callback_info info)1436  napi_value Subscribe(napi_env env, napi_callback_info info)
1437  {
1438      ANS_LOGD("enter");
1439  
1440      napi_ref callback = nullptr;
1441      std::shared_ptr<SubscriberInstance> objectInfo = nullptr;
1442      NotificationSubscribeInfo subscriberInfo;
1443      if (ParseParameters(env, info, subscriberInfo, objectInfo, callback) == nullptr) {
1444          ANS_LOGD("ParseParameters is nullptr.");
1445          return Common::NapiGetUndefined(env);
1446      }
1447  
1448      AsyncCallbackInfoSubscribe *asynccallbackinfo = new (std::nothrow) AsyncCallbackInfoSubscribe {
1449          .env = env, .asyncWork = nullptr, .objectInfo = objectInfo, .subscriberInfo = subscriberInfo
1450      };
1451      if (!asynccallbackinfo) {
1452          ANS_LOGD("Asynccallbackinfo is nullptr.");
1453          return Common::JSParaError(env, callback);
1454      }
1455      napi_value promise = nullptr;
1456      Common::PaddingCallbackPromiseInfo(env, callback, asynccallbackinfo->info, promise);
1457  
1458      ANS_LOGD("Create subscribeNotification string.");
1459      napi_value resourceName = nullptr;
1460      napi_create_string_latin1(env, "subscribeNotification", NAPI_AUTO_LENGTH, &resourceName);
1461      // Asynchronous function call
1462      napi_create_async_work(env,
1463          nullptr,
1464          resourceName,
1465          [](napi_env env, void *data) {
1466              ANS_LOGD("Subscribe work excuted.");
1467              if (!data) {
1468                  ANS_LOGE("Invalid asynccallbackinfo!");
1469                  return;
1470              }
1471              auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
1472              if (asynccallbackinfo) {
1473                  if (asynccallbackinfo->subscriberInfo.hasSubscribeInfo) {
1474                      ANS_LOGD("Subscribe with NotificationSubscribeInfo excute.");
1475                      OHOS::Notification::NotificationSubscribeInfo subscribeInfo;
1476                      subscribeInfo.AddAppNames(asynccallbackinfo->subscriberInfo.bundleNames);
1477                      subscribeInfo.AddAppUserId(asynccallbackinfo->subscriberInfo.userId);
1478                      asynccallbackinfo->info.errorCode =
1479                          NotificationHelper::SubscribeNotification(*(asynccallbackinfo->objectInfo), subscribeInfo);
1480                  } else {
1481                      ANS_LOGD("SubscribeNotification execute.");
1482                      asynccallbackinfo->info.errorCode =
1483                          NotificationHelper::SubscribeNotification(*(asynccallbackinfo->objectInfo));
1484                  }
1485              }
1486          },
1487          [](napi_env env, napi_status status, void *data) {
1488              ANS_LOGD("Subscribe work complete.");
1489              if (!data) {
1490                  ANS_LOGE("Invalid asynccallbackinfo!");
1491                  return;
1492              }
1493              auto asynccallbackinfo = reinterpret_cast<AsyncCallbackInfoSubscribe *>(data);
1494              if (asynccallbackinfo) {
1495                  Common::ReturnCallbackPromise(env, asynccallbackinfo->info, Common::NapiGetNull(env));
1496                  if (asynccallbackinfo->info.callback != nullptr) {
1497                      ANS_LOGD("Delete subscribe callback reference.");
1498                      napi_delete_reference(env, asynccallbackinfo->info.callback);
1499                  }
1500                  napi_delete_async_work(env, asynccallbackinfo->asyncWork);
1501                  delete asynccallbackinfo;
1502                  asynccallbackinfo = nullptr;
1503              }
1504              ANS_LOGD("Subscribe work complete end.");
1505          },
1506          (void *)asynccallbackinfo,
1507          &asynccallbackinfo->asyncWork);
1508  
1509      napi_queue_async_work_with_qos(env, asynccallbackinfo->asyncWork, napi_qos_user_initiated);
1510  
1511      if (asynccallbackinfo->info.isCallback) {
1512          ANS_LOGD("subscribe callback is nullptr.");
1513          return Common::NapiGetNull(env);
1514      } else {
1515          return promise;
1516      }
1517  }
1518  
AddDeletingSubscriber(std::shared_ptr<SubscriberInstance> subscriber)1519  bool AddDeletingSubscriber(std::shared_ptr<SubscriberInstance> subscriber)
1520  {
1521      std::lock_guard<std::mutex> lock(delMutex_);
1522      auto iter = std::find(DeletingSubscriber.begin(), DeletingSubscriber.end(), subscriber);
1523      if (iter != DeletingSubscriber.end()) {
1524          return false;
1525      }
1526  
1527      DeletingSubscriber.push_back(subscriber);
1528      return true;
1529  }
1530  
DelDeletingSubscriber(std::shared_ptr<SubscriberInstance> subscriber)1531  void DelDeletingSubscriber(std::shared_ptr<SubscriberInstance> subscriber)
1532  {
1533      std::lock_guard<std::mutex> lock(delMutex_);
1534      auto iter = std::find(DeletingSubscriber.begin(), DeletingSubscriber.end(), subscriber);
1535      if (iter != DeletingSubscriber.end()) {
1536          DeletingSubscriber.erase(iter);
1537      }
1538  }
1539  }  // namespace NotificationNapi
1540  }  // namespace OHOS