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